ydb-embedded-ui 4.15.1 → 4.16.1

Sign up to get free protection for your applications and to get access to all the features.
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>;