ydb-embedded-ui 2.4.4 → 2.6.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.
Files changed (77) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/dist/components/InfoViewer/InfoViewer.scss +3 -3
  3. package/dist/components/InfoViewer/formatters/schema.ts +2 -1
  4. package/dist/components/InfoViewer/schemaInfo/CDCStreamInfo.tsx +23 -22
  5. package/dist/components/InfoViewer/schemaInfo/PersQueueGroupInfo.tsx +8 -13
  6. package/dist/components/InfoViewer/schemaInfo/TableIndexInfo.tsx +2 -12
  7. package/dist/components/InfoViewer/schemaOverview/CDCStreamOverview.tsx +3 -16
  8. package/dist/components/InfoViewer/schemaOverview/PersQueueGroupOverview.tsx +8 -13
  9. package/dist/components/InfoViewer/utils.ts +6 -6
  10. package/dist/components/Loader/Loader.scss +6 -3
  11. package/dist/components/Loader/Loader.tsx +7 -5
  12. package/dist/components/Loader/index.ts +1 -0
  13. package/dist/components/UptimeFIlter/UptimeFilter.tsx +21 -0
  14. package/dist/components/UptimeFIlter/index.ts +1 -0
  15. package/dist/containers/Node/Node.scss +1 -0
  16. package/dist/containers/Node/Node.tsx +3 -8
  17. package/dist/containers/Node/NodeStructure/NodeStructure.scss +0 -6
  18. package/dist/containers/Node/NodeStructure/NodeStructure.tsx +1 -1
  19. package/dist/containers/Nodes/Nodes.js +22 -10
  20. package/dist/{components → containers}/NodesViewer/NodesViewer.js +49 -62
  21. package/dist/{components → containers}/NodesViewer/NodesViewer.scss +0 -0
  22. package/dist/containers/Storage/Pdisk/Pdisk.scss +1 -1
  23. package/dist/containers/Storage/Pdisk/Pdisk.tsx +3 -9
  24. package/dist/containers/Storage/Pdisk/__tests__/colors.tsx +1 -1
  25. package/dist/containers/Storage/Storage.js +46 -11
  26. package/dist/containers/Storage/StorageGroups/StorageGroups.tsx +39 -32
  27. package/dist/containers/Storage/StorageNodes/StorageNodes.scss +2 -2
  28. package/dist/containers/Storage/StorageNodes/StorageNodes.tsx +35 -17
  29. package/dist/containers/Storage/StorageNodes/i18n/en.json +6 -4
  30. package/dist/containers/Storage/StorageNodes/i18n/ru.json +6 -4
  31. package/dist/containers/Storage/UsageFilter/UsageFilter.scss +10 -5
  32. package/dist/containers/Tenant/Acl/Acl.js +1 -7
  33. package/dist/containers/Tenant/Diagnostics/Compute/Compute.js +22 -14
  34. package/dist/containers/Tenant/Diagnostics/Consumers/Consumers.tsx +52 -10
  35. package/dist/containers/Tenant/Diagnostics/Describe/Describe.scss +0 -8
  36. package/dist/containers/Tenant/Diagnostics/Describe/Describe.tsx +42 -15
  37. package/dist/containers/Tenant/Diagnostics/Diagnostics.scss +0 -7
  38. package/dist/containers/Tenant/Diagnostics/Diagnostics.tsx +19 -15
  39. package/dist/containers/Tenant/Diagnostics/DiagnosticsPages.ts +1 -1
  40. package/dist/containers/Tenant/Diagnostics/Healthcheck/Healthcheck.tsx +13 -5
  41. package/dist/containers/Tenant/Diagnostics/Network/Network.js +17 -4
  42. package/dist/containers/Tenant/Diagnostics/Overview/Overview.tsx +50 -16
  43. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.js +16 -2
  44. package/dist/containers/Tenant/Diagnostics/TopQueries/TopQueries.js +1 -0
  45. package/dist/containers/Tenant/Diagnostics/TopShards/TopShards.js +21 -13
  46. package/dist/containers/Tenant/ObjectGeneral/ObjectGeneral.tsx +1 -5
  47. package/dist/containers/Tenant/QueryEditor/QueryExplain/QueryExplain.js +4 -4
  48. package/dist/containers/Tenant/QueryEditor/SaveQuery/SaveQuery.js +1 -4
  49. package/dist/containers/Tenant/Schema/SchemaInfoViewer/SchemaInfoViewer.js +23 -28
  50. package/dist/containers/Tenant/Schema/SchemaTree/SchemaTree.tsx +2 -2
  51. package/dist/containers/Tenant/TenantPages.tsx +1 -1
  52. package/dist/containers/Tenant/utils/schema.ts +84 -0
  53. package/dist/containers/Tenant/utils/schemaActions.ts +9 -20
  54. package/dist/services/api.d.ts +17 -11
  55. package/dist/store/reducers/clusterNodes.js +29 -10
  56. package/dist/store/reducers/describe.ts +56 -14
  57. package/dist/store/reducers/healthcheckInfo.ts +23 -8
  58. package/dist/store/reducers/network.js +22 -1
  59. package/dist/store/reducers/nodes.js +37 -3
  60. package/dist/store/reducers/schema.ts +229 -0
  61. package/dist/store/reducers/storage.js +59 -5
  62. package/dist/types/api/enums.ts +10 -0
  63. package/dist/types/api/nodes.ts +96 -0
  64. package/dist/types/api/pdisk.ts +48 -0
  65. package/dist/types/api/schema.ts +148 -9
  66. package/dist/types/api/storage.ts +3 -173
  67. package/dist/types/api/tablet.ts +97 -0
  68. package/dist/types/api/vdisk.ts +120 -0
  69. package/dist/types/store/describe.ts +8 -2
  70. package/dist/types/store/healthcheck.ts +12 -0
  71. package/dist/types/store/schema.ts +52 -0
  72. package/dist/utils/index.js +6 -2
  73. package/dist/utils/nodes.ts +9 -0
  74. package/dist/utils/pdisk.ts +1 -1
  75. package/dist/utils/storage.ts +1 -1
  76. package/package.json +1 -1
  77. package/dist/store/reducers/schema.js +0 -148
package/CHANGELOG.md CHANGED
@@ -1,5 +1,47 @@
1
1
  # Changelog
2
2
 
3
+ ## [2.6.0](https://github.com/ydb-platform/ydb-embedded-ui/compare/v2.5.0...v2.6.0) (2022-12-05)
4
+
5
+
6
+ ### Features
7
+
8
+ * **Describe:** add topic data for CDCStream ([3a289d4](https://github.com/ydb-platform/ydb-embedded-ui/commit/3a289d4f6452e3f2d719c0d508f48b389fd044d7))
9
+ * **Diagnostics:** add consumers tab for CdcStream ([22c6efd](https://github.com/ydb-platform/ydb-embedded-ui/commit/22c6efdd39d85ab1585943bc13d88cf03f9bc2ae))
10
+ * **Overview:** add topic data for CDCStream ([be80545](https://github.com/ydb-platform/ydb-embedded-ui/commit/be80545df65a03820265875fedd98c6f181af491))
11
+
12
+
13
+ ### Bug Fixes
14
+
15
+ * **Compute:** update data on path change ([1783240](https://github.com/ydb-platform/ydb-embedded-ui/commit/17832403623ae3e718f47aec508c834cd2e3458c))
16
+ * **Diagnostics:** render db tabs for not root dbs ([7d46ce2](https://github.com/ydb-platform/ydb-embedded-ui/commit/7d46ce2783a58b1ae6e41cae6592e78f95d61bcc))
17
+ * **Healthcheck:** render loader on path change ([ec40f19](https://github.com/ydb-platform/ydb-embedded-ui/commit/ec40f19c0b369de0b8d0658b4a1dd68c5c419c1c))
18
+ * **InfoViewer:** allow multiline values ([17755dc](https://github.com/ydb-platform/ydb-embedded-ui/commit/17755dc2eae7b6fc0a56ff70da95679fc590dccb))
19
+ * **Network:** update data on path change ([588c53f](https://github.com/ydb-platform/ydb-embedded-ui/commit/588c53f80a81376301216a77d9ead95cdff9812f))
20
+ * **SchemaTree:** do not expand childless components ([90468de](https://github.com/ydb-platform/ydb-embedded-ui/commit/90468de74b74e00a66255ba042378c9d7e1cbc27))
21
+ * **Storage:** update data on path change ([f5486bc](https://github.com/ydb-platform/ydb-embedded-ui/commit/f5486bcb2838b9e290c566089980533b4d22d035))
22
+ * **Tablets:** fix postponed data update on path change ([d474c6c](https://github.com/ydb-platform/ydb-embedded-ui/commit/d474c6cb36597f0c720ef3bb8d0360ec73973e26))
23
+ * **TopQueries:** update data on path change ([32d7720](https://github.com/ydb-platform/ydb-embedded-ui/commit/32d77208b8ef09682c41160c60a1a7742b0c6c4c))
24
+
25
+ ## [2.5.0](https://github.com/ydb-platform/ydb-embedded-ui/compare/v2.4.4...v2.5.0) (2022-11-25)
26
+
27
+
28
+ ### Features
29
+
30
+ * **Nodes:** add uptime filter ([9bb4f66](https://github.com/ydb-platform/ydb-embedded-ui/commit/9bb4f664df8fadec5b5e612b2adb866c28415efa))
31
+ * **NodesViewer:** add uptime filter ([a802442](https://github.com/ydb-platform/ydb-embedded-ui/commit/a8024422a09ff95e55c399d26046f5103cab3f89))
32
+ * **Storage:** add nodes uptime filter ([d8cfea1](https://github.com/ydb-platform/ydb-embedded-ui/commit/d8cfea14369e8235d1f7ef86a9a3f34c05efdf5c))
33
+
34
+
35
+ ### Bug Fixes
36
+
37
+ * **Consumers:** add autorefresh to useAutofetcher ([e0da2a1](https://github.com/ydb-platform/ydb-embedded-ui/commit/e0da2a11fcd18cb8ba808a07873a78cbf7191cdc))
38
+ * **Consumers:** add loader ([a59f472](https://github.com/ydb-platform/ydb-embedded-ui/commit/a59f472fd7c9347bcde8cc21d4001f999fc88110))
39
+ * **QueryExplain:** fix schema rerender on path change ([eb52978](https://github.com/ydb-platform/ydb-embedded-ui/commit/eb529787bf747bb2bf49bae65676011426341a23))
40
+ * **Storage:** add message on empty nodes with small uptime ([70959ab](https://github.com/ydb-platform/ydb-embedded-ui/commit/70959ab90bd0f81ebab7712b7d34c0ca80f4dd0b))
41
+ * **Storage:** fix uneven PDisks ([0269dba](https://github.com/ydb-platform/ydb-embedded-ui/commit/0269dbab0336ae5b8cbf43e1b52458e932527a66))
42
+ * **StorageNodes:** fix message display on not empty data ([bb5fffa](https://github.com/ydb-platform/ydb-embedded-ui/commit/bb5fffa786cde3f680375f8e11e3893c52c4f6da))
43
+ * **UsageFilter:** add min-width ([56b2701](https://github.com/ydb-platform/ydb-embedded-ui/commit/56b2701a17420e0322fac0223bce26e18a2f0e47))
44
+
3
45
  ## [2.4.4](https://github.com/ydb-platform/ydb-embedded-ui/compare/v2.4.3...v2.4.4) (2022-11-22)
4
46
 
5
47
 
@@ -24,10 +24,10 @@
24
24
 
25
25
  &__row {
26
26
  display: flex;
27
- align-items: flex-end;
27
+ align-items: baseline;
28
28
 
29
29
  max-width: 100%;
30
- height: 24px;
30
+ padding-top: 4px;
31
31
  }
32
32
 
33
33
  &__label {
@@ -54,7 +54,7 @@
54
54
  &__value {
55
55
  display: flex;
56
56
 
57
- white-space: nowrap;
57
+ word-break: break-all;
58
58
  }
59
59
 
60
60
  &_size {
@@ -32,7 +32,8 @@ export const formatPQGroupItem = createInfoFormatter<TPersQueueGroupDescription>
32
32
  values: {
33
33
  Partitions: (value) => formatNumber(value?.length || 0),
34
34
  PQTabletConfig: (value) => {
35
- const hours = Math.round(value.PartitionConfig.LifetimeSeconds / HOUR_IN_SECONDS * 100) / 100;
35
+ const hours =
36
+ Math.round((value.PartitionConfig.LifetimeSeconds / HOUR_IN_SECONDS) * 100) / 100;
36
37
  return `${formatNumber(hours)} hours`;
37
38
  },
38
39
  },
@@ -1,44 +1,45 @@
1
1
  import type {TEvDescribeSchemeResult, TCdcStreamDescription} from '../../../types/api/schema';
2
+ import {useTypedSelector} from '../../../utils/hooks';
3
+ import {selectSchemaData} from '../../../store/reducers/schema';
2
4
 
3
- import {formatCdcStreamItem, formatCommonItem} from '../formatters';
5
+ import {formatCdcStreamItem, formatPQGroupItem, formatCommonItem} from '../formatters';
4
6
  import {InfoViewer, InfoViewerItem} from '..';
5
7
 
6
- const DISPLAYED_FIELDS: Set<keyof TCdcStreamDescription> = new Set([
7
- 'Mode',
8
- 'Format',
9
- ]);
8
+ const DISPLAYED_FIELDS: Set<keyof TCdcStreamDescription> = new Set(['Mode', 'Format']);
10
9
 
11
10
  interface CDCStreamInfoProps {
12
11
  data?: TEvDescribeSchemeResult;
12
+ childrenPaths?: string[];
13
13
  }
14
14
 
15
- export const CDCStreamInfo = ({data}: CDCStreamInfoProps) => {
16
- if (!data) {
17
- return (
18
- <div className="error">No CDC Stream data</div>
19
- );
15
+ export const CDCStreamInfo = ({data, childrenPaths}: CDCStreamInfoProps) => {
16
+ const pqGroupData = useTypedSelector((state) => selectSchemaData(state, childrenPaths?.[0]));
17
+
18
+ if (!data || !pqGroupData) {
19
+ return <div className="error">No Changefeed data</div>;
20
20
  }
21
21
 
22
- const TableIndex = data.PathDescription?.CdcStreamDescription;
22
+ const cdcStream = data.PathDescription?.CdcStreamDescription;
23
+ const pqGroup = pqGroupData?.PathDescription?.PersQueueGroup;
24
+
23
25
  const info: Array<InfoViewerItem> = [];
24
26
 
25
- info.push(formatCommonItem('PathType', data.PathDescription?.Self?.PathType));
26
27
  info.push(formatCommonItem('CreateStep', data.PathDescription?.Self?.CreateStep));
27
28
 
28
29
  let key: keyof TCdcStreamDescription;
29
- for (key in TableIndex) {
30
+ for (key in cdcStream) {
30
31
  if (DISPLAYED_FIELDS.has(key)) {
31
- info.push(formatCdcStreamItem(key, TableIndex?.[key]));
32
+ info.push(formatCdcStreamItem(key, cdcStream?.[key]));
32
33
  }
33
34
  }
34
35
 
35
- return (
36
- <>
37
- {info.length ? (
38
- <InfoViewer info={info}></InfoViewer>
39
- ) : (
40
- <>Empty</>
41
- )}
42
- </>
36
+ info.push(formatPQGroupItem('Partitions', pqGroup?.Partitions || []));
37
+ info.push(
38
+ formatPQGroupItem(
39
+ 'PQTabletConfig',
40
+ pqGroup?.PQTabletConfig || {PartitionConfig: {LifetimeSeconds: 0}},
41
+ ),
43
42
  );
43
+
44
+ return <InfoViewer title={'Changefeed'} info={info} />;
44
45
  };
@@ -9,9 +9,7 @@ interface PersQueueGrouopInfoProps {
9
9
 
10
10
  export const PersQueueGroupInfo = ({data}: PersQueueGrouopInfoProps) => {
11
11
  if (!data) {
12
- return (
13
- <div className="error">No PersQueueGroup data</div>
14
- );
12
+ return <div className="error">No PersQueueGroup data</div>;
15
13
  }
16
14
 
17
15
  const pqGroup = data.PathDescription?.PersQueueGroup;
@@ -20,15 +18,12 @@ export const PersQueueGroupInfo = ({data}: PersQueueGrouopInfoProps) => {
20
18
  info.push(formatCommonItem('PathType', data.PathDescription?.Self?.PathType));
21
19
 
22
20
  info.push(formatPQGroupItem('Partitions', pqGroup?.Partitions || []));
23
- info.push(formatPQGroupItem('PQTabletConfig', pqGroup?.PQTabletConfig || {PartitionConfig: {LifetimeSeconds: 0}}));
24
-
25
- return (
26
- <>
27
- {info.length ? (
28
- <InfoViewer info={info}></InfoViewer>
29
- ) : (
30
- <>Empty</>
31
- )}
32
- </>
21
+ info.push(
22
+ formatPQGroupItem(
23
+ 'PQTabletConfig',
24
+ pqGroup?.PQTabletConfig || {PartitionConfig: {LifetimeSeconds: 0}},
25
+ ),
33
26
  );
27
+
28
+ return <>{info.length ? <InfoViewer info={info}></InfoViewer> : <>Empty</>}</>;
34
29
  };
@@ -17,9 +17,7 @@ interface TableIndexInfoProps {
17
17
 
18
18
  export const TableIndexInfo = ({data}: TableIndexInfoProps) => {
19
19
  if (!data) {
20
- return (
21
- <div className="error">no index data</div>
22
- );
20
+ return <div className="error">no index data</div>;
23
21
  }
24
22
 
25
23
  const TableIndex = data.PathDescription?.TableIndex;
@@ -32,13 +30,5 @@ export const TableIndexInfo = ({data}: TableIndexInfoProps) => {
32
30
  }
33
31
  }
34
32
 
35
- return (
36
- <>
37
- {info.length ? (
38
- <InfoViewer info={info}></InfoViewer>
39
- ) : (
40
- <>Empty</>
41
- )}
42
- </>
43
- );
33
+ return <>{info.length ? <InfoViewer info={info}></InfoViewer> : <>Empty</>}</>;
44
34
  };
@@ -3,10 +3,7 @@ import type {TEvDescribeSchemeResult, TCdcStreamDescription} from '../../../type
3
3
  import {InfoViewer, InfoViewerItem} from '..';
4
4
  import {formatCdcStreamItem, formatCommonItem} from '../formatters';
5
5
 
6
- const DISPLAYED_FIELDS: Set<keyof TCdcStreamDescription> = new Set([
7
- 'Mode',
8
- 'Format',
9
- ]);
6
+ const DISPLAYED_FIELDS: Set<keyof TCdcStreamDescription> = new Set(['Mode', 'Format']);
10
7
 
11
8
  interface CDCStreamOverviewProps {
12
9
  data?: TEvDescribeSchemeResult;
@@ -14,9 +11,7 @@ interface CDCStreamOverviewProps {
14
11
 
15
12
  export const CDCStreamOverview = ({data}: CDCStreamOverviewProps) => {
16
13
  if (!data) {
17
- return (
18
- <div className="error">No CDC Stream data</div>
19
- );
14
+ return <div className="error">No CDC Stream data</div>;
20
15
  }
21
16
 
22
17
  const TableIndex = data.PathDescription?.CdcStreamDescription;
@@ -32,13 +27,5 @@ export const CDCStreamOverview = ({data}: CDCStreamOverviewProps) => {
32
27
  }
33
28
  }
34
29
 
35
- return (
36
- <>
37
- {info.length ? (
38
- <InfoViewer info={info}></InfoViewer>
39
- ) : (
40
- <>Empty</>
41
- )}
42
- </>
43
- );
30
+ return <>{info.length ? <InfoViewer info={info}></InfoViewer> : <>Empty</>}</>;
44
31
  };
@@ -9,9 +9,7 @@ interface PersQueueGroupOverviewProps {
9
9
 
10
10
  export const PersQueueGroupOverview = ({data}: PersQueueGroupOverviewProps) => {
11
11
  if (!data) {
12
- return (
13
- <div className="error">No PersQueueGroup data</div>
14
- );
12
+ return <div className="error">No PersQueueGroup data</div>;
15
13
  }
16
14
 
17
15
  const pqGroup = data.PathDescription?.PersQueueGroup;
@@ -21,15 +19,12 @@ export const PersQueueGroupOverview = ({data}: PersQueueGroupOverviewProps) => {
21
19
  info.push(formatCommonItem('CreateStep', data.PathDescription?.Self?.CreateStep));
22
20
 
23
21
  info.push(formatPQGroupItem('Partitions', pqGroup?.Partitions || []));
24
- info.push(formatPQGroupItem('PQTabletConfig', pqGroup?.PQTabletConfig || {PartitionConfig: {LifetimeSeconds: 0}}));
25
-
26
- return (
27
- <>
28
- {info.length ? (
29
- <InfoViewer info={info}></InfoViewer>
30
- ) : (
31
- <>Empty</>
32
- )}
33
- </>
22
+ info.push(
23
+ formatPQGroupItem(
24
+ 'PQTabletConfig',
25
+ pqGroup?.PQTabletConfig || {PartitionConfig: {LifetimeSeconds: 0}},
26
+ ),
34
27
  );
28
+
29
+ return <>{info.length ? <InfoViewer info={info}></InfoViewer> : <>Empty</>}</>;
35
30
  };
@@ -1,12 +1,12 @@
1
- import type {ReactNode} from "react";
1
+ import type {ReactNode} from 'react';
2
2
 
3
3
  type LabelMap<T> = {
4
4
  [label in keyof T]?: string;
5
- }
5
+ };
6
6
 
7
7
  type ValueFormatters<T> = {
8
8
  [label in keyof T]?: (value: T[label]) => ReactNode;
9
- }
9
+ };
10
10
 
11
11
  function formatLabel<Shape>(label: keyof Shape, map: LabelMap<Shape>) {
12
12
  return map[label] ?? label;
@@ -25,9 +25,9 @@ function formatValue<Shape, Key extends keyof Shape>(
25
25
  }
26
26
 
27
27
  interface CreateInfoFormatterOptions<Shape> {
28
- values?: ValueFormatters<Shape>,
29
- labels?: LabelMap<Shape>,
30
- defaultValueFormatter?: (value: Shape[keyof Shape]) => ReactNode,
28
+ values?: ValueFormatters<Shape>;
29
+ labels?: LabelMap<Shape>;
30
+ defaultValueFormatter?: (value: Shape[keyof Shape]) => ReactNode;
31
31
  }
32
32
 
33
33
  export function createInfoFormatter<Shape extends Record<string, any>>({
@@ -1,5 +1,8 @@
1
- @import '../../styles/mixins.scss';
1
+ .ydb-loader {
2
+ display: flex;
3
+ flex: 1 1 auto;
4
+ justify-content: center;
5
+ align-items: center;
2
6
 
3
- .kv-loader {
4
- @include loader();
7
+ height: 100%;
5
8
  }
@@ -3,14 +3,16 @@ import {Loader as KitLoader, LoaderSize} from '@gravity-ui/uikit';
3
3
 
4
4
  import './Loader.scss';
5
5
 
6
- const b = cn('kv-loader');
6
+ const b = cn('ydb-loader');
7
7
 
8
- function Loader({size = 'l'}: {size?: LoaderSize}) {
8
+ interface LoaderProps {
9
+ size?: LoaderSize;
10
+ }
11
+
12
+ export const Loader = ({size = 'm'}: LoaderProps) => {
9
13
  return (
10
14
  <div className={b()}>
11
15
  <KitLoader size={size} />
12
16
  </div>
13
17
  );
14
- }
15
-
16
- export default Loader;
18
+ };
@@ -0,0 +1 @@
1
+ export * from './Loader';
@@ -0,0 +1,21 @@
1
+ import {RadioButton} from '@gravity-ui/uikit';
2
+
3
+ import {NodesUptimeFilterValues, NodesUptimeFilterTitles} from '../../utils/nodes';
4
+
5
+ interface UptimeFilterProps {
6
+ value: keyof typeof NodesUptimeFilterValues;
7
+ onChange: (value: string) => void;
8
+ }
9
+
10
+ export const UptimeFilter = ({value, onChange}: UptimeFilterProps) => {
11
+ return (
12
+ <RadioButton value={value} onUpdate={onChange}>
13
+ <RadioButton.Option value={NodesUptimeFilterValues.All}>
14
+ {NodesUptimeFilterTitles[NodesUptimeFilterValues.All]}
15
+ </RadioButton.Option>
16
+ <RadioButton.Option value={NodesUptimeFilterValues.SmallUptime}>
17
+ {NodesUptimeFilterTitles[NodesUptimeFilterValues.SmallUptime]}
18
+ </RadioButton.Option>
19
+ </RadioButton>
20
+ );
21
+ };
@@ -0,0 +1 @@
1
+ export * from './UptimeFilter';
@@ -45,6 +45,7 @@
45
45
  }
46
46
 
47
47
  &__node-page-wrapper {
48
+ height: 100%;
48
49
  padding: 20px;
49
50
  }
50
51
  }
@@ -12,7 +12,7 @@ import Tablets from '../Tablets/Tablets';
12
12
  import Storage from '../Storage/Storage';
13
13
  import NodeOverview from './NodeOverview/NodeOverview';
14
14
  import NodeStructure from './NodeStructure/NodeStructure';
15
- import Loader from '../../components/Loader/Loader';
15
+ import {Loader} from '../../components/Loader';
16
16
  import {BasicNodeViewer} from '../../components/BasicNodeViewer';
17
17
 
18
18
  import {getNodeInfo, resetNode} from '../../store/reducers/node';
@@ -132,12 +132,7 @@ function Node(props: NodeProps) {
132
132
  }
133
133
 
134
134
  case OVERVIEW: {
135
- return (
136
- <NodeOverview
137
- node={node}
138
- className={b('overview-wrapper')}
139
- />
140
- );
135
+ return <NodeOverview node={node} className={b('overview-wrapper')} />;
141
136
  }
142
137
 
143
138
  case STRUCTURE: {
@@ -155,7 +150,7 @@ function Node(props: NodeProps) {
155
150
  };
156
151
 
157
152
  if (loading && !wasLoaded) {
158
- return <Loader />;
153
+ return <Loader size="l" />;
159
154
  } else if (error) {
160
155
  return <div>{error.statusText}</div>;
161
156
  } else {
@@ -10,12 +10,6 @@
10
10
  @include flex-container();
11
11
  @include body2-typography();
12
12
 
13
- &__loader {
14
- display: flex;
15
- flex-grow: 1;
16
- justify-content: center;
17
- }
18
-
19
13
  &__pdisk {
20
14
  display: flex;
21
15
  flex-direction: column;
@@ -6,7 +6,7 @@ import _ from 'lodash';
6
6
  import cn from 'bem-cn-lite';
7
7
 
8
8
  import {PDisk} from './Pdisk';
9
- import Loader from '../.././../components/Loader/Loader';
9
+ import {Loader} from '../.././../components/Loader';
10
10
 
11
11
  import {getNodeStructure, selectNodeStructure} from '../../../store/reducers/node';
12
12
 
@@ -9,17 +9,19 @@ import {Loader, TextInput, Label} from '@gravity-ui/uikit';
9
9
  import ProblemFilter, {problemFilterType} from '../../components/ProblemFilter/ProblemFilter';
10
10
  import {Illustration} from '../../components/Illustration';
11
11
  import {AccessDenied} from '../../components/Errors/403';
12
+ import {UptimeFilter} from '../../components/UptimeFIlter';
12
13
 
13
14
  import {hideTooltip, showTooltip} from '../../store/reducers/tooltip';
14
15
  import {withSearch} from '../../HOCS';
15
16
  import {AUTO_RELOAD_INTERVAL, ALL, DEFAULT_TABLE_SETTINGS} from '../../utils/constants';
16
17
  import {getFilteredNodes} from '../../store/reducers/clusterNodes';
17
- import {getNodes} from '../../store/reducers/nodes';
18
+ import {getNodes, setNodesUptimeFilter} from '../../store/reducers/nodes';
18
19
  import {changeFilter} from '../../store/reducers/settings';
19
20
  import {setHeader} from '../../store/reducers/header';
20
21
  import routes, {CLUSTER_PAGES, createHref} from '../../routes';
21
22
  import {calcUptime} from '../../utils';
22
23
  import {getNodesColumns} from '../../utils/getNodesColumns';
24
+ import {NodesUptimeFilterValues} from '../../utils/nodes';
23
25
 
24
26
  import './Nodes.scss';
25
27
 
@@ -44,12 +46,14 @@ class Nodes extends React.Component {
44
46
  hideTooltip: PropTypes.func,
45
47
  searchQuery: PropTypes.string,
46
48
  handleSearchQuery: PropTypes.func,
47
- filter: problemFilterType,
49
+ problemFilter: problemFilterType,
48
50
  changeFilter: PropTypes.func,
49
51
  setHeader: PropTypes.func,
50
52
  className: PropTypes.string,
51
53
  singleClusterMode: PropTypes.bool,
52
54
  additionalNodesInfo: PropTypes.object,
55
+ nodesUptimeFilter: PropTypes.string,
56
+ setNodesUptimeFilter: PropTypes.func,
53
57
  };
54
58
 
55
59
  componentDidMount() {
@@ -73,12 +77,16 @@ class Nodes extends React.Component {
73
77
  this.props.handleSearchQuery(search);
74
78
  };
75
79
 
76
- handleFilterChange = (filter) => {
77
- this.props.changeFilter(filter);
80
+ handleProblemFilterChange = (value) => {
81
+ this.props.changeFilter(value);
82
+ };
83
+
84
+ handleUptimeFilterChange = (value) => {
85
+ this.props.setNodesUptimeFilter(value);
78
86
  };
79
87
 
80
88
  renderControls() {
81
- const {searchQuery, filter, nodes} = this.props;
89
+ const {nodes, searchQuery, problemFilter, nodesUptimeFilter} = this.props;
82
90
 
83
91
  return (
84
92
  <div className={b('controls')}>
@@ -90,7 +98,8 @@ class Nodes extends React.Component {
90
98
  hasClear
91
99
  autoFocus
92
100
  />
93
- <ProblemFilter value={filter} onChange={this.handleFilterChange} />
101
+ <ProblemFilter value={problemFilter} onChange={this.handleProblemFilterChange} />
102
+ <UptimeFilter value={nodesUptimeFilter} onChange={this.handleUptimeFilterChange} />
94
103
  <Label theme="info" size="m">{`Nodes: ${nodes?.length}`}</Label>
95
104
  </div>
96
105
  );
@@ -99,7 +108,8 @@ class Nodes extends React.Component {
99
108
  renderTable = () => {
100
109
  const {
101
110
  nodes = [],
102
- filter,
111
+ problemFilter,
112
+ nodesUptimeFilter,
103
113
  searchQuery,
104
114
  showTooltip,
105
115
  hideTooltip,
@@ -126,7 +136,7 @@ class Nodes extends React.Component {
126
136
  }));
127
137
 
128
138
  if (preparedNodes.length === 0) {
129
- if (filter !== ALL) {
139
+ if (problemFilter !== ALL || nodesUptimeFilter !== NodesUptimeFilterValues.All) {
130
140
  return <Illustration name="thumbsUp" width="200" />;
131
141
  }
132
142
  }
@@ -177,7 +187,7 @@ class Nodes extends React.Component {
177
187
  }
178
188
 
179
189
  const mapStateToProps = (state) => {
180
- const {wasLoaded, loading, error} = state.nodes;
190
+ const {wasLoaded, loading, error, nodesUptimeFilter} = state.nodes;
181
191
 
182
192
  const nodes = getFilteredNodes(state);
183
193
  return {
@@ -186,7 +196,8 @@ const mapStateToProps = (state) => {
186
196
  wasLoaded,
187
197
  loading,
188
198
  error,
189
- filter: state.settings.problemFilter,
199
+ problemFilter: state.settings.problemFilter,
200
+ nodesUptimeFilter,
190
201
  };
191
202
  };
192
203
 
@@ -196,6 +207,7 @@ const mapDispatchToProps = {
196
207
  showTooltip,
197
208
  changeFilter,
198
209
  setHeader,
210
+ setNodesUptimeFilter,
199
211
  };
200
212
 
201
213
  export default withSearch(connect(mapStateToProps, mapDispatchToProps)(Nodes));