@databiosphere/findable-ui 43.0.0 → 44.0.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/.release-please-manifest.json +1 -1
- package/CHANGELOG.md +14 -0
- package/lib/common/filters/sort/config/types.d.ts +13 -0
- package/lib/common/filters/sort/config/types.js +8 -0
- package/lib/common/filters/sort/config/utils.d.ts +8 -0
- package/lib/common/filters/sort/config/utils.js +9 -0
- package/lib/common/filters/sort/models/utils.d.ts +23 -0
- package/lib/common/filters/sort/models/utils.js +41 -0
- package/lib/components/Filter/components/adapters/tanstack/ColumnFiltersAdapter/columnFiltersAdapter.js +6 -1
- package/lib/components/Filter/components/adapters/tanstack/ColumnFiltersAdapter/hooks/UseUpdateFilterSort/hook.d.ts +3 -0
- package/lib/components/Filter/components/adapters/tanstack/ColumnFiltersAdapter/hooks/UseUpdateFilterSort/hook.js +8 -0
- package/lib/components/Filter/components/adapters/tanstack/ColumnFiltersAdapter/hooks/UseUpdateFilterSort/types.d.ts +6 -0
- package/lib/components/Filter/components/adapters/tanstack/ColumnFiltersAdapter/hooks/UseUpdateFilterSort/types.js +1 -0
- package/lib/components/Filter/components/adapters/tanstack/ColumnFiltersAdapter/hooks/UseUpdateFilterSort/utils.d.ts +14 -0
- package/lib/components/Filter/components/adapters/tanstack/ColumnFiltersAdapter/hooks/UseUpdateFilterSort/utils.js +23 -0
- package/lib/components/Filter/components/adapters/tanstack/ColumnFiltersAdapter/types.d.ts +2 -0
- package/lib/components/Filter/components/adapters/tanstack/ColumnFiltersAdapter/utils.d.ts +3 -1
- package/lib/components/Filter/components/adapters/tanstack/ColumnFiltersAdapter/utils.js +24 -16
- package/lib/components/Filter/components/controls/Controls/components/FilterSort/constants.d.ts +5 -0
- package/lib/components/Filter/components/controls/Controls/components/FilterSort/constants.js +17 -0
- package/lib/components/Filter/components/controls/Controls/components/FilterSort/filterSort.d.ts +2 -0
- package/lib/components/Filter/components/controls/Controls/components/FilterSort/filterSort.js +28 -0
- package/lib/components/Filter/components/controls/Controls/components/FilterSort/filterSort.styles.d.ts +9 -0
- package/lib/components/Filter/components/controls/Controls/components/FilterSort/filterSort.styles.js +25 -0
- package/lib/components/Filter/components/controls/Controls/components/FilterSort/stories/filterSort.stories.d.ts +6 -0
- package/lib/components/Filter/components/controls/Controls/components/FilterSort/stories/filterSort.stories.js +9 -0
- package/lib/components/Filter/components/controls/Controls/components/FilterSort/types.d.ts +6 -0
- package/lib/components/Filter/components/controls/Controls/components/FilterSort/types.js +1 -0
- package/lib/components/Filter/components/controls/Controls/controls.d.ts +2 -3
- package/lib/components/Filter/components/controls/Controls/controls.js +4 -2
- package/lib/components/Filter/components/controls/Controls/controls.styles.js +2 -1
- package/lib/components/Filter/components/controls/Controls/types.d.ts +6 -0
- package/lib/components/Filter/components/controls/Controls/types.js +1 -0
- package/lib/components/Filter/components/surfaces/types.d.ts +3 -1
- package/lib/components/Index/components/EntityView/components/views/ChartView/components/Chart/hooks/UsePlotOptions/hook.js +2 -2
- package/lib/components/Index/components/EntityView/components/views/ChartView/components/Chart/utils.d.ts +0 -7
- package/lib/components/Index/components/EntityView/components/views/ChartView/components/Chart/utils.js +0 -11
- package/lib/config/entities.d.ts +2 -0
- package/lib/hooks/useCategoryFilter.d.ts +4 -9
- package/lib/hooks/useCategoryFilter.js +5 -15
- package/lib/providers/exploreState/actions/updateFilterSort/action.d.ts +10 -0
- package/lib/providers/exploreState/actions/updateFilterSort/action.js +21 -0
- package/lib/providers/exploreState/actions/updateFilterSort/dispatch.d.ts +7 -0
- package/lib/providers/exploreState/actions/updateFilterSort/dispatch.js +12 -0
- package/lib/providers/exploreState/actions/updateFilterSort/types.d.ts +7 -0
- package/lib/providers/exploreState/actions/updateFilterSort/types.js +1 -0
- package/lib/providers/exploreState/actions/updateFilterSort/utils.d.ts +10 -0
- package/lib/providers/exploreState/actions/updateFilterSort/utils.js +22 -0
- package/lib/providers/exploreState/initializer/constants.js +2 -0
- package/lib/providers/exploreState/initializer/utils.js +2 -0
- package/lib/providers/exploreState.d.ts +5 -1
- package/lib/providers/exploreState.js +9 -1
- package/lib/tests/testIds.d.ts +2 -0
- package/lib/tests/testIds.js +2 -0
- package/lib/views/ExploreView/exploreView.js +7 -1
- package/lib/views/ExploreView/hooks/UseUpdateFilterSort/hook.d.ts +2 -0
- package/lib/views/ExploreView/hooks/UseUpdateFilterSort/hook.js +12 -0
- package/lib/views/ExploreView/hooks/UseUpdateFilterSort/types.d.ts +6 -0
- package/lib/views/ExploreView/hooks/UseUpdateFilterSort/types.js +1 -0
- package/package.json +1 -1
- package/src/common/filters/sort/config/types.ts +14 -0
- package/src/common/filters/sort/config/utils.ts +11 -0
- package/src/common/filters/sort/models/utils.ts +57 -0
- package/src/components/Filter/components/adapters/tanstack/ColumnFiltersAdapter/columnFiltersAdapter.tsx +11 -1
- package/src/components/Filter/components/adapters/tanstack/ColumnFiltersAdapter/hooks/UseUpdateFilterSort/hook.ts +22 -0
- package/src/components/Filter/components/adapters/tanstack/ColumnFiltersAdapter/hooks/UseUpdateFilterSort/types.ts +7 -0
- package/src/components/Filter/components/adapters/tanstack/ColumnFiltersAdapter/hooks/UseUpdateFilterSort/utils.ts +33 -0
- package/src/components/Filter/components/adapters/tanstack/ColumnFiltersAdapter/types.ts +2 -0
- package/src/components/Filter/components/adapters/tanstack/ColumnFiltersAdapter/utils.ts +36 -13
- package/src/components/Filter/components/controls/Controls/components/FilterSort/constants.ts +22 -0
- package/src/components/Filter/components/controls/Controls/components/FilterSort/filterSort.styles.ts +34 -0
- package/src/components/Filter/components/controls/Controls/components/FilterSort/filterSort.tsx +73 -0
- package/src/components/Filter/components/controls/Controls/components/FilterSort/stories/filterSort.stories.tsx +15 -0
- package/src/components/Filter/components/controls/Controls/components/FilterSort/types.ts +7 -0
- package/src/components/Filter/components/controls/Controls/controls.styles.ts +2 -1
- package/src/components/Filter/components/controls/Controls/controls.tsx +11 -3
- package/src/components/Filter/components/controls/Controls/types.ts +10 -0
- package/src/components/Filter/components/surfaces/types.ts +3 -1
- package/src/components/Index/components/EntityView/components/views/ChartView/components/Chart/hooks/UsePlotOptions/hook.ts +2 -2
- package/src/components/Index/components/EntityView/components/views/ChartView/components/Chart/utils.ts +0 -15
- package/src/config/entities.ts +2 -0
- package/src/hooks/useCategoryFilter.ts +8 -19
- package/src/providers/exploreState/actions/updateFilterSort/action.ts +30 -0
- package/src/providers/exploreState/actions/updateFilterSort/dispatch.ts +16 -0
- package/src/providers/exploreState/actions/updateFilterSort/types.ts +9 -0
- package/src/providers/exploreState/actions/updateFilterSort/utils.ts +30 -0
- package/src/providers/exploreState/initializer/constants.ts +2 -0
- package/src/providers/exploreState/initializer/utils.ts +2 -0
- package/src/providers/exploreState.tsx +14 -1
- package/src/tests/testIds.ts +2 -0
- package/src/views/ExploreView/exploreView.tsx +16 -1
- package/src/views/ExploreView/hooks/UseUpdateFilterSort/hook.ts +20 -0
- package/src/views/ExploreView/hooks/UseUpdateFilterSort/types.ts +7 -0
- package/tests/buildCategoryViews.test.ts +282 -0
- package/tests/filterSortUtils.test.ts +180 -0
- package/tests/getFilterSortType.test.ts +45 -0
|
@@ -7,9 +7,10 @@ import {
|
|
|
7
7
|
SelectCategoryValueView,
|
|
8
8
|
SelectCategoryView,
|
|
9
9
|
} from "../../../../../../common/entities";
|
|
10
|
+
import { FILTER_SORT } from "../../../../../../common/filters/sort/config/types";
|
|
11
|
+
import { sortCategoryValueViews } from "../../../../../../common/filters/sort/models/utils";
|
|
10
12
|
import { CategoryGroup } from "../../../../../../config/entities";
|
|
11
13
|
import { getColumnHeader } from "../../../../../Table/common/utils";
|
|
12
|
-
import { getSortedFacetedValues } from "../../../../../Table/featureOptions/facetedColumn/utils";
|
|
13
14
|
import { CategoryFilter } from "../../../Filters/filters";
|
|
14
15
|
import { SurfaceProps } from "../../../surfaces/types";
|
|
15
16
|
import { ColumnFiltersTableMeta } from "./types";
|
|
@@ -31,16 +32,22 @@ function buildCategoryConfigs<T extends RowData>(
|
|
|
31
32
|
/**
|
|
32
33
|
* Adapter for TanStack table to category filters.
|
|
33
34
|
* @param table - Table.
|
|
35
|
+
* @param filterSort - Filter sort.
|
|
34
36
|
* @param categoryGroups - Category groups.
|
|
35
37
|
* @returns Category filters.
|
|
36
38
|
*/
|
|
37
39
|
function buildCategoryFilters<T extends RowData>(
|
|
38
40
|
table: Table<T>,
|
|
41
|
+
filterSort: FILTER_SORT,
|
|
39
42
|
categoryGroups: CategoryGroup[]
|
|
40
43
|
): SurfaceProps["categoryFilters"] {
|
|
41
44
|
return categoryGroups.reduce<SurfaceProps["categoryFilters"]>(
|
|
42
45
|
(acc, categoryGroup) => {
|
|
43
|
-
const categoryFilter = mapCategoryFilter(
|
|
46
|
+
const categoryFilter = mapCategoryFilter(
|
|
47
|
+
table,
|
|
48
|
+
filterSort,
|
|
49
|
+
categoryGroup
|
|
50
|
+
);
|
|
44
51
|
if (categoryFilter) acc.push(categoryFilter);
|
|
45
52
|
return acc;
|
|
46
53
|
},
|
|
@@ -51,10 +58,12 @@ function buildCategoryFilters<T extends RowData>(
|
|
|
51
58
|
/**
|
|
52
59
|
* Adapter for TanStack table column filters to category filters.
|
|
53
60
|
* @param table - Table.
|
|
61
|
+
* @param filterSort - Filter sort.
|
|
54
62
|
* @returns Category filters.
|
|
55
63
|
*/
|
|
56
64
|
export function buildColumnFilters<T extends RowData>(
|
|
57
|
-
table: Table<T
|
|
65
|
+
table: Table<T>,
|
|
66
|
+
filterSort = FILTER_SORT.ALPHA
|
|
58
67
|
): SurfaceProps["categoryFilters"] {
|
|
59
68
|
const { options } = table;
|
|
60
69
|
const { meta = {} } = options;
|
|
@@ -64,11 +73,13 @@ export function buildColumnFilters<T extends RowData>(
|
|
|
64
73
|
// Build single category group with all (filterable) columns.
|
|
65
74
|
const categoryConfigs: CategoryConfig[] = buildCategoryConfigs(table);
|
|
66
75
|
// Build category filters from single category group.
|
|
67
|
-
return buildCategoryFilters(table,
|
|
76
|
+
return buildCategoryFilters(table, filterSort, [
|
|
77
|
+
{ categoryConfigs, label: "" },
|
|
78
|
+
]);
|
|
68
79
|
}
|
|
69
80
|
|
|
70
81
|
// Build category filters from category groups.
|
|
71
|
-
return buildCategoryFilters(table, categoryGroups);
|
|
82
|
+
return buildCategoryFilters(table, filterSort, categoryGroups);
|
|
72
83
|
}
|
|
73
84
|
|
|
74
85
|
/**
|
|
@@ -104,11 +115,13 @@ function mapCategoryConfig<T extends RowData>(
|
|
|
104
115
|
/**
|
|
105
116
|
* Adapter for TanStack table to category filter.
|
|
106
117
|
* @param table - Table.
|
|
118
|
+
* @param filterSort - Filter sort.
|
|
107
119
|
* @param categoryGroup - Category group.
|
|
108
120
|
* @returns Category filter.
|
|
109
121
|
*/
|
|
110
122
|
function mapCategoryFilter<T extends RowData>(
|
|
111
123
|
table: Table<T>,
|
|
124
|
+
filterSort: FILTER_SORT,
|
|
112
125
|
categoryGroup: CategoryGroup
|
|
113
126
|
): CategoryFilter | undefined {
|
|
114
127
|
const { categoryConfigs, label } = categoryGroup;
|
|
@@ -126,7 +139,11 @@ function mapCategoryFilter<T extends RowData>(
|
|
|
126
139
|
categoryView = mapColumnToRangeCategoryView(column, categoryConfig);
|
|
127
140
|
} else {
|
|
128
141
|
// Build select category view.
|
|
129
|
-
categoryView = mapColumnToSelectCategoryView(
|
|
142
|
+
categoryView = mapColumnToSelectCategoryView(
|
|
143
|
+
column,
|
|
144
|
+
filterSort,
|
|
145
|
+
categoryConfig
|
|
146
|
+
);
|
|
130
147
|
}
|
|
131
148
|
|
|
132
149
|
return [...acc, categoryView];
|
|
@@ -174,16 +191,18 @@ function mapColumnToRangeCategoryView<T extends RowData>(
|
|
|
174
191
|
/**
|
|
175
192
|
* Adapter for TanStack column to select category view.
|
|
176
193
|
* @param column - Column.
|
|
194
|
+
* @param filterSort - Filter sort.
|
|
177
195
|
* @param categoryConfig - Category config.
|
|
178
196
|
* @returns Select category view.
|
|
179
197
|
*/
|
|
180
198
|
function mapColumnToSelectCategoryView<T extends RowData>(
|
|
181
199
|
column: Column<T>,
|
|
200
|
+
filterSort: FILTER_SORT,
|
|
182
201
|
categoryConfig?: CategoryConfig
|
|
183
202
|
): SelectCategoryView {
|
|
184
203
|
const facetedUniqueValues = column.getFacetedUniqueValues();
|
|
185
204
|
const isDisabled = facetedUniqueValues.size === 0;
|
|
186
|
-
const values = mapColumnToSelectCategoryValueView(column);
|
|
205
|
+
const values = mapColumnToSelectCategoryValueView(column, filterSort);
|
|
187
206
|
return {
|
|
188
207
|
annotation: undefined,
|
|
189
208
|
enableChartView: false,
|
|
@@ -198,22 +217,24 @@ function mapColumnToSelectCategoryView<T extends RowData>(
|
|
|
198
217
|
/**
|
|
199
218
|
* Adapter for TanStack column to select category value view.
|
|
200
219
|
* @param column - Column.
|
|
220
|
+
* @param filterSort - Filter sort.
|
|
201
221
|
* @returns Select category value view.
|
|
202
222
|
*/
|
|
203
223
|
function mapColumnToSelectCategoryValueView<T extends RowData>(
|
|
204
|
-
column: Column<T
|
|
224
|
+
column: Column<T>,
|
|
225
|
+
filterSort: FILTER_SORT
|
|
205
226
|
): SelectCategoryValueView[] {
|
|
206
227
|
// Get the faceted unique values and sort them.
|
|
207
228
|
const facetedUniqueValues = column.getFacetedUniqueValues();
|
|
208
|
-
const sortedFacetsValues = getSortedFacetedValues(facetedUniqueValues);
|
|
209
229
|
|
|
210
230
|
// Selected values for the column.
|
|
211
231
|
const filterValue = (column.getFilterValue() || []) as unknown[];
|
|
212
232
|
|
|
213
233
|
// Build the select category values.
|
|
214
|
-
const
|
|
215
|
-
|
|
216
|
-
|
|
234
|
+
const categoryValueViews: SelectCategoryValueView[] = [];
|
|
235
|
+
|
|
236
|
+
for (const [label, count] of [...facetedUniqueValues]) {
|
|
237
|
+
categoryValueViews.push({
|
|
217
238
|
count,
|
|
218
239
|
key: String(label),
|
|
219
240
|
label: String(label),
|
|
@@ -221,5 +242,7 @@ function mapColumnToSelectCategoryValueView<T extends RowData>(
|
|
|
221
242
|
});
|
|
222
243
|
}
|
|
223
244
|
|
|
224
|
-
|
|
245
|
+
sortCategoryValueViews(categoryValueViews, filterSort);
|
|
246
|
+
|
|
247
|
+
return categoryValueViews;
|
|
225
248
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { ListItemTextProps, MenuProps, SvgIconProps } from "@mui/material";
|
|
2
|
+
import { SVG_ICON_PROPS as MUI_SVG_ICON_PROPS } from "../../../../../../../styles/common/mui/svgIcon";
|
|
3
|
+
import { TYPOGRAPHY_PROPS } from "../../../../../../../styles/common/mui/typography";
|
|
4
|
+
|
|
5
|
+
export const LIST_ITEM_BUTTON_TEXT_PROPS: ListItemTextProps = {
|
|
6
|
+
slotProps: { primary: { variant: TYPOGRAPHY_PROPS.VARIANT.BODY_400 } },
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export const LIST_ITEM_TEXT_PROPS: ListItemTextProps = {
|
|
10
|
+
slotProps: { primary: { variant: TYPOGRAPHY_PROPS.VARIANT.BODY_500 } },
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export const MENU_PROPS: Omit<MenuProps, "anchorEl" | "onClose" | "open"> = {
|
|
14
|
+
anchorOrigin: { horizontal: "left", vertical: "bottom" },
|
|
15
|
+
marginThreshold: 8,
|
|
16
|
+
slotProps: { paper: { variant: "menu" } },
|
|
17
|
+
transformOrigin: { horizontal: "left", vertical: "top" },
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const SVG_ICON_PROPS: SvgIconProps = {
|
|
21
|
+
fontSize: MUI_SVG_ICON_PROPS.FONT_SIZE.SMALL,
|
|
22
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { css } from "@emotion/react";
|
|
2
|
+
import styled from "@emotion/styled";
|
|
3
|
+
import {
|
|
4
|
+
IconButton,
|
|
5
|
+
Menu,
|
|
6
|
+
MenuProps,
|
|
7
|
+
menuClasses,
|
|
8
|
+
paperClasses,
|
|
9
|
+
} from "@mui/material";
|
|
10
|
+
import { PALETTE } from "../../../../../../../styles/common/constants/palette";
|
|
11
|
+
import { MuiListItemButtonRoot } from "../../../../FilterList/filterList.styles";
|
|
12
|
+
|
|
13
|
+
export const StyledIconButton = styled(IconButton)<Pick<MenuProps, "open">>`
|
|
14
|
+
align-self: center;
|
|
15
|
+
padding: 0;
|
|
16
|
+
|
|
17
|
+
${({ open }) =>
|
|
18
|
+
open &&
|
|
19
|
+
css`
|
|
20
|
+
color: ${PALETTE.INK_MAIN};
|
|
21
|
+
`}
|
|
22
|
+
`;
|
|
23
|
+
|
|
24
|
+
export const StyledMenu = styled(Menu)`
|
|
25
|
+
.${paperClasses.root} {
|
|
26
|
+
margin: 4px 0;
|
|
27
|
+
max-width: 300px;
|
|
28
|
+
width: 100%;
|
|
29
|
+
|
|
30
|
+
.${menuClasses.list} {
|
|
31
|
+
${MuiListItemButtonRoot}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
`;
|
package/src/components/Filter/components/controls/Controls/components/FilterSort/filterSort.tsx
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { SettingsOutlined } from "@mui/icons-material";
|
|
2
|
+
import { ListItem, ListItemButton, ListItemText, Radio } from "@mui/material";
|
|
3
|
+
import React, { Fragment } from "react";
|
|
4
|
+
import { FILTER_SORT } from "../../../../../../../common/filters/sort/config/types";
|
|
5
|
+
import { ICON_BUTTON_PROPS } from "../../../../../../../styles/common/mui/iconButton";
|
|
6
|
+
import { TEST_IDS } from "../../../../../../../tests/testIds";
|
|
7
|
+
import { RadioCheckedIcon } from "../../../../../../common/CustomIcon/components/RadioCheckedIcon/radioCheckedIcon";
|
|
8
|
+
import { RadioUncheckedIcon } from "../../../../../../common/CustomIcon/components/RadioUncheckedIcon/radioUncheckedIcon";
|
|
9
|
+
import { useMenu } from "../../../../../../common/Menu/hooks/useMenu";
|
|
10
|
+
import {
|
|
11
|
+
LIST_ITEM_BUTTON_TEXT_PROPS,
|
|
12
|
+
LIST_ITEM_TEXT_PROPS,
|
|
13
|
+
MENU_PROPS,
|
|
14
|
+
SVG_ICON_PROPS,
|
|
15
|
+
} from "./constants";
|
|
16
|
+
import { StyledIconButton, StyledMenu } from "./filterSort.styles";
|
|
17
|
+
import { FilterSortProps } from "./types";
|
|
18
|
+
|
|
19
|
+
export const FilterSort = ({
|
|
20
|
+
enabled = false,
|
|
21
|
+
filterSort = FILTER_SORT.ALPHA,
|
|
22
|
+
onFilterSortChange,
|
|
23
|
+
}: FilterSortProps): JSX.Element | null => {
|
|
24
|
+
const { anchorEl, onClose, onOpen, open } = useMenu();
|
|
25
|
+
|
|
26
|
+
if (!enabled || !onFilterSortChange) return null;
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<Fragment>
|
|
30
|
+
<StyledIconButton
|
|
31
|
+
color={ICON_BUTTON_PROPS.COLOR.INK_LIGHT}
|
|
32
|
+
data-testid={TEST_IDS.FILTER_SORT_BUTTON}
|
|
33
|
+
onClick={onOpen}
|
|
34
|
+
open={open}
|
|
35
|
+
>
|
|
36
|
+
<SettingsOutlined {...SVG_ICON_PROPS} />
|
|
37
|
+
</StyledIconButton>
|
|
38
|
+
<StyledMenu
|
|
39
|
+
{...MENU_PROPS}
|
|
40
|
+
anchorEl={anchorEl}
|
|
41
|
+
data-testid={TEST_IDS.FILTER_SORT_MENU}
|
|
42
|
+
onClose={onClose}
|
|
43
|
+
open={open}
|
|
44
|
+
>
|
|
45
|
+
<ListItem>
|
|
46
|
+
<ListItemText {...LIST_ITEM_TEXT_PROPS}>
|
|
47
|
+
Sort Filter Values By
|
|
48
|
+
</ListItemText>
|
|
49
|
+
</ListItem>
|
|
50
|
+
<ListItemButton onClick={() => onFilterSortChange(FILTER_SORT.ALPHA)}>
|
|
51
|
+
<Radio
|
|
52
|
+
checked={filterSort === FILTER_SORT.ALPHA}
|
|
53
|
+
checkedIcon={<RadioCheckedIcon {...SVG_ICON_PROPS} />}
|
|
54
|
+
icon={<RadioUncheckedIcon {...SVG_ICON_PROPS} />}
|
|
55
|
+
/>
|
|
56
|
+
<ListItemText {...LIST_ITEM_BUTTON_TEXT_PROPS}>
|
|
57
|
+
Alphabetical
|
|
58
|
+
</ListItemText>
|
|
59
|
+
</ListItemButton>
|
|
60
|
+
<ListItemButton onClick={() => onFilterSortChange(FILTER_SORT.COUNT)}>
|
|
61
|
+
<Radio
|
|
62
|
+
checked={filterSort === FILTER_SORT.COUNT}
|
|
63
|
+
checkedIcon={<RadioCheckedIcon {...SVG_ICON_PROPS} />}
|
|
64
|
+
icon={<RadioUncheckedIcon {...SVG_ICON_PROPS} />}
|
|
65
|
+
/>
|
|
66
|
+
<ListItemText {...LIST_ITEM_BUTTON_TEXT_PROPS}>
|
|
67
|
+
By Count (Descending)
|
|
68
|
+
</ListItemText>
|
|
69
|
+
</ListItemButton>
|
|
70
|
+
</StyledMenu>
|
|
71
|
+
</Fragment>
|
|
72
|
+
);
|
|
73
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { FILTER_SORT } from "../../../../../../../../common/filters/sort/config/types";
|
|
3
|
+
import { FilterSort } from "../filterSort";
|
|
4
|
+
|
|
5
|
+
const meta: Meta<typeof FilterSort> = {
|
|
6
|
+
component: FilterSort,
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export default meta;
|
|
10
|
+
|
|
11
|
+
type Story = StoryObj<typeof meta>;
|
|
12
|
+
|
|
13
|
+
export const DEFAULT: Story = {
|
|
14
|
+
args: { enabled: true, filterSort: FILTER_SORT.ALPHA },
|
|
15
|
+
};
|
|
@@ -3,9 +3,9 @@ import React from "react";
|
|
|
3
3
|
import { CLEAR_ALL } from "../../../../../common/entities";
|
|
4
4
|
import { TYPOGRAPHY_PROPS } from "../../../../../styles/common/mui/typography";
|
|
5
5
|
import { BUTTON_PROPS } from "../../../../common/Button/constants";
|
|
6
|
-
import {
|
|
7
|
-
import { SurfaceProps } from "../../surfaces/types";
|
|
6
|
+
import { FilterSort } from "./components/FilterSort/filterSort";
|
|
8
7
|
import { StyledGrid } from "./controls.styles";
|
|
8
|
+
import { ControlsProps } from "./types";
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Renders filter title and "Clear All" button.
|
|
@@ -13,8 +13,11 @@ import { StyledGrid } from "./controls.styles";
|
|
|
13
13
|
|
|
14
14
|
export const Controls = ({
|
|
15
15
|
className,
|
|
16
|
+
filterSort,
|
|
17
|
+
filterSortEnabled = false,
|
|
16
18
|
onFilter,
|
|
17
|
-
|
|
19
|
+
onFilterSortChange,
|
|
20
|
+
}: ControlsProps): JSX.Element | null => {
|
|
18
21
|
return (
|
|
19
22
|
<StyledGrid className={className} container>
|
|
20
23
|
<Typography variant={TYPOGRAPHY_PROPS.VARIANT.BODY_LARGE_500}>
|
|
@@ -26,6 +29,11 @@ export const Controls = ({
|
|
|
26
29
|
>
|
|
27
30
|
Clear All
|
|
28
31
|
</MButton>
|
|
32
|
+
<FilterSort
|
|
33
|
+
enabled={filterSortEnabled}
|
|
34
|
+
filterSort={filterSort}
|
|
35
|
+
onFilterSortChange={onFilterSortChange}
|
|
36
|
+
/>
|
|
29
37
|
</StyledGrid>
|
|
30
38
|
);
|
|
31
39
|
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { BaseComponentProps } from "../../../../types";
|
|
2
|
+
import { SurfaceProps } from "../../surfaces/types";
|
|
3
|
+
import { FilterSortProps } from "./components/FilterSort/types";
|
|
4
|
+
|
|
5
|
+
export interface ControlsProps
|
|
6
|
+
extends BaseComponentProps,
|
|
7
|
+
Pick<SurfaceProps, "onFilter">,
|
|
8
|
+
Omit<FilterSortProps, "enabled"> {
|
|
9
|
+
filterSortEnabled?: boolean;
|
|
10
|
+
}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { OnFilterFn } from "../../../../hooks/useCategoryFilter";
|
|
2
2
|
import { CategoryFilter } from "../Filters/filters";
|
|
3
|
+
import { FilterSortProps } from "../controls/Controls/components/FilterSort/types";
|
|
3
4
|
|
|
4
|
-
export interface SurfaceProps {
|
|
5
|
+
export interface SurfaceProps extends Omit<FilterSortProps, "enabled"> {
|
|
5
6
|
categoryFilters: CategoryFilter[];
|
|
6
7
|
count?: number;
|
|
8
|
+
filterSortEnabled: boolean;
|
|
7
9
|
onFilter: OnFilterFn;
|
|
8
10
|
}
|
|
9
11
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { useMemo } from "react";
|
|
2
2
|
import { SelectCategoryValueView } from "../../../../../../../../../../../common/entities";
|
|
3
|
+
import { sortCategoryValueViewsCount } from "../../../../../../../../../../../common/filters/sort/models/utils";
|
|
3
4
|
import { getPlotOptions } from "../../barX/plot";
|
|
4
5
|
import { getCategoryTotalCount } from "../../barX/utils";
|
|
5
|
-
import { sortByCountThenLabel } from "../../utils";
|
|
6
6
|
import { UsePlotOptions } from "./types";
|
|
7
7
|
|
|
8
8
|
export const usePlotOptions = (
|
|
@@ -13,7 +13,7 @@ export const usePlotOptions = (
|
|
|
13
13
|
// Organise the select category value views (sort and slice) for chart display.
|
|
14
14
|
const data = selectCategoryValueViews
|
|
15
15
|
// Sort the category values by count and label.
|
|
16
|
-
.sort(
|
|
16
|
+
.sort(sortCategoryValueViewsCount)
|
|
17
17
|
// Slice the category values to the number of bars to display.
|
|
18
18
|
.slice(0, barCount);
|
|
19
19
|
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { SelectCategoryValueView } from "../../../../../../../../../common/entities";
|
|
2
|
-
import { sortCategoryValueViews } from "../../../../../../../../../hooks/useCategoryFilter";
|
|
3
2
|
|
|
4
3
|
/**
|
|
5
4
|
* Renders the button text for the chart.
|
|
@@ -19,17 +18,3 @@ export function renderButtonText(
|
|
|
19
18
|
|
|
20
19
|
return `Show ${count} additional results`;
|
|
21
20
|
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Sorts category value views by count in descending order, then label in ascending order.
|
|
25
|
-
* @param a - First category value view.
|
|
26
|
-
* @param b - Second category value view.
|
|
27
|
-
* @returns Sorted category value views.
|
|
28
|
-
*/
|
|
29
|
-
export function sortByCountThenLabel(
|
|
30
|
-
a: SelectCategoryValueView,
|
|
31
|
-
b: SelectCategoryValueView
|
|
32
|
-
): number {
|
|
33
|
-
const compare = b.count - a.count;
|
|
34
|
-
return compare === 0 ? sortCategoryValueViews(a, b) : compare;
|
|
35
|
-
}
|
package/src/config/entities.ts
CHANGED
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
DataDictionaryConfig,
|
|
18
18
|
SelectedFilter,
|
|
19
19
|
} from "../common/entities";
|
|
20
|
+
import { FilterSortConfig } from "../common/filters/sort/config/types";
|
|
20
21
|
import { FooterProps } from "../components/Layout/components/Footer/footer";
|
|
21
22
|
import { HeaderProps } from "../components/Layout/components/Header/header";
|
|
22
23
|
import { ExploreMode } from "../hooks/useExploreMode/types";
|
|
@@ -378,6 +379,7 @@ export interface SiteConfig {
|
|
|
378
379
|
export?: ExportConfig;
|
|
379
380
|
exportsRequireAuth?: boolean;
|
|
380
381
|
exportToTerraUrl?: string; // TODO(cc) revist location; possibly nest inside "export"?
|
|
382
|
+
filterSort?: FilterSortConfig;
|
|
381
383
|
gitHubUrl?: string;
|
|
382
384
|
layout: {
|
|
383
385
|
floating?: FloatingConfig;
|
|
@@ -18,6 +18,8 @@ import {
|
|
|
18
18
|
SelectCategoryView,
|
|
19
19
|
SelectedFilter,
|
|
20
20
|
} from "../common/entities";
|
|
21
|
+
import { FILTER_SORT } from "../common/filters/sort/config/types";
|
|
22
|
+
import { sortCategoryValueViews } from "../common/filters/sort/models/utils";
|
|
21
23
|
|
|
22
24
|
/**
|
|
23
25
|
* State backing filter functionality and calculations. Converted to view model for display.
|
|
@@ -94,12 +96,14 @@ function buildCategoryView(
|
|
|
94
96
|
* @param categories - Categories, category value and their counts with the current filter applied.
|
|
95
97
|
* @param categoryConfigs - Category configs indicating accept list as well as label configuration.
|
|
96
98
|
* @param filterState - Current set of selected category and category values.
|
|
99
|
+
* @param filterSort - Sort configuration (ALPHA or COUNT).
|
|
97
100
|
* @returns Array of category view objects.
|
|
98
101
|
*/
|
|
99
102
|
export function buildCategoryViews(
|
|
100
103
|
categories: Category[],
|
|
101
104
|
categoryConfigs: CategoryConfig[] | undefined,
|
|
102
|
-
filterState: FilterState
|
|
105
|
+
filterState: FilterState,
|
|
106
|
+
filterSort: FILTER_SORT
|
|
103
107
|
): CategoryView[] {
|
|
104
108
|
if (!categories || !categoryConfigs) {
|
|
105
109
|
return [];
|
|
@@ -131,7 +135,9 @@ export function buildCategoryViews(
|
|
|
131
135
|
const categoryValueViews = category.values.map((categoryValue) =>
|
|
132
136
|
buildCategoryValueView(categoryValue, categorySelectedFilter)
|
|
133
137
|
);
|
|
134
|
-
|
|
138
|
+
|
|
139
|
+
// Sort category value views based on filter sort configuration.
|
|
140
|
+
sortCategoryValueViews(categoryValueViews, filterSort);
|
|
135
141
|
|
|
136
142
|
// Build category view model.
|
|
137
143
|
return buildCategoryView(category, categoryValueViews, categoryConfigs);
|
|
@@ -272,23 +278,6 @@ function isCategoryAcceptListed(
|
|
|
272
278
|
);
|
|
273
279
|
}
|
|
274
280
|
|
|
275
|
-
/**
|
|
276
|
-
* Sort category value views by key, ascending.
|
|
277
|
-
* @param cvv0 - First category value view to compare.
|
|
278
|
-
* @param cvv1 - Second category value view to compare.
|
|
279
|
-
* @returns Number indicating sort precedence of cv0 vs cv1.
|
|
280
|
-
*/
|
|
281
|
-
export function sortCategoryValueViews(
|
|
282
|
-
cvv0: SelectCategoryValueView,
|
|
283
|
-
cvv1: SelectCategoryValueView
|
|
284
|
-
): number {
|
|
285
|
-
return !cvv0.label
|
|
286
|
-
? 1
|
|
287
|
-
: !cvv1.label
|
|
288
|
-
? -1
|
|
289
|
-
: COLLATOR_CASE_INSENSITIVE.compare(cvv0.label, cvv1.label);
|
|
290
|
-
}
|
|
291
|
-
|
|
292
281
|
/**
|
|
293
282
|
* Sort category views by display label, ascending.
|
|
294
283
|
* @param c0 - First category view to compare.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { ExploreState } from "../../../exploreState";
|
|
2
|
+
import { updateEntityStateByCategoryGroupConfigKey } from "../../utils";
|
|
3
|
+
import { UpdateFilterSortPayload } from "./types";
|
|
4
|
+
import { sortCategoryViews } from "./utils";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Reducer function to handle the "update filter sort" action.
|
|
8
|
+
* Updates the filter sort in the state for the current entity.
|
|
9
|
+
* @param state - Explore State.
|
|
10
|
+
* @param payload - Payload.
|
|
11
|
+
* @returns explore state.
|
|
12
|
+
*/
|
|
13
|
+
export function updateFilterSortAction(
|
|
14
|
+
state: ExploreState,
|
|
15
|
+
payload: UpdateFilterSortPayload
|
|
16
|
+
): ExploreState {
|
|
17
|
+
const filterSort = payload;
|
|
18
|
+
|
|
19
|
+
// Sort the category views based on the new filter sort.
|
|
20
|
+
const categoryViews = sortCategoryViews(state, filterSort);
|
|
21
|
+
|
|
22
|
+
// Update entity state by category group config key
|
|
23
|
+
updateEntityStateByCategoryGroupConfigKey(state, { categoryViews });
|
|
24
|
+
|
|
25
|
+
return {
|
|
26
|
+
...state,
|
|
27
|
+
categoryViews,
|
|
28
|
+
filterSort,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ExploreActionKind } from "../../../exploreState";
|
|
2
|
+
import { UpdateFilterSortAction, UpdateFilterSortPayload } from "./types";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Action creator for updating filter sort in the state.
|
|
6
|
+
* @param payload - Payload.
|
|
7
|
+
* @returns Action with payload and action type.
|
|
8
|
+
*/
|
|
9
|
+
export function updateFilterSort(
|
|
10
|
+
payload: UpdateFilterSortPayload
|
|
11
|
+
): UpdateFilterSortAction {
|
|
12
|
+
return {
|
|
13
|
+
payload,
|
|
14
|
+
type: ExploreActionKind.UpdateFilterSort,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { FILTER_SORT } from "../../../../common/filters/sort/config/types";
|
|
2
|
+
import { ExploreActionKind } from "../../../exploreState";
|
|
3
|
+
|
|
4
|
+
export type UpdateFilterSortAction = {
|
|
5
|
+
payload: UpdateFilterSortPayload;
|
|
6
|
+
type: ExploreActionKind.UpdateFilterSort;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export type UpdateFilterSortPayload = FILTER_SORT;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { isRangeCategory } from "../../../../common/categories/models/range/typeGuards";
|
|
2
|
+
import { CategoryView } from "../../../../common/categories/views/types";
|
|
3
|
+
import { FILTER_SORT } from "../../../../common/filters/sort/config/types";
|
|
4
|
+
import { sortCategoryValueViews } from "../../../../common/filters/sort/models/utils";
|
|
5
|
+
import { ExploreState } from "../../../exploreState";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Sorts the category views for the current entity type, based on the filter sort.
|
|
9
|
+
* @param state - Explore state.
|
|
10
|
+
* @param filterSort - Filter sort.
|
|
11
|
+
* @returns Sorted category views.
|
|
12
|
+
*/
|
|
13
|
+
export function sortCategoryViews(
|
|
14
|
+
state: ExploreState,
|
|
15
|
+
filterSort: FILTER_SORT
|
|
16
|
+
): CategoryView[] {
|
|
17
|
+
return [...state.categoryViews].map((categoryView) => {
|
|
18
|
+
// Skip range categories.
|
|
19
|
+
if (isRangeCategory(categoryView)) return categoryView;
|
|
20
|
+
|
|
21
|
+
// Use structural clone for select categories that need sorting.
|
|
22
|
+
const nextCategoryView = {
|
|
23
|
+
...categoryView,
|
|
24
|
+
values: [...categoryView.values],
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
sortCategoryValueViews(nextCategoryView.values, filterSort);
|
|
28
|
+
return nextCategoryView;
|
|
29
|
+
});
|
|
30
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { FILTER_SORT } from "../../../common/filters/sort/config/types";
|
|
1
2
|
import { CategoryGroup } from "../../../config/entities";
|
|
2
3
|
import { ExploreState, PaginationState } from "../../exploreState";
|
|
3
4
|
import { SELECT_CATEGORY_KEY } from "../constants";
|
|
@@ -34,6 +35,7 @@ export const INITIAL_STATE: ExploreState = {
|
|
|
34
35
|
entityStateByCategoryGroupConfigKey: new Map(),
|
|
35
36
|
featureFlagState: undefined,
|
|
36
37
|
filterCount: 0,
|
|
38
|
+
filterSort: FILTER_SORT.ALPHA,
|
|
37
39
|
filterState: [],
|
|
38
40
|
listItems: [],
|
|
39
41
|
loading: true,
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
} from "@tanstack/react-table";
|
|
6
6
|
import { CategoryConfig } from "../../../common/categories/config/types";
|
|
7
7
|
import { SelectCategory, SelectedFilter } from "../../../common/entities";
|
|
8
|
+
import { getFilterSortType } from "../../../common/filters/sort/config/utils";
|
|
8
9
|
import { getInitialColumnVisibilityState } from "../../../components/TableCreator/options/initialState/columnVisibility";
|
|
9
10
|
import {
|
|
10
11
|
CategoryGroup,
|
|
@@ -325,6 +326,7 @@ export function initReducerArguments(
|
|
|
325
326
|
entityStateByCategoryGroupConfigKey,
|
|
326
327
|
featureFlagState: decodedFeatureFlagParam,
|
|
327
328
|
filterCount: getFilterCount(filterState),
|
|
329
|
+
filterSort: getFilterSortType(config),
|
|
328
330
|
filterState,
|
|
329
331
|
tabValue: entityListType,
|
|
330
332
|
};
|