@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
package/lib/config/entities.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { JSXElementConstructor, ReactNode } from "react";
|
|
|
4
4
|
import { AzulSummaryResponse } from "../apis/azul/common/entities";
|
|
5
5
|
import { CategoryConfig } from "../common/categories/config/types";
|
|
6
6
|
import { DataDictionaryAnnotation, DataDictionaryConfig, SelectedFilter } from "../common/entities";
|
|
7
|
+
import { FilterSortConfig } from "../common/filters/sort/config/types";
|
|
7
8
|
import { FooterProps } from "../components/Layout/components/Footer/footer";
|
|
8
9
|
import { HeaderProps } from "../components/Layout/components/Header/header";
|
|
9
10
|
import { ExploreMode } from "../hooks/useExploreMode/types";
|
|
@@ -305,6 +306,7 @@ export interface SiteConfig {
|
|
|
305
306
|
export?: ExportConfig;
|
|
306
307
|
exportsRequireAuth?: boolean;
|
|
307
308
|
exportToTerraUrl?: string;
|
|
309
|
+
filterSort?: FilterSortConfig;
|
|
308
310
|
gitHubUrl?: string;
|
|
309
311
|
layout: {
|
|
310
312
|
floating?: FloatingConfig;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { CategoryConfig } from "../common/categories/config/types";
|
|
2
2
|
import { Category } from "../common/categories/models/types";
|
|
3
3
|
import { CategoryView, VIEW_KIND } from "../common/categories/views/types";
|
|
4
|
-
import { CategoryKey, CategoryValueKey, ClearAll, Filters, SelectCategoryValue
|
|
4
|
+
import { CategoryKey, CategoryValueKey, ClearAll, Filters, SelectCategoryValue } from "../common/entities";
|
|
5
|
+
import { FILTER_SORT } from "../common/filters/sort/config/types";
|
|
5
6
|
/**
|
|
6
7
|
* State backing filter functionality and calculations. Converted to view model for display.
|
|
7
8
|
*/
|
|
@@ -15,9 +16,10 @@ export type OnFilterFn = (categoryKey: CategoryKey | ClearAll, selectedCategoryV
|
|
|
15
16
|
* @param categories - Categories, category value and their counts with the current filter applied.
|
|
16
17
|
* @param categoryConfigs - Category configs indicating accept list as well as label configuration.
|
|
17
18
|
* @param filterState - Current set of selected category and category values.
|
|
19
|
+
* @param filterSort - Sort configuration (ALPHA or COUNT).
|
|
18
20
|
* @returns Array of category view objects.
|
|
19
21
|
*/
|
|
20
|
-
export declare function buildCategoryViews(categories: Category[], categoryConfigs: CategoryConfig[] | undefined, filterState: FilterState): CategoryView[];
|
|
22
|
+
export declare function buildCategoryViews(categories: Category[], categoryConfigs: CategoryConfig[] | undefined, filterState: FilterState, filterSort: FILTER_SORT): CategoryView[];
|
|
21
23
|
/**
|
|
22
24
|
* Build new set of selected filters on de/select of filter.
|
|
23
25
|
* @param filterState - Current set of selected category and category values.
|
|
@@ -34,10 +36,3 @@ export declare function buildNextFilterState(filterState: FilterState, categoryK
|
|
|
34
36
|
* @returns original select category value.
|
|
35
37
|
*/
|
|
36
38
|
export declare function getSelectCategoryValue(selectCategoryValue: SelectCategoryValue): SelectCategoryValue;
|
|
37
|
-
/**
|
|
38
|
-
* Sort category value views by key, ascending.
|
|
39
|
-
* @param cvv0 - First category value view to compare.
|
|
40
|
-
* @param cvv1 - Second category value view to compare.
|
|
41
|
-
* @returns Number indicating sort precedence of cv0 vs cv1.
|
|
42
|
-
*/
|
|
43
|
-
export declare function sortCategoryValueViews(cvv0: SelectCategoryValueView, cvv1: SelectCategoryValueView): number;
|
|
@@ -5,6 +5,7 @@ import { buildNextSelectFilterState } from "../common/categories/models/select/u
|
|
|
5
5
|
import { buildRangeCategoryView } from "../common/categories/views/range/utils";
|
|
6
6
|
import { VIEW_KIND } from "../common/categories/views/types";
|
|
7
7
|
import { COLLATOR_CASE_INSENSITIVE } from "../common/constants";
|
|
8
|
+
import { sortCategoryValueViews } from "../common/filters/sort/models/utils";
|
|
8
9
|
/**
|
|
9
10
|
* Build the view-specific model of the given category value.
|
|
10
11
|
* @param categoryValue - The category value to build a view model of.
|
|
@@ -46,9 +47,10 @@ function buildCategoryView(selectCategory, selectCategoryValueViews, categoryCon
|
|
|
46
47
|
* @param categories - Categories, category value and their counts with the current filter applied.
|
|
47
48
|
* @param categoryConfigs - Category configs indicating accept list as well as label configuration.
|
|
48
49
|
* @param filterState - Current set of selected category and category values.
|
|
50
|
+
* @param filterSort - Sort configuration (ALPHA or COUNT).
|
|
49
51
|
* @returns Array of category view objects.
|
|
50
52
|
*/
|
|
51
|
-
export function buildCategoryViews(categories, categoryConfigs, filterState) {
|
|
53
|
+
export function buildCategoryViews(categories, categoryConfigs, filterState, filterSort) {
|
|
52
54
|
if (!categories || !categoryConfigs) {
|
|
53
55
|
return [];
|
|
54
56
|
}
|
|
@@ -64,7 +66,8 @@ export function buildCategoryViews(categories, categoryConfigs, filterState) {
|
|
|
64
66
|
}
|
|
65
67
|
// Build view model for single or multiselect categories.
|
|
66
68
|
const categoryValueViews = category.values.map((categoryValue) => buildCategoryValueView(categoryValue, categorySelectedFilter));
|
|
67
|
-
|
|
69
|
+
// Sort category value views based on filter sort configuration.
|
|
70
|
+
sortCategoryValueViews(categoryValueViews, filterSort);
|
|
68
71
|
// Build category view model.
|
|
69
72
|
return buildCategoryView(category, categoryValueViews, categoryConfigs);
|
|
70
73
|
});
|
|
@@ -156,19 +159,6 @@ function isCategoryValueSelected(categoryValueKey, categorySelectedFilter) {
|
|
|
156
159
|
function isCategoryAcceptListed(category, categoryConfigs) {
|
|
157
160
|
return categoryConfigs.some((categoryConfig) => categoryConfig.key === category.key);
|
|
158
161
|
}
|
|
159
|
-
/**
|
|
160
|
-
* Sort category value views by key, ascending.
|
|
161
|
-
* @param cvv0 - First category value view to compare.
|
|
162
|
-
* @param cvv1 - Second category value view to compare.
|
|
163
|
-
* @returns Number indicating sort precedence of cv0 vs cv1.
|
|
164
|
-
*/
|
|
165
|
-
export function sortCategoryValueViews(cvv0, cvv1) {
|
|
166
|
-
return !cvv0.label
|
|
167
|
-
? 1
|
|
168
|
-
: !cvv1.label
|
|
169
|
-
? -1
|
|
170
|
-
: COLLATOR_CASE_INSENSITIVE.compare(cvv0.label, cvv1.label);
|
|
171
|
-
}
|
|
172
162
|
/**
|
|
173
163
|
* Sort category views by display label, ascending.
|
|
174
164
|
* @param c0 - First category view to compare.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ExploreState } from "../../../exploreState";
|
|
2
|
+
import { UpdateFilterSortPayload } from "./types";
|
|
3
|
+
/**
|
|
4
|
+
* Reducer function to handle the "update filter sort" action.
|
|
5
|
+
* Updates the filter sort in the state for the current entity.
|
|
6
|
+
* @param state - Explore State.
|
|
7
|
+
* @param payload - Payload.
|
|
8
|
+
* @returns explore state.
|
|
9
|
+
*/
|
|
10
|
+
export declare function updateFilterSortAction(state: ExploreState, payload: UpdateFilterSortPayload): ExploreState;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { updateEntityStateByCategoryGroupConfigKey } from "../../utils";
|
|
2
|
+
import { sortCategoryViews } from "./utils";
|
|
3
|
+
/**
|
|
4
|
+
* Reducer function to handle the "update filter sort" action.
|
|
5
|
+
* Updates the filter sort in the state for the current entity.
|
|
6
|
+
* @param state - Explore State.
|
|
7
|
+
* @param payload - Payload.
|
|
8
|
+
* @returns explore state.
|
|
9
|
+
*/
|
|
10
|
+
export function updateFilterSortAction(state, payload) {
|
|
11
|
+
const filterSort = payload;
|
|
12
|
+
// Sort the category views based on the new filter sort.
|
|
13
|
+
const categoryViews = sortCategoryViews(state, filterSort);
|
|
14
|
+
// Update entity state by category group config key
|
|
15
|
+
updateEntityStateByCategoryGroupConfigKey(state, { categoryViews });
|
|
16
|
+
return {
|
|
17
|
+
...state,
|
|
18
|
+
categoryViews,
|
|
19
|
+
filterSort,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { UpdateFilterSortAction, UpdateFilterSortPayload } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* Action creator for updating filter sort in the state.
|
|
4
|
+
* @param payload - Payload.
|
|
5
|
+
* @returns Action with payload and action type.
|
|
6
|
+
*/
|
|
7
|
+
export declare function updateFilterSort(payload: UpdateFilterSortPayload): UpdateFilterSortAction;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { ExploreActionKind } from "../../../exploreState";
|
|
2
|
+
/**
|
|
3
|
+
* Action creator for updating filter sort in the state.
|
|
4
|
+
* @param payload - Payload.
|
|
5
|
+
* @returns Action with payload and action type.
|
|
6
|
+
*/
|
|
7
|
+
export function updateFilterSort(payload) {
|
|
8
|
+
return {
|
|
9
|
+
payload,
|
|
10
|
+
type: ExploreActionKind.UpdateFilterSort,
|
|
11
|
+
};
|
|
12
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { FILTER_SORT } from "../../../../common/filters/sort/config/types";
|
|
2
|
+
import { ExploreActionKind } from "../../../exploreState";
|
|
3
|
+
export type UpdateFilterSortAction = {
|
|
4
|
+
payload: UpdateFilterSortPayload;
|
|
5
|
+
type: ExploreActionKind.UpdateFilterSort;
|
|
6
|
+
};
|
|
7
|
+
export type UpdateFilterSortPayload = FILTER_SORT;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { CategoryView } from "../../../../common/categories/views/types";
|
|
2
|
+
import { FILTER_SORT } from "../../../../common/filters/sort/config/types";
|
|
3
|
+
import { ExploreState } from "../../../exploreState";
|
|
4
|
+
/**
|
|
5
|
+
* Sorts the category views for the current entity type, based on the filter sort.
|
|
6
|
+
* @param state - Explore state.
|
|
7
|
+
* @param filterSort - Filter sort.
|
|
8
|
+
* @returns Sorted category views.
|
|
9
|
+
*/
|
|
10
|
+
export declare function sortCategoryViews(state: ExploreState, filterSort: FILTER_SORT): CategoryView[];
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { isRangeCategory } from "../../../../common/categories/models/range/typeGuards";
|
|
2
|
+
import { sortCategoryValueViews } from "../../../../common/filters/sort/models/utils";
|
|
3
|
+
/**
|
|
4
|
+
* Sorts the category views for the current entity type, based on the filter sort.
|
|
5
|
+
* @param state - Explore state.
|
|
6
|
+
* @param filterSort - Filter sort.
|
|
7
|
+
* @returns Sorted category views.
|
|
8
|
+
*/
|
|
9
|
+
export function sortCategoryViews(state, filterSort) {
|
|
10
|
+
return [...state.categoryViews].map((categoryView) => {
|
|
11
|
+
// Skip range categories.
|
|
12
|
+
if (isRangeCategory(categoryView))
|
|
13
|
+
return categoryView;
|
|
14
|
+
// Use structural clone for select categories that need sorting.
|
|
15
|
+
const nextCategoryView = {
|
|
16
|
+
...categoryView,
|
|
17
|
+
values: [...categoryView.values],
|
|
18
|
+
};
|
|
19
|
+
sortCategoryValueViews(nextCategoryView.values, filterSort);
|
|
20
|
+
return nextCategoryView;
|
|
21
|
+
});
|
|
22
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { FILTER_SORT } from "../../../common/filters/sort/config/types";
|
|
1
2
|
import { SELECT_CATEGORY_KEY } from "../constants";
|
|
2
3
|
export const DEFAULT_CATEGORY_GROUP_SAVED_FILTERS = {
|
|
3
4
|
categoryConfigs: [
|
|
@@ -27,6 +28,7 @@ export const INITIAL_STATE = {
|
|
|
27
28
|
entityStateByCategoryGroupConfigKey: new Map(),
|
|
28
29
|
featureFlagState: undefined,
|
|
29
30
|
filterCount: 0,
|
|
31
|
+
filterSort: FILTER_SORT.ALPHA,
|
|
30
32
|
filterState: [],
|
|
31
33
|
listItems: [],
|
|
32
34
|
loading: true,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getFilterSortType } from "../../../common/filters/sort/config/utils";
|
|
1
2
|
import { getInitialColumnVisibilityState } from "../../../components/TableCreator/options/initialState/columnVisibility";
|
|
2
3
|
import { SELECT_CATEGORY_KEY } from "../constants";
|
|
3
4
|
import { buildNextEntities } from "../entities/state";
|
|
@@ -237,6 +238,7 @@ export function initReducerArguments(config, entityListType, decodedFilterParam,
|
|
|
237
238
|
entityStateByCategoryGroupConfigKey,
|
|
238
239
|
featureFlagState: decodedFeatureFlagParam,
|
|
239
240
|
filterCount: getFilterCount(filterState),
|
|
241
|
+
filterSort: getFilterSortType(config),
|
|
240
242
|
filterState,
|
|
241
243
|
tabValue: entityListType,
|
|
242
244
|
};
|
|
@@ -2,10 +2,12 @@ import React, { Dispatch, ReactNode } from "react";
|
|
|
2
2
|
import { AzulSearchIndex } from "../apis/azul/common/entities";
|
|
3
3
|
import { CategoryView } from "../common/categories/views/types";
|
|
4
4
|
import { SelectedFilter } from "../common/entities";
|
|
5
|
+
import { FILTER_SORT } from "../common/filters/sort/config/types";
|
|
5
6
|
import { RowPreviewState } from "../components/Table/features/RowPreview/entities";
|
|
6
7
|
import { CategoryGroup, SiteConfig } from "../config/entities";
|
|
7
8
|
import { ClearMetaAction } from "./exploreState/actions/clearMeta/types";
|
|
8
9
|
import { StateToUrlAction } from "./exploreState/actions/stateToUrl/types";
|
|
10
|
+
import { UpdateFilterSortAction } from "./exploreState/actions/updateFilterSort/types";
|
|
9
11
|
import { UpdateGroupingAction } from "./exploreState/actions/updateGrouping/types";
|
|
10
12
|
import { UpdateColumnVisibilityAction } from "./exploreState/actions/updateVisibility/types";
|
|
11
13
|
import { UrlToStateAction } from "./exploreState/actions/urlToState/types";
|
|
@@ -32,6 +34,7 @@ export type ExploreState = {
|
|
|
32
34
|
entityStateByCategoryGroupConfigKey: EntityStateByCategoryGroupConfigKey;
|
|
33
35
|
featureFlagState: FeatureFlagState;
|
|
34
36
|
filterCount: number;
|
|
37
|
+
filterSort: FILTER_SORT;
|
|
35
38
|
filterState: SelectedFilter[];
|
|
36
39
|
listItems: ListItems;
|
|
37
40
|
loading: boolean;
|
|
@@ -114,6 +117,7 @@ export declare enum ExploreActionKind {
|
|
|
114
117
|
UpdateEntityFilters = "UPDATE_ENTITY_FILTERS",
|
|
115
118
|
UpdateEntityViewAccess = "UPDATE_ENTITY_VIEW_ACCESS",
|
|
116
119
|
UpdateFilter = "UPDATE_FILTER",
|
|
120
|
+
UpdateFilterSort = "UPDATE_FILTER_SORT",
|
|
117
121
|
UpdateGrouping = "UPDATE_GROUPING",
|
|
118
122
|
UpdateRowPreview = "UPDATE_ROW_PREVIEW",
|
|
119
123
|
UpdateRowSelection = "UPDATE_ROW_SELECTION",
|
|
@@ -123,7 +127,7 @@ export declare enum ExploreActionKind {
|
|
|
123
127
|
/**
|
|
124
128
|
* Explore action.
|
|
125
129
|
*/
|
|
126
|
-
export type ExploreAction = ApplySavedFilterAction | ClearFiltersAction | ClearMetaAction | PaginateTableAction | PatchExploreResponseAction | ProcessExploreResponseAction | ResetExploreResponseAction | ResetStateAction | SelectEntityTypeAction | StateToUrlAction | UpdateColumnVisibilityAction | UpdateEntityFiltersAction | UpdateEntityViewAccessAction | UpdateFilterAction | UpdateGroupingAction | UpdateRowPreviewAction | UpdateRowSelectionAction | UpdateSortingAction | UrlToStateAction;
|
|
130
|
+
export type ExploreAction = ApplySavedFilterAction | ClearFiltersAction | ClearMetaAction | PaginateTableAction | PatchExploreResponseAction | ProcessExploreResponseAction | ResetExploreResponseAction | ResetStateAction | SelectEntityTypeAction | StateToUrlAction | UpdateColumnVisibilityAction | UpdateEntityFiltersAction | UpdateEntityViewAccessAction | UpdateFilterAction | UpdateFilterSortAction | UpdateGroupingAction | UpdateRowPreviewAction | UpdateRowSelectionAction | UpdateSortingAction | UrlToStateAction;
|
|
127
131
|
/**
|
|
128
132
|
* Apply saved filter action.
|
|
129
133
|
*/
|
|
@@ -6,6 +6,7 @@ import { useConfig } from "../hooks/useConfig";
|
|
|
6
6
|
import { useURLFilterParams } from "../hooks/useURLFilterParams";
|
|
7
7
|
import { clearMetaAction } from "./exploreState/actions/clearMeta/action";
|
|
8
8
|
import { stateToUrlAction } from "./exploreState/actions/stateToUrl/action";
|
|
9
|
+
import { updateFilterSortAction } from "./exploreState/actions/updateFilterSort/action";
|
|
9
10
|
import { updateGroupingAction } from "./exploreState/actions/updateGrouping/action";
|
|
10
11
|
import { updateColumnVisibilityAction } from "./exploreState/actions/updateVisibility/action";
|
|
11
12
|
import { urlToStateAction } from "./exploreState/actions/urlToState/action";
|
|
@@ -77,6 +78,7 @@ export var ExploreActionKind;
|
|
|
77
78
|
ExploreActionKind["UpdateEntityFilters"] = "UPDATE_ENTITY_FILTERS";
|
|
78
79
|
ExploreActionKind["UpdateEntityViewAccess"] = "UPDATE_ENTITY_VIEW_ACCESS";
|
|
79
80
|
ExploreActionKind["UpdateFilter"] = "UPDATE_FILTER";
|
|
81
|
+
ExploreActionKind["UpdateFilterSort"] = "UPDATE_FILTER_SORT";
|
|
80
82
|
ExploreActionKind["UpdateGrouping"] = "UPDATE_GROUPING";
|
|
81
83
|
ExploreActionKind["UpdateRowPreview"] = "UPDATE_ROW_PREVIEW";
|
|
82
84
|
ExploreActionKind["UpdateRowSelection"] = "UPDATE_ROW_SELECTION";
|
|
@@ -192,7 +194,7 @@ function exploreReducer(state, action, exploreContext) {
|
|
|
192
194
|
? buildCategoryViews([
|
|
193
195
|
...payload.selectCategories,
|
|
194
196
|
...entityState.savedSelectCategories, // "savedFilter" select categories are built from config at reducer initialization.
|
|
195
|
-
], entityState.categoryConfigs, [...state.filterState, ...entityState.savedFilterState])
|
|
197
|
+
], entityState.categoryConfigs, [...state.filterState, ...entityState.savedFilterState], state.filterSort)
|
|
196
198
|
: state.categoryViews;
|
|
197
199
|
const rowPreview = entityPageState.rowPreview;
|
|
198
200
|
updateEntityStateByCategoryGroupConfigKey(state, {
|
|
@@ -328,6 +330,12 @@ function exploreReducer(state, action, exploreContext) {
|
|
|
328
330
|
rowPreview,
|
|
329
331
|
};
|
|
330
332
|
}
|
|
333
|
+
/**
|
|
334
|
+
* Update filter sort
|
|
335
|
+
*/
|
|
336
|
+
case ExploreActionKind.UpdateFilterSort: {
|
|
337
|
+
return updateFilterSortAction(state, payload);
|
|
338
|
+
}
|
|
331
339
|
/**
|
|
332
340
|
* Update grouping
|
|
333
341
|
**/
|
package/lib/tests/testIds.d.ts
CHANGED
package/lib/tests/testIds.js
CHANGED
|
@@ -9,6 +9,8 @@ export const TEST_IDS = {
|
|
|
9
9
|
FILTER_ITEM: "filter-item",
|
|
10
10
|
FILTER_POPOVER: "filter-popover",
|
|
11
11
|
FILTER_RANGE: "filter-range",
|
|
12
|
+
FILTER_SORT_BUTTON: "filter-sort-button",
|
|
13
|
+
FILTER_SORT_MENU: "filter-sort-menu",
|
|
12
14
|
FILTER_TERM: "filter-term",
|
|
13
15
|
SEARCH_ALL_FILTERS: "search-all-filters",
|
|
14
16
|
SIDEBAR: "sidebar",
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import { Stack } from "@mui/material";
|
|
1
2
|
import React, { useEffect, useMemo } from "react";
|
|
2
3
|
import { track } from "../../common/analytics/analytics";
|
|
3
4
|
import { EVENT_NAME, EVENT_PARAM } from "../../common/analytics/entities";
|
|
4
5
|
import { DrawerProvider } from "../../components/common/Drawer/provider/provider";
|
|
5
6
|
import { ClearAllFilters } from "../../components/Filter/components/ClearAllFilters/clearAllFilters";
|
|
7
|
+
import { FilterSort } from "../../components/Filter/components/controls/Controls/components/FilterSort/filterSort";
|
|
6
8
|
import { Filters, } from "../../components/Filter/components/Filters/filters";
|
|
7
9
|
import { SearchAllFilters } from "../../components/Filter/components/SearchAllFilters/searchAllFilters";
|
|
8
10
|
import { SURFACE_TYPE } from "../../components/Filter/components/surfaces/types";
|
|
@@ -21,6 +23,7 @@ import { stateToUrl } from "../../providers/exploreState/actions/stateToUrl/disp
|
|
|
21
23
|
import { urlToState } from "../../providers/exploreState/actions/urlToState/dispatch";
|
|
22
24
|
import { SELECT_CATEGORY_KEY } from "../../providers/exploreState/constants";
|
|
23
25
|
import { TEST_IDS } from "../../tests/testIds";
|
|
26
|
+
import { useUpdateFilterSort } from "./hooks/UseUpdateFilterSort/hook";
|
|
24
27
|
import { buildStateSyncManagerContext } from "./utils";
|
|
25
28
|
export const ExploreView = (props) => {
|
|
26
29
|
const { mdDown } = useBreakpoint();
|
|
@@ -32,6 +35,7 @@ export const ExploreView = (props) => {
|
|
|
32
35
|
useEntityList(props); // Fetch entities.
|
|
33
36
|
const { entityListType } = props;
|
|
34
37
|
const categoryFilters = useMemo(() => buildCategoryFilters(categoryViews, categoryGroups), [categoryGroups, categoryViews]);
|
|
38
|
+
const { enabled: filterSortEnabled, filterSort, onFilterSortChange, } = useUpdateFilterSort();
|
|
35
39
|
/**
|
|
36
40
|
* State sync manager.
|
|
37
41
|
* Handles state synchronization between the explore state and the URL.
|
|
@@ -98,7 +102,9 @@ export const ExploreView = (props) => {
|
|
|
98
102
|
categoryViews && !!categoryViews.length && (React.createElement(Sidebar, null,
|
|
99
103
|
React.createElement(SidebarTools, { "data-testid": TEST_IDS.FILTER_CONTROLS },
|
|
100
104
|
React.createElement(SidebarLabel, { label: "Filters" }),
|
|
101
|
-
React.createElement(
|
|
105
|
+
React.createElement(Stack, { direction: "row", gap: 4 },
|
|
106
|
+
React.createElement(ClearAllFilters, null),
|
|
107
|
+
React.createElement(FilterSort, { enabled: filterSortEnabled, filterSort: filterSort, onFilterSortChange: onFilterSortChange })),
|
|
102
108
|
React.createElement(SearchAllFilters, { categoryViews: categoryViews, onFilter: onFilterChange.bind(null, true), surfaceType: mdDown ? SURFACE_TYPE.POPPER_DRAWER : SURFACE_TYPE.POPPER_MENU })),
|
|
103
109
|
React.createElement(Filters, { categoryFilters: categoryFilters, onFilter: onFilterChange.bind(null, false), surfaceType: mdDown ? SURFACE_TYPE.DRAWER : SURFACE_TYPE.MENU, trackFilterOpened: trackingConfig?.trackFilterOpened }))),
|
|
104
110
|
React.createElement(IndexView, { className: props.className, categoryFilters: categoryFilters, entityListType: entityListType, entityName: label, loading: loading })));
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { useCallback } from "react";
|
|
2
|
+
import { useConfig } from "../../../../hooks/useConfig";
|
|
3
|
+
import { useExploreState } from "../../../../hooks/useExploreState";
|
|
4
|
+
import { updateFilterSort } from "../../../../providers/exploreState/actions/updateFilterSort/dispatch";
|
|
5
|
+
export const useUpdateFilterSort = () => {
|
|
6
|
+
const { config } = useConfig();
|
|
7
|
+
const { exploreDispatch, exploreState } = useExploreState();
|
|
8
|
+
const { filterSort } = exploreState;
|
|
9
|
+
const enabled = Boolean(config.filterSort?.sortBy);
|
|
10
|
+
const onFilterSortChange = useCallback((filterSort) => exploreDispatch(updateFilterSort(filterSort)), [exploreDispatch]);
|
|
11
|
+
return { enabled, filterSort, onFilterSortChange };
|
|
12
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { SiteConfig } from "../../../../config/entities";
|
|
2
|
+
import { FILTER_SORT } from "./types";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Returns the default filter sort type "ALPHA" or "COUNT" from config or ALPHA as fallback.
|
|
6
|
+
* @param config - Filter sort configuration.
|
|
7
|
+
* @returns default filter sort type.
|
|
8
|
+
*/
|
|
9
|
+
export function getFilterSortType(config?: SiteConfig): FILTER_SORT {
|
|
10
|
+
return config?.filterSort?.sortBy ?? FILTER_SORT.ALPHA;
|
|
11
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { COLLATOR_CASE_INSENSITIVE } from "../../../constants";
|
|
2
|
+
import { SelectCategoryValueView } from "../../../entities";
|
|
3
|
+
import { FILTER_SORT } from "../config/types";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Sort category value views based on filter sort configuration.
|
|
7
|
+
* Uses function selection pattern for efficiency.
|
|
8
|
+
* @param categoryValueViews - Array of category value views to sort.
|
|
9
|
+
* @param filterSort - Sort configuration (ALPHA or COUNT).
|
|
10
|
+
*/
|
|
11
|
+
export function sortCategoryValueViews(
|
|
12
|
+
categoryValueViews: SelectCategoryValueView[],
|
|
13
|
+
filterSort: FILTER_SORT
|
|
14
|
+
): void {
|
|
15
|
+
const sortFn =
|
|
16
|
+
filterSort === FILTER_SORT.ALPHA
|
|
17
|
+
? sortCategoryValueViewsAlpha
|
|
18
|
+
: sortCategoryValueViewsCount;
|
|
19
|
+
|
|
20
|
+
categoryValueViews.sort(sortFn);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Sort category value views alphabetically.
|
|
25
|
+
* @param cvv0 - First category value view to compare.
|
|
26
|
+
* @param cvv1 - Second category value view to compare.
|
|
27
|
+
* @returns Number indicating sort precedence of cvv0 vs cvv1.
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
export function sortCategoryValueViewsAlpha(
|
|
31
|
+
cvv0: SelectCategoryValueView,
|
|
32
|
+
cvv1: SelectCategoryValueView
|
|
33
|
+
): number {
|
|
34
|
+
// Handle empty labels.
|
|
35
|
+
if (!cvv0.label) return 1;
|
|
36
|
+
if (!cvv1.label) return -1;
|
|
37
|
+
|
|
38
|
+
return COLLATOR_CASE_INSENSITIVE.compare(cvv0.label, cvv1.label);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Sort category value views by count (descending), then alphabetically.
|
|
43
|
+
* @param cvv0 - First category value view to compare.
|
|
44
|
+
* @param cvv1 - Second category value view to compare.
|
|
45
|
+
* @returns Number indicating sort precedence of cvv0 vs cvv1.
|
|
46
|
+
*/
|
|
47
|
+
export function sortCategoryValueViewsCount(
|
|
48
|
+
cvv0: SelectCategoryValueView,
|
|
49
|
+
cvv1: SelectCategoryValueView
|
|
50
|
+
): number {
|
|
51
|
+
// Sort by count descending, then alphabetically.
|
|
52
|
+
const countDiff = cvv1.count - cvv0.count;
|
|
53
|
+
|
|
54
|
+
if (countDiff !== 0) return countDiff;
|
|
55
|
+
|
|
56
|
+
return sortCategoryValueViewsAlpha(cvv0, cvv1);
|
|
57
|
+
}
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
ClearAll,
|
|
9
9
|
} from "../../../../../../common/entities";
|
|
10
10
|
import { updater } from "../../../../../Table/components/TableFeatures/ColumnFilter/utils";
|
|
11
|
+
import { useUpdateFilterSort } from "./hooks/UseUpdateFilterSort/hook";
|
|
11
12
|
import { ColumnFiltersAdapterProps } from "./types";
|
|
12
13
|
import { buildColumnFilters, getColumnFiltersCount } from "./utils";
|
|
13
14
|
|
|
@@ -15,7 +16,13 @@ export const ColumnFiltersAdapter = <T extends RowData>({
|
|
|
15
16
|
renderSurface,
|
|
16
17
|
table,
|
|
17
18
|
}: ColumnFiltersAdapterProps<T>): JSX.Element | null => {
|
|
18
|
-
const
|
|
19
|
+
const {
|
|
20
|
+
enabled: filterSortEnabled,
|
|
21
|
+
filterSort,
|
|
22
|
+
onFilterSortChange,
|
|
23
|
+
} = useUpdateFilterSort(table);
|
|
24
|
+
|
|
25
|
+
const categoryFilters = buildColumnFilters(table, filterSort);
|
|
19
26
|
const count = getColumnFiltersCount(table);
|
|
20
27
|
|
|
21
28
|
const onFilter = useCallback(
|
|
@@ -50,6 +57,9 @@ export const ColumnFiltersAdapter = <T extends RowData>({
|
|
|
50
57
|
return renderSurface({
|
|
51
58
|
categoryFilters,
|
|
52
59
|
count,
|
|
60
|
+
filterSort,
|
|
61
|
+
filterSortEnabled,
|
|
53
62
|
onFilter,
|
|
63
|
+
onFilterSortChange,
|
|
54
64
|
});
|
|
55
65
|
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { RowData, Table } from "@tanstack/react-table";
|
|
2
|
+
import { useCallback, useMemo, useState } from "react";
|
|
3
|
+
import { FILTER_SORT } from "../../../../../../../../common/filters/sort/config/types";
|
|
4
|
+
import { UseUpdateFilterSort } from "./types";
|
|
5
|
+
import { initFilterSort, isFilterSortEnabled } from "./utils";
|
|
6
|
+
|
|
7
|
+
export const useUpdateFilterSort = <T extends RowData>(
|
|
8
|
+
table: Table<T>
|
|
9
|
+
): UseUpdateFilterSort => {
|
|
10
|
+
const [filterSort, setFilterSort] = useState<FILTER_SORT>(
|
|
11
|
+
initFilterSort(table)
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
const enabled = useMemo(() => isFilterSortEnabled(table), [table]);
|
|
15
|
+
|
|
16
|
+
const onFilterSortChange = useCallback(
|
|
17
|
+
(value: FILTER_SORT) => setFilterSort(value),
|
|
18
|
+
[]
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
return { enabled, filterSort, onFilterSortChange };
|
|
22
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { RowData, Table } from "@tanstack/react-table";
|
|
2
|
+
import { FILTER_SORT } from "../../../../../../../../common/filters/sort/config/types";
|
|
3
|
+
import { ColumnFiltersTableMeta } from "../../types";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Returns the default filter sort type "ALPHA" or "COUNT" from table meta or ALPHA as fallback.
|
|
7
|
+
* @param table - Table.
|
|
8
|
+
* @returns default filter sort type.
|
|
9
|
+
*/
|
|
10
|
+
export function initFilterSort<T extends RowData>(
|
|
11
|
+
table: Table<T>
|
|
12
|
+
): FILTER_SORT {
|
|
13
|
+
const { options } = table;
|
|
14
|
+
const { meta = {} } = options;
|
|
15
|
+
const { filterSort } = meta as ColumnFiltersTableMeta<T>;
|
|
16
|
+
|
|
17
|
+
return filterSort || FILTER_SORT.ALPHA;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Returns true if filter sort is enabled.
|
|
22
|
+
* @param table - Table.
|
|
23
|
+
* @returns true if filter sort is enabled.
|
|
24
|
+
*/
|
|
25
|
+
export function isFilterSortEnabled<T extends RowData>(
|
|
26
|
+
table: Table<T>
|
|
27
|
+
): boolean {
|
|
28
|
+
const { options } = table;
|
|
29
|
+
const { meta = {} } = options;
|
|
30
|
+
const { filterSort } = meta as ColumnFiltersTableMeta<T>;
|
|
31
|
+
|
|
32
|
+
return Boolean(filterSort);
|
|
33
|
+
}
|
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
Table,
|
|
4
4
|
TableMeta as TanStackTableMeta,
|
|
5
5
|
} from "@tanstack/react-table";
|
|
6
|
+
import { FILTER_SORT } from "../../../../../../common/filters/sort/config/types";
|
|
6
7
|
import { CategoryGroup } from "../../../../../../config/entities";
|
|
7
8
|
import { SurfaceProps } from "../../../surfaces/types";
|
|
8
9
|
|
|
@@ -13,4 +14,5 @@ export interface ColumnFiltersAdapterProps<T extends RowData> {
|
|
|
13
14
|
export interface ColumnFiltersTableMeta<T extends RowData>
|
|
14
15
|
extends TanStackTableMeta<T> {
|
|
15
16
|
categoryGroups?: CategoryGroup[];
|
|
17
|
+
filterSort?: FILTER_SORT;
|
|
16
18
|
}
|