ydb-embedded-ui 6.3.0 → 6.5.0
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +39 -17
- package/dist/assets/icons/disableFullscreen.svg +4 -0
- package/dist/assets/icons/emptyState.svg +13 -0
- package/dist/assets/icons/key.svg +6 -0
- package/dist/assets/icons/monitoring.svg +9 -0
- package/dist/assets/icons/network.svg +21 -0
- package/dist/components/AsyncReplicationState/AsyncReplicationState.d.ts +6 -0
- package/dist/components/AsyncReplicationState/AsyncReplicationState.js +20 -0
- package/dist/components/AsyncReplicationState/index.d.ts +1 -0
- package/dist/components/AsyncReplicationState/index.js +1 -0
- package/dist/components/BasicNodeViewer/BasicNodeViewer.js +11 -5
- package/dist/components/ButtonWithConfirmDialog/ButtonWithConfirmDialog.d.ts +6 -2
- package/dist/components/ButtonWithConfirmDialog/ButtonWithConfirmDialog.js +12 -3
- package/dist/components/CriticalActionDialog/CriticalActionDialog.js +3 -4
- package/dist/components/CriticalActionDialog/CriticalActionDialog.scss +2 -0
- package/dist/components/EmptyState/EmptyState.js +3 -2
- package/dist/components/EnableFullscreenButton/EnableFullscreenButton.js +3 -3
- package/dist/components/Errors/ResponseError/ResponseError.js +3 -0
- package/dist/components/Fullscreen/Fullscreen.js +3 -3
- package/dist/components/MonitoringButton/MonitoringButton.js +3 -3
- package/dist/components/NodeHostWrapper/NodeHostWrapper.js +3 -3
- package/dist/components/PDiskInfo/i18n/index.d.ts +1 -1
- package/dist/components/QueryExecutionStatus/QueryExecutionStatus.d.ts +1 -2
- package/dist/components/QueryExecutionStatus/QueryExecutionStatus.js +6 -6
- package/dist/components/StatusIcon/StatusIcon.js +5 -7
- package/dist/components/VDiskInfo/i18n/index.d.ts +1 -1
- package/dist/containers/App/App.js +1 -2
- package/dist/containers/AsideNavigation/AsideNavigation.js +4 -9
- package/dist/containers/AsideNavigation/YdbInternalUser/YdbInternalUser.js +2 -3
- package/dist/containers/AsideNavigation/useNavigationMenuItems.js +5 -6
- package/dist/containers/Authentication/Authentication.js +2 -4
- package/dist/containers/Clusters/Clusters.js +7 -2
- package/dist/containers/Clusters/constants.d.ts +1 -3
- package/dist/containers/Clusters/constants.js +0 -18
- package/dist/containers/Node/NodeStructure/Pdisk.js +4 -4
- package/dist/containers/Nodes/Nodes.js +19 -15
- package/dist/containers/Nodes/VirtualNodes.js +23 -6
- package/dist/containers/PDiskPage/PDiskPage.js +3 -2
- package/dist/containers/PDiskPage/i18n/en.json +2 -1
- package/dist/containers/PDiskPage/i18n/index.d.ts +1 -1
- package/dist/containers/Storage/Storage.js +50 -22
- package/dist/containers/Storage/StorageGroups/getStorageGroupsColumns.js +2 -2
- package/dist/containers/Storage/VirtualStorage.js +32 -10
- package/dist/containers/Storage/utils/index.d.ts +4 -1
- package/dist/containers/Storage/utils/index.js +29 -0
- package/dist/containers/Tablet/Tablet.js +3 -3
- package/dist/containers/Tablet/TabletControls/TabletControls.js +3 -1
- package/dist/containers/Tablet/i18n/en.json +3 -0
- package/dist/containers/Tablet/i18n/index.d.ts +1 -1
- package/dist/containers/Tablet/i18n/index.js +1 -2
- package/dist/containers/Tablets/Tablets.d.ts +1 -2
- package/dist/containers/Tablets/Tablets.js +113 -53
- package/dist/containers/Tablets/i18n/en.json +10 -4
- package/dist/containers/Tablets/i18n/index.d.ts +1 -1
- package/dist/containers/Tablets/i18n/index.js +1 -2
- package/dist/containers/Tenant/Diagnostics/Diagnostics.js +5 -5
- package/dist/containers/Tenant/Diagnostics/DiagnosticsPages.d.ts +7 -0
- package/dist/containers/Tenant/Diagnostics/DiagnosticsPages.js +2 -0
- package/dist/containers/Tenant/Diagnostics/HotKeys/HotKeys.js +31 -19
- package/dist/containers/Tenant/Diagnostics/HotKeys/HotKeys.scss +14 -4
- package/dist/containers/Tenant/Diagnostics/HotKeys/i18n/en.json +2 -1
- package/dist/containers/Tenant/Diagnostics/HotKeys/i18n/index.d.ts +1 -1
- package/dist/containers/Tenant/Diagnostics/Network/Network.js +3 -3
- package/dist/containers/Tenant/Diagnostics/Overview/AsyncReplicationInfo/AsyncReplicationInfo.d.ts +7 -0
- package/dist/containers/Tenant/Diagnostics/Overview/AsyncReplicationInfo/AsyncReplicationInfo.js +39 -0
- package/dist/containers/Tenant/Diagnostics/Overview/AsyncReplicationInfo/Credentials.d.ts +6 -0
- package/dist/containers/Tenant/Diagnostics/Overview/AsyncReplicationInfo/Credentials.js +14 -0
- package/dist/containers/Tenant/Diagnostics/Overview/AsyncReplicationInfo/i18n/en.json +7 -0
- package/dist/containers/Tenant/Diagnostics/Overview/AsyncReplicationInfo/i18n/index.d.ts +2 -0
- package/dist/containers/Tenant/Diagnostics/Overview/AsyncReplicationInfo/i18n/index.js +4 -0
- package/dist/containers/Tenant/Diagnostics/Overview/AsyncReplicationInfo/index.d.ts +1 -0
- package/dist/containers/Tenant/Diagnostics/Overview/AsyncReplicationInfo/index.js +1 -0
- package/dist/containers/Tenant/Diagnostics/Overview/AsyncReplicationPaths/AsyncReplicationPaths.d.ts +7 -0
- package/dist/containers/Tenant/Diagnostics/Overview/AsyncReplicationPaths/AsyncReplicationPaths.js +34 -0
- package/dist/containers/Tenant/Diagnostics/Overview/AsyncReplicationPaths/AsyncReplicationPaths.scss +7 -0
- package/dist/containers/Tenant/Diagnostics/Overview/AsyncReplicationPaths/i18n/en.json +7 -0
- package/dist/containers/Tenant/Diagnostics/Overview/AsyncReplicationPaths/i18n/index.d.ts +2 -0
- package/dist/containers/Tenant/Diagnostics/Overview/AsyncReplicationPaths/i18n/index.js +4 -0
- package/dist/containers/Tenant/Diagnostics/Overview/AsyncReplicationPaths/index.d.ts +1 -0
- package/dist/containers/Tenant/Diagnostics/Overview/AsyncReplicationPaths/index.js +1 -0
- package/dist/containers/Tenant/Diagnostics/Overview/Overview.js +2 -0
- package/dist/containers/Tenant/Diagnostics/TenantOverview/Healthcheck/HealthcheckPreview.js +2 -2
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/TopQueries.js +2 -1
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantCpu/TopShards.js +2 -1
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantStorage/TopTables.js +2 -1
- package/dist/containers/Tenant/Diagnostics/TenantOverview/i18n/index.d.ts +1 -1
- package/dist/containers/Tenant/Diagnostics/TopQueries/TopQueries.js +3 -3
- package/dist/containers/Tenant/Diagnostics/TopShards/TopShards.js +3 -3
- package/dist/containers/Tenant/ObjectGeneral/ObjectGeneral.js +2 -8
- package/dist/containers/Tenant/ObjectSummary/ObjectSummary.js +23 -9
- package/dist/containers/Tenant/Query/ExecuteResult/ExecuteResult.d.ts +2 -2
- package/dist/containers/Tenant/Query/ExecuteResult/ExecuteResult.js +5 -6
- package/dist/containers/Tenant/Query/ExplainResult/ExplainResult.js +6 -14
- package/dist/containers/Tenant/Query/Issues/Issues.js +6 -9
- package/dist/containers/Tenant/Query/Preview/Preview.js +5 -5
- package/dist/containers/Tenant/Query/QueryEditor/QueryEditor.d.ts +2 -8
- package/dist/containers/Tenant/Query/QueryEditor/QueryEditor.js +18 -19
- package/dist/containers/Tenant/Query/QueryEditorControls/QueryEditorControls.js +4 -4
- package/dist/containers/Tenant/Query/SavedQueries/SavedQueries.js +3 -3
- package/dist/containers/Tenant/Schema/SchemaViewer/helpers.js +3 -2
- package/dist/containers/Tenant/Tenant.js +3 -2
- package/dist/containers/Tenant/utils/ToggleButton.scss +0 -2
- package/dist/containers/Tenant/utils/paneVisibilityToggleHelpers.js +4 -4
- package/dist/containers/Tenant/utils/schema.js +8 -0
- package/dist/containers/Tenant/utils/schemaActions.js +1 -0
- package/dist/containers/Tenant/utils/schemaControls.js +4 -3
- package/dist/containers/VDiskPage/VDiskPage.js +3 -2
- package/dist/containers/VDiskPage/i18n/en.json +2 -1
- package/dist/containers/VDiskPage/i18n/index.d.ts +1 -1
- package/dist/routes.d.ts +1 -1
- package/dist/services/api.d.ts +3 -3
- package/dist/services/settings.d.ts +19 -1
- package/dist/services/settings.js +2 -1
- package/dist/store/configureStore.d.ts +0 -12
- package/dist/store/defaultStore.d.ts +0 -6
- package/dist/store/reducers/authentication/authentication.d.ts +187 -13
- package/dist/store/reducers/authentication/authentication.js +12 -3
- package/dist/store/reducers/authentication/types.d.ts +5 -1
- package/dist/store/reducers/cluster/cluster.js +4 -0
- package/dist/store/reducers/executeQuery.d.ts +4 -65
- package/dist/store/reducers/executeQuery.js +38 -34
- package/dist/store/reducers/executeTopQueries/executeTopQueries.js +4 -1
- package/dist/store/reducers/explainQuery/explainQuery.d.ts +9 -0
- package/dist/store/reducers/explainQuery/explainQuery.js +32 -0
- package/dist/store/reducers/explainQuery/types.d.ts +12 -0
- package/dist/store/reducers/explainQuery/utils.d.ts +6 -0
- package/dist/store/reducers/explainQuery/utils.js +40 -0
- package/dist/store/reducers/healthcheckInfo/healthcheckInfo.d.ts +0 -60
- package/dist/store/reducers/host.d.ts +61 -4
- package/dist/store/reducers/index.d.ts +0 -9
- package/dist/store/reducers/index.js +0 -6
- package/dist/store/reducers/node/selectors.d.ts +0 -3
- package/dist/store/reducers/nodes/nodes.d.ts +1 -5
- package/dist/store/reducers/nodes/nodes.js +0 -27
- package/dist/store/reducers/nodes/types.d.ts +4 -13
- package/dist/store/reducers/nodesList.d.ts +0 -3
- package/dist/store/reducers/olapStats.js +4 -1
- package/dist/store/reducers/preview.js +4 -1
- package/dist/store/reducers/schema/schema.d.ts +61 -4
- package/dist/store/reducers/schemaAcl/schemaAcl.d.ts +61 -4
- package/dist/store/reducers/shardsWorkload/shardsWorkload.js +4 -1
- package/dist/store/reducers/storage/selectors.d.ts +2 -17
- package/dist/store/reducers/storage/selectors.js +1 -36
- package/dist/store/reducers/storage/storage.d.ts +2 -6
- package/dist/store/reducers/storage/storage.js +0 -44
- package/dist/store/reducers/storage/types.d.ts +15 -22
- package/dist/store/reducers/storage/types.js +4 -1
- package/dist/store/reducers/tablets.d.ts +91 -1
- package/dist/store/reducers/tablets.js +16 -1
- package/dist/store/reducers/tabletsFilters.d.ts +61 -4
- package/dist/store/reducers/tenant/tenant.d.ts +2 -2
- package/dist/store/reducers/tenant/tenant.js +10 -1
- package/dist/store/reducers/tenant/types.d.ts +8 -3
- package/dist/store/reducers/tenant/types.js +3 -1
- package/dist/store/reducers/tenantOverview/executeTopTables/executeTopTables.js +6 -3
- package/dist/store/reducers/tenantOverview/topQueries/tenantOverviewTopQueries.js +6 -3
- package/dist/store/reducers/tenantOverview/topShards/tenantOverviewTopShards.js +6 -3
- package/dist/store/reducers/tenants/selectors.d.ts +0 -27
- package/dist/store/reducers/tenants/utils.d.ts +4 -4
- package/dist/store/reducers/tenants/utils.js +8 -8
- package/dist/store/reducers/topic.d.ts +0 -45
- package/dist/store/state-url-mapping.js +0 -22
- package/dist/store/utils.d.ts +2 -3
- package/dist/store/utils.js +1 -1
- package/dist/types/api/schema/replication.d.ts +74 -0
- package/dist/types/api/schema/replication.js +7 -0
- package/dist/types/api/schema/schema.d.ts +4 -1
- package/dist/types/api/schema/schema.js +1 -0
- package/dist/types/api/whoami.d.ts +6 -0
- package/dist/types/store/executeQuery.d.ts +2 -9
- package/dist/utils/constants.d.ts +1 -0
- package/dist/utils/constants.js +1 -0
- package/dist/utils/monaco/yql/constants.d.ts +2 -0
- package/dist/utils/monaco/yql/constants.js +33 -0
- package/dist/utils/monaco/yql/generateSuggestions.d.ts +1 -0
- package/dist/utils/monaco/yql/generateSuggestions.js +28 -11
- package/dist/utils/monaco/yql/yqlSuggestions.js +6 -1
- package/dist/utils/nodes.d.ts +2 -0
- package/dist/utils/nodes.js +4 -0
- package/dist/utils/query.d.ts +5 -3
- package/dist/utils/query.js +27 -4
- package/dist/utils/response.d.ts +4 -0
- package/dist/utils/response.js +9 -0
- package/dist/utils/tablet.d.ts +2 -0
- package/dist/utils/tablet.js +14 -0
- package/package.json +4 -3
- package/dist/assets/icons/bug.svg +0 -1
- package/dist/assets/icons/circle-exclamation.svg +0 -1
- package/dist/assets/icons/circle-info.svg +0 -1
- package/dist/assets/icons/circle-xmark.svg +0 -1
- package/dist/assets/icons/close.svg +0 -1
- package/dist/assets/icons/control-menu-button.svg +0 -1
- package/dist/assets/icons/dots.svg +0 -1
- package/dist/assets/icons/hide.svg +0 -1
- package/dist/assets/icons/question.svg +0 -1
- package/dist/assets/icons/server.svg +0 -1
- package/dist/assets/icons/settings-with-dot.svg +0 -1
- package/dist/assets/icons/settings.svg +0 -1
- package/dist/assets/icons/shield.svg +0 -3
- package/dist/assets/icons/show.svg +0 -1
- package/dist/assets/icons/signIn.svg +0 -1
- package/dist/assets/icons/signOut.svg +0 -1
- package/dist/assets/icons/storage.svg +0 -1
- package/dist/assets/icons/support.svg +0 -1
- package/dist/assets/icons/triangle-exclamation.svg +0 -1
- package/dist/assets/icons/update-arrow.svg +0 -6
- package/dist/components/Icon/Icon.d.ts +0 -14
- package/dist/components/Icon/Icon.js +0 -16
- package/dist/components/Icon/index.d.ts +0 -1
- package/dist/components/Icon/index.js +0 -1
- package/dist/containers/AppIcons/AppIcons.d.ts +0 -2
- package/dist/containers/AppIcons/AppIcons.js +0 -9
- package/dist/containers/Tablet/i18n/ru.json +0 -10
- package/dist/containers/Tablets/Tablets.scss +0 -35
- package/dist/containers/Tablets/i18n/ru.json +0 -6
- package/dist/store/reducers/explainQuery.d.ts +0 -149
- package/dist/store/reducers/explainQuery.js +0 -94
- package/dist/types/store/explainQuery.d.ts +0 -27
- package/dist/utils/error.d.ts +0 -2
- package/dist/utils/error.js +0 -13
- /package/dist/{types/store/explainQuery.js → store/reducers/explainQuery/types.js} +0 -0
@@ -1,4 +1,5 @@
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
2
|
+
import { ArrowRightFromSquare, ArrowRightToSquare } from '@gravity-ui/icons';
|
2
3
|
import { Button, Icon } from '@gravity-ui/uikit';
|
3
4
|
import { useHistory } from 'react-router';
|
4
5
|
import routes, { createHref } from '../../../routes';
|
@@ -6,8 +7,6 @@ import { logout } from '../../../store/reducers/authentication/authentication';
|
|
6
7
|
import { cn } from '../../../utils/cn';
|
7
8
|
import { useTypedDispatch, useTypedSelector } from '../../../utils/hooks';
|
8
9
|
import i18n from '../i18n';
|
9
|
-
import signOutIcon from '@gravity-ui/icons/svgs/arrow-right-from-square.svg';
|
10
|
-
import signInIcon from '@gravity-ui/icons/svgs/arrow-right-to-square.svg';
|
11
10
|
import './YdbInternalUser.scss';
|
12
11
|
const b = cn('kv-ydb-internal-user');
|
13
12
|
export function YdbInternalUser() {
|
@@ -20,5 +19,5 @@ export function YdbInternalUser() {
|
|
20
19
|
const handleLogout = () => {
|
21
20
|
dispatch(logout);
|
22
21
|
};
|
23
|
-
return (_jsxs("div", { className: b(), children: [_jsxs("div", { className: b('user-info-wrapper'), children: [_jsx("div", { className: b('ydb-internal-user-title'), children: i18n('account.user') }), ydbUser && _jsx("div", { className: b('username'), children: ydbUser })] }), ydbUser ? (_jsx(Button, { view: "flat-secondary", title: i18n('account.logout'), onClick: handleLogout, children: _jsx(Icon, { data:
|
22
|
+
return (_jsxs("div", { className: b(), children: [_jsxs("div", { className: b('user-info-wrapper'), children: [_jsx("div", { className: b('ydb-internal-user-title'), children: i18n('account.user') }), ydbUser && _jsx("div", { className: b('username'), children: ydbUser })] }), ydbUser ? (_jsx(Button, { view: "flat-secondary", title: i18n('account.logout'), onClick: handleLogout, children: _jsx(Icon, { data: ArrowRightFromSquare }) })) : (_jsx(Button, { view: "flat-secondary", title: i18n('account.login'), onClick: handleLoginClick, children: _jsx(Icon, { data: ArrowRightToSquare }) }))] }));
|
24
23
|
}
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import React from 'react';
|
2
|
+
import { Pulse, Terminal } from '@gravity-ui/icons';
|
2
3
|
import { useHistory, useLocation } from 'react-router';
|
3
4
|
import routes, { parseQuery } from '../../routes';
|
4
5
|
import { TENANT_PAGE, TENANT_PAGES_IDS } from '../../store/reducers/tenant/constants';
|
@@ -6,13 +7,11 @@ import { TENANT_INITIAL_PAGE_KEY } from '../../utils/constants';
|
|
6
7
|
import { useSetting, useTypedSelector } from '../../utils/hooks';
|
7
8
|
import { getTenantPath } from '../Tenant/TenantPages';
|
8
9
|
import i18n from './i18n';
|
9
|
-
import pulseIcon from '@gravity-ui/icons/svgs/pulse.svg';
|
10
|
-
import terminalIcon from '@gravity-ui/icons/svgs/terminal.svg';
|
11
10
|
export function useNavigationMenuItems() {
|
12
11
|
const location = useLocation();
|
13
12
|
const history = useHistory();
|
14
|
-
const [
|
15
|
-
const { tenantPage
|
13
|
+
const [, setInitialTenantPage] = useSetting(TENANT_INITIAL_PAGE_KEY);
|
14
|
+
const { tenantPage } = useTypedSelector((state) => state.tenant);
|
16
15
|
const { pathname } = location;
|
17
16
|
const queryParams = parseQuery(location);
|
18
17
|
const isTenantPage = pathname === routes.tenant;
|
@@ -24,14 +23,14 @@ export function useNavigationMenuItems() {
|
|
24
23
|
{
|
25
24
|
id: TENANT_PAGES_IDS.query,
|
26
25
|
title: i18n('pages.query'),
|
27
|
-
icon:
|
26
|
+
icon: Terminal,
|
28
27
|
iconSize: 20,
|
29
28
|
location: getTenantPath(Object.assign(Object.assign({}, queryParams), { [TENANT_PAGE]: TENANT_PAGES_IDS.query })),
|
30
29
|
},
|
31
30
|
{
|
32
31
|
id: TENANT_PAGES_IDS.diagnostics,
|
33
32
|
title: i18n('pages.diagnostics'),
|
34
|
-
icon:
|
33
|
+
icon: Pulse,
|
35
34
|
iconSize: 20,
|
36
35
|
location: getTenantPath(Object.assign(Object.assign({}, queryParams), { [TENANT_PAGE]: TENANT_PAGES_IDS.diagnostics })),
|
37
36
|
},
|
@@ -1,14 +1,12 @@
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
2
2
|
import React from 'react';
|
3
|
+
import { Eye, EyeSlash, Xmark } from '@gravity-ui/icons';
|
3
4
|
import { Button, Link as ExternalLink, Icon, TextInput } from '@gravity-ui/uikit';
|
4
5
|
import { useHistory, useLocation } from 'react-router';
|
5
6
|
import { parseQuery } from '../../routes';
|
6
7
|
import { authenticate } from '../../store/reducers/authentication/authentication';
|
7
8
|
import { cn } from '../../utils/cn';
|
8
9
|
import { useTypedDispatch, useTypedSelector } from '../../utils/hooks';
|
9
|
-
import closeIcon from '../../assets/icons/close.svg';
|
10
|
-
import hideIcon from '../../assets/icons/hide.svg';
|
11
|
-
import showIcon from '../../assets/icons/show.svg';
|
12
10
|
import ydbLogoIcon from '../../assets/icons/ydb.svg';
|
13
11
|
import './Authentication.scss';
|
14
12
|
const b = cn('authentication');
|
@@ -64,6 +62,6 @@ function Authentication({ closable = false }) {
|
|
64
62
|
const onTogglePasswordVisibility = () => {
|
65
63
|
setShowPassword((prev) => !prev);
|
66
64
|
};
|
67
|
-
return (_jsxs("section", { className: b(), children: [_jsxs("form", { className: b('form-wrapper'), children: [_jsxs("div", { className: b('header'), children: [_jsxs("div", { className: b('logo'), children: [_jsx(Icon, { data: ydbLogoIcon, size: 24 }), "YDB"] }), _jsx(ExternalLink, { href: "http://ydb.tech/docs", target: "_blank", children: "Documentation" })] }), _jsx("h2", { className: b('title'), children: "Sign in" }), _jsx("div", { className: b('field-wrapper'), children: _jsx(TextInput, { value: login, onUpdate: onLoginUpdate, placeholder: 'Username', error: loginError, onKeyDown: onEnterClick, size: "l", autoFocus: true }) }), _jsxs("div", { className: b('field-wrapper'), children: [_jsx(TextInput, { value: pass, onUpdate: onPassUpdate, type: showPassword ? 'text' : 'password', placeholder: 'Password', error: passwordError, onKeyDown: onEnterClick, size: "l" }), _jsx(Button, { onClick: onTogglePasswordVisibility, size: "l", className: b('show-password-button'), children: _jsx(Icon, { data: showPassword ?
|
65
|
+
return (_jsxs("section", { className: b(), children: [_jsxs("form", { className: b('form-wrapper'), children: [_jsxs("div", { className: b('header'), children: [_jsxs("div", { className: b('logo'), children: [_jsx(Icon, { data: ydbLogoIcon, size: 24 }), "YDB"] }), _jsx(ExternalLink, { href: "http://ydb.tech/docs", target: "_blank", children: "Documentation" })] }), _jsx("h2", { className: b('title'), children: "Sign in" }), _jsx("div", { className: b('field-wrapper'), children: _jsx(TextInput, { value: login, onUpdate: onLoginUpdate, placeholder: 'Username', error: loginError, onKeyDown: onEnterClick, size: "l", autoFocus: true }) }), _jsxs("div", { className: b('field-wrapper'), children: [_jsx(TextInput, { value: pass, onUpdate: onPassUpdate, type: showPassword ? 'text' : 'password', placeholder: 'Password', error: passwordError, onKeyDown: onEnterClick, size: "l" }), _jsx(Button, { onClick: onTogglePasswordVisibility, size: "l", className: b('show-password-button'), children: _jsx(Icon, { data: showPassword ? EyeSlash : Eye, size: 16 }) })] }), _jsx(Button, { view: "action", onClick: onLoginClick, width: "max", size: "l", disabled: Boolean(!login || loginError || passwordError), className: b('button-sign-in'), children: "Sign in" })] }), closable && history.length > 1 && (_jsx(Button, { onClick: onClose, className: b('close'), children: _jsx(Icon, { data: Xmark, size: 24 }) }))] }));
|
68
66
|
}
|
69
67
|
export default Authentication;
|
@@ -14,7 +14,7 @@ import { useTypedDispatch, useTypedSelector } from '../../utils/hooks';
|
|
14
14
|
import { getMinorVersion } from '../../utils/versions';
|
15
15
|
import { ClustersStatistics } from './ClustersStatistics';
|
16
16
|
import { CLUSTERS_COLUMNS, CLUSTERS_COLUMNS_WIDTH_LS_KEY } from './columns';
|
17
|
-
import {
|
17
|
+
import { COLUMNS_NAMES, COLUMNS_TITLES, DEFAULT_COLUMNS, SELECTED_COLUMNS_KEY } from './constants';
|
18
18
|
import i18n from './i18n';
|
19
19
|
import { b } from './shared';
|
20
20
|
import { useSelectedColumns } from './useSelectedColumns';
|
@@ -67,10 +67,15 @@ export function Clusters() {
|
|
67
67
|
return filterClusters(clusters !== null && clusters !== void 0 ? clusters : [], { clusterName, status, service, version });
|
68
68
|
}, [clusterName, clusters, service, status, version]);
|
69
69
|
const aggregation = React.useMemo(() => aggregateClustersInfo(filteredClusters), [filteredClusters]);
|
70
|
+
const statuses = React.useMemo(() => {
|
71
|
+
return Array.from(new Set((clusters !== null && clusters !== void 0 ? clusters : []).map((cluster) => cluster.status).filter(Boolean)))
|
72
|
+
.sort()
|
73
|
+
.map((el) => ({ value: el, content: el }));
|
74
|
+
}, [clusters]);
|
70
75
|
if (query.isLoading) {
|
71
76
|
return _jsx(Loader, { size: "l" });
|
72
77
|
}
|
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:
|
78
|
+
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: 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: {
|
74
79
|
columnId: COLUMNS_NAMES.TITLE,
|
75
80
|
order: DataTable.ASCENDING,
|
76
81
|
} }) }) })] }));
|
@@ -1,4 +1,3 @@
|
|
1
|
-
import type { SelectOption } from '@gravity-ui/uikit';
|
2
1
|
export declare const SELECTED_COLUMNS_KEY = "selectedColumns";
|
3
2
|
export declare const COLUMNS_NAMES: {
|
4
3
|
readonly TITLE: "title";
|
@@ -15,7 +14,7 @@ export declare const COLUMNS_NAMES: {
|
|
15
14
|
readonly DESCRIPTION: "description";
|
16
15
|
readonly BALANCER: "balancer";
|
17
16
|
};
|
18
|
-
export declare const DEFAULT_COLUMNS: ("nodes" | "storage" | "
|
17
|
+
export declare const DEFAULT_COLUMNS: ("nodes" | "storage" | "status" | "tenants" | "versions" | "service" | "hosts" | "balancer" | "title" | "owner" | "load")[];
|
19
18
|
export declare const COLUMNS_TITLES: {
|
20
19
|
readonly title: "Cluster";
|
21
20
|
readonly versions: "Versions";
|
@@ -31,4 +30,3 @@ export declare const COLUMNS_TITLES: {
|
|
31
30
|
readonly description: "Description";
|
32
31
|
readonly balancer: "Balancer";
|
33
32
|
};
|
34
|
-
export declare const CLUSTER_STATUSES: SelectOption[];
|
@@ -42,21 +42,3 @@ export const COLUMNS_TITLES = {
|
|
42
42
|
[COLUMNS_NAMES.DESCRIPTION]: 'Description',
|
43
43
|
[COLUMNS_NAMES.BALANCER]: 'Balancer',
|
44
44
|
};
|
45
|
-
export const CLUSTER_STATUSES = [
|
46
|
-
{
|
47
|
-
value: 'production',
|
48
|
-
content: 'Production',
|
49
|
-
},
|
50
|
-
{
|
51
|
-
value: 'preprod',
|
52
|
-
content: 'Preprod',
|
53
|
-
},
|
54
|
-
{
|
55
|
-
value: 'testing',
|
56
|
-
content: 'Testing',
|
57
|
-
},
|
58
|
-
{
|
59
|
-
value: 'development',
|
60
|
-
content: 'Development',
|
61
|
-
},
|
62
|
-
];
|
@@ -1,10 +1,10 @@
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
2
2
|
import React from 'react';
|
3
|
+
import { ArrowUpRightFromSquare, CircleInfoFill } from '@gravity-ui/icons';
|
3
4
|
import DataTable from '@gravity-ui/react-data-table';
|
4
|
-
import { ArrowToggle, Button, Popover } from '@gravity-ui/uikit';
|
5
|
+
import { ArrowToggle, Button, Icon, Popover } from '@gravity-ui/uikit';
|
5
6
|
import isEmpty from 'lodash/isEmpty';
|
6
7
|
import { EntityStatus } from '../../../components/EntityStatus/EntityStatus';
|
7
|
-
import { Icon } from '../../../components/Icon';
|
8
8
|
import { PDiskInfo } from '../../../components/PDiskInfo/PDiskInfo';
|
9
9
|
import { ProgressViewer } from '../../../components/ProgressViewer/ProgressViewer';
|
10
10
|
import { EFlag } from '../../../types/api/enums';
|
@@ -49,7 +49,7 @@ function getColumns({ pDiskId, selectedVdiskId, nodeId, }) {
|
|
49
49
|
vDiskSlotId,
|
50
50
|
});
|
51
51
|
}
|
52
|
-
return (_jsxs("div", { className: b('vdisk-id', { selected: row.id === selectedVdiskId }), children: [_jsx("span", { children: vDiskSlotId }), vdiskInternalViewerLink && (_jsx(Button, { size: "s", className: b('external-button', { hidden: true }), href: vdiskInternalViewerLink, target: "_blank", title: i18n('vdisk.developer-ui-button-title'), children: _jsx(Icon, {
|
52
|
+
return (_jsxs("div", { className: b('vdisk-id', { selected: row.id === selectedVdiskId }), children: [_jsx("span", { children: vDiskSlotId }), vdiskInternalViewerLink && (_jsx(Button, { size: "s", className: b('external-button', { hidden: true }), href: vdiskInternalViewerLink, target: "_blank", title: i18n('vdisk.developer-ui-button-title'), children: _jsx(Icon, { data: ArrowUpRightFromSquare }) }))] }));
|
53
53
|
},
|
54
54
|
align: DataTable.LEFT,
|
55
55
|
},
|
@@ -80,7 +80,7 @@ function getColumns({ pDiskId, selectedVdiskId, nodeId, }) {
|
|
80
80
|
render: ({ row }) => {
|
81
81
|
return (_jsx(Popover, { placement: ['right'], content: _jsx(Vdisk, { data: row }), tooltipContentClassName: b('vdisk-details'), children: _jsx(Button, { view: "flat-secondary", className: b('vdisk-details-button', {
|
82
82
|
selected: row.id === selectedVdiskId,
|
83
|
-
}), children: _jsx(Icon, {
|
83
|
+
}), children: _jsx(Icon, { data: CircleInfoFill, size: 18 }) }) }));
|
84
84
|
},
|
85
85
|
sortable: false,
|
86
86
|
},
|
@@ -2,6 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import React from 'react';
|
3
3
|
import { ASCENDING } from '@gravity-ui/react-data-table/build/esm/lib/constants';
|
4
4
|
import { skipToken } from '@reduxjs/toolkit/query';
|
5
|
+
import { StringParam, useQueryParams } from 'use-query-params';
|
5
6
|
import { EntitiesCount } from '../../components/EntitiesCount';
|
6
7
|
import { AccessDenied } from '../../components/Errors/403';
|
7
8
|
import { ResponseError } from '../../components/Errors/ResponseError';
|
@@ -11,21 +12,27 @@ import { ResizeableDataTable } from '../../components/ResizeableDataTable/Resize
|
|
11
12
|
import { Search } from '../../components/Search';
|
12
13
|
import { TableWithControlsLayout } from '../../components/TableWithControlsLayout/TableWithControlsLayout';
|
13
14
|
import { UptimeFilter } from '../../components/UptimeFIlter';
|
14
|
-
import { nodesApi
|
15
|
+
import { nodesApi } from '../../store/reducers/nodes/nodes';
|
15
16
|
import { filterNodes } from '../../store/reducers/nodes/selectors';
|
16
17
|
import { ProblemFilterValues, changeFilter } from '../../store/reducers/settings/settings';
|
17
18
|
import { cn } from '../../utils/cn';
|
18
19
|
import { DEFAULT_POLLING_INTERVAL, DEFAULT_TABLE_SETTINGS, USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY, } from '../../utils/constants';
|
19
20
|
import { useSetting, useTableSort, useTypedDispatch, useTypedSelector } from '../../utils/hooks';
|
20
|
-
import { NodesUptimeFilterValues, isSortableNodesProperty, isUnavailableNode, } from '../../utils/nodes';
|
21
|
+
import { NodesUptimeFilterValues, isSortableNodesProperty, isUnavailableNode, nodesUptimeFilterValuesSchema, } from '../../utils/nodes';
|
21
22
|
import { NODES_COLUMNS_WIDTH_LS_KEY, getNodesColumns } from './getNodesColumns';
|
22
23
|
import i18n from './i18n';
|
23
24
|
import './Nodes.scss';
|
24
25
|
const b = cn('ydb-nodes');
|
25
26
|
export const Nodes = ({ path, additionalNodesProps = {} }) => {
|
27
|
+
var _a;
|
28
|
+
const [queryParams, setQueryParams] = useQueryParams({
|
29
|
+
uptimeFilter: StringParam,
|
30
|
+
search: StringParam,
|
31
|
+
});
|
32
|
+
const uptimeFilter = nodesUptimeFilterValuesSchema.parse(queryParams.uptimeFilter);
|
33
|
+
const searchValue = (_a = queryParams.search) !== null && _a !== void 0 ? _a : '';
|
26
34
|
const dispatch = useTypedDispatch();
|
27
35
|
const isClusterNodes = !path;
|
28
|
-
const { uptimeFilter, searchValue, sortOrder = ASCENDING, sortValue = 'NodeId', } = useTypedSelector((state) => state.nodes);
|
29
36
|
const problemFilter = useTypedSelector((state) => state.settings.problemFilter);
|
30
37
|
const { autorefresh } = useTypedSelector((state) => state.schema);
|
31
38
|
const [useNodesEndpoint] = useSetting(USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY);
|
@@ -39,25 +46,22 @@ export const Nodes = ({ path, additionalNodesProps = {} }) => {
|
|
39
46
|
pollingInterval: autoRefreshInterval,
|
40
47
|
});
|
41
48
|
const { currentData: data, isLoading, error } = useGetComputeNodes ? computeQuery : nodesQuery;
|
42
|
-
const [
|
49
|
+
const [sortValue, setSortValue] = React.useState({
|
50
|
+
sortValue: 'NodeId',
|
51
|
+
sortOrder: ASCENDING,
|
52
|
+
});
|
53
|
+
const [sort, handleSort] = useTableSort(sortValue, (sortParams) => {
|
54
|
+
setSortValue(sortParams);
|
55
|
+
});
|
43
56
|
const handleSearchQueryChange = (value) => {
|
44
|
-
|
57
|
+
setQueryParams({ search: value || undefined }, 'replaceIn');
|
45
58
|
};
|
46
59
|
const handleProblemFilterChange = (value) => {
|
47
60
|
dispatch(changeFilter(value));
|
48
61
|
};
|
49
62
|
const handleUptimeFilterChange = (value) => {
|
50
|
-
|
63
|
+
setQueryParams({ uptimeFilter: value }, 'replaceIn');
|
51
64
|
};
|
52
|
-
// Since Nodes component is used in several places,
|
53
|
-
// we need to reset filters, searchValue
|
54
|
-
// in nodes reducer when path changes
|
55
|
-
React.useEffect(() => {
|
56
|
-
return () => {
|
57
|
-
// Clean data on component unmount
|
58
|
-
dispatch(setInitialState());
|
59
|
-
};
|
60
|
-
}, [dispatch, path]);
|
61
65
|
const nodes = React.useMemo(() => {
|
62
66
|
return filterNodes(data === null || data === void 0 ? void 0 : data.Nodes, { searchValue, uptimeFilter, problemFilter });
|
63
67
|
}, [data, searchValue, uptimeFilter, problemFilter]);
|
@@ -1,5 +1,6 @@
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
2
2
|
import React from 'react';
|
3
|
+
import { StringParam, useQueryParams } from 'use-query-params';
|
3
4
|
import { EntitiesCount } from '../../components/EntitiesCount';
|
4
5
|
import { AccessDenied } from '../../components/Errors/403';
|
5
6
|
import { ResponseError } from '../../components/Errors/ResponseError';
|
@@ -8,18 +9,25 @@ import { ProblemFilter } from '../../components/ProblemFilter';
|
|
8
9
|
import { Search } from '../../components/Search';
|
9
10
|
import { UptimeFilter } from '../../components/UptimeFIlter';
|
10
11
|
import { ResizeableVirtualTable } from '../../components/VirtualTable/ResizeableVirtualTable';
|
11
|
-
import { ProblemFilterValues } from '../../store/reducers/settings/settings';
|
12
|
+
import { ProblemFilterValues, changeFilter } from '../../store/reducers/settings/settings';
|
12
13
|
import { cn } from '../../utils/cn';
|
13
|
-
import {
|
14
|
+
import { useTypedDispatch, useTypedSelector } from '../../utils/hooks';
|
15
|
+
import { NodesUptimeFilterValues, getProblemParamValue, getUptimeParamValue, isSortableNodesProperty, isUnavailableNode, nodesUptimeFilterValuesSchema, } from '../../utils/nodes';
|
14
16
|
import { getNodes } from './getNodes';
|
15
17
|
import { NODES_COLUMNS_WIDTH_LS_KEY, getNodesColumns } from './getNodesColumns';
|
16
18
|
import i18n from './i18n';
|
17
19
|
import './Nodes.scss';
|
18
20
|
const b = cn('ydb-nodes');
|
19
21
|
export const VirtualNodes = ({ path, parentContainer, additionalNodesProps }) => {
|
20
|
-
|
21
|
-
const [
|
22
|
-
|
22
|
+
var _a;
|
23
|
+
const [queryParams, setQueryParams] = useQueryParams({
|
24
|
+
uptimeFilter: StringParam,
|
25
|
+
search: StringParam,
|
26
|
+
});
|
27
|
+
const uptimeFilter = nodesUptimeFilterValuesSchema.parse(queryParams.uptimeFilter);
|
28
|
+
const searchValue = (_a = queryParams.search) !== null && _a !== void 0 ? _a : '';
|
29
|
+
const dispatch = useTypedDispatch();
|
30
|
+
const problemFilter = useTypedSelector((state) => state.settings.problemFilter);
|
23
31
|
const filters = React.useMemo(() => {
|
24
32
|
return [path, searchValue, problemFilter, uptimeFilter];
|
25
33
|
}, [path, searchValue, problemFilter, uptimeFilter]);
|
@@ -39,7 +47,16 @@ export const VirtualNodes = ({ path, parentContainer, additionalNodesProps }) =>
|
|
39
47
|
return b('node', { unavailable: isUnavailableNode(row) });
|
40
48
|
};
|
41
49
|
const renderControls = ({ totalEntities, foundEntities, inited }) => {
|
42
|
-
|
50
|
+
const handleSearchQueryChange = (value) => {
|
51
|
+
setQueryParams({ search: value || undefined }, 'replaceIn');
|
52
|
+
};
|
53
|
+
const handleProblemFilterChange = (value) => {
|
54
|
+
dispatch(changeFilter(value));
|
55
|
+
};
|
56
|
+
const handleUptimeFilterChange = (value) => {
|
57
|
+
setQueryParams({ uptimeFilter: value }, 'replaceIn');
|
58
|
+
};
|
59
|
+
return (_jsxs(React.Fragment, { children: [_jsx(Search, { onChange: handleSearchQueryChange, placeholder: "Host name", className: b('search'), value: searchValue }), _jsx(ProblemFilter, { value: problemFilter, onChange: handleProblemFilterChange }), _jsx(UptimeFilter, { value: uptimeFilter, onChange: handleUptimeFilterChange }), _jsx(EntitiesCount, { total: totalEntities, current: foundEntities, label: 'Nodes', loading: !inited })] }));
|
43
60
|
};
|
44
61
|
const renderEmptyDataMessage = () => {
|
45
62
|
if (problemFilter !== ProblemFilterValues.ALL ||
|
@@ -1,5 +1,6 @@
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
2
2
|
import React from 'react';
|
3
|
+
import { ArrowRotateLeft } from '@gravity-ui/icons';
|
3
4
|
import { Icon } from '@gravity-ui/uikit';
|
4
5
|
import { skipToken } from '@reduxjs/toolkit/query';
|
5
6
|
import { Helmet } from 'react-helmet-async';
|
@@ -19,12 +20,12 @@ import { useTypedDispatch, useTypedSelector } from '../../utils/hooks';
|
|
19
20
|
import { PDiskGroups } from './PDiskGroups';
|
20
21
|
import { pDiskPageKeyset } from './i18n';
|
21
22
|
import { pdiskPageCn } from './shared';
|
22
|
-
import ArrowRotateLeftIcon from '@gravity-ui/icons/svgs/arrow-rotate-left.svg';
|
23
23
|
import './PDiskPage.scss';
|
24
24
|
export function PDiskPage() {
|
25
25
|
var _a;
|
26
26
|
const dispatch = useTypedDispatch();
|
27
27
|
const nodesMap = useTypedSelector(selectNodesMap);
|
28
|
+
const { isUserAllowedToMakeChanges } = useTypedSelector((state) => state.authentication);
|
28
29
|
const [{ nodeId, pDiskId }] = useQueryParams({
|
29
30
|
nodeId: StringParam,
|
30
31
|
pDiskId: StringParam,
|
@@ -74,7 +75,7 @@ export function PDiskPage() {
|
|
74
75
|
return (_jsx(DiskPageTitle, { entityName: pDiskPageKeyset('pdisk'), status: getSeverityColor(Severity), id: pDiskId, className: pdiskPageCn('title') }));
|
75
76
|
};
|
76
77
|
const renderControls = () => {
|
77
|
-
return (_jsx("div", { className: pdiskPageCn('controls'), children: _jsxs(ButtonWithConfirmDialog, { onConfirmAction: handleRestart, onConfirmActionSuccess: handleAfterRestart, buttonDisabled: !nodeId || !pDiskId, buttonView: "normal", dialogContent: pDiskPageKeyset('restart-pdisk-dialog'), children: [_jsx(Icon, { data:
|
78
|
+
return (_jsx("div", { className: pdiskPageCn('controls'), children: _jsxs(ButtonWithConfirmDialog, { onConfirmAction: handleRestart, onConfirmActionSuccess: handleAfterRestart, buttonDisabled: !nodeId || !pDiskId || !isUserAllowedToMakeChanges, buttonView: "normal", dialogContent: pDiskPageKeyset('restart-pdisk-dialog'), withPopover: true, popoverContent: pDiskPageKeyset('restart-pdisk-not-allowed'), popoverDisabled: isUserAllowedToMakeChanges, children: [_jsx(Icon, { data: ArrowRotateLeft }), pDiskPageKeyset('restart-pdisk-button')] }) }));
|
78
79
|
};
|
79
80
|
const renderInfo = () => {
|
80
81
|
if (pDiskLoading) {
|
@@ -4,5 +4,6 @@
|
|
4
4
|
"groups": "Groups",
|
5
5
|
"node": "Node",
|
6
6
|
"restart-pdisk-button": "Restart PDisk",
|
7
|
-
"restart-pdisk-dialog": "PDisk will be restarted. Do you want to proceed?"
|
7
|
+
"restart-pdisk-dialog": "PDisk will be restarted. Do you want to proceed?",
|
8
|
+
"restart-pdisk-not-allowed": "You don't have enough rights to restart PDisk"
|
8
9
|
}
|
@@ -1 +1 @@
|
|
1
|
-
export declare const pDiskPageKeyset: (key: "
|
1
|
+
export declare const pDiskPageKeyset: (key: "node" | "groups" | "fqdn" | "pdisk" | "restart-pdisk-button" | "restart-pdisk-dialog" | "restart-pdisk-not-allowed", params?: import("@gravity-ui/i18n").Params | undefined) => string;
|
@@ -1,28 +1,62 @@
|
|
1
1
|
import { __rest } from "tslib";
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
3
3
|
import React from 'react';
|
4
|
+
import { ArrayParam, StringParam, useQueryParams, withDefault } from 'use-query-params';
|
4
5
|
import { AccessDenied } from '../../components/Errors/403';
|
5
6
|
import { ResponseError } from '../../components/Errors/ResponseError';
|
6
7
|
import { TableWithControlsLayout } from '../../components/TableWithControlsLayout/TableWithControlsLayout';
|
7
8
|
import { selectNodesMap } from '../../store/reducers/nodesList';
|
8
9
|
import { STORAGE_TYPES, VISIBLE_ENTITIES } from '../../store/reducers/storage/constants';
|
9
|
-
import { filterGroups, filterNodes, getUsageFilterOptions,
|
10
|
-
import {
|
10
|
+
import { filterGroups, filterNodes, getUsageFilterOptions, } from '../../store/reducers/storage/selectors';
|
11
|
+
import { storageApi } from '../../store/reducers/storage/storage';
|
12
|
+
import { storageTypeSchema, visibleEntitiesSchema } from '../../store/reducers/storage/types';
|
11
13
|
import { DEFAULT_POLLING_INTERVAL, DEFAULT_TABLE_SETTINGS } from '../../utils/constants';
|
12
|
-
import { useNodesRequestParams, useStorageRequestParams, useTableSort,
|
13
|
-
import { NodesUptimeFilterValues } from '../../utils/nodes';
|
14
|
+
import { useNodesRequestParams, useStorageRequestParams, useTableSort, useTypedSelector, } from '../../utils/hooks';
|
15
|
+
import { NodesUptimeFilterValues, nodesUptimeFilterValuesSchema } from '../../utils/nodes';
|
14
16
|
import { StorageControls } from './StorageControls/StorageControls';
|
15
17
|
import { StorageGroups } from './StorageGroups/StorageGroups';
|
16
18
|
import { StorageNodes } from './StorageNodes/StorageNodes';
|
17
19
|
import { b } from './shared';
|
20
|
+
import { defaultSortNode, getDefaultSortGroup } from './utils';
|
18
21
|
import './Storage.scss';
|
22
|
+
const UsageFilterParam = withDefault({
|
23
|
+
encode: ArrayParam.encode,
|
24
|
+
decode: (input) => {
|
25
|
+
if (input === null || input === undefined) {
|
26
|
+
return input;
|
27
|
+
}
|
28
|
+
if (!Array.isArray(input)) {
|
29
|
+
return input ? [input] : [];
|
30
|
+
}
|
31
|
+
return input.filter(Boolean);
|
32
|
+
},
|
33
|
+
}, []);
|
19
34
|
export const Storage = ({ additionalNodesProps, tenant, nodeId }) => {
|
20
|
-
|
35
|
+
var _a;
|
21
36
|
const { autorefresh } = useTypedSelector((state) => state.schema);
|
22
|
-
const
|
37
|
+
const [queryParams, setQueryParams] = useQueryParams({
|
38
|
+
type: StringParam,
|
39
|
+
visible: StringParam,
|
40
|
+
search: StringParam,
|
41
|
+
uptimeFilter: StringParam,
|
42
|
+
usageFilter: UsageFilterParam,
|
43
|
+
});
|
44
|
+
const type = storageTypeSchema.parse(queryParams.type);
|
45
|
+
const visibleEntities = visibleEntitiesSchema.parse(queryParams.visible);
|
46
|
+
const filter = (_a = queryParams.search) !== null && _a !== void 0 ? _a : '';
|
47
|
+
const uptimeFilter = nodesUptimeFilterValuesSchema.parse(queryParams.uptimeFilter);
|
48
|
+
const usageFilter = queryParams.usageFilter;
|
23
49
|
const nodesMap = useTypedSelector(selectNodesMap);
|
24
|
-
const
|
25
|
-
|
50
|
+
const [nodeSort, setNodeSort] = React.useState({
|
51
|
+
sortOrder: undefined,
|
52
|
+
sortValue: undefined,
|
53
|
+
});
|
54
|
+
const nodesSortParams = nodeSort.sortValue ? nodeSort : defaultSortNode;
|
55
|
+
const [groupSort, setGroupSort] = React.useState({
|
56
|
+
sortOrder: undefined,
|
57
|
+
sortValue: undefined,
|
58
|
+
});
|
59
|
+
const groupsSortParams = groupSort.sortOrder ? groupSort : getDefaultSortGroup(visibleEntities);
|
26
60
|
// Do not display Nodes table for Node page (NodeId present)
|
27
61
|
const isNodePage = nodeId !== undefined;
|
28
62
|
const storageType = isNodePage ? STORAGE_TYPES.groups : type;
|
@@ -40,33 +74,27 @@ export const Storage = ({ additionalNodesProps, tenant, nodeId }) => {
|
|
40
74
|
const { currentData, isFetching, error } = storageType === STORAGE_TYPES.nodes ? nodesQuery : groupsQuery;
|
41
75
|
const { currentData: { nodes = [] } = {} } = nodesQuery;
|
42
76
|
const { currentData: { groups = [] } = {} } = groupsQuery;
|
43
|
-
const
|
77
|
+
const _b = currentData !== null && currentData !== void 0 ? currentData : { found: 0, total: 0 }, { nodes: _, groups: __ } = _b, entitiesCount = __rest(_b, ["nodes", "groups"]);
|
44
78
|
const isLoading = currentData === undefined && isFetching;
|
45
79
|
const storageNodes = React.useMemo(() => filterNodes(nodes, filter, uptimeFilter), [filter, nodes, uptimeFilter]);
|
46
80
|
const storageGroups = React.useMemo(() => filterGroups(groups, filter, usageFilter), [filter, groups, usageFilter]);
|
47
81
|
const usageFilterOptions = React.useMemo(() => getUsageFilterOptions(groups), [groups]);
|
48
|
-
|
49
|
-
|
50
|
-
// Clean data on component unmount
|
51
|
-
dispatch(setInitialState());
|
52
|
-
};
|
53
|
-
}, [dispatch]);
|
54
|
-
const [nodesSort, handleNodesSort] = useTableSort(nodesSortParams, (params) => dispatch(setNodesSortParams(params)));
|
55
|
-
const [groupsSort, handleGroupsSort] = useTableSort(groupsSortParams, (params) => dispatch(setGroupsSortParams(params)));
|
82
|
+
const [nodesSort, handleNodesSort] = useTableSort(nodesSortParams, (params) => setNodeSort(params));
|
83
|
+
const [groupsSort, handleGroupsSort] = useTableSort(groupsSortParams, (params) => setGroupSort(params));
|
56
84
|
const handleUsageFilterChange = (value) => {
|
57
|
-
|
85
|
+
setQueryParams({ usageFilter: value.length ? value : undefined }, 'replaceIn');
|
58
86
|
};
|
59
87
|
const handleTextFilterChange = (value) => {
|
60
|
-
|
88
|
+
setQueryParams({ search: value || undefined }, 'replaceIn');
|
61
89
|
};
|
62
90
|
const handleGroupVisibilityChange = (value) => {
|
63
|
-
|
91
|
+
setQueryParams({ visible: value }, 'replaceIn');
|
64
92
|
};
|
65
93
|
const handleStorageTypeChange = (value) => {
|
66
|
-
|
94
|
+
setQueryParams({ type: value }, 'replaceIn');
|
67
95
|
};
|
68
96
|
const handleUptimeFilterChange = (value) => {
|
69
|
-
|
97
|
+
setQueryParams({ uptimeFilter: value }, 'replaceIn');
|
70
98
|
};
|
71
99
|
const handleShowAllNodes = () => {
|
72
100
|
handleGroupVisibilityChange(VISIBLE_ENTITIES.all);
|
@@ -1,5 +1,6 @@
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
2
2
|
import React from 'react';
|
3
|
+
import { ShieldKeyhole } from '@gravity-ui/icons';
|
3
4
|
import DataTable from '@gravity-ui/react-data-table';
|
4
5
|
import { Icon, Label, Popover, PopoverBehavior } from '@gravity-ui/uikit';
|
5
6
|
import { CellWithPopover } from '../../../components/CellWithPopover/CellWithPopover';
|
@@ -14,7 +15,6 @@ import { isSortableStorageProperty } from '../../../utils/storage';
|
|
14
15
|
import { bytesToGB, bytesToSpeed } from '../../../utils/utils';
|
15
16
|
import { getDegradedSeverity, getUsageSeverityForStorageGroup } from '../utils';
|
16
17
|
import i18n from './i18n';
|
17
|
-
import shieldIcon from '../../../assets/icons/shield.svg';
|
18
18
|
import './StorageGroups.scss';
|
19
19
|
const b = cn('global-storage-groups');
|
20
20
|
export const STORAGE_GROUPS_COLUMNS_WIDTH_LS_KEY = 'storageGroupsColumnsWidth';
|
@@ -49,7 +49,7 @@ const typeColumn = {
|
|
49
49
|
width: 100,
|
50
50
|
resizeMinWidth: 100,
|
51
51
|
align: DataTable.LEFT,
|
52
|
-
render: ({ row }) => (_jsxs(React.Fragment, { children: [_jsx(Label, { children: row.MediaType || '—' }), '\u00a0', row.Encryption && (_jsx(Popover, { content: i18n('encrypted'), placement: "right", behavior: PopoverBehavior.Immediate, children: _jsx(Label, { children: _jsx(Icon, { data:
|
52
|
+
render: ({ row }) => (_jsxs(React.Fragment, { children: [_jsx(Label, { children: row.MediaType || '—' }), '\u00a0', row.Encryption && (_jsx(Popover, { content: i18n('encrypted'), placement: "right", behavior: PopoverBehavior.Immediate, children: _jsx(Label, { children: _jsx(Icon, { data: ShieldKeyhole, size: 18 }) }) }))] })),
|
53
53
|
sortable: false,
|
54
54
|
};
|
55
55
|
const erasureColumn = {
|
@@ -1,29 +1,51 @@
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
2
|
-
import
|
2
|
+
import { StringParam, useQueryParams } from 'use-query-params';
|
3
3
|
import { AccessDenied } from '../../components/Errors/403/AccessDenied';
|
4
4
|
import { ResponseError } from '../../components/Errors/ResponseError/ResponseError';
|
5
5
|
import { selectNodesMap } from '../../store/reducers/nodesList';
|
6
6
|
import { STORAGE_TYPES, VISIBLE_ENTITIES } from '../../store/reducers/storage/constants';
|
7
|
+
import { storageTypeSchema, visibleEntitiesSchema } from '../../store/reducers/storage/types';
|
7
8
|
import { useTypedSelector } from '../../utils/hooks';
|
8
|
-
import { NodesUptimeFilterValues } from '../../utils/nodes';
|
9
|
+
import { NodesUptimeFilterValues, nodesUptimeFilterValuesSchema } from '../../utils/nodes';
|
9
10
|
import { StorageControls } from './StorageControls/StorageControls';
|
10
11
|
import { VirtualStorageGroups } from './StorageGroups/VirtualStorageGroups';
|
11
12
|
import { VirtualStorageNodes } from './StorageNodes/VirtualStorageNodes';
|
12
13
|
export const VirtualStorage = ({ tenant, nodeId, parentContainer, additionalNodesProps, }) => {
|
13
|
-
|
14
|
-
const [
|
15
|
-
|
16
|
-
|
14
|
+
var _a;
|
15
|
+
const [queryParams, setQueryParams] = useQueryParams({
|
16
|
+
type: StringParam,
|
17
|
+
visible: StringParam,
|
18
|
+
search: StringParam,
|
19
|
+
uptimeFilter: StringParam,
|
20
|
+
});
|
21
|
+
const storageType = storageTypeSchema.parse(queryParams.type);
|
22
|
+
const visibleEntities = visibleEntitiesSchema.parse(queryParams.visible);
|
23
|
+
const searchValue = (_a = queryParams.search) !== null && _a !== void 0 ? _a : '';
|
24
|
+
const nodesUptimeFilter = nodesUptimeFilterValuesSchema.parse(queryParams.uptimeFilter);
|
25
|
+
const handleTextFilterChange = (value) => {
|
26
|
+
setQueryParams({ search: value || undefined }, 'replaceIn');
|
27
|
+
};
|
28
|
+
const handleGroupVisibilityChange = (value) => {
|
29
|
+
setQueryParams({ visible: value }, 'replaceIn');
|
30
|
+
};
|
31
|
+
const handleStorageTypeChange = (value) => {
|
32
|
+
setQueryParams({ type: value }, 'replaceIn');
|
33
|
+
};
|
34
|
+
const handleUptimeFilterChange = (value) => {
|
35
|
+
setQueryParams({ uptimeFilter: value }, 'replaceIn');
|
36
|
+
};
|
17
37
|
const nodesMap = useTypedSelector(selectNodesMap);
|
18
38
|
const handleShowAllGroups = () => {
|
19
|
-
|
39
|
+
handleGroupVisibilityChange(VISIBLE_ENTITIES.all);
|
20
40
|
};
|
21
41
|
const handleShowAllNodes = () => {
|
22
|
-
|
23
|
-
|
42
|
+
setQueryParams({
|
43
|
+
visible: VISIBLE_ENTITIES.all,
|
44
|
+
uptimeFilter: NodesUptimeFilterValues.All,
|
45
|
+
}, 'replaceIn');
|
24
46
|
};
|
25
47
|
const renderControls = ({ totalEntities, foundEntities, inited }) => {
|
26
|
-
return (_jsx(StorageControls, { searchValue: searchValue, handleSearchValueChange:
|
48
|
+
return (_jsx(StorageControls, { searchValue: searchValue, handleSearchValueChange: handleTextFilterChange, withTypeSelector: !nodeId, storageType: storageType, handleStorageTypeChange: handleStorageTypeChange, visibleEntities: visibleEntities, handleVisibleEntitiesChange: handleGroupVisibilityChange, nodesUptimeFilter: nodesUptimeFilter, handleNodesUptimeFilterChange: handleUptimeFilterChange, withGroupsUsageFilter: false, entitiesCountCurrent: foundEntities, entitiesCountTotal: totalEntities, entitiesLoading: !inited }));
|
27
49
|
};
|
28
50
|
const renderErrorMessage = (error) => {
|
29
51
|
if (error.status === 403) {
|
@@ -1,5 +1,8 @@
|
|
1
|
-
import type {
|
1
|
+
import type { NodesSortParams } from '../../../store/reducers/nodes/types';
|
2
|
+
import type { PreparedStorageGroup, StorageSortParams, VisibleEntities } from '../../../store/reducers/storage/types';
|
2
3
|
import { EFlag } from '../../../types/api/enums';
|
3
4
|
export declare const getDegradedSeverity: (group: PreparedStorageGroup) => "success" | "danger" | "warning" | undefined;
|
4
5
|
export declare const getUsageSeverityForStorageGroup: (value: number) => "success" | "danger" | "warning" | undefined;
|
5
6
|
export declare const getUsageSeverityForEntityStatus: (value: number) => EFlag.Green | EFlag.Yellow | EFlag.Red | undefined;
|
7
|
+
export declare const defaultSortNode: NodesSortParams;
|
8
|
+
export declare function getDefaultSortGroup(visibleEntities: VisibleEntities): StorageSortParams;
|