@devtron-labs/devtron-fe-common-lib 0.0.62-beta-4 → 0.0.62-beta-5
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/dist/Common/DraggableWrapper/types.d.ts +4 -1
- package/dist/Common/Hooks/useUrlFilters/index.d.ts +1 -1
- package/dist/Common/Hooks/useUrlFilters/types.d.ts +54 -1
- package/dist/Common/Hooks/useUrlFilters/useUrlFilters.d.ts +2 -14
- package/dist/Pages/GlobalConfigurations/Authorization/constants.d.ts +5 -1
- package/dist/Pages/GlobalConfigurations/Authorization/index.d.ts +1 -0
- package/dist/Pages/GlobalConfigurations/Authorization/types.d.ts +23 -0
- package/dist/Shared/Components/BulkSelection/types.d.ts +2 -0
- package/dist/Shared/Components/FilterChips/FilterChips.component.d.ts +7 -0
- package/dist/Shared/Components/FilterChips/index.d.ts +2 -0
- package/dist/Shared/Components/FilterChips/types.d.ts +37 -0
- package/dist/Shared/Components/index.d.ts +1 -0
- package/dist/index.js +90 -26
- package/package.json +1 -1
- package/src/Common/DraggableWrapper/types.ts +4 -1
- package/src/Common/Helper.tsx +7 -1
- package/src/Common/Hooks/useUrlFilters/index.ts +1 -1
- package/src/Common/Hooks/useUrlFilters/types.ts +56 -1
- package/src/Common/Hooks/useUrlFilters/useUrlFilters.ts +28 -6
- package/src/Pages/GlobalConfigurations/Authorization/constants.ts +6 -1
- package/src/Pages/GlobalConfigurations/Authorization/index.ts +1 -0
- package/src/Pages/GlobalConfigurations/Authorization/types.ts +25 -0
- package/src/Shared/Components/BulkSelection/BulkSelection.tsx +2 -2
- package/src/Shared/Components/BulkSelection/BulkSelectionProvider.tsx +16 -5
- package/src/Shared/Components/BulkSelection/types.tsx +2 -0
- package/src/Shared/Components/FilterChips/FilterChips.component.tsx +100 -0
- package/src/Shared/Components/FilterChips/index.ts +2 -0
- package/src/Shared/Components/FilterChips/types.ts +39 -0
- package/src/Shared/Components/index.ts +1 -0
|
@@ -5,7 +5,10 @@ export declare enum DraggablePositionVariant {
|
|
|
5
5
|
}
|
|
6
6
|
export interface DraggableWrapperProps {
|
|
7
7
|
children: ReactNode;
|
|
8
|
-
|
|
8
|
+
/**
|
|
9
|
+
* Support for passing the direct value or calc functions as well
|
|
10
|
+
*/
|
|
11
|
+
zIndex?: number | string;
|
|
9
12
|
positionVariant?: DraggablePositionVariant;
|
|
10
13
|
/**
|
|
11
14
|
* dragSelector (class - (append with .), id, etc) will be used to identify the grabbable button that will grab the div to drag
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { default as useUrlFilters } from './useUrlFilters';
|
|
2
|
-
export type { UseUrlFiltersProps } from './types';
|
|
2
|
+
export type { UseUrlFiltersProps, UseUrlFiltersReturnType } from './types';
|
|
@@ -1,6 +1,59 @@
|
|
|
1
|
-
|
|
1
|
+
import { SortingOrder } from '../../Constants';
|
|
2
|
+
export interface UseUrlFiltersProps<T, K> {
|
|
2
3
|
/**
|
|
3
4
|
* The key on which the sorting should be applied
|
|
4
5
|
*/
|
|
5
6
|
initialSortKey?: T;
|
|
7
|
+
/**
|
|
8
|
+
* Callback function for parsing the search params
|
|
9
|
+
*/
|
|
10
|
+
parseSearchParams?: (searchParams: URLSearchParams) => K;
|
|
6
11
|
}
|
|
12
|
+
export type UseUrlFiltersReturnType<T, K = unknown> = K & {
|
|
13
|
+
/**
|
|
14
|
+
* Currently applied page size
|
|
15
|
+
*/
|
|
16
|
+
pageSize: number;
|
|
17
|
+
/**
|
|
18
|
+
* Handler for updating the current page
|
|
19
|
+
*/
|
|
20
|
+
changePage: (pageNumber: number) => void;
|
|
21
|
+
/**
|
|
22
|
+
* Handler for updating the current page size
|
|
23
|
+
*/
|
|
24
|
+
changePageSize: (pageSize: number) => void;
|
|
25
|
+
/**
|
|
26
|
+
* Current search key
|
|
27
|
+
*/
|
|
28
|
+
searchKey: string;
|
|
29
|
+
/**
|
|
30
|
+
* Handler for updating the search
|
|
31
|
+
*/
|
|
32
|
+
handleSearch: (searchKey: string) => void;
|
|
33
|
+
/**
|
|
34
|
+
* Computed offset using the pageSize and pageNumber
|
|
35
|
+
*
|
|
36
|
+
* Note: Used in pagination component
|
|
37
|
+
*/
|
|
38
|
+
offset: number;
|
|
39
|
+
/**
|
|
40
|
+
* Key on which the sorting is applied
|
|
41
|
+
*/
|
|
42
|
+
sortBy: T;
|
|
43
|
+
/**
|
|
44
|
+
* Current sort order
|
|
45
|
+
*/
|
|
46
|
+
sortOrder: SortingOrder;
|
|
47
|
+
/**
|
|
48
|
+
* Handle the sorting type change / key change
|
|
49
|
+
*/
|
|
50
|
+
handleSorting: (sortBy: T) => void;
|
|
51
|
+
/**
|
|
52
|
+
* Clear all the applied filters
|
|
53
|
+
*/
|
|
54
|
+
clearFilters: () => void;
|
|
55
|
+
/**
|
|
56
|
+
* Update the search params with the passed object
|
|
57
|
+
*/
|
|
58
|
+
updateSearchParams: (paramsToSerialize: K) => void;
|
|
59
|
+
};
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { UseUrlFiltersProps } from './types';
|
|
1
|
+
import { UseUrlFiltersProps, UseUrlFiltersReturnType } from './types';
|
|
3
2
|
/**
|
|
4
3
|
* Generic hook for implementing URL based filters.
|
|
5
4
|
* eg: pagination, search, sort.
|
|
@@ -17,16 +16,5 @@ import { UseUrlFiltersProps } from './types';
|
|
|
17
16
|
* ```
|
|
18
17
|
*
|
|
19
18
|
*/
|
|
20
|
-
declare const useUrlFilters: <T = string>({ initialSortKey }?: UseUrlFiltersProps<T>) =>
|
|
21
|
-
pageSize: number;
|
|
22
|
-
changePage: (page: number) => void;
|
|
23
|
-
changePageSize: (_pageSize: number) => void;
|
|
24
|
-
searchKey: string;
|
|
25
|
-
handleSearch: (searchTerm: string) => void;
|
|
26
|
-
offset: number;
|
|
27
|
-
sortBy: T;
|
|
28
|
-
sortOrder: SortingOrder;
|
|
29
|
-
handleSorting: (_sortBy: T) => void;
|
|
30
|
-
clearFilters: () => void;
|
|
31
|
-
};
|
|
19
|
+
declare const useUrlFilters: <T = string, K = unknown>({ initialSortKey, parseSearchParams, }?: UseUrlFiltersProps<T, K>) => UseUrlFiltersReturnType<T, K>;
|
|
32
20
|
export default useUrlFilters;
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
export declare enum UserListSortableKeys {
|
|
2
|
+
email = "email_id",
|
|
3
|
+
lastLogin = "last_login"
|
|
4
|
+
}
|
|
1
5
|
/**
|
|
2
6
|
* User Status received from the API
|
|
3
7
|
*/
|
|
@@ -11,5 +15,5 @@ export declare enum UserStatusDto {
|
|
|
11
15
|
export declare enum UserStatus {
|
|
12
16
|
active = "active",
|
|
13
17
|
inactive = "inactive",
|
|
14
|
-
temporary = "
|
|
18
|
+
temporary = "temporaryAccess"
|
|
15
19
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { SortingParams } from '../../../Common';
|
|
2
|
+
import { UserListSortableKeys, UserStatus } from './constants';
|
|
3
|
+
export type BaseFilterQueryParams<T> = {
|
|
4
|
+
/**
|
|
5
|
+
* Offset for the list result
|
|
6
|
+
*/
|
|
7
|
+
offset?: number;
|
|
8
|
+
/**
|
|
9
|
+
* Number of items required in the list
|
|
10
|
+
*/
|
|
11
|
+
size?: number;
|
|
12
|
+
/**
|
|
13
|
+
* Search string (if any)
|
|
14
|
+
*/
|
|
15
|
+
searchKey?: string;
|
|
16
|
+
/**
|
|
17
|
+
* If true, all items are returned with any search / filtering applied without pagination
|
|
18
|
+
*/
|
|
19
|
+
showAll?: boolean;
|
|
20
|
+
} & SortingParams<T>;
|
|
21
|
+
export type UserListFilterParams = BaseFilterQueryParams<UserListSortableKeys> & {
|
|
22
|
+
status: UserStatus[];
|
|
23
|
+
};
|
|
@@ -23,6 +23,8 @@ export interface GetBulkSelectionCheckboxValuesType {
|
|
|
23
23
|
export interface UseBulkSelectionReturnType<T> extends GetBulkSelectionCheckboxValuesType {
|
|
24
24
|
selectedIdentifiers: T;
|
|
25
25
|
handleBulkSelection: ({ action, data }: HandleBulkSelectionType<T>) => void;
|
|
26
|
+
isBulkSelectionApplied: boolean;
|
|
27
|
+
getSelectedIdentifiersCount: () => number;
|
|
26
28
|
}
|
|
27
29
|
export interface BulkSelectionProps {
|
|
28
30
|
showPagination: boolean;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { FilterChipsProps } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* Component for rendering the applied filter chips
|
|
5
|
+
*/
|
|
6
|
+
declare const FilterChips: ({ filterConfig, clearFilters, onRemoveFilter, getFormattedLabel, getFormattedValue, }: FilterChipsProps) => JSX.Element;
|
|
7
|
+
export default FilterChips;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
export interface FilterChipProps {
|
|
3
|
+
/**
|
|
4
|
+
* Filter label
|
|
5
|
+
*/
|
|
6
|
+
label: string;
|
|
7
|
+
/**
|
|
8
|
+
* Corresponding value of the filter
|
|
9
|
+
*/
|
|
10
|
+
value: unknown;
|
|
11
|
+
/**
|
|
12
|
+
* Callback handler for removing the filter
|
|
13
|
+
*/
|
|
14
|
+
handleRemoveFilter: (label: string, valueToRemove: unknown) => void;
|
|
15
|
+
/**
|
|
16
|
+
* If passed, the label will be formatted accordingly
|
|
17
|
+
*/
|
|
18
|
+
getFormattedLabel?: (filterKey: string) => ReactNode;
|
|
19
|
+
/**
|
|
20
|
+
* If passed, the label will be formatted accordingly
|
|
21
|
+
*/
|
|
22
|
+
getFormattedValue?: (filterKey: string, filterValue: unknown) => ReactNode;
|
|
23
|
+
}
|
|
24
|
+
export interface FilterChipsProps extends Pick<FilterChipProps, 'getFormattedLabel' | 'getFormattedValue'> {
|
|
25
|
+
/**
|
|
26
|
+
* Current filter configuration
|
|
27
|
+
*/
|
|
28
|
+
filterConfig: Record<string, unknown>;
|
|
29
|
+
/**
|
|
30
|
+
* Callback handler for removing the filters
|
|
31
|
+
*/
|
|
32
|
+
clearFilters: () => void;
|
|
33
|
+
/**
|
|
34
|
+
* Handler for removing a applied filter
|
|
35
|
+
*/
|
|
36
|
+
onRemoveFilter: (filterConfig: Record<string, unknown>) => void;
|
|
37
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -11811,7 +11811,14 @@ var getUrlWithSearchParams = function (url, params) {
|
|
|
11811
11811
|
var searchParams = new URLSearchParams();
|
|
11812
11812
|
Object.keys(params).forEach(function (key) {
|
|
11813
11813
|
if (params[key]) {
|
|
11814
|
-
|
|
11814
|
+
if (Array.isArray(params[key])) {
|
|
11815
|
+
params[key].forEach(function (val) {
|
|
11816
|
+
searchParams.append(key, val);
|
|
11817
|
+
});
|
|
11818
|
+
}
|
|
11819
|
+
else {
|
|
11820
|
+
searchParams.set(key, params[key]);
|
|
11821
|
+
}
|
|
11815
11822
|
}
|
|
11816
11823
|
});
|
|
11817
11824
|
var queryString = searchParams.toString();
|
|
@@ -25686,7 +25693,7 @@ var PAGE_SIZE = URL_FILTER_KEYS.PAGE_SIZE, PAGE_NUMBER = URL_FILTER_KEYS.PAGE_NU
|
|
|
25686
25693
|
*
|
|
25687
25694
|
*/
|
|
25688
25695
|
var useUrlFilters = function (_a) {
|
|
25689
|
-
var _b = _a === void 0 ? {} : _a, initialSortKey = _b.initialSortKey;
|
|
25696
|
+
var _b = _a === void 0 ? {} : _a, initialSortKey = _b.initialSortKey, parseSearchParams = _b.parseSearchParams;
|
|
25690
25697
|
var location = reactRouterDom.useLocation();
|
|
25691
25698
|
var history = reactRouterDom.useHistory();
|
|
25692
25699
|
var searchParams = new URLSearchParams(location.search);
|
|
@@ -25699,6 +25706,7 @@ var useUrlFilters = function (_a) {
|
|
|
25699
25706
|
var sortByKey = (_sortBy || initialSortKey || '');
|
|
25700
25707
|
// Fallback to ascending order
|
|
25701
25708
|
var sortByOrder = Object.values(exports.SortingOrder).includes(_sortOrder) ? _sortOrder : exports.SortingOrder.ASC;
|
|
25709
|
+
var _parsedParams = parseSearchParams ? parseSearchParams(searchParams) : {};
|
|
25702
25710
|
return {
|
|
25703
25711
|
pageSize: Number(_pageSize) || DEFAULT_BASE_PAGE_SIZE,
|
|
25704
25712
|
pageNumber: Number(_pageNumber) || DEFAULT_PAGE_NUMBER,
|
|
@@ -25706,8 +25714,9 @@ var useUrlFilters = function (_a) {
|
|
|
25706
25714
|
sortBy: sortByKey,
|
|
25707
25715
|
// sort order should only be applied if the key is available
|
|
25708
25716
|
sortOrder: (sortByKey ? sortByOrder : ''),
|
|
25717
|
+
parsedParams: _parsedParams,
|
|
25709
25718
|
};
|
|
25710
|
-
}, [searchParams]), pageSize = _c.pageSize, pageNumber = _c.pageNumber, searchKey = _c.searchKey, sortBy = _c.sortBy, sortOrder = _c.sortOrder;
|
|
25719
|
+
}, [searchParams]), pageSize = _c.pageSize, pageNumber = _c.pageNumber, searchKey = _c.searchKey, sortBy = _c.sortBy, sortOrder = _c.sortOrder, parsedParams = _c.parsedParams;
|
|
25711
25720
|
/**
|
|
25712
25721
|
* Used for getting the required result from the API
|
|
25713
25722
|
*/
|
|
@@ -25749,23 +25758,26 @@ var useUrlFilters = function (_a) {
|
|
|
25749
25758
|
_resetPageNumber();
|
|
25750
25759
|
};
|
|
25751
25760
|
var clearFilters = function () {
|
|
25752
|
-
|
|
25753
|
-
searchParams.delete(key);
|
|
25754
|
-
});
|
|
25755
|
-
history.replace({ search: searchParams.toString() });
|
|
25761
|
+
history.replace({ search: '' });
|
|
25756
25762
|
};
|
|
25757
|
-
|
|
25758
|
-
|
|
25759
|
-
|
|
25760
|
-
|
|
25761
|
-
|
|
25762
|
-
|
|
25763
|
-
|
|
25764
|
-
|
|
25765
|
-
|
|
25766
|
-
|
|
25767
|
-
|
|
25763
|
+
var updateSearchParams = function (paramsToSerialize) {
|
|
25764
|
+
Object.keys(paramsToSerialize).forEach(function (key) {
|
|
25765
|
+
if (paramsToSerialize[key]) {
|
|
25766
|
+
if (Array.isArray(paramsToSerialize[key])) {
|
|
25767
|
+
searchParams.delete(key);
|
|
25768
|
+
paramsToSerialize[key].forEach(function (val) {
|
|
25769
|
+
searchParams.append(key, val);
|
|
25770
|
+
});
|
|
25771
|
+
}
|
|
25772
|
+
else {
|
|
25773
|
+
searchParams.set(key, paramsToSerialize[key]);
|
|
25774
|
+
}
|
|
25775
|
+
}
|
|
25776
|
+
});
|
|
25777
|
+
// Not replacing the params as it is being done by _resetPageNumber
|
|
25778
|
+
_resetPageNumber();
|
|
25768
25779
|
};
|
|
25780
|
+
return __assign(__assign({ pageSize: pageSize, changePage: changePage, changePageSize: changePageSize, searchKey: searchKey, handleSearch: handleSearch, offset: offset, sortBy: sortBy, sortOrder: sortOrder, handleSorting: handleSorting, clearFilters: clearFilters }, parsedParams), { updateSearchParams: updateSearchParams });
|
|
25769
25781
|
};
|
|
25770
25782
|
|
|
25771
25783
|
var StatusConstants = {
|
|
@@ -29462,6 +29474,8 @@ var BulkSelectionContext = React.createContext({
|
|
|
29462
29474
|
handleBulkSelection: noop$1,
|
|
29463
29475
|
isChecked: false,
|
|
29464
29476
|
checkboxValue: exports.CHECKBOX_VALUE.CHECKED,
|
|
29477
|
+
isBulkSelectionApplied: false,
|
|
29478
|
+
getSelectedIdentifiersCount: noop$1,
|
|
29465
29479
|
});
|
|
29466
29480
|
var useBulkSelection = function () {
|
|
29467
29481
|
var context = React.useContext(BulkSelectionContext);
|
|
@@ -29473,6 +29487,8 @@ var useBulkSelection = function () {
|
|
|
29473
29487
|
var BulkSelectionProvider = function (_a) {
|
|
29474
29488
|
var children = _a.children, identifiers = _a.identifiers, getSelectAllDialogStatus = _a.getSelectAllDialogStatus;
|
|
29475
29489
|
var _b = __read(React.useState({}), 2), selectedIdentifiers = _b[0], setSelectedIdentifiers = _b[1];
|
|
29490
|
+
var isBulkSelectionApplied = selectedIdentifiers[SELECT_ALL_ACROSS_PAGES_LOCATOR];
|
|
29491
|
+
var getSelectedIdentifiersCount = function () { return Object.keys(selectedIdentifiers).length; };
|
|
29476
29492
|
var setIdentifiersAfterClear = function (newIdentifiers, selectedIds) {
|
|
29477
29493
|
var _newIdentifiers = JSON.parse(JSON.stringify(newIdentifiers));
|
|
29478
29494
|
selectedIds.forEach(function (id) {
|
|
@@ -29483,7 +29499,7 @@ var BulkSelectionProvider = function (_a) {
|
|
|
29483
29499
|
var setIdentifiersAfterPageSelection = function (baseObject) {
|
|
29484
29500
|
var _selectedIdentifiers = JSON.parse(JSON.stringify(selectedIdentifiers));
|
|
29485
29501
|
// removing bulk selection across pages if present
|
|
29486
|
-
if (
|
|
29502
|
+
if (isBulkSelectionApplied) {
|
|
29487
29503
|
delete _selectedIdentifiers[SELECT_ALL_ACROSS_PAGES_LOCATOR];
|
|
29488
29504
|
}
|
|
29489
29505
|
setSelectedIdentifiers(__assign(__assign({}, _selectedIdentifiers), baseObject));
|
|
@@ -29508,10 +29524,13 @@ var BulkSelectionProvider = function (_a) {
|
|
|
29508
29524
|
break;
|
|
29509
29525
|
}
|
|
29510
29526
|
case exports.BulkSelectionEvents.SELECT_ALL_ACROSS_PAGES: {
|
|
29511
|
-
if (
|
|
29527
|
+
if (isBulkSelectionApplied) {
|
|
29512
29528
|
return;
|
|
29513
29529
|
}
|
|
29514
|
-
var selectedIdentifiersLength =
|
|
29530
|
+
var selectedIdentifiersLength = getSelectedIdentifiersCount();
|
|
29531
|
+
// This is for showing a modal dialog if applicable to confirm if bulk selection is to be applied
|
|
29532
|
+
// Do note that the 'getSelectAllDialogStatus' should be called after the length check explicitly
|
|
29533
|
+
// otherwise the modal will open each time
|
|
29515
29534
|
if (selectedIdentifiersLength > 0 && getSelectAllDialogStatus() === exports.SelectAllDialogStatus.OPEN) {
|
|
29516
29535
|
return;
|
|
29517
29536
|
}
|
|
@@ -29549,7 +29568,7 @@ var BulkSelectionProvider = function (_a) {
|
|
|
29549
29568
|
};
|
|
29550
29569
|
}
|
|
29551
29570
|
// if selectedIdentifiers contains select all across pages locator then it means all are selected
|
|
29552
|
-
if (
|
|
29571
|
+
if (isBulkSelectionApplied) {
|
|
29553
29572
|
return {
|
|
29554
29573
|
isChecked: true,
|
|
29555
29574
|
checkboxValue: exports.CHECKBOX_VALUE.BULK_CHECKED,
|
|
@@ -29574,7 +29593,9 @@ var BulkSelectionProvider = function (_a) {
|
|
|
29574
29593
|
handleBulkSelection: handleBulkSelection,
|
|
29575
29594
|
isChecked: isChecked,
|
|
29576
29595
|
checkboxValue: checkboxValue,
|
|
29577
|
-
|
|
29596
|
+
isBulkSelectionApplied: isBulkSelectionApplied,
|
|
29597
|
+
getSelectedIdentifiersCount: getSelectedIdentifiersCount,
|
|
29598
|
+
}); }, [selectedIdentifiers, handleBulkSelection, isChecked, checkboxValue, getSelectedIdentifiersCount]);
|
|
29578
29599
|
return jsxRuntime.jsx(BulkSelectionContext.Provider, __assign({ value: value }, { children: children }));
|
|
29579
29600
|
};
|
|
29580
29601
|
|
|
@@ -29656,8 +29677,8 @@ var SvgIcClose = function SvgIcClose(props) {
|
|
|
29656
29677
|
|
|
29657
29678
|
var BulkSelection = function (_a) {
|
|
29658
29679
|
var showPagination = _a.showPagination;
|
|
29659
|
-
var _b = useBulkSelection(), handleBulkSelection = _b.handleBulkSelection,
|
|
29660
|
-
var areOptionsSelected =
|
|
29680
|
+
var _b = useBulkSelection(), handleBulkSelection = _b.handleBulkSelection, isChecked = _b.isChecked, checkboxValue = _b.checkboxValue, getSelectedIdentifiersCount = _b.getSelectedIdentifiersCount;
|
|
29681
|
+
var areOptionsSelected = getSelectedIdentifiersCount() > 0;
|
|
29661
29682
|
var BulkSelectionItems = __spreadArray(__spreadArray([
|
|
29662
29683
|
{
|
|
29663
29684
|
locator: exports.BulkSelectionEvents.SELECT_ALL_ON_PAGE,
|
|
@@ -29687,6 +29708,43 @@ var BulkSelection = function (_a) {
|
|
|
29687
29708
|
return (jsxRuntime.jsxs(PopupMenu, __assign({ autoClose: true }, { children: [jsxRuntime.jsxs(PopupMenu.Button, __assign({ isKebab: true, rootClassName: "h-20 flexbox p-0 dc__no-background dc__no-border dc__outline-none-imp", dataTestId: BULK_DROPDOWN_TEST_ID }, { children: [jsxRuntime.jsx(Checkbox$1, { isChecked: isChecked, onChange: noop$1, rootClassName: "icon-dim-20 m-0", value: checkboxValue }), jsxRuntime.jsx(SvgIcChevronDown, { className: "icon-dim-20 fcn-6 dc__no-shrink" })] })), jsxRuntime.jsx(PopupMenu.Body, __assign({ rootClassName: "dc__top-22 w-150 dc__right-0 pt-4 pb-4 pl-0 pr-0 bcn-0 flex column dc__content-start dc__align-start dc__position-abs bcn-0 dc__border dc__border-radius-4-imp" }, { children: BulkSelectionItems.map(function (item) { return (jsxRuntime.jsx(BulkSelectionDropdownItems, { locator: item.locator, label: item.label, isSelected: item.isSelected, icon: item.icon, handleBulkSelection: handleBulkSelection }, item.locator)); }) }))] })));
|
|
29688
29709
|
};
|
|
29689
29710
|
|
|
29711
|
+
var FilterChip = function (_a) {
|
|
29712
|
+
var _b, _c;
|
|
29713
|
+
var label = _a.label, value = _a.value, handleRemoveFilter = _a.handleRemoveFilter, _d = _a.getFormattedLabel, getFormattedLabel = _d === void 0 ? noop$1 : _d, _e = _a.getFormattedValue, getFormattedValue = _e === void 0 ? noop$1 : _e;
|
|
29714
|
+
var removeFilter = function () {
|
|
29715
|
+
handleRemoveFilter(label, value);
|
|
29716
|
+
};
|
|
29717
|
+
var labelToDisplay = (_b = getFormattedLabel(label)) !== null && _b !== void 0 ? _b : label;
|
|
29718
|
+
var valueToDisplay = (_c = getFormattedValue(label, value)) !== null && _c !== void 0 ? _c : value;
|
|
29719
|
+
return (jsxRuntime.jsxs("div", __assign({ className: "flexbox flex-align-center br-4 dc__border dc__bg-n50 pl-6 pr-6 pt-2 pb-2 dc__user-select-none h-24 dc__gap-6 fs-12 lh-20 cn-9 fw-4" }, { children: [jsxRuntime.jsx("span", __assign({ className: "fw-6 dc__capitalize" }, { children: labelToDisplay })), jsxRuntime.jsx("span", { className: "dc__divider h-24" }), jsxRuntime.jsx("span", __assign({ className: "dc__ellipsis-right" }, { children: valueToDisplay })), jsxRuntime.jsx("button", __assign({ type: "button", className: "flex p-0 dc__transparent", onClick: removeFilter, "aria-label": "Remove filter" }, { children: jsxRuntime.jsx(SvgIcClose, { className: "icon-dim-12 icon-use-fill-n6" }) }))] })));
|
|
29720
|
+
};
|
|
29721
|
+
/**
|
|
29722
|
+
* Component for rendering the applied filter chips
|
|
29723
|
+
*/
|
|
29724
|
+
var FilterChips = function (_a) {
|
|
29725
|
+
var filterConfig = _a.filterConfig, clearFilters = _a.clearFilters, onRemoveFilter = _a.onRemoveFilter, getFormattedLabel = _a.getFormattedLabel, getFormattedValue = _a.getFormattedValue;
|
|
29726
|
+
var handleRemoveFilter = function (filterKey, valueToRemove) {
|
|
29727
|
+
var _a;
|
|
29728
|
+
var updatedFilterConfig = JSON.parse(JSON.stringify(filterConfig));
|
|
29729
|
+
if (Array.isArray(filterConfig[filterKey])) {
|
|
29730
|
+
onRemoveFilter(__assign(__assign({}, updatedFilterConfig), (_a = {}, _a[filterKey] = updatedFilterConfig[filterKey].filter(function (val) { return val !== valueToRemove; }), _a)));
|
|
29731
|
+
return;
|
|
29732
|
+
}
|
|
29733
|
+
if (filterKey in updatedFilterConfig) {
|
|
29734
|
+
delete updatedFilterConfig[filterKey];
|
|
29735
|
+
onRemoveFilter(updatedFilterConfig);
|
|
29736
|
+
}
|
|
29737
|
+
};
|
|
29738
|
+
var chips = Object.entries(filterConfig).filter(function (_a) {
|
|
29739
|
+
var _b = __read(_a, 2), value = _b[1];
|
|
29740
|
+
return (Array.isArray(value) ? value.length : !!value);
|
|
29741
|
+
});
|
|
29742
|
+
return (chips.length > 0 && (jsxRuntime.jsxs("div", __assign({ className: "flexbox pt-6 pb-6 flex-wrap dc__gap-8" }, { children: [chips.map(function (_a) {
|
|
29743
|
+
var _b = __read(_a, 2), filterKey = _b[0], filterValue = _b[1];
|
|
29744
|
+
return Array.isArray(filterValue) ? (filterValue.map(function (filter) { return (jsxRuntime.jsx(FilterChip, { label: filterKey, value: filter, handleRemoveFilter: handleRemoveFilter, getFormattedLabel: getFormattedLabel, getFormattedValue: getFormattedValue }, "".concat(filterKey, "-").concat(filter))); })) : (jsxRuntime.jsx(FilterChip, { label: filterKey, value: filterValue, handleRemoveFilter: handleRemoveFilter, getFormattedLabel: getFormattedLabel, getFormattedValue: getFormattedValue }, filterKey));
|
|
29745
|
+
}), jsxRuntime.jsx("div", __assign({ className: "flex" }, { children: jsxRuntime.jsx("button", __assign({ type: "button", className: "cta text fs-13 lh-20-imp h-20 p-0-imp", onClick: clearFilters }, { children: "Clear All Filters" })) }))] }))));
|
|
29746
|
+
};
|
|
29747
|
+
|
|
29690
29748
|
var MESSAGES = {
|
|
29691
29749
|
PROVIDE_A_NUMBER: 'Please provide a number',
|
|
29692
29750
|
LOWERCASE_ALPHANUMERIC: 'Only lowercase alphanumeric characters, -, _ or . allowed',
|
|
@@ -30218,6 +30276,11 @@ var BuildInfraConfigForm = function (_a) {
|
|
|
30218
30276
|
isRequired: true, profileUnitsMap: unitsMap[action.actionType], handleProfileInputChange: handleProfileInputChange, currentUnitName: currentConfigurations[action.actionType].unit, currentValue: currentConfigurations[action.actionType].value }, action.actionType)); }) })) }), field.locator)); }) }))] }))] })));
|
|
30219
30277
|
};
|
|
30220
30278
|
|
|
30279
|
+
exports.UserListSortableKeys = void 0;
|
|
30280
|
+
(function (UserListSortableKeys) {
|
|
30281
|
+
UserListSortableKeys["email"] = "email_id";
|
|
30282
|
+
UserListSortableKeys["lastLogin"] = "last_login";
|
|
30283
|
+
})(exports.UserListSortableKeys || (exports.UserListSortableKeys = {}));
|
|
30221
30284
|
/**
|
|
30222
30285
|
* User Status received from the API
|
|
30223
30286
|
*/
|
|
@@ -30233,7 +30296,7 @@ exports.UserStatus = void 0;
|
|
|
30233
30296
|
(function (UserStatus) {
|
|
30234
30297
|
UserStatus["active"] = "active";
|
|
30235
30298
|
UserStatus["inactive"] = "inactive";
|
|
30236
|
-
UserStatus["temporary"] = "
|
|
30299
|
+
UserStatus["temporary"] = "temporaryAccess";
|
|
30237
30300
|
})(exports.UserStatus || (exports.UserStatus = {}));
|
|
30238
30301
|
|
|
30239
30302
|
exports.APIResponseHandler = APIResponseHandler;
|
|
@@ -30289,6 +30352,7 @@ exports.EmptyState = EmptyState;
|
|
|
30289
30352
|
exports.ErrorScreenManager = ErrorScreenManager;
|
|
30290
30353
|
exports.ErrorScreenNotAuthorized = ErrorScreenNotAuthorized;
|
|
30291
30354
|
exports.FALLBACK_REQUEST_TIMEOUT = FALLBACK_REQUEST_TIMEOUT;
|
|
30355
|
+
exports.FilterChips = FilterChips;
|
|
30292
30356
|
exports.ForceDeleteDialog = ForceDeleteDialog;
|
|
30293
30357
|
exports.GenericEmptyState = GenericEmptyState;
|
|
30294
30358
|
exports.Grid = Grid;
|
package/package.json
CHANGED
|
@@ -8,7 +8,10 @@ export enum DraggablePositionVariant {
|
|
|
8
8
|
|
|
9
9
|
export interface DraggableWrapperProps {
|
|
10
10
|
children: ReactNode
|
|
11
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Support for passing the direct value or calc functions as well
|
|
13
|
+
*/
|
|
14
|
+
zIndex?: number | string
|
|
12
15
|
positionVariant?: DraggablePositionVariant
|
|
13
16
|
/**
|
|
14
17
|
* dragSelector (class - (append with .), id, etc) will be used to identify the grabbable button that will grab the div to drag
|
package/src/Common/Helper.tsx
CHANGED
|
@@ -449,7 +449,13 @@ export const getUrlWithSearchParams = (url: string, params: Record<string | numb
|
|
|
449
449
|
const searchParams = new URLSearchParams()
|
|
450
450
|
Object.keys(params).forEach((key) => {
|
|
451
451
|
if (params[key]) {
|
|
452
|
-
|
|
452
|
+
if (Array.isArray(params[key])) {
|
|
453
|
+
params[key].forEach((val) => {
|
|
454
|
+
searchParams.append(key, val)
|
|
455
|
+
})
|
|
456
|
+
} else {
|
|
457
|
+
searchParams.set(key, params[key])
|
|
458
|
+
}
|
|
453
459
|
}
|
|
454
460
|
})
|
|
455
461
|
const queryString = searchParams.toString()
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { default as useUrlFilters } from './useUrlFilters'
|
|
2
|
-
export type { UseUrlFiltersProps } from './types'
|
|
2
|
+
export type { UseUrlFiltersProps, UseUrlFiltersReturnType } from './types'
|
|
@@ -1,6 +1,61 @@
|
|
|
1
|
-
|
|
1
|
+
import { SortingOrder } from '../../Constants'
|
|
2
|
+
|
|
3
|
+
export interface UseUrlFiltersProps<T, K> {
|
|
2
4
|
/**
|
|
3
5
|
* The key on which the sorting should be applied
|
|
4
6
|
*/
|
|
5
7
|
initialSortKey?: T
|
|
8
|
+
/**
|
|
9
|
+
* Callback function for parsing the search params
|
|
10
|
+
*/
|
|
11
|
+
parseSearchParams?: (searchParams: URLSearchParams) => K
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export type UseUrlFiltersReturnType<T, K = unknown> = K & {
|
|
15
|
+
/**
|
|
16
|
+
* Currently applied page size
|
|
17
|
+
*/
|
|
18
|
+
pageSize: number
|
|
19
|
+
/**
|
|
20
|
+
* Handler for updating the current page
|
|
21
|
+
*/
|
|
22
|
+
changePage: (pageNumber: number) => void
|
|
23
|
+
/**
|
|
24
|
+
* Handler for updating the current page size
|
|
25
|
+
*/
|
|
26
|
+
changePageSize: (pageSize: number) => void
|
|
27
|
+
/**
|
|
28
|
+
* Current search key
|
|
29
|
+
*/
|
|
30
|
+
searchKey: string
|
|
31
|
+
/**
|
|
32
|
+
* Handler for updating the search
|
|
33
|
+
*/
|
|
34
|
+
handleSearch: (searchKey: string) => void
|
|
35
|
+
/**
|
|
36
|
+
* Computed offset using the pageSize and pageNumber
|
|
37
|
+
*
|
|
38
|
+
* Note: Used in pagination component
|
|
39
|
+
*/
|
|
40
|
+
offset: number
|
|
41
|
+
/**
|
|
42
|
+
* Key on which the sorting is applied
|
|
43
|
+
*/
|
|
44
|
+
sortBy: T
|
|
45
|
+
/**
|
|
46
|
+
* Current sort order
|
|
47
|
+
*/
|
|
48
|
+
sortOrder: SortingOrder
|
|
49
|
+
/**
|
|
50
|
+
* Handle the sorting type change / key change
|
|
51
|
+
*/
|
|
52
|
+
handleSorting: (sortBy: T) => void
|
|
53
|
+
/**
|
|
54
|
+
* Clear all the applied filters
|
|
55
|
+
*/
|
|
56
|
+
clearFilters: () => void
|
|
57
|
+
/**
|
|
58
|
+
* Update the search params with the passed object
|
|
59
|
+
*/
|
|
60
|
+
updateSearchParams: (paramsToSerialize: K) => void
|
|
6
61
|
}
|
|
@@ -2,7 +2,7 @@ import { useMemo } from 'react'
|
|
|
2
2
|
import { useHistory, useLocation } from 'react-router-dom'
|
|
3
3
|
import { DEFAULT_BASE_PAGE_SIZE, SortingOrder } from '../../Constants'
|
|
4
4
|
import { DEFAULT_PAGE_NUMBER, URL_FILTER_KEYS } from './constants'
|
|
5
|
-
import { UseUrlFiltersProps } from './types'
|
|
5
|
+
import { UseUrlFiltersProps, UseUrlFiltersReturnType } from './types'
|
|
6
6
|
|
|
7
7
|
const { PAGE_SIZE, PAGE_NUMBER, SEARCH_KEY, SORT_BY, SORT_ORDER } = URL_FILTER_KEYS
|
|
8
8
|
|
|
@@ -23,12 +23,15 @@ const { PAGE_SIZE, PAGE_NUMBER, SEARCH_KEY, SORT_BY, SORT_ORDER } = URL_FILTER_K
|
|
|
23
23
|
* ```
|
|
24
24
|
*
|
|
25
25
|
*/
|
|
26
|
-
const useUrlFilters = <T = string
|
|
26
|
+
const useUrlFilters = <T = string, K = unknown>({
|
|
27
|
+
initialSortKey,
|
|
28
|
+
parseSearchParams,
|
|
29
|
+
}: UseUrlFiltersProps<T, K> = {}): UseUrlFiltersReturnType<T, K> => {
|
|
27
30
|
const location = useLocation()
|
|
28
31
|
const history = useHistory()
|
|
29
32
|
const searchParams = new URLSearchParams(location.search)
|
|
30
33
|
|
|
31
|
-
const { pageSize, pageNumber, searchKey, sortBy, sortOrder } = useMemo(() => {
|
|
34
|
+
const { pageSize, pageNumber, searchKey, sortBy, sortOrder, parsedParams } = useMemo(() => {
|
|
32
35
|
const _pageSize = searchParams.get(PAGE_SIZE)
|
|
33
36
|
const _pageNumber = searchParams.get(PAGE_NUMBER)
|
|
34
37
|
const _searchKey = searchParams.get(SEARCH_KEY)
|
|
@@ -39,6 +42,8 @@ const useUrlFilters = <T = string>({ initialSortKey }: UseUrlFiltersProps<T> = {
|
|
|
39
42
|
// Fallback to ascending order
|
|
40
43
|
const sortByOrder = Object.values(SortingOrder).includes(_sortOrder) ? _sortOrder : SortingOrder.ASC
|
|
41
44
|
|
|
45
|
+
const _parsedParams = parseSearchParams ? parseSearchParams(searchParams) : ({} as K)
|
|
46
|
+
|
|
42
47
|
return {
|
|
43
48
|
pageSize: Number(_pageSize) || DEFAULT_BASE_PAGE_SIZE,
|
|
44
49
|
pageNumber: Number(_pageNumber) || DEFAULT_PAGE_NUMBER,
|
|
@@ -46,6 +51,7 @@ const useUrlFilters = <T = string>({ initialSortKey }: UseUrlFiltersProps<T> = {
|
|
|
46
51
|
sortBy: sortByKey,
|
|
47
52
|
// sort order should only be applied if the key is available
|
|
48
53
|
sortOrder: (sortByKey ? sortByOrder : '') as SortingOrder,
|
|
54
|
+
parsedParams: _parsedParams,
|
|
49
55
|
}
|
|
50
56
|
}, [searchParams])
|
|
51
57
|
|
|
@@ -98,10 +104,24 @@ const useUrlFilters = <T = string>({ initialSortKey }: UseUrlFiltersProps<T> = {
|
|
|
98
104
|
}
|
|
99
105
|
|
|
100
106
|
const clearFilters = () => {
|
|
101
|
-
|
|
102
|
-
|
|
107
|
+
history.replace({ search: '' })
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const updateSearchParams = (paramsToSerialize: K) => {
|
|
111
|
+
Object.keys(paramsToSerialize).forEach((key) => {
|
|
112
|
+
if (paramsToSerialize[key]) {
|
|
113
|
+
if (Array.isArray(paramsToSerialize[key])) {
|
|
114
|
+
searchParams.delete(key)
|
|
115
|
+
paramsToSerialize[key].forEach((val) => {
|
|
116
|
+
searchParams.append(key, val)
|
|
117
|
+
})
|
|
118
|
+
} else {
|
|
119
|
+
searchParams.set(key, paramsToSerialize[key])
|
|
120
|
+
}
|
|
121
|
+
}
|
|
103
122
|
})
|
|
104
|
-
|
|
123
|
+
// Not replacing the params as it is being done by _resetPageNumber
|
|
124
|
+
_resetPageNumber()
|
|
105
125
|
}
|
|
106
126
|
|
|
107
127
|
return {
|
|
@@ -115,6 +135,8 @@ const useUrlFilters = <T = string>({ initialSortKey }: UseUrlFiltersProps<T> = {
|
|
|
115
135
|
sortOrder,
|
|
116
136
|
handleSorting,
|
|
117
137
|
clearFilters,
|
|
138
|
+
...parsedParams,
|
|
139
|
+
updateSearchParams,
|
|
118
140
|
}
|
|
119
141
|
}
|
|
120
142
|
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
export enum UserListSortableKeys {
|
|
2
|
+
email = 'email_id',
|
|
3
|
+
lastLogin = 'last_login',
|
|
4
|
+
}
|
|
5
|
+
|
|
1
6
|
/**
|
|
2
7
|
* User Status received from the API
|
|
3
8
|
*/
|
|
@@ -12,5 +17,5 @@ export enum UserStatusDto {
|
|
|
12
17
|
export enum UserStatus {
|
|
13
18
|
active = 'active',
|
|
14
19
|
inactive = 'inactive',
|
|
15
|
-
temporary = '
|
|
20
|
+
temporary = 'temporaryAccess',
|
|
16
21
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { SortingParams } from '../../../Common'
|
|
2
|
+
import { UserListSortableKeys, UserStatus } from './constants'
|
|
3
|
+
|
|
4
|
+
export type BaseFilterQueryParams<T> = {
|
|
5
|
+
/**
|
|
6
|
+
* Offset for the list result
|
|
7
|
+
*/
|
|
8
|
+
offset?: number
|
|
9
|
+
/**
|
|
10
|
+
* Number of items required in the list
|
|
11
|
+
*/
|
|
12
|
+
size?: number
|
|
13
|
+
/**
|
|
14
|
+
* Search string (if any)
|
|
15
|
+
*/
|
|
16
|
+
searchKey?: string
|
|
17
|
+
/**
|
|
18
|
+
* If true, all items are returned with any search / filtering applied without pagination
|
|
19
|
+
*/
|
|
20
|
+
showAll?: boolean
|
|
21
|
+
} & SortingParams<T>
|
|
22
|
+
|
|
23
|
+
export type UserListFilterParams = BaseFilterQueryParams<UserListSortableKeys> & {
|
|
24
|
+
status: UserStatus[]
|
|
25
|
+
}
|
|
@@ -9,8 +9,8 @@ import { ReactComponent as ICCheckAll } from '../../../Assets/Icon/ic-check-all.
|
|
|
9
9
|
import { ReactComponent as ICClose } from '../../../Assets/Icon/ic-close.svg'
|
|
10
10
|
|
|
11
11
|
const BulkSelection = <T,>({ showPagination }: BulkSelectionProps) => {
|
|
12
|
-
const { handleBulkSelection,
|
|
13
|
-
const areOptionsSelected =
|
|
12
|
+
const { handleBulkSelection, isChecked, checkboxValue, getSelectedIdentifiersCount } = useBulkSelection<T>()
|
|
13
|
+
const areOptionsSelected = getSelectedIdentifiersCount() > 0
|
|
14
14
|
const BulkSelectionItems: BulkSelectionDropdownItemsType[] = [
|
|
15
15
|
{
|
|
16
16
|
locator: BulkSelectionEvents.SELECT_ALL_ON_PAGE,
|
|
@@ -22,6 +22,8 @@ const BulkSelectionContext = createContext<UseBulkSelectionReturnType<any>>({
|
|
|
22
22
|
handleBulkSelection: noop,
|
|
23
23
|
isChecked: false,
|
|
24
24
|
checkboxValue: CHECKBOX_VALUE.CHECKED,
|
|
25
|
+
isBulkSelectionApplied: false,
|
|
26
|
+
getSelectedIdentifiersCount: noop,
|
|
25
27
|
})
|
|
26
28
|
|
|
27
29
|
export const useBulkSelection = <T,>() => {
|
|
@@ -39,6 +41,10 @@ export const BulkSelectionProvider = <T,>({
|
|
|
39
41
|
}: UseBulkSelectionProps<T>) => {
|
|
40
42
|
const [selectedIdentifiers, setSelectedIdentifiers] = useState<T>({} as T)
|
|
41
43
|
|
|
44
|
+
const isBulkSelectionApplied = selectedIdentifiers[SELECT_ALL_ACROSS_PAGES_LOCATOR]
|
|
45
|
+
|
|
46
|
+
const getSelectedIdentifiersCount = () => Object.keys(selectedIdentifiers).length
|
|
47
|
+
|
|
42
48
|
const setIdentifiersAfterClear = (newIdentifiers: T, selectedIds: (number | string)[]) => {
|
|
43
49
|
const _newIdentifiers = JSON.parse(JSON.stringify(newIdentifiers))
|
|
44
50
|
selectedIds.forEach((id) => {
|
|
@@ -50,7 +56,7 @@ export const BulkSelectionProvider = <T,>({
|
|
|
50
56
|
const setIdentifiersAfterPageSelection = (baseObject: T) => {
|
|
51
57
|
const _selectedIdentifiers = JSON.parse(JSON.stringify(selectedIdentifiers))
|
|
52
58
|
// removing bulk selection across pages if present
|
|
53
|
-
if (
|
|
59
|
+
if (isBulkSelectionApplied) {
|
|
54
60
|
delete _selectedIdentifiers[SELECT_ALL_ACROSS_PAGES_LOCATOR]
|
|
55
61
|
}
|
|
56
62
|
|
|
@@ -81,10 +87,13 @@ export const BulkSelectionProvider = <T,>({
|
|
|
81
87
|
}
|
|
82
88
|
|
|
83
89
|
case BulkSelectionEvents.SELECT_ALL_ACROSS_PAGES: {
|
|
84
|
-
if (
|
|
90
|
+
if (isBulkSelectionApplied) {
|
|
85
91
|
return
|
|
86
92
|
}
|
|
87
|
-
const selectedIdentifiersLength =
|
|
93
|
+
const selectedIdentifiersLength = getSelectedIdentifiersCount()
|
|
94
|
+
// This is for showing a modal dialog if applicable to confirm if bulk selection is to be applied
|
|
95
|
+
// Do note that the 'getSelectAllDialogStatus' should be called after the length check explicitly
|
|
96
|
+
// otherwise the modal will open each time
|
|
88
97
|
if (selectedIdentifiersLength > 0 && getSelectAllDialogStatus() === SelectAllDialogStatus.OPEN) {
|
|
89
98
|
return
|
|
90
99
|
}
|
|
@@ -130,7 +139,7 @@ export const BulkSelectionProvider = <T,>({
|
|
|
130
139
|
}
|
|
131
140
|
|
|
132
141
|
// if selectedIdentifiers contains select all across pages locator then it means all are selected
|
|
133
|
-
if (
|
|
142
|
+
if (isBulkSelectionApplied) {
|
|
134
143
|
return {
|
|
135
144
|
isChecked: true,
|
|
136
145
|
checkboxValue: CHECKBOX_VALUE.BULK_CHECKED,
|
|
@@ -163,8 +172,10 @@ export const BulkSelectionProvider = <T,>({
|
|
|
163
172
|
handleBulkSelection,
|
|
164
173
|
isChecked,
|
|
165
174
|
checkboxValue,
|
|
175
|
+
isBulkSelectionApplied,
|
|
176
|
+
getSelectedIdentifiersCount,
|
|
166
177
|
}),
|
|
167
|
-
[selectedIdentifiers, handleBulkSelection, isChecked, checkboxValue],
|
|
178
|
+
[selectedIdentifiers, handleBulkSelection, isChecked, checkboxValue, getSelectedIdentifiersCount],
|
|
168
179
|
)
|
|
169
180
|
|
|
170
181
|
return <BulkSelectionContext.Provider value={value}>{children}</BulkSelectionContext.Provider>
|
|
@@ -26,6 +26,8 @@ export interface GetBulkSelectionCheckboxValuesType {
|
|
|
26
26
|
export interface UseBulkSelectionReturnType<T> extends GetBulkSelectionCheckboxValuesType {
|
|
27
27
|
selectedIdentifiers: T
|
|
28
28
|
handleBulkSelection: ({ action, data }: HandleBulkSelectionType<T>) => void
|
|
29
|
+
isBulkSelectionApplied: boolean
|
|
30
|
+
getSelectedIdentifiersCount: () => number
|
|
29
31
|
}
|
|
30
32
|
|
|
31
33
|
export interface BulkSelectionProps {
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { ReactComponent as CloseIcon } from '../../../Assets/Icon/ic-close.svg'
|
|
2
|
+
import { noop } from '../../../Common'
|
|
3
|
+
import { FilterChipProps, FilterChipsProps } from './types'
|
|
4
|
+
|
|
5
|
+
const FilterChip = ({
|
|
6
|
+
label,
|
|
7
|
+
value,
|
|
8
|
+
handleRemoveFilter,
|
|
9
|
+
getFormattedLabel = noop,
|
|
10
|
+
getFormattedValue = noop,
|
|
11
|
+
}: FilterChipProps) => {
|
|
12
|
+
const removeFilter = () => {
|
|
13
|
+
handleRemoveFilter(label, value)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const labelToDisplay = getFormattedLabel(label) ?? label
|
|
17
|
+
|
|
18
|
+
const valueToDisplay = getFormattedValue(label, value) ?? value
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<div className="flexbox flex-align-center br-4 dc__border dc__bg-n50 pl-6 pr-6 pt-2 pb-2 dc__user-select-none h-24 dc__gap-6 fs-12 lh-20 cn-9 fw-4">
|
|
22
|
+
<span className="fw-6 dc__capitalize">{labelToDisplay}</span>
|
|
23
|
+
<span className="dc__divider h-24" />
|
|
24
|
+
<span className="dc__ellipsis-right">{valueToDisplay}</span>
|
|
25
|
+
<button
|
|
26
|
+
type="button"
|
|
27
|
+
className="flex p-0 dc__transparent"
|
|
28
|
+
onClick={removeFilter}
|
|
29
|
+
aria-label="Remove filter"
|
|
30
|
+
>
|
|
31
|
+
<CloseIcon className="icon-dim-12 icon-use-fill-n6" />
|
|
32
|
+
</button>
|
|
33
|
+
</div>
|
|
34
|
+
)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Component for rendering the applied filter chips
|
|
39
|
+
*/
|
|
40
|
+
const FilterChips = ({
|
|
41
|
+
filterConfig,
|
|
42
|
+
clearFilters,
|
|
43
|
+
onRemoveFilter,
|
|
44
|
+
getFormattedLabel,
|
|
45
|
+
getFormattedValue,
|
|
46
|
+
}: FilterChipsProps) => {
|
|
47
|
+
const handleRemoveFilter = (filterKey, valueToRemove) => {
|
|
48
|
+
const updatedFilterConfig = JSON.parse(JSON.stringify(filterConfig))
|
|
49
|
+
if (Array.isArray(filterConfig[filterKey])) {
|
|
50
|
+
onRemoveFilter({
|
|
51
|
+
...updatedFilterConfig,
|
|
52
|
+
[filterKey]: updatedFilterConfig[filterKey].filter((val) => val !== valueToRemove),
|
|
53
|
+
})
|
|
54
|
+
return
|
|
55
|
+
}
|
|
56
|
+
if (filterKey in updatedFilterConfig) {
|
|
57
|
+
delete updatedFilterConfig[filterKey]
|
|
58
|
+
onRemoveFilter(updatedFilterConfig)
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const chips = Object.entries(filterConfig).filter(([, value]) => (Array.isArray(value) ? value.length : !!value))
|
|
63
|
+
|
|
64
|
+
return (
|
|
65
|
+
chips.length > 0 && (
|
|
66
|
+
<div className="flexbox pt-6 pb-6 flex-wrap dc__gap-8">
|
|
67
|
+
{chips.map(([filterKey, filterValue]) =>
|
|
68
|
+
Array.isArray(filterValue) ? (
|
|
69
|
+
filterValue.map((filter) => (
|
|
70
|
+
<FilterChip
|
|
71
|
+
key={`${filterKey}-${filter}`}
|
|
72
|
+
label={filterKey}
|
|
73
|
+
value={filter}
|
|
74
|
+
handleRemoveFilter={handleRemoveFilter}
|
|
75
|
+
getFormattedLabel={getFormattedLabel}
|
|
76
|
+
getFormattedValue={getFormattedValue}
|
|
77
|
+
/>
|
|
78
|
+
))
|
|
79
|
+
) : (
|
|
80
|
+
<FilterChip
|
|
81
|
+
key={filterKey}
|
|
82
|
+
label={filterKey}
|
|
83
|
+
value={filterValue}
|
|
84
|
+
handleRemoveFilter={handleRemoveFilter}
|
|
85
|
+
getFormattedLabel={getFormattedLabel}
|
|
86
|
+
getFormattedValue={getFormattedValue}
|
|
87
|
+
/>
|
|
88
|
+
),
|
|
89
|
+
)}
|
|
90
|
+
<div className="flex">
|
|
91
|
+
<button type="button" className="cta text fs-13 lh-20-imp h-20 p-0-imp" onClick={clearFilters}>
|
|
92
|
+
Clear All Filters
|
|
93
|
+
</button>
|
|
94
|
+
</div>
|
|
95
|
+
</div>
|
|
96
|
+
)
|
|
97
|
+
)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export default FilterChips
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { ReactNode } from 'react'
|
|
2
|
+
|
|
3
|
+
export interface FilterChipProps {
|
|
4
|
+
/**
|
|
5
|
+
* Filter label
|
|
6
|
+
*/
|
|
7
|
+
label: string
|
|
8
|
+
/**
|
|
9
|
+
* Corresponding value of the filter
|
|
10
|
+
*/
|
|
11
|
+
value: unknown
|
|
12
|
+
/**
|
|
13
|
+
* Callback handler for removing the filter
|
|
14
|
+
*/
|
|
15
|
+
handleRemoveFilter: (label: string, valueToRemove: unknown) => void
|
|
16
|
+
/**
|
|
17
|
+
* If passed, the label will be formatted accordingly
|
|
18
|
+
*/
|
|
19
|
+
getFormattedLabel?: (filterKey: string) => ReactNode
|
|
20
|
+
/**
|
|
21
|
+
* If passed, the label will be formatted accordingly
|
|
22
|
+
*/
|
|
23
|
+
getFormattedValue?: (filterKey: string, filterValue: unknown) => ReactNode
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface FilterChipsProps extends Pick<FilterChipProps, 'getFormattedLabel' | 'getFormattedValue'> {
|
|
27
|
+
/**
|
|
28
|
+
* Current filter configuration
|
|
29
|
+
*/
|
|
30
|
+
filterConfig: Record<string, unknown>
|
|
31
|
+
/**
|
|
32
|
+
* Callback handler for removing the filters
|
|
33
|
+
*/
|
|
34
|
+
clearFilters: () => void
|
|
35
|
+
/**
|
|
36
|
+
* Handler for removing a applied filter
|
|
37
|
+
*/
|
|
38
|
+
onRemoveFilter: (filterConfig: Record<string, unknown>) => void
|
|
39
|
+
}
|