@databiosphere/findable-ui 2.0.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/lib/components/Table/table.js +1 -1
  2. package/lib/components/common/AnchorLink/anchorLink.styles.js +1 -0
  3. package/lib/config/entities.d.ts +10 -3
  4. package/lib/hooks/useEntityList.js +1 -1
  5. package/lib/hooks/useSessionTimeout.js +9 -2
  6. package/lib/providers/exploreState/entities.d.ts +19 -0
  7. package/lib/providers/exploreState/entities.js +2 -0
  8. package/lib/providers/exploreState/initializer/constants.d.ts +5 -0
  9. package/lib/providers/exploreState/initializer/constants.js +32 -0
  10. package/lib/providers/exploreState/initializer/utils.d.ts +12 -0
  11. package/lib/providers/exploreState/initializer/utils.js +116 -0
  12. package/lib/providers/exploreState/utils.d.ts +37 -22
  13. package/lib/providers/exploreState/utils.js +64 -65
  14. package/lib/providers/exploreState.d.ts +4 -21
  15. package/lib/providers/exploreState.js +23 -22
  16. package/lib/views/ExploreView/exploreView.js +6 -6
  17. package/package.json +1 -1
  18. package/src/components/Table/table.tsx +1 -1
  19. package/src/components/common/AnchorLink/anchorLink.styles.ts +1 -0
  20. package/src/config/entities.ts +11 -3
  21. package/src/hooks/useEntityList.ts +1 -1
  22. package/src/hooks/useSessionTimeout.ts +9 -3
  23. package/src/providers/exploreState/entities.ts +32 -0
  24. package/src/providers/exploreState/{constants.ts → initializer/constants.ts} +8 -3
  25. package/src/providers/exploreState/initializer/utils.ts +183 -0
  26. package/src/providers/exploreState/utils.ts +103 -92
  27. package/src/providers/exploreState.tsx +50 -81
  28. package/src/views/ExploreView/exploreView.tsx +8 -8
@@ -29,8 +29,9 @@ const useAuthentication_1 = require("../hooks/useAuthentication/useAuthenticatio
29
29
  const useCategoryFilter_1 = require("../hooks/useCategoryFilter");
30
30
  const useConfig_1 = require("../hooks/useConfig");
31
31
  const useURLFilterParams_1 = require("../hooks/useURLFilterParams");
32
- const constants_1 = require("./exploreState/constants");
33
- const utils_1 = require("./exploreState/utils");
32
+ const constants_1 = require("./exploreState/initializer/constants");
33
+ const utils_1 = require("./exploreState/initializer/utils");
34
+ const utils_2 = require("./exploreState/utils");
34
35
  /**
35
36
  * Entity view.
36
37
  */
@@ -66,11 +67,11 @@ function ExploreStateProvider({ children, entityListType, }) {
66
67
  const { decodedCatalogParam, decodedFeatureFlagParam, decodedFilterParam } = (0, useURLFilterParams_1.useURLFilterParams)();
67
68
  const { isEnabled: isAuthEnabled, token } = (0, useAuthentication_1.useAuthentication)();
68
69
  const entityList = entityListType || defaultEntityListType;
69
- const [initReducerState] = (0, react_1.useState)(() => (0, utils_1.initExploreState)(config, entityList, decodedFilterParam, decodedCatalogParam, decodedFeatureFlagParam));
70
+ const [initializerArg] = (0, react_1.useState)(() => (0, utils_1.initReducerArguments)(config, entityList, decodedFilterParam, decodedCatalogParam, decodedFeatureFlagParam));
70
71
  const [exploreState, exploreDispatch] = (0, react_1.useReducer)((s, a) => exploreReducer(s, a, {
71
72
  config,
72
73
  entityList,
73
- }), initReducerState);
74
+ }), initializerArg);
74
75
  // does this help? https://hswolff.com/blog/how-to-usecontext-with-usereducer/
75
76
  const exploreContextValue = (0, react_1.useMemo)(() => {
76
77
  return { exploreDispatch, exploreState };
@@ -119,7 +120,11 @@ function exploreReducer(state, action, exploreContext) {
119
120
  * Clear all filters
120
121
  **/
121
122
  case ExploreActionKind.ClearFilters: {
122
- return Object.assign(Object.assign({}, state), { filterCount: 0, filterState: [], paginationState: (0, utils_1.resetPage)(state.paginationState) });
123
+ const filterCount = 0;
124
+ const filterState = [];
125
+ (0, utils_2.updateEntityStateByCategoryGroupConfigKey)(state, { filterState });
126
+ return Object.assign(Object.assign({}, state), { filterCount,
127
+ filterState, paginationState: (0, utils_2.resetPage)(state.paginationState) });
123
128
  }
124
129
  /**
125
130
  * Paginate table
@@ -140,12 +145,13 @@ function exploreReducer(state, action, exploreContext) {
140
145
  * Process explore response
141
146
  **/
142
147
  case ExploreActionKind.ProcessExploreResponse: {
143
- const { entityPageState, tabValue } = state;
144
- const { categoryConfigs, categoryViews, filterState } = entityPageState[tabValue];
145
148
  const nextCategoryViews = payload.selectCategories
146
- ? (0, useCategoryFilter_1.buildCategoryViews)(payload.selectCategories, categoryConfigs, filterState)
147
- : undefined;
148
- return Object.assign(Object.assign({}, state), { categoryGroupConfigs: entityPageState[tabValue].categoryGroupConfigs, categoryViews: nextCategoryViews !== null && nextCategoryViews !== void 0 ? nextCategoryViews : categoryViews, entityPageState: Object.assign(Object.assign({}, entityPageState), { [tabValue]: Object.assign(Object.assign({}, entityPageState[tabValue]), { categoryViews: nextCategoryViews !== null && nextCategoryViews !== void 0 ? nextCategoryViews : categoryViews }) }), listItems: payload.loading ? [] : payload.listItems, loading: payload.loading, paginationState: Object.assign(Object.assign({}, state.paginationState), payload.paginationResponse) });
149
+ ? (0, useCategoryFilter_1.buildCategoryViews)(payload.selectCategories, (0, utils_2.getEntityCategoryConfigs)(state), state.filterState)
150
+ : state.categoryViews;
151
+ (0, utils_2.updateEntityStateByCategoryGroupConfigKey)(state, {
152
+ categoryViews: nextCategoryViews,
153
+ });
154
+ return Object.assign(Object.assign({}, state), { categoryViews: nextCategoryViews, listItems: payload.loading ? [] : payload.listItems, loading: payload.loading, paginationState: Object.assign(Object.assign({}, state.paginationState), payload.paginationResponse) });
149
155
  }
150
156
  /**
151
157
  * Process related response
@@ -163,7 +169,7 @@ function exploreReducer(state, action, exploreContext) {
163
169
  * Reset the current state to the initial
164
170
  */
165
171
  case ExploreActionKind.ResetState: {
166
- return (0, utils_1.initExploreState)(config, entityList, "");
172
+ return (0, utils_1.initReducerArguments)(config, entityList, "");
167
173
  }
168
174
  /**
169
175
  * Select entity type
@@ -172,7 +178,8 @@ function exploreReducer(state, action, exploreContext) {
172
178
  if (payload === state.tabValue) {
173
179
  return state;
174
180
  }
175
- return Object.assign(Object.assign({}, state), { filterCount: state.entityPageState[payload].filterCount, filterState: state.entityPageState[payload].filterState, listItems: [], loading: true, paginationState: (0, utils_1.resetPage)(state.paginationState), tabValue: payload });
181
+ const entityState = (0, utils_2.getEntityState)((0, utils_2.getEntityCategoryGroupConfigKey)(payload, state.entityPageState), state);
182
+ return Object.assign(Object.assign({}, state), { categoryGroups: entityState.categoryGroups, categoryViews: entityState.categoryViews, filterCount: (0, utils_2.getFilterCount)(entityState.filterState), filterState: entityState.filterState, listItems: [], loading: true, paginationState: (0, utils_2.resetPage)(state.paginationState), tabValue: payload });
176
183
  }
177
184
  /**
178
185
  * Toggle entity view
@@ -185,26 +192,20 @@ function exploreReducer(state, action, exploreContext) {
185
192
  **/
186
193
  case ExploreActionKind.UpdateFilter: {
187
194
  const filterState = (0, useCategoryFilter_1.buildNextFilterState)(state.filterState, payload.categoryKey, payload.selectedValue, payload.selected);
188
- const filterCount = (0, utils_1.getFilterCount)(filterState);
189
- return Object.assign(Object.assign({}, state), { entityPageState: Object.assign(Object.assign({}, state.entityPageState), { [state.tabValue]: Object.assign(Object.assign({}, state.entityPageState[state.tabValue]), { filterCount,
190
- filterState }) }), filterCount,
191
- filterState, paginationState: (0, utils_1.resetPage)(state.paginationState) });
195
+ (0, utils_2.updateEntityStateByCategoryGroupConfigKey)(state, { filterState });
196
+ return Object.assign(Object.assign({}, state), { filterCount: (0, utils_2.getFilterCount)(filterState), filterState, paginationState: (0, utils_2.resetPage)(state.paginationState) });
192
197
  }
193
198
  /**
194
199
  * Update sorting
195
200
  **/
196
201
  case ExploreActionKind.UpdateSorting: {
197
- const currentEntity = state.tabValue;
198
- const currentPageState = state.entityPageState[currentEntity];
199
- return Object.assign(Object.assign({}, state), { entityPageState: Object.assign(Object.assign({}, state.entityPageState), { [currentEntity]: Object.assign(Object.assign({}, currentPageState), { sorting: payload }) }), paginationState: (0, utils_1.resetPage)(state.paginationState) });
202
+ return Object.assign(Object.assign({}, state), { entityPageState: (0, utils_2.updateEntityPageState)(state.tabValue, state.entityPageState, { sorting: payload }), paginationState: (0, utils_2.resetPage)(state.paginationState) });
200
203
  }
201
204
  /**
202
205
  * Update column visibility
203
206
  **/
204
207
  case ExploreActionKind.UpdateColumnVisibility: {
205
- const currentEntity = state.tabValue;
206
- const currentPageState = state.entityPageState[currentEntity];
207
- return Object.assign(Object.assign({}, state), { entityPageState: Object.assign(Object.assign({}, state.entityPageState), { [currentEntity]: Object.assign(Object.assign({}, currentPageState), { columnsVisibility: payload }) }) });
208
+ return Object.assign(Object.assign({}, state), { entityPageState: (0, utils_2.updateEntityPageState)(state.tabValue, state.entityPageState, { columnsVisibility: payload }) });
208
209
  }
209
210
  default:
210
211
  return state;
@@ -68,14 +68,14 @@ const ExploreView = (props) => {
68
68
  const { entities, explorerTitle, summaryConfig, trackingConfig } = config;
69
69
  const { listView } = entityConfig;
70
70
  const { listHero, subTitleHero } = listView || {};
71
- const { categoryGroupConfigs, categoryViews, filterCount, isRelatedView, tabValue, } = exploreState;
71
+ const { categoryGroups, categoryViews, filterCount, isRelatedView, tabValue, } = exploreState;
72
72
  const { push } = (0, router_1.useRouter)();
73
73
  const tabs = getTabs(entities);
74
74
  const { response: summaryResponse } = (0, useSummary_1.useSummary)(); // Fetch summary.
75
75
  (0, useEntityList_1.useEntityList)(props); // Fetch entities.
76
76
  (0, useEntityListRelatedView_1.useEntityListRelatedView)(); // Fetch related entities.
77
77
  const { entityListType } = props;
78
- const categoryFilters = (0, react_1.useMemo)(() => buildCategoryFilters(categoryViews, categoryGroupConfigs), [categoryViews, categoryGroupConfigs]);
78
+ const categoryFilters = (0, react_1.useMemo)(() => buildCategoryFilters(categoryViews, categoryGroups), [categoryGroups, categoryViews]);
79
79
  /**
80
80
  * Closes filter drawer.
81
81
  */
@@ -159,14 +159,14 @@ exports.ExploreView = ExploreView;
159
159
  /**
160
160
  * Builds the category views into category views grouped by the given category group configuration.
161
161
  * @param selectCategoryViews - View models of categories to display.
162
- * @param categoryGroupConfigs - Category group configuration.
162
+ * @param categoryGroups - Category groups.
163
163
  * @returns category filters.
164
164
  */
165
- function buildCategoryFilters(selectCategoryViews, categoryGroupConfigs) {
166
- if (!categoryGroupConfigs) {
165
+ function buildCategoryFilters(selectCategoryViews, categoryGroups) {
166
+ if (!categoryGroups) {
167
167
  return [{ categoryViews: selectCategoryViews }];
168
168
  }
169
- return categoryGroupConfigs.map(({ categoryConfigs, label }) => {
169
+ return categoryGroups.map(({ categoryConfigs, label }) => {
170
170
  // Grab the category views for the configured grouped categories.
171
171
  const categoryViews = categoryConfigs.reduce((acc, { key: categoryKey }) => {
172
172
  const categoryView = selectCategoryViews.find(({ key }) => key === categoryKey);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@databiosphere/findable-ui",
3
- "version": "2.0.0",
3
+ "version": "2.0.1",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "test": "jest",
@@ -31,7 +31,7 @@ import { useExploreMode } from "../../hooks/useExploreMode";
31
31
  import { useExploreState } from "../../hooks/useExploreState";
32
32
  import { useScroll } from "../../hooks/useScroll";
33
33
  import { ENTITY_VIEW, ExploreActionKind } from "../../providers/exploreState";
34
- import { DEFAULT_PAGINATION_STATE } from "../../providers/exploreState/constants";
34
+ import { DEFAULT_PAGINATION_STATE } from "../../providers/exploreState/initializer/constants";
35
35
  import { TABLET } from "../../theme/common/breakpoints";
36
36
  import { FluidPaper, GridPaper } from "../common/Paper/paper.styles";
37
37
  import { NoResults } from "../NoResults/noResults";
@@ -6,6 +6,7 @@ export const AnchorLink = styled(Link)`
6
6
  color: ${inkLight};
7
7
  margin-left: 4px;
8
8
  opacity: 0;
9
+ position: absolute;
9
10
  transition: opacity 0.2s ease-in-out;
10
11
 
11
12
  svg {
@@ -51,9 +51,17 @@ export interface BackPageTabConfig extends TabConfig {
51
51
  }
52
52
 
53
53
  /**
54
- * Model of grouped configured categories in site config.
54
+ * Model of category group config in site config.
55
55
  */
56
56
  export interface CategoryGroupConfig {
57
+ categoryGroups: CategoryGroup[];
58
+ key: string;
59
+ }
60
+
61
+ /**
62
+ * Model of grouped configured categories in site config.
63
+ */
64
+ export interface CategoryGroup {
57
65
  categoryConfigs: CategoryConfig[];
58
66
  label?: string;
59
67
  }
@@ -143,7 +151,7 @@ export type EntityPath = string;
143
151
  // eslint-disable-next-line @typescript-eslint/no-explicit-any -- This config model is part of a generic array
144
152
  export interface EntityConfig<T = any, I = any> extends TabConfig {
145
153
  apiPath?: EntityPath;
146
- categoryGroupConfigs?: CategoryGroupConfig[];
154
+ categoryGroupConfig?: CategoryGroupConfig;
147
155
  detail: BackPageConfig;
148
156
  entityMapper?: EntityMapper<T, I>;
149
157
  exploreMode: ExploreMode;
@@ -358,7 +366,7 @@ export interface SiteConfig {
358
366
  appTitle: string;
359
367
  authentication?: AuthenticationConfig;
360
368
  browserURL: string;
361
- categoryGroupConfigs?: CategoryGroupConfig[];
369
+ categoryGroupConfig?: CategoryGroupConfig;
362
370
  contentDir?: string;
363
371
  contentThemeOptionsFn?: ThemeOptionsFn;
364
372
  dataSource: DataSourceConfig;
@@ -12,7 +12,7 @@ import {
12
12
  import { EntityMapper } from "../config/entities";
13
13
  import { getEntityConfig } from "../config/utils";
14
14
  import { ExploreActionKind } from "../providers/exploreState";
15
- import { DEFAULT_PAGINATION_STATE } from "../providers/exploreState/constants";
15
+ import { DEFAULT_PAGINATION_STATE } from "../providers/exploreState/initializer/constants";
16
16
  import { useAsync } from "./useAsync";
17
17
  import { useAuthentication } from "./useAuthentication/useAuthentication";
18
18
  import { useConfig } from "./useConfig";
@@ -1,4 +1,6 @@
1
- import { useEffect, useState } from "react";
1
+ import Router from "next/router";
2
+ import { useCallback, useEffect, useState } from "react";
3
+ import { useConfig } from "./useConfig";
2
4
  import { useLocation } from "./useLocation";
3
5
 
4
6
  export const INACTIVITY_PARAM = "inactivityTimeout";
@@ -13,15 +15,19 @@ interface UseSessionTimeout {
13
15
  * @returns flag indicating if the session has timed out.
14
16
  */
15
17
  export const useSessionTimeout = (): UseSessionTimeout => {
18
+ const {
19
+ config: { redirectRootToPath },
20
+ } = useConfig();
16
21
  const [isSessionTimeout, setIsSessionTimeout] = useState<boolean>(false);
17
22
  // Get the session timeout from URL parameters.
18
23
  const { search } = useLocation() || {};
19
24
  const sessionTimeout = search?.get(INACTIVITY_PARAM);
20
25
 
21
26
  // Clears session timeout state.
22
- const clearSessionTimeout = (): void => {
27
+ const clearSessionTimeout = useCallback((): void => {
23
28
  setIsSessionTimeout(false);
24
- };
29
+ Router.replace(redirectRootToPath);
30
+ }, [redirectRootToPath]);
25
31
 
26
32
  useEffect(() => {
27
33
  setIsSessionTimeout(sessionTimeout === "true");
@@ -0,0 +1,32 @@
1
+ import { ColumnSort } from "@tanstack/react-table";
2
+ import { SelectCategory, SelectedFilter } from "../../common/entities";
3
+ import {
4
+ CategoryConfig,
5
+ CategoryGroup,
6
+ CategoryGroupConfig,
7
+ EntityPath,
8
+ } from "../../config/entities";
9
+
10
+ export interface EntityPageState {
11
+ categoryGroupConfigKey: CategoryGroupConfigKey;
12
+ columnsVisibility: Record<string, boolean>;
13
+ sorting: ColumnSort[];
14
+ }
15
+
16
+ export interface EntityPageStateMapper {
17
+ [key: EntityPath]: EntityPageState;
18
+ }
19
+
20
+ export interface EntityState {
21
+ categoryConfigs?: CategoryConfig[];
22
+ categoryGroups?: CategoryGroup[];
23
+ categoryViews: SelectCategory[];
24
+ filterState: SelectedFilter[];
25
+ }
26
+
27
+ export type EntityStateByCategoryGroupConfigKey = Map<
28
+ CategoryGroupConfigKey,
29
+ EntityState
30
+ >;
31
+
32
+ export type CategoryGroupConfigKey = CategoryGroupConfig["key"];
@@ -1,6 +1,11 @@
1
- import { ExploreState, PaginationState } from "../exploreState";
1
+ import { ExploreState, PaginationState } from "../../exploreState";
2
+ import { EntityState } from "../entities";
3
+
4
+ export const DEFAULT_ENTITY_STATE: EntityState = {
5
+ categoryViews: [],
6
+ filterState: [],
7
+ };
2
8
 
3
- // Template constants
4
9
  export const DEFAULT_PAGINATION_STATE: PaginationState = {
5
10
  currentPage: 1,
6
11
  index: null,
@@ -11,11 +16,11 @@ export const DEFAULT_PAGINATION_STATE: PaginationState = {
11
16
  rows: 0,
12
17
  };
13
18
 
14
- // Initial state
15
19
  export const INITIAL_STATE: ExploreState = {
16
20
  catalogState: undefined,
17
21
  categoryViews: [],
18
22
  entityPageState: {},
23
+ entityStateByCategoryGroupConfigKey: new Map(),
19
24
  featureFlagState: undefined,
20
25
  filterCount: 0,
21
26
  filterState: [],
@@ -0,0 +1,183 @@
1
+ import { SelectedFilter } from "../../../common/entities";
2
+ import { getInitialTableColumnVisibility } from "../../../components/Table/common/utils";
3
+ import {
4
+ CategoryConfig,
5
+ CategoryGroup,
6
+ CategoryGroupConfig,
7
+ EntityConfig,
8
+ SiteConfig,
9
+ } from "../../../config/entities";
10
+ import { getDefaultSorting } from "../../../config/utils";
11
+ import { ExploreState } from "../../exploreState";
12
+ import {
13
+ CategoryGroupConfigKey,
14
+ EntityPageStateMapper,
15
+ EntityStateByCategoryGroupConfigKey,
16
+ } from "../entities";
17
+ import { getEntityCategoryGroupConfigKey, getFilterCount } from "../utils";
18
+ import { DEFAULT_ENTITY_STATE, INITIAL_STATE } from "./constants";
19
+
20
+ /**
21
+ * Returns entity related configured category group config where entity config takes precedence over site config.
22
+ * @param siteConfig - Site config.
23
+ * @param entityConfig - Entity config.
24
+ * @returns entity related category group config.
25
+ */
26
+ function getEntityCategoryGroupConfig(
27
+ siteConfig: SiteConfig,
28
+ entityConfig: EntityConfig
29
+ ): CategoryGroupConfig | undefined {
30
+ const siteCategoryGroupConfig = siteConfig.categoryGroupConfig;
31
+ const entityCategoryGroupConfig = entityConfig.categoryGroupConfig;
32
+ return entityCategoryGroupConfig ?? siteCategoryGroupConfig;
33
+ }
34
+
35
+ /**
36
+ * Returns configured category groups as a list of configured categories.
37
+ * @param categoryGroups - Configured category groups.
38
+ * @returns a list of configured categories.
39
+ */
40
+ function flattenCategoryGroups(
41
+ categoryGroups?: CategoryGroup[]
42
+ ): CategoryConfig[] | undefined {
43
+ return categoryGroups?.flatMap(({ categoryConfigs }) => categoryConfigs);
44
+ }
45
+
46
+ /**
47
+ * Initializes category group config key for the entity.
48
+ * @param siteConfig - Site config.
49
+ * @param entityConfig - Entity config.
50
+ * @returns category group config key.
51
+ */
52
+ function initCategoryGroupConfigKey(
53
+ siteConfig: SiteConfig,
54
+ entityConfig: EntityConfig
55
+ ): CategoryGroupConfigKey {
56
+ const categoryGroupConfig = getEntityCategoryGroupConfig(
57
+ siteConfig,
58
+ entityConfig
59
+ );
60
+ return categoryGroupConfig?.key || entityConfig.route;
61
+ }
62
+
63
+ /**
64
+ * Initializes category groups for the current entity.
65
+ * @param entityStateByCategoryGroupConfigKey - Entity state by category group config key.
66
+ * @param categoryGroupConfigKey - Category group config key.
67
+ * @returns category groups.
68
+ */
69
+ function initCategoryGroups(
70
+ entityStateByCategoryGroupConfigKey: EntityStateByCategoryGroupConfigKey,
71
+ categoryGroupConfigKey: CategoryGroupConfigKey
72
+ ): CategoryGroup[] | undefined {
73
+ return entityStateByCategoryGroupConfigKey.get(categoryGroupConfigKey)
74
+ ?.categoryGroups;
75
+ }
76
+
77
+ /**
78
+ * Initializes entity page state.
79
+ * @param config - Site config.
80
+ * @returns entity page state.
81
+ */
82
+ function initEntityPageState(config: SiteConfig): EntityPageStateMapper {
83
+ return config.entities.reduce((acc, entity): EntityPageStateMapper => {
84
+ return {
85
+ ...acc,
86
+ [entity.route]: {
87
+ categoryGroupConfigKey: initCategoryGroupConfigKey(config, entity),
88
+ columnsVisibility: getInitialTableColumnVisibility(entity.list.columns),
89
+ sorting: getDefaultSorting(entity),
90
+ },
91
+ };
92
+ }, {} as EntityPageStateMapper);
93
+ }
94
+
95
+ /**
96
+ * Initializes entity state by category group config key.
97
+ * @param config - Site config.
98
+ * @param categoryGroupConfigKey - Category group config key.
99
+ * @param filterState - Filter state.
100
+ * @returns entity state by category group config key.
101
+ */
102
+ function initEntityStateByCategoryGroupConfigKey(
103
+ config: SiteConfig,
104
+ categoryGroupConfigKey: CategoryGroupConfigKey,
105
+ filterState: SelectedFilter[]
106
+ ): EntityStateByCategoryGroupConfigKey {
107
+ const entityStateByCategoryGroupConfigKey: EntityStateByCategoryGroupConfigKey =
108
+ new Map();
109
+ for (const entity of config.entities) {
110
+ const categoryGroupConfig = getEntityCategoryGroupConfig(config, entity);
111
+ if (!categoryGroupConfig) continue;
112
+ const { categoryGroups, key } = categoryGroupConfig;
113
+ if (entityStateByCategoryGroupConfigKey.has(key)) continue;
114
+ entityStateByCategoryGroupConfigKey.set(key, {
115
+ ...DEFAULT_ENTITY_STATE,
116
+ categoryConfigs: flattenCategoryGroups(categoryGroups),
117
+ categoryGroups,
118
+ filterState: key === categoryGroupConfigKey ? filterState : [],
119
+ });
120
+ }
121
+ return entityStateByCategoryGroupConfigKey;
122
+ }
123
+
124
+ /**
125
+ * Initializes filter state from URL "filter" parameter.
126
+ * @param decodedFilterParam - Decoded filter parameter.
127
+ * @returns filter state.
128
+ */
129
+ function initFilterState(decodedFilterParam: string): SelectedFilter[] {
130
+ // Define filter state, from URL "filter" parameter, if present and valid.
131
+ let filterState: SelectedFilter[] = [];
132
+ try {
133
+ filterState = JSON.parse(decodedFilterParam);
134
+ } catch {
135
+ // do nothing
136
+ }
137
+ return filterState;
138
+ }
139
+
140
+ /**
141
+ * Returns the explore state reducer initial arguments.
142
+ * @param config - Site config.
143
+ * @param entityListType - Entity list type.
144
+ * @param decodedFilterParam - Decoded filter parameter.
145
+ * @param decodedCatalogParam - Decoded catalog parameter.
146
+ * @param decodedFeatureFlagParam - Decoded feature flag parameter.
147
+ * @returns explore state reducer initial arguments.
148
+ */
149
+ export function initReducerArguments(
150
+ config: SiteConfig,
151
+ entityListType: string,
152
+ decodedFilterParam: string,
153
+ decodedCatalogParam?: string,
154
+ decodedFeatureFlagParam?: string
155
+ ): ExploreState {
156
+ const filterState = initFilterState(decodedFilterParam);
157
+ const entityPageState = initEntityPageState(config);
158
+ const categoryGroupConfigKey = getEntityCategoryGroupConfigKey(
159
+ entityListType,
160
+ entityPageState
161
+ );
162
+ const entityStateByCategoryGroupConfigKey =
163
+ initEntityStateByCategoryGroupConfigKey(
164
+ config,
165
+ categoryGroupConfigKey,
166
+ filterState
167
+ );
168
+ const categoryGroups = initCategoryGroups(
169
+ entityStateByCategoryGroupConfigKey,
170
+ categoryGroupConfigKey
171
+ );
172
+ return {
173
+ ...INITIAL_STATE,
174
+ catalogState: decodedCatalogParam,
175
+ categoryGroups,
176
+ entityPageState,
177
+ entityStateByCategoryGroupConfigKey,
178
+ featureFlagState: decodedFeatureFlagParam,
179
+ filterCount: getFilterCount(filterState),
180
+ filterState,
181
+ tabValue: entityListType,
182
+ };
183
+ }