diff --git a/packages/pxweb2/public/config/config.js b/packages/pxweb2/public/config/config.js
index 87ec89910..fff68fc5a 100644
--- a/packages/pxweb2/public/config/config.js
+++ b/packages/pxweb2/public/config/config.js
@@ -12,6 +12,9 @@ globalThis.PxWeb2Config = {
baseApplicationPath: '/',
apiUrl: 'https://api.scb.se/OV0104/v2beta/api/v2',
maxDataCells: 150000,
+ tableViewer: {
+ selectionOnLanguageChange: 'keep', // Options: 'keep', 'reset'
+ },
useDynamicContentInTitle: false,
showBreadCrumbOnStartPage: false,
specialCharacters: ['.', '..', ':', '-', '...', '*'],
diff --git a/packages/pxweb2/src/app/components/Presentation/Presentation.tsx b/packages/pxweb2/src/app/components/Presentation/Presentation.tsx
index 3f48d6014..035e336b3 100644
--- a/packages/pxweb2/src/app/components/Presentation/Presentation.tsx
+++ b/packages/pxweb2/src/app/components/Presentation/Presentation.tsx
@@ -147,7 +147,16 @@ export function Presentation({
setInitialRun(false);
}
}
- }, [tableId, selectedVBValues]);
+ }, [
+ tableId,
+ selectedVBValues,
+ pxTableMetadata,
+ hasLoadedInitialSelection,
+ isLoadingMetadata,
+ initialRun,
+ isMobile,
+ i18n.resolvedLanguage,
+ ]);
useEffect(() => {
memoizedDataFetch();
diff --git a/packages/pxweb2/src/app/components/Selection/Selection.spec.tsx b/packages/pxweb2/src/app/components/Selection/Selection.spec.tsx
index e3e8b9eb8..fde81aef3 100644
--- a/packages/pxweb2/src/app/components/Selection/Selection.spec.tsx
+++ b/packages/pxweb2/src/app/components/Selection/Selection.spec.tsx
@@ -1,5 +1,5 @@
import React from 'react';
-import { act } from '@testing-library/react';
+import { act, waitFor, render } from '@testing-library/react';
import { vi } from 'vitest';
import {
@@ -8,11 +8,45 @@ import {
} from '../../util/testing-utils';
import Selection from './Selection';
import { AccessibilityProvider } from '../../context/AccessibilityProvider';
-import { TableDataContext } from '../../context/TableDataProvider';
+import {
+ TableDataContext,
+ TableDataProvider,
+} from '../../context/TableDataProvider';
+import { AppProvider } from '../../context/AppProvider';
+import { VariablesProvider } from '../../context/VariablesProvider';
+import { TablesService } from '@pxweb2/pxweb2-api-client';
+import { mockedConfig } from '../../../../test/setupTests';
+
+let mockResolvedLanguage = 'en';
+
+vi.mock('react-i18next', () => ({
+ useTranslation: () => ({
+ t: (key: string) => key,
+ i18n: {
+ changeLanguage: () => Promise.resolve(),
+ language: mockResolvedLanguage,
+ resolvedLanguage: mockResolvedLanguage,
+ dir: () => 'ltr',
+ },
+ }),
+ useRouteError: vi.fn(),
+ useLocation: vi.fn(),
+ useNavigate: vi.fn(() => vi.fn()),
+ initReactI18next: {
+ type: '3rdParty',
+ init: vi.fn(),
+ },
+}));
describe('Selection', () => {
mockTableService();
+ beforeEach(() => {
+ mockResolvedLanguage = 'en';
+ mockedConfig.tableViewer = { selectionOnLanguageChange: 'reset' };
+ vi.clearAllMocks();
+ });
+
it('should throw an error when triggered', () => {
const TestComponent = () => {
const context = React.useContext(TableDataContext);
@@ -54,4 +88,74 @@ describe('Selection', () => {
throw new Error('Simulated error');
}).toThrow('Simulated error');
});
+
+ it('reloads default selection when language changes in reset mode', async () => {
+ const view = (
+
+
+
+
+
+
+
+
+
+ );
+
+ const { rerender } = render(view);
+
+ await waitFor(() => {
+ expect(TablesService.getDefaultSelection).toHaveBeenCalledTimes(1);
+ });
+
+ mockResolvedLanguage = 'sv';
+
+ rerender(view);
+
+ await waitFor(() => {
+ expect(TablesService.getDefaultSelection).toHaveBeenCalledTimes(2);
+ });
+ });
+
+ it('keeps current selection when language changes in keep mode', async () => {
+ mockedConfig.tableViewer = { selectionOnLanguageChange: 'keep' };
+
+ const view = (
+
+
+
+
+
+
+
+
+
+ );
+
+ const { rerender } = render(view);
+
+ await waitFor(() => {
+ expect(TablesService.getDefaultSelection).toHaveBeenCalledTimes(1);
+ });
+
+ mockResolvedLanguage = 'sv';
+
+ rerender(view);
+
+ await waitFor(() => {
+ expect(TablesService.getMetadataById).toHaveBeenCalled();
+ });
+
+ expect(TablesService.getDefaultSelection).toHaveBeenCalledTimes(1);
+ });
});
diff --git a/packages/pxweb2/src/app/components/Selection/Selection.tsx b/packages/pxweb2/src/app/components/Selection/Selection.tsx
index 77a1b3183..31dd76be6 100644
--- a/packages/pxweb2/src/app/components/Selection/Selection.tsx
+++ b/packages/pxweb2/src/app/components/Selection/Selection.tsx
@@ -36,6 +36,7 @@ import useApp from '../../context/useApp';
import { NavigationItem } from '../../components/NavigationMenu/NavigationItem/NavigationItemType';
import useAccessibility from '../../context/useAccessibility';
import { problemMessage } from '../../util/problemMessage';
+import { getConfig } from '../../util/config/getConfig';
import {
getSelectedCodelists,
updateSelectedCodelistForVariable,
@@ -233,6 +234,7 @@ export function Selection({
setSelectedNavigationView,
hideMenuRef,
}: SelectionProps) {
+ const config = getConfig();
const variables = useVariables();
const app = useApp();
const { isTablet } = useApp();
@@ -271,14 +273,22 @@ export function Selection({
return;
}
- // If the table has changed, or the language has changed, we need to reload the default selection
+ const isTableChanged = prevTableId === '' || prevTableId !== selectedTabId;
+ const languageChanged = prevLang !== i18n.resolvedLanguage;
+ const shouldResetSelectionOnLanguageChange =
+ config.tableViewer?.selectionOnLanguageChange !== 'keep';
+
+ // If table changes, selection should always be reset to initial selection.
+ // If language changes, resetting is controlled by config.
if (
- prevTableId === '' ||
- prevTableId !== selectedTabId ||
- prevLang !== i18n.resolvedLanguage
+ isTableChanged ||
+ (languageChanged && shouldResetSelectionOnLanguageChange)
) {
variables.setHasLoadedInitialSelection(false);
shouldGetInitialSelection = true;
+ }
+
+ if (isTableChanged || languageChanged) {
setPrevTableId(selectedTabId);
setPrevLang(i18n.resolvedLanguage ?? '');
}
diff --git a/packages/pxweb2/src/app/context/TableDataProvider.tsx b/packages/pxweb2/src/app/context/TableDataProvider.tsx
index 16e7d4139..ca988582e 100644
--- a/packages/pxweb2/src/app/context/TableDataProvider.tsx
+++ b/packages/pxweb2/src/app/context/TableDataProvider.tsx
@@ -29,6 +29,7 @@ import {
} from './TableDataProviderUtils';
import { problemMessage } from '../util/problemMessage';
import { PivotType } from './PivotType';
+import { getConfig } from '../util/config/getConfig';
// Define types for the context state and provider props
export interface TableDataContextType {
@@ -79,6 +80,7 @@ const TableDataContext = createContext({
});
const TableDataProvider: React.FC = ({ children }) => {
+ const config = getConfig();
const [isInitialized] = useState(true);
// Data (metadata) that reflects variables and values selected by user right now. Used as data source for the table
const [data, setData] = useState(undefined);
@@ -337,7 +339,12 @@ const TableDataProvider: React.FC = ({ children }) => {
accumulatedData?.metadata.language.toLowerCase() !==
i18n.language.toLowerCase()
) {
- variablesSelection = { selection: [] }; // If language is changed we shall fetch data with the default selection.
+ const shouldResetSelectionOnLanguageChange =
+ config.tableViewer?.selectionOnLanguageChange !== 'keep';
+
+ if (shouldResetSelectionOnLanguageChange) {
+ variablesSelection = { selection: [] }; // If language is changed we shall fetch data with the default selection.
+ }
}
const pxTable: PxTable = await fetchFromApi(
@@ -353,7 +360,11 @@ const TableDataProvider: React.FC = ({ children }) => {
setAccumulatedData(structuredClone(pxTable));
// }
},
- [accumulatedData?.metadata.language, initializeStubAndHeading],
+ [
+ accumulatedData?.metadata.language,
+ config.tableViewer?.selectionOnLanguageChange,
+ initializeStubAndHeading,
+ ],
);
/**
diff --git a/packages/pxweb2/src/app/util/config/configType.ts b/packages/pxweb2/src/app/util/config/configType.ts
index 783d29b57..0aa09e12e 100644
--- a/packages/pxweb2/src/app/util/config/configType.ts
+++ b/packages/pxweb2/src/app/util/config/configType.ts
@@ -9,6 +9,9 @@ export type Config = {
baseApplicationPath: string;
apiUrl: string;
maxDataCells: number;
+ tableViewer?: {
+ selectionOnLanguageChange?: 'reset' | 'keep';
+ };
useDynamicContentInTitle: boolean;
showBreadCrumbOnStartPage: boolean;
specialCharacters: string[];
diff --git a/packages/pxweb2/test/setupTests.ts b/packages/pxweb2/test/setupTests.ts
index e6a1c354f..0070d27a3 100644
--- a/packages/pxweb2/test/setupTests.ts
+++ b/packages/pxweb2/test/setupTests.ts
@@ -61,6 +61,10 @@ export const mockedConfig: Config = {
baseApplicationPath: '/',
apiUrl: '',
maxDataCells: 100000,
+ tableViewer: {
+ selectionOnLanguageChange: 'reset',
+ },
+ useDynamicContentInTitle: false,
showBreadCrumbOnStartPage: true,
specialCharacters: ['.', '..', ':', '-', '...', '*'],
variableFilterExclusionList: {