@addev-be/ui 0.2.6 → 0.2.8
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/assets/icons/arrow-down-1-9.svg +1 -0
- package/assets/icons/arrow-down-big-small.svg +1 -0
- package/assets/icons/arrow-up-9-1.svg +1 -0
- package/assets/icons/arrow-up-big-small.svg +1 -0
- package/assets/icons/chevron-down.svg +1 -0
- package/assets/icons/ellipsis.svg +1 -0
- package/assets/icons/sigma.svg +1 -0
- package/assets/icons/table-footer-slash.svg +5 -0
- package/assets/icons/table-footer.svg +4 -0
- package/assets/icons/table.svg +1 -0
- package/assets/icons/tally.svg +1 -0
- package/assets/icons/x-bar.svg +4 -0
- package/dist/Icons.d.ts +13 -1
- package/dist/Icons.js +25 -1
- package/dist/components/data/AdvancedRequestDataGrid/index.js +3 -3
- package/dist/components/data/DataGrid/DataGridColumnsModal/hooks.js +2 -1
- package/dist/components/data/DataGrid/DataGridFilterMenu/index.js +85 -7
- package/dist/components/data/DataGrid/DataGridFilterMenu/styles.d.ts +3 -9
- package/dist/components/data/DataGrid/DataGridFilterMenu/styles.js +10 -37
- package/dist/components/data/DataGrid/DataGridFooter.d.ts +1 -1
- package/dist/components/data/DataGrid/DataGridFooter.js +35 -12
- package/dist/components/data/DataGrid/DataGridHeader.js +1 -1
- package/dist/components/data/DataGrid/DataGridHeaderCell.js +6 -22
- package/dist/components/data/DataGrid/helpers/columns.d.ts +1 -1
- package/dist/components/data/DataGrid/helpers/columns.js +71 -16
- package/dist/components/data/DataGrid/hooks/useDataGrid.d.ts +1 -1
- package/dist/components/data/DataGrid/hooks/useDataGrid.js +60 -30
- package/dist/components/data/DataGrid/hooks/useDataGridCopy.d.ts +2 -2
- package/dist/components/data/DataGrid/hooks/useDataGridCopy.js +41 -39
- package/dist/components/data/DataGrid/index.d.ts +4 -2
- package/dist/components/data/DataGrid/index.js +22 -12
- package/dist/components/data/DataGrid/styles.d.ts +8 -4
- package/dist/components/data/DataGrid/styles.js +27 -17
- package/dist/components/data/DataGrid/types.d.ts +8 -1
- package/dist/components/data/SqlRequestDataGrid/helpers/columns.d.ts +1 -1
- package/dist/components/data/SqlRequestDataGrid/helpers/columns.js +24 -11
- package/dist/components/data/SqlRequestDataGrid/index.js +105 -33
- package/dist/components/ui/ContextMenu/index.d.ts +11 -0
- package/dist/components/ui/ContextMenu/index.js +58 -0
- package/dist/components/ui/ContextMenu/styles.d.ts +18 -0
- package/dist/components/ui/ContextMenu/styles.js +56 -0
- package/dist/services/advancedRequests.d.ts +1 -1
- package/dist/services/sqlRequests.d.ts +9 -4
- package/dist/services/sqlRequests.js +1 -0
- package/package.json +1 -1
- package/src/Icons.tsx +24 -0
- package/src/components/data/AdvancedRequestDataGrid/index.tsx +3 -5
- package/src/components/data/DataGrid/DataGridColumnsModal/hooks.tsx +2 -1
- package/src/components/data/DataGrid/DataGridFilterMenu/index.tsx +180 -22
- package/src/components/data/DataGrid/DataGridFilterMenu/styles.ts +13 -64
- package/src/components/data/DataGrid/DataGridFooter.tsx +20 -22
- package/src/components/data/DataGrid/DataGridHeader.tsx +5 -5
- package/src/components/data/DataGrid/DataGridHeaderCell.tsx +3 -38
- package/src/components/data/DataGrid/FilterValuesScroller.tsx +33 -27
- package/src/components/data/DataGrid/helpers/columns.tsx +103 -8
- package/src/components/data/DataGrid/helpers/filters.ts +29 -19
- package/src/components/data/DataGrid/hooks/useDataGrid.tsx +58 -17
- package/src/components/data/DataGrid/hooks/useDataGridCopy.ts +35 -30
- package/src/components/data/DataGrid/index.tsx +22 -14
- package/src/components/data/DataGrid/styles.ts +50 -9
- package/src/components/data/DataGrid/types.ts +24 -3
- package/src/components/data/SqlRequestDataGrid/helpers/columns.tsx +39 -3
- package/src/components/data/SqlRequestDataGrid/index.tsx +116 -21
- package/src/components/ui/ContextMenu/index.tsx +79 -0
- package/src/components/ui/ContextMenu/styles.ts +119 -0
- package/src/services/advancedRequests.ts +1 -1
- package/src/services/sqlRequests.ts +16 -5
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) {
|
|
3
|
+
if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
|
|
4
|
+
return cooked;
|
|
5
|
+
};
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
18
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
19
|
+
}) : function(o, v) {
|
|
20
|
+
o["default"] = v;
|
|
21
|
+
});
|
|
22
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
23
|
+
if (mod && mod.__esModule) return mod;
|
|
24
|
+
var result = {};
|
|
25
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
26
|
+
__setModuleDefault(result, mod);
|
|
27
|
+
return result;
|
|
28
|
+
};
|
|
29
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
30
|
+
exports.Divider = exports.MenuItemContainer = exports.SubMenu = exports.MenuContainer = void 0;
|
|
31
|
+
var styled_components_1 = __importStar(require("styled-components"));
|
|
32
|
+
var menuContainerCss = (0, styled_components_1.css)(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n position: absolute;\n color: var(--color-neutral-900);\n border-radius: var(--rounded-md);\n padding: var(--space-1) 0;\n box-shadow: var(--shadow-lg);\n background-color: var(--color-neutral-100);\n min-width: 20em;\n outline: 1px solid var(--color-neutral-200);\n display: flex;\n flex-direction: column;\n"], ["\n position: absolute;\n color: var(--color-neutral-900);\n border-radius: var(--rounded-md);\n padding: var(--space-1) 0;\n box-shadow: var(--shadow-lg);\n background-color: var(--color-neutral-100);\n min-width: 20em;\n outline: 1px solid var(--color-neutral-200);\n display: flex;\n flex-direction: column;\n"])));
|
|
33
|
+
exports.MenuContainer = styled_components_1.default.div.attrs({
|
|
34
|
+
className: 'MenuContainer',
|
|
35
|
+
})(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n ", "\n inset: 0;\n"], ["\n ", "\n inset: 0;\n"])), menuContainerCss);
|
|
36
|
+
exports.MenuContainer.displayName = 'MenuContainer';
|
|
37
|
+
exports.SubMenu = styled_components_1.default.div.attrs({
|
|
38
|
+
className: 'SubMenu',
|
|
39
|
+
})(templateObject_3 || (templateObject_3 = __makeTemplateObject(["\n ", "\n top: 0;\n left: 100%;\n margin-top: -var(--space-1);\n"], ["\n ", "\n top: 0;\n left: 100%;\n margin-top: -var(--space-1);\n"])), menuContainerCss);
|
|
40
|
+
exports.SubMenu.displayName = 'SubMenu';
|
|
41
|
+
exports.MenuItemContainer = styled_components_1.default.div.attrs({
|
|
42
|
+
className: 'MenuItemContainer',
|
|
43
|
+
})(templateObject_8 || (templateObject_8 = __makeTemplateObject(["\n position: relative;\n display: flex;\n align-items: center;\n font-family: var(--font-sans);\n font-weight: normal;\n text-align: left;\n padding: var(--space-1) var(--space-2);\n font-size: var(--text-base);\n line-height: var(--leading-6);\n border: none;\n cursor: pointer;\n\n ", "\n\n ", "\n\n svg {\n fill: currentColor;\n width: var(--space-4);\n height: var(--space-4);\n margin-right: var(--space-2);\n }\n\n & > ", " {\n display: none;\n margin-top: calc(0px - var(--space-1));\n }\n &.opened > ", " {\n display: block;\n }\n"], ["\n position: relative;\n display: flex;\n align-items: center;\n font-family: var(--font-sans);\n font-weight: normal;\n text-align: left;\n padding: var(--space-1) var(--space-2);\n font-size: var(--text-base);\n line-height: var(--leading-6);\n border: none;\n cursor: pointer;\n\n ", "\n\n ", "\n\n svg {\n fill: currentColor;\n width: var(--space-4);\n height: var(--space-4);\n margin-right: var(--space-2);\n }\n\n & > ", " {\n display: none;\n margin-top: calc(0px - var(--space-1));\n }\n &.opened > ", " {\n display: block;\n }\n"])), function (_a) {
|
|
44
|
+
var $withArrow = _a.$withArrow;
|
|
45
|
+
return $withArrow && (0, styled_components_1.css)(templateObject_4 || (templateObject_4 = __makeTemplateObject(["\n &::after {\n content: '';\n position: absolute;\n right: var(--space-2);\n top: 50%;\n transform: translateY(-50%);\n border: 4px solid transparent;\n border-left-color: var(--color-neutral-600);\n }\n "], ["\n &::after {\n content: '';\n position: absolute;\n right: var(--space-2);\n top: 50%;\n transform: translateY(-50%);\n border: 4px solid transparent;\n border-left-color: var(--color-neutral-600);\n }\n "])));
|
|
46
|
+
}, function (_a) {
|
|
47
|
+
var $color = _a.$color, disabled = _a.disabled;
|
|
48
|
+
return disabled
|
|
49
|
+
? (0, styled_components_1.css)(templateObject_5 || (templateObject_5 = __makeTemplateObject(["\n color: var(--color-neutral-300);\n background-color: var(--color-neutral-100);\n cursor: default;\n "], ["\n color: var(--color-neutral-300);\n background-color: var(--color-neutral-100);\n cursor: default;\n "]))) : $color
|
|
50
|
+
? (0, styled_components_1.css)(templateObject_6 || (templateObject_6 = __makeTemplateObject(["\n color: var(--color-", "-600);\n background-color: var(--color-neutral-100);\n &:hover {\n background-color: var(--color-", "-200);\n }\n "], ["\n color: var(--color-", "-600);\n background-color: var(--color-neutral-100);\n &:hover {\n background-color: var(--color-", "-200);\n }\n "])), $color, $color) : (0, styled_components_1.css)(templateObject_7 || (templateObject_7 = __makeTemplateObject(["\n color: var(--color-neutral-900);\n background-color: var(--color-neutral-100);\n &:hover {\n background-color: var(--color-neutral-200);\n }\n "], ["\n color: var(--color-neutral-900);\n background-color: var(--color-neutral-100);\n &:hover {\n background-color: var(--color-neutral-200);\n }\n "])));
|
|
51
|
+
}, exports.SubMenu, exports.SubMenu);
|
|
52
|
+
exports.MenuItemContainer.displayName = 'MenuItemContainer';
|
|
53
|
+
exports.Divider = styled_components_1.default.div.attrs({
|
|
54
|
+
className: 'Divider',
|
|
55
|
+
})(templateObject_9 || (templateObject_9 = __makeTemplateObject(["\n border-top: 1px solid var(--color-neutral-200);\n margin: var(--space-1) 0;\n"], ["\n border-top: 1px solid var(--color-neutral-200);\n margin: var(--space-1) 0;\n"])));
|
|
56
|
+
var templateObject_1, templateObject_2, templateObject_3, templateObject_4, templateObject_5, templateObject_6, templateObject_7, templateObject_8, templateObject_9;
|
|
@@ -14,27 +14,32 @@ export type ConditionDTO = {
|
|
|
14
14
|
};
|
|
15
15
|
export type OrderByDTO = {
|
|
16
16
|
field: string;
|
|
17
|
+
type: string;
|
|
17
18
|
direction?: 'ASC' | 'DESC';
|
|
18
19
|
};
|
|
20
|
+
export type SqlRequestFooterFunction = 'sum' | 'avg' | 'count' | 'max' | 'min';
|
|
19
21
|
export type SqlRequestDTO = {
|
|
20
22
|
columns?: string[];
|
|
21
23
|
returnColumns?: string[];
|
|
24
|
+
columnTypes?: string[];
|
|
25
|
+
totalColumns?: Record<string, SqlRequestFooterFunction>;
|
|
22
26
|
conditions?: ConditionDTO[];
|
|
23
27
|
orderBy?: OrderByDTO[];
|
|
24
28
|
start?: number;
|
|
25
29
|
length?: number;
|
|
26
|
-
|
|
30
|
+
getCount?: boolean;
|
|
27
31
|
unique?: boolean;
|
|
28
32
|
};
|
|
29
33
|
export type SqlRequestRow<R> = {
|
|
30
|
-
[K in keyof R]: R[K] extends string | number | null ? R[K] : string | number | null;
|
|
34
|
+
[K in keyof R]: R[K] extends string | number | null | undefined ? R[K] : string | number | null | undefined;
|
|
31
35
|
};
|
|
32
36
|
export type SqlResponseDTO<T = any> = {
|
|
33
37
|
data: SqlRequestRow<T>[];
|
|
34
|
-
|
|
38
|
+
count?: number;
|
|
39
|
+
totals?: Record<string, string | number | null | undefined>;
|
|
35
40
|
};
|
|
36
41
|
type SqlRequestHandler<T> = (request: SqlRequestDTO) => Promise<SqlResponseDTO<T>>;
|
|
37
42
|
export declare const useSqlRequestHandler: <T = any>(name: string) => [SqlRequestHandler<T>, SqlRequestHandler<{
|
|
38
43
|
Id: string;
|
|
39
|
-
}
|
|
44
|
+
}>, SqlRequestHandler<Partial<T>>];
|
|
40
45
|
export {};
|
|
@@ -6,5 +6,6 @@ var hooks_1 = require("./hooks");
|
|
|
6
6
|
var useSqlRequestHandler = function (name) { return [
|
|
7
7
|
(0, hooks_1.useWebSocketRequestHandler)(name),
|
|
8
8
|
(0, hooks_1.useWebSocketRequestHandler)(name),
|
|
9
|
+
(0, hooks_1.useWebSocketRequestHandler)(name),
|
|
9
10
|
]; };
|
|
10
11
|
exports.useSqlRequestHandler = useSqlRequestHandler;
|
package/package.json
CHANGED
package/src/Icons.tsx
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
import { FC, SVGProps, useEffect, useState } from 'react';
|
|
2
2
|
|
|
3
|
+
import ArrowDown19Icon from '../assets/icons/arrow-down-1-9.svg?react';
|
|
3
4
|
import ArrowDownAZIcon from '../assets/icons/arrow-down-a-z.svg?react';
|
|
5
|
+
import ArrowDownBigSmallIcon from '../assets/icons/arrow-down-big-small.svg?react';
|
|
6
|
+
import ArrowUp91Icon from '../assets/icons/arrow-up-9-1.svg?react';
|
|
7
|
+
import ArrowUpBigSmallIcon from '../assets/icons/arrow-up-big-small.svg?react';
|
|
4
8
|
import ArrowUpZAIcon from '../assets/icons/arrow-up-z-a.svg?react';
|
|
5
9
|
import ArrowsRotateIcon from '../assets/icons/arrows-rotate.svg?react';
|
|
6
10
|
import ArrowsUpDownIcon from '../assets/icons/arrows-up-down.svg?react';
|
|
7
11
|
import CheckIcon from '../assets/icons/check.svg?react';
|
|
12
|
+
import ChevronDownIcon from '../assets/icons/chevron-down.svg?react';
|
|
8
13
|
import CopyIcon from '../assets/icons/copy.svg?react';
|
|
9
14
|
import DownIcon from '../assets/icons/down.svg?react';
|
|
15
|
+
import EllipsisIcon from '../assets/icons/ellipsis.svg?react';
|
|
10
16
|
import FilterFullIcon from '../assets/icons/filter-full.svg?react';
|
|
11
17
|
import FilterIcon from '../assets/icons/filter.svg?react';
|
|
12
18
|
import FilterSlashIcon from '../assets/icons/filter-slash.svg?react';
|
|
@@ -17,10 +23,16 @@ import MagnifierIcon from '../assets/icons/magnifier.svg?react';
|
|
|
17
23
|
import PhoneIcon from '../assets/icons/phone.svg?react';
|
|
18
24
|
import PlusIcon from '../assets/icons/plus.svg?react';
|
|
19
25
|
import RightIcon from '../assets/icons/right.svg?react';
|
|
26
|
+
import SigmaIcon from '../assets/icons/sigma.svg?react';
|
|
20
27
|
import SpinnerIcon from '../assets/icons/spinner-third.svg?react';
|
|
21
28
|
import TableColumnsIcon from '../assets/icons/table-columns.svg?react';
|
|
29
|
+
import TableFooterIcon from '../assets/icons/table-footer.svg?react';
|
|
30
|
+
import TableFooterSlashIcon from '../assets/icons/table-footer-slash.svg?react';
|
|
31
|
+
import TableIcon from '../assets/icons/table.svg?react';
|
|
32
|
+
import TallyIcon from '../assets/icons/tally.svg?react';
|
|
22
33
|
import UpIcon from '../assets/icons/up.svg?react';
|
|
23
34
|
import UserTieIcon from '../assets/icons/user-tie.svg?react';
|
|
35
|
+
import XBarIcon from '../assets/icons/x-bar.svg?react';
|
|
24
36
|
|
|
25
37
|
type IconFCProps = SVGProps<SVGSVGElement>;
|
|
26
38
|
export type IconFC = FC<IconFCProps>;
|
|
@@ -57,12 +69,18 @@ export const LoadingIcon: FC<IconFCProps> = ({ className, ...props }) => (
|
|
|
57
69
|
|
|
58
70
|
export {
|
|
59
71
|
ArrowDownAZIcon,
|
|
72
|
+
ArrowDown19Icon,
|
|
73
|
+
ArrowDownBigSmallIcon,
|
|
60
74
|
ArrowUpZAIcon,
|
|
75
|
+
ArrowUpBigSmallIcon,
|
|
76
|
+
ArrowUp91Icon,
|
|
61
77
|
ArrowsRotateIcon,
|
|
62
78
|
ArrowsUpDownIcon,
|
|
63
79
|
CheckIcon,
|
|
80
|
+
ChevronDownIcon,
|
|
64
81
|
CopyIcon,
|
|
65
82
|
DownIcon,
|
|
83
|
+
EllipsisIcon,
|
|
66
84
|
FilterFullIcon,
|
|
67
85
|
FilterIcon,
|
|
68
86
|
FilterSlashIcon,
|
|
@@ -73,8 +91,14 @@ export {
|
|
|
73
91
|
PhoneIcon,
|
|
74
92
|
PlusIcon,
|
|
75
93
|
RightIcon,
|
|
94
|
+
SigmaIcon,
|
|
76
95
|
SpinnerIcon,
|
|
77
96
|
TableColumnsIcon,
|
|
97
|
+
TableFooterIcon,
|
|
98
|
+
TableFooterSlashIcon,
|
|
99
|
+
TableIcon,
|
|
100
|
+
TallyIcon,
|
|
78
101
|
UpIcon,
|
|
79
102
|
UserTieIcon,
|
|
103
|
+
XBarIcon,
|
|
80
104
|
};
|
|
@@ -95,8 +95,8 @@ export const AdvancedRequestDataGrid = <R,>({
|
|
|
95
95
|
})
|
|
96
96
|
).then((response) => {
|
|
97
97
|
if (getTotal) {
|
|
98
|
-
currentRows.current = Array(response.
|
|
99
|
-
if (getTotal) setTotal(response.
|
|
98
|
+
currentRows.current = Array(response.count).fill(null);
|
|
99
|
+
if (getTotal) setTotal(response.count ?? 0);
|
|
100
100
|
}
|
|
101
101
|
const parsedRows = parseJsonObjectFields(
|
|
102
102
|
response.data,
|
|
@@ -121,9 +121,7 @@ export const AdvancedRequestDataGrid = <R,>({
|
|
|
121
121
|
],
|
|
122
122
|
conditions: [
|
|
123
123
|
...(props.conditions ?? []),
|
|
124
|
-
...Object.values(
|
|
125
|
-
_.pickBy(conditions, (condition, key) => key !== columnKey)
|
|
126
|
-
),
|
|
124
|
+
...Object.values(_.pickBy(conditions, (_, key) => key !== columnKey)),
|
|
127
125
|
].filter((condition) => condition.field !== columnKey),
|
|
128
126
|
orderBy: [
|
|
129
127
|
{
|
|
@@ -12,8 +12,9 @@ export const useDataGridColumnsModal = <R,>(context: DataGridContext<R>) => {
|
|
|
12
12
|
const [currentColumns, setCurrentColumns] = useState(columns);
|
|
13
13
|
|
|
14
14
|
const openModal = useCallback(() => {
|
|
15
|
+
setCurrentColumns(columns);
|
|
15
16
|
setIsVisible(true);
|
|
16
|
-
}, []);
|
|
17
|
+
}, [columns]);
|
|
17
18
|
const closeModal = useCallback(() => {
|
|
18
19
|
setIsVisible(false);
|
|
19
20
|
}, []);
|
|
@@ -3,8 +3,29 @@
|
|
|
3
3
|
|
|
4
4
|
import * as styles from './styles';
|
|
5
5
|
|
|
6
|
-
import {
|
|
7
|
-
|
|
6
|
+
import {
|
|
7
|
+
ArrowDown19Icon,
|
|
8
|
+
ArrowDownAZIcon,
|
|
9
|
+
ArrowDownBigSmallIcon,
|
|
10
|
+
ArrowUp91Icon,
|
|
11
|
+
ArrowUpBigSmallIcon,
|
|
12
|
+
ArrowUpZAIcon,
|
|
13
|
+
FilterIcon,
|
|
14
|
+
FilterSlashIcon,
|
|
15
|
+
IconFC,
|
|
16
|
+
MagnifierIcon,
|
|
17
|
+
SigmaIcon,
|
|
18
|
+
TableFooterIcon,
|
|
19
|
+
TableFooterSlashIcon,
|
|
20
|
+
TallyIcon,
|
|
21
|
+
XBarIcon,
|
|
22
|
+
} from '../../../../Icons';
|
|
23
|
+
import {
|
|
24
|
+
DataGridContext,
|
|
25
|
+
DataGridFilterType,
|
|
26
|
+
DataGridFilterValue,
|
|
27
|
+
DataGridFooterPredefinedFunction,
|
|
28
|
+
} from '../types';
|
|
8
29
|
import {
|
|
9
30
|
applyFilters,
|
|
10
31
|
defaultRendererAndFormatter,
|
|
@@ -20,6 +41,7 @@ import {
|
|
|
20
41
|
useState,
|
|
21
42
|
} from 'react';
|
|
22
43
|
|
|
44
|
+
import { ContextMenu } from '../../../ui/ContextMenu';
|
|
23
45
|
import { FilterValuesScroller } from '../FilterValuesScroller';
|
|
24
46
|
import { Input } from '../../../forms';
|
|
25
47
|
import { useFilterModal } from './hooks';
|
|
@@ -31,6 +53,34 @@ type FilterValuesProps<R> = {
|
|
|
31
53
|
onClose?: () => void;
|
|
32
54
|
};
|
|
33
55
|
|
|
56
|
+
const sortAsc: Record<DataGridFilterType, [string, IconFC]> = {
|
|
57
|
+
number: ['Trier du plus petit au plus grand', ArrowDown19Icon],
|
|
58
|
+
text: ['Trier de A à Z', ArrowDownAZIcon],
|
|
59
|
+
// date: 'Trier du plus ancien au plus récent',
|
|
60
|
+
};
|
|
61
|
+
const sortDesc: Record<DataGridFilterType, [string, IconFC]> = {
|
|
62
|
+
number: ['Trier du plus grand au plus petit', ArrowUp91Icon],
|
|
63
|
+
text: ['Trier de Z à A', ArrowUpZAIcon],
|
|
64
|
+
// date: 'Trier du plus récent au plus ancien',
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const footerFunctionsTexts: Record<DataGridFooterPredefinedFunction, string> = {
|
|
68
|
+
average: 'Moyenne',
|
|
69
|
+
avg: 'Moyenne',
|
|
70
|
+
count: 'Nombre',
|
|
71
|
+
max: 'Maximum',
|
|
72
|
+
min: 'Minimum',
|
|
73
|
+
sum: 'Somme',
|
|
74
|
+
};
|
|
75
|
+
const footerFunctionsIcons: Record<DataGridFooterPredefinedFunction, IconFC> = {
|
|
76
|
+
average: XBarIcon,
|
|
77
|
+
avg: XBarIcon,
|
|
78
|
+
count: TallyIcon,
|
|
79
|
+
max: ArrowUpBigSmallIcon,
|
|
80
|
+
min: ArrowDownBigSmallIcon,
|
|
81
|
+
sum: SigmaIcon,
|
|
82
|
+
};
|
|
83
|
+
|
|
34
84
|
export const DataGridFilterMenu = <R,>({
|
|
35
85
|
columnKey,
|
|
36
86
|
context,
|
|
@@ -39,10 +89,13 @@ export const DataGridFilterMenu = <R,>({
|
|
|
39
89
|
const { openModal, modal } = useFilterModal({ columnKey, context });
|
|
40
90
|
const {
|
|
41
91
|
filters = {},
|
|
92
|
+
footers = {},
|
|
42
93
|
rows,
|
|
43
94
|
columns,
|
|
44
95
|
setFilters,
|
|
45
96
|
filterValuesLoader,
|
|
97
|
+
setSorts,
|
|
98
|
+
setFooters,
|
|
46
99
|
} = useContext(context);
|
|
47
100
|
const column = columns[columnKey] ?? {};
|
|
48
101
|
const textFilterInputRef = useRef<HTMLInputElement>(null);
|
|
@@ -63,7 +116,13 @@ export const DataGridFilterMenu = <R,>({
|
|
|
63
116
|
.map(([, filter]) => filter);
|
|
64
117
|
const availableRows = applyFilters(rows, otherFilters);
|
|
65
118
|
const values = availableRows.map((row) => column.filter!.getter(row));
|
|
66
|
-
setAvailableValues(() =>
|
|
119
|
+
setAvailableValues(() =>
|
|
120
|
+
uniq(values).sort(
|
|
121
|
+
column.filter?.type === 'number'
|
|
122
|
+
? (a, b) => (a as number) - (b as number)
|
|
123
|
+
: (a, b) => (a as string).localeCompare(b as string)
|
|
124
|
+
)
|
|
125
|
+
);
|
|
67
126
|
}
|
|
68
127
|
}, [column.filter, columnKey, filterValuesLoader, filters, rows]);
|
|
69
128
|
|
|
@@ -138,19 +197,10 @@ export const DataGridFilterMenu = <R,>({
|
|
|
138
197
|
}, []);
|
|
139
198
|
|
|
140
199
|
const checkboxesComponent = useMemo(() => {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
values={filteredAvailableValues}
|
|
146
|
-
selectedValues={selectedValues}
|
|
147
|
-
onToggle={toggleValues}
|
|
148
|
-
formatter={formatter}
|
|
149
|
-
renderer={renderer}
|
|
150
|
-
groups={groups}
|
|
151
|
-
/>
|
|
152
|
-
);
|
|
153
|
-
}
|
|
200
|
+
const groups =
|
|
201
|
+
column.type === 'date'
|
|
202
|
+
? getDateGroups(filteredAvailableValues)
|
|
203
|
+
: undefined;
|
|
154
204
|
return (
|
|
155
205
|
<FilterValuesScroller
|
|
156
206
|
values={filteredAvailableValues}
|
|
@@ -158,6 +208,7 @@ export const DataGridFilterMenu = <R,>({
|
|
|
158
208
|
onToggle={toggleValues}
|
|
159
209
|
formatter={formatter}
|
|
160
210
|
renderer={renderer}
|
|
211
|
+
groups={groups}
|
|
161
212
|
/>
|
|
162
213
|
);
|
|
163
214
|
}, [
|
|
@@ -169,17 +220,124 @@ export const DataGridFilterMenu = <R,>({
|
|
|
169
220
|
toggleValues,
|
|
170
221
|
]);
|
|
171
222
|
|
|
223
|
+
const onSortAscClicked = useCallback(() => {
|
|
224
|
+
setSorts({ [columnKey]: 'asc' });
|
|
225
|
+
onClose?.();
|
|
226
|
+
}, [columnKey, onClose, setSorts]);
|
|
227
|
+
const onSortDescClicked = useCallback(() => {
|
|
228
|
+
setSorts({ [columnKey]: 'desc' });
|
|
229
|
+
onClose?.();
|
|
230
|
+
}, [columnKey, onClose, setSorts]);
|
|
231
|
+
|
|
232
|
+
const hasFilters = filters[columnKey]?.values.length > 0;
|
|
233
|
+
const [[sortAscText, SortAscIcon], [sortDescText, SortDescIcon]] = [
|
|
234
|
+
sortAsc[column.filter?.type ?? 'text'],
|
|
235
|
+
sortDesc[column.filter?.type ?? 'text'],
|
|
236
|
+
];
|
|
237
|
+
|
|
238
|
+
const isFooterVisible =
|
|
239
|
+
columnKey in footers && footers[columnKey] !== undefined;
|
|
240
|
+
const showFooter = useCallback(
|
|
241
|
+
(key: string) => {
|
|
242
|
+
setFooters((prevFooters) => ({
|
|
243
|
+
...prevFooters,
|
|
244
|
+
[columnKey]: key,
|
|
245
|
+
}));
|
|
246
|
+
onClose?.();
|
|
247
|
+
},
|
|
248
|
+
[columnKey, onClose, setFooters]
|
|
249
|
+
);
|
|
250
|
+
const hideFooter = useCallback(() => {
|
|
251
|
+
setFooters((prevFooters) => {
|
|
252
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
253
|
+
const { [columnKey]: _, ...newFooters } = prevFooters;
|
|
254
|
+
return newFooters;
|
|
255
|
+
});
|
|
256
|
+
onClose?.();
|
|
257
|
+
}, [columnKey, onClose, setFooters]);
|
|
258
|
+
|
|
172
259
|
return (
|
|
173
|
-
<
|
|
260
|
+
<ContextMenu>
|
|
174
261
|
{modal}
|
|
175
|
-
|
|
262
|
+
{column.sortGetter && (
|
|
263
|
+
<>
|
|
264
|
+
<ContextMenu.Item onClick={onSortAscClicked}>
|
|
265
|
+
<SortAscIcon />
|
|
266
|
+
{sortAscText}
|
|
267
|
+
</ContextMenu.Item>
|
|
268
|
+
<ContextMenu.Item onClick={onSortDescClicked}>
|
|
269
|
+
<SortDescIcon />
|
|
270
|
+
{sortDescText}
|
|
271
|
+
</ContextMenu.Item>
|
|
272
|
+
<ContextMenu.Divider />
|
|
273
|
+
</>
|
|
274
|
+
)}
|
|
275
|
+
{isFooterVisible && typeof column.footer === 'function' && (
|
|
276
|
+
<>
|
|
277
|
+
<ContextMenu.Item onClick={hideFooter}>
|
|
278
|
+
<TableFooterSlashIcon />
|
|
279
|
+
Masquer le total
|
|
280
|
+
</ContextMenu.Item>
|
|
281
|
+
<ContextMenu.Divider />
|
|
282
|
+
</>
|
|
283
|
+
)}
|
|
284
|
+
{!isFooterVisible && typeof column.footer === 'function' && (
|
|
285
|
+
<>
|
|
286
|
+
<ContextMenu.Item onClick={() => showFooter('count')}>
|
|
287
|
+
<TableFooterIcon />
|
|
288
|
+
Afficher le total
|
|
289
|
+
</ContextMenu.Item>
|
|
290
|
+
<ContextMenu.Divider />
|
|
291
|
+
</>
|
|
292
|
+
)}
|
|
293
|
+
{typeof column.footer === 'object' && (
|
|
294
|
+
<>
|
|
295
|
+
<ContextMenu.ParentItem>
|
|
296
|
+
<TableFooterIcon />
|
|
297
|
+
Afficher le total
|
|
298
|
+
<ContextMenu.SubMenu>
|
|
299
|
+
{Object.keys(column.footer).map((key) => {
|
|
300
|
+
const TotalIcon =
|
|
301
|
+
footerFunctionsIcons[
|
|
302
|
+
key as DataGridFooterPredefinedFunction
|
|
303
|
+
] ?? TableFooterIcon;
|
|
304
|
+
return (
|
|
305
|
+
<ContextMenu.Item key={key} onClick={() => showFooter(key)}>
|
|
306
|
+
<TotalIcon />
|
|
307
|
+
{key in footerFunctionsTexts
|
|
308
|
+
? footerFunctionsTexts[
|
|
309
|
+
key as DataGridFooterPredefinedFunction
|
|
310
|
+
]
|
|
311
|
+
: key}
|
|
312
|
+
</ContextMenu.Item>
|
|
313
|
+
);
|
|
314
|
+
})}
|
|
315
|
+
<ContextMenu.Divider />
|
|
316
|
+
<ContextMenu.Item
|
|
317
|
+
onClick={hideFooter}
|
|
318
|
+
disabled={!isFooterVisible}
|
|
319
|
+
>
|
|
320
|
+
<TableFooterSlashIcon />
|
|
321
|
+
Masquer le total
|
|
322
|
+
</ContextMenu.Item>
|
|
323
|
+
</ContextMenu.SubMenu>
|
|
324
|
+
</ContextMenu.ParentItem>
|
|
325
|
+
<ContextMenu.Divider />
|
|
326
|
+
</>
|
|
327
|
+
)}
|
|
328
|
+
<ContextMenu.Item onClick={openModal}>
|
|
176
329
|
<FilterIcon />
|
|
177
330
|
Filtrer ...
|
|
178
|
-
</
|
|
179
|
-
<
|
|
331
|
+
</ContextMenu.Item>
|
|
332
|
+
<ContextMenu.Item
|
|
333
|
+
$color="danger"
|
|
334
|
+
onClick={clearFilter}
|
|
335
|
+
disabled={!hasFilters}
|
|
336
|
+
>
|
|
180
337
|
<FilterSlashIcon />
|
|
181
338
|
Supprimer le filtre
|
|
182
|
-
</
|
|
339
|
+
</ContextMenu.Item>
|
|
340
|
+
<ContextMenu.Divider />
|
|
183
341
|
<styles.InputContainer>
|
|
184
342
|
<MagnifierIcon />
|
|
185
343
|
<Input
|
|
@@ -195,6 +353,6 @@ export const DataGridFilterMenu = <R,>({
|
|
|
195
353
|
<styles.CheckboxesContainer>
|
|
196
354
|
{checkboxesComponent}
|
|
197
355
|
</styles.CheckboxesContainer>
|
|
198
|
-
</
|
|
356
|
+
</ContextMenu>
|
|
199
357
|
);
|
|
200
358
|
};
|
|
@@ -1,70 +1,11 @@
|
|
|
1
|
-
import styled
|
|
2
|
-
|
|
3
|
-
import { ThemeColor } from '../../../../providers/ThemeProvider/types';
|
|
4
|
-
|
|
5
|
-
export const Menu = styled.div.attrs({
|
|
6
|
-
className: 'Menu',
|
|
7
|
-
})`
|
|
8
|
-
position: absolute;
|
|
9
|
-
inset: 0;
|
|
10
|
-
color: var(--color-neutral-900);
|
|
11
|
-
border-radius: var(--rounded-md);
|
|
12
|
-
padding: var(--space-1) 0;
|
|
13
|
-
box-shadow: var(--shadow-lg);
|
|
14
|
-
background-color: var(--color-neutral-100);
|
|
15
|
-
min-width: 20em;
|
|
16
|
-
outline: 1px solid var(--color-neutral-200);
|
|
17
|
-
display: flex;
|
|
18
|
-
flex-direction: column;
|
|
19
|
-
`;
|
|
20
|
-
|
|
21
|
-
export const MenuItem = styled.button.attrs({
|
|
22
|
-
className: 'MenuItem',
|
|
23
|
-
})<{ $color?: ThemeColor }>`
|
|
24
|
-
display: flex;
|
|
25
|
-
align-items: center;
|
|
26
|
-
width: 100%;
|
|
27
|
-
font-family: var(--font-sans);
|
|
28
|
-
font-weight: normal;
|
|
29
|
-
text-align: left;
|
|
30
|
-
padding: var(--space-1) var(--space-2);
|
|
31
|
-
font-size: var(--text-base);
|
|
32
|
-
line-height: var(--leading-6);
|
|
33
|
-
border: none;
|
|
34
|
-
cursor: pointer;
|
|
35
|
-
|
|
36
|
-
${({ $color }) =>
|
|
37
|
-
$color
|
|
38
|
-
? css`
|
|
39
|
-
color: var(--color-${$color}-600);
|
|
40
|
-
background-color: var(--color-neutral-100);
|
|
41
|
-
&:hover {
|
|
42
|
-
background-color: var(--color-${$color}-200);
|
|
43
|
-
}
|
|
44
|
-
`
|
|
45
|
-
: css`
|
|
46
|
-
color: var(--color-neutral-900);
|
|
47
|
-
background-color: var(--color-neutral-100);
|
|
48
|
-
&:hover {
|
|
49
|
-
background-color: var(--color-neutral-200);
|
|
50
|
-
}
|
|
51
|
-
`}
|
|
52
|
-
|
|
53
|
-
svg {
|
|
54
|
-
fill: currentColor;
|
|
55
|
-
width: var(--space-4);
|
|
56
|
-
height: var(--space-4);
|
|
57
|
-
margin-right: var(--space-2);
|
|
58
|
-
}
|
|
59
|
-
`;
|
|
1
|
+
import styled from 'styled-components';
|
|
60
2
|
|
|
61
3
|
export const InputContainer = styled.div.attrs({
|
|
62
4
|
className: 'InputContainer',
|
|
63
5
|
})`
|
|
64
6
|
position: relative;
|
|
65
7
|
border-radius: var(--rounded-md);
|
|
66
|
-
padding: 0 var(--space-
|
|
67
|
-
margin-top: var(--space-1);
|
|
8
|
+
padding: 0 var(--space-1);
|
|
68
9
|
|
|
69
10
|
svg {
|
|
70
11
|
position: absolute;
|
|
@@ -89,12 +30,20 @@ export const CheckboxesContainer = styled.div.attrs({
|
|
|
89
30
|
font-weight: normal;
|
|
90
31
|
user-select: none;
|
|
91
32
|
padding: var(--space-2);
|
|
92
|
-
margin: var(--space-
|
|
93
|
-
|
|
33
|
+
margin: var(--space-1);
|
|
34
|
+
margin-bottom: 0;
|
|
35
|
+
border: 1px solid var(--color-neutral-300);
|
|
94
36
|
border-radius: var(--rounded-md);
|
|
95
37
|
box-shadow: var(--shadow-inner);
|
|
96
|
-
background-color: var(--color-neutral-
|
|
38
|
+
background-color: var(--color-neutral-0);
|
|
97
39
|
height: 20em;
|
|
98
40
|
overflow-y: hidden;
|
|
99
41
|
white-space: nowrap;
|
|
100
42
|
`;
|
|
43
|
+
|
|
44
|
+
export const Separator = styled.div.attrs({
|
|
45
|
+
className: 'Separator',
|
|
46
|
+
})`
|
|
47
|
+
border-top: 1px solid var(--color-neutral-200);
|
|
48
|
+
margin: var(--space-1) 0;
|
|
49
|
+
`;
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
2
|
/* eslint-disable @typescript-eslint/no-unnecessary-type-constraint */
|
|
3
3
|
|
|
4
|
+
import * as styles from './styles';
|
|
5
|
+
|
|
4
6
|
import { DataGridContext } from './types';
|
|
5
|
-
import { getScrollBarSize } from '../../../helpers/getScrollbarSize';
|
|
6
7
|
import { useDataGridContext } from './hooks';
|
|
7
8
|
|
|
8
|
-
const SCROLL_BAR_SIZE = getScrollBarSize();
|
|
9
|
-
|
|
10
9
|
export const DataGridFooter = <R,>({
|
|
11
10
|
context,
|
|
12
11
|
}: {
|
|
@@ -17,28 +16,27 @@ export const DataGridFooter = <R,>({
|
|
|
17
16
|
rows,
|
|
18
17
|
selectedRows,
|
|
19
18
|
sortedRows,
|
|
20
|
-
rowHeight = 48,
|
|
21
19
|
selectable,
|
|
20
|
+
footers = {},
|
|
21
|
+
gridTemplateColumns,
|
|
22
|
+
footerFunctions,
|
|
22
23
|
} = useDataGridContext(context);
|
|
23
24
|
|
|
25
|
+
if (!Object.keys(footers).length) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
|
|
24
29
|
return (
|
|
25
|
-
<
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
{visibleColumns.map(([key, col]) => (
|
|
37
|
-
<div key={key} style={{ width: (col.width ?? 150) + 'px' }}>
|
|
38
|
-
{col.footer?.(rows, sortedRows, selectedRows)}
|
|
39
|
-
</div>
|
|
40
|
-
))}
|
|
41
|
-
</tr>
|
|
42
|
-
</tfoot>
|
|
30
|
+
<styles.DataGridFooterRow $gridTemplateColumns={gridTemplateColumns}>
|
|
31
|
+
{!!selectable && <styles.HeaderSelectionCell />}
|
|
32
|
+
{visibleColumns.map(([key, col]) => (
|
|
33
|
+
<styles.DataGridHeaderCellContainer
|
|
34
|
+
key={key}
|
|
35
|
+
style={{ width: (col.width ?? 150) + 'px' }}
|
|
36
|
+
>
|
|
37
|
+
{footerFunctions?.[key]?.(rows, sortedRows, selectedRows)}
|
|
38
|
+
</styles.DataGridHeaderCellContainer>
|
|
39
|
+
))}
|
|
40
|
+
</styles.DataGridFooterRow>
|
|
43
41
|
);
|
|
44
42
|
};
|
|
@@ -102,11 +102,11 @@ export const DataGridHeader = <R,>({
|
|
|
102
102
|
$headerColor={headerColor}
|
|
103
103
|
>
|
|
104
104
|
{!!selectable && (
|
|
105
|
-
<styles.HeaderSelectionCell
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
/>
|
|
105
|
+
<styles.HeaderSelectionCell
|
|
106
|
+
$headerColor={headerColor}
|
|
107
|
+
onClick={() => toggleAll(!(checkboxStatus ?? true))}
|
|
108
|
+
>
|
|
109
|
+
<IndeterminateCheckbox checked={checkboxStatus} readOnly />
|
|
110
110
|
</styles.HeaderSelectionCell>
|
|
111
111
|
)}
|
|
112
112
|
{visibleColumns.map(([key, col], index) => (
|