@databiosphere/findable-ui 1.0.1 → 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.
- package/lib/components/Loading/loading.d.ts +2 -1
- package/lib/components/Loading/loading.js +4 -4
- package/lib/components/Table/table.js +1 -1
- package/lib/components/TableCreator/tableCreator.js +3 -2
- package/lib/components/TableCreator/tableCreator.styles.d.ts +5 -0
- package/lib/components/TableCreator/tableCreator.styles.js +10 -0
- package/lib/components/common/AnchorLink/anchorLink.styles.js +1 -0
- package/lib/config/entities.d.ts +10 -2
- package/lib/hooks/useEntityList.js +1 -1
- package/lib/hooks/useSessionTimeout.js +9 -2
- package/lib/providers/exploreState/entities.d.ts +19 -0
- package/lib/providers/exploreState/entities.js +2 -0
- package/lib/providers/exploreState/initializer/constants.d.ts +5 -0
- package/lib/providers/exploreState/initializer/constants.js +32 -0
- package/lib/providers/exploreState/initializer/utils.d.ts +12 -0
- package/lib/providers/exploreState/initializer/utils.js +116 -0
- package/lib/providers/exploreState/utils.d.ts +37 -22
- package/lib/providers/exploreState/utils.js +64 -47
- package/lib/providers/exploreState.d.ts +4 -16
- package/lib/providers/exploreState.js +25 -21
- package/lib/views/ExploreView/exploreView.js +8 -8
- package/package.json +1 -1
- package/src/components/Loading/loading.tsx +5 -2
- package/src/components/Table/table.tsx +1 -1
- package/src/components/TableCreator/tableCreator.styles.ts +5 -0
- package/src/components/TableCreator/tableCreator.tsx +4 -2
- package/src/components/common/AnchorLink/anchorLink.styles.ts +1 -0
- package/src/config/entities.ts +11 -2
- package/src/hooks/useEntityList.ts +1 -1
- package/src/hooks/useSessionTimeout.ts +9 -3
- package/src/providers/exploreState/entities.ts +32 -0
- package/src/providers/exploreState/{constants.ts → initializer/constants.ts} +8 -3
- package/src/providers/exploreState/initializer/utils.ts +183 -0
- package/src/providers/exploreState/utils.ts +104 -65
- package/src/providers/exploreState.tsx +54 -55
- package/src/views/ExploreView/exploreView.tsx +16 -16
- package/src/hooks/useCategoryConfigs.ts +0 -17
|
@@ -26,12 +26,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
26
26
|
exports.ExploreActionKind = exports.ExploreStateProvider = exports.ExploreStateContext = exports.ENTITY_VIEW = void 0;
|
|
27
27
|
const react_1 = __importStar(require("react"));
|
|
28
28
|
const useAuthentication_1 = require("../hooks/useAuthentication/useAuthentication");
|
|
29
|
-
const useCategoryConfigs_1 = require("../hooks/useCategoryConfigs");
|
|
30
29
|
const useCategoryFilter_1 = require("../hooks/useCategoryFilter");
|
|
31
30
|
const useConfig_1 = require("../hooks/useConfig");
|
|
32
31
|
const useURLFilterParams_1 = require("../hooks/useURLFilterParams");
|
|
33
|
-
const constants_1 = require("./exploreState/constants");
|
|
34
|
-
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");
|
|
35
35
|
/**
|
|
36
36
|
* Entity view.
|
|
37
37
|
*/
|
|
@@ -64,16 +64,14 @@ exports.ExploreStateContext = (0, react_1.createContext)({
|
|
|
64
64
|
*/
|
|
65
65
|
function ExploreStateProvider({ children, entityListType, }) {
|
|
66
66
|
const { config, defaultEntityListType } = (0, useConfig_1.useConfig)();
|
|
67
|
-
const categoryConfigs = (0, useCategoryConfigs_1.useCategoryConfigs)();
|
|
68
67
|
const { decodedCatalogParam, decodedFeatureFlagParam, decodedFilterParam } = (0, useURLFilterParams_1.useURLFilterParams)();
|
|
69
68
|
const { isEnabled: isAuthEnabled, token } = (0, useAuthentication_1.useAuthentication)();
|
|
70
69
|
const entityList = entityListType || defaultEntityListType;
|
|
71
|
-
const [
|
|
70
|
+
const [initializerArg] = (0, react_1.useState)(() => (0, utils_1.initReducerArguments)(config, entityList, decodedFilterParam, decodedCatalogParam, decodedFeatureFlagParam));
|
|
72
71
|
const [exploreState, exploreDispatch] = (0, react_1.useReducer)((s, a) => exploreReducer(s, a, {
|
|
73
|
-
categoryConfigs,
|
|
74
72
|
config,
|
|
75
73
|
entityList,
|
|
76
|
-
}),
|
|
74
|
+
}), initializerArg);
|
|
77
75
|
// does this help? https://hswolff.com/blog/how-to-usecontext-with-usereducer/
|
|
78
76
|
const exploreContextValue = (0, react_1.useMemo)(() => {
|
|
79
77
|
return { exploreDispatch, exploreState };
|
|
@@ -116,13 +114,17 @@ var ExploreActionKind;
|
|
|
116
114
|
*/
|
|
117
115
|
function exploreReducer(state, action, exploreContext) {
|
|
118
116
|
const { payload, type } = action;
|
|
119
|
-
const {
|
|
117
|
+
const { config, entityList } = exploreContext;
|
|
120
118
|
switch (type) {
|
|
121
119
|
/**
|
|
122
120
|
* Clear all filters
|
|
123
121
|
**/
|
|
124
122
|
case ExploreActionKind.ClearFilters: {
|
|
125
|
-
|
|
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) });
|
|
126
128
|
}
|
|
127
129
|
/**
|
|
128
130
|
* Paginate table
|
|
@@ -143,9 +145,13 @@ function exploreReducer(state, action, exploreContext) {
|
|
|
143
145
|
* Process explore response
|
|
144
146
|
**/
|
|
145
147
|
case ExploreActionKind.ProcessExploreResponse: {
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
148
|
+
const nextCategoryViews = payload.selectCategories
|
|
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.
|
|
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
|
-
|
|
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,23 +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
|
-
|
|
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) });
|
|
189
197
|
}
|
|
190
198
|
/**
|
|
191
199
|
* Update sorting
|
|
192
200
|
**/
|
|
193
201
|
case ExploreActionKind.UpdateSorting: {
|
|
194
|
-
|
|
195
|
-
const currentPageState = state.entityPageState[currentEntity];
|
|
196
|
-
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) });
|
|
197
203
|
}
|
|
198
204
|
/**
|
|
199
205
|
* Update column visibility
|
|
200
206
|
**/
|
|
201
207
|
case ExploreActionKind.UpdateColumnVisibility: {
|
|
202
|
-
|
|
203
|
-
const currentPageState = state.entityPageState[currentEntity];
|
|
204
|
-
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 }) });
|
|
205
209
|
}
|
|
206
210
|
default:
|
|
207
211
|
return state;
|
|
@@ -65,17 +65,17 @@ const ExploreView = (props) => {
|
|
|
65
65
|
const tabletDown = (0, useBreakpointHelper_1.useBreakpointHelper)(useBreakpointHelper_1.BREAKPOINT_FN_NAME.DOWN, breakpoints_1.DESKTOP_SM);
|
|
66
66
|
const { config, entityConfig } = (0, useConfig_1.useConfig)(); // Get app level config.
|
|
67
67
|
const { exploreDispatch, exploreState } = (0, useExploreState_1.useExploreState)(); // Get the useReducer state and dispatch for "Explore".
|
|
68
|
-
const {
|
|
68
|
+
const { entities, explorerTitle, summaryConfig, trackingConfig } = config;
|
|
69
69
|
const { listView } = entityConfig;
|
|
70
70
|
const { listHero, subTitleHero } = listView || {};
|
|
71
|
-
const { 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,
|
|
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
|
|
162
|
+
* @param categoryGroups - Category groups.
|
|
163
163
|
* @returns category filters.
|
|
164
164
|
*/
|
|
165
|
-
function buildCategoryFilters(selectCategoryViews,
|
|
166
|
-
if (!
|
|
165
|
+
function buildCategoryFilters(selectCategoryViews, categoryGroups) {
|
|
166
|
+
if (!categoryGroups) {
|
|
167
167
|
return [{ categoryViews: selectCategoryViews }];
|
|
168
168
|
}
|
|
169
|
-
return
|
|
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);
|
|
@@ -208,7 +208,7 @@ function renderList(exploreState, entityConfig, entityListType) {
|
|
|
208
208
|
if (entityListType !== tabValue) {
|
|
209
209
|
// required currently for client-side fetching as the pre-rendered page
|
|
210
210
|
// loads with the previous tabs data on the first render after switching tabs. (or similar)
|
|
211
|
-
return react_1.default.createElement(react_1.default.Fragment, null);
|
|
211
|
+
return react_1.default.createElement(react_1.default.Fragment, null);
|
|
212
212
|
}
|
|
213
213
|
return (react_1.default.createElement(tableCreator_1.TableCreator, { columns: columnsConfig, defaultSort: defaultSort, items: isRelatedView && relatedListItems ? relatedListItems : listItems !== null && listItems !== void 0 ? listItems : [], listView: listView, loading: loading, pages: paginationState.pages, pageSize: paginationState.pageSize, pagination: undefined, total: paginationState.rows }));
|
|
214
214
|
}
|
package/package.json
CHANGED
|
@@ -21,6 +21,7 @@ export enum LOADING_PANEL_STYLE {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
export interface LoadingProps {
|
|
24
|
+
appear?: boolean; // Note, if false, the component will not transition on the initial render and onEnter callbacks will not be called. In this instance, ensure the parent container is styled correctly with position relative.
|
|
24
25
|
iconSize?: SvgIconProps["fontSize"];
|
|
25
26
|
loading: boolean;
|
|
26
27
|
panelStyle?: LoadingPanelStyle; // Enables loading to mirror parent container styles.
|
|
@@ -28,6 +29,7 @@ export interface LoadingProps {
|
|
|
28
29
|
}
|
|
29
30
|
|
|
30
31
|
export const Loading = ({
|
|
32
|
+
appear = true,
|
|
31
33
|
iconSize = "large",
|
|
32
34
|
loading,
|
|
33
35
|
panelStyle = PAPER_PANEL_STYLE.ROUNDED,
|
|
@@ -35,6 +37,7 @@ export const Loading = ({
|
|
|
35
37
|
}: LoadingProps): JSX.Element | null => {
|
|
36
38
|
return (
|
|
37
39
|
<Fade
|
|
40
|
+
appear={appear}
|
|
38
41
|
in={loading}
|
|
39
42
|
mountOnEnter
|
|
40
43
|
onEnter={(node: HTMLElement): void => onFadeEnter(node)}
|
|
@@ -59,7 +62,7 @@ export const Loading = ({
|
|
|
59
62
|
*/
|
|
60
63
|
function onFadeEnter(node: HTMLElement): void {
|
|
61
64
|
const parentEl = node.parentElement;
|
|
62
|
-
if (parentEl) parentEl.style.position
|
|
65
|
+
if (parentEl) parentEl.style.setProperty("position", "relative");
|
|
63
66
|
}
|
|
64
67
|
|
|
65
68
|
/**
|
|
@@ -69,5 +72,5 @@ function onFadeEnter(node: HTMLElement): void {
|
|
|
69
72
|
*/
|
|
70
73
|
function onFadeExited(node: HTMLElement): void {
|
|
71
74
|
const parentEl = node.parentElement;
|
|
72
|
-
if (parentEl) parentEl.style.position
|
|
75
|
+
if (parentEl) parentEl.style.removeProperty("position");
|
|
73
76
|
}
|
|
@@ -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";
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import styled from "@emotion/styled";
|
|
2
|
+
|
|
3
|
+
export const TableCreator = styled.div`
|
|
4
|
+
position: relative; // Required; when the table mounts, the loading element should not transition in and therefore to position the loading element correctly, the parent container must be styled with position relative.
|
|
5
|
+
`;
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
sortingFn,
|
|
12
12
|
} from "../Table/common/utils";
|
|
13
13
|
import { Table } from "../Table/table";
|
|
14
|
+
import { TableCreator as TableCreatorContainer } from "./tableCreator.styles";
|
|
14
15
|
|
|
15
16
|
export interface TableCreatorProps<T> {
|
|
16
17
|
columns: ColumnConfig<T>[];
|
|
@@ -69,8 +70,9 @@ export const TableCreator = <T extends object>({
|
|
|
69
70
|
);
|
|
70
71
|
const initialState = getInitialState(columns, defaultSort);
|
|
71
72
|
return (
|
|
72
|
-
<
|
|
73
|
+
<TableCreatorContainer>
|
|
73
74
|
<Loading
|
|
75
|
+
appear={false}
|
|
74
76
|
loading={loading || false}
|
|
75
77
|
panelStyle={PAPER_PANEL_STYLE.FLUID}
|
|
76
78
|
/>
|
|
@@ -86,6 +88,6 @@ export const TableCreator = <T extends object>({
|
|
|
86
88
|
pagination={pagination}
|
|
87
89
|
total={total}
|
|
88
90
|
/>
|
|
89
|
-
</
|
|
91
|
+
</TableCreatorContainer>
|
|
90
92
|
);
|
|
91
93
|
};
|
package/src/config/entities.ts
CHANGED
|
@@ -51,9 +51,17 @@ export interface BackPageTabConfig extends TabConfig {
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
/**
|
|
54
|
-
* Model of
|
|
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,6 +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;
|
|
154
|
+
categoryGroupConfig?: CategoryGroupConfig;
|
|
146
155
|
detail: BackPageConfig;
|
|
147
156
|
entityMapper?: EntityMapper<T, I>;
|
|
148
157
|
exploreMode: ExploreMode;
|
|
@@ -357,7 +366,7 @@ export interface SiteConfig {
|
|
|
357
366
|
appTitle: string;
|
|
358
367
|
authentication?: AuthenticationConfig;
|
|
359
368
|
browserURL: string;
|
|
360
|
-
|
|
369
|
+
categoryGroupConfig?: CategoryGroupConfig;
|
|
361
370
|
contentDir?: string;
|
|
362
371
|
contentThemeOptionsFn?: ThemeOptionsFn;
|
|
363
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
|
|
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 "
|
|
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
|
+
}
|