@databiosphere/findable-ui 3.0.0 → 3.2.0
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/Links/common/constants.d.ts +1 -0
- package/lib/components/Links/common/constants.js +4 -0
- package/lib/components/Links/common/entities.d.ts +8 -0
- package/lib/components/Links/common/utils.d.ts +13 -0
- package/lib/components/Links/common/utils.js +21 -1
- package/lib/components/Links/components/Link/components/ExploreViewLink/exploreViewLink.d.ts +7 -0
- package/lib/components/Links/components/Link/components/ExploreViewLink/exploreViewLink.js +148 -0
- package/lib/components/Links/components/Link/link.d.ts +2 -2
- package/lib/components/Links/components/Link/link.js +22 -6
- package/lib/components/common/Progress/components/CircularProgress/circularProgress.d.ts +7 -0
- package/lib/components/common/Progress/components/CircularProgress/circularProgress.js +28 -0
- package/lib/components/common/Progress/components/CircularProgress/circularProgress.styles.d.ts +5 -0
- package/lib/components/common/Progress/components/CircularProgress/circularProgress.styles.js +11 -0
- package/lib/components/common/Progress/components/CircularProgress/components/CircularProgressTrack/circularProgressTrack.d.ts +7 -0
- package/lib/components/common/Progress/components/CircularProgress/components/CircularProgressTrack/circularProgressTrack.js +44 -0
- package/lib/components/common/Progress/components/CircularProgress/components/CircularProgressTrack/circularProgressTrack.styles.d.ts +3 -0
- package/lib/components/common/Progress/components/CircularProgress/components/CircularProgressTrack/circularProgressTrack.styles.js +32 -0
- package/lib/config/entities.d.ts +2 -1
- package/lib/hooks/useCategoryFilter.d.ts +7 -1
- package/lib/hooks/useCategoryFilter.js +25 -6
- package/lib/providers/exploreState/initializer/constants.d.ts +2 -0
- package/lib/providers/exploreState/initializer/constants.js +7 -1
- package/lib/providers/exploreState/initializer/utils.js +1 -8
- package/lib/providers/exploreState/payloads/entities.d.ts +8 -1
- package/lib/providers/exploreState/utils.d.ts +4 -2
- package/lib/providers/exploreState/utils.js +4 -4
- package/lib/providers/exploreState.d.ts +10 -2
- package/lib/providers/exploreState.js +13 -0
- package/lib/styles/common/mixins/colors.d.ts +3 -3
- package/lib/styles/common/mixins/colors.js +7 -7
- package/lib/theme/common/components.d.ts +6 -0
- package/lib/theme/common/components.js +31 -1
- package/lib/theme/theme.js +1 -0
- package/package.json +1 -1
- package/src/components/Links/common/constants.ts +1 -0
- package/src/components/Links/common/entities.ts +11 -0
- package/src/components/Links/common/utils.ts +28 -0
- package/src/components/Links/components/Link/components/ExploreViewLink/exploreViewLink.tsx +172 -0
- package/src/components/Links/components/Link/link.tsx +36 -14
- package/src/components/common/Progress/components/CircularProgress/circularProgress.styles.ts +6 -0
- package/src/components/common/Progress/components/CircularProgress/circularProgress.tsx +26 -0
- package/src/components/common/Progress/components/CircularProgress/components/CircularProgressTrack/circularProgressTrack.styles.ts +33 -0
- package/src/components/common/Progress/components/CircularProgress/components/CircularProgressTrack/circularProgressTrack.tsx +23 -0
- package/src/config/entities.ts +4 -0
- package/src/hooks/useCategoryFilter.ts +31 -7
- package/src/providers/exploreState/initializer/constants.ts +8 -0
- package/src/providers/exploreState/initializer/utils.ts +6 -9
- package/src/providers/exploreState/payloads/entities.ts +8 -0
- package/src/providers/exploreState/utils.ts +11 -7
- package/src/providers/exploreState.tsx +33 -0
- package/src/styles/common/mixins/colors.ts +6 -6
- package/src/theme/common/components.ts +32 -0
- package/src/theme/theme.ts +1 -0
- package/types/data-explorer-ui.d.ts +10 -0
|
@@ -3,7 +3,7 @@ import { AzulSearchIndex } from "../apis/azul/common/entities";
|
|
|
3
3
|
import { SelectCategoryView, SelectedFilter } from "../common/entities";
|
|
4
4
|
import { CategoryGroup, SiteConfig } from "../config/entities";
|
|
5
5
|
import { EntityPageStateMapper, EntityStateByCategoryGroupConfigKey, ListItem } from "./exploreState/entities";
|
|
6
|
-
import { ApplySavedFilterPayload, PaginateTablePayload, PatchExploreResponsePayload, ProcessExploreResponsePayload, ProcessRelatedResponsePayload, ResetExploreResponsePayload, ToggleEntityViewPayload, UpdateColumnVisibilityPayload, UpdateEntityViewAccessPayload, UpdateFilterPayload, UpdateRowSelectionPayload, UpdateSortingPayload } from "./exploreState/payloads/entities";
|
|
6
|
+
import { ApplySavedFilterPayload, PaginateTablePayload, PatchExploreResponsePayload, ProcessExploreResponsePayload, ProcessRelatedResponsePayload, ResetExploreResponsePayload, ToggleEntityViewPayload, UpdateColumnVisibilityPayload, UpdateEntityFiltersPayload, UpdateEntityViewAccessPayload, UpdateFilterPayload, UpdateRowSelectionPayload, UpdateSortingPayload } from "./exploreState/payloads/entities";
|
|
7
7
|
export declare type CatalogState = string | undefined;
|
|
8
8
|
/**
|
|
9
9
|
* Entity view.
|
|
@@ -114,6 +114,7 @@ export declare enum ExploreActionKind {
|
|
|
114
114
|
SelectEntityType = "SELECT_ENTITY_TYPE",
|
|
115
115
|
ToggleEntityView = "TOGGLE_ENTITY_VIEW",
|
|
116
116
|
UpdateColumnVisibility = "UPDATE_COLUMN_VISIBILITY",
|
|
117
|
+
UpdateEntityFilters = "UPDATE_ENTITY_FILTERS",
|
|
117
118
|
UpdateEntityViewAccess = "UPDATE_ENTITY_VIEW_ACCESS",
|
|
118
119
|
UpdateFilter = "UPDATE_FILTER",
|
|
119
120
|
UpdateRowSelection = "UPDATE_ROW_SELECTION",
|
|
@@ -122,7 +123,7 @@ export declare enum ExploreActionKind {
|
|
|
122
123
|
/**
|
|
123
124
|
* Explore action.
|
|
124
125
|
*/
|
|
125
|
-
export declare type ExploreAction = ApplySavedFilterAction | ClearFiltersAction | PaginateTableAction | PatchExploreResponseAction | ProcessExploreResponseAction | ProcessRelatedResponseAction | ResetExploreResponseAction | ResetStateAction | SelectEntityTypeAction | ToggleEntityViewAction | UpdateColumnVisibilityAction | UpdateEntityViewAccessAction | UpdateFilterAction | UpdateRowSelectionAction | UpdateSortingAction;
|
|
126
|
+
export declare type ExploreAction = ApplySavedFilterAction | ClearFiltersAction | PaginateTableAction | PatchExploreResponseAction | ProcessExploreResponseAction | ProcessRelatedResponseAction | ResetExploreResponseAction | ResetStateAction | SelectEntityTypeAction | ToggleEntityViewAction | UpdateColumnVisibilityAction | UpdateEntityFiltersAction | UpdateEntityViewAccessAction | UpdateFilterAction | UpdateRowSelectionAction | UpdateSortingAction;
|
|
126
127
|
/**
|
|
127
128
|
* Apply saved filter action.
|
|
128
129
|
*/
|
|
@@ -200,6 +201,13 @@ declare type UpdateColumnVisibilityAction = {
|
|
|
200
201
|
payload: UpdateColumnVisibilityPayload;
|
|
201
202
|
type: ExploreActionKind.UpdateColumnVisibility;
|
|
202
203
|
};
|
|
204
|
+
/**
|
|
205
|
+
* Update entity filters action.
|
|
206
|
+
*/
|
|
207
|
+
declare type UpdateEntityFiltersAction = {
|
|
208
|
+
payload: UpdateEntityFiltersPayload;
|
|
209
|
+
type: ExploreActionKind.UpdateEntityFilters;
|
|
210
|
+
};
|
|
203
211
|
/**
|
|
204
212
|
* Update entity view access action.
|
|
205
213
|
*/
|
|
@@ -104,6 +104,7 @@ var ExploreActionKind;
|
|
|
104
104
|
ExploreActionKind["SelectEntityType"] = "SELECT_ENTITY_TYPE";
|
|
105
105
|
ExploreActionKind["ToggleEntityView"] = "TOGGLE_ENTITY_VIEW";
|
|
106
106
|
ExploreActionKind["UpdateColumnVisibility"] = "UPDATE_COLUMN_VISIBILITY";
|
|
107
|
+
ExploreActionKind["UpdateEntityFilters"] = "UPDATE_ENTITY_FILTERS";
|
|
107
108
|
ExploreActionKind["UpdateEntityViewAccess"] = "UPDATE_ENTITY_VIEW_ACCESS";
|
|
108
109
|
ExploreActionKind["UpdateFilter"] = "UPDATE_FILTER";
|
|
109
110
|
ExploreActionKind["UpdateRowSelection"] = "UPDATE_ROW_SELECTION";
|
|
@@ -224,6 +225,18 @@ function exploreReducer(state, action, exploreContext) {
|
|
|
224
225
|
case ExploreActionKind.UpdateColumnVisibility: {
|
|
225
226
|
return Object.assign(Object.assign({}, state), { entityPageState: (0, utils_2.updateEntityPageState)(state.tabValue, state.entityPageState, { columnsVisibility: payload }) });
|
|
226
227
|
}
|
|
228
|
+
/**
|
|
229
|
+
* Update entity filters.
|
|
230
|
+
*/
|
|
231
|
+
case ExploreActionKind.UpdateEntityFilters: {
|
|
232
|
+
const { entityListType, filters: filterState } = payload;
|
|
233
|
+
const categoryGroupConfigKey = (0, utils_2.getEntityCategoryGroupConfigKey)(entityListType, state.entityPageState);
|
|
234
|
+
(0, utils_2.updateEntityStateByCategoryGroupConfigKey)(state, {
|
|
235
|
+
filterState,
|
|
236
|
+
savedFilterState: [], // Clear saved filter state.
|
|
237
|
+
}, categoryGroupConfigKey);
|
|
238
|
+
return Object.assign(Object.assign({}, state), { entityPageState: (0, utils_2.resetRowSelection)(state, categoryGroupConfigKey) });
|
|
239
|
+
}
|
|
227
240
|
/**
|
|
228
241
|
* Update entity view access
|
|
229
242
|
**/
|
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
import { CommonColors, PaletteColor } from "@mui/material/styles/createPalette";
|
|
2
2
|
import { ThemeProps } from "../../../theme/theme";
|
|
3
|
+
export declare const alertLight: ({ theme }: ThemeProps) => PaletteColor["light"];
|
|
3
4
|
export declare const alertLightest: ({ theme, }: ThemeProps) => PaletteColor["lightest"];
|
|
4
5
|
export declare const alertMain: ({ theme }: ThemeProps) => PaletteColor["main"];
|
|
5
6
|
export declare const errorMain: ({ theme }: ThemeProps) => PaletteColor["main"];
|
|
6
|
-
export declare const infoDark: ({ theme }: ThemeProps) => PaletteColor["dark"];
|
|
7
7
|
export declare const infoLight: ({ theme }: ThemeProps) => PaletteColor["light"];
|
|
8
8
|
export declare const infoLightest: ({ theme }: ThemeProps) => PaletteColor["lightest"];
|
|
9
9
|
export declare const infoMain: ({ theme }: ThemeProps) => PaletteColor["main"];
|
|
10
|
-
export declare const inkDark: ({ theme }: ThemeProps) => PaletteColor["dark"];
|
|
11
10
|
export declare const inkLight: ({ theme }: ThemeProps) => PaletteColor["light"];
|
|
12
|
-
export declare const inkLightest: ({ theme }: ThemeProps) => PaletteColor["lightest"];
|
|
13
11
|
export declare const inkMain: ({ theme }: ThemeProps) => PaletteColor["main"];
|
|
14
12
|
export declare const primaryDark: ({ theme }: ThemeProps) => PaletteColor["dark"];
|
|
15
13
|
export declare const primaryMain: ({ theme }: ThemeProps) => PaletteColor["main"];
|
|
@@ -17,8 +15,10 @@ export declare const smokeDark: ({ theme }: ThemeProps) => PaletteColor["dark"];
|
|
|
17
15
|
export declare const smokeLight: ({ theme }: ThemeProps) => PaletteColor["light"];
|
|
18
16
|
export declare const smokeLightest: ({ theme, }: ThemeProps) => PaletteColor["lightest"];
|
|
19
17
|
export declare const smokeMain: ({ theme }: ThemeProps) => PaletteColor["main"];
|
|
18
|
+
export declare const successLight: ({ theme }: ThemeProps) => PaletteColor["light"];
|
|
20
19
|
export declare const successLightest: ({ theme, }: ThemeProps) => PaletteColor["lightest"];
|
|
21
20
|
export declare const successMain: ({ theme }: ThemeProps) => PaletteColor["main"];
|
|
21
|
+
export declare const warningLight: ({ theme }: ThemeProps) => PaletteColor["light"];
|
|
22
22
|
export declare const warningLightest: ({ theme, }: ThemeProps) => PaletteColor["lightest"];
|
|
23
23
|
export declare const warningMain: ({ theme }: ThemeProps) => PaletteColor["main"];
|
|
24
24
|
export declare const white: ({ theme }: ThemeProps) => CommonColors["white"];
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.white = exports.warningMain = exports.warningLightest = exports.successMain = exports.successLightest = exports.smokeMain = exports.smokeLightest = exports.smokeLight = exports.smokeDark = exports.primaryMain = exports.primaryDark = exports.inkMain = exports.
|
|
3
|
+
exports.white = exports.warningMain = exports.warningLightest = exports.warningLight = exports.successMain = exports.successLightest = exports.successLight = exports.smokeMain = exports.smokeLightest = exports.smokeLight = exports.smokeDark = exports.primaryMain = exports.primaryDark = exports.inkMain = exports.inkLight = exports.infoMain = exports.infoLightest = exports.infoLight = exports.errorMain = exports.alertMain = exports.alertLightest = exports.alertLight = void 0;
|
|
4
4
|
// Alert
|
|
5
|
+
const alertLight = ({ theme }) => theme.palette.alert.light;
|
|
6
|
+
exports.alertLight = alertLight;
|
|
5
7
|
const alertLightest = ({ theme, }) => theme.palette.alert.lightest;
|
|
6
8
|
exports.alertLightest = alertLightest;
|
|
7
9
|
const alertMain = ({ theme }) => theme.palette.alert.main;
|
|
@@ -10,8 +12,6 @@ exports.alertMain = alertMain;
|
|
|
10
12
|
const errorMain = ({ theme }) => theme.palette.error.main;
|
|
11
13
|
exports.errorMain = errorMain;
|
|
12
14
|
// Info
|
|
13
|
-
const infoDark = ({ theme }) => theme.palette.info.dark;
|
|
14
|
-
exports.infoDark = infoDark;
|
|
15
15
|
const infoLight = ({ theme }) => theme.palette.info.light;
|
|
16
16
|
exports.infoLight = infoLight;
|
|
17
17
|
const infoLightest = ({ theme }) => theme.palette.info.lightest;
|
|
@@ -19,12 +19,8 @@ exports.infoLightest = infoLightest;
|
|
|
19
19
|
const infoMain = ({ theme }) => theme.palette.info.main;
|
|
20
20
|
exports.infoMain = infoMain;
|
|
21
21
|
// Ink
|
|
22
|
-
const inkDark = ({ theme }) => theme.palette.ink.dark;
|
|
23
|
-
exports.inkDark = inkDark;
|
|
24
22
|
const inkLight = ({ theme }) => theme.palette.ink.light;
|
|
25
23
|
exports.inkLight = inkLight;
|
|
26
|
-
const inkLightest = ({ theme }) => theme.palette.ink.lightest;
|
|
27
|
-
exports.inkLightest = inkLightest;
|
|
28
24
|
const inkMain = ({ theme }) => theme.palette.ink.main;
|
|
29
25
|
exports.inkMain = inkMain;
|
|
30
26
|
// Primary
|
|
@@ -42,11 +38,15 @@ exports.smokeLightest = smokeLightest;
|
|
|
42
38
|
const smokeMain = ({ theme }) => theme.palette.smoke.main;
|
|
43
39
|
exports.smokeMain = smokeMain;
|
|
44
40
|
// Success
|
|
41
|
+
const successLight = ({ theme }) => theme.palette.success.light;
|
|
42
|
+
exports.successLight = successLight;
|
|
45
43
|
const successLightest = ({ theme, }) => theme.palette.success.lightest;
|
|
46
44
|
exports.successLightest = successLightest;
|
|
47
45
|
const successMain = ({ theme }) => theme.palette.success.main;
|
|
48
46
|
exports.successMain = successMain;
|
|
49
47
|
// Warning
|
|
48
|
+
const warningLight = ({ theme }) => theme.palette.warning.light;
|
|
49
|
+
exports.warningLight = warningLight;
|
|
50
50
|
const warningLightest = ({ theme, }) => theme.palette.warning.lightest;
|
|
51
51
|
exports.warningLightest = warningLightest;
|
|
52
52
|
const warningMain = ({ theme }) => theme.palette.warning.main;
|
|
@@ -75,6 +75,12 @@ export declare const MuiCheckbox: (theme: Theme) => Components["MuiCheckbox"];
|
|
|
75
75
|
* @returns MuiChip component theme styles.
|
|
76
76
|
*/
|
|
77
77
|
export declare const MuiChip: (theme: Theme) => Components["MuiChip"];
|
|
78
|
+
/**
|
|
79
|
+
* MuiCircularProgress Component
|
|
80
|
+
* @param theme - Theme.
|
|
81
|
+
* @returns MuiCircularProgress component theme styles.
|
|
82
|
+
*/
|
|
83
|
+
export declare const MuiCircularProgress: (theme: Theme) => Components["MuiCircularProgress"];
|
|
78
84
|
/**
|
|
79
85
|
* MuiCssBaseline Component
|
|
80
86
|
* @param theme - Theme.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.MuiTypography = exports.MuiTooltip = exports.MuiToolbar = exports.MuiToggleButtonGroup = exports.MuiToggleButton = exports.MuiTabs = exports.MuiTableSortLabel = exports.MuiTableCell = exports.MuiTab = exports.MuiSvgIcon = exports.MuiSelect = exports.MuiRadio = exports.MuiPaper = exports.MuiOutlinedInput = exports.MuiMenuItem = exports.MuiListSubheader = exports.MuiListItemText = exports.MuiListItemButton = exports.MuiLink = exports.MuiInputBase = exports.MuiIconButton = exports.MuiFormHelperText = exports.MuiFormGroup = exports.MuiFormControlLabel = exports.MuiDrawer = exports.MuiDivider = exports.MuiDialogTitle = exports.MuiDialogContent = exports.MuiDialogActions = exports.MuiDialog = exports.MuiCssBaseline = exports.MuiChip = exports.MuiCheckbox = exports.MuiCard = exports.MuiButtonGroup = exports.MuiButtonBase = exports.MuiButton = exports.MuiBreadcrumbs = exports.MuiBackdrop = exports.MuiAppBar = exports.MuiAlertTitle = exports.MuiAlert = exports.MuiAccordionSummary = exports.MuiAccordionDetails = exports.MuiAccordion = void 0;
|
|
3
|
+
exports.MuiTypography = exports.MuiTooltip = exports.MuiToolbar = exports.MuiToggleButtonGroup = exports.MuiToggleButton = exports.MuiTabs = exports.MuiTableSortLabel = exports.MuiTableCell = exports.MuiTab = exports.MuiSvgIcon = exports.MuiSelect = exports.MuiRadio = exports.MuiPaper = exports.MuiOutlinedInput = exports.MuiMenuItem = exports.MuiListSubheader = exports.MuiListItemText = exports.MuiListItemButton = exports.MuiLink = exports.MuiInputBase = exports.MuiIconButton = exports.MuiFormHelperText = exports.MuiFormGroup = exports.MuiFormControlLabel = exports.MuiDrawer = exports.MuiDivider = exports.MuiDialogTitle = exports.MuiDialogContent = exports.MuiDialogActions = exports.MuiDialog = exports.MuiCssBaseline = exports.MuiCircularProgress = exports.MuiChip = exports.MuiCheckbox = exports.MuiCard = exports.MuiButtonGroup = exports.MuiButtonBase = exports.MuiButton = exports.MuiBreadcrumbs = exports.MuiBackdrop = exports.MuiAppBar = exports.MuiAlertTitle = exports.MuiAlert = exports.MuiAccordionSummary = exports.MuiAccordionDetails = exports.MuiAccordion = void 0;
|
|
4
4
|
const errorIcon_1 = require("../../components/common/CustomIcon/components/ErrorIcon/errorIcon");
|
|
5
5
|
const infoIcon_1 = require("../../components/common/CustomIcon/components/InfoIcon/infoIcon");
|
|
6
6
|
const successIcon_1 = require("../../components/common/CustomIcon/components/SuccessIcon/successIcon");
|
|
@@ -552,6 +552,31 @@ const MuiChip = (theme) => {
|
|
|
552
552
|
};
|
|
553
553
|
};
|
|
554
554
|
exports.MuiChip = MuiChip;
|
|
555
|
+
/**
|
|
556
|
+
* MuiCircularProgress Component
|
|
557
|
+
* @param theme - Theme.
|
|
558
|
+
* @returns MuiCircularProgress component theme styles.
|
|
559
|
+
*/
|
|
560
|
+
const MuiCircularProgress = (theme) => {
|
|
561
|
+
return {
|
|
562
|
+
styleOverrides: {
|
|
563
|
+
circle: {
|
|
564
|
+
strokeLinecap: "round",
|
|
565
|
+
},
|
|
566
|
+
},
|
|
567
|
+
variants: [
|
|
568
|
+
{
|
|
569
|
+
props: {
|
|
570
|
+
color: "alert",
|
|
571
|
+
},
|
|
572
|
+
style: {
|
|
573
|
+
color: theme.palette.alert.main,
|
|
574
|
+
},
|
|
575
|
+
},
|
|
576
|
+
],
|
|
577
|
+
};
|
|
578
|
+
};
|
|
579
|
+
exports.MuiCircularProgress = MuiCircularProgress;
|
|
555
580
|
/**
|
|
556
581
|
* MuiCssBaseline Component
|
|
557
582
|
* @param theme - Theme.
|
|
@@ -851,6 +876,11 @@ exports.MuiLink = {
|
|
|
851
876
|
defaultProps: {
|
|
852
877
|
underline: "hover",
|
|
853
878
|
},
|
|
879
|
+
styleOverrides: {
|
|
880
|
+
root: {
|
|
881
|
+
cursor: "pointer",
|
|
882
|
+
},
|
|
883
|
+
},
|
|
854
884
|
};
|
|
855
885
|
/**
|
|
856
886
|
* MuiListItemButton Component
|
package/lib/theme/theme.js
CHANGED
|
@@ -96,6 +96,7 @@ function createAppTheme(customOptions) {
|
|
|
96
96
|
MuiCard: C.MuiCard,
|
|
97
97
|
MuiCheckbox: C.MuiCheckbox(theme),
|
|
98
98
|
MuiChip: C.MuiChip(theme),
|
|
99
|
+
MuiCircularProgress: C.MuiCircularProgress(theme),
|
|
99
100
|
MuiCssBaseline: C.MuiCssBaseline(theme),
|
|
100
101
|
MuiDialog: C.MuiDialog(theme),
|
|
101
102
|
MuiDialogActions: C.MuiDialogActions,
|
package/package.json
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const URL_OBJECT_KEYS = ["href", "query"];
|
|
@@ -1,4 +1,15 @@
|
|
|
1
|
+
import { UrlObject } from "url";
|
|
2
|
+
|
|
1
3
|
export enum ANCHOR_TARGET {
|
|
2
4
|
BLANK = "_blank",
|
|
3
5
|
SELF = "_self",
|
|
4
6
|
}
|
|
7
|
+
|
|
8
|
+
export type StrictUrlObject = Omit<UrlObject, "href" | "query"> & {
|
|
9
|
+
href: string;
|
|
10
|
+
query: string;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export type Url = string | UrlObjectWithHrefAndQuery;
|
|
14
|
+
|
|
15
|
+
export type UrlObjectWithHrefAndQuery = Pick<StrictUrlObject, "href" | "query">;
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { URL_OBJECT_KEYS } from "./constants";
|
|
2
|
+
import { Url, UrlObjectWithHrefAndQuery } from "./entities";
|
|
3
|
+
|
|
1
4
|
/**
|
|
2
5
|
* Returns true if the given link is an internal link.
|
|
3
6
|
* @param link - Link.
|
|
@@ -6,3 +9,28 @@
|
|
|
6
9
|
export function isClientSideNavigation(link: string): boolean {
|
|
7
10
|
return /^\/(?!\/)/.test(link);
|
|
8
11
|
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Returns true if the given url is a URL object with href and query.
|
|
15
|
+
* @param value - URL.
|
|
16
|
+
* @returns true if the given url is a URL object with href and query.
|
|
17
|
+
*/
|
|
18
|
+
export function isURLObjectWithHrefAndQuery(
|
|
19
|
+
value: Url
|
|
20
|
+
): value is UrlObjectWithHrefAndQuery {
|
|
21
|
+
return (
|
|
22
|
+
typeof value !== "string" &&
|
|
23
|
+
Object.entries(value).every(
|
|
24
|
+
([key, value]) => URL_OBJECT_KEYS.includes(key) && !!value
|
|
25
|
+
)
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Returns true if the given url is a string.
|
|
31
|
+
* @param value - URL.
|
|
32
|
+
* @returns true if the given url is a string.
|
|
33
|
+
*/
|
|
34
|
+
export function isURLString(value: Url): value is string {
|
|
35
|
+
return typeof value === "string";
|
|
36
|
+
}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import Link from "next/link";
|
|
2
|
+
import React, { useCallback } from "react";
|
|
3
|
+
import { UrlObject } from "url";
|
|
4
|
+
import { SelectedFilter } from "../../../../../../common/entities";
|
|
5
|
+
import { useExploreState } from "../../../../../../hooks/useExploreState";
|
|
6
|
+
import {
|
|
7
|
+
ExploreActionKind,
|
|
8
|
+
ExploreState,
|
|
9
|
+
} from "../../../../../../providers/exploreState";
|
|
10
|
+
import {
|
|
11
|
+
ANCHOR_TARGET,
|
|
12
|
+
UrlObjectWithHrefAndQuery,
|
|
13
|
+
} from "../../../../common/entities";
|
|
14
|
+
import { LinkProps } from "../../link";
|
|
15
|
+
|
|
16
|
+
const PARAM_FILTER = "filter";
|
|
17
|
+
|
|
18
|
+
export interface ExploreViewLinkProps
|
|
19
|
+
extends Omit<LinkProps, "copyable" | "noWrap" | "url"> {
|
|
20
|
+
url: UrlObjectWithHrefAndQuery;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const ExploreViewLink = ({
|
|
24
|
+
className,
|
|
25
|
+
label,
|
|
26
|
+
onClick,
|
|
27
|
+
target = ANCHOR_TARGET.SELF,
|
|
28
|
+
url,
|
|
29
|
+
}: ExploreViewLinkProps): JSX.Element => {
|
|
30
|
+
const { exploreDispatch, exploreState } = useExploreState();
|
|
31
|
+
|
|
32
|
+
if (!isValidExploreURL(url, exploreState)) {
|
|
33
|
+
throwError(url);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const onNavigate = useCallback(() => {
|
|
37
|
+
const entityListType = getEntityListType(url.href);
|
|
38
|
+
const filters = getSelectedFilters(url.query);
|
|
39
|
+
exploreDispatch({
|
|
40
|
+
payload: { entityListType, filters },
|
|
41
|
+
type: ExploreActionKind.UpdateEntityFilters,
|
|
42
|
+
});
|
|
43
|
+
onClick?.();
|
|
44
|
+
}, [exploreDispatch, onClick, url]);
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<Link
|
|
48
|
+
className={className}
|
|
49
|
+
href={url.href}
|
|
50
|
+
onClick={onNavigate}
|
|
51
|
+
rel="noopener"
|
|
52
|
+
target={target}
|
|
53
|
+
>
|
|
54
|
+
{label}
|
|
55
|
+
</Link>
|
|
56
|
+
);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Returns the entity list type "entityListType" inferred from the given href.
|
|
61
|
+
* @param href - Href.
|
|
62
|
+
* @returns entity list type.
|
|
63
|
+
*/
|
|
64
|
+
function getEntityListType(href: UrlObjectWithHrefAndQuery["href"]): string {
|
|
65
|
+
return href.substring(1);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Returns the selected filters from the given query.
|
|
70
|
+
* @param query - Query.
|
|
71
|
+
* @returns selected filters.
|
|
72
|
+
*/
|
|
73
|
+
function getSelectedFilters(
|
|
74
|
+
query: UrlObjectWithHrefAndQuery["query"]
|
|
75
|
+
): SelectedFilter[] {
|
|
76
|
+
const decodedQuery = decodeURIComponent(query);
|
|
77
|
+
const parsedQuery = JSON.parse(decodedQuery);
|
|
78
|
+
return parsedQuery[PARAM_FILTER];
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Returns true if the given value is a SelectedFilter.
|
|
83
|
+
* @param value - Value.
|
|
84
|
+
* @returns true if the given value is a SelectedFilter.
|
|
85
|
+
*/
|
|
86
|
+
function isSelectedFilter(value: unknown): value is SelectedFilter {
|
|
87
|
+
return (
|
|
88
|
+
typeof value === "object" &&
|
|
89
|
+
value !== null &&
|
|
90
|
+
"categoryKey" in value &&
|
|
91
|
+
"value" in value
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Returns true if the given query string is a valid JSON string.
|
|
97
|
+
* @param query - Query string.
|
|
98
|
+
* @returns true if the given query string is a valid JSON string.
|
|
99
|
+
*/
|
|
100
|
+
function isValidJsonString(query: string): boolean {
|
|
101
|
+
try {
|
|
102
|
+
JSON.parse(query);
|
|
103
|
+
return true;
|
|
104
|
+
} catch (e) {
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Returns true if the given explore link is valid.
|
|
111
|
+
* @param url - Explore link URL.
|
|
112
|
+
* @param exploreState - Explore state.
|
|
113
|
+
* @returns true if the given explore link is valid.
|
|
114
|
+
*/
|
|
115
|
+
function isValidExploreURL(
|
|
116
|
+
url: UrlObjectWithHrefAndQuery,
|
|
117
|
+
exploreState: ExploreState
|
|
118
|
+
): boolean {
|
|
119
|
+
const validHref = isValidHref(url, exploreState);
|
|
120
|
+
const validQuery = isValidQuery(url);
|
|
121
|
+
return validHref && validQuery;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Returns true if the given href is a configured key in the explore state's entityPageState.
|
|
126
|
+
* @param url - Explore link URL.
|
|
127
|
+
* @param exploreState - Explore state.
|
|
128
|
+
* @returns true if the given href is configured in the explore state.
|
|
129
|
+
*/
|
|
130
|
+
function isValidHref(
|
|
131
|
+
url: UrlObjectWithHrefAndQuery,
|
|
132
|
+
exploreState: ExploreState
|
|
133
|
+
): boolean {
|
|
134
|
+
const { entityPageState } = exploreState;
|
|
135
|
+
const { href } = url;
|
|
136
|
+
return href.startsWith("/") && href.substring(1) in entityPageState;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Returns true if the given explore query is valid.
|
|
141
|
+
* @param url - Explore link URL.
|
|
142
|
+
* @returns true if the given explore query is valid.
|
|
143
|
+
*/
|
|
144
|
+
function isValidQuery(url: UrlObjectWithHrefAndQuery): boolean {
|
|
145
|
+
const { query } = url;
|
|
146
|
+
// Decode and parse the query.
|
|
147
|
+
const decodedQuery = decodeURIComponent(query);
|
|
148
|
+
// Query should be a valid JSON string.
|
|
149
|
+
if (isValidJsonString(decodedQuery)) {
|
|
150
|
+
const parsedQuery = JSON.parse(decodedQuery);
|
|
151
|
+
// Query should contain "filter" key.
|
|
152
|
+
if (PARAM_FILTER in parsedQuery) {
|
|
153
|
+
const filters = parsedQuery[PARAM_FILTER];
|
|
154
|
+
// Filter should be an array.
|
|
155
|
+
if (Array.isArray(filters)) {
|
|
156
|
+
// Filter should contain only SelectedFilter objects.
|
|
157
|
+
return filters.every(isSelectedFilter);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return false;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Throws an error with the given URL object.
|
|
166
|
+
* @param url - URL object.
|
|
167
|
+
*/
|
|
168
|
+
function throwError(url: UrlObject): never {
|
|
169
|
+
throw new Error(
|
|
170
|
+
`Invalid explore URL href or query: ${url.href}, ${url.query}`
|
|
171
|
+
);
|
|
172
|
+
}
|
|
@@ -3,8 +3,13 @@ import NLink from "next/link";
|
|
|
3
3
|
import React, { ReactNode } from "react";
|
|
4
4
|
import { isValidUrl } from "../../../../common/utils";
|
|
5
5
|
import { CopyToClipboard } from "../../../common/CopyToClipboard/copyToClipboard";
|
|
6
|
-
import { ANCHOR_TARGET } from "../../common/entities";
|
|
7
|
-
import {
|
|
6
|
+
import { ANCHOR_TARGET, Url } from "../../common/entities";
|
|
7
|
+
import {
|
|
8
|
+
isClientSideNavigation,
|
|
9
|
+
isURLObjectWithHrefAndQuery,
|
|
10
|
+
isURLString,
|
|
11
|
+
} from "../../common/utils";
|
|
12
|
+
import { ExploreViewLink } from "./components/ExploreViewLink/exploreViewLink";
|
|
8
13
|
|
|
9
14
|
export interface LinkProps {
|
|
10
15
|
className?: string;
|
|
@@ -13,7 +18,7 @@ export interface LinkProps {
|
|
|
13
18
|
noWrap?: MLinkProps["noWrap"];
|
|
14
19
|
onClick?: () => void;
|
|
15
20
|
target?: ANCHOR_TARGET;
|
|
16
|
-
url:
|
|
21
|
+
url: Url /* url specified as UrlObject with href and query defined, and is currently only used for internal links */;
|
|
17
22
|
}
|
|
18
23
|
|
|
19
24
|
export const Link = ({
|
|
@@ -25,9 +30,22 @@ export const Link = ({
|
|
|
25
30
|
target,
|
|
26
31
|
url,
|
|
27
32
|
}: LinkProps): JSX.Element => {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
33
|
+
if (isURLObjectWithHrefAndQuery(url)) {
|
|
34
|
+
/* Internal navigation - explore link */
|
|
35
|
+
return (
|
|
36
|
+
<ExploreViewLink
|
|
37
|
+
className={className}
|
|
38
|
+
label={label}
|
|
39
|
+
onClick={onClick}
|
|
40
|
+
target={target}
|
|
41
|
+
url={url}
|
|
42
|
+
/>
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
if (isURLString(url)) {
|
|
46
|
+
if (isClientSideNavigation(url)) {
|
|
47
|
+
/* Client-side navigation */
|
|
48
|
+
return (
|
|
31
49
|
<>
|
|
32
50
|
<NLink href={url} legacyBehavior passHref>
|
|
33
51
|
<MLink
|
|
@@ -42,23 +60,27 @@ export const Link = ({
|
|
|
42
60
|
</NLink>
|
|
43
61
|
{copyable && <CopyToClipboard copyStr={url} />}
|
|
44
62
|
</>
|
|
45
|
-
)
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
if (isValidUrl(url)) {
|
|
66
|
+
/* External navigation */
|
|
67
|
+
return (
|
|
46
68
|
<>
|
|
47
69
|
<MLink
|
|
48
70
|
className={className}
|
|
49
71
|
href={url}
|
|
50
|
-
rel="noopener noreferrer"
|
|
51
72
|
noWrap={noWrap}
|
|
52
|
-
target={target || ANCHOR_TARGET.BLANK}
|
|
53
73
|
onClick={onClick}
|
|
74
|
+
rel="noopener noreferrer"
|
|
75
|
+
target={target || ANCHOR_TARGET.BLANK}
|
|
54
76
|
>
|
|
55
77
|
{label}
|
|
56
78
|
</MLink>
|
|
57
79
|
{copyable && <CopyToClipboard copyStr={url} />}
|
|
58
80
|
</>
|
|
59
|
-
)
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/* Invalid URL */
|
|
85
|
+
return <>{label}</>;
|
|
64
86
|
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CircularProgress as MCircularProgress,
|
|
3
|
+
CircularProgressProps as MCircularProgressProps,
|
|
4
|
+
} from "@mui/material";
|
|
5
|
+
import React, { ElementType } from "react";
|
|
6
|
+
import { ProgressPositioner } from "./circularProgress.styles";
|
|
7
|
+
import { CircularProgressTrack } from "./components/CircularProgressTrack/circularProgressTrack";
|
|
8
|
+
|
|
9
|
+
export interface CircularProgressProps extends MCircularProgressProps {
|
|
10
|
+
className?: string;
|
|
11
|
+
Track?: ElementType<CircularProgressProps>;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const CircularProgress = ({
|
|
15
|
+
className,
|
|
16
|
+
value,
|
|
17
|
+
Track = CircularProgressTrack,
|
|
18
|
+
...props /* Spread props to allow for CircularProgress specific props e.g. "disableShrink". */
|
|
19
|
+
}: CircularProgressProps): JSX.Element => {
|
|
20
|
+
return (
|
|
21
|
+
<ProgressPositioner className={className}>
|
|
22
|
+
<Track {...props} />
|
|
23
|
+
<MCircularProgress value={value} {...props} />
|
|
24
|
+
</ProgressPositioner>
|
|
25
|
+
);
|
|
26
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import styled from "@emotion/styled";
|
|
2
|
+
import { CircularProgress as MCircularProgress } from "@mui/material";
|
|
3
|
+
import {
|
|
4
|
+
alertLight,
|
|
5
|
+
infoLight,
|
|
6
|
+
smokeLight,
|
|
7
|
+
successLight,
|
|
8
|
+
warningLight,
|
|
9
|
+
} from "../../../../../../../styles/common/mixins/colors";
|
|
10
|
+
|
|
11
|
+
export const CircularProgress = styled(MCircularProgress)`
|
|
12
|
+
color: ${smokeLight};
|
|
13
|
+
left: 0;
|
|
14
|
+
position: absolute;
|
|
15
|
+
top: 0;
|
|
16
|
+
z-index: 0;
|
|
17
|
+
|
|
18
|
+
&.MuiCircularProgress-colorAlert {
|
|
19
|
+
color: ${alertLight};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
&.MuiCircularProgress-colorInfo {
|
|
23
|
+
color: ${infoLight};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
&.MuiCircularProgress-colorSuccess {
|
|
27
|
+
color: ${successLight};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
&.MuiCircularProgress-colorWarning {
|
|
31
|
+
color: ${warningLight};
|
|
32
|
+
}
|
|
33
|
+
`;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { CircularProgressProps as MCircularProgressProps } from "@mui/material";
|
|
2
|
+
import React, { Fragment } from "react";
|
|
3
|
+
import { CircularProgress } from "./circularProgressTrack.styles";
|
|
4
|
+
|
|
5
|
+
export interface CircularProgressTrackProps extends MCircularProgressProps {
|
|
6
|
+
className?: string;
|
|
7
|
+
track?: boolean;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const CircularProgressTrack = ({
|
|
11
|
+
className,
|
|
12
|
+
track = true,
|
|
13
|
+
value = 100,
|
|
14
|
+
...props /* Spread props to allow for CircularProgress specific props e.g. "disableShrink". */
|
|
15
|
+
}: CircularProgressTrackProps): JSX.Element => {
|
|
16
|
+
return (
|
|
17
|
+
<Fragment>
|
|
18
|
+
{track && (
|
|
19
|
+
<CircularProgress className={className} value={value} {...props} />
|
|
20
|
+
)}
|
|
21
|
+
</Fragment>
|
|
22
|
+
);
|
|
23
|
+
};
|
package/src/config/entities.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { ColumnSort } from "@tanstack/react-table";
|
|
|
3
3
|
import { JSXElementConstructor, ReactNode } from "react";
|
|
4
4
|
import {
|
|
5
5
|
CategoryKey,
|
|
6
|
+
SelectCategoryValueView,
|
|
6
7
|
SelectedFilter,
|
|
7
8
|
SelectedFilterValue,
|
|
8
9
|
} from "../common/entities";
|
|
@@ -77,6 +78,9 @@ export interface CategoryGroup {
|
|
|
77
78
|
export interface CategoryConfig {
|
|
78
79
|
key: string;
|
|
79
80
|
label: string;
|
|
81
|
+
mapSelectCategoryValue?: (
|
|
82
|
+
selectCategoryValue: SelectCategoryValueView
|
|
83
|
+
) => SelectCategoryValueView;
|
|
80
84
|
}
|
|
81
85
|
|
|
82
86
|
/**
|