ydb-embedded-ui 6.1.0 → 6.2.1
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/components/DateRange/DateRange.scss +7 -0
- package/dist/components/EntityStatus/EntityStatus.d.ts +3 -1
- package/dist/components/EntityStatus/EntityStatus.js +4 -4
- package/dist/components/EntityStatus/EntityStatus.scss +2 -10
- package/dist/components/NodeHostWrapper/NodeHostWrapper.js +3 -2
- package/dist/components/NodeHostWrapper/NodeHostWrapper.scss +1 -10
- package/dist/components/QueryResultTable/QueryResultTable.d.ts +2 -2
- package/dist/components/QueryResultTable/QueryResultTable.js +2 -1
- package/dist/components/QueryResultTable/QueryResultTable.scss +1 -0
- package/dist/components/ResizeableDataTable/ResizeableDataTable.d.ts +7 -0
- package/dist/components/ResizeableDataTable/ResizeableDataTable.js +14 -0
- package/dist/components/ResizeableDataTable/ResizeableDataTable.scss +8 -0
- package/dist/components/VirtualTable/ResizeHandler.d.ts +8 -0
- package/dist/components/VirtualTable/ResizeHandler.js +62 -0
- package/dist/components/VirtualTable/ResizeableVirtualTable.d.ts +6 -0
- package/dist/components/VirtualTable/ResizeableVirtualTable.js +16 -0
- package/dist/components/VirtualTable/TableHead.d.ts +3 -3
- package/dist/components/VirtualTable/TableHead.js +16 -31
- package/dist/components/VirtualTable/VirtualTable.d.ts +2 -4
- package/dist/components/VirtualTable/VirtualTable.scss +24 -4
- package/dist/components/VirtualTable/types.d.ts +3 -0
- package/dist/components/VirtualTable/utils.d.ts +2 -0
- package/dist/components/VirtualTable/utils.js +21 -0
- package/dist/containers/ClusterModeGuard/ClusterModeGuard.js +1 -1
- package/dist/containers/Clusters/Clusters.js +3 -2
- package/dist/containers/Clusters/Clusters.scss +5 -0
- package/dist/containers/Clusters/columns.d.ts +1 -0
- package/dist/containers/Clusters/columns.js +4 -3
- package/dist/containers/Nodes/Nodes.js +4 -4
- package/dist/containers/Nodes/Nodes.scss +0 -5
- package/dist/containers/Nodes/VirtualNodes.js +4 -6
- package/dist/containers/Nodes/getNodesColumns.d.ts +1 -0
- package/dist/containers/Nodes/getNodesColumns.js +9 -1
- package/dist/containers/PDiskPage/PDiskGroups.js +3 -3
- package/dist/containers/Storage/Storage.scss +0 -4
- package/dist/containers/Storage/StorageGroups/StorageGroups.js +3 -3
- package/dist/containers/Storage/StorageGroups/VirtualStorageGroups.js +3 -3
- package/dist/containers/Storage/StorageGroups/getStorageGroupsColumns.d.ts +3 -0
- package/dist/containers/Storage/StorageGroups/getStorageGroupsColumns.js +7 -3
- package/dist/containers/Storage/StorageNodes/StorageNodes.js +3 -3
- package/dist/containers/Storage/StorageNodes/VirtualStorageNodes.js +3 -3
- package/dist/containers/Storage/StorageNodes/getStorageNodesColumns.d.ts +3 -0
- package/dist/containers/Storage/StorageNodes/getStorageNodesColumns.js +2 -0
- package/dist/containers/Tablet/Tablet.scss +0 -4
- package/dist/containers/Tablet/TabletTable/TabletTable.js +5 -3
- package/dist/containers/Tenant/Acl/Acl.js +3 -2
- package/dist/containers/Tenant/Acl/Acl.scss +0 -6
- package/dist/containers/Tenant/Diagnostics/Consumers/Consumers.js +3 -3
- package/dist/containers/Tenant/Diagnostics/Consumers/Consumers.scss +2 -0
- package/dist/containers/Tenant/Diagnostics/Consumers/columns/columns.d.ts +1 -0
- package/dist/containers/Tenant/Diagnostics/Consumers/columns/columns.js +2 -0
- package/dist/containers/Tenant/Diagnostics/HotKeys/HotKeys.js +5 -4
- package/dist/containers/Tenant/Diagnostics/HotKeys/HotKeys.scss +1 -5
- package/dist/containers/Tenant/Diagnostics/Partitions/Partitions.js +8 -4
- package/dist/containers/Tenant/Diagnostics/Partitions/Partitions.scss +2 -0
- package/dist/containers/Tenant/Diagnostics/Partitions/PartitionsControls/PartitionsControls.js +1 -1
- package/dist/containers/Tenant/Diagnostics/Partitions/columns/Columns.scss +0 -8
- package/dist/containers/Tenant/Diagnostics/Partitions/columns/columns.d.ts +1 -0
- package/dist/containers/Tenant/Diagnostics/Partitions/columns/columns.js +11 -4
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/TopNodesByCpu.js +2 -2
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/TopNodesByLoad.js +2 -2
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/TopQueries.js +3 -2
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/TopShards.js +2 -2
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantMemory/TopNodesByMemory.js +2 -2
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.scss +3 -7
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverviewTableLayout.d.ts +2 -2
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverviewTableLayout.js +2 -2
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantStorage/TopGroups.js +2 -2
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantStorage/TopTables.js +4 -2
- package/dist/containers/Tenant/Diagnostics/TopQueries/TopQueries.js +8 -11
- package/dist/containers/Tenant/Diagnostics/TopQueries/TopQueries.scss +2 -24
- package/dist/containers/Tenant/Diagnostics/TopQueries/getTopQueriesColumns.d.ts +1 -0
- package/dist/containers/Tenant/Diagnostics/TopQueries/getTopQueriesColumns.js +7 -0
- package/dist/containers/Tenant/Diagnostics/TopShards/Filters/Filters.d.ts +1 -2
- package/dist/containers/Tenant/Diagnostics/TopShards/Filters/Filters.js +3 -4
- package/dist/containers/Tenant/Diagnostics/TopShards/TopShards.d.ts +0 -1
- package/dist/containers/Tenant/Diagnostics/TopShards/TopShards.js +8 -10
- package/dist/containers/Tenant/Diagnostics/TopShards/TopShards.scss +4 -15
- package/dist/containers/Tenant/Diagnostics/TopShards/getTopShardsColumns.d.ts +1 -0
- package/dist/containers/Tenant/Diagnostics/TopShards/getTopShardsColumns.js +5 -0
- package/dist/containers/Tenant/ObjectSummary/ObjectSummary.js +1 -1
- package/dist/containers/Tenant/ObjectSummary/ObjectSummary.scss +0 -6
- package/dist/containers/Tenant/Query/ExecuteResult/ExecuteResult.scss +1 -21
- package/dist/containers/Tenant/Query/ExplainResult/ExplainResult.js +4 -4
- package/dist/containers/Tenant/Query/ExplainResult/utils.d.ts +0 -3
- package/dist/containers/Tenant/Query/ExplainResult/utils.js +0 -34
- package/dist/containers/Tenant/Query/Preview/Preview.js +3 -2
- package/dist/containers/Tenant/Query/Preview/Preview.scss +6 -3
- package/dist/containers/Tenant/Query/QueriesHistory/QueriesHistory.js +4 -2
- package/dist/containers/Tenant/Query/QueriesHistory/QueriesHistory.scss +0 -1
- package/dist/containers/Tenant/Query/QueryEditor/helpers.js +2 -1
- package/dist/containers/Tenant/Query/SavedQueries/SavedQueries.js +4 -1
- package/dist/containers/Tenant/Query/SavedQueries/SavedQueries.scss +0 -1
- package/dist/containers/Tenant/Schema/SchemaViewer/SchemaViewer.d.ts +1 -2
- package/dist/containers/Tenant/Schema/SchemaViewer/SchemaViewer.js +4 -3
- package/dist/containers/Tenant/Schema/SchemaViewer/helpers.d.ts +1 -0
- package/dist/containers/Tenant/Schema/SchemaViewer/helpers.js +4 -2
- package/dist/containers/Tenants/Tenants.js +12 -7
- package/dist/containers/Tenants/Tenants.scss +15 -9
- package/dist/containers/Versions/GroupedNodesTree/GroupedNodesTree.scss +0 -2
- package/dist/containers/Versions/NodesTable/NodesTable.js +14 -9
- package/dist/styles/mixins.scss +0 -47
- package/dist/utils/constants.d.ts +25 -10
- package/dist/utils/hooks/useTableResize.d.ts +2 -7
- package/dist/utils/hooks/useTableResize.js +12 -24
- package/package.json +10 -10
- package/dist/containers/Tenant/Diagnostics/TopShards/Filters/Filters.scss +0 -8
@@ -1,11 +1,18 @@
|
|
1
1
|
.date-range {
|
2
2
|
&__input {
|
3
3
|
min-width: 190px;
|
4
|
+
height: 28px;
|
4
5
|
padding: 5px 8px;
|
5
6
|
|
6
7
|
color: var(--g-color-text-primary);
|
7
8
|
border: 1px solid var(--g-color-line-generic);
|
8
9
|
border-radius: var(--g-border-radius-m);
|
10
|
+
outline: none;
|
9
11
|
background: transparent;
|
10
12
|
}
|
13
|
+
|
14
|
+
&__input:focus,
|
15
|
+
&__input:focus-visible {
|
16
|
+
border: 1px solid var(--g-color-line-generic-hover);
|
17
|
+
}
|
11
18
|
}
|
@@ -1,3 +1,4 @@
|
|
1
|
+
/// <reference types="react" />
|
1
2
|
import { EFlag } from '../../types/api/enums';
|
2
3
|
import type { StatusIconMode, StatusIconSize } from '../StatusIcon/StatusIcon';
|
3
4
|
import './EntityStatus.scss';
|
@@ -15,6 +16,7 @@ interface EntityStatusProps {
|
|
15
16
|
hasClipboardButton?: boolean;
|
16
17
|
clipboardButtonAlwaysVisible?: boolean;
|
17
18
|
className?: string;
|
19
|
+
additionalControls?: React.ReactNode;
|
18
20
|
}
|
19
|
-
export declare function EntityStatus({ status, name, label, path, iconPath, size, mode, showStatus, externalLink, withLeftTrim, hasClipboardButton, clipboardButtonAlwaysVisible, className, }: EntityStatusProps): import("react/jsx-runtime").JSX.Element;
|
21
|
+
export declare function EntityStatus({ status, name, label, path, iconPath, size, mode, showStatus, externalLink, withLeftTrim, hasClipboardButton, clipboardButtonAlwaysVisible, className, additionalControls, }: EntityStatusProps): import("react/jsx-runtime").JSX.Element;
|
20
22
|
export {};
|
@@ -1,13 +1,13 @@
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
2
2
|
import { Link as UIKitLink } from '@gravity-ui/uikit';
|
3
|
-
import { Link } from 'react-router-dom';
|
4
3
|
import { EFlag } from '../../types/api/enums';
|
5
4
|
import { cn } from '../../utils/cn';
|
6
5
|
import { ClipboardButton } from '../ClipboardButton';
|
6
|
+
import { InternalLink } from '../InternalLink/InternalLink';
|
7
7
|
import { StatusIcon } from '../StatusIcon/StatusIcon';
|
8
8
|
import './EntityStatus.scss';
|
9
9
|
const b = cn('entity-status');
|
10
|
-
export function EntityStatus({ status = EFlag.Grey, name = '', label, path, iconPath, size = 's', mode = 'color', showStatus = true, externalLink = false, withLeftTrim = false, hasClipboardButton, clipboardButtonAlwaysVisible = false, className, }) {
|
10
|
+
export function EntityStatus({ status = EFlag.Grey, name = '', label, path, iconPath, size = 's', mode = 'color', showStatus = true, externalLink = false, withLeftTrim = false, hasClipboardButton, clipboardButtonAlwaysVisible = false, className, additionalControls, }) {
|
11
11
|
const renderIcon = () => {
|
12
12
|
if (!showStatus) {
|
13
13
|
return null;
|
@@ -22,11 +22,11 @@ export function EntityStatus({ status = EFlag.Grey, name = '', label, path, icon
|
|
22
22
|
if (externalLink) {
|
23
23
|
return (_jsx(UIKitLink, { className: b('name'), href: path, children: name }));
|
24
24
|
}
|
25
|
-
return (_jsx(
|
25
|
+
return (_jsx(InternalLink, { className: b('name'), to: path, children: name }));
|
26
26
|
}
|
27
27
|
return name && _jsx("span", { className: b('name'), children: name });
|
28
28
|
};
|
29
29
|
return (_jsxs("div", { className: b(null, className), title: name, children: [iconPath ? renderStatusLink(iconPath) : renderIcon(), label && (_jsx("span", { title: label, className: b('label', { size, state: status.toLowerCase() }), children: label })), _jsx("span", { className: b('link', { 'with-left-trim': withLeftTrim }), children: renderLink() }), hasClipboardButton && (_jsx(ClipboardButton, { text: name, size: "s", className: b('clipboard-button', {
|
30
30
|
visible: clipboardButtonAlwaysVisible,
|
31
|
-
}) }))] }));
|
31
|
+
}) })), additionalControls] }));
|
32
32
|
}
|
@@ -14,7 +14,9 @@
|
|
14
14
|
}
|
15
15
|
|
16
16
|
&__clipboard-button {
|
17
|
+
display: flex;
|
17
18
|
visibility: hidden;
|
19
|
+
flex-shrink: 0;
|
18
20
|
|
19
21
|
margin-left: 8px;
|
20
22
|
|
@@ -25,16 +27,6 @@
|
|
25
27
|
}
|
26
28
|
}
|
27
29
|
|
28
|
-
a {
|
29
|
-
text-decoration: none;
|
30
|
-
|
31
|
-
color: var(--g-color-text-link);
|
32
|
-
}
|
33
|
-
|
34
|
-
a:hover {
|
35
|
-
color: var(--g-color-text-link-hover);
|
36
|
-
}
|
37
|
-
|
38
30
|
&__label {
|
39
31
|
margin-right: 2px;
|
40
32
|
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import { jsx as _jsx
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
2
2
|
import { Button, PopoverBehavior } from '@gravity-ui/uikit';
|
3
3
|
import { getDefaultNodePath } from '../../containers/Node/NodePages';
|
4
4
|
import { cn } from '../../utils/cn';
|
@@ -20,5 +20,6 @@ export const NodeHostWrapper = ({ node, getNodeRef }) => {
|
|
20
20
|
tenantName: node.TenantName,
|
21
21
|
})
|
22
22
|
: undefined;
|
23
|
-
|
23
|
+
const additionalControls = nodeRef ? (_jsx(Button, { size: "s", href: nodeRef, className: b('external-button'), target: "_blank", children: _jsx(Icon, { name: "external" }) })) : null;
|
24
|
+
return (_jsx(CellWithPopover, { disabled: !isNodeAvailable, content: _jsx(NodeEndpointsTooltipContent, { data: node }), placement: ['top', 'bottom'], behavior: PopoverBehavior.Immediate, children: _jsx(EntityStatus, { name: node.Host, status: node.SystemState, path: nodePath, hasClipboardButton: true, additionalControls: additionalControls }) }));
|
24
25
|
};
|
@@ -1,8 +1,8 @@
|
|
1
|
-
import type { DataTableProps } from '@gravity-ui/react-data-table';
|
2
1
|
import type { ColumnType, KeyValueRow } from '../../types/api/query';
|
2
|
+
import type { ResizeableDataTableProps } from '../ResizeableDataTable/ResizeableDataTable';
|
3
3
|
import './QueryResultTable.scss';
|
4
4
|
export declare const b: import("@bem-react/classname").ClassNameFormatter;
|
5
|
-
interface QueryResultTableProps extends Omit<
|
5
|
+
interface QueryResultTableProps extends Omit<ResizeableDataTableProps<KeyValueRow>, 'data' | 'columns'> {
|
6
6
|
data?: KeyValueRow[];
|
7
7
|
columns?: ColumnType[];
|
8
8
|
}
|
@@ -6,6 +6,7 @@ import { cn } from '../../utils/cn';
|
|
6
6
|
import { DEFAULT_TABLE_SETTINGS } from '../../utils/constants';
|
7
7
|
import { getColumnType, prepareQueryResponse } from '../../utils/query';
|
8
8
|
import { isNumeric } from '../../utils/utils';
|
9
|
+
import { ResizeableDataTable } from '../ResizeableDataTable/ResizeableDataTable';
|
9
10
|
import { Cell } from './Cell';
|
10
11
|
import i18n from './i18n';
|
11
12
|
import './QueryResultTable.scss';
|
@@ -62,7 +63,7 @@ export const QueryResultTable = (props) => {
|
|
62
63
|
if (!columns.length) {
|
63
64
|
return _jsx("div", { className: b('message'), children: i18n('empty') });
|
64
65
|
}
|
65
|
-
return (_jsx(
|
66
|
+
return (_jsx(ResizeableDataTable, Object.assign({ data: data, columns: columns, settings: settings,
|
66
67
|
// prevent accessing row.id in case it is present but is not the PK (i.e. may repeat)
|
67
68
|
rowKey: getRowIndex }, restProps)));
|
68
69
|
};
|
@@ -0,0 +1,7 @@
|
|
1
|
+
import type { DataTableProps } from '@gravity-ui/react-data-table';
|
2
|
+
import './ResizeableDataTable.scss';
|
3
|
+
export interface ResizeableDataTableProps<T> extends Omit<DataTableProps<T>, 'theme' | 'onResize'> {
|
4
|
+
columnsWidthLSKey?: string;
|
5
|
+
wrapperClassName?: string;
|
6
|
+
}
|
7
|
+
export declare function ResizeableDataTable<T>({ columnsWidthLSKey, columns, settings, wrapperClassName, ...props }: ResizeableDataTableProps<T>): import("react/jsx-runtime").JSX.Element;
|
@@ -0,0 +1,14 @@
|
|
1
|
+
import { __rest } from "tslib";
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
3
|
+
import DataTable, { updateColumnsWidth } from '@gravity-ui/react-data-table';
|
4
|
+
import { cn } from '../../utils/cn';
|
5
|
+
import { useTableResize } from '../../utils/hooks/useTableResize';
|
6
|
+
import './ResizeableDataTable.scss';
|
7
|
+
const b = cn('ydb-resizeable-data-table');
|
8
|
+
export function ResizeableDataTable(_a) {
|
9
|
+
var { columnsWidthLSKey, columns, settings, wrapperClassName } = _a, props = __rest(_a, ["columnsWidthLSKey", "columns", "settings", "wrapperClassName"]);
|
10
|
+
const [tableColumnsWidth, setTableColumnsWidth] = useTableResize(columnsWidthLSKey);
|
11
|
+
const updatedColumns = updateColumnsWidth(columns, tableColumnsWidth);
|
12
|
+
const newSettings = Object.assign(Object.assign({}, settings), { defaultResizeable: true });
|
13
|
+
return (_jsx("div", { className: b(null, wrapperClassName), children: _jsx(DataTable, Object.assign({ theme: "yandex-cloud", columns: updatedColumns, onResize: setTableColumnsWidth, settings: newSettings }, props)) }));
|
14
|
+
}
|
@@ -0,0 +1,8 @@
|
|
1
|
+
interface ResizeHandlerProps {
|
2
|
+
maxWidth?: number;
|
3
|
+
minWidth?: number;
|
4
|
+
getCurrentColumnWidth: () => number | undefined;
|
5
|
+
onResize?: (width: number) => void;
|
6
|
+
}
|
7
|
+
export declare function ResizeHandler({ minWidth, maxWidth, getCurrentColumnWidth, onResize, }: ResizeHandlerProps): import("react/jsx-runtime").JSX.Element;
|
8
|
+
export {};
|
@@ -0,0 +1,62 @@
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
2
|
+
import React from 'react';
|
3
|
+
import { b } from './shared';
|
4
|
+
import { calculateColumnWidth, rafThrottle } from './utils';
|
5
|
+
export function ResizeHandler({ minWidth, maxWidth, getCurrentColumnWidth, onResize, }) {
|
6
|
+
const elementRef = React.useRef(null);
|
7
|
+
const [resizing, setResizing] = React.useState(false);
|
8
|
+
React.useEffect(() => {
|
9
|
+
const element = elementRef.current;
|
10
|
+
if (!element) {
|
11
|
+
return undefined;
|
12
|
+
}
|
13
|
+
let mouseXPosition;
|
14
|
+
let initialColumnWidth;
|
15
|
+
let currentColumnWidth;
|
16
|
+
const onMouseMove = rafThrottle((e) => {
|
17
|
+
restrictMouseEvent(e);
|
18
|
+
if (typeof mouseXPosition !== 'number' || typeof initialColumnWidth !== 'number') {
|
19
|
+
return;
|
20
|
+
}
|
21
|
+
const xDiff = e.clientX - mouseXPosition;
|
22
|
+
const newWidth = calculateColumnWidth(initialColumnWidth + xDiff, minWidth, maxWidth);
|
23
|
+
if (newWidth === currentColumnWidth) {
|
24
|
+
return;
|
25
|
+
}
|
26
|
+
currentColumnWidth = newWidth;
|
27
|
+
onResize === null || onResize === void 0 ? void 0 : onResize(currentColumnWidth);
|
28
|
+
});
|
29
|
+
const onMouseUp = (e) => {
|
30
|
+
restrictMouseEvent(e);
|
31
|
+
if (currentColumnWidth !== undefined) {
|
32
|
+
onResize === null || onResize === void 0 ? void 0 : onResize(currentColumnWidth);
|
33
|
+
}
|
34
|
+
setResizing(false);
|
35
|
+
mouseXPosition = undefined;
|
36
|
+
document.removeEventListener('mousemove', onMouseMove);
|
37
|
+
document.removeEventListener('mouseup', onMouseUp);
|
38
|
+
};
|
39
|
+
const onMouseDown = (e) => {
|
40
|
+
initialColumnWidth = getCurrentColumnWidth();
|
41
|
+
restrictMouseEvent(e);
|
42
|
+
mouseXPosition = e.clientX;
|
43
|
+
setResizing(true);
|
44
|
+
document.addEventListener('mousemove', onMouseMove);
|
45
|
+
document.addEventListener('mouseup', onMouseUp);
|
46
|
+
};
|
47
|
+
element.addEventListener('mousedown', onMouseDown);
|
48
|
+
return () => {
|
49
|
+
element.removeEventListener('mousedown', onMouseDown);
|
50
|
+
document.removeEventListener('mousemove', onMouseMove);
|
51
|
+
document.removeEventListener('mouseup', onMouseUp);
|
52
|
+
};
|
53
|
+
}, [onResize, minWidth, maxWidth, getCurrentColumnWidth]);
|
54
|
+
return (_jsx("span", { ref: elementRef, className: b('resize-handler', { resizing }),
|
55
|
+
// Prevent sort trigger on resize
|
56
|
+
onClick: (e) => restrictMouseEvent(e) }));
|
57
|
+
}
|
58
|
+
// Prevent sort trigger and text selection on resize
|
59
|
+
function restrictMouseEvent(e) {
|
60
|
+
e.preventDefault();
|
61
|
+
e.stopPropagation();
|
62
|
+
}
|
@@ -0,0 +1,6 @@
|
|
1
|
+
import type { VirtualTableProps } from './VirtualTable';
|
2
|
+
interface ResizeableVirtualTableProps<T> extends Omit<VirtualTableProps<T>, 'onColumnsResize'> {
|
3
|
+
columnsWidthLSKey: string;
|
4
|
+
}
|
5
|
+
export declare function ResizeableVirtualTable<T>({ columnsWidthLSKey, columns, ...props }: ResizeableVirtualTableProps<T>): import("react/jsx-runtime").JSX.Element;
|
6
|
+
export {};
|
@@ -0,0 +1,16 @@
|
|
1
|
+
import { __rest } from "tslib";
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
3
|
+
import { useTableResize } from '../../utils/hooks/useTableResize';
|
4
|
+
import { VirtualTable } from './VirtualTable';
|
5
|
+
function updateColumnsWidth(columns, columnsWidthSetup) {
|
6
|
+
return columns.map((column) => {
|
7
|
+
var _a;
|
8
|
+
return Object.assign(Object.assign({}, column), { width: (_a = columnsWidthSetup[column.name]) !== null && _a !== void 0 ? _a : column.width });
|
9
|
+
});
|
10
|
+
}
|
11
|
+
export function ResizeableVirtualTable(_a) {
|
12
|
+
var { columnsWidthLSKey, columns } = _a, props = __rest(_a, ["columnsWidthLSKey", "columns"]);
|
13
|
+
const [tableColumnsWidth, setTableColumnsWidth] = useTableResize(columnsWidthLSKey);
|
14
|
+
const updatedColumns = updateColumnsWidth(columns, tableColumnsWidth);
|
15
|
+
return (_jsx(VirtualTable, Object.assign({ columns: updatedColumns, onColumnsResize: setTableColumnsWidth }, props)));
|
16
|
+
}
|
@@ -1,5 +1,4 @@
|
|
1
|
-
import type { HandleTableColumnsResize } from '
|
2
|
-
import type { Column, OnSort, SortOrderType } from './types';
|
1
|
+
import type { Column, HandleTableColumnsResize, OnSort, SortOrderType } from './types';
|
3
2
|
interface TableHeadCellProps<T> {
|
4
3
|
column: Column<T>;
|
5
4
|
resizeable?: boolean;
|
@@ -9,8 +8,9 @@ interface TableHeadCellProps<T> {
|
|
9
8
|
rowHeight: number;
|
10
9
|
onCellMount?: (element: Element) => void;
|
11
10
|
onCellUnMount?: (element: Element) => void;
|
11
|
+
onColumnsResize?: HandleTableColumnsResize;
|
12
12
|
}
|
13
|
-
export declare const TableHeadCell: <T>({ column, resizeable, sortOrder, defaultSortOrder, onSort, rowHeight, onCellMount, onCellUnMount, }: TableHeadCellProps<T>) => import("react/jsx-runtime").JSX.Element;
|
13
|
+
export declare const TableHeadCell: <T>({ column, resizeable, sortOrder, defaultSortOrder, onSort, rowHeight, onCellMount, onCellUnMount, onColumnsResize, }: TableHeadCellProps<T>) => import("react/jsx-runtime").JSX.Element;
|
14
14
|
interface TableHeadProps<T> {
|
15
15
|
columns: Column<T>[];
|
16
16
|
onSort?: OnSort;
|
@@ -1,8 +1,8 @@
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
2
2
|
import React from 'react';
|
3
|
+
import { ResizeHandler } from './ResizeHandler';
|
3
4
|
import { ASCENDING, DEFAULT_RESIZEABLE, DEFAULT_SORT_ORDER, DEFAULT_TABLE_ROW_HEIGHT, DESCENDING, } from './constants';
|
4
5
|
import { b } from './shared';
|
5
|
-
const COLUMN_NAME_HTML_ATTRIBUTE = 'data-columnname';
|
6
6
|
// Icon similar to original DataTable icons to keep the same tables across diferent pages and tabs
|
7
7
|
const SortIcon = ({ order }) => {
|
8
8
|
return (_jsx("svg", { className: b('sort-icon', { desc: order === DESCENDING }), viewBox: "0 0 10 6", width: "10", height: "6", children: _jsx("path", { fill: "currentColor", d: "M0 5h10l-5 -5z" }) }));
|
@@ -15,7 +15,7 @@ const ColumnSortIcon = ({ sortOrder, sortable, defaultSortOrder }) => {
|
|
15
15
|
return null;
|
16
16
|
}
|
17
17
|
};
|
18
|
-
export const TableHeadCell = ({ column, resizeable, sortOrder, defaultSortOrder, onSort, rowHeight, onCellMount, onCellUnMount, }) => {
|
18
|
+
export const TableHeadCell = ({ column, resizeable, sortOrder, defaultSortOrder, onSort, rowHeight, onCellMount, onCellUnMount, onColumnsResize, }) => {
|
19
19
|
var _a;
|
20
20
|
const cellWrapperRef = React.useRef(null);
|
21
21
|
React.useEffect(() => {
|
@@ -29,40 +29,25 @@ export const TableHeadCell = ({ column, resizeable, sortOrder, defaultSortOrder,
|
|
29
29
|
}
|
30
30
|
};
|
31
31
|
}, [onCellMount, onCellUnMount]);
|
32
|
+
const getCurrentColumnWidth = React.useCallback(() => {
|
33
|
+
var _a;
|
34
|
+
return (_a = cellWrapperRef.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect().width;
|
35
|
+
}, []);
|
36
|
+
const handleResize = React.useCallback((newWidth) => {
|
37
|
+
onColumnsResize === null || onColumnsResize === void 0 ? void 0 : onColumnsResize(column.name, newWidth);
|
38
|
+
}, [onColumnsResize, column.name]);
|
32
39
|
const content = (_a = column.header) !== null && _a !== void 0 ? _a : column.name;
|
33
|
-
return (_jsx("th", { children:
|
40
|
+
return (_jsx("th", { children: _jsxs("div", { ref: cellWrapperRef, className: b('head-cell-wrapper'), style: {
|
34
41
|
height: `${rowHeight}px`,
|
35
42
|
width: `${column.width}px`,
|
36
|
-
},
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
43
|
+
}, children: [_jsxs("div", { className: b('head-cell', { align: column.align, sortable: column.sortable }, column.className), onClick: () => {
|
44
|
+
if (column.sortable) {
|
45
|
+
onSort === null || onSort === void 0 ? void 0 : onSort(column.name);
|
46
|
+
}
|
47
|
+
}, children: [_jsx("div", { className: b('head-cell-content'), children: content }), _jsx(ColumnSortIcon, { sortOrder: sortOrder, sortable: column.sortable, defaultSortOrder: defaultSortOrder })] }), resizeable ? (_jsx(ResizeHandler, { maxWidth: column.resizeMaxWidth, minWidth: column.resizeMinWidth, getCurrentColumnWidth: getCurrentColumnWidth, onResize: handleResize })) : null] }) }));
|
41
48
|
};
|
42
49
|
export const TableHead = ({ columns, onSort, onColumnsResize, defaultSortOrder = DEFAULT_SORT_ORDER, rowHeight = DEFAULT_TABLE_ROW_HEIGHT, }) => {
|
43
50
|
const [sortParams, setSortParams] = React.useState({});
|
44
|
-
const isTableResizeable = Boolean(onColumnsResize);
|
45
|
-
const resizeObserver = React.useMemo(() => {
|
46
|
-
if (!isTableResizeable) {
|
47
|
-
return undefined;
|
48
|
-
}
|
49
|
-
return new ResizeObserver((entries) => {
|
50
|
-
const columnsWidth = {};
|
51
|
-
entries.forEach((entry) => {
|
52
|
-
var _a;
|
53
|
-
// @ts-expect-error ignore custrom property usage
|
54
|
-
const id = (_a = entry.target.attributes[COLUMN_NAME_HTML_ATTRIBUTE]) === null || _a === void 0 ? void 0 : _a.value;
|
55
|
-
columnsWidth[id] = entry.contentRect.width;
|
56
|
-
});
|
57
|
-
onColumnsResize === null || onColumnsResize === void 0 ? void 0 : onColumnsResize(columnsWidth);
|
58
|
-
});
|
59
|
-
}, [onColumnsResize, isTableResizeable]);
|
60
|
-
const handleCellMount = React.useCallback((element) => {
|
61
|
-
resizeObserver === null || resizeObserver === void 0 ? void 0 : resizeObserver.observe(element);
|
62
|
-
}, [resizeObserver]);
|
63
|
-
const handleCellUnMount = React.useCallback((element) => {
|
64
|
-
resizeObserver === null || resizeObserver === void 0 ? void 0 : resizeObserver.unobserve(element);
|
65
|
-
}, [resizeObserver]);
|
66
51
|
const handleSort = (columnId) => {
|
67
52
|
let newSortParams = {};
|
68
53
|
// Order is changed in following order:
|
@@ -100,7 +85,7 @@ export const TableHead = ({ columns, onSort, onColumnsResize, defaultSortOrder =
|
|
100
85
|
var _a;
|
101
86
|
const sortOrder = sortParams.columnId === column.name ? sortParams.sortOrder : undefined;
|
102
87
|
const resizeable = onColumnsResize && ((_a = column.resizeable) !== null && _a !== void 0 ? _a : DEFAULT_RESIZEABLE);
|
103
|
-
return (_jsx(TableHeadCell, { column: column, resizeable: resizeable, sortOrder: sortOrder, defaultSortOrder: defaultSortOrder, onSort: handleSort, rowHeight: rowHeight,
|
88
|
+
return (_jsx(TableHeadCell, { column: column, resizeable: resizeable, sortOrder: sortOrder, defaultSortOrder: defaultSortOrder, onSort: handleSort, rowHeight: rowHeight, onColumnsResize: onColumnsResize }, column.name));
|
104
89
|
}) }) }));
|
105
90
|
};
|
106
91
|
return (_jsxs(React.Fragment, { children: [renderTableColGroups(), renderTableHead()] }));
|
@@ -1,7 +1,6 @@
|
|
1
|
-
import type { HandleTableColumnsResize } from '
|
2
|
-
import type { Column, FetchData, GetRowClassName, RenderControls, RenderEmptyDataMessage, RenderErrorMessage, SortParams } from './types';
|
1
|
+
import type { Column, FetchData, GetRowClassName, HandleTableColumnsResize, RenderControls, RenderEmptyDataMessage, RenderErrorMessage, SortParams } from './types';
|
3
2
|
import './VirtualTable.scss';
|
4
|
-
interface VirtualTableProps<T> {
|
3
|
+
export interface VirtualTableProps<T> {
|
5
4
|
limit: number;
|
6
5
|
fetchData: FetchData<T>;
|
7
6
|
columns: Column<T>[];
|
@@ -16,4 +15,3 @@ interface VirtualTableProps<T> {
|
|
16
15
|
dependencyArray?: unknown[];
|
17
16
|
}
|
18
17
|
export declare const VirtualTable: <T>({ limit, fetchData, columns, getRowClassName, rowHeight, parentContainer, initialSortParams, onColumnsResize, renderControls, renderEmptyDataMessage, renderErrorMessage, dependencyArray, }: VirtualTableProps<T>) => import("react/jsx-runtime").JSX.Element;
|
19
|
-
export {};
|
@@ -60,14 +60,12 @@
|
|
60
60
|
}
|
61
61
|
|
62
62
|
&__head-cell-wrapper {
|
63
|
+
position: relative;
|
64
|
+
|
63
65
|
display: flex;
|
64
66
|
overflow-x: hidden;
|
65
67
|
|
66
68
|
border-bottom: $cell-border;
|
67
|
-
|
68
|
-
&_resizeable {
|
69
|
-
resize: horizontal;
|
70
|
-
}
|
71
69
|
}
|
72
70
|
|
73
71
|
&__head-cell {
|
@@ -145,4 +143,26 @@
|
|
145
143
|
}
|
146
144
|
}
|
147
145
|
}
|
146
|
+
|
147
|
+
&__resize-handler {
|
148
|
+
position: absolute;
|
149
|
+
top: 0;
|
150
|
+
right: 0;
|
151
|
+
|
152
|
+
visibility: hidden;
|
153
|
+
|
154
|
+
width: 6px;
|
155
|
+
height: 100%;
|
156
|
+
|
157
|
+
cursor: col-resize;
|
158
|
+
|
159
|
+
background-color: var(--g-color-base-generic);
|
160
|
+
|
161
|
+
&_resizing {
|
162
|
+
visibility: visible;
|
163
|
+
}
|
164
|
+
}
|
165
|
+
&__head-cell-wrapper:hover > &__resize-handler {
|
166
|
+
visibility: visible;
|
167
|
+
}
|
148
168
|
}
|
@@ -18,6 +18,7 @@ export type SortParams = {
|
|
18
18
|
sortOrder?: SortOrderType;
|
19
19
|
};
|
20
20
|
export type OnSort = (params: SortParams) => void;
|
21
|
+
export type HandleTableColumnsResize = (columnId: string, width: number) => void;
|
21
22
|
export interface Column<T> {
|
22
23
|
name: string;
|
23
24
|
header?: React.ReactNode;
|
@@ -29,6 +30,8 @@ export interface Column<T> {
|
|
29
30
|
index: number;
|
30
31
|
}) => React.ReactNode;
|
31
32
|
width: number;
|
33
|
+
resizeMaxWidth?: number;
|
34
|
+
resizeMinWidth?: number;
|
32
35
|
align: AlignType;
|
33
36
|
}
|
34
37
|
export interface VirtualTableData<T> {
|
@@ -0,0 +1,21 @@
|
|
1
|
+
// invoke passed function at most once per animation frame
|
2
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
3
|
+
export function rafThrottle(fn) {
|
4
|
+
let rafId = null;
|
5
|
+
let latestArgs;
|
6
|
+
return function throttled(...args) {
|
7
|
+
// call throttled function with latest args
|
8
|
+
latestArgs = args;
|
9
|
+
if (typeof rafId === 'number') {
|
10
|
+
return;
|
11
|
+
}
|
12
|
+
rafId = requestAnimationFrame(() => {
|
13
|
+
fn(...latestArgs);
|
14
|
+
rafId = null;
|
15
|
+
});
|
16
|
+
};
|
17
|
+
}
|
18
|
+
// 40px minWidth so sort icon won't overlap wrapped column title
|
19
|
+
export function calculateColumnWidth(newWidth, minWidth = 40, maxWidth = Infinity) {
|
20
|
+
return Math.max(minWidth, Math.min(newWidth, maxWidth));
|
21
|
+
}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
2
2
|
import React from 'react';
|
3
|
-
import { useTypedSelector } from '../../
|
3
|
+
import { useTypedSelector } from '../../utils/hooks';
|
4
4
|
export function ClusterModeGuard({ children, mode }) {
|
5
5
|
const shouldRender = useTypedSelector((state) => mode === 'single' ? state.singleClusterMode : !state.singleClusterMode);
|
6
6
|
return shouldRender ? _jsx(React.Fragment, { children: children }) : null;
|
@@ -5,6 +5,7 @@ import { Select, TableColumnSetup } from '@gravity-ui/uikit';
|
|
5
5
|
import { Helmet } from 'react-helmet-async';
|
6
6
|
import { ResponseError } from '../../components/Errors/ResponseError';
|
7
7
|
import { Loader } from '../../components/Loader';
|
8
|
+
import { ResizeableDataTable } from '../../components/ResizeableDataTable/ResizeableDataTable';
|
8
9
|
import { Search } from '../../components/Search';
|
9
10
|
import { changeClustersFilters, clustersApi } from '../../store/reducers/clusters/clusters';
|
10
11
|
import { aggregateClustersInfo, filterClusters, selectClusterNameFilter, selectServiceFilter, selectStatusFilter, selectVersionFilter, } from '../../store/reducers/clusters/selectors';
|
@@ -12,7 +13,7 @@ import { DEFAULT_POLLING_INTERVAL, DEFAULT_TABLE_SETTINGS } from '../../utils/co
|
|
12
13
|
import { useTypedDispatch, useTypedSelector } from '../../utils/hooks';
|
13
14
|
import { getMinorVersion } from '../../utils/versions';
|
14
15
|
import { ClustersStatistics } from './ClustersStatistics';
|
15
|
-
import { CLUSTERS_COLUMNS } from './columns';
|
16
|
+
import { CLUSTERS_COLUMNS, CLUSTERS_COLUMNS_WIDTH_LS_KEY } from './columns';
|
16
17
|
import { CLUSTER_STATUSES, COLUMNS_NAMES, COLUMNS_TITLES, DEFAULT_COLUMNS, SELECTED_COLUMNS_KEY, } from './constants';
|
17
18
|
import i18n from './i18n';
|
18
19
|
import { b } from './shared';
|
@@ -69,7 +70,7 @@ export function Clusters() {
|
|
69
70
|
if (query.isLoading) {
|
70
71
|
return _jsx(Loader, { size: "l" });
|
71
72
|
}
|
72
|
-
return (_jsxs("div", { className: b(), children: [_jsx(Helmet, { children: _jsx("title", { children: i18n('page_title') }) }), _jsx(ClustersStatistics, { stats: aggregation, count: filteredClusters.length }), _jsxs("div", { className: b('controls'), children: [_jsx("div", { className: b('control', { wide: true }), children: _jsx(Search, { placeholder: i18n('controls_search-placeholder'), onChange: changeClusterName, value: clusterName }) }), _jsx("div", { className: b('control'), children: _jsx(Select, { multiple: true, filterable: true, hasClear: true, placeholder: i18n('controls_select-placeholder'), label: i18n('controls_status-select-label'), value: status, options: CLUSTER_STATUSES, onUpdate: changeStatus, width: "max" }) }), _jsx("div", { className: b('control'), children: _jsx(Select, { multiple: true, filterable: true, hasClear: true, placeholder: i18n('controls_select-placeholder'), label: i18n('controls_service-select-label'), value: service, options: servicesToSelect, onUpdate: changeService, width: "max" }) }), _jsx("div", { className: b('control'), children: _jsx(Select, { multiple: true, filterable: true, hasClear: true, placeholder: i18n('controls_select-placeholder'), label: i18n('controls_version-select-label'), value: version, options: versions, onUpdate: changeVersion, width: "max" }) }), _jsx("div", { className: b('control'), children: _jsx(TableColumnSetup, { popupWidth: 242, items: columnsToSelect, showStatus: true, onUpdate: setColumns, sortable: false }, "TableColumnSetup") })] }), query.isError ? _jsx(ResponseError, { error: query.error, className: b('error') }) : null, _jsx("div", { className: b('table-wrapper'), children: _jsx("div", { className: b('table-content'), children: _jsx(
|
73
|
+
return (_jsxs("div", { className: b(), children: [_jsx(Helmet, { children: _jsx("title", { children: i18n('page_title') }) }), _jsx(ClustersStatistics, { stats: aggregation, count: filteredClusters.length }), _jsxs("div", { className: b('controls'), children: [_jsx("div", { className: b('control', { wide: true }), children: _jsx(Search, { placeholder: i18n('controls_search-placeholder'), onChange: changeClusterName, value: clusterName }) }), _jsx("div", { className: b('control'), children: _jsx(Select, { multiple: true, filterable: true, hasClear: true, placeholder: i18n('controls_select-placeholder'), label: i18n('controls_status-select-label'), value: status, options: CLUSTER_STATUSES, onUpdate: changeStatus, width: "max" }) }), _jsx("div", { className: b('control'), children: _jsx(Select, { multiple: true, filterable: true, hasClear: true, placeholder: i18n('controls_select-placeholder'), label: i18n('controls_service-select-label'), value: service, options: servicesToSelect, onUpdate: changeService, width: "max" }) }), _jsx("div", { className: b('control'), children: _jsx(Select, { multiple: true, filterable: true, hasClear: true, placeholder: i18n('controls_select-placeholder'), label: i18n('controls_version-select-label'), value: version, options: versions, onUpdate: changeVersion, width: "max" }) }), _jsx("div", { className: b('control'), children: _jsx(TableColumnSetup, { popupWidth: 242, items: columnsToSelect, showStatus: true, onUpdate: setColumns, sortable: false }, "TableColumnSetup") })] }), query.isError ? _jsx(ResponseError, { error: query.error, className: b('error') }) : null, _jsx("div", { className: b('table-wrapper'), children: _jsx("div", { className: b('table-content'), children: _jsx(ResizeableDataTable, { columnsWidthLSKey: CLUSTERS_COLUMNS_WIDTH_LS_KEY, wrapperClassName: b('table'), data: filteredClusters, columns: columnsToShow, settings: Object.assign(Object.assign({}, DEFAULT_TABLE_SETTINGS), { dynamicRender: false }), initialSortOrder: {
|
73
74
|
columnId: COLUMNS_NAMES.TITLE,
|
74
75
|
order: DataTable.ASCENDING,
|
75
76
|
} }) }) })] }));
|
@@ -1,3 +1,4 @@
|
|
1
1
|
import type { Column } from '@gravity-ui/react-data-table';
|
2
2
|
import type { PreparedCluster } from '../../store/reducers/clusters/types';
|
3
|
+
export declare const CLUSTERS_COLUMNS_WIDTH_LS_KEY = "clustersTableColumnsWidth";
|
3
4
|
export declare const CLUSTERS_COLUMNS: Column<PreparedCluster>[];
|
@@ -11,6 +11,7 @@ import { clusterTabsIds, getClusterPath } from '../Cluster/utils';
|
|
11
11
|
import { COLUMNS_NAMES, COLUMNS_TITLES } from './constants';
|
12
12
|
import i18n from './i18n';
|
13
13
|
import { b } from './shared';
|
14
|
+
export const CLUSTERS_COLUMNS_WIDTH_LS_KEY = 'clustersTableColumnsWidth';
|
14
15
|
const EMPTY_CELL = _jsx("span", { className: b('empty-cell'), children: "\u2014" });
|
15
16
|
export const CLUSTERS_COLUMNS = [
|
16
17
|
{
|
@@ -83,7 +84,7 @@ export const CLUSTERS_COLUMNS = [
|
|
83
84
|
{
|
84
85
|
name: COLUMNS_NAMES.NODES,
|
85
86
|
header: COLUMNS_TITLES[COLUMNS_NAMES.NODES],
|
86
|
-
|
87
|
+
resizeMinWidth: 140,
|
87
88
|
defaultOrder: DataTable.DESCENDING,
|
88
89
|
sortAccessor: ({ cluster = {} }) => {
|
89
90
|
const { NodesTotal = 0 } = cluster;
|
@@ -100,7 +101,7 @@ export const CLUSTERS_COLUMNS = [
|
|
100
101
|
{
|
101
102
|
name: COLUMNS_NAMES.LOAD,
|
102
103
|
header: COLUMNS_TITLES[COLUMNS_NAMES.LOAD],
|
103
|
-
|
104
|
+
resizeMinWidth: 140,
|
104
105
|
defaultOrder: DataTable.DESCENDING,
|
105
106
|
sortAccessor: ({ cluster }) => {
|
106
107
|
return cluster === null || cluster === void 0 ? void 0 : cluster.NumberOfCpus;
|
@@ -116,7 +117,7 @@ export const CLUSTERS_COLUMNS = [
|
|
116
117
|
{
|
117
118
|
name: COLUMNS_NAMES.STORAGE,
|
118
119
|
header: COLUMNS_TITLES[COLUMNS_NAMES.STORAGE],
|
119
|
-
|
120
|
+
resizeMinWidth: 140,
|
120
121
|
defaultOrder: DataTable.DESCENDING,
|
121
122
|
sortAccessor: ({ cluster }) => {
|
122
123
|
return Number(cluster === null || cluster === void 0 ? void 0 : cluster.StorageTotal);
|