ydb-embedded-ui 20.3.0 → 20.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/Drawer/Drawer.d.ts +2 -1
- package/dist/components/Drawer/Drawer.js +4 -4
- package/dist/components/Drawer/Drawer.js.map +1 -1
- package/dist/components/EntityStatus/EntityStatus.d.ts +4 -1
- package/dist/components/EntityStatus/EntityStatus.js +2 -2
- package/dist/components/EntityStatus/EntityStatus.js.map +1 -1
- package/dist/components/PDiskInfo/i18n/index.d.ts +1 -1
- package/dist/components/TenantNameWrapper/utils.d.ts +1 -1
- package/dist/components/TenantNameWrapper/utils.js.map +1 -1
- package/dist/containers/Cluster/Cluster.js +1 -1
- package/dist/containers/Cluster/Cluster.js.map +1 -1
- package/dist/containers/Cluster/ClusterDrawerHealthcheck.d.ts +8 -0
- package/dist/containers/Cluster/ClusterDrawerHealthcheck.js +71 -9
- package/dist/containers/Cluster/ClusterDrawerHealthcheck.js.map +1 -1
- package/dist/containers/Cluster/ClusterInfo/ClusterInfo.d.ts +2 -1
- package/dist/containers/Cluster/ClusterInfo/ClusterInfo.js +2 -2
- package/dist/containers/Cluster/ClusterInfo/ClusterInfo.js.map +1 -1
- package/dist/containers/Cluster/ClusterOverview/ClusterOverview.d.ts +1 -0
- package/dist/containers/Cluster/ClusterOverview/ClusterOverview.js.map +1 -1
- package/dist/containers/Cluster/ClusterOverview/components/BridgeInfoTable.d.ts +2 -0
- package/dist/containers/Cluster/ClusterOverview/components/BridgeInfoTable.js +54 -103
- package/dist/containers/Cluster/ClusterOverview/components/BridgeInfoTable.js.map +1 -1
- package/dist/containers/Cluster/ClusterOverview/components/BridgeInfoTable.scss +24 -89
- package/dist/containers/Cluster/ClusterOverview/components/bridgePileHealthcheck.d.ts +13 -0
- package/dist/containers/Cluster/ClusterOverview/components/bridgePileHealthcheck.js +94 -0
- package/dist/containers/Cluster/ClusterOverview/components/bridgePileHealthcheck.js.map +1 -0
- package/dist/containers/Cluster/i18n/en.json +8 -5
- package/dist/containers/Cluster/i18n/index.d.ts +1 -1
- package/dist/containers/Clusters/constants.d.ts +1 -1
- package/dist/containers/Header/DatabaseRightControls.d.ts +4 -2
- package/dist/containers/Header/DatabaseRightControls.js +2 -2
- package/dist/containers/Header/DatabaseRightControls.js.map +1 -1
- package/dist/containers/Header/Header.js +2 -2
- package/dist/containers/Header/Header.js.map +1 -1
- package/dist/containers/Header/HeaderActionsMenu.d.ts +4 -2
- package/dist/containers/Header/HeaderActionsMenu.js +19 -2
- package/dist/containers/Header/HeaderActionsMenu.js.map +1 -1
- package/dist/containers/Header/HeaderRightControls.d.ts +4 -2
- package/dist/containers/Header/HeaderRightControls.js +2 -2
- package/dist/containers/Header/HeaderRightControls.js.map +1 -1
- package/dist/containers/Header/hooks/useClusterData.d.ts +1 -0
- package/dist/containers/Header/hooks/useHeaderData.d.ts +1 -0
- package/dist/containers/Header/hooks/useHeaderData.js +1 -0
- package/dist/containers/Header/hooks/useHeaderData.js.map +1 -1
- package/dist/containers/Header/hooks/useSharedDatabasePath.d.ts +10 -0
- package/dist/containers/Header/hooks/useSharedDatabasePath.js +102 -0
- package/dist/containers/Header/hooks/useSharedDatabasePath.js.map +1 -0
- package/dist/containers/Header/i18n/en.json +1 -0
- package/dist/containers/Header/i18n/index.d.ts +1 -1
- package/dist/containers/Operations/constants.d.ts +1 -1
- package/dist/containers/Storage/PaginatedStorageGroupsTable/columns/i18n/index.d.ts +1 -1
- package/dist/containers/Tablets/Tablets.js +3 -3
- package/dist/containers/Tablets/Tablets.js.map +1 -1
- package/dist/containers/Tablets/TabletsTable.js +17 -27
- package/dist/containers/Tablets/TabletsTable.js.map +1 -1
- package/dist/containers/Tablets/i18n/en.json +3 -0
- package/dist/containers/Tablets/i18n/index.d.ts +1 -1
- package/dist/containers/Tablets/useTabletQueryParams.d.ts +8 -0
- package/dist/containers/Tablets/useTabletQueryParams.js +40 -0
- package/dist/containers/Tablets/useTabletQueryParams.js.map +1 -0
- package/dist/containers/Tablets/utils.d.ts +11 -0
- package/dist/containers/Tablets/utils.js +23 -0
- package/dist/containers/Tablets/utils.js.map +1 -0
- package/dist/containers/Tenant/Healthcheck/Healthcheck.d.ts +6 -1
- package/dist/containers/Tenant/Healthcheck/Healthcheck.js +5 -5
- package/dist/containers/Tenant/Healthcheck/Healthcheck.js.map +1 -1
- package/dist/containers/Tenant/Healthcheck/components/HealthcheckDrawer.d.ts +2 -1
- package/dist/containers/Tenant/Healthcheck/components/HealthcheckDrawer.js +2 -2
- package/dist/containers/Tenant/Healthcheck/components/HealthcheckDrawer.js.map +1 -1
- package/dist/containers/Tenant/Healthcheck/components/HealthcheckIssue.d.ts +5 -1
- package/dist/containers/Tenant/Healthcheck/components/HealthcheckIssue.js +5 -3
- package/dist/containers/Tenant/Healthcheck/components/HealthcheckIssue.js.map +1 -1
- package/dist/containers/Tenant/Healthcheck/components/HealthcheckIssueDetails/ComputeLocation.d.ts +1 -1
- package/dist/containers/Tenant/Healthcheck/components/HealthcheckIssueDetails/ComputeLocation.js +11 -2
- package/dist/containers/Tenant/Healthcheck/components/HealthcheckIssueDetails/ComputeLocation.js.map +1 -1
- package/dist/containers/Tenant/Healthcheck/components/HealthcheckIssueDetails/NodeInfo.js +2 -0
- package/dist/containers/Tenant/Healthcheck/components/HealthcheckIssueDetails/NodeInfo.js.map +1 -1
- package/dist/containers/Tenant/Healthcheck/components/HealthcheckIssueDetails/StorageLocation.js +4 -1
- package/dist/containers/Tenant/Healthcheck/components/HealthcheckIssueDetails/StorageLocation.js.map +1 -1
- package/dist/containers/Tenant/Healthcheck/components/HealthcheckIssues.d.ts +5 -1
- package/dist/containers/Tenant/Healthcheck/components/HealthcheckIssues.js +2 -2
- package/dist/containers/Tenant/Healthcheck/components/HealthcheckIssues.js.map +1 -1
- package/dist/containers/Tenant/Healthcheck/i18n/en.json +2 -1
- package/dist/containers/Tenant/Healthcheck/i18n/index.d.ts +1 -1
- package/dist/containers/Tenant/Query/SavedQueries/SavedQueries.scss +2 -0
- package/dist/containers/VDiskPage/i18n/index.d.ts +1 -1
- package/dist/routes.d.ts +4 -1
- package/dist/routes.js +3 -2
- package/dist/routes.js.map +1 -1
- package/dist/services/api/viewer.d.ts +3 -1
- package/dist/services/api/viewer.js +3 -2
- package/dist/services/api/viewer.js.map +1 -1
- package/dist/store/reducers/cluster/cluster.d.ts +2 -1
- package/dist/store/reducers/cluster/cluster.js +1 -0
- package/dist/store/reducers/cluster/cluster.js.map +1 -1
- package/dist/store/reducers/healthcheckInfo/types.d.ts +1 -0
- package/dist/store/reducers/healthcheckInfo/utils.d.ts +1 -0
- package/dist/store/reducers/healthcheckInfo/utils.js +43 -9
- package/dist/store/reducers/healthcheckInfo/utils.js.map +1 -1
- package/dist/store/reducers/tenants/tenants.d.ts +10 -1
- package/dist/store/reducers/tenants/tenants.js +33 -0
- package/dist/store/reducers/tenants/tenants.js.map +1 -1
- package/dist/store/reducers/tenants/types.d.ts +4 -0
- package/dist/types/api/healthcheck.d.ts +7 -0
- package/package.json +1 -1
- package/src/components/Drawer/Drawer.tsx +6 -0
- package/src/components/EntityStatus/EntityStatus.tsx +9 -1
- package/src/components/TenantNameWrapper/utils.ts +1 -1
- package/src/containers/Cluster/Cluster.tsx +1 -0
- package/src/containers/Cluster/ClusterDrawerHealthcheck.tsx +112 -13
- package/src/containers/Cluster/ClusterInfo/ClusterInfo.tsx +7 -1
- package/src/containers/Cluster/ClusterOverview/ClusterOverview.tsx +1 -0
- package/src/containers/Cluster/ClusterOverview/components/BridgeInfoTable.scss +24 -89
- package/src/containers/Cluster/ClusterOverview/components/BridgeInfoTable.tsx +156 -200
- package/src/containers/Cluster/ClusterOverview/components/bridgePileHealthcheck.ts +142 -0
- package/src/containers/Cluster/i18n/en.json +8 -5
- package/src/containers/Header/DatabaseRightControls.tsx +7 -1
- package/src/containers/Header/Header.tsx +3 -0
- package/src/containers/Header/HeaderActionsMenu.tsx +24 -2
- package/src/containers/Header/HeaderRightControls.tsx +7 -1
- package/src/containers/Header/hooks/useHeaderData.ts +1 -0
- package/src/containers/Header/hooks/useSharedDatabasePath.ts +195 -0
- package/src/containers/Header/i18n/en.json +1 -0
- package/src/containers/Tablets/Tablets.tsx +3 -3
- package/src/containers/Tablets/TabletsTable.tsx +37 -31
- package/src/containers/Tablets/i18n/en.json +3 -0
- package/src/containers/Tablets/useTabletQueryParams.ts +54 -0
- package/src/containers/Tablets/utils.ts +43 -0
- package/src/containers/Tenant/Healthcheck/Healthcheck.tsx +37 -4
- package/src/containers/Tenant/Healthcheck/components/HealthcheckDrawer.tsx +3 -0
- package/src/containers/Tenant/Healthcheck/components/HealthcheckIssue.tsx +17 -4
- package/src/containers/Tenant/Healthcheck/components/HealthcheckIssueDetails/ComputeLocation.tsx +13 -3
- package/src/containers/Tenant/Healthcheck/components/HealthcheckIssueDetails/NodeInfo.tsx +1 -0
- package/src/containers/Tenant/Healthcheck/components/HealthcheckIssueDetails/StorageLocation.tsx +3 -1
- package/src/containers/Tenant/Healthcheck/components/HealthcheckIssues.tsx +15 -2
- package/src/containers/Tenant/Healthcheck/i18n/en.json +2 -1
- package/src/containers/Tenant/Query/SavedQueries/SavedQueries.scss +2 -0
- package/src/routes.ts +8 -2
- package/src/services/api/viewer.ts +10 -2
- package/src/store/reducers/cluster/cluster.ts +2 -1
- package/src/store/reducers/healthcheckInfo/types.ts +1 -0
- package/src/store/reducers/healthcheckInfo/utils.ts +50 -10
- package/src/store/reducers/tenants/tenants.ts +55 -1
- package/src/store/reducers/tenants/types.ts +5 -0
- package/src/types/api/healthcheck.ts +8 -0
|
@@ -15,6 +15,7 @@ interface HealthcheckDrawerProps {
|
|
|
15
15
|
children: React.ReactNode;
|
|
16
16
|
isDrawerVisible: boolean;
|
|
17
17
|
onCloseDrawer: () => void;
|
|
18
|
+
onTransitionInComplete?: () => void;
|
|
18
19
|
renderDrawerContent: () => React.ReactNode;
|
|
19
20
|
drawerId: string;
|
|
20
21
|
storageKey: string;
|
|
@@ -30,6 +31,7 @@ export function HealthcheckDrawer({
|
|
|
30
31
|
children,
|
|
31
32
|
isDrawerVisible,
|
|
32
33
|
onCloseDrawer,
|
|
34
|
+
onTransitionInComplete,
|
|
33
35
|
renderDrawerContent,
|
|
34
36
|
drawerId,
|
|
35
37
|
storageKey,
|
|
@@ -83,6 +85,7 @@ export function HealthcheckDrawer({
|
|
|
83
85
|
<DrawerWrapper
|
|
84
86
|
isDrawerVisible={isDrawerVisible}
|
|
85
87
|
onCloseDrawer={onCloseDrawer}
|
|
88
|
+
onTransitionInComplete={onTransitionInComplete}
|
|
86
89
|
renderDrawerContent={renderDrawerContent}
|
|
87
90
|
drawerId={drawerId}
|
|
88
91
|
storageKey={storageKey}
|
|
@@ -15,11 +15,19 @@ import {HealthcheckIssueTabs} from './HealthcheckIssueTabs';
|
|
|
15
15
|
interface HealthcheckIssueProps {
|
|
16
16
|
issue: IssuesTree;
|
|
17
17
|
expanded?: boolean;
|
|
18
|
+
targeted?: boolean;
|
|
19
|
+
targetIssueId?: string;
|
|
20
|
+
targetRef?: React.Ref<HTMLDivElement>;
|
|
18
21
|
}
|
|
19
22
|
|
|
20
|
-
export function HealthcheckIssue({
|
|
23
|
+
export function HealthcheckIssue({
|
|
24
|
+
issue,
|
|
25
|
+
expanded,
|
|
26
|
+
targeted,
|
|
27
|
+
targetIssueId,
|
|
28
|
+
targetRef,
|
|
29
|
+
}: HealthcheckIssueProps) {
|
|
21
30
|
const {assistant} = useHealthcheckContext();
|
|
22
|
-
const [selectedTab, setSelectedTab] = React.useState(issue.id);
|
|
23
31
|
const parents = React.useMemo(() => {
|
|
24
32
|
const parents = [];
|
|
25
33
|
let current: IssuesTree | undefined = issue;
|
|
@@ -29,6 +37,11 @@ export function HealthcheckIssue({issue, expanded}: HealthcheckIssueProps) {
|
|
|
29
37
|
}
|
|
30
38
|
return parents.reverse();
|
|
31
39
|
}, [issue]);
|
|
40
|
+
const [selectedTab, setSelectedTab] = React.useState(
|
|
41
|
+
targetIssueId && parents.some((parentIssue) => parentIssue.id === targetIssueId)
|
|
42
|
+
? targetIssueId
|
|
43
|
+
: issue.id,
|
|
44
|
+
);
|
|
32
45
|
|
|
33
46
|
const currentIssue = React.useMemo(() => {
|
|
34
47
|
return parents.find((parent) => parent.id === selectedTab);
|
|
@@ -39,8 +52,8 @@ export function HealthcheckIssue({issue, expanded}: HealthcheckIssueProps) {
|
|
|
39
52
|
);
|
|
40
53
|
|
|
41
54
|
return (
|
|
42
|
-
<Flex className={b('issue-wrapper')}>
|
|
43
|
-
<Disclosure className={b('issue-content')} defaultExpanded={expanded}>
|
|
55
|
+
<Flex ref={targetRef} className={b('issue-wrapper')} qa={`healthcheck-issue-${issue.id}`}>
|
|
56
|
+
<Disclosure className={b('issue-content')} defaultExpanded={expanded || targeted}>
|
|
44
57
|
<Disclosure.Summary>
|
|
45
58
|
{(props) => {
|
|
46
59
|
const {
|
package/src/containers/Tenant/Healthcheck/components/HealthcheckIssueDetails/ComputeLocation.tsx
CHANGED
|
@@ -13,7 +13,7 @@ import {NodeInfo} from './NodeInfo';
|
|
|
13
13
|
import {PoolInfo} from './PoolInfo';
|
|
14
14
|
import {IdList, LocationDetails, SectionWithTitle} from './utils';
|
|
15
15
|
|
|
16
|
-
export type LocationFieldCompute = 'tablet' | 'schema' | 'node' | 'pool' | 'state_storage';
|
|
16
|
+
export type LocationFieldCompute = 'tablet' | 'schema' | 'node' | 'pool' | 'pile' | 'state_storage';
|
|
17
17
|
|
|
18
18
|
type ComputeLocationType = Location['compute'];
|
|
19
19
|
|
|
@@ -25,6 +25,12 @@ const LocationFieldRenderer: Record<
|
|
|
25
25
|
pool: (location: ComputeLocationType) => <PoolInfo location={location} key="pool" />,
|
|
26
26
|
tablet: (location: ComputeLocationType) => <TabletInfo location={location} key="tablet" />,
|
|
27
27
|
schema: (location: ComputeLocationType) => <SchemaInfo location={location} key="schema" />,
|
|
28
|
+
pile: (location: ComputeLocationType) => (
|
|
29
|
+
<LocationDetails
|
|
30
|
+
fields={[{value: location?.pile?.name, title: i18n('label_pile')}]}
|
|
31
|
+
key="pile"
|
|
32
|
+
/>
|
|
33
|
+
),
|
|
28
34
|
state_storage: (location: ComputeLocationType) => (
|
|
29
35
|
<StateStorageInfo location={location} key="state_storage" />
|
|
30
36
|
),
|
|
@@ -36,7 +42,7 @@ interface ComputeLocationProps {
|
|
|
36
42
|
}
|
|
37
43
|
|
|
38
44
|
export function ComputeLocation({location, hiddenFields = []}: ComputeLocationProps) {
|
|
39
|
-
const {node, tablet, schema, pool, state_storage: stateStorage} = location ?? {};
|
|
45
|
+
const {node, tablet, schema, pool, pile, state_storage: stateStorage} = location ?? {};
|
|
40
46
|
|
|
41
47
|
const fields = React.useMemo(() => {
|
|
42
48
|
const fields: LocationFieldCompute[] = [];
|
|
@@ -52,11 +58,14 @@ export function ComputeLocation({location, hiddenFields = []}: ComputeLocationPr
|
|
|
52
58
|
if (schema) {
|
|
53
59
|
fields.push('schema');
|
|
54
60
|
}
|
|
61
|
+
if (pile) {
|
|
62
|
+
fields.push('pile');
|
|
63
|
+
}
|
|
55
64
|
if (stateStorage) {
|
|
56
65
|
fields.push('state_storage');
|
|
57
66
|
}
|
|
58
67
|
return fields.filter((field) => !hiddenFields.includes(field));
|
|
59
|
-
}, [node, pool, tablet, schema, stateStorage, hiddenFields]);
|
|
68
|
+
}, [node, pool, tablet, schema, pile, stateStorage, hiddenFields]);
|
|
60
69
|
|
|
61
70
|
if (!location || isEmpty(location) || fields.length === 0) {
|
|
62
71
|
return null;
|
|
@@ -142,6 +151,7 @@ function StateStorageInfo({location}: ComputeSectionProps) {
|
|
|
142
151
|
: undefined,
|
|
143
152
|
title: i18n('label_state-storage-ring'),
|
|
144
153
|
},
|
|
154
|
+
{value: stateStorage.pile?.name, title: i18n('label_pile')},
|
|
145
155
|
]}
|
|
146
156
|
/>
|
|
147
157
|
<NodeInfo node={stateStorage.node} />
|
|
@@ -33,6 +33,7 @@ export function NodeInfo({node, title}: NodeInfoProps) {
|
|
|
33
33
|
{value: nodeLink, title: i18n('label_node-id')},
|
|
34
34
|
{value: node.host, title: i18n('label_node-host'), copy: node.host},
|
|
35
35
|
{value: node.port, title: i18n('label_node-port')},
|
|
36
|
+
{value: node.pile?.name, title: i18n('label_pile')},
|
|
36
37
|
]}
|
|
37
38
|
/>
|
|
38
39
|
);
|
package/src/containers/Tenant/Healthcheck/components/HealthcheckIssueDetails/StorageLocation.tsx
CHANGED
|
@@ -81,8 +81,9 @@ function GroupInfo({location}: StorageSectionProps) {
|
|
|
81
81
|
const {group} = pool ?? {};
|
|
82
82
|
|
|
83
83
|
const ids = group?.id;
|
|
84
|
+
const pileName = group?.pile?.name;
|
|
84
85
|
|
|
85
|
-
if (!ids?.length) {
|
|
86
|
+
if (!ids?.length && !pileName) {
|
|
86
87
|
return null;
|
|
87
88
|
}
|
|
88
89
|
|
|
@@ -93,6 +94,7 @@ function GroupInfo({location}: StorageSectionProps) {
|
|
|
93
94
|
value: ids?.length ? <IdList ids={ids} /> : undefined,
|
|
94
95
|
title: i18n('label_group-id'),
|
|
95
96
|
},
|
|
97
|
+
{value: pileName, title: i18n('label_pile')},
|
|
96
98
|
]}
|
|
97
99
|
/>
|
|
98
100
|
);
|
|
@@ -14,9 +14,17 @@ import {HealthcheckIssue} from './HealthcheckIssue';
|
|
|
14
14
|
|
|
15
15
|
interface IssuesProps {
|
|
16
16
|
issues: IssuesTree[];
|
|
17
|
+
targetIssueId?: string;
|
|
18
|
+
targetLeafIssueId?: string;
|
|
19
|
+
targetLeafIssueRef?: React.Ref<HTMLDivElement>;
|
|
17
20
|
}
|
|
18
21
|
|
|
19
|
-
export function Issues({
|
|
22
|
+
export function Issues({
|
|
23
|
+
issues,
|
|
24
|
+
targetIssueId,
|
|
25
|
+
targetLeafIssueId,
|
|
26
|
+
targetLeafIssueRef,
|
|
27
|
+
}: IssuesProps) {
|
|
20
28
|
const SuccessImage = getIllustration('SuccessOperation');
|
|
21
29
|
|
|
22
30
|
const {view, issuesFilter} = useTenantQueryParams();
|
|
@@ -72,8 +80,13 @@ export function Issues({issues}: IssuesProps) {
|
|
|
72
80
|
return filteredIssuesCurrentView.map((issue) => (
|
|
73
81
|
<HealthcheckIssue
|
|
74
82
|
issue={issue}
|
|
75
|
-
key={issue.id
|
|
83
|
+
key={`${issue.id}:${Boolean(issuesFilter)}:${
|
|
84
|
+
issue.id === targetLeafIssueId ? targetIssueId : ''
|
|
85
|
+
}`}
|
|
76
86
|
expanded={Boolean(issuesFilter)}
|
|
87
|
+
targeted={issue.id === targetLeafIssueId}
|
|
88
|
+
targetIssueId={issue.id === targetLeafIssueId ? targetIssueId : undefined}
|
|
89
|
+
targetRef={issue.id === targetLeafIssueId ? targetLeafIssueRef : undefined}
|
|
77
90
|
/>
|
|
78
91
|
));
|
|
79
92
|
}
|
package/src/routes.ts
CHANGED
|
@@ -185,8 +185,14 @@ export const getClusterPath = (
|
|
|
185
185
|
return createHref(routes.cluster, params, query, options, domain);
|
|
186
186
|
};
|
|
187
187
|
|
|
188
|
-
export
|
|
189
|
-
|
|
188
|
+
export interface TenantPathOptions extends CreateHrefOptions {
|
|
189
|
+
environment?: string;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
export const getTenantPath = (query: TenantQuery, options: TenantPathOptions = {}) => {
|
|
193
|
+
const {environment: routeEnvironment, ...createHrefOptions} = options;
|
|
194
|
+
|
|
195
|
+
return createHref(routes.tenant, {environment: routeEnvironment}, query, createHrefOptions);
|
|
190
196
|
};
|
|
191
197
|
|
|
192
198
|
export const homePageTabSchema = z.enum(['clusters', 'databases']);
|
|
@@ -83,12 +83,20 @@ export class ViewerAPI extends BaseYdbAPI {
|
|
|
83
83
|
);
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
-
getTenants(
|
|
86
|
+
getTenants(
|
|
87
|
+
{
|
|
88
|
+
clusterName,
|
|
89
|
+
metadataCache,
|
|
90
|
+
storage = true,
|
|
91
|
+
}: {clusterName?: string; metadataCache?: boolean; storage?: boolean},
|
|
92
|
+
{concurrentId, signal}: AxiosOptions = {},
|
|
93
|
+
) {
|
|
87
94
|
return this.get<TTenantInfo>(
|
|
88
95
|
this.getPath('/viewer/json/tenantinfo'),
|
|
89
96
|
{
|
|
90
97
|
tablets: false,
|
|
91
|
-
storage
|
|
98
|
+
storage,
|
|
99
|
+
metadata_cache: metadataCache,
|
|
92
100
|
cluster_name: clusterName,
|
|
93
101
|
},
|
|
94
102
|
{concurrentId, requestConfig: {signal}},
|
|
@@ -177,6 +177,7 @@ export function useClusterBaseInfo() {
|
|
|
177
177
|
settings: parseSettingsField(data.settings),
|
|
178
178
|
links: parseLinksField(data.links),
|
|
179
179
|
|
|
180
|
+
isError,
|
|
180
181
|
isResolved,
|
|
181
182
|
};
|
|
182
183
|
}
|
|
@@ -201,7 +202,7 @@ export function useClusterProxySettingResolved() {
|
|
|
201
202
|
|
|
202
203
|
type ClusterBaseInfo = ReturnType<typeof useClusterBaseInfo>;
|
|
203
204
|
|
|
204
|
-
export type ClusterInfo = Omit<ClusterBaseInfo, 'isResolved'>;
|
|
205
|
+
export type ClusterInfo = Omit<ClusterBaseInfo, 'isError' | 'isResolved'>;
|
|
205
206
|
|
|
206
207
|
const createClusterInfoSelector = createSelector(
|
|
207
208
|
(clusterName?: string) => clusterName,
|
|
@@ -23,6 +23,23 @@ export const selfCheckResultToHcStatus: Record<SelfCheckResult, StatusFlag> = {
|
|
|
23
23
|
[SelfCheckResult.EMERGENCY]: StatusFlag.RED,
|
|
24
24
|
};
|
|
25
25
|
|
|
26
|
+
export function getHealthcheckIssuePileNames(issue: Pick<IssueLog, 'location'>): string[] {
|
|
27
|
+
const rawNames = [
|
|
28
|
+
issue.location?.storage?.pool?.group?.pile?.name,
|
|
29
|
+
issue.location?.compute?.pile?.name,
|
|
30
|
+
issue.location?.compute?.state_storage?.pile?.name,
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
const names = new Set<string>();
|
|
34
|
+
for (const rawName of rawNames) {
|
|
35
|
+
if (rawName?.trim()) {
|
|
36
|
+
names.add(rawName);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return Array.from(names);
|
|
41
|
+
}
|
|
42
|
+
|
|
26
43
|
// Issue type prefixes that should be routed to the "storage" tab in the UI,
|
|
27
44
|
// covering regular disk issues alongside ring/board/state-storage issues.
|
|
28
45
|
// 'BOARD_' (with underscore) is intentionally narrow to match only BOARD_RING /
|
|
@@ -35,6 +52,7 @@ const STORAGE_TAB_PREFIXES = [
|
|
|
35
52
|
'BOARD_',
|
|
36
53
|
'STATE_STORAGE',
|
|
37
54
|
];
|
|
55
|
+
const STORAGE_TAB_EXACT_TYPES = new Set(['BOARD']);
|
|
38
56
|
|
|
39
57
|
// Maps a state-storage summary issue type to the corresponding `_RING` type.
|
|
40
58
|
// Backend reports the summary (BLUE) and the detailed RING/NODE chain as
|
|
@@ -50,7 +68,10 @@ export function isStorageRelatedType(type?: string): boolean {
|
|
|
50
68
|
if (!type) {
|
|
51
69
|
return false;
|
|
52
70
|
}
|
|
53
|
-
return
|
|
71
|
+
return (
|
|
72
|
+
STORAGE_TAB_EXACT_TYPES.has(type) ||
|
|
73
|
+
STORAGE_TAB_PREFIXES.some((prefix) => type.startsWith(prefix))
|
|
74
|
+
);
|
|
54
75
|
}
|
|
55
76
|
|
|
56
77
|
export function isComputeRelatedType(type?: string): boolean {
|
|
@@ -112,9 +133,18 @@ export function linkStateStorageSummaries(issues: IssueLog[]): IssueLog[] {
|
|
|
112
133
|
|
|
113
134
|
function getCategoryForUI(issueType?: string) {
|
|
114
135
|
if (issueType) {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
136
|
+
// Compatibility fallback until HealthCheck links every PILE_* summary to its
|
|
137
|
+
// *_RING children through reason. Once those links are guaranteed, the branch
|
|
138
|
+
// category will come from the direct child after the root and this can be removed.
|
|
139
|
+
const issueTypeVariants = issueType.startsWith('PILE_')
|
|
140
|
+
? [issueType, issueType.slice('PILE_'.length)]
|
|
141
|
+
: [issueType];
|
|
142
|
+
|
|
143
|
+
for (const type of issueTypeVariants) {
|
|
144
|
+
for (const category of uiFactory.healthcheck.issueCategories) {
|
|
145
|
+
if (uiFactory.healthcheck.isIssueTypeOfCategory(type, category)) {
|
|
146
|
+
return category;
|
|
147
|
+
}
|
|
118
148
|
}
|
|
119
149
|
}
|
|
120
150
|
}
|
|
@@ -125,7 +155,7 @@ function getCategoryForUI(issueType?: string) {
|
|
|
125
155
|
function extendIssue(
|
|
126
156
|
issue: IssueLog,
|
|
127
157
|
rootTypeForUI?: string,
|
|
128
|
-
fields?: {parent
|
|
158
|
+
fields?: {parent?: IssuesTree; sourceOrderPath?: number[]},
|
|
129
159
|
): IssuesTree {
|
|
130
160
|
return {
|
|
131
161
|
...issue,
|
|
@@ -136,12 +166,14 @@ function extendIssue(
|
|
|
136
166
|
|
|
137
167
|
export function getLeavesFromTree(issues: IssueLog[], root: IssueLog): IssuesTree[] {
|
|
138
168
|
const result: IssuesTree[] = [];
|
|
169
|
+
const rootSourceIndex = issues.findIndex((issue) => issue.id === root.id);
|
|
170
|
+
const rootSourceOrderPath = [rootSourceIndex];
|
|
139
171
|
|
|
140
172
|
if (!root.reason || root.reason.length === 0) {
|
|
141
|
-
return [extendIssue(root)];
|
|
173
|
+
return [extendIssue(root, undefined, {sourceOrderPath: rootSourceOrderPath})];
|
|
142
174
|
}
|
|
143
175
|
|
|
144
|
-
for (const issueId of root.reason) {
|
|
176
|
+
for (const [reasonIndex, issueId] of root.reason.entries()) {
|
|
145
177
|
const directChild: IssueLog | undefined = issues.find((issue) => issue.id === issueId);
|
|
146
178
|
if (!directChild) {
|
|
147
179
|
continue;
|
|
@@ -157,9 +189,12 @@ export function getLeavesFromTree(issues: IssueLog[], root: IssueLog): IssuesTre
|
|
|
157
189
|
// standalone card (when it has no `reason` and is not referenced
|
|
158
190
|
// by any other issue) or as a tab in some leaf's breadcrumb. The
|
|
159
191
|
// leaf (issue without `reason`) is the rightmost tab.
|
|
160
|
-
const rootNode = extendIssue(root, directChildCategory
|
|
192
|
+
const rootNode = extendIssue(root, directChildCategory, {
|
|
193
|
+
sourceOrderPath: rootSourceOrderPath,
|
|
194
|
+
});
|
|
161
195
|
const initialNode: IssuesTree = extendIssue(directChild, directChildCategory, {
|
|
162
196
|
parent: rootNode,
|
|
197
|
+
sourceOrderPath: [...rootSourceOrderPath, reasonIndex],
|
|
163
198
|
});
|
|
164
199
|
const stack: IssuesTree[] = [initialNode];
|
|
165
200
|
|
|
@@ -174,12 +209,17 @@ export function getLeavesFromTree(issues: IssueLog[], root: IssueLog): IssuesTre
|
|
|
174
209
|
continue;
|
|
175
210
|
}
|
|
176
211
|
|
|
177
|
-
for (const reason of currentNode.reason) {
|
|
212
|
+
for (const [childReasonIndex, reason] of currentNode.reason.entries()) {
|
|
178
213
|
const child: IssueLog | undefined = issues.find((issue) => issue.id === reason);
|
|
179
214
|
if (!child) {
|
|
180
215
|
continue;
|
|
181
216
|
}
|
|
182
|
-
stack.push(
|
|
217
|
+
stack.push(
|
|
218
|
+
extendIssue(child, directChildCategory, {
|
|
219
|
+
parent: currentNode,
|
|
220
|
+
sourceOrderPath: [...(currentNode.sourceOrderPath ?? []), childReasonIndex],
|
|
221
|
+
}),
|
|
222
|
+
);
|
|
183
223
|
}
|
|
184
224
|
}
|
|
185
225
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type {TTenantInfo} from '../../../types/api/tenant';
|
|
2
2
|
import {api} from '../api';
|
|
3
3
|
|
|
4
|
-
import type {PreparedTenant} from './types';
|
|
4
|
+
import type {PreparedTenant, SharedDatabaseTarget} from './types';
|
|
5
5
|
import {prepareTenants} from './utils';
|
|
6
6
|
|
|
7
7
|
export const tenantsApi = api.injectEndpoints({
|
|
@@ -49,6 +49,60 @@ export const tenantsApi = api.injectEndpoints({
|
|
|
49
49
|
},
|
|
50
50
|
providesTags: ['All'],
|
|
51
51
|
}),
|
|
52
|
+
getSharedDatabase: build.query<
|
|
53
|
+
SharedDatabaseTarget | null,
|
|
54
|
+
{
|
|
55
|
+
backend?: string;
|
|
56
|
+
clusterName?: string;
|
|
57
|
+
database?: string;
|
|
58
|
+
environmentName?: string;
|
|
59
|
+
isMonitoringAllowed: boolean;
|
|
60
|
+
needNodeIds?: boolean;
|
|
61
|
+
resourceId: string;
|
|
62
|
+
}
|
|
63
|
+
>({
|
|
64
|
+
queryFn: async (
|
|
65
|
+
{clusterName, database, isMonitoringAllowed, needNodeIds, resourceId},
|
|
66
|
+
{signal},
|
|
67
|
+
) => {
|
|
68
|
+
if (isMonitoringAllowed && database && !needNodeIds) {
|
|
69
|
+
try {
|
|
70
|
+
const data = await window.api.viewer.getTabletDescribe(
|
|
71
|
+
{PathId: resourceId},
|
|
72
|
+
database,
|
|
73
|
+
{signal},
|
|
74
|
+
);
|
|
75
|
+
const sharedDatabaseName = data?.Path?.trim();
|
|
76
|
+
|
|
77
|
+
if (sharedDatabaseName) {
|
|
78
|
+
return {data: {name: sharedDatabaseName}};
|
|
79
|
+
}
|
|
80
|
+
} catch (error) {
|
|
81
|
+
if (signal.aborted) {
|
|
82
|
+
return {error};
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
try {
|
|
88
|
+
const response = await window.api.viewer.getTenants(
|
|
89
|
+
{clusterName, metadataCache: false, storage: false},
|
|
90
|
+
{signal},
|
|
91
|
+
);
|
|
92
|
+
const sharedDatabase = response.TenantInfo?.find(({Id}) => Id === resourceId);
|
|
93
|
+
const sharedDatabaseName = sharedDatabase?.Name?.trim();
|
|
94
|
+
|
|
95
|
+
return {
|
|
96
|
+
data: sharedDatabaseName
|
|
97
|
+
? {name: sharedDatabaseName, nodeIds: sharedDatabase?.NodeIds}
|
|
98
|
+
: null,
|
|
99
|
+
};
|
|
100
|
+
} catch (error) {
|
|
101
|
+
return {error};
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
providesTags: ['All'],
|
|
105
|
+
}),
|
|
52
106
|
}),
|
|
53
107
|
overrideExisting: 'throw',
|
|
54
108
|
});
|
|
@@ -17,10 +17,15 @@ export enum StatusFlag {
|
|
|
17
17
|
RED = 'RED',
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
interface LocationBridgePile {
|
|
21
|
+
name?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
20
24
|
interface LocationNode {
|
|
21
25
|
id?: number;
|
|
22
26
|
host?: string;
|
|
23
27
|
port?: number;
|
|
28
|
+
pile?: LocationBridgePile;
|
|
24
29
|
}
|
|
25
30
|
|
|
26
31
|
interface LocationStoragePDisk {
|
|
@@ -36,6 +41,7 @@ interface LocationStorageVDisk {
|
|
|
36
41
|
interface LocationStorageGroup {
|
|
37
42
|
id?: string[];
|
|
38
43
|
vdisk?: LocationStorageVDisk;
|
|
44
|
+
pile?: LocationBridgePile;
|
|
39
45
|
}
|
|
40
46
|
|
|
41
47
|
interface LocationStoragePool {
|
|
@@ -66,6 +72,7 @@ interface LocationComputeSchema {
|
|
|
66
72
|
interface LocationComputeStateStorage {
|
|
67
73
|
node?: LocationNode;
|
|
68
74
|
ring?: number;
|
|
75
|
+
pile?: LocationBridgePile;
|
|
69
76
|
}
|
|
70
77
|
|
|
71
78
|
interface LocationCompute {
|
|
@@ -73,6 +80,7 @@ interface LocationCompute {
|
|
|
73
80
|
pool?: LocationComputePool;
|
|
74
81
|
tablet?: LocationComputeTablet;
|
|
75
82
|
schema?: LocationComputeSchema;
|
|
83
|
+
pile?: LocationBridgePile;
|
|
76
84
|
state_storage?: LocationComputeStateStorage;
|
|
77
85
|
}
|
|
78
86
|
|