ydb-embedded-ui 4.15.1 → 4.16.1

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.
Files changed (63) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/components/BasicNodeViewer/BasicNodeViewer.tsx +2 -2
  3. package/dist/components/DiagnosticCard/DiagnosticCard.scss +5 -0
  4. package/dist/components/DiagnosticCard/DiagnosticCard.tsx +17 -0
  5. package/dist/components/EntityStatus/EntityStatus.js +2 -2
  6. package/dist/components/EntityStatus/EntityStatus.scss +15 -0
  7. package/dist/components/NodeHostWrapper/NodeHostWrapper.tsx +2 -1
  8. package/dist/containers/Cluster/Cluster.tsx +2 -2
  9. package/dist/containers/Node/Node.tsx +3 -1
  10. package/dist/containers/Node/NodeStructure/NodeStructure.tsx +3 -1
  11. package/dist/containers/Node/NodeStructure/Pdisk.tsx +2 -2
  12. package/dist/containers/Nodes/Nodes.tsx +3 -2
  13. package/dist/containers/Nodes/getNodesColumns.tsx +3 -1
  14. package/dist/containers/Storage/Storage.tsx +3 -2
  15. package/dist/containers/Storage/StorageNodes/StorageNodes.tsx +2 -2
  16. package/dist/containers/Tenant/Diagnostics/DetailedOverview/DetailedOverview.tsx +5 -12
  17. package/dist/containers/Tenant/Diagnostics/Diagnostics.tsx +3 -2
  18. package/dist/containers/Tenant/Diagnostics/Healthcheck/Details/Details.tsx +20 -11
  19. package/dist/containers/Tenant/Diagnostics/Healthcheck/Healthcheck.scss +14 -1
  20. package/dist/containers/Tenant/Diagnostics/Healthcheck/Healthcheck.tsx +26 -37
  21. package/dist/containers/Tenant/Diagnostics/Healthcheck/Preview/Preview.tsx +37 -25
  22. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.tsx +155 -0
  23. package/dist/containers/Tenant/Diagnostics/TenantOverview/i18n/en.json +7 -0
  24. package/dist/containers/Tenant/Diagnostics/TenantOverview/i18n/index.ts +11 -0
  25. package/dist/containers/Tenant/Diagnostics/TenantOverview/i18n/ru.json +7 -0
  26. package/dist/containers/Tenant/ObjectGeneral/ObjectGeneral.tsx +3 -2
  27. package/dist/containers/Tenant/Query/QueriesHistory/QueriesHistory.scss +4 -1
  28. package/dist/containers/Tenant/Query/QueriesHistory/QueriesHistory.tsx +42 -11
  29. package/dist/containers/Tenant/Query/QueryEditor/QueryEditor.js +1 -1
  30. package/dist/containers/Tenant/Query/QueryEditorControls/QueryEditorControls.tsx +11 -7
  31. package/dist/containers/Tenant/Query/i18n/en.json +3 -0
  32. package/dist/containers/Tenant/Query/i18n/ru.json +3 -0
  33. package/dist/containers/Tenant/Tenant.tsx +3 -2
  34. package/dist/containers/UserSettings/Setting.tsx +9 -2
  35. package/dist/containers/UserSettings/i18n/en.json +5 -1
  36. package/dist/containers/UserSettings/i18n/ru.json +5 -1
  37. package/dist/containers/UserSettings/settings.ts +25 -0
  38. package/dist/services/api.ts +16 -16
  39. package/dist/store/reducers/executeQuery.ts +33 -7
  40. package/dist/store/reducers/explainQuery.ts +12 -4
  41. package/dist/store/reducers/healthcheckInfo.ts +27 -11
  42. package/dist/store/reducers/settings/settings.ts +4 -10
  43. package/dist/store/reducers/tenant/tenant.ts +19 -1
  44. package/dist/store/reducers/tenant/types.ts +3 -1
  45. package/dist/store/reducers/tenants/selectors.ts +1 -1
  46. package/dist/store/reducers/tenants/utils.ts +2 -2
  47. package/dist/types/additionalProps.ts +8 -1
  48. package/dist/types/api/tenant.ts +19 -20
  49. package/dist/types/store/executeQuery.ts +11 -1
  50. package/dist/types/store/query.ts +2 -1
  51. package/dist/utils/autofetcher.ts +7 -7
  52. package/dist/utils/constants.ts +2 -1
  53. package/dist/utils/hooks/i18n/en.json +1 -1
  54. package/dist/utils/hooks/i18n/ru.json +1 -1
  55. package/dist/utils/hooks/useQueryModes.ts +4 -2
  56. package/dist/utils/i18n/i18n.ts +10 -4
  57. package/dist/utils/nodes.ts +0 -6
  58. package/dist/utils/query.ts +14 -0
  59. package/dist/utils/settings.ts +10 -0
  60. package/package.json +1 -1
  61. package/dist/containers/Tenant/Diagnostics/Healthcheck/Preview/PreviewItem/PreviewItem.tsx +0 -33
  62. package/dist/containers/Tenant/Diagnostics/Healthcheck/Preview/PreviewItem/index.ts +0 -1
  63. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.js +0 -213
package/CHANGELOG.md CHANGED
@@ -1,5 +1,26 @@
1
1
  # Changelog
2
2
 
3
+ ## [4.16.1](https://github.com/ydb-platform/ydb-embedded-ui/compare/v4.16.0...v4.16.1) (2023-08-25)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * fix types for external props ([#522](https://github.com/ydb-platform/ydb-embedded-ui/issues/522)) ([173081f](https://github.com/ydb-platform/ydb-embedded-ui/commit/173081f2f0d2814b2311757988d91fbffc2a509f))
9
+
10
+ ## [4.16.0](https://github.com/ydb-platform/ydb-embedded-ui/compare/v4.15.1...v4.16.0) (2023-08-25)
11
+
12
+
13
+ ### Features
14
+
15
+ * add language setting ([#520](https://github.com/ydb-platform/ydb-embedded-ui/issues/520)) ([425c9ae](https://github.com/ydb-platform/ydb-embedded-ui/commit/425c9ae1fed83d7695d2a9288c2ef24c2807d8da))
16
+ * **Diagnostics:** update Healthcheck design ([#509](https://github.com/ydb-platform/ydb-embedded-ui/issues/509)) ([e315ca4](https://github.com/ydb-platform/ydb-embedded-ui/commit/e315ca42ac6c9d1736aaa25e2dd90afc2bcb9a8e))
17
+ * **Query:** support PostgreSQL syntax ([#515](https://github.com/ydb-platform/ydb-embedded-ui/issues/515)) ([0c8346e](https://github.com/ydb-platform/ydb-embedded-ui/commit/0c8346efc3643a8d201137901880f985dc100458))
18
+
19
+
20
+ ### Bug Fixes
21
+
22
+ * **UserSettings:** update query mode setting description ([#521](https://github.com/ydb-platform/ydb-embedded-ui/issues/521)) ([c526471](https://github.com/ydb-platform/ydb-embedded-ui/commit/c52647192ff95d8fb9961479a85cc4d5a639d4e6))
23
+
3
24
  ## [4.15.1](https://github.com/ydb-platform/ydb-embedded-ui/compare/v4.15.0...v4.15.1) (2023-08-21)
4
25
 
5
26
 
@@ -1,7 +1,7 @@
1
1
  import cn from 'bem-cn-lite';
2
2
 
3
3
  import type {TSystemStateInfo} from '../../types/api/nodes';
4
- import type {AdditionalNodesInfo} from '../../utils/nodes';
4
+ import type {AdditionalNodesProps} from '../../types/additionalProps';
5
5
 
6
6
  import EntityStatus from '../EntityStatus/EntityStatus';
7
7
  import {Tags} from '../Tags';
@@ -13,7 +13,7 @@ const b = cn('basic-node-viewer');
13
13
 
14
14
  interface BasicNodeViewerProps {
15
15
  node: TSystemStateInfo;
16
- additionalNodesInfo?: AdditionalNodesInfo;
16
+ additionalNodesInfo?: AdditionalNodesProps;
17
17
  className?: string;
18
18
  }
19
19
 
@@ -0,0 +1,5 @@
1
+ .diagnostic-card {
2
+ min-width: 200px;
3
+ max-width: 350px;
4
+ padding: 16px;
5
+ }
@@ -0,0 +1,17 @@
1
+ import {ReactNode} from 'react';
2
+ import cn from 'bem-cn-lite';
3
+
4
+ import {Card} from '@gravity-ui/uikit';
5
+
6
+ import './DiagnosticCard.scss';
7
+
8
+ const b = cn('diagnostic-card');
9
+
10
+ interface DiagnosticCardProps {
11
+ children?: ReactNode;
12
+ className?: string;
13
+ }
14
+
15
+ export function DiagnosticCard({children, className}: DiagnosticCardProps) {
16
+ return <Card className={b(null, className)}>{children}</Card>;
17
+ }
@@ -107,13 +107,13 @@ class EntityStatus extends React.Component {
107
107
  );
108
108
  }
109
109
  render() {
110
- const {name, label, iconPath, hasClipboardButton, className} = this.props;
110
+ const {name, label, iconPath, hasClipboardButton, className, size, status} = this.props;
111
111
 
112
112
  return (
113
113
  <div className={b(null, className)} title={name}>
114
114
  {iconPath ? this.renderStatusLink() : this.renderIcon()}
115
115
  {label && (
116
- <span title={label} className={b('label')}>
116
+ <span title={label} className={b('label', {size, state: status.toLowerCase()})}>
117
117
  {label}
118
118
  </span>
119
119
  )}
@@ -47,6 +47,15 @@
47
47
  line-height: var(--yc-text-body-2-line-height);
48
48
 
49
49
  color: var(--yc-color-text-complementary);
50
+
51
+ &_size_m {
52
+ font-size: var(--yc-text-body-2-font-size);
53
+ line-height: var(--yc-text-body-2-line-height);
54
+ }
55
+
56
+ &_size_l {
57
+ font-size: var(--yc-text-header-2-font-size);
58
+ }
50
59
  }
51
60
 
52
61
  &__link {
@@ -89,6 +98,11 @@
89
98
  width: 18px;
90
99
  height: 18px;
91
100
  }
101
+
102
+ &_size_l {
103
+ width: 27px;
104
+ height: 27px;
105
+ }
92
106
  }
93
107
 
94
108
  &__status-color {
@@ -115,6 +129,7 @@
115
129
  }
116
130
  }
117
131
 
132
+ &__label,
118
133
  &__status-icon {
119
134
  &_state_blue {
120
135
  color: var(--yc-color-infographics-info-heavy);
@@ -3,8 +3,9 @@ import block from 'bem-cn-lite';
3
3
  import {Button, Popover, PopoverBehavior} from '@gravity-ui/uikit';
4
4
 
5
5
  import type {NodesPreparedEntity} from '../../store/reducers/nodes/types';
6
+ import type {NodeAddress} from '../../types/additionalProps';
6
7
  import {getDefaultNodePath} from '../../containers/Node/NodePages';
7
- import {isUnavailableNode, NodeAddress} from '../../utils/nodes';
8
+ import {isUnavailableNode} from '../../utils/nodes';
8
9
 
9
10
  import EntityStatus from '../EntityStatus/EntityStatus';
10
11
  import {NodeEndpointsTooltipContent} from '../TooltipsContent';
@@ -10,8 +10,8 @@ import type {
10
10
  AdditionalClusterProps,
11
11
  AdditionalTenantsProps,
12
12
  AdditionalVersionsProps,
13
+ AdditionalNodesProps,
13
14
  } from '../../types/additionalProps';
14
- import type {AdditionalNodesInfo} from '../../utils/nodes';
15
15
  import routes from '../../routes';
16
16
 
17
17
  import {setHeaderBreadcrumbs} from '../../store/reducers/header/header';
@@ -35,7 +35,7 @@ const b = cn('cluster');
35
35
 
36
36
  interface ClusterProps {
37
37
  additionalTenantsProps?: AdditionalTenantsProps;
38
- additionalNodesInfo?: AdditionalNodesInfo;
38
+ additionalNodesInfo?: AdditionalNodesProps;
39
39
  additionalClusterProps?: AdditionalClusterProps;
40
40
  additionalVersionsProps?: AdditionalVersionsProps;
41
41
  }
@@ -21,6 +21,8 @@ import {setHeaderBreadcrumbs} from '../../store/reducers/header/header';
21
21
  import {AutoFetcher} from '../../utils/autofetcher';
22
22
  import {useTypedSelector} from '../../utils/hooks';
23
23
 
24
+ import type {AdditionalNodesProps} from '../../types/additionalProps';
25
+
24
26
  import {clusterTabsIds} from '../Cluster/utils';
25
27
 
26
28
  import './Node.scss';
@@ -32,7 +34,7 @@ export const STORAGE_ROLE = 'Storage';
32
34
  const autofetcher = new AutoFetcher();
33
35
 
34
36
  interface NodeProps {
35
- additionalNodesInfo?: any;
37
+ additionalNodesInfo?: AdditionalNodesProps;
36
38
  className?: string;
37
39
  }
38
40
 
@@ -13,6 +13,8 @@ import {selectNodeStructure} from '../../../store/reducers/node/selectors';
13
13
  import {AutoFetcher} from '../../../utils/autofetcher';
14
14
  import {useTypedSelector} from '../../../utils/hooks';
15
15
 
16
+ import type {AdditionalNodesProps} from '../../../types/additionalProps';
17
+
16
18
  import {PDisk} from './Pdisk';
17
19
 
18
20
  import './NodeStructure.scss';
@@ -30,7 +32,7 @@ function generateId({type, id}: {type: 'pdisk' | 'vdisk'; id: string}) {
30
32
  interface NodeStructureProps {
31
33
  nodeId: string;
32
34
  className?: string;
33
- additionalNodesInfo?: any;
35
+ additionalNodesInfo?: AdditionalNodesProps;
34
36
  }
35
37
 
36
38
  const autofetcher = new AutoFetcher();
@@ -27,7 +27,7 @@ interface PDiskProps {
27
27
  unfolded?: boolean;
28
28
  id: string;
29
29
  selectedVdiskId?: string;
30
- nodeHref?: string;
30
+ nodeHref?: string | null;
31
31
  }
32
32
 
33
33
  enum VDiskTableColumnsIds {
@@ -62,7 +62,7 @@ function getColumns({
62
62
  }: {
63
63
  pDiskId: number;
64
64
  selectedVdiskId?: string;
65
- nodeHref?: string;
65
+ nodeHref?: string | null;
66
66
  }) {
67
67
  const columns: Column<RowType>[] = [
68
68
  {
@@ -26,7 +26,7 @@ import {
26
26
  useNodesRequestParams,
27
27
  useTableSort,
28
28
  } from '../../utils/hooks';
29
- import {AdditionalNodesInfo, isUnavailableNode, NodesUptimeFilterValues} from '../../utils/nodes';
29
+ import {isUnavailableNode, NodesUptimeFilterValues} from '../../utils/nodes';
30
30
 
31
31
  import {
32
32
  getNodes,
@@ -39,6 +39,7 @@ import {
39
39
  } from '../../store/reducers/nodes/nodes';
40
40
  import {selectFilteredNodes} from '../../store/reducers/nodes/selectors';
41
41
  import {changeFilter, ProblemFilterValues} from '../../store/reducers/settings/settings';
42
+ import type {AdditionalNodesProps} from '../../types/additionalProps';
42
43
 
43
44
  import {isDatabaseEntityType} from '../Tenant/utils/schema';
44
45
 
@@ -53,7 +54,7 @@ const b = cn('ydb-nodes');
53
54
  interface NodesProps {
54
55
  path?: string;
55
56
  type?: EPathType;
56
- additionalNodesInfo?: AdditionalNodesInfo;
57
+ additionalNodesInfo?: AdditionalNodesProps;
57
58
  }
58
59
 
59
60
  export const Nodes = ({path, type, additionalNodesInfo = {}}: NodesProps) => {
@@ -6,11 +6,13 @@ import ProgressViewer from '../../components/ProgressViewer/ProgressViewer';
6
6
  import {TabletsStatistic} from '../../components/TabletsStatistic';
7
7
  import {NodeHostWrapper} from '../../components/NodeHostWrapper/NodeHostWrapper';
8
8
 
9
- import {isSortableNodesProperty, type NodeAddress} from '../../utils/nodes';
9
+ import {isSortableNodesProperty} from '../../utils/nodes';
10
10
  import {formatBytesToGigabyte} from '../../utils/index';
11
11
 
12
12
  import type {NodesPreparedEntity} from '../../store/reducers/nodes/types';
13
13
 
14
+ import type {NodeAddress} from '../../types/additionalProps';
15
+
14
16
  const NODES_COLUMNS_IDS = {
15
17
  NodeId: 'NodeId',
16
18
  Host: 'Host',
@@ -15,6 +15,7 @@ import type {
15
15
  VisibleEntities,
16
16
  } from '../../store/reducers/storage/types';
17
17
  import type {NodesSortParams} from '../../store/reducers/nodes/types';
18
+ import type {AdditionalNodesProps} from '../../types/additionalProps';
18
19
  import {
19
20
  setInitialState,
20
21
  setVisibleEntities,
@@ -45,7 +46,7 @@ import {
45
46
  useTableSort,
46
47
  useTypedSelector,
47
48
  } from '../../utils/hooks';
48
- import {AdditionalNodesInfo, NodesUptimeFilterValues} from '../../utils/nodes';
49
+ import {NodesUptimeFilterValues} from '../../utils/nodes';
49
50
  import {DEFAULT_TABLE_SETTINGS} from '../../utils/constants';
50
51
 
51
52
  import {StorageGroups} from './StorageGroups/StorageGroups';
@@ -59,7 +60,7 @@ import './Storage.scss';
59
60
  const b = cn('global-storage');
60
61
 
61
62
  interface StorageProps {
62
- additionalNodesInfo?: AdditionalNodesInfo;
63
+ additionalNodesInfo?: AdditionalNodesProps;
63
64
  tenant?: string;
64
65
  nodeId?: string;
65
66
  }
@@ -5,10 +5,10 @@ import DataTable, {Column, Settings, SortOrder} from '@gravity-ui/react-data-tab
5
5
  import type {ValueOf} from '../../../types/common';
6
6
  import type {PreparedStorageNode, VisibleEntities} from '../../../store/reducers/storage/types';
7
7
  import type {HandleSort} from '../../../utils/hooks/useTableSort';
8
+ import type {AdditionalNodesProps} from '../../../types/additionalProps';
8
9
 
9
10
  import {VISIBLE_ENTITIES} from '../../../store/reducers/storage/constants';
10
11
  import {
11
- AdditionalNodesInfo,
12
12
  isSortableNodesProperty,
13
13
  isUnavailableNode,
14
14
  NodesUptimeFilterValues,
@@ -40,7 +40,7 @@ interface StorageNodesProps {
40
40
  visibleEntities: VisibleEntities;
41
41
  nodesUptimeFilter: keyof typeof NodesUptimeFilterValues;
42
42
  onShowAll?: VoidFunction;
43
- additionalNodesInfo?: AdditionalNodesInfo;
43
+ additionalNodesInfo?: AdditionalNodesProps;
44
44
  sort?: SortOrder;
45
45
  handleSort?: HandleSort;
46
46
  }
@@ -5,11 +5,11 @@ import cn from 'bem-cn-lite';
5
5
  import {Button, Modal} from '@gravity-ui/uikit';
6
6
 
7
7
  import type {EPathType} from '../../../../types/api/schema';
8
+ import type {AdditionalTenantsProps} from '../../../../types/additionalProps';
8
9
  import {Icon} from '../../../../components/Icon';
9
10
  import Overview from '../Overview/Overview';
10
11
  import {Healthcheck} from '../Healthcheck';
11
- //@ts-ignore
12
- import TenantOverview from '../TenantOverview/TenantOverview';
12
+ import {TenantOverview} from '../TenantOverview/TenantOverview';
13
13
 
14
14
  import './DetailedOverview.scss';
15
15
 
@@ -17,7 +17,7 @@ interface DetailedOverviewProps {
17
17
  type?: EPathType;
18
18
  className?: string;
19
19
  tenantName: string;
20
- additionalTenantInfo?: any;
20
+ additionalTenantInfo?: AdditionalTenantsProps;
21
21
  }
22
22
 
23
23
  const b = cn('kv-detailed-overview');
@@ -25,12 +25,9 @@ const b = cn('kv-detailed-overview');
25
25
  function DetailedOverview(props: DetailedOverviewProps) {
26
26
  const [isModalVisible, setIsModalVisible] = useState(false);
27
27
 
28
- const [expandedIssueId, setExpandedIssueId] = useState<string>();
29
-
30
28
  const {currentSchemaPath} = useSelector((state: any) => state.schema);
31
29
 
32
- const openModalHandler = (id: string) => {
33
- setExpandedIssueId(id);
30
+ const openModalHandler = () => {
34
31
  setIsModalVisible(true);
35
32
  };
36
33
 
@@ -41,11 +38,7 @@ function DetailedOverview(props: DetailedOverviewProps) {
41
38
  const renderModal = () => {
42
39
  return (
43
40
  <Modal open={isModalVisible} onClose={closeModalHandler} className={b('modal')}>
44
- <Healthcheck
45
- tenant={props.tenantName}
46
- fetchData={false}
47
- expandedIssueId={expandedIssueId}
48
- />
41
+ <Healthcheck tenant={props.tenantName} fetchData={false} />
49
42
  <Button
50
43
  className={b('close-modal-button')}
51
44
  onClick={closeModalHandler}
@@ -8,6 +8,7 @@ import {useLocation} from 'react-router';
8
8
  import {Switch, Tabs} from '@gravity-ui/uikit';
9
9
 
10
10
  import type {EPathType} from '../../../types/api/schema';
11
+ import type {AdditionalTenantsProps, AdditionalNodesProps} from '../../../types/additionalProps';
11
12
 
12
13
  import {useTypedSelector} from '../../../utils/hooks';
13
14
  import routes, {createHref} from '../../../routes';
@@ -41,8 +42,8 @@ import './Diagnostics.scss';
41
42
 
42
43
  interface DiagnosticsProps {
43
44
  type?: EPathType;
44
- additionalTenantInfo?: any;
45
- additionalNodesInfo?: any;
45
+ additionalTenantInfo?: AdditionalTenantsProps;
46
+ additionalNodesInfo?: AdditionalNodesProps;
46
47
  }
47
48
 
48
49
  const b = cn('kv-tenant-diagnostics');
@@ -4,7 +4,9 @@ import {Button, Icon} from '@gravity-ui/uikit';
4
4
 
5
5
  import updateArrow from '../../../../../assets/icons/update-arrow.svg';
6
6
 
7
+ import type {IResponseError} from '../../../../../types/api/error';
7
8
  import type {IIssuesTree} from '../../../../../types/store/healthcheck';
9
+ import {ResponseError} from '../../../../../components/Errors/ResponseError';
8
10
 
9
11
  import IssueTree from '../IssuesViewer/IssueTree';
10
12
 
@@ -13,17 +15,14 @@ import i18n from '../i18n';
13
15
  const b = cn('healthcheck');
14
16
 
15
17
  interface DetailsProps {
16
- issueTree?: IIssuesTree;
18
+ issueTrees?: IIssuesTree[];
17
19
  loading?: boolean;
18
20
  onUpdate: VoidFunction;
21
+ error?: IResponseError;
19
22
  }
20
23
 
21
24
  export const Details = (props: DetailsProps) => {
22
- const {loading, onUpdate, issueTree} = props;
23
-
24
- if (!issueTree) {
25
- return null;
26
- }
25
+ const {loading, onUpdate, issueTrees, error} = props;
27
26
 
28
27
  const renderHealthcheckHeader = () => {
29
28
  return (
@@ -38,18 +37,28 @@ export const Details = (props: DetailsProps) => {
38
37
  );
39
38
  };
40
39
 
41
- const renderHealthcheckIssues = () => {
40
+ const renderContent = () => {
41
+ if (error) {
42
+ return <ResponseError error={error} defaultMessage={i18n('no-data')} />;
43
+ }
44
+
45
+ if (!issueTrees || !issueTrees.length) {
46
+ return i18n('status_message.ok');
47
+ }
48
+
42
49
  return (
43
- <div className={b('issues-wrapper')}>
44
- <IssueTree issueTree={issueTree} />
45
- </div>
50
+ <>
51
+ {issueTrees.map((issueTree) => (
52
+ <IssueTree key={issueTree.id} issueTree={issueTree} />
53
+ ))}
54
+ </>
46
55
  );
47
56
  };
48
57
 
49
58
  return (
50
59
  <div className={b('details')}>
51
60
  {renderHealthcheckHeader()}
52
- {renderHealthcheckIssues()}
61
+ <div className={b('details-content-wrapper')}>{renderContent()}</div>
53
62
  </div>
54
63
  );
55
64
  };
@@ -3,6 +3,8 @@
3
3
  @import '@gravity-ui/uikit/styles/mixins.scss';
4
4
 
5
5
  .healthcheck {
6
+ display: flex;
7
+
6
8
  &_expanded {
7
9
  // Since most of the inner containers have fixed width, we can set fixed width here as well
8
10
  // Thus we will get rid of unneeded layout shift when scrollbar appear
@@ -17,7 +19,7 @@
17
19
  margin-bottom: 15px;
18
20
  }
19
21
 
20
- &__issues-wrapper {
22
+ &__details-content-wrapper {
21
23
  overflow-x: hidden;
22
24
  overflow-y: auto;
23
25
 
@@ -67,6 +69,17 @@
67
69
  line-height: 24px;
68
70
  }
69
71
 
72
+ &__issues-statistics {
73
+ display: flex;
74
+ flex-wrap: wrap;
75
+ align-items: center;
76
+
77
+ margin: 10px 0;
78
+
79
+ column-gap: 26px;
80
+ row-gap: 16px;
81
+ }
82
+
70
83
  &__self-check-status-indicator {
71
84
  padding: 0 8px;
72
85
 
@@ -8,40 +8,36 @@ import {SelfCheckResult} from '../../../../types/api/healthcheck';
8
8
  import {useTypedSelector, useAutofetcher} from '../../../../utils/hooks';
9
9
  import {
10
10
  getHealthcheckInfo,
11
- selectIssuesTreeById,
12
- selectIssuesTreesRoots,
11
+ selectIssuesStatistics,
12
+ selectIssuesTrees,
13
13
  setDataWasNotLoaded,
14
14
  } from '../../../../store/reducers/healthcheckInfo';
15
+ import {DiagnosticCard} from '../../../../components/DiagnosticCard/DiagnosticCard';
15
16
 
16
17
  import {Details} from './Details';
17
18
  import {Preview} from './Preview';
18
19
 
19
- import i18n from './i18n';
20
20
  import './Healthcheck.scss';
21
21
 
22
22
  interface HealthcheckProps {
23
23
  tenant: string;
24
24
  preview?: boolean;
25
25
  fetchData?: boolean;
26
- expandedIssueId?: string;
27
- showMoreHandler?: (id: string) => void;
26
+ showMoreHandler?: VoidFunction;
28
27
  }
29
28
 
30
29
  const b = cn('healthcheck');
31
30
 
32
31
  export const Healthcheck = (props: HealthcheckProps) => {
33
- const {tenant, preview, fetchData = true, showMoreHandler, expandedIssueId} = props;
32
+ const {tenant, preview, fetchData = true, showMoreHandler} = props;
34
33
 
35
34
  const dispatch = useDispatch();
36
35
 
37
36
  const {data, loading, wasLoaded, error} = useTypedSelector((state) => state.healthcheckInfo);
38
37
  const selfCheckResult = data?.self_check_result || SelfCheckResult.UNSPECIFIED;
39
38
 
40
- const issuesTreesRoots = useTypedSelector(selectIssuesTreesRoots);
41
- const expandedIssueTree = useTypedSelector((state) =>
42
- selectIssuesTreeById(state, expandedIssueId),
43
- );
44
-
39
+ const issuesStatistics = useTypedSelector(selectIssuesStatistics);
40
+ const issueTrees = useTypedSelector(selectIssuesTrees);
45
41
  const {autorefresh} = useTypedSelector((state) => state.schema);
46
42
 
47
43
  const fetchHealthcheck = useCallback(
@@ -66,37 +62,30 @@ export const Healthcheck = (props: HealthcheckProps) => {
66
62
  );
67
63
 
68
64
  const renderContent = () => {
69
- if (error) {
70
- return error.statusText;
71
- }
72
-
73
65
  if (loading && !wasLoaded) {
74
66
  return (
75
- <div className={b('loader')}>
67
+ <DiagnosticCard className={b('loader')}>
76
68
  <Loader size="m" />
77
- </div>
69
+ </DiagnosticCard>
78
70
  );
79
71
  }
80
-
81
- if (data && data['self_check_result']) {
82
- return preview ? (
83
- <Preview
84
- issuesTrees={issuesTreesRoots}
85
- selfCheckResult={selfCheckResult}
86
- loading={loading}
87
- onShowMore={showMoreHandler}
88
- onUpdate={fetchHealthcheck}
89
- />
90
- ) : (
91
- <Details
92
- issueTree={expandedIssueTree}
93
- loading={loading}
94
- onUpdate={fetchHealthcheck}
95
- />
96
- );
97
- }
98
-
99
- return <div className="error">{i18n('no-data')}</div>;
72
+ return preview ? (
73
+ <Preview
74
+ issuesStatistics={issuesStatistics}
75
+ selfCheckResult={selfCheckResult}
76
+ loading={loading}
77
+ onShowMore={showMoreHandler}
78
+ onUpdate={fetchHealthcheck}
79
+ error={error}
80
+ />
81
+ ) : (
82
+ <Details
83
+ loading={loading}
84
+ onUpdate={fetchHealthcheck}
85
+ issueTrees={issueTrees}
86
+ error={error}
87
+ />
88
+ );
100
89
  };
101
90
 
102
91
  return <div className={b({expanded: !preview})}>{renderContent()}</div>;