@databiosphere/findable-ui 29.0.2 → 30.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 +22 -0
- package/lib/common/categories/config/types.d.ts +28 -0
- package/lib/common/categories/config/utils.d.ts +31 -0
- package/lib/common/categories/config/utils.js +29 -0
- package/lib/common/categories/models/range/typeGuards.d.ts +14 -0
- package/lib/common/categories/models/range/typeGuards.js +18 -0
- package/lib/common/categories/models/range/types.d.ts +15 -0
- package/lib/common/categories/models/range/types.js +1 -0
- package/lib/common/categories/models/range/utils.d.ts +23 -0
- package/lib/common/categories/models/range/utils.js +41 -0
- package/lib/common/categories/models/select/utils.d.ts +8 -0
- package/lib/common/categories/models/select/utils.js +16 -0
- package/lib/common/categories/models/types.d.ts +6 -0
- package/lib/common/categories/models/types.js +1 -0
- package/lib/common/categories/views/common/types.d.ts +10 -0
- package/lib/common/categories/views/common/types.js +1 -0
- package/lib/common/categories/views/range/typeGuards.d.ts +8 -0
- package/lib/common/categories/views/range/typeGuards.js +8 -0
- package/lib/common/categories/views/range/types.d.ts +19 -0
- package/lib/common/categories/views/range/types.js +1 -0
- package/lib/common/categories/views/range/utils.d.ts +12 -0
- package/lib/common/categories/views/range/utils.js +24 -0
- package/lib/common/categories/views/select/typeGuards.d.ts +8 -0
- package/lib/common/categories/views/select/typeGuards.js +8 -0
- package/lib/common/categories/views/select/types.d.ts +7 -0
- package/lib/common/categories/views/select/types.js +1 -0
- package/lib/common/categories/views/types.d.ts +13 -0
- package/lib/common/categories/views/types.js +8 -0
- package/lib/common/entities.d.ts +5 -2
- package/lib/components/DataDictionary/components/Table/components/BasicCell/basicCell.d.ts +3 -2
- package/lib/components/DataDictionary/components/Table/components/BasicCell/basicCell.js +6 -2
- package/lib/components/DataDictionary/components/Table/components/BasicCell/utils.d.ts +9 -0
- package/lib/components/DataDictionary/components/Table/components/BasicCell/utils.js +12 -0
- package/lib/components/DataDictionary/dataDictionary.styles.js +2 -3
- package/lib/components/Filter/components/Filter/filter.d.ts +2 -2
- package/lib/components/Filter/components/Filter/filter.js +11 -3
- package/lib/components/Filter/components/Filter/stories/args.d.ts +5 -0
- package/lib/components/Filter/components/Filter/stories/args.js +19 -0
- package/lib/components/Filter/components/Filter/stories/filter.stories.d.ts +8 -0
- package/lib/components/Filter/components/Filter/stories/filter.stories.js +21 -0
- package/lib/components/Filter/components/FilterMenu/filterMenu.js +2 -2
- package/lib/components/Filter/components/FilterMenu/filterMenu.styles.d.ts +1 -1
- package/lib/components/Filter/components/FilterMenu/filterMenu.styles.js +1 -1
- package/lib/components/Filter/components/FilterRange/constants.d.ts +0 -2
- package/lib/components/Filter/components/FilterRange/constants.js +0 -5
- package/lib/components/Filter/components/FilterRange/filterRange.d.ts +1 -1
- package/lib/components/Filter/components/FilterRange/filterRange.js +50 -21
- package/lib/components/Filter/components/FilterRange/filterRange.styles.js +58 -10
- package/lib/components/Filter/components/FilterRange/hooks/UseFilterRange/constants.d.ts +5 -0
- package/lib/components/Filter/components/FilterRange/hooks/UseFilterRange/constants.js +5 -0
- package/lib/components/Filter/components/FilterRange/hooks/UseFilterRange/hook.d.ts +2 -2
- package/lib/components/Filter/components/FilterRange/hooks/UseFilterRange/hook.js +32 -7
- package/lib/components/Filter/components/FilterRange/hooks/UseFilterRange/schema.d.ts +6 -0
- package/lib/components/Filter/components/FilterRange/hooks/UseFilterRange/schema.js +50 -0
- package/lib/components/Filter/components/FilterRange/hooks/UseFilterRange/types.d.ts +26 -3
- package/lib/components/Filter/components/FilterRange/hooks/UseFilterRange/types.js +6 -1
- package/lib/components/Filter/components/FilterRange/hooks/UseFilterRange/utils.d.ts +15 -0
- package/lib/components/Filter/components/FilterRange/hooks/UseFilterRange/utils.js +25 -0
- package/lib/components/Filter/components/FilterRange/stories/args.d.ts +3 -0
- package/lib/components/Filter/components/FilterRange/stories/args.js +13 -0
- package/lib/components/Filter/components/FilterRange/stories/filterRange.stories.js +2 -2
- package/lib/components/Filter/components/FilterRange/types.d.ts +10 -6
- package/lib/components/Filter/components/FilterRange/types.js +1 -6
- package/lib/components/Filter/components/FilterRange/utils.d.ts +8 -0
- package/lib/components/Filter/components/FilterRange/utils.js +15 -0
- package/lib/components/Filter/components/FilterTag/stories/args.d.ts +5 -0
- package/lib/components/Filter/components/FilterTag/stories/args.js +17 -0
- package/lib/components/Filter/components/FilterTag/stories/filterTag.stories.d.ts +8 -0
- package/lib/components/Filter/components/FilterTag/stories/filterTag.stories.js +21 -0
- package/lib/components/Filter/components/FilterTag/utils.d.ts +10 -0
- package/lib/components/Filter/components/FilterTag/utils.js +40 -0
- package/lib/components/Filter/components/Filters/filters.d.ts +2 -2
- package/lib/components/Filter/components/Filters/filters.js +15 -8
- package/lib/components/Filter/components/Filters/stories/args.d.ts +3 -0
- package/lib/components/Filter/components/Filters/stories/args.js +15 -0
- package/lib/components/Filter/components/Filters/stories/constants.d.ts +22 -0
- package/lib/components/Filter/components/Filters/stories/constants.js +134 -0
- package/lib/components/Filter/components/Filters/stories/filters.stories.d.ts +6 -0
- package/lib/components/Filter/components/Filters/stories/filters.stories.js +15 -0
- package/lib/components/Filter/components/SearchAllFilters/components/VariableSizeList/VariableSizeList.d.ts +1 -1
- package/lib/components/Filter/components/SearchAllFilters/components/VariableSizeList/VariableSizeList.js +5 -5
- package/lib/components/Filter/components/SearchAllFilters/components/VariableSizeListItem/variableSizeListItem.js +2 -1
- package/lib/components/Filter/components/SearchAllFilters/searchAllFilters.d.ts +3 -2
- package/lib/components/Filter/components/SearchAllFilters/searchAllFilters.js +6 -4
- package/lib/components/Filter/components/VariableSizeListItem/variableSizeListItem.js +2 -1
- package/lib/components/Index/components/EntitiesView/components/ChartView/utils.js +2 -0
- package/lib/components/Index/table/hook.js +4 -0
- package/lib/components/Table/columnDef/accessorFn/typeGuards.d.ts +9 -0
- package/lib/components/Table/columnDef/accessorFn/typeGuards.js +10 -0
- package/lib/components/Table/common/utils.d.ts +2 -2
- package/lib/components/Table/common/utils.js +28 -13
- package/lib/components/Table/components/TableCell/components/ChipCell/chipCell.d.ts +3 -0
- package/lib/components/Table/components/TableCell/components/ChipCell/chipCell.js +8 -0
- package/lib/components/Table/components/TableCell/components/LinkCell/linkCell.d.ts +4 -0
- package/lib/components/Table/components/TableCell/components/LinkCell/linkCell.js +21 -0
- package/lib/components/Table/components/TableCell/components/LinkCell/stories/args.d.ts +6 -0
- package/lib/components/Table/components/TableCell/components/LinkCell/stories/args.js +27 -0
- package/lib/components/Table/components/TableCell/components/LinkCell/stories/linkCell.stories.d.ts +9 -0
- package/lib/components/Table/components/TableCell/components/LinkCell/stories/linkCell.stories.js +18 -0
- package/lib/components/Table/components/TableCell/components/LinkCell/stories/types.d.ts +3 -0
- package/lib/components/Table/components/TableCell/components/LinkCell/stories/types.js +1 -0
- package/lib/components/Table/components/TableCell/components/LinkCell/utils.d.ts +22 -0
- package/lib/components/Table/components/TableCell/components/LinkCell/utils.js +45 -0
- package/lib/components/Table/featureOptions/facetedColumn/getFacetedMinMaxValues.d.ts +8 -0
- package/lib/components/Table/featureOptions/facetedColumn/getFacetedMinMaxValues.js +46 -0
- package/lib/components/common/Link/typeGuards.d.ts +13 -0
- package/lib/components/common/Link/typeGuards.js +21 -0
- package/lib/config/entities.d.ts +2 -11
- package/lib/hooks/useCategoryFilter.d.ts +8 -13
- package/lib/hooks/useCategoryFilter.js +31 -28
- package/lib/providers/exploreState/entities.d.ts +5 -3
- package/lib/providers/exploreState/payloads/entities.d.ts +6 -2
- package/lib/providers/exploreState.d.ts +3 -2
- package/lib/providers/exploreState.js +1 -1
- package/lib/tests/utils.d.ts +24 -0
- package/lib/tests/utils.js +34 -0
- package/lib/theme/common/components.js +19 -1
- package/lib/views/ExploreView/exploreView.js +10 -8
- package/package.json +2 -1
- package/src/common/categories/config/types.ts +42 -0
- package/src/common/categories/config/utils.ts +47 -0
- package/src/common/categories/models/range/typeGuards.ts +24 -0
- package/src/common/categories/models/range/types.ts +17 -0
- package/src/common/categories/models/range/utils.ts +51 -0
- package/src/common/categories/models/select/utils.ts +23 -0
- package/src/common/categories/models/types.ts +7 -0
- package/src/common/categories/views/common/types.ts +11 -0
- package/src/common/categories/views/range/typeGuards.ts +13 -0
- package/src/common/categories/views/range/types.ts +21 -0
- package/src/common/categories/views/range/utils.ts +35 -0
- package/src/common/categories/views/select/typeGuards.ts +13 -0
- package/src/common/categories/views/select/types.ts +8 -0
- package/src/common/categories/views/types.ts +15 -0
- package/src/common/entities.ts +10 -5
- package/src/components/DataDictionary/components/Table/components/BasicCell/basicCell.tsx +12 -4
- package/src/components/DataDictionary/components/Table/components/BasicCell/utils.ts +13 -0
- package/src/components/DataDictionary/dataDictionary.styles.ts +2 -3
- package/src/components/Filter/components/Filter/filter.tsx +38 -13
- package/src/components/Filter/components/Filter/stories/args.ts +24 -0
- package/src/components/Filter/components/Filter/stories/filter.stories.tsx +32 -0
- package/src/components/Filter/components/FilterMenu/filterMenu.styles.ts +1 -1
- package/src/components/Filter/components/FilterMenu/filterMenu.tsx +7 -3
- package/src/components/Filter/components/FilterRange/constants.ts +0 -7
- package/src/components/Filter/components/FilterRange/filterRange.styles.ts +58 -14
- package/src/components/Filter/components/FilterRange/filterRange.tsx +112 -40
- package/src/components/Filter/components/FilterRange/hooks/UseFilterRange/constants.ts +5 -0
- package/src/components/Filter/components/FilterRange/hooks/UseFilterRange/hook.ts +51 -10
- package/src/components/Filter/components/FilterRange/hooks/UseFilterRange/schema.ts +60 -0
- package/src/components/Filter/components/FilterRange/hooks/UseFilterRange/types.ts +34 -3
- package/src/components/Filter/components/FilterRange/hooks/UseFilterRange/utils.ts +32 -0
- package/src/components/Filter/components/FilterRange/stories/args.ts +16 -0
- package/src/components/Filter/components/FilterRange/stories/filterRange.stories.tsx +2 -2
- package/src/components/Filter/components/FilterRange/types.ts +12 -6
- package/src/components/Filter/components/FilterRange/utils.ts +16 -0
- package/src/components/Filter/components/FilterTag/stories/args.ts +22 -0
- package/src/components/Filter/components/FilterTag/stories/filterTag.stories.tsx +32 -0
- package/src/components/Filter/components/FilterTag/utils.ts +57 -0
- package/src/components/Filter/components/Filters/filters.tsx +21 -12
- package/src/components/Filter/components/Filters/stories/args.ts +24 -0
- package/src/components/Filter/components/Filters/stories/constants.ts +151 -0
- package/src/components/Filter/components/Filters/stories/filters.stories.tsx +24 -0
- package/src/components/Filter/components/SearchAllFilters/components/VariableSizeList/VariableSizeList.tsx +32 -29
- package/src/components/Filter/components/SearchAllFilters/components/VariableSizeListItem/variableSizeListItem.tsx +9 -1
- package/src/components/Filter/components/SearchAllFilters/searchAllFilters.tsx +12 -6
- package/src/components/Filter/components/VariableSizeListItem/variableSizeListItem.tsx +2 -1
- package/src/components/Index/components/EntitiesView/components/ChartView/utils.ts +2 -0
- package/src/components/Index/table/hook.ts +4 -0
- package/src/components/Table/columnDef/accessorFn/typeGuards.ts +15 -0
- package/src/components/Table/common/utils.ts +37 -16
- package/src/components/Table/components/TableCell/components/ChipCell/chipCell.tsx +14 -0
- package/src/components/Table/components/TableCell/components/LinkCell/linkCell.tsx +64 -0
- package/src/components/Table/components/TableCell/components/LinkCell/stories/args.ts +35 -0
- package/src/components/Table/components/TableCell/components/LinkCell/stories/linkCell.stories.tsx +32 -0
- package/src/components/Table/components/TableCell/components/LinkCell/stories/types.ts +4 -0
- package/src/components/Table/components/TableCell/components/LinkCell/utils.ts +59 -0
- package/src/components/Table/featureOptions/facetedColumn/getFacetedMinMaxValues.ts +64 -0
- package/src/components/common/Link/typeGuards.ts +35 -0
- package/src/config/entities.ts +1 -14
- package/src/hooks/useCategoryFilter.ts +56 -53
- package/src/providers/exploreState/entities.ts +3 -3
- package/src/providers/exploreState/initializer/utils.ts +1 -1
- package/src/providers/exploreState/payloads/entities.ts +5 -2
- package/src/providers/exploreState.tsx +5 -3
- package/src/tests/utils.ts +44 -0
- package/src/theme/common/components.ts +19 -1
- package/src/views/ExploreView/exploreView.tsx +17 -22
- package/tests/filter.test.tsx +100 -0
- package/tests/filterRange.test.tsx +331 -46
- package/tests/filters.test.tsx +61 -0
- package/tests/getFacetedMinMaxValues.test.ts +166 -0
- package/tests/linkCell.test.tsx +89 -0
- package/lib/components/DataDictionary/components/Table/components/BasicCell/types.d.ts +0 -3
- package/lib/components/Filter/components/Filter/filter.stories.d.ts +0 -25
- package/lib/components/Filter/components/Filter/filter.stories.js +0 -42
- package/lib/components/Filter/components/FilterTag/filterTag.stories.d.ts +0 -16
- package/lib/components/Filter/components/FilterTag/filterTag.stories.js +0 -17
- package/lib/components/Filter/components/Filters/filters.stories.d.ts +0 -6
- package/lib/components/Filter/components/Filters/filters.stories.js +0 -91
- package/src/components/DataDictionary/components/Table/components/BasicCell/types.ts +0 -7
- package/src/components/Filter/components/Filter/filter.stories.tsx +0 -52
- package/src/components/Filter/components/FilterTag/filterTag.stories.tsx +0 -23
- package/src/components/Filter/components/Filters/filters.stories.tsx +0 -101
- package/tests/filterRangeMock.test.tsx +0 -38
- /package/lib/{components/DataDictionary/components/Table/components/BasicCell → common/categories/config}/types.js +0 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Box } from "@mui/material";
|
|
2
|
+
import { Meta, StoryObj } from "@storybook/react";
|
|
3
|
+
import React from "react";
|
|
4
|
+
import { FilterTag } from "../filterTag";
|
|
5
|
+
import { DEFAULT_ARGS, WITH_ELLIPSIS_ARGS, WITH_RANGE_ARGS } from "./args";
|
|
6
|
+
|
|
7
|
+
const meta: Meta<typeof FilterTag> = {
|
|
8
|
+
component: FilterTag,
|
|
9
|
+
decorators: [
|
|
10
|
+
(Story): JSX.Element => (
|
|
11
|
+
<Box sx={{ width: 232 }}>
|
|
12
|
+
<Story />
|
|
13
|
+
</Box>
|
|
14
|
+
),
|
|
15
|
+
],
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export default meta;
|
|
19
|
+
|
|
20
|
+
type Story = StoryObj<typeof meta>;
|
|
21
|
+
|
|
22
|
+
export const Default: Story = {
|
|
23
|
+
args: DEFAULT_ARGS,
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export const WithEllipsis: Story = {
|
|
27
|
+
args: WITH_ELLIPSIS_ARGS,
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const WithRange: Story = {
|
|
31
|
+
args: WITH_RANGE_ARGS,
|
|
32
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { RangeCategoryView } from "../../../../common/categories/views/range/types";
|
|
2
|
+
import { VIEW_KIND } from "../../../../common/categories/views/types";
|
|
3
|
+
import { CategoryTag } from "../../../../common/entities";
|
|
4
|
+
import { OnFilterFn } from "../../../../hooks/useCategoryFilter";
|
|
5
|
+
import { RANGE_OPERATOR } from "../FilterRange/hooks/UseFilterRange/types";
|
|
6
|
+
import { getRangeOperator } from "../FilterRange/utils";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Returns set of filter tags with tag label (the selected range values) and corresponding Tag onRemove function.
|
|
10
|
+
* @param categoryView - View model of range category.
|
|
11
|
+
* @param onFilter - Function to execute on selection or removal of category value.
|
|
12
|
+
* @returns Array of selected filter tags.
|
|
13
|
+
*/
|
|
14
|
+
export function buildRangeTag(
|
|
15
|
+
categoryView: RangeCategoryView,
|
|
16
|
+
onFilter: OnFilterFn
|
|
17
|
+
): CategoryTag[] {
|
|
18
|
+
const rangeOperator = getRangeOperator(categoryView);
|
|
19
|
+
if (!rangeOperator) return [];
|
|
20
|
+
return [
|
|
21
|
+
{
|
|
22
|
+
label: buildRangeTagLabel(categoryView, rangeOperator),
|
|
23
|
+
onRemove: () =>
|
|
24
|
+
onFilter(
|
|
25
|
+
categoryView.key,
|
|
26
|
+
undefined,
|
|
27
|
+
false,
|
|
28
|
+
undefined,
|
|
29
|
+
VIEW_KIND.RANGE
|
|
30
|
+
),
|
|
31
|
+
superseded: false,
|
|
32
|
+
},
|
|
33
|
+
];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Returns the label for the range tag based on the selected values.
|
|
38
|
+
* @param categoryView - View model of range category.
|
|
39
|
+
* @param rangeOperator - The range operator.
|
|
40
|
+
* @returns The label for the range tag.
|
|
41
|
+
*/
|
|
42
|
+
function buildRangeTagLabel(
|
|
43
|
+
categoryView: RangeCategoryView,
|
|
44
|
+
rangeOperator: RANGE_OPERATOR
|
|
45
|
+
): string {
|
|
46
|
+
const { selectedMax, selectedMin } = categoryView;
|
|
47
|
+
switch (rangeOperator) {
|
|
48
|
+
case RANGE_OPERATOR.BETWEEN:
|
|
49
|
+
return `${selectedMin} - ${selectedMax}`;
|
|
50
|
+
case RANGE_OPERATOR.GREATER_THAN:
|
|
51
|
+
return `> ${selectedMin}`;
|
|
52
|
+
case RANGE_OPERATOR.LESS_THAN:
|
|
53
|
+
return `< ${selectedMax}`;
|
|
54
|
+
default:
|
|
55
|
+
return "";
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { Divider } from "@mui/material";
|
|
2
2
|
import React, { Fragment, useEffect, useRef, useState } from "react";
|
|
3
|
-
import {
|
|
3
|
+
import { isRangeCategoryView } from "../../../../common/categories/views/range/typeGuards";
|
|
4
|
+
import { CategoryView } from "../../../../common/categories/views/types";
|
|
5
|
+
import { CategoryTag } from "../../../../common/entities";
|
|
4
6
|
import { TrackFilterOpenedFunction } from "../../../../config/entities";
|
|
5
7
|
import {
|
|
6
8
|
BREAKPOINT_FN_NAME,
|
|
@@ -11,11 +13,12 @@ import { useWindowResize } from "../../../../hooks/useWindowResize";
|
|
|
11
13
|
import { TEST_IDS } from "../../../../tests/testIds";
|
|
12
14
|
import { DESKTOP_SM } from "../../../../theme/common/breakpoints";
|
|
13
15
|
import { Filter } from "../Filter/filter";
|
|
16
|
+
import { buildRangeTag } from "../FilterTag/utils";
|
|
14
17
|
import { FilterTags } from "../FilterTags/filterTags";
|
|
15
18
|
import { CategoryViewsLabel, Filters as FilterList } from "./filters.styles";
|
|
16
19
|
|
|
17
20
|
export interface CategoryFilter {
|
|
18
|
-
categoryViews:
|
|
21
|
+
categoryViews: CategoryView[];
|
|
19
22
|
label?: string;
|
|
20
23
|
}
|
|
21
24
|
|
|
@@ -28,15 +31,21 @@ export interface FiltersProps {
|
|
|
28
31
|
}
|
|
29
32
|
|
|
30
33
|
/**
|
|
31
|
-
* Returns
|
|
34
|
+
* Returns filter tags for the given category view.
|
|
32
35
|
* @param categoryView - View model of category to display.
|
|
33
|
-
* @param onFilter - Function to execute on
|
|
34
|
-
* @returns Array of
|
|
36
|
+
* @param onFilter - Function to execute on selection or removal of category value.
|
|
37
|
+
* @returns Array of filter tags.
|
|
35
38
|
*/
|
|
36
|
-
function
|
|
37
|
-
categoryView:
|
|
39
|
+
function buildFilterTags(
|
|
40
|
+
categoryView: CategoryView,
|
|
38
41
|
onFilter: OnFilterFn
|
|
39
42
|
): CategoryTag[] {
|
|
43
|
+
// Handle range category views
|
|
44
|
+
if (isRangeCategoryView(categoryView)) {
|
|
45
|
+
return buildRangeTag(categoryView, onFilter);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Handle select category views.
|
|
40
49
|
const { key: categoryKey, values } = categoryView;
|
|
41
50
|
return values
|
|
42
51
|
.filter(({ selected }) => selected)
|
|
@@ -50,16 +59,16 @@ function buildSelectCategoryTags(
|
|
|
50
59
|
}
|
|
51
60
|
|
|
52
61
|
/**
|
|
53
|
-
*
|
|
62
|
+
* Returns filter tags element for the given category view.
|
|
54
63
|
* @param categoryView - View model of category to display.
|
|
55
|
-
* @param onFilter - Function to execute on
|
|
56
|
-
* @returns Filter tags element
|
|
64
|
+
* @param onFilter - Function to execute on selection or removal of category value.
|
|
65
|
+
* @returns Filter tags element.
|
|
57
66
|
*/
|
|
58
67
|
function renderFilterTags(
|
|
59
|
-
categoryView:
|
|
68
|
+
categoryView: CategoryView,
|
|
60
69
|
onFilter: OnFilterFn
|
|
61
70
|
): JSX.Element {
|
|
62
|
-
const tags =
|
|
71
|
+
const tags = buildFilterTags(categoryView, onFilter);
|
|
63
72
|
return <FilterTags tags={tags} />;
|
|
64
73
|
}
|
|
65
74
|
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { fn } from "@storybook/test";
|
|
2
|
+
import { ComponentProps } from "react";
|
|
3
|
+
import { Filters } from "../filters";
|
|
4
|
+
import {
|
|
5
|
+
BIOLOGICAL_SEX,
|
|
6
|
+
DONOR_COUNT,
|
|
7
|
+
FILE_FORMAT,
|
|
8
|
+
FILE_TYPE,
|
|
9
|
+
GENUS_SPECIES,
|
|
10
|
+
} from "./constants";
|
|
11
|
+
|
|
12
|
+
export const DEFAULT_ARGS: ComponentProps<typeof Filters> = {
|
|
13
|
+
categoryFilters: [
|
|
14
|
+
{
|
|
15
|
+
categoryViews: [BIOLOGICAL_SEX, GENUS_SPECIES, DONOR_COUNT],
|
|
16
|
+
label: "Donor",
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
categoryViews: [FILE_FORMAT, FILE_TYPE],
|
|
20
|
+
label: "File",
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
onFilter: fn(),
|
|
24
|
+
};
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { RangeCategoryView } from "../../../../../common/categories/views/range/types";
|
|
2
|
+
import { SelectCategoryView } from "../../../../../common/entities";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Biological Sex
|
|
6
|
+
*/
|
|
7
|
+
const MALE = {
|
|
8
|
+
count: 14,
|
|
9
|
+
key: "male",
|
|
10
|
+
label: "Male",
|
|
11
|
+
selected: false,
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Biological Sex
|
|
16
|
+
*/
|
|
17
|
+
const FEMALE = {
|
|
18
|
+
count: 12,
|
|
19
|
+
key: "female",
|
|
20
|
+
label: "Female",
|
|
21
|
+
selected: false,
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Genus Species
|
|
26
|
+
*/
|
|
27
|
+
const HOMO_SAPIENS = {
|
|
28
|
+
count: 471,
|
|
29
|
+
key: "Homo sapiens",
|
|
30
|
+
label: "Homo sapiens",
|
|
31
|
+
selected: false,
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Genus Species
|
|
36
|
+
*/
|
|
37
|
+
const MUS_MUSCLES = {
|
|
38
|
+
count: 55,
|
|
39
|
+
key: "Mus musculus",
|
|
40
|
+
label: "Mus musculus",
|
|
41
|
+
selected: false,
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* File Format
|
|
46
|
+
*/
|
|
47
|
+
const BAM = {
|
|
48
|
+
count: 7,
|
|
49
|
+
key: "bam",
|
|
50
|
+
label: "bam",
|
|
51
|
+
selected: false,
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* File Format
|
|
56
|
+
*/
|
|
57
|
+
const CSV = {
|
|
58
|
+
count: 5,
|
|
59
|
+
key: "csv",
|
|
60
|
+
label: "csv",
|
|
61
|
+
selected: false,
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* File Format
|
|
66
|
+
*/
|
|
67
|
+
const FASTQ = {
|
|
68
|
+
count: 38,
|
|
69
|
+
key: "fastq",
|
|
70
|
+
label: "fastq",
|
|
71
|
+
selected: false,
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* File Format
|
|
76
|
+
*/
|
|
77
|
+
const TSV = {
|
|
78
|
+
count: 3,
|
|
79
|
+
key: "tsv",
|
|
80
|
+
label: "tsv",
|
|
81
|
+
selected: false,
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* File Type
|
|
86
|
+
*/
|
|
87
|
+
const RAW = {
|
|
88
|
+
count: 1,
|
|
89
|
+
key: "raw",
|
|
90
|
+
label: "raw",
|
|
91
|
+
selected: false,
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* File Type
|
|
96
|
+
*/
|
|
97
|
+
const PROCESSED = {
|
|
98
|
+
count: 1,
|
|
99
|
+
key: "processed",
|
|
100
|
+
label: "processed",
|
|
101
|
+
selected: false,
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Biological Sex select category view
|
|
106
|
+
*/
|
|
107
|
+
export const BIOLOGICAL_SEX: SelectCategoryView = {
|
|
108
|
+
key: "biologicalSex",
|
|
109
|
+
label: "Biological Sex",
|
|
110
|
+
values: [MALE, FEMALE],
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Genus Species select category view
|
|
115
|
+
*/
|
|
116
|
+
export const GENUS_SPECIES: SelectCategoryView = {
|
|
117
|
+
key: "genusSpecies",
|
|
118
|
+
label: "Genus Species",
|
|
119
|
+
values: [HOMO_SAPIENS, MUS_MUSCLES],
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Donor Count range category view
|
|
124
|
+
*/
|
|
125
|
+
export const DONOR_COUNT: RangeCategoryView = {
|
|
126
|
+
key: "Donor Count",
|
|
127
|
+
label: "Donor Count",
|
|
128
|
+
max: 200,
|
|
129
|
+
min: 10,
|
|
130
|
+
selectedMax: null,
|
|
131
|
+
selectedMin: null,
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* File Format select category view
|
|
136
|
+
*/
|
|
137
|
+
export const FILE_FORMAT: SelectCategoryView = {
|
|
138
|
+
key: "fileFormat",
|
|
139
|
+
label: "File Format",
|
|
140
|
+
values: [BAM, CSV, FASTQ, TSV],
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* File Type select category view
|
|
145
|
+
*/
|
|
146
|
+
export const FILE_TYPE: SelectCategoryView = {
|
|
147
|
+
isDisabled: true,
|
|
148
|
+
key: "fileType",
|
|
149
|
+
label: "File Type",
|
|
150
|
+
values: [RAW, PROCESSED],
|
|
151
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Box } from "@mui/material";
|
|
2
|
+
import { Meta, StoryObj } from "@storybook/react";
|
|
3
|
+
import React from "react";
|
|
4
|
+
import { Filters } from "../filters";
|
|
5
|
+
import { DEFAULT_ARGS } from "./args";
|
|
6
|
+
|
|
7
|
+
const meta: Meta<typeof Filters> = {
|
|
8
|
+
component: Filters,
|
|
9
|
+
decorators: [
|
|
10
|
+
(Story): JSX.Element => (
|
|
11
|
+
<Box sx={{ width: 264 }}>
|
|
12
|
+
<Story />
|
|
13
|
+
</Box>
|
|
14
|
+
),
|
|
15
|
+
],
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export default meta;
|
|
19
|
+
|
|
20
|
+
type Story = StoryObj<typeof Filters>;
|
|
21
|
+
|
|
22
|
+
export const Default: Story = {
|
|
23
|
+
args: DEFAULT_ARGS,
|
|
24
|
+
};
|
|
@@ -46,12 +46,12 @@ export type ItemSizeByItemKey = Map<string, number>;
|
|
|
46
46
|
|
|
47
47
|
export interface VariableSizeListProps {
|
|
48
48
|
autocompleteListProps: Omit<MListProps, "children">;
|
|
49
|
-
categoryViews: SelectCategoryView[];
|
|
50
49
|
height?: number; // Height of list; vertical list must be a number.
|
|
51
50
|
itemSize?: number; // Default item size.
|
|
52
51
|
onFilter: OnFilterFn;
|
|
53
52
|
overscanCount?: ListProps["overscanCount"];
|
|
54
53
|
searchTerm: string;
|
|
54
|
+
selectCategoryViews: SelectCategoryView[];
|
|
55
55
|
width?: ListProps["width"]; // Width of list; default to 100% width of parent element.
|
|
56
56
|
}
|
|
57
57
|
|
|
@@ -120,17 +120,17 @@ export const VariableSizeList = forwardRef<
|
|
|
120
120
|
>(function VariableSizeList(
|
|
121
121
|
{
|
|
122
122
|
autocompleteListProps,
|
|
123
|
-
categoryViews,
|
|
124
123
|
height: initHeight = MAX_LIST_HEIGHT_PX,
|
|
125
124
|
itemSize = LIST_ITEM_HEIGHT,
|
|
126
125
|
onFilter,
|
|
127
126
|
overscanCount = MAX_DISPLAYABLE_LIST_ITEMS * 2,
|
|
128
127
|
searchTerm,
|
|
128
|
+
selectCategoryViews,
|
|
129
129
|
width = "100%",
|
|
130
130
|
}: VariableSizeListProps,
|
|
131
131
|
autocompleteListRef
|
|
132
132
|
): JSX.Element {
|
|
133
|
-
const filteredItems = applyMenuFilter(
|
|
133
|
+
const filteredItems = applyMenuFilter(selectCategoryViews, searchTerm);
|
|
134
134
|
let resizeRequired = true;
|
|
135
135
|
const desktopSmDown = useBreakpointHelper(
|
|
136
136
|
BREAKPOINT_FN_NAME.DOWN,
|
|
@@ -223,40 +223,43 @@ export const VariableSizeList = forwardRef<
|
|
|
223
223
|
|
|
224
224
|
/**
|
|
225
225
|
* Filter categories' values by a search term and return model of list items
|
|
226
|
-
* @param
|
|
226
|
+
* @param selectCategoryViews - Select category views
|
|
227
227
|
* @param inputValue - Search term
|
|
228
228
|
* @returns array of objects representing list items to be rendered
|
|
229
229
|
*/
|
|
230
230
|
function applyMenuFilter(
|
|
231
|
-
|
|
231
|
+
selectCategoryViews: SelectCategoryView[],
|
|
232
232
|
inputValue: string
|
|
233
233
|
): SearchAllFiltersItem[] {
|
|
234
234
|
const sortMatches = getSortMatchesFn(inputValue);
|
|
235
|
-
const filteredItems =
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
if (
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
235
|
+
const filteredItems = selectCategoryViews.reduce(
|
|
236
|
+
(filteredItems, category) => {
|
|
237
|
+
if (!category.isDisabled) {
|
|
238
|
+
const categoryValueKeyPrefix =
|
|
239
|
+
"value_" + category.key.replaceAll(";", ";;") + ";_"; // Terminating the category key with a semicolon (and escaping preceding semicolons) ensures a unique prefix
|
|
240
|
+
const filteredCategoryValues = sortMatches(category.values).map(
|
|
241
|
+
(match): ValueItem => ({
|
|
242
|
+
categoryKey: category.key,
|
|
243
|
+
key: categoryValueKeyPrefix + match.value.key,
|
|
244
|
+
matchRanges: match.labelRanges,
|
|
245
|
+
type: ITEM_TYPE.VALUE,
|
|
246
|
+
value: match.value,
|
|
247
|
+
})
|
|
248
|
+
);
|
|
249
|
+
if (filteredCategoryValues.length) {
|
|
250
|
+
if (filteredItems.length) filteredItems.push(DIVIDER_ITEM);
|
|
251
|
+
filteredItems.push({
|
|
252
|
+
categoryLabel: category.label,
|
|
253
|
+
key: "category_" + category.key,
|
|
254
|
+
type: ITEM_TYPE.CATEGORY,
|
|
255
|
+
});
|
|
256
|
+
filteredItems.push(...filteredCategoryValues);
|
|
257
|
+
}
|
|
256
258
|
}
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
259
|
+
return filteredItems;
|
|
260
|
+
},
|
|
261
|
+
[] as SearchAllFiltersItem[]
|
|
262
|
+
);
|
|
260
263
|
if (filteredItems.length === 0) filteredItems.push(NO_RESULTS_ITEM);
|
|
261
264
|
return filteredItems;
|
|
262
265
|
}
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
Typography,
|
|
7
7
|
} from "@mui/material";
|
|
8
8
|
import React, { useEffect, useRef } from "react";
|
|
9
|
+
import { VIEW_KIND } from "../../../../../../common/categories/views/types";
|
|
9
10
|
import { OnFilterFn } from "../../../../../../hooks/useCategoryFilter";
|
|
10
11
|
import { TEST_IDS } from "../../../../../../tests/testIds";
|
|
11
12
|
import { TEXT_BODY_SMALL_400 } from "../../../../../../theme/common/typography";
|
|
@@ -54,7 +55,14 @@ export default function VariableSizeListItem({
|
|
|
54
55
|
ref={setRef}
|
|
55
56
|
key={key}
|
|
56
57
|
onClick={(): void =>
|
|
57
|
-
onFilter(
|
|
58
|
+
onFilter(
|
|
59
|
+
categoryKey,
|
|
60
|
+
valueKey,
|
|
61
|
+
!selected,
|
|
62
|
+
undefined,
|
|
63
|
+
VIEW_KIND.SELECT,
|
|
64
|
+
searchTerm
|
|
65
|
+
)
|
|
58
66
|
}
|
|
59
67
|
selected={selected}
|
|
60
68
|
style={style}
|
|
@@ -10,6 +10,8 @@ import React, {
|
|
|
10
10
|
useRef,
|
|
11
11
|
useState,
|
|
12
12
|
} from "react";
|
|
13
|
+
import { isSelectCategoryView } from "../../../../common/categories/views/select/typeGuards";
|
|
14
|
+
import { CategoryView } from "../../../../common/categories/views/types";
|
|
13
15
|
import { SelectCategoryView } from "../../../../common/entities";
|
|
14
16
|
import { SELECTOR } from "../../../../common/selectors";
|
|
15
17
|
import {
|
|
@@ -29,18 +31,18 @@ import { VariableSizeList } from "./components/VariableSizeList/VariableSizeList
|
|
|
29
31
|
import { Autocomplete } from "./searchAllFilters.styles";
|
|
30
32
|
|
|
31
33
|
export interface SearchAllFiltersProps {
|
|
32
|
-
categoryViews:
|
|
34
|
+
categoryViews: CategoryView[];
|
|
33
35
|
drawerOpen?: boolean;
|
|
34
36
|
onFilter: OnFilterFn;
|
|
35
37
|
}
|
|
36
38
|
|
|
37
39
|
interface ListboxContextValue {
|
|
38
|
-
categoryViews: SelectCategoryView[];
|
|
39
40
|
onClearSearch: () => void;
|
|
40
41
|
onCloseSearch: () => void;
|
|
41
42
|
onFilter: OnFilterFn;
|
|
42
43
|
open: boolean;
|
|
43
44
|
searchTerm: string;
|
|
45
|
+
selectCategoryViews: SelectCategoryView[];
|
|
44
46
|
}
|
|
45
47
|
|
|
46
48
|
const renderInput = (params: AutocompleteRenderInputParams): JSX.Element => (
|
|
@@ -48,12 +50,12 @@ const renderInput = (params: AutocompleteRenderInputParams): JSX.Element => (
|
|
|
48
50
|
);
|
|
49
51
|
|
|
50
52
|
export const ListboxContext = createContext<ListboxContextValue>({
|
|
51
|
-
categoryViews: [],
|
|
52
53
|
onClearSearch: (): void => undefined,
|
|
53
54
|
onCloseSearch: (): void => undefined,
|
|
54
55
|
onFilter: (): void => undefined,
|
|
55
56
|
open: false,
|
|
56
57
|
searchTerm: "",
|
|
58
|
+
selectCategoryViews: [],
|
|
57
59
|
});
|
|
58
60
|
|
|
59
61
|
const Listbox = React.forwardRef<HTMLUListElement, MListProps>(function Listbox(
|
|
@@ -63,14 +65,15 @@ const Listbox = React.forwardRef<HTMLUListElement, MListProps>(function Listbox(
|
|
|
63
65
|
props = Object.assign({}, props, {
|
|
64
66
|
children: undefined, // Content is controlled by VariableSizeList
|
|
65
67
|
});
|
|
66
|
-
const {
|
|
68
|
+
const { onFilter, searchTerm, selectCategoryViews } =
|
|
69
|
+
useContext(ListboxContext);
|
|
67
70
|
return (
|
|
68
71
|
<VariableSizeList
|
|
69
72
|
autocompleteListProps={props}
|
|
70
|
-
categoryViews={categoryViews}
|
|
71
73
|
onFilter={onFilter}
|
|
72
74
|
ref={ref}
|
|
73
75
|
searchTerm={searchTerm}
|
|
76
|
+
selectCategoryViews={selectCategoryViews}
|
|
74
77
|
/>
|
|
75
78
|
);
|
|
76
79
|
});
|
|
@@ -84,6 +87,9 @@ export const SearchAllFilters = ({
|
|
|
84
87
|
const autocompleteRef = useRef<HTMLDivElement>(null);
|
|
85
88
|
const [open, setOpen] = useState(false);
|
|
86
89
|
const [searchTerm, setSearchTerm] = useState("");
|
|
90
|
+
const selectCategoryViews = categoryViews.filter((view) =>
|
|
91
|
+
isSelectCategoryView(view)
|
|
92
|
+
);
|
|
87
93
|
|
|
88
94
|
// Handles background scroll action (desktop only).
|
|
89
95
|
const handleBackgroundScroll = (overflowStyle: OVERFLOW_STYLE): void => {
|
|
@@ -145,12 +151,12 @@ export const SearchAllFilters = ({
|
|
|
145
151
|
return (
|
|
146
152
|
<ListboxContext.Provider
|
|
147
153
|
value={{
|
|
148
|
-
categoryViews,
|
|
149
154
|
onClearSearch,
|
|
150
155
|
onCloseSearch,
|
|
151
156
|
onFilter,
|
|
152
157
|
open,
|
|
153
158
|
searchTerm,
|
|
159
|
+
selectCategoryViews,
|
|
154
160
|
}}
|
|
155
161
|
>
|
|
156
162
|
<Autocomplete
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
Typography,
|
|
6
6
|
} from "@mui/material";
|
|
7
7
|
import React, { CSSProperties, useEffect, useRef } from "react";
|
|
8
|
+
import { VIEW_KIND } from "../../../../common/categories/views/types";
|
|
8
9
|
import { CategoryKey } from "../../../../common/entities";
|
|
9
10
|
import { OnFilterFn } from "../../../../hooks/useCategoryFilter";
|
|
10
11
|
import { SELECT_CATEGORY_KEY } from "../../../../providers/exploreState/constants";
|
|
@@ -45,7 +46,7 @@ export default function VariableSizeListItem({
|
|
|
45
46
|
}, [key, onUpdateItemSizeByItemKey]);
|
|
46
47
|
|
|
47
48
|
const handleItemClicked = (): void => {
|
|
48
|
-
onFilter(categoryKey, key, !selected, categorySection);
|
|
49
|
+
onFilter(categoryKey, key, !selected, categorySection, VIEW_KIND.SELECT);
|
|
49
50
|
};
|
|
50
51
|
|
|
51
52
|
return (
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isSelectCategoryView } from "../../../../../../common/categories/views/select/typeGuards";
|
|
1
2
|
import { SelectCategoryView } from "../../../../../../common/entities";
|
|
2
3
|
import { CategoryFilter } from "../../../../../Filter/components/Filters/filters";
|
|
3
4
|
|
|
@@ -11,6 +12,7 @@ export function getSelectCategoryViews(
|
|
|
11
12
|
): SelectCategoryView[] {
|
|
12
13
|
return categoryFilters
|
|
13
14
|
.flatMap(({ categoryViews }) => categoryViews)
|
|
15
|
+
.filter(isSelectCategoryView)
|
|
14
16
|
.filter(({ enableChartView = true }) => enableChartView)
|
|
15
17
|
.filter(({ values }) => values.length > 0);
|
|
16
18
|
}
|
|
@@ -33,6 +33,7 @@ import {
|
|
|
33
33
|
isClientFilteringEnabled,
|
|
34
34
|
sortingFn,
|
|
35
35
|
} from "../../Table/common/utils";
|
|
36
|
+
import { getFacetedMinMaxValues } from "../../Table/featureOptions/facetedColumn/getFacetedMinMaxValues";
|
|
36
37
|
import { ROW_POSITION } from "../../Table/features/RowPosition/constants";
|
|
37
38
|
import { ROW_PREVIEW } from "../../Table/features/RowPreview/constants";
|
|
38
39
|
import { RowPreviewState } from "../../Table/features/RowPreview/entities";
|
|
@@ -167,6 +168,9 @@ export const useTable = <T extends RowData>(): UseTable<T> => {
|
|
|
167
168
|
enableMultiSort: clientFiltering, // TODO(cc) move to sorting options; default to false and let the table options in config flag this value.
|
|
168
169
|
filterFns: { arrIncludesSome },
|
|
169
170
|
getCoreRowModel: getCoreRowModel(),
|
|
171
|
+
getFacetedMinMaxValues: clientFiltering
|
|
172
|
+
? getFacetedMinMaxValues()
|
|
173
|
+
: undefined,
|
|
170
174
|
getFacetedRowModel: clientFiltering ? getFacetedRowModel() : undefined,
|
|
171
175
|
getFacetedUniqueValues: clientFiltering
|
|
172
176
|
? getFacetedUniqueValuesWithArrayValues()
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { RowData } from "@tanstack/react-table";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Type guard to check if a row has a specific key.
|
|
5
|
+
* Useful for generic accessor functions.
|
|
6
|
+
* @param row - The row to check.
|
|
7
|
+
* @param key - The key to check.
|
|
8
|
+
* @returns True if the row has the specified key, false otherwise.
|
|
9
|
+
*/
|
|
10
|
+
export function rowHasKey<T extends RowData, K extends PropertyKey, TValue>(
|
|
11
|
+
row: T,
|
|
12
|
+
key: K
|
|
13
|
+
): row is T & Record<K, TValue> {
|
|
14
|
+
return row != null && typeof row === "object" && key in row;
|
|
15
|
+
}
|