ydb-embedded-ui 4.5.2 → 4.7.0
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +33 -0
- package/dist/assets/icons/versions.svg +3 -0
- package/dist/components/NodeHostWrapper/NodeHostWrapper.tsx +7 -2
- package/dist/components/Tablet/Tablet.tsx +17 -3
- package/dist/components/TabletsStatistic/TabletsStatistic.tsx +23 -16
- package/dist/containers/App/Content.js +8 -4
- package/dist/containers/AsideNavigation/AsideNavigation.tsx +4 -50
- package/dist/containers/Cluster/Cluster.scss +7 -48
- package/dist/containers/Cluster/Cluster.tsx +129 -20
- package/dist/containers/Cluster/ClusterInfo/ClusterInfo.scss +34 -17
- package/dist/containers/Cluster/ClusterInfo/ClusterInfo.tsx +58 -92
- package/dist/containers/Cluster/ClusterInfoSkeleton/ClusterInfoSkeleton.scss +48 -0
- package/dist/containers/Cluster/ClusterInfoSkeleton/ClusterInfoSkeleton.tsx +34 -0
- package/dist/containers/Cluster/utils.tsx +45 -0
- package/dist/containers/Header/Header.scss +4 -19
- package/dist/containers/Header/Header.tsx +72 -46
- package/dist/containers/Header/breadcrumbs.ts +146 -0
- package/dist/containers/Node/Node.tsx +25 -29
- package/dist/containers/Node/NodePages.ts +10 -6
- package/dist/containers/Nodes/Nodes.tsx +0 -16
- package/dist/containers/Nodes/getNodesColumns.tsx +1 -1
- package/dist/containers/Storage/Storage.js +1 -11
- package/dist/containers/Storage/StorageGroups/StorageGroups.tsx +11 -3
- package/dist/containers/Tablet/Tablet.tsx +40 -4
- package/dist/containers/Tablet/TabletInfo/TabletInfo.tsx +2 -2
- package/dist/containers/TabletsFilters/TabletsFilters.js +15 -2
- package/dist/containers/Tenant/Diagnostics/Consumers/columns/columns.tsx +1 -1
- package/dist/containers/Tenant/Diagnostics/Describe/Describe.tsx +1 -1
- package/dist/containers/Tenant/Diagnostics/DetailedOverview/DetailedOverview.scss +7 -0
- package/dist/containers/Tenant/Diagnostics/Diagnostics.tsx +4 -4
- package/dist/containers/Tenant/Diagnostics/Healthcheck/Healthcheck.scss +5 -3
- package/dist/containers/Tenant/Diagnostics/Healthcheck/Healthcheck.tsx +1 -1
- package/dist/containers/Tenant/Diagnostics/Overview/ChangefeedInfo/ChangefeedInfo.tsx +4 -6
- package/dist/containers/Tenant/Diagnostics/Overview/Overview.tsx +56 -53
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.js +2 -1
- package/dist/containers/Tenant/Diagnostics/TopQueries/TopQueries.tsx +11 -13
- package/dist/containers/Tenant/Diagnostics/TopShards/TopShards.tsx +1 -1
- package/dist/containers/Tenant/ObjectGeneral/ObjectGeneral.tsx +2 -2
- package/dist/containers/Tenant/ObjectSummary/ObjectSummary.tsx +7 -3
- package/dist/containers/Tenant/Preview/Preview.js +1 -1
- package/dist/containers/Tenant/{QueryEditor/QueryResult/QueryResult.js → Query/ExecuteResult/ExecuteResult.js} +3 -5
- package/dist/containers/Tenant/{QueryEditor/QueryResult/QueryResult.scss → Query/ExecuteResult/ExecuteResult.scss} +1 -1
- package/dist/containers/Tenant/{QueryEditor/QueryExplain/QueryExplain.js → Query/ExplainResult/ExplainResult.js} +3 -5
- package/dist/containers/Tenant/{QueryEditor/QueryExplain/QueryExplain.scss → Query/ExplainResult/ExplainResult.scss} +1 -1
- package/dist/containers/Tenant/Query/QueriesHistory/QueriesHistory.scss +20 -0
- package/dist/containers/Tenant/Query/QueriesHistory/QueriesHistory.tsx +60 -0
- package/dist/containers/Tenant/Query/Query.scss +16 -0
- package/dist/containers/Tenant/Query/Query.tsx +73 -0
- package/dist/containers/Tenant/{QueryEditor → Query/QueryEditor}/QueryEditor.js +43 -100
- package/dist/containers/Tenant/{QueryEditor → Query/QueryEditor}/QueryEditor.scss +7 -23
- package/dist/containers/Tenant/{QueryEditor → Query}/QueryEditorControls/OldQueryEditorControls.tsx +10 -3
- package/dist/containers/Tenant/{QueryEditor → Query}/QueryEditorControls/QueryEditorControls.scss +1 -4
- package/dist/containers/Tenant/{QueryEditor → Query}/QueryEditorControls/QueryEditorControls.tsx +8 -1
- package/dist/containers/Tenant/{QueryEditor → Query}/QueryEditorControls/shared.ts +1 -6
- package/dist/containers/Tenant/Query/QueryTabs/QueryTabs.tsx +59 -0
- package/dist/containers/Tenant/{QueryEditor → Query}/SaveQuery/SaveQuery.js +5 -5
- package/dist/containers/Tenant/Query/SavedQueries/SavedQueries.scss +55 -0
- package/dist/containers/Tenant/Query/SavedQueries/SavedQueries.tsx +150 -0
- package/dist/containers/Tenant/Query/i18n/en.json +12 -0
- package/dist/containers/Tenant/Query/i18n/ru.json +12 -0
- package/dist/containers/Tenant/Query/utils/getPreparedResult.ts +30 -0
- package/dist/containers/Tenant/Schema/SchemaTree/SchemaTree.tsx +1 -1
- package/dist/containers/Tenant/Tenant.tsx +4 -25
- package/dist/containers/Tenant/TenantPages.tsx +8 -2
- package/dist/containers/Tenant/utils/constants.ts +10 -0
- package/dist/containers/Tenant/utils/schemaActions.ts +8 -3
- package/dist/containers/Tenants/Tenants.js +39 -37
- package/dist/containers/Tenants/Tenants.scss +2 -4
- package/dist/containers/UserSettings/i18n/en.json +2 -2
- package/dist/containers/UserSettings/i18n/ru.json +2 -2
- package/dist/containers/UserSettings/settings.ts +4 -4
- package/dist/containers/Versions/Versions.scss +0 -4
- package/dist/containers/Versions/Versions.tsx +74 -66
- package/dist/routes.ts +8 -6
- package/dist/services/api.ts +15 -7
- package/dist/store/reducers/clusterNodes/clusterNodes.tsx +4 -0
- package/dist/store/reducers/executeQuery.ts +1 -1
- package/dist/store/reducers/header/header.ts +31 -0
- package/dist/store/reducers/header/types.ts +54 -0
- package/dist/store/reducers/index.ts +4 -2
- package/dist/store/reducers/node/types.ts +2 -0
- package/dist/store/reducers/overview/overview.ts +109 -0
- package/dist/store/reducers/overview/types.ts +24 -0
- package/dist/store/reducers/{schema.ts → schema/schema.ts} +24 -50
- package/dist/{types/store/schema.ts → store/reducers/schema/types.ts} +16 -15
- package/dist/store/reducers/settings/settings.ts +5 -3
- package/dist/store/reducers/tablet.ts +18 -1
- package/dist/store/reducers/tenant/constants.ts +6 -0
- package/dist/store/reducers/tenant/tenant.ts +21 -2
- package/dist/store/reducers/tenant/types.ts +9 -2
- package/dist/store/reducers/topic.ts +1 -1
- package/dist/store/state-url-mapping.js +4 -1
- package/dist/types/api/query.ts +78 -44
- package/dist/types/store/explainQuery.ts +2 -2
- package/dist/types/store/query.ts +9 -2
- package/dist/types/store/tablet.ts +7 -4
- package/dist/utils/constants.ts +5 -1
- package/dist/utils/nodes.ts +1 -1
- package/dist/utils/query.ts +3 -3
- package/package.json +2 -1
- package/dist/containers/Tenant/QueryEditor/QueriesHistory/QueriesHistory.scss +0 -85
- package/dist/containers/Tenant/QueryEditor/QueriesHistory/QueriesHistory.tsx +0 -95
- package/dist/containers/Tenant/QueryEditor/SavedQueries/SavedQueries.js +0 -161
- package/dist/containers/Tenant/QueryEditor/SavedQueries/SavedQueries.scss +0 -93
- package/dist/containers/Tenant/QueryEditor/i18n/en.json +0 -3
- package/dist/containers/Tenant/QueryEditor/i18n/ru.json +0 -3
- package/dist/store/reducers/header.ts +0 -26
- /package/dist/containers/Tenant/{QueryEditor → Query}/Issues/Issues.scss +0 -0
- /package/dist/containers/Tenant/{QueryEditor → Query}/Issues/Issues.tsx +0 -0
- /package/dist/containers/Tenant/{QueryEditor → Query}/Issues/models.ts +0 -0
- /package/dist/containers/Tenant/{QueryEditor → Query}/QueryDuration/QueryDuration.scss +0 -0
- /package/dist/containers/Tenant/{QueryEditor → Query}/QueryDuration/QueryDuration.tsx +0 -0
- /package/dist/containers/Tenant/{QueryEditor → Query}/SaveQuery/SaveQuery.scss +0 -0
- /package/dist/containers/Tenant/{QueryEditor → Query}/i18n/index.ts +0 -0
package/CHANGELOG.md
CHANGED
@@ -1,5 +1,38 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## [4.7.0](https://github.com/ydb-platform/ydb-embedded-ui/compare/v4.6.0...v4.7.0) (2023-06-23)
|
4
|
+
|
5
|
+
|
6
|
+
### Features
|
7
|
+
|
8
|
+
* **QueryEditor:** transform history and saved to tabs ([#427](https://github.com/ydb-platform/ydb-embedded-ui/issues/427)) ([6378ca7](https://github.com/ydb-platform/ydb-embedded-ui/commit/6378ca7013239b33e55c1f88fdde7cab3a102df6))
|
9
|
+
* update breadcrumbs ([#432](https://github.com/ydb-platform/ydb-embedded-ui/issues/432)) ([e583a03](https://github.com/ydb-platform/ydb-embedded-ui/commit/e583a03fe0d77698f29c924e611133f015c3f7ad))
|
10
|
+
|
11
|
+
|
12
|
+
### Bug Fixes
|
13
|
+
|
14
|
+
* **Cluster:** add icons to tabs ([#430](https://github.com/ydb-platform/ydb-embedded-ui/issues/430)) ([e9e649f](https://github.com/ydb-platform/ydb-embedded-ui/commit/e9e649f614691e44172c9b93dd3119066c145413))
|
15
|
+
* **ClusterInfo:** hide by default ([#435](https://github.com/ydb-platform/ydb-embedded-ui/issues/435)) ([ef2b353](https://github.com/ydb-platform/ydb-embedded-ui/commit/ef2b3535f2c6324a34c4386680f5050655a04eb4))
|
16
|
+
* **Cluster:** use counter from uikit for tabs ([#428](https://github.com/ydb-platform/ydb-embedded-ui/issues/428)) ([19ca3bd](https://github.com/ydb-platform/ydb-embedded-ui/commit/19ca3bd14b15bdab1a9621939ddceee6d23b08ac))
|
17
|
+
* **DetailedOverview:** prevent tenant info scroll on overflow ([#434](https://github.com/ydb-platform/ydb-embedded-ui/issues/434)) ([8ed6076](https://github.com/ydb-platform/ydb-embedded-ui/commit/8ed60760d54913d05f39d35d00a34c8b1d7d9738))
|
18
|
+
* rename Internal Viewer to Developer UI ([#423](https://github.com/ydb-platform/ydb-embedded-ui/issues/423)) ([3eb21f3](https://github.com/ydb-platform/ydb-embedded-ui/commit/3eb21f35a230cc591f02ef9b195f99031f832e8a))
|
19
|
+
* **Storage:** update columns ([#437](https://github.com/ydb-platform/ydb-embedded-ui/issues/437)) ([264fbc9](https://github.com/ydb-platform/ydb-embedded-ui/commit/264fbc984cd9ef1467110d3e2f5ed9b29a526c2b))
|
20
|
+
* **Tablet:** clear tablet data on unmount ([#425](https://github.com/ydb-platform/ydb-embedded-ui/issues/425)) ([5d308cd](https://github.com/ydb-platform/ydb-embedded-ui/commit/5d308cdded342d7a40cbc6a91431d3f286c39b8a))
|
21
|
+
* **TabletsStatistic:** use tenant backend ([#429](https://github.com/ydb-platform/ydb-embedded-ui/issues/429)) ([d290684](https://github.com/ydb-platform/ydb-embedded-ui/commit/d290684ba08aec8b66c0492ba571a5337b5b896c))
|
22
|
+
|
23
|
+
## [4.6.0](https://github.com/ydb-platform/ydb-embedded-ui/compare/v4.5.2...v4.6.0) (2023-06-13)
|
24
|
+
|
25
|
+
|
26
|
+
### Features
|
27
|
+
|
28
|
+
* **QueryEditor:** add data and query modes ([#422](https://github.com/ydb-platform/ydb-embedded-ui/issues/422)) ([c142f03](https://github.com/ydb-platform/ydb-embedded-ui/commit/c142f03e9caeab4dcf1d34b3988e949a94213932))
|
29
|
+
* rework navigation, update breadcrumbs ([#418](https://github.com/ydb-platform/ydb-embedded-ui/issues/418)) ([2d807d6](https://github.com/ydb-platform/ydb-embedded-ui/commit/2d807d6a52e13edcf2a7e1591672224339d91949))
|
30
|
+
|
31
|
+
|
32
|
+
### Bug Fixes
|
33
|
+
|
34
|
+
* **Diagnostics:** remove unneded tenantInfo fetch ([#420](https://github.com/ydb-platform/ydb-embedded-ui/issues/420)) ([ccaafe4](https://github.com/ydb-platform/ydb-embedded-ui/commit/ccaafe4ec9346ee1ec2ebd2a62600274f2175bfb))
|
35
|
+
|
3
36
|
## [4.5.2](https://github.com/ydb-platform/ydb-embedded-ui/compare/v4.5.1...v4.5.2) (2023-06-06)
|
4
37
|
|
5
38
|
|
@@ -0,0 +1,3 @@
|
|
1
|
+
<svg width="14" height="14" viewBox="0 0 14 14" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
2
|
+
<path d="M8.625 13.0156C8.625 13.2695 8.47266 13.498 8.24414 13.5742C8.04102 13.6758 7.76172 13.6504 7.58398 13.4727L5.55273 11.6445C5.42578 11.543 5.375 11.3652 5.375 11.1875C5.375 11.0352 5.42578 10.8574 5.55273 10.7559L7.58398 8.92773C7.76172 8.75 8.04102 8.72461 8.24414 8.82617C8.47266 8.90234 8.625 9.13086 8.625 9.35938V10.5781H9.03125C10.0215 10.5781 10.8594 9.76562 10.8594 8.75V4.61133C10.0215 4.35742 9.4375 3.57031 9.4375 2.65625C9.4375 1.53906 10.3262 0.625 11.4688 0.625C12.5859 0.625 13.5 1.53906 13.5 2.65625C13.5 3.57031 12.8906 4.35742 12.0781 4.61133V8.75C12.0781 10.4512 10.707 11.7969 9.03125 11.7969H8.625V13.0156ZM12.2812 2.65625C12.2812 2.22461 11.9004 1.84375 11.4688 1.84375C11.0117 1.84375 10.6562 2.22461 10.6562 2.65625C10.6562 3.11328 11.0117 3.46875 11.4688 3.46875C11.9004 3.46875 12.2812 3.11328 12.2812 2.65625ZM5.375 1.23438C5.375 1.00586 5.50195 0.777344 5.73047 0.701172C5.93359 0.599609 6.21289 0.625 6.39062 0.802734L8.42188 2.63086C8.54883 2.73242 8.625 2.91016 8.625 3.0625C8.625 3.24023 8.54883 3.41797 8.42188 3.51953L6.39062 5.34766C6.21289 5.52539 5.93359 5.55078 5.73047 5.44922C5.50195 5.37305 5.375 5.14453 5.375 4.89062V3.67188H4.96875C3.95312 3.67188 3.14062 4.50977 3.14062 5.5V9.66406C3.95312 9.91797 4.5625 10.7051 4.5625 11.5938C4.5625 12.7363 3.64844 13.625 2.53125 13.625C1.38867 13.625 0.5 12.7363 0.5 11.5938C0.5 10.7051 1.08398 9.91797 1.92188 9.66406V5.5C1.92188 3.82422 3.26758 2.45312 4.96875 2.45312H5.375V1.23438ZM1.71875 11.5938C1.71875 12.0508 2.07422 12.4062 2.53125 12.4062C2.96289 12.4062 3.34375 12.0508 3.34375 11.5938C3.34375 11.1621 2.96289 10.7812 2.53125 10.7812C2.07422 10.7812 1.71875 11.1621 1.71875 11.5938Z"/>
|
3
|
+
</svg>
|
@@ -16,7 +16,7 @@ const b = block('ydb-node-host-wrapper');
|
|
16
16
|
|
17
17
|
interface NodeHostWrapperProps {
|
18
18
|
node: INodesPreparedEntity;
|
19
|
-
getNodeRef?: (node?: NodeAddress) => string;
|
19
|
+
getNodeRef?: (node?: NodeAddress) => string | null;
|
20
20
|
}
|
21
21
|
|
22
22
|
export const NodeHostWrapper = ({node, getNodeRef}: NodeHostWrapperProps) => {
|
@@ -26,6 +26,11 @@ export const NodeHostWrapper = ({node, getNodeRef}: NodeHostWrapperProps) => {
|
|
26
26
|
|
27
27
|
const isNodeAvailable = !isUnavailableNode(node);
|
28
28
|
const nodeRef = isNodeAvailable && getNodeRef ? getNodeRef(node) + 'internal' : undefined;
|
29
|
+
const nodePath = isNodeAvailable
|
30
|
+
? getDefaultNodePath(node.NodeId, {
|
31
|
+
tenantName: node.TenantName,
|
32
|
+
})
|
33
|
+
: undefined;
|
29
34
|
|
30
35
|
return (
|
31
36
|
<div className={b()}>
|
@@ -39,7 +44,7 @@ export const NodeHostWrapper = ({node, getNodeRef}: NodeHostWrapperProps) => {
|
|
39
44
|
<EntityStatus
|
40
45
|
name={node.Host}
|
41
46
|
status={node.SystemState}
|
42
|
-
path={
|
47
|
+
path={nodePath}
|
43
48
|
hasClipboardButton
|
44
49
|
className={b('host')}
|
45
50
|
/>
|
@@ -14,18 +14,32 @@ const b = cn('tablet');
|
|
14
14
|
|
15
15
|
interface TabletProps {
|
16
16
|
tablet?: TTabletStateInfo;
|
17
|
+
tenantName?: string;
|
17
18
|
}
|
18
19
|
|
19
|
-
export const Tablet = ({tablet = {}}: TabletProps) => {
|
20
|
-
const {TabletId: id} = tablet;
|
20
|
+
export const Tablet = ({tablet = {}, tenantName}: TabletProps) => {
|
21
|
+
const {TabletId: id, NodeId, Type, State} = tablet;
|
21
22
|
const status = tablet.Overall?.toLowerCase();
|
22
23
|
|
24
|
+
const tabletPath =
|
25
|
+
id &&
|
26
|
+
createHref(
|
27
|
+
routes.tablet,
|
28
|
+
{id},
|
29
|
+
{
|
30
|
+
nodeId: NodeId,
|
31
|
+
type: Type,
|
32
|
+
state: State,
|
33
|
+
tenantName,
|
34
|
+
},
|
35
|
+
);
|
36
|
+
|
23
37
|
return (
|
24
38
|
<ContentWithPopup
|
25
39
|
className={b('wrapper')}
|
26
40
|
content={<TabletTooltipContent data={tablet} className={b('popup-content')} />}
|
27
41
|
>
|
28
|
-
<InternalLink to={
|
42
|
+
<InternalLink to={tabletPath}>
|
29
43
|
<div className={b({status})}>
|
30
44
|
<div className={b('type')}>{[getTabletLabel(tablet.Type)]}</div>
|
31
45
|
</div>
|
@@ -12,9 +12,9 @@ import './TabletsStatistic.scss';
|
|
12
12
|
|
13
13
|
const b = cn('tablets-statistic');
|
14
14
|
|
15
|
-
type
|
15
|
+
type Tablets = TFullTabletStateInfo[] | TComputeTabletStateInfo[];
|
16
16
|
|
17
|
-
const prepareTablets = (tablets:
|
17
|
+
const prepareTablets = (tablets: Tablets) => {
|
18
18
|
const res = tablets.map((tablet) => {
|
19
19
|
return {
|
20
20
|
label: getTabletLabel(tablet.Type),
|
@@ -28,25 +28,32 @@ const prepareTablets = (tablets: ITablets) => {
|
|
28
28
|
};
|
29
29
|
|
30
30
|
interface TabletsStatisticProps {
|
31
|
-
tablets:
|
31
|
+
tablets: Tablets;
|
32
32
|
path: string | undefined;
|
33
33
|
nodeIds: string[] | number[];
|
34
|
+
backend?: string;
|
34
35
|
}
|
35
36
|
|
36
|
-
export const TabletsStatistic = ({tablets = [], path, nodeIds}: TabletsStatisticProps) => {
|
37
|
+
export const TabletsStatistic = ({tablets = [], path, nodeIds, backend}: TabletsStatisticProps) => {
|
37
38
|
const renderTabletInfo = (item: ReturnType<typeof prepareTablets>[number], index: number) => {
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
39
|
+
const tabletsPath = createHref(routes.tabletsFilters, undefined, {
|
40
|
+
nodeIds,
|
41
|
+
state: item.state,
|
42
|
+
type: item.type,
|
43
|
+
path,
|
44
|
+
backend,
|
45
|
+
});
|
46
|
+
|
47
|
+
const label = `${item.label}: ${item.count}`;
|
48
|
+
const className = b('tablet', {state: item.state?.toLowerCase()});
|
49
|
+
|
50
|
+
return backend ? (
|
51
|
+
<a href={tabletsPath} key={index} className={className}>
|
52
|
+
{label}
|
53
|
+
</a>
|
54
|
+
) : (
|
55
|
+
<Link to={tabletsPath} key={index} className={className}>
|
56
|
+
{label}
|
50
57
|
</Link>
|
51
58
|
);
|
52
59
|
};
|
@@ -1,11 +1,11 @@
|
|
1
1
|
import React from 'react';
|
2
|
-
import {Switch, Route, Redirect, Router} from 'react-router-dom';
|
2
|
+
import {Switch, Route, Redirect, Router, useLocation} from 'react-router-dom';
|
3
3
|
import cn from 'bem-cn-lite';
|
4
4
|
import {connect} from 'react-redux';
|
5
5
|
|
6
6
|
import {ThemeProvider} from '@gravity-ui/uikit';
|
7
7
|
|
8
|
-
import routes, {createHref
|
8
|
+
import routes, {createHref} from '../../routes';
|
9
9
|
|
10
10
|
import Cluster from '../Cluster/Cluster';
|
11
11
|
import Tenant from '../Tenant/Tenant';
|
@@ -23,10 +23,13 @@ import './App.scss';
|
|
23
23
|
import PropTypes from 'prop-types';
|
24
24
|
import HistoryContext from '../../contexts/HistoryContext';
|
25
25
|
import Authentication from '../Authentication/Authentication';
|
26
|
+
import {clusterTabsIds} from '../Cluster/utils';
|
26
27
|
|
27
28
|
const b = cn('app');
|
28
29
|
|
29
30
|
export function Content(props) {
|
31
|
+
const location = useLocation();
|
32
|
+
|
30
33
|
const {singleClusterMode} = props;
|
31
34
|
const isClustersPage =
|
32
35
|
location.pathname.includes('/clusters') ||
|
@@ -44,7 +47,7 @@ export function Content(props) {
|
|
44
47
|
<Route path={routes.tabletsFilters} component={TabletsFilters} />
|
45
48
|
<Redirect
|
46
49
|
to={createHref(routes.cluster, {
|
47
|
-
activeTab:
|
50
|
+
activeTab: clusterTabsIds.tenants,
|
48
51
|
})}
|
49
52
|
/>
|
50
53
|
</Switch>
|
@@ -53,7 +56,7 @@ export function Content(props) {
|
|
53
56
|
};
|
54
57
|
return (
|
55
58
|
<React.Fragment>
|
56
|
-
{!isClustersPage && <Header
|
59
|
+
{!isClustersPage && <Header mainPage={props.mainPage} />}
|
57
60
|
<main className={b('main')}>{renderRoute()}</main>
|
58
61
|
<ReduxTooltip />
|
59
62
|
<AppIcons />
|
@@ -65,6 +68,7 @@ Content.propTypes = {
|
|
65
68
|
singleClusterMode: PropTypes.bool,
|
66
69
|
children: PropTypes.node,
|
67
70
|
clusterName: PropTypes.string,
|
71
|
+
mainPage: PropTypes.object,
|
68
72
|
};
|
69
73
|
|
70
74
|
function ContentWrapper(props) {
|
@@ -9,11 +9,7 @@ import {AsideHeader, MenuItem as AsideHeaderMenuItem, FooterItem} from '@gravity
|
|
9
9
|
|
10
10
|
import signOutIcon from '../../assets/icons/signOut.svg';
|
11
11
|
import signInIcon from '../../assets/icons/signIn.svg';
|
12
|
-
import databaseIcon from '../../assets/icons/server.svg';
|
13
|
-
import storageIcon from '../../assets/icons/storage.svg';
|
14
|
-
import clusterIcon from '../../assets/icons/cluster.svg';
|
15
12
|
import ydbLogoIcon from '../../assets/icons/ydb.svg';
|
16
|
-
import databasesIcon from '../../assets/icons/databases.svg';
|
17
13
|
import userSecret from '../../assets/icons/user-secret.svg';
|
18
14
|
import userChecked from '../../assets/icons/user-check.svg';
|
19
15
|
import settingsIcon from '../../assets/icons/settings.svg';
|
@@ -21,7 +17,7 @@ import supportIcon from '../../assets/icons/support.svg';
|
|
21
17
|
|
22
18
|
import {UserSettings} from '../UserSettings/UserSettings';
|
23
19
|
|
24
|
-
import routes, {createHref
|
20
|
+
import routes, {createHref} from '../../routes';
|
25
21
|
|
26
22
|
import {logout} from '../../store/reducers/authentication';
|
27
23
|
import {getParsedSettingValue, setSettingValue} from '../../store/reducers/settings/settings';
|
@@ -115,46 +111,8 @@ interface AsideNavigationProps {
|
|
115
111
|
setSettingValue: (name: string, value: string) => void;
|
116
112
|
}
|
117
113
|
|
118
|
-
|
119
|
-
|
120
|
-
id: CLUSTER_PAGES.tenants.id,
|
121
|
-
title: 'Databases',
|
122
|
-
icon: databasesIcon,
|
123
|
-
iconSize: 20,
|
124
|
-
location: createHref(routes.cluster, {
|
125
|
-
activeTab: CLUSTER_PAGES.tenants.id,
|
126
|
-
}),
|
127
|
-
locationKeys: ['/tenant'],
|
128
|
-
},
|
129
|
-
{
|
130
|
-
id: CLUSTER_PAGES.nodes.id,
|
131
|
-
title: 'Nodes',
|
132
|
-
icon: databaseIcon,
|
133
|
-
iconSize: 20,
|
134
|
-
location: createHref(routes.cluster, {activeTab: CLUSTER_PAGES.nodes.id}),
|
135
|
-
locationKeys: ['/node'],
|
136
|
-
},
|
137
|
-
{
|
138
|
-
id: CLUSTER_PAGES.storage.id,
|
139
|
-
title: 'Storage',
|
140
|
-
icon: storageIcon,
|
141
|
-
iconSize: 20,
|
142
|
-
location: createHref(routes.cluster, {
|
143
|
-
activeTab: CLUSTER_PAGES.storage.id,
|
144
|
-
}),
|
145
|
-
locationKeys: ['/storage'],
|
146
|
-
},
|
147
|
-
{
|
148
|
-
id: CLUSTER_PAGES.cluster.id,
|
149
|
-
title: 'Cluster',
|
150
|
-
icon: clusterIcon,
|
151
|
-
iconSize: 20,
|
152
|
-
location: createHref(routes.cluster, {
|
153
|
-
activeTab: CLUSTER_PAGES.cluster.id,
|
154
|
-
}),
|
155
|
-
locationKeys: ['/cluster/cluster'],
|
156
|
-
},
|
157
|
-
];
|
114
|
+
// FIXME: add items or delete
|
115
|
+
const items: MenuItem[] = [];
|
158
116
|
|
159
117
|
enum Panel {
|
160
118
|
UserSettings = 'UserSettings',
|
@@ -172,17 +130,13 @@ function AsideNavigation(props: AsideNavigationProps) {
|
|
172
130
|
|
173
131
|
const menuItems: AsideHeaderMenuItem[] = React.useMemo(() => {
|
174
132
|
const {pathname} = location;
|
175
|
-
const isClusterPage = pathname === '/cluster';
|
176
133
|
const menuItems: AsideHeaderMenuItem[] = items.map((item) => {
|
177
134
|
const locationKeysCoincidence = item.locationKeys?.filter((key) =>
|
178
135
|
pathname.startsWith(key),
|
179
136
|
);
|
180
|
-
|
137
|
+
const current =
|
181
138
|
(locationKeysCoincidence && locationKeysCoincidence.length > 0) ||
|
182
139
|
item.location.startsWith(pathname);
|
183
|
-
if (isClusterPage && item.id !== CLUSTER_PAGES.tenants.id) {
|
184
|
-
current = false;
|
185
|
-
}
|
186
140
|
return {
|
187
141
|
id: item.id,
|
188
142
|
title: item.title,
|
@@ -2,57 +2,16 @@
|
|
2
2
|
|
3
3
|
.cluster {
|
4
4
|
overflow: auto;
|
5
|
+
flex-grow: 1;
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
&_tab_cluster {
|
10
|
-
padding: 0px;
|
11
|
-
}
|
12
|
-
|
13
|
-
&__tab {
|
14
|
-
text-decoration: none;
|
15
|
-
|
16
|
-
&:first-letter {
|
17
|
-
text-transform: uppercase;
|
18
|
-
}
|
19
|
-
}
|
20
|
-
|
21
|
-
&__format-label {
|
22
|
-
margin-right: 15px;
|
23
|
-
}
|
24
|
-
|
25
|
-
&__title {
|
26
|
-
text-align: center;
|
27
|
-
}
|
7
|
+
height: 100%;
|
8
|
+
padding: 20px 20px 0px;
|
28
9
|
|
29
|
-
|
30
|
-
animation: none !important;
|
31
|
-
}
|
32
|
-
|
33
|
-
&__search {
|
34
|
-
width: 255px;
|
35
|
-
margin: 0 15px 0 0;
|
36
|
-
}
|
37
|
-
|
38
|
-
&__tablets {
|
39
|
-
padding: 0 !important;
|
40
|
-
|
41
|
-
.tablets-viewer__grid {
|
42
|
-
grid-template-columns: 125px;
|
43
|
-
}
|
44
|
-
}
|
45
|
-
|
46
|
-
&__controls {
|
47
|
-
display: flex;
|
48
|
-
justify-content: space-between;
|
10
|
+
@include flex-container();
|
49
11
|
|
50
|
-
|
51
|
-
|
12
|
+
&__content {
|
13
|
+
overflow: auto;
|
52
14
|
|
53
|
-
|
54
|
-
display: flex;
|
55
|
-
flex: 1 1 auto;
|
56
|
-
flex-direction: column;
|
15
|
+
height: 100%;
|
57
16
|
}
|
58
17
|
}
|
@@ -1,51 +1,112 @@
|
|
1
|
-
import {
|
1
|
+
import {useEffect, useMemo} from 'react';
|
2
|
+
import {useLocation, useRouteMatch} from 'react-router';
|
3
|
+
import {useDispatch} from 'react-redux';
|
2
4
|
import cn from 'bem-cn-lite';
|
5
|
+
import qs from 'qs';
|
6
|
+
|
7
|
+
import {Tabs} from '@gravity-ui/uikit';
|
3
8
|
|
4
9
|
import type {AdditionalClusterProps, AdditionalVersionsProps} from '../../types/additionalProps';
|
5
|
-
import
|
10
|
+
import type {AdditionalNodesInfo} from '../../utils/nodes';
|
11
|
+
import routes from '../../routes';
|
6
12
|
|
7
|
-
import {
|
13
|
+
import {setHeaderBreadcrumbs} from '../../store/reducers/header/header';
|
14
|
+
import {getClusterInfo} from '../../store/reducers/cluster/cluster';
|
15
|
+
import {getClusterNodes} from '../../store/reducers/clusterNodes/clusterNodes';
|
16
|
+
import {parseNodesToVersionsValues, parseVersionsToVersionToColorMap} from '../../utils/versions';
|
17
|
+
import {useAutofetcher, useTypedSelector} from '../../utils/hooks';
|
18
|
+
|
19
|
+
import {InternalLink} from '../../components/InternalLink';
|
8
20
|
import Tenants from '../Tenants/Tenants';
|
9
21
|
import {Nodes} from '../Nodes/Nodes';
|
10
22
|
import Storage from '../Storage/Storage';
|
23
|
+
import {Versions} from '../Versions/Versions';
|
24
|
+
|
25
|
+
import {ClusterInfo} from './ClusterInfo/ClusterInfo';
|
26
|
+
import {ClusterTab, clusterTabs, clusterTabsIds, getClusterPath} from './utils';
|
11
27
|
|
12
28
|
import './Cluster.scss';
|
13
29
|
|
14
30
|
const b = cn('cluster');
|
15
31
|
|
16
32
|
interface ClusterProps {
|
17
|
-
additionalTenantsInfo?:
|
18
|
-
additionalNodesInfo?:
|
33
|
+
additionalTenantsInfo?: unknown;
|
34
|
+
additionalNodesInfo?: AdditionalNodesInfo;
|
19
35
|
additionalClusterProps?: AdditionalClusterProps;
|
20
36
|
additionalVersionsProps?: AdditionalVersionsProps;
|
21
37
|
}
|
22
38
|
|
23
39
|
function Cluster({
|
40
|
+
additionalClusterProps,
|
24
41
|
additionalTenantsInfo,
|
25
42
|
additionalNodesInfo,
|
26
|
-
additionalClusterProps,
|
27
43
|
additionalVersionsProps,
|
28
44
|
}: ClusterProps) {
|
29
|
-
const
|
30
|
-
|
31
|
-
const
|
45
|
+
const dispatch = useDispatch();
|
46
|
+
|
47
|
+
const match = useRouteMatch<{activeTab: string}>(routes.cluster);
|
48
|
+
const {activeTab = clusterTabsIds.tenants} = match?.params || {};
|
49
|
+
|
50
|
+
const location = useLocation();
|
51
|
+
const queryParams = qs.parse(location.search, {
|
52
|
+
ignoreQueryPrefix: true,
|
53
|
+
});
|
54
|
+
const {clusterName} = queryParams;
|
55
|
+
|
56
|
+
const {
|
57
|
+
data: cluster = {},
|
58
|
+
loading: clusterLoading,
|
59
|
+
wasLoaded: clusterWasLoaded,
|
60
|
+
error: clusterError,
|
61
|
+
} = useTypedSelector((state) => state.cluster);
|
62
|
+
const {
|
63
|
+
nodes,
|
64
|
+
loading: nodesLoading,
|
65
|
+
wasLoaded: nodesWasLoaded,
|
66
|
+
} = useTypedSelector((state) => state.clusterNodes);
|
67
|
+
|
68
|
+
const {Name} = cluster;
|
69
|
+
|
70
|
+
const infoLoading = (clusterLoading && !clusterWasLoaded) || (nodesLoading && !nodesWasLoaded);
|
71
|
+
|
72
|
+
useEffect(() => {
|
73
|
+
dispatch(getClusterNodes());
|
74
|
+
}, [dispatch]);
|
75
|
+
|
76
|
+
useAutofetcher(
|
77
|
+
() => dispatch(getClusterInfo(clusterName ? String(clusterName) : undefined)),
|
78
|
+
[dispatch, clusterName],
|
79
|
+
true,
|
80
|
+
);
|
81
|
+
|
82
|
+
useEffect(() => {
|
83
|
+
dispatch(setHeaderBreadcrumbs('cluster', {}));
|
84
|
+
}, [dispatch, Name]);
|
85
|
+
|
86
|
+
const versionToColor = useMemo(() => {
|
87
|
+
if (additionalVersionsProps?.getVersionToColorMap) {
|
88
|
+
return additionalVersionsProps?.getVersionToColorMap();
|
89
|
+
}
|
90
|
+
return parseVersionsToVersionToColorMap(cluster?.Versions);
|
91
|
+
}, [additionalVersionsProps, cluster]);
|
92
|
+
|
93
|
+
const versionsValues = useMemo(() => {
|
94
|
+
return parseNodesToVersionsValues(nodes, versionToColor);
|
95
|
+
}, [nodes, versionToColor]);
|
96
|
+
|
97
|
+
const renderTab = () => {
|
32
98
|
switch (activeTab) {
|
33
|
-
case
|
99
|
+
case clusterTabsIds.tenants: {
|
34
100
|
return <Tenants additionalTenantsInfo={additionalTenantsInfo} />;
|
35
101
|
}
|
36
|
-
case
|
102
|
+
case clusterTabsIds.nodes: {
|
37
103
|
return <Nodes additionalNodesInfo={additionalNodesInfo} />;
|
38
104
|
}
|
39
|
-
case
|
105
|
+
case clusterTabsIds.storage: {
|
40
106
|
return <Storage additionalNodesInfo={additionalNodesInfo} />;
|
41
107
|
}
|
42
|
-
case
|
43
|
-
return
|
44
|
-
<ClusterInfo
|
45
|
-
additionalClusterProps={additionalClusterProps}
|
46
|
-
additionalVersionsProps={additionalVersionsProps}
|
47
|
-
/>
|
48
|
-
);
|
108
|
+
case clusterTabsIds.versions: {
|
109
|
+
return <Versions versionToColor={versionToColor} />;
|
49
110
|
}
|
50
111
|
default: {
|
51
112
|
return null;
|
@@ -53,7 +114,55 @@ function Cluster({
|
|
53
114
|
}
|
54
115
|
};
|
55
116
|
|
56
|
-
|
117
|
+
const getTabEntityCount = (tabId: ClusterTab) => {
|
118
|
+
switch (tabId) {
|
119
|
+
case clusterTabsIds.tenants: {
|
120
|
+
return cluster?.Tenants ? Number(cluster.Tenants) : undefined;
|
121
|
+
}
|
122
|
+
case clusterTabsIds.nodes: {
|
123
|
+
return cluster?.NodesTotal ? Number(cluster.NodesTotal) : undefined;
|
124
|
+
}
|
125
|
+
default: {
|
126
|
+
return undefined;
|
127
|
+
}
|
128
|
+
}
|
129
|
+
};
|
130
|
+
|
131
|
+
return (
|
132
|
+
<div className={b()}>
|
133
|
+
<ClusterInfo
|
134
|
+
cluster={cluster}
|
135
|
+
versionsValues={versionsValues}
|
136
|
+
loading={infoLoading}
|
137
|
+
error={clusterError}
|
138
|
+
additionalClusterProps={additionalClusterProps}
|
139
|
+
/>
|
140
|
+
|
141
|
+
<div>
|
142
|
+
<Tabs
|
143
|
+
size="l"
|
144
|
+
allowNotSelected={true}
|
145
|
+
activeTab={activeTab as string}
|
146
|
+
items={clusterTabs.map((item) => {
|
147
|
+
return {
|
148
|
+
...item,
|
149
|
+
counter: getTabEntityCount(item.id),
|
150
|
+
};
|
151
|
+
})}
|
152
|
+
wrapTo={({id}, node) => {
|
153
|
+
const path = getClusterPath(id as ClusterTab, queryParams);
|
154
|
+
return (
|
155
|
+
<InternalLink to={path} key={id}>
|
156
|
+
{node}
|
157
|
+
</InternalLink>
|
158
|
+
);
|
159
|
+
}}
|
160
|
+
/>
|
161
|
+
</div>
|
162
|
+
|
163
|
+
<div className={b('content')}>{renderTab()}</div>
|
164
|
+
</div>
|
165
|
+
);
|
57
166
|
}
|
58
167
|
|
59
168
|
export default Cluster;
|
@@ -1,31 +1,48 @@
|
|
1
1
|
@import '../../../styles/mixins';
|
2
2
|
|
3
3
|
.cluster-info {
|
4
|
-
|
5
|
-
$progress_width: 100%;
|
4
|
+
width: 100%;
|
6
5
|
|
7
|
-
|
8
|
-
|
9
|
-
flex-direction: column;
|
6
|
+
&__header {
|
7
|
+
display: flex;
|
10
8
|
|
11
|
-
|
9
|
+
width: fit-content;
|
10
|
+
margin-bottom: 20px;
|
12
11
|
|
13
|
-
|
14
|
-
line-height: var(--yc-text-body-2-line-height);
|
12
|
+
cursor: pointer;
|
15
13
|
|
16
|
-
|
17
|
-
|
14
|
+
&__expand-button {
|
15
|
+
margin-left: 6px;
|
18
16
|
|
19
|
-
|
20
|
-
|
17
|
+
&_rotate {
|
18
|
+
transform: rotate(180deg);
|
19
|
+
}
|
20
|
+
}
|
21
21
|
}
|
22
22
|
|
23
|
-
&__title {
|
24
|
-
|
25
|
-
|
23
|
+
&__title .entity-status__name {
|
24
|
+
font-size: var(--yc-text-header-1-font-size);
|
25
|
+
font-weight: var(--yc-text-header-font-weight);
|
26
|
+
line-height: var(--yc-text-header-1-line-height);
|
27
|
+
}
|
28
|
+
|
29
|
+
&__title-skeleton {
|
30
|
+
width: 20%;
|
31
|
+
min-width: 200px;
|
32
|
+
height: var(--yc-text-header-1-line-height);
|
33
|
+
}
|
26
34
|
|
27
|
-
|
35
|
+
&__error {
|
36
|
+
font-size: var(--yc-text-body-2-font-size);
|
37
|
+
line-height: var(--yc-text-body-2-line-height);
|
38
|
+
}
|
39
|
+
|
40
|
+
&__info {
|
28
41
|
margin-bottom: 20px;
|
42
|
+
|
43
|
+
&_hidden {
|
44
|
+
display: none;
|
45
|
+
}
|
29
46
|
}
|
30
47
|
|
31
48
|
&__metric-field {
|
@@ -38,7 +55,7 @@
|
|
38
55
|
align-items: center;
|
39
56
|
|
40
57
|
& .tablet {
|
41
|
-
margin-
|
58
|
+
margin-top: 2px;
|
42
59
|
}
|
43
60
|
}
|
44
61
|
|