ydb-embedded-ui 4.3.0 → 4.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/containers/App/Content.js +2 -8
  3. package/dist/containers/AsideNavigation/AsideNavigation.tsx +1 -1
  4. package/dist/containers/Cluster/Cluster.scss +4 -0
  5. package/dist/containers/Cluster/Cluster.tsx +14 -8
  6. package/dist/{components → containers}/ClusterInfo/ClusterInfo.scss +39 -0
  7. package/dist/containers/ClusterInfo/ClusterInfo.tsx +207 -0
  8. package/dist/containers/ClusterInfo/utils.ts +13 -0
  9. package/dist/containers/Header/Header.tsx +9 -16
  10. package/dist/containers/Nodes/Nodes.tsx +4 -6
  11. package/dist/containers/Storage/DiskStateProgressBar/DiskStateProgressBar.tsx +2 -3
  12. package/dist/containers/Tenant/Diagnostics/Partitions/Headers/Headers.tsx +4 -4
  13. package/dist/containers/Tenant/Diagnostics/Partitions/Partitions.scss +4 -0
  14. package/dist/containers/Tenant/Diagnostics/Partitions/Partitions.tsx +2 -2
  15. package/dist/containers/Tenant/Diagnostics/Partitions/PartitionsControls/PartitionsControls.tsx +20 -26
  16. package/dist/containers/Tenant/Diagnostics/Partitions/i18n/en.json +1 -1
  17. package/dist/containers/Tenant/Diagnostics/Partitions/i18n/ru.json +1 -1
  18. package/dist/containers/UserSettings/Setting.tsx +82 -0
  19. package/dist/containers/UserSettings/UserSettings.tsx +61 -99
  20. package/dist/containers/Versions/GroupedNodesTree/GroupedNodesTree.scss +59 -0
  21. package/dist/containers/Versions/GroupedNodesTree/GroupedNodesTree.tsx +98 -0
  22. package/dist/containers/Versions/NodesTable/NodesTable.tsx +150 -0
  23. package/dist/containers/Versions/NodesTreeTitle/NodesTreeTitle.scss +55 -0
  24. package/dist/containers/Versions/NodesTreeTitle/NodesTreeTitle.tsx +62 -0
  25. package/dist/containers/Versions/Versions.scss +32 -0
  26. package/dist/containers/Versions/Versions.tsx +121 -0
  27. package/dist/containers/Versions/groupNodes.ts +124 -0
  28. package/dist/containers/Versions/types.ts +16 -0
  29. package/dist/routes.ts +0 -6
  30. package/dist/services/api.ts +3 -0
  31. package/dist/store/reducers/cluster/cluster.ts +4 -0
  32. package/dist/store/reducers/cluster/types.ts +3 -2
  33. package/dist/store/reducers/clusterNodes/clusterNodes.tsx +64 -0
  34. package/dist/store/reducers/clusterNodes/types.ts +22 -0
  35. package/dist/store/reducers/index.ts +2 -8
  36. package/dist/store/reducers/partitions/partitions.ts +2 -2
  37. package/dist/store/reducers/partitions/types.ts +1 -1
  38. package/dist/types/additionalProps.ts +5 -0
  39. package/dist/types/versions.ts +9 -0
  40. package/dist/utils/constants.ts +0 -11
  41. package/dist/utils/hooks/useSetting.ts +5 -3
  42. package/dist/utils/versions/getVersionsColors.ts +98 -0
  43. package/dist/utils/versions/index.ts +3 -0
  44. package/dist/utils/versions/parseNodesToVersionsValues.ts +28 -0
  45. package/dist/utils/versions/parseVersion.ts +23 -0
  46. package/package.json +1 -1
  47. package/dist/components/ClusterInfo/ClusterInfo.tsx +0 -239
  48. package/dist/components/FullGroupViewer/FullGroupViewer.js +0 -147
  49. package/dist/components/FullGroupViewer/FullGroupViewer.scss +0 -35
  50. package/dist/components/GroupTreeViewer/GroupTreeViewer.js +0 -87
  51. package/dist/components/GroupTreeViewer/GroupTreeViewer.scss +0 -16
  52. package/dist/components/GroupViewer/GroupViewer.js +0 -100
  53. package/dist/components/GroupViewer/GroupViewer.scss +0 -45
  54. package/dist/components/PDiskViewer/PDiskViewer.js +0 -79
  55. package/dist/components/PDiskViewer/PDiskViewer.scss +0 -46
  56. package/dist/components/TabletsViewer/TabletsViewer.js +0 -44
  57. package/dist/components/TabletsViewer/TabletsViewer.scss +0 -40
  58. package/dist/components/VerticalBars/VerticalBars.scss +0 -15
  59. package/dist/components/VerticalBars/VerticalBars.tsx +0 -38
  60. package/dist/components/VerticalBars/index.ts +0 -1
  61. package/dist/containers/Group/Group.js +0 -97
  62. package/dist/containers/Group/Group.scss +0 -6
  63. package/dist/containers/Header/Host/Host.js +0 -66
  64. package/dist/containers/Header/Host/Host.scss +0 -50
  65. package/dist/containers/Pdisk/Pdisk.js +0 -156
  66. package/dist/containers/Pdisk/Pdisk.scss +0 -42
  67. package/dist/containers/Pool/Pool.js +0 -170
  68. package/dist/containers/Pool/Pool.scss +0 -35
  69. package/dist/containers/Vdisk/Vdisk.js +0 -158
  70. package/dist/containers/Vdisk/Vdisk.scss +0 -42
  71. package/dist/containers/VdiskPdiskNode/VdiskPdiskNode.js +0 -526
  72. package/dist/containers/VdiskPdiskNode/VdiskPdiskNode.scss +0 -60
  73. package/dist/store/reducers/group.js +0 -49
  74. package/dist/store/reducers/pdisk.js +0 -51
  75. package/dist/store/reducers/pool.js +0 -42
  76. package/dist/store/reducers/vdisk.js +0 -49
@@ -1,100 +0,0 @@
1
- import React from 'react';
2
- import PropTypes from 'prop-types';
3
- import cn from 'bem-cn-lite';
4
-
5
- import EntityStatus from '../EntityStatus/EntityStatus';
6
- import ProgressViewer from '../ProgressViewer/ProgressViewer';
7
-
8
- import routes, {createHref} from '../../routes';
9
- import {formatStorageValues, formatThroughput, formatIOPS} from '../../utils';
10
-
11
- import './GroupViewer.scss';
12
-
13
- const b = cn('group-viewer');
14
-
15
- class GroupViewer extends React.Component {
16
- static propTypes = {
17
- group: PropTypes.object.isRequired,
18
- className: PropTypes.string,
19
- };
20
-
21
- static defaultProps = {
22
- className: '',
23
- };
24
-
25
- render() {
26
- const {group, className} = this.props;
27
- const {
28
- GroupID = 'no id',
29
- Overall = 'gray',
30
- VDisks,
31
- ErasureSpecies,
32
- Latency = 'gray',
33
- AcquiredIOPS,
34
- AcquiredSize,
35
- AcquiredThroughput,
36
- MaximumIOPS,
37
- MaximumSize,
38
- MaximumThroughput,
39
- } = group;
40
- if (group && Object.keys(group).length) {
41
- return (
42
- <div className={`${b()} ${className}`}>
43
- <div className={b('group')}>
44
- <EntityStatus
45
- name={GroupID}
46
- status={Overall}
47
- path={createHref(routes.group, {id: GroupID})}
48
- className={b('name')}
49
- />
50
- </div>
51
-
52
- <div className={b('latency')}>
53
- <EntityStatus name="Latency" status={Latency} />
54
- </div>
55
-
56
- <div className={b('label')}>{(VDisks && VDisks.length) || 0} Vdisks</div>
57
- <div className={b('label')}>{ErasureSpecies || 'no ErasureSpecies info'}</div>
58
- <div className={b('vdisks')}>
59
- {VDisks?.map((disk) => (
60
- <div key={disk.Guid} className={b('disk-overall')}>
61
- <EntityStatus status={disk.Overall} />
62
- </div>
63
- ))}
64
- </div>
65
-
66
- <div className={b('progress')}>
67
- <ProgressViewer
68
- value={AcquiredSize}
69
- capacity={MaximumSize}
70
- colorizeProgress={true}
71
- formatValues={formatStorageValues}
72
- />
73
- </div>
74
-
75
- <div className={b('progress')}>
76
- <ProgressViewer
77
- value={AcquiredIOPS}
78
- capacity={MaximumIOPS}
79
- colorizeProgress={true}
80
- formatValues={formatIOPS}
81
- />
82
- </div>
83
-
84
- <div className={b('progress')}>
85
- <ProgressViewer
86
- value={AcquiredThroughput}
87
- capacity={MaximumThroughput}
88
- colorizeProgress={true}
89
- formatValues={formatThroughput}
90
- />
91
- </div>
92
- </div>
93
- );
94
- } else {
95
- return <div className={b()}>No data</div>;
96
- }
97
- }
98
- }
99
-
100
- export default GroupViewer;
@@ -1,45 +0,0 @@
1
- .group-viewer {
2
- display: flex;
3
- align-items: center;
4
- &__group {
5
- margin-right: 20px;
6
- }
7
-
8
- &__label {
9
- margin-right: 20px;
10
-
11
- font-size: var(--yc-text-body-1-font-size);
12
-
13
- color: var(--yc-color-text-complementary);
14
- }
15
-
16
- &__name {
17
- display: inline-block;
18
-
19
- text-decoration: none;
20
-
21
- color: var(--yc-color-base-special);
22
-
23
- &:before {
24
- transform: translateY(3px);
25
- }
26
- }
27
-
28
- &__latency {
29
- margin-right: 20px;
30
- }
31
-
32
- &__vdisks {
33
- display: flex;
34
- }
35
-
36
- &__disk-overall {
37
- .entity-status:before {
38
- margin-right: 5px;
39
- }
40
- }
41
-
42
- &__progress {
43
- margin-right: 10px;
44
- }
45
- }
@@ -1,79 +0,0 @@
1
- import React from 'react';
2
- import PropTypes from 'prop-types';
3
- import cn from 'bem-cn-lite';
4
-
5
- import ProgressViewer from '../ProgressViewer/ProgressViewer';
6
- import EntityStatus from '../EntityStatus/EntityStatus';
7
-
8
- import {formatStorageValues} from '../../utils';
9
- import routes, {createHref} from '../../routes';
10
-
11
- import {getDefaultNodePath} from '../../containers/Node/NodePages';
12
-
13
- import './PDiskViewer.scss';
14
-
15
- const b = cn('pdisk-viewer');
16
-
17
- class PDiskViewer extends React.Component {
18
- static propTypes = {
19
- disk: PropTypes.object.isRequired,
20
- className: PropTypes.string,
21
- };
22
-
23
- static defaultProps = {
24
- className: '',
25
- };
26
-
27
- render() {
28
- const {disk, className} = this.props;
29
-
30
- if (disk) {
31
- return (
32
- <div className={`${b()} ${className}`}>
33
- {disk && (
34
- <div className={b('item')}>
35
- <EntityStatus
36
- status={disk.Realtime}
37
- path={createHref(
38
- routes.pdisk,
39
- {id: disk.PDiskId},
40
- {node_id: disk.NodeId},
41
- )}
42
- label="PDiskID"
43
- name={disk.PDiskId}
44
- />
45
- </div>
46
- )}
47
-
48
- {disk && (
49
- <div className={b('item')}>
50
- <EntityStatus
51
- status={'green'}
52
- label="NodeID"
53
- path={getDefaultNodePath(disk.NodeId)}
54
- name={disk.NodeId}
55
- />
56
- </div>
57
- )}
58
-
59
- {disk && (
60
- <ProgressViewer
61
- value={disk.TotalSize - disk.AvailableSize || 0}
62
- capacity={disk.TotalSize || 0}
63
- formatValues={formatStorageValues}
64
- colorizeProgress={true}
65
- className={b('size')}
66
- />
67
- )}
68
- <div className={b('item')}>
69
- {disk && <div className={b('label')}>{disk.Path || 'no path'}</div>}
70
- </div>
71
- </div>
72
- );
73
- } else {
74
- return <div className="error">no PDisk data</div>;
75
- }
76
- }
77
- }
78
-
79
- export default PDiskViewer;
@@ -1,46 +0,0 @@
1
- .pdisk-viewer {
2
- display: flex;
3
- align-items: center;
4
-
5
- &__item,
6
- &__size {
7
- margin-right: 24px;
8
-
9
- font-size: var(--yc-text-body-2-font-size);
10
- line-height: 0;
11
-
12
- color: var(--yc-color-text-complementary);
13
- }
14
-
15
- &__item .entity-status {
16
- min-width: 100px;
17
- }
18
-
19
- &__item .entity-status a {
20
- overflow: initial;
21
- }
22
-
23
- &__row {
24
- display: flex;
25
- align-items: center;
26
- }
27
-
28
- &__size {
29
- width: 120px;
30
-
31
- font-size: 10px;
32
-
33
- color: var(--yc-color-text-complementary);
34
- }
35
-
36
- &__label {
37
- margin: 0 5px;
38
- &_link {
39
- display: inline-block;
40
-
41
- text-decoration: none;
42
-
43
- color: var(--yc-color-base-special);
44
- }
45
- }
46
- }
@@ -1,44 +0,0 @@
1
- import React from 'react';
2
- import cn from 'bem-cn-lite';
3
- import PropTypes from 'prop-types';
4
- import {formatNumber} from '../../utils';
5
- import './TabletsViewer.scss';
6
-
7
- import {TABLET_STATES} from '../../utils/constants';
8
-
9
- const b = cn('tablets-viewer');
10
-
11
- const prepareStates = (states) => {
12
- return states.map((state) => {
13
- return {
14
- label: TABLET_STATES[state.VolatileState],
15
- count: formatNumber(state.Count),
16
- };
17
- });
18
- };
19
-
20
- class TabletsViewer extends React.Component {
21
- static propTypes = {
22
- tablets: PropTypes.array,
23
- };
24
- renderTabletInfo = (item, index) => {
25
- return (
26
- <div key={index} className={b('row')}>
27
- <div className={b('tablet-label')}>{item.label}</div>
28
- <span>{item.count}</span>
29
- </div>
30
- );
31
- };
32
- render() {
33
- const {tablets = []} = this.props;
34
- const preparedStates = prepareStates(tablets);
35
-
36
- return (
37
- <div className={b()}>
38
- <div className={b('grid')}>{preparedStates.map(this.renderTabletInfo)}</div>
39
- </div>
40
- );
41
- }
42
- }
43
-
44
- export default TabletsViewer;
@@ -1,40 +0,0 @@
1
- .tablets-viewer {
2
- &__grid {
3
- display: grid;
4
- grid-gap: 8px;
5
-
6
- grid-template-columns: repeat(auto-fill, 125px);
7
- }
8
-
9
- &__row {
10
- display: flex;
11
- align-items: center;
12
-
13
- margin: 0;
14
- }
15
-
16
- &__tablet-label {
17
- min-width: 60px;
18
- margin-right: 20px;
19
-
20
- font-size: var(--yc-text-body-1-font-size);
21
- line-height: 18px;
22
- white-space: nowrap;
23
- text-transform: capitalize;
24
-
25
- color: var(--yc-color-text-hint);
26
-
27
- .yc-root_theme_dark & {
28
- color: var(--yc-color-text-hint);
29
- }
30
- }
31
-
32
- &__title {
33
- margin: 0;
34
- margin-bottom: 16px;
35
-
36
- font-size: var(--yc-text-body-2-font-size);
37
- font-weight: bold;
38
- line-height: 20px;
39
- }
40
- }
@@ -1,15 +0,0 @@
1
- .ydb-bars {
2
- display: flex;
3
- flex-direction: row;
4
- align-items: flex-end;
5
-
6
- height: 20px;
7
-
8
- &__value {
9
- width: 6px;
10
- min-height: 3px;
11
- margin-right: 2px;
12
-
13
- background-color: var(--yc-color-infographics-info-heavy);
14
- }
15
- }
@@ -1,38 +0,0 @@
1
- import cn from 'bem-cn-lite';
2
- import {useMemo} from 'react';
3
-
4
- import './VerticalBars.scss';
5
-
6
- const b = cn('ydb-bars');
7
-
8
- const calculateValuesInPercents = (values: number[]) => {
9
- const max = Math.max(...values);
10
-
11
- if (!max) {
12
- return values;
13
- }
14
-
15
- const res = [];
16
-
17
- for (const value of values) {
18
- res.push((value / max) * 100);
19
- }
20
-
21
- return res;
22
- };
23
-
24
- interface VerticalBarsProps {
25
- values: number[];
26
- }
27
-
28
- export const VerticalBars = ({values}: VerticalBarsProps) => {
29
- const preparedValues = useMemo(() => calculateValuesInPercents(values), [values]);
30
-
31
- const getBars = () => {
32
- return preparedValues.map((value, index) => {
33
- return <div key={index} style={{height: `${value}%`}} className={b('value')} />;
34
- });
35
- };
36
-
37
- return <div className={b()}>{getBars()}</div>;
38
- };
@@ -1 +0,0 @@
1
- export * from './VerticalBars';
@@ -1,97 +0,0 @@
1
- import React from 'react';
2
- import PropTypes from 'prop-types';
3
- import cn from 'bem-cn-lite';
4
- import {connect} from 'react-redux';
5
- import {getGroupInfo, clearStore} from '../../store/reducers/group';
6
- import FullGroupViewer from '../../components/FullGroupViewer/FullGroupViewer';
7
- import {Loader} from '@gravity-ui/uikit';
8
- import {GROUP_AUTO_RELOAD_INTERVAL} from '../../utils/constants';
9
- import './Group.scss';
10
-
11
- const b = cn('group');
12
-
13
- class Group extends React.Component {
14
- static renderLoader() {
15
- return (
16
- <div className={'loader'}>
17
- <Loader size="l" />
18
- </div>
19
- );
20
- }
21
-
22
- static propTypes = {
23
- className: PropTypes.string,
24
- loading: PropTypes.bool,
25
- wasLoaded: PropTypes.bool,
26
- error: PropTypes.bool,
27
- getGroupInfo: PropTypes.func,
28
- clearStore: PropTypes.func,
29
- group: PropTypes.object,
30
- location: PropTypes.object,
31
- match: PropTypes.object,
32
- };
33
-
34
- static defaultProps = {
35
- className: '',
36
- };
37
-
38
- componentDidMount() {
39
- const {id} = this.props.match.params;
40
- this.props.getGroupInfo(id);
41
- this.reloadDescriptor = setInterval(
42
- () => this.props.getGroupInfo(id),
43
- GROUP_AUTO_RELOAD_INTERVAL,
44
- );
45
- }
46
-
47
- componentWillUnmount() {
48
- this.props.clearStore();
49
- clearInterval(this.reloadDescriptor);
50
- }
51
-
52
- renderContent = () => {
53
- const {className, group} = this.props;
54
- return (
55
- <div className={`${b()} ${className}`}>
56
- <FullGroupViewer group={group} />
57
- </div>
58
- );
59
- };
60
-
61
- render() {
62
- const {loading, wasLoaded, error, group} = this.props;
63
-
64
- if (loading && !wasLoaded) {
65
- return Group.renderLoader();
66
- } else if (error) {
67
- return <div>{error.statusText}</div>;
68
- } else if (group) {
69
- return this.renderContent();
70
- } else {
71
- return <div className="error">no data</div>;
72
- }
73
- }
74
- }
75
-
76
- const mapStateToProps = (state) => {
77
- const {data, wasLoaded, loading, error} = state.group;
78
-
79
- let group;
80
- if (data) {
81
- group = data.StoragePools[0].Groups[0];
82
- }
83
-
84
- return {
85
- group,
86
- wasLoaded,
87
- loading,
88
- error,
89
- };
90
- };
91
-
92
- const mapDispatchToProps = {
93
- getGroupInfo,
94
- clearStore,
95
- };
96
-
97
- export default connect(mapStateToProps, mapDispatchToProps)(Group);
@@ -1,6 +0,0 @@
1
- @import '../../styles/mixins';
2
-
3
- .group {
4
- overflow: auto;
5
- @include flex-container();
6
- }
@@ -1,66 +0,0 @@
1
- import React from 'react';
2
- import PropTypes from 'prop-types';
3
- import cn from 'bem-cn-lite';
4
-
5
- import {Link as ExternalLink} from '@gravity-ui/uikit';
6
-
7
- import EntityStatus from '../../../components/EntityStatus/EntityStatus';
8
- import {Tag} from '../../../components/Tag';
9
-
10
- import {calcUptime} from '../../../utils';
11
- import {customBackend} from '../../../store';
12
-
13
- import './Host.scss';
14
-
15
- const b = cn('host');
16
-
17
- export default class Host extends React.Component {
18
- static propTypes = {
19
- host: PropTypes.object,
20
- singleClusterMode: PropTypes.bool,
21
- };
22
-
23
- renderStatus = () => {
24
- const {host} = this.props;
25
-
26
- return (
27
- <div className={b('status')}>
28
- <EntityStatus size="m" status={host.SystemState} name={'Internal viewer'} />
29
- </div>
30
- );
31
- };
32
-
33
- render() {
34
- const {host, backend, singleClusterMode} = this.props;
35
- const uptime = calcUptime(host.StartTime);
36
-
37
- let link = backend + '/internal';
38
-
39
- if (singleClusterMode && !customBackend) {
40
- link = `/internal`;
41
- }
42
-
43
- return (
44
- <div className={b()}>
45
- <div className={b('common')}>
46
- {link ? (
47
- <ExternalLink href={link}>{this.renderStatus()}</ExternalLink>
48
- ) : (
49
- this.renderStatus()
50
- )}
51
- <Tag text={host.DataCenter} />
52
- </div>
53
- <div className={b('info')}>
54
- <div className={b('info-item')}>
55
- <div className={b('label')}>Uptime</div>
56
- <div className={b('value')}>{uptime}</div>
57
- </div>
58
- <div className={b('info-item')}>
59
- <div className={b('label')}>Version</div>
60
- <div className={b('value')}>{host.Version}</div>
61
- </div>
62
- </div>
63
- </div>
64
- );
65
- }
66
- }
@@ -1,50 +0,0 @@
1
- .host {
2
- display: flex;
3
- flex-direction: column;
4
-
5
- &__common {
6
- display: flex;
7
- align-items: center;
8
-
9
- margin-bottom: 4px;
10
- }
11
- &__status {
12
- display: flex;
13
-
14
- margin-right: 15px;
15
-
16
- font-size: var(--yc-text-body-2-font-size);
17
- line-height: var(--yc-text-body-2-line-height);
18
- }
19
- &__info {
20
- display: flex;
21
- align-items: center;
22
- }
23
- &__info-item {
24
- display: flex;
25
-
26
- margin-right: 20px;
27
-
28
- &:last-child {
29
- margin-right: 0;
30
- }
31
- }
32
- &__label {
33
- margin-right: 10px;
34
-
35
- font-size: var(--yc-text-body-1-font-size);
36
- line-height: var(--yc-text-body-1-line-height);
37
-
38
- color: var(--yc-color-text-hint);
39
-
40
- .yc-root_theme_dark & {
41
- color: var(--yc-color-text-hint);
42
- }
43
- }
44
- &__value {
45
- font-size: var(--yc-text-body-1-font-size);
46
- line-height: var(--yc-text-body-1-line-height);
47
-
48
- color: var(--yc-color-text-primary);
49
- }
50
- }