ydb-embedded-ui 3.5.0 → 4.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/dist/components/ClusterInfo/ClusterInfo.tsx +3 -3
  3. package/dist/{containers/Nodes/NodesTable.scss → components/NodeHostWrapper/NodeHostWrapper.scss} +4 -6
  4. package/dist/components/NodeHostWrapper/NodeHostWrapper.tsx +60 -0
  5. package/dist/containers/AsideNavigation/AsideNavigation.tsx +1 -11
  6. package/dist/containers/Header/Header.tsx +1 -1
  7. package/dist/containers/Nodes/getNodesColumns.tsx +7 -46
  8. package/dist/containers/Storage/StorageNodes/StorageNodes.scss +0 -24
  9. package/dist/containers/Storage/StorageNodes/StorageNodes.tsx +2 -39
  10. package/dist/containers/Tenant/QueryEditor/QueriesHistory/QueriesHistory.tsx +3 -3
  11. package/dist/containers/Tenant/QueryEditor/QueryDuration/QueryDuration.scss +8 -0
  12. package/dist/containers/Tenant/QueryEditor/QueryDuration/QueryDuration.tsx +21 -0
  13. package/dist/containers/Tenant/QueryEditor/QueryEditor.js +58 -83
  14. package/dist/containers/Tenant/QueryEditor/QueryEditor.scss +0 -33
  15. package/dist/containers/Tenant/QueryEditor/QueryEditorControls/OldQueryEditorControls.tsx +83 -0
  16. package/dist/containers/Tenant/QueryEditor/QueryEditorControls/QueryEditorControls.scss +57 -0
  17. package/dist/containers/Tenant/QueryEditor/QueryEditorControls/QueryEditorControls.tsx +84 -0
  18. package/dist/containers/Tenant/QueryEditor/QueryEditorControls/shared.ts +23 -0
  19. package/dist/containers/Tenant/QueryEditor/QueryExplain/QueryExplain.js +12 -23
  20. package/dist/containers/Tenant/QueryEditor/QueryResult/QueryResult.js +4 -6
  21. package/dist/containers/Tenant/QueryEditor/i18n/en.json +3 -0
  22. package/dist/containers/Tenant/QueryEditor/i18n/index.ts +11 -0
  23. package/dist/containers/Tenant/QueryEditor/i18n/ru.json +3 -0
  24. package/dist/containers/Tenants/Tenants.js +1 -1
  25. package/dist/containers/UserSettings/UserSettings.tsx +30 -1
  26. package/dist/services/api.ts +383 -0
  27. package/dist/store/reducers/{cluster.js → cluster/cluster.ts} +9 -14
  28. package/dist/store/reducers/cluster/types.ts +13 -0
  29. package/dist/store/reducers/executeQuery.ts +12 -37
  30. package/dist/store/reducers/executeTopQueries.ts +2 -2
  31. package/dist/store/reducers/{explainQuery.js → explainQuery.ts} +44 -59
  32. package/dist/store/reducers/index.ts +5 -4
  33. package/dist/store/reducers/settings.js +19 -17
  34. package/dist/store/reducers/{tenants.js → tenants/tenants.ts} +14 -9
  35. package/dist/store/reducers/tenants/types.ts +17 -0
  36. package/dist/store/utils.ts +3 -2
  37. package/dist/types/api/acl.ts +25 -0
  38. package/dist/types/api/cluster.ts +3 -0
  39. package/dist/types/api/compute.ts +5 -3
  40. package/dist/types/api/error.ts +14 -0
  41. package/dist/types/api/netInfo.ts +48 -0
  42. package/dist/types/api/nodes.ts +5 -3
  43. package/dist/types/api/pdisk.ts +11 -2
  44. package/dist/types/api/query.ts +226 -117
  45. package/dist/types/api/storage.ts +5 -3
  46. package/dist/types/api/tenant.ts +18 -3
  47. package/dist/types/api/vdisk.ts +10 -2
  48. package/dist/types/api/whoami.ts +19 -0
  49. package/dist/types/store/executeQuery.ts +4 -8
  50. package/dist/types/store/explainQuery.ts +38 -0
  51. package/dist/types/store/query.ts +23 -3
  52. package/dist/types/window.d.ts +5 -0
  53. package/dist/utils/constants.ts +2 -1
  54. package/dist/utils/error.ts +25 -0
  55. package/dist/utils/hooks/useTypedSelector.ts +2 -2
  56. package/dist/utils/index.js +0 -49
  57. package/dist/utils/nodes.ts +3 -1
  58. package/dist/utils/prepareQueryExplain.ts +7 -24
  59. package/dist/utils/query.test.ts +153 -231
  60. package/dist/utils/query.ts +44 -78
  61. package/dist/utils/timeParsers/i18n/en.json +9 -9
  62. package/dist/utils/timeParsers/i18n/ru.json +9 -9
  63. package/dist/utils/timeParsers/parsers.ts +9 -0
  64. package/dist/utils/utils.js +1 -2
  65. package/package.json +1 -1
  66. package/dist/services/api.d.ts +0 -86
  67. package/dist/services/api.js +0 -278
package/CHANGELOG.md CHANGED
@@ -1,5 +1,39 @@
1
1
  # Changelog
2
2
 
3
+ ## [4.1.0](https://github.com/ydb-platform/ydb-embedded-ui/compare/v4.0.0...v4.1.0) (2023-05-10)
4
+
5
+
6
+ ### Features
7
+
8
+ * **Navigation:** remove legacy navigation setting support ([8544f11](https://github.com/ydb-platform/ydb-embedded-ui/commit/8544f114255ba44834d38cd9e709450c49e4a96a))
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * disable link and popover for unavailable nodes ([990a9fa](https://github.com/ydb-platform/ydb-embedded-ui/commit/990a9fa42a7133a6c40d07e11c3518240e18b4a9))
14
+
15
+ ## [4.0.0](https://github.com/ydb-platform/ydb-embedded-ui/compare/v3.5.0...v4.0.0) (2023-04-28)
16
+
17
+
18
+ ### ⚠ BREAKING CHANGES
19
+
20
+ * app no longer parses query responses from older ydb versions
21
+ * v0.1 explain plans are no longer rendered
22
+
23
+ ### Features
24
+
25
+ * enable explain-script parsing, remove deprecated code ([5c6e9a2](https://github.com/ydb-platform/ydb-embedded-ui/commit/5c6e9a21026ea9eb3e32650e6fdda89c7900e7e6))
26
+ * **QueryEditor:** add explain query modes ([39ad943](https://github.com/ydb-platform/ydb-embedded-ui/commit/39ad9434c1622e22901e6cc1af1568e0edf6b434))
27
+ * **QueryEditor:** display query duration ([967f102](https://github.com/ydb-platform/ydb-embedded-ui/commit/967f10296d2362709654172ed7318509286efc78))
28
+ * remove support for explain v0.1 ([c8741a6](https://github.com/ydb-platform/ydb-embedded-ui/commit/c8741a69b82053185a07c7ba563455d4f28ecdce))
29
+
30
+
31
+ ### Bug Fixes
32
+
33
+ * **query:** correctly process NetworkError on actions failure ([cf5bd6c](https://github.com/ydb-platform/ydb-embedded-ui/commit/cf5bd6c5c4c2972fec93b2dc9135c92c639fa5f9))
34
+ * **QueryExplain:** do not request ast when missing ([54cf151](https://github.com/ydb-platform/ydb-embedded-ui/commit/54cf151452e17256173736450f5727085ea591ff))
35
+ * **QueryExplain:** request AST if it is empty ([d028b4e](https://github.com/ydb-platform/ydb-embedded-ui/commit/d028b4ed08a98281baff81683204f1cbc1c20c37))
36
+
3
37
  ## [3.5.0](https://github.com/ydb-platform/ydb-embedded-ui/compare/v3.4.5...v3.5.0) (2023-04-18)
4
38
 
5
39
 
@@ -15,7 +15,7 @@ import {Tablet} from '../Tablet';
15
15
  //@ts-ignore
16
16
  import {hideTooltip, showTooltip} from '../../store/reducers/tooltip';
17
17
  //@ts-ignore
18
- import {getClusterInfo} from '../../store/reducers/cluster';
18
+ import {getClusterInfo} from '../../store/reducers/cluster/cluster';
19
19
  //@ts-ignore
20
20
  import {clusterName, backend, customBackend} from '../../store';
21
21
 
@@ -68,6 +68,8 @@ class ClusterInfo extends React.Component<ClusterInfoProps> {
68
68
  return 0;
69
69
  }
70
70
 
71
+ private autofetcher: any;
72
+
71
73
  componentDidMount() {
72
74
  const {setHeader} = this.props;
73
75
  setHeader([
@@ -107,8 +109,6 @@ class ClusterInfo extends React.Component<ClusterInfoProps> {
107
109
  return <div className={b(null, className)}>{helper || this.renderContent()}</div>;
108
110
  }
109
111
 
110
- private autofetcher: any;
111
-
112
112
  private getInfo() {
113
113
  const {cluster = {}, additionalClusterInfo = [], singleClusterMode} = this.props;
114
114
  const {StorageTotal, StorageUsed} = cluster;
@@ -1,12 +1,10 @@
1
- .ydb-nodes-table {
2
- &__host-field-wrapper {
3
- display: flex;
4
- }
1
+ .ydb-node-host-wrapper {
2
+ display: flex;
5
3
 
6
4
  &__host-wrapper {
7
5
  display: flex;
8
6
 
9
- max-width: 330px;
7
+ width: 330px;
10
8
  }
11
9
 
12
10
  &__host {
@@ -21,7 +19,7 @@
21
19
  }
22
20
 
23
21
  .data-table__row:hover {
24
- .ydb-nodes-table__external-button {
22
+ .ydb-node-host-wrapper__external-button {
25
23
  display: inline-flex;
26
24
  }
27
25
  }
@@ -0,0 +1,60 @@
1
+ import block from 'bem-cn-lite';
2
+
3
+ import {Button, Popover, PopoverBehavior} from '@gravity-ui/uikit';
4
+
5
+ import type {INodesPreparedEntity} from '../../types/store/nodes';
6
+ import {getDefaultNodePath} from '../../containers/Node/NodePages';
7
+ import {isUnavailableNode, NodeAddress} from '../../utils/nodes';
8
+
9
+ import EntityStatus from '../EntityStatus/EntityStatus';
10
+ import {NodeEndpointsTooltip} from '../Tooltips/NodeEndpointsTooltip/NodeEndpointsTooltip';
11
+ import {IconWrapper} from '../Icon';
12
+
13
+ import './NodeHostWrapper.scss';
14
+
15
+ const b = block('ydb-node-host-wrapper');
16
+
17
+ interface NodeHostWrapperProps {
18
+ node: INodesPreparedEntity;
19
+ getNodeRef?: (node?: NodeAddress) => string;
20
+ }
21
+
22
+ export const NodeHostWrapper = ({node, getNodeRef}: NodeHostWrapperProps) => {
23
+ if (!node.Host) {
24
+ return <span>—</span>;
25
+ }
26
+
27
+ const isNodeAvailable = !isUnavailableNode(node);
28
+ const nodeRef = isNodeAvailable && getNodeRef ? getNodeRef(node) + 'internal' : undefined;
29
+
30
+ return (
31
+ <div className={b()}>
32
+ <Popover
33
+ disabled={!isNodeAvailable}
34
+ content={<NodeEndpointsTooltip data={node} />}
35
+ placement={['top', 'bottom']}
36
+ behavior={PopoverBehavior.Immediate}
37
+ >
38
+ <div className={b('host-wrapper')}>
39
+ <EntityStatus
40
+ name={node.Host}
41
+ status={node.SystemState}
42
+ path={isNodeAvailable ? getDefaultNodePath(node.NodeId) : undefined}
43
+ hasClipboardButton
44
+ className={b('host')}
45
+ />
46
+ {nodeRef && (
47
+ <Button
48
+ size="s"
49
+ href={nodeRef}
50
+ className={b('external-button')}
51
+ target="_blank"
52
+ >
53
+ <IconWrapper name="external" />
54
+ </Button>
55
+ )}
56
+ </div>
57
+ </Popover>
58
+ </div>
59
+ );
60
+ };
@@ -1,4 +1,4 @@
1
- import React, {useEffect, useState} from 'react';
1
+ import React, {useState} from 'react';
2
2
  import {connect} from 'react-redux';
3
3
  import {useLocation} from 'react-router';
4
4
  import {useHistory} from 'react-router-dom';
@@ -170,16 +170,6 @@ function AsideNavigation(props: AsideNavigationProps) {
170
170
  props.setSettingValue(ASIDE_HEADER_COMPACT_KEY, JSON.stringify(compact));
171
171
  };
172
172
 
173
- // navigation managed its compact state internally before, and its approach is not compatible with settings
174
- // to migrate, save the incoming value again; save only `false` because `true` is the default value
175
- // assume it is safe to remove this code block if it is at least a few months old
176
- // there a two of these, search for a similar comment
177
- useEffect(() => {
178
- if (props.compact === false) {
179
- setIsCompact(props.compact);
180
- }
181
- }, []); // eslint-disable-line react-hooks/exhaustive-deps
182
-
183
173
  const menuItems: AsideHeaderMenuItem[] = React.useMemo(() => {
184
174
  const {pathname} = location;
185
175
  const isClusterPage = pathname === '/cluster';
@@ -8,7 +8,7 @@ import Divider from '../../components/Divider/Divider';
8
8
  import {Icon} from '../../components/Icon';
9
9
 
10
10
  import {clusterName as clusterNameLocation, backend, customBackend} from '../../store';
11
- import {getClusterInfo} from '../../store/reducers/cluster';
11
+ import {getClusterInfo} from '../../store/reducers/cluster/cluster';
12
12
  import {getHostInfo} from '../../store/reducers/host';
13
13
  import {HeaderItemType} from '../../store/reducers/header';
14
14
 
@@ -1,29 +1,22 @@
1
- import cn from 'bem-cn-lite';
2
1
  import DataTable, {Column} from '@gravity-ui/react-data-table';
3
- import {Button, Popover, PopoverBehavior} from '@gravity-ui/uikit';
2
+ import {Popover} from '@gravity-ui/uikit';
4
3
 
5
- import {IconWrapper} from '../../components/Icon';
6
- import EntityStatus from '../../components/EntityStatus/EntityStatus';
7
4
  import PoolsGraph from '../../components/PoolsGraph/PoolsGraph';
8
5
  import ProgressViewer from '../../components/ProgressViewer/ProgressViewer';
9
6
  import {TabletsStatistic} from '../../components/TabletsStatistic';
10
- import {NodeEndpointsTooltip} from '../../components/Tooltips/NodeEndpointsTooltip/NodeEndpointsTooltip';
7
+ import {NodeHostWrapper} from '../../components/NodeHostWrapper/NodeHostWrapper';
11
8
 
9
+ import type {NodeAddress} from '../../utils/nodes';
12
10
  import {formatBytesToGigabyte} from '../../utils/index';
13
- import {INodesPreparedEntity} from '../../types/store/nodes';
14
- import {showTooltip as externalShowTooltip} from '../../store/reducers/tooltip';
15
-
16
- import {getDefaultNodePath} from '../Node/NodePages';
17
-
18
- import './NodesTable.scss';
19
11
 
20
- const b = cn('ydb-nodes-table');
12
+ import type {INodesPreparedEntity} from '../../types/store/nodes';
13
+ import {showTooltip as externalShowTooltip} from '../../store/reducers/tooltip';
21
14
 
22
15
  interface GetNodesColumnsProps {
23
16
  showTooltip: (...args: Parameters<typeof externalShowTooltip>) => void;
24
17
  hideTooltip: VoidFunction;
25
18
  tabletsPath?: string;
26
- getNodeRef?: Function;
19
+ getNodeRef?: (node?: NodeAddress) => string;
27
20
  }
28
21
 
29
22
  export function getNodesColumns({
@@ -42,39 +35,7 @@ export function getNodesColumns({
42
35
  {
43
36
  name: 'Host',
44
37
  render: ({row}) => {
45
- const nodeRef = getNodeRef ? getNodeRef(row) + 'internal' : undefined;
46
- if (typeof row.Host === 'undefined') {
47
- return <span>—</span>;
48
- }
49
- return (
50
- <div className={b('host-field-wrapper')}>
51
- <Popover
52
- content={<NodeEndpointsTooltip data={row} />}
53
- placement={['top', 'bottom']}
54
- behavior={PopoverBehavior.Immediate}
55
- >
56
- <div className={b('host-wrapper')}>
57
- <EntityStatus
58
- name={row.Host}
59
- status={row.SystemState}
60
- path={getDefaultNodePath(row.NodeId)}
61
- hasClipboardButton
62
- className={b('host')}
63
- />
64
- {nodeRef && (
65
- <Button
66
- size="s"
67
- href={nodeRef}
68
- className={b('external-button')}
69
- target="_blank"
70
- >
71
- <IconWrapper name="external" />
72
- </Button>
73
- )}
74
- </div>
75
- </Popover>
76
- </div>
77
- );
38
+ return <NodeHostWrapper node={row} getNodeRef={getNodeRef} />;
78
39
  },
79
40
  width: '350px',
80
41
  align: DataTable.LEFT,
@@ -20,18 +20,6 @@
20
20
  margin-right: 0px;
21
21
  }
22
22
  }
23
- &__fqdn-field-wrapper {
24
- width: 330px;
25
- }
26
- &__fqdn-wrapper {
27
- display: flex;
28
- align-items: center;
29
-
30
- max-width: 330px;
31
- }
32
- &__fqdn {
33
- overflow: hidden;
34
- }
35
23
 
36
24
  &__group-id {
37
25
  font-weight: 500;
@@ -40,16 +28,4 @@
40
28
  &__node_unavailable {
41
29
  opacity: 0.6;
42
30
  }
43
-
44
- &__external-button {
45
- display: none;
46
-
47
- margin-left: 4px;
48
- }
49
- }
50
-
51
- .data-table__row:hover {
52
- .global-storage-nodes__external-button {
53
- display: inline-flex;
54
- }
55
31
  }
@@ -2,11 +2,6 @@ import _ from 'lodash';
2
2
  import cn from 'bem-cn-lite';
3
3
 
4
4
  import DataTable, {Column, Settings, SortOrder} from '@gravity-ui/react-data-table';
5
- import {Button, Popover, PopoverBehavior} from '@gravity-ui/uikit';
6
-
7
- import {NodeEndpointsTooltip} from '../../../components/Tooltips/NodeEndpointsTooltip/NodeEndpointsTooltip';
8
- import EntityStatus from '../../../components/EntityStatus/EntityStatus';
9
- import {IconWrapper} from '../../../components/Icon';
10
5
 
11
6
  import {VisibleEntities} from '../../../store/reducers/storage';
12
7
  import {
@@ -15,7 +10,7 @@ import {
15
10
  NodesUptimeFilterValues,
16
11
  } from '../../../utils/nodes';
17
12
 
18
- import {getDefaultNodePath} from '../../Node/NodePages';
13
+ import {NodeHostWrapper} from '../../../components/NodeHostWrapper/NodeHostWrapper';
19
14
 
20
15
  import {EmptyFilter} from '../EmptyFilter/EmptyFilter';
21
16
  import {PDisk} from '../PDisk';
@@ -100,39 +95,7 @@ function StorageNodes({
100
95
  header: tableColumnsNames[TableColumnsIds.FQDN],
101
96
  width: 350,
102
97
  render: ({row}) => {
103
- const nodeRef = getNodeRef ? getNodeRef(row) + 'internal' : undefined;
104
- if (!row.Host) {
105
- return <span>—</span>;
106
- }
107
- return (
108
- <div className={b('fqdn-field-wrapper')}>
109
- <Popover
110
- content={<NodeEndpointsTooltip data={row} />}
111
- placement={['top', 'bottom']}
112
- behavior={PopoverBehavior.Immediate}
113
- >
114
- <div className={b('fqdn-wrapper')}>
115
- <EntityStatus
116
- name={row.Host}
117
- showStatus={false}
118
- path={getDefaultNodePath(row.NodeId)}
119
- hasClipboardButton
120
- className={b('fqdn')}
121
- />
122
- {nodeRef && (
123
- <Button
124
- size="s"
125
- href={nodeRef}
126
- className={b('external-button')}
127
- target="_blank"
128
- >
129
- <IconWrapper name="external" />
130
- </Button>
131
- )}
132
- </div>
133
- </Popover>
134
- </div>
135
- );
98
+ return <NodeHostWrapper node={row} getNodeRef={getNodeRef} />;
136
99
  },
137
100
  align: DataTable.LEFT,
138
101
  },
@@ -2,8 +2,9 @@ import React, {useRef, useState} from 'react';
2
2
  import cn from 'bem-cn-lite';
3
3
  import _ from 'lodash';
4
4
  import {Button, Popup} from '@gravity-ui/uikit';
5
+
5
6
  import TruncatedQuery from '../../../../components/TruncatedQuery/TruncatedQuery';
6
- import {useSelector} from 'react-redux';
7
+ import {useTypedSelector} from '../../../../utils/hooks';
7
8
 
8
9
  import './QueriesHistory.scss';
9
10
 
@@ -17,8 +18,7 @@ interface QueriesHistoryProps {
17
18
 
18
19
  function QueriesHistory(props: QueriesHistoryProps) {
19
20
  const [isHistoryVisible, setIsHistoryVisible] = useState(false);
20
- const history: string[] =
21
- useSelector((state: any) => state.executeQuery.history?.queries) ?? [];
21
+ const history = useTypedSelector((state) => state.executeQuery.history.queries) ?? [];
22
22
  const anchor = useRef(null);
23
23
 
24
24
  const onShowHistoryClick = () => {
@@ -0,0 +1,8 @@
1
+ .ydb-query-duration {
2
+ display: flex;
3
+ align-items: center;
4
+
5
+ margin-left: 10px;
6
+
7
+ color: var(--yc-color-text-complementary);
8
+ }
@@ -0,0 +1,21 @@
1
+ import block from 'bem-cn-lite';
2
+
3
+ import {formatDurationToShortTimeFormat, parseUsToMs} from '../../../../utils/timeParsers';
4
+
5
+ import './QueryDuration.scss';
6
+
7
+ interface QueryDurationProps {
8
+ duration?: string;
9
+ }
10
+
11
+ const b = block('ydb-query-duration');
12
+
13
+ export const QueryDuration = ({duration}: QueryDurationProps) => {
14
+ if (!duration) {
15
+ return null;
16
+ }
17
+
18
+ const parsedDuration = formatDurationToShortTimeFormat(parseUsToMs(duration), 1);
19
+
20
+ return <span className={b()}>{parsedDuration}</span>;
21
+ };