@databiosphere/findable-ui 3.1.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/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/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
|
@@ -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
|
+
};
|
|
@@ -1,6 +1,14 @@
|
|
|
1
|
+
import { CategoryGroup } from "../../../config/entities";
|
|
1
2
|
import { ExploreState, PaginationState } from "../../exploreState";
|
|
3
|
+
import { SELECT_CATEGORY_KEY } from "../constants";
|
|
2
4
|
import { EntityState } from "../entities";
|
|
3
5
|
|
|
6
|
+
export const DEFAULT_CATEGORY_GROUP_SAVED_FILTERS: CategoryGroup = {
|
|
7
|
+
categoryConfigs: [
|
|
8
|
+
{ key: SELECT_CATEGORY_KEY.SAVED_FILTERS, label: "Saved Filters" },
|
|
9
|
+
],
|
|
10
|
+
};
|
|
11
|
+
|
|
4
12
|
export const DEFAULT_ENTITY_STATE: EntityState = {
|
|
5
13
|
categoryViews: [],
|
|
6
14
|
filterState: [],
|
|
@@ -20,7 +20,11 @@ import {
|
|
|
20
20
|
SavedFilterByCategoryValueKey,
|
|
21
21
|
} from "../entities";
|
|
22
22
|
import { getEntityCategoryGroupConfigKey, getFilterCount } from "../utils";
|
|
23
|
-
import {
|
|
23
|
+
import {
|
|
24
|
+
DEFAULT_CATEGORY_GROUP_SAVED_FILTERS,
|
|
25
|
+
DEFAULT_ENTITY_STATE,
|
|
26
|
+
INITIAL_STATE,
|
|
27
|
+
} from "./constants";
|
|
24
28
|
|
|
25
29
|
/**
|
|
26
30
|
* Builds category groups from the given category group config (adds the saved filters category to the category groups).
|
|
@@ -32,14 +36,7 @@ function buildCategoryGroups(
|
|
|
32
36
|
): CategoryGroup[] {
|
|
33
37
|
const { categoryGroups, savedFilters } = categoryGroupConfig;
|
|
34
38
|
if (!savedFilters) return categoryGroups;
|
|
35
|
-
|
|
36
|
-
const savedFiltersCategoryGroup: CategoryGroup = {
|
|
37
|
-
categoryConfigs: [
|
|
38
|
-
{ key: SELECT_CATEGORY_KEY.SAVED_FILTERS, label: "Saved Filters" },
|
|
39
|
-
],
|
|
40
|
-
};
|
|
41
|
-
clonedCategoryGroups.unshift(savedFiltersCategoryGroup);
|
|
42
|
-
return clonedCategoryGroups;
|
|
39
|
+
return [DEFAULT_CATEGORY_GROUP_SAVED_FILTERS, ...categoryGroups];
|
|
43
40
|
}
|
|
44
41
|
|
|
45
42
|
/**
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
CategoryValueKey,
|
|
9
9
|
PaginationDirectionType,
|
|
10
10
|
SelectCategory,
|
|
11
|
+
SelectedFilter,
|
|
11
12
|
} from "../../../common/entities";
|
|
12
13
|
import {
|
|
13
14
|
ENTITY_VIEW,
|
|
@@ -71,6 +72,13 @@ export type ToggleEntityViewPayload = ENTITY_VIEW;
|
|
|
71
72
|
*/
|
|
72
73
|
export type UpdateColumnVisibilityPayload = VisibilityState;
|
|
73
74
|
|
|
75
|
+
/**
|
|
76
|
+
* Update entity filters payload.
|
|
77
|
+
*/
|
|
78
|
+
export interface UpdateEntityFiltersPayload {
|
|
79
|
+
entityListType: string;
|
|
80
|
+
filters: SelectedFilter[];
|
|
81
|
+
}
|
|
74
82
|
/**
|
|
75
83
|
* Update entity view access payload.
|
|
76
84
|
*/
|