ydb-embedded-ui 4.8.1 → 4.9.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 (39) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/components/NodeHostWrapper/NodeHostWrapper.tsx +2 -2
  3. package/dist/components/Tablet/Tablet.tsx +2 -13
  4. package/dist/containers/Header/breadcrumbs.ts +22 -6
  5. package/dist/containers/Nodes/Nodes.tsx +1 -1
  6. package/dist/containers/Nodes/getNodesColumns.tsx +2 -2
  7. package/dist/containers/Storage/PDisk/PDisk.tsx +1 -1
  8. package/dist/containers/Storage/Storage.js +26 -48
  9. package/dist/containers/Storage/StorageGroups/StorageGroups.tsx +16 -19
  10. package/dist/containers/Storage/StorageNodes/StorageNodes.tsx +12 -10
  11. package/dist/containers/Storage/StorageTypeFilter/StorageTypeFilter.tsx +27 -0
  12. package/dist/containers/Storage/StorageVisibleEntityFilter/StorageVisibleEntityFilter.tsx +31 -0
  13. package/dist/containers/Tablet/Tablet.tsx +2 -11
  14. package/dist/containers/TabletsFilters/TabletsFilters.js +8 -3
  15. package/dist/containers/Tenant/Query/QueryEditor/QueryEditor.js +17 -43
  16. package/dist/containers/Tenant/Query/QueryEditorControls/QueryEditorControls.scss +20 -15
  17. package/dist/containers/Tenant/Query/QueryEditorControls/QueryEditorControls.tsx +74 -27
  18. package/dist/containers/Tenant/Query/i18n/en.json +1 -1
  19. package/dist/containers/Tenant/Query/i18n/ru.json +1 -1
  20. package/dist/containers/UserSettings/i18n/en.json +1 -1
  21. package/dist/containers/UserSettings/i18n/ru.json +1 -1
  22. package/dist/services/api.ts +6 -13
  23. package/dist/store/reducers/executeQuery.ts +2 -3
  24. package/dist/store/reducers/explainQuery.ts +2 -2
  25. package/dist/store/reducers/header/types.ts +0 -2
  26. package/dist/store/reducers/index.ts +2 -2
  27. package/dist/store/reducers/{nodes.ts → nodes/nodes.ts} +31 -30
  28. package/dist/{types/store/nodes.ts → store/reducers/nodes/types.ts} +24 -27
  29. package/dist/store/reducers/settings/settings.ts +10 -2
  30. package/dist/store/reducers/storage/constants.ts +10 -0
  31. package/dist/store/reducers/{storage.js → storage/storage.js} +19 -53
  32. package/dist/store/reducers/storage/types.ts +12 -0
  33. package/dist/types/store/query.ts +5 -6
  34. package/dist/utils/constants.ts +1 -0
  35. package/dist/utils/nodes.ts +2 -2
  36. package/dist/utils/query.ts +12 -0
  37. package/package.json +1 -1
  38. package/dist/containers/Tenant/Query/QueryEditorControls/OldQueryEditorControls.tsx +0 -90
  39. package/dist/containers/Tenant/Query/QueryEditorControls/shared.ts +0 -18
@@ -1,22 +1,23 @@
1
- import type {IResponseError} from '../api/error';
2
- import type {TEndpoint, TPoolStats} from '../api/nodes';
3
- import type {TTabletStateInfo as TComputeTabletStateInfo} from '../api/compute';
4
- import type {TTabletStateInfo as TFullTabletStateInfo} from '../api/tablet';
5
- import type {EFlag} from '../api/enums';
1
+ import type {IResponseError} from '../../../types/api/error';
2
+ import type {TEndpoint, TPoolStats} from '../../../types/api/nodes';
3
+ import type {TTabletStateInfo as TComputeTabletStateInfo} from '../../../types/api/compute';
4
+ import type {TTabletStateInfo as TFullTabletStateInfo} from '../../../types/api/tablet';
5
+ import type {EFlag} from '../../../types/api/enums';
6
+ import type {ApiRequestAction} from '../../utils';
7
+ import type {VisibleEntities} from '../storage/types';
6
8
 
7
- import {NodesUptimeFilterValues} from '../../utils/nodes';
9
+ import {NodesUptimeFilterValues} from '../../../utils/nodes';
8
10
  import {
9
11
  FETCH_NODES,
10
12
  resetNodesState,
11
13
  setDataWasNotLoaded,
12
14
  setNodesUptimeFilter,
13
15
  setSearchValue,
14
- } from '../../store/reducers/nodes';
15
- import {ApiRequestAction} from '../../store/utils';
16
+ } from './nodes';
16
17
 
17
18
  // Since nodes from different endpoints can have different types,
18
19
  // This type describes fields, that are expected by tables with nodes
19
- export interface INodesPreparedEntity {
20
+ export interface NodesPreparedEntity {
20
21
  NodeId: number;
21
22
  Host?: string;
22
23
  SystemState?: EFlag;
@@ -33,43 +34,39 @@ export interface INodesPreparedEntity {
33
34
  Endpoints?: TEndpoint[];
34
35
  }
35
36
 
36
- export interface INodesState {
37
+ export interface NodesState {
37
38
  loading: boolean;
38
39
  wasLoaded: boolean;
39
40
  nodesUptimeFilter: NodesUptimeFilterValues;
40
41
  searchValue: string;
41
- data?: INodesPreparedEntity[];
42
+ data?: NodesPreparedEntity[];
42
43
  totalNodes?: number;
43
44
  error?: IResponseError;
44
45
  }
45
46
 
46
- type INodesApiRequestNodeType = 'static' | 'dynamic' | 'any';
47
+ export type NodeType = 'static' | 'dynamic' | 'any';
47
48
 
48
- // Space - out of space nodes
49
- // Missing - nodes with missing disks
50
- type INodesApiRequestProblemType = 'missing' | 'space';
51
-
52
- export interface INodesApiRequestParams {
49
+ export interface NodesApiRequestParams {
53
50
  tenant?: string;
54
- type?: INodesApiRequestNodeType;
55
- filter?: INodesApiRequestProblemType;
51
+ type?: NodeType;
52
+ visibleEntities?: VisibleEntities;
56
53
  storage?: boolean;
57
54
  tablets?: boolean;
58
55
  }
59
56
 
60
- export interface INodesHandledResponse {
61
- Nodes?: INodesPreparedEntity[];
57
+ export interface NodesHandledResponse {
58
+ Nodes?: NodesPreparedEntity[];
62
59
  TotalNodes: number;
63
60
  }
64
61
 
65
- type INodesApiRequestAction = ApiRequestAction<
62
+ type NodesApiRequestAction = ApiRequestAction<
66
63
  typeof FETCH_NODES,
67
- INodesHandledResponse,
64
+ NodesHandledResponse,
68
65
  IResponseError
69
66
  >;
70
67
 
71
- export type INodesAction =
72
- | INodesApiRequestAction
68
+ export type NodesAction =
69
+ | NodesApiRequestAction
73
70
  | (
74
71
  | ReturnType<typeof setDataWasNotLoaded>
75
72
  | ReturnType<typeof setNodesUptimeFilter>
@@ -77,6 +74,6 @@ export type INodesAction =
77
74
  | ReturnType<typeof resetNodesState>
78
75
  );
79
76
 
80
- export interface INodesRootStateSlice {
81
- nodes: INodesState;
77
+ export interface NodesStateSlice {
78
+ nodes: NodesState;
82
79
  }
@@ -13,10 +13,11 @@ import {
13
13
  QUERY_INITIAL_MODE_KEY,
14
14
  ENABLE_ADDITIONAL_QUERY_MODES,
15
15
  CLUSTER_INFO_HIDDEN_KEY,
16
+ LAST_USED_QUERY_ACTION_KEY,
16
17
  } from '../../../utils/constants';
17
18
  import '../../../services/api';
18
19
  import {getValueFromLS, parseJson} from '../../../utils/utils';
19
- import {QueryModes} from '../../../types/store/query';
20
+ import {QUERY_ACTIONS, QUERY_MODES} from '../../../utils/query';
20
21
 
21
22
  import {TENANT_PAGES_IDS} from '../tenant/constants';
22
23
 
@@ -64,7 +65,14 @@ export const initialState = {
64
65
  TENANT_INITIAL_PAGE_KEY,
65
66
  TENANT_PAGES_IDS.query,
66
67
  ),
67
- [QUERY_INITIAL_MODE_KEY]: readSavedSettingsValue(QUERY_INITIAL_MODE_KEY, QueryModes.script),
68
+ [QUERY_INITIAL_MODE_KEY]: readSavedSettingsValue(
69
+ QUERY_INITIAL_MODE_KEY,
70
+ QUERY_MODES.script,
71
+ ),
72
+ [LAST_USED_QUERY_ACTION_KEY]: readSavedSettingsValue(
73
+ LAST_USED_QUERY_ACTION_KEY,
74
+ QUERY_ACTIONS.execute,
75
+ ),
68
76
  [ASIDE_HEADER_COMPACT_KEY]: readSavedSettingsValue(ASIDE_HEADER_COMPACT_KEY, 'true'),
69
77
  [PARTITIONS_HIDDEN_COLUMNS_KEY]: readSavedSettingsValue(PARTITIONS_HIDDEN_COLUMNS_KEY),
70
78
  [CLUSTER_INFO_HIDDEN_KEY]: readSavedSettingsValue(CLUSTER_INFO_HIDDEN_KEY, 'true'),
@@ -0,0 +1,10 @@
1
+ export const VISIBLE_ENTITIES = {
2
+ all: 'all',
3
+ missing: 'missing',
4
+ space: 'space',
5
+ } as const;
6
+
7
+ export const STORAGE_TYPES = {
8
+ groups: 'groups',
9
+ nodes: 'nodes',
10
+ } as const;
@@ -1,31 +1,16 @@
1
1
  import _ from 'lodash';
2
2
  import {createSelector} from 'reselect';
3
3
 
4
- import {calcUptime} from '../../utils';
5
- import {getUsage} from '../../utils/storage';
6
- import {NodesUptimeFilterValues} from '../../utils/nodes';
7
- import {getPDiskType} from '../../utils/pdisk';
8
- import '../../services/api';
9
-
10
- import {createRequestActionTypes, createApiRequest} from '../utils';
11
- import {filterNodesByUptime} from './nodes';
12
-
13
- export const VisibleEntities = {
14
- All: 'All',
15
- Missing: 'Missing',
16
- Space: 'Space',
17
- };
4
+ import {calcUptime} from '../../../utils';
5
+ import {getUsage} from '../../../utils/storage';
6
+ import {NodesUptimeFilterValues} from '../../../utils/nodes';
7
+ import {getPDiskType} from '../../../utils/pdisk';
8
+ import '../../../services/api';
18
9
 
19
- export const VisibleEntitiesTitles = {
20
- [VisibleEntities.All]: 'All',
21
- [VisibleEntities.Missing]: 'Degraded',
22
- [VisibleEntities.Space]: 'Out of Space',
23
- };
10
+ import {createRequestActionTypes, createApiRequest} from '../../utils';
11
+ import {filterNodesByUptime} from '../nodes/nodes';
24
12
 
25
- export const StorageTypes = {
26
- groups: 'Groups',
27
- nodes: 'Nodes',
28
- };
13
+ import {VISIBLE_ENTITIES, STORAGE_TYPES} from './constants';
29
14
 
30
15
  const FETCH_STORAGE = createRequestActionTypes('storage', 'FETCH_STORAGE');
31
16
  const SET_INITIAL = 'storage/SET_INITIAL';
@@ -41,9 +26,9 @@ const initialState = {
41
26
  wasLoaded: false,
42
27
  filter: '',
43
28
  usageFilter: [],
44
- visible: VisibleEntities.Missing,
29
+ visible: VISIBLE_ENTITIES.missing,
45
30
  nodesUptimeFilter: NodesUptimeFilterValues.All,
46
- type: StorageTypes.groups,
31
+ type: STORAGE_TYPES.groups,
47
32
  };
48
33
 
49
34
  const storage = (state = initialState, action) => {
@@ -134,16 +119,16 @@ export function setInitialState() {
134
119
  };
135
120
  }
136
121
 
137
- export function getStorageInfo({tenant, filter, nodeId, type}, {concurrentId}) {
138
- if (type === StorageTypes.nodes) {
122
+ export function getStorageInfo({tenant, visibleEntities, nodeId, type}, {concurrentId}) {
123
+ if (type === STORAGE_TYPES.nodes) {
139
124
  return createApiRequest({
140
- request: window.api.getNodes({tenant, filter, type: 'static'}, {concurrentId}),
125
+ request: window.api.getNodes({tenant, visibleEntities, type: 'static'}, {concurrentId}),
141
126
  actions: FETCH_STORAGE,
142
127
  });
143
128
  }
144
129
 
145
130
  return createApiRequest({
146
- request: window.api.getStorageInfo({tenant, filter, nodeId}, {concurrentId}),
131
+ request: window.api.getStorageInfo({tenant, visibleEntities, nodeId}, {concurrentId}),
147
132
  actions: FETCH_STORAGE,
148
133
  });
149
134
  }
@@ -343,26 +328,13 @@ export const getVDisksForPDisk = createSelector(
343
328
  export const getFlatListStorage = createSelector(
344
329
  [getStorageType, getFlatListStorageGroups, getFlatListStorageNodes],
345
330
  (storageType, groupsList, nodesList) => {
346
- if (storageType === StorageTypes.groups) {
331
+ if (storageType === STORAGE_TYPES.groups) {
347
332
  return groupsList;
348
333
  }
349
334
  return nodesList;
350
335
  },
351
336
  );
352
337
 
353
- export const getVisibleEntitiesList = createSelector(
354
- [getVisibleEntities, getFlatListStorage],
355
- (visibleGroups, storageList) => {
356
- if (visibleGroups === VisibleEntities.All) {
357
- return storageList;
358
- } else if (visibleGroups === VisibleEntities.Missing) {
359
- return _.filter(storageList, (g) => g.Missing > 0);
360
- } else {
361
- return _.filter(storageList, (g) => g.UsedSpaceFlag > 100);
362
- }
363
- },
364
- );
365
-
366
338
  const filterByText = (entities, type, text) => {
367
339
  const cleanedFilter = text.trim().toLowerCase();
368
340
 
@@ -371,7 +343,7 @@ const filterByText = (entities, type, text) => {
371
343
  }
372
344
 
373
345
  return entities.filter((entity) => {
374
- if (type === StorageTypes.groups) {
346
+ if (type === STORAGE_TYPES.groups) {
375
347
  return (
376
348
  entity.PoolName.toLowerCase().includes(cleanedFilter) ||
377
349
  entity.GroupID?.toString().includes(cleanedFilter)
@@ -397,19 +369,13 @@ const filterByUsage = (entities, usage) => {
397
369
  };
398
370
 
399
371
  export const getFilteredEntities = createSelector(
400
- [
401
- getStorageFilter,
402
- getUsageFilter,
403
- getStorageType,
404
- getNodesUptimeFilter,
405
- getVisibleEntitiesList,
406
- ],
372
+ [getStorageFilter, getUsageFilter, getStorageType, getNodesUptimeFilter, getFlatListStorage],
407
373
  (textFilter, usageFilter, type, nodesUptimeFilter, entities) => {
408
374
  let result = entities;
409
375
  result = filterByText(result, type, textFilter);
410
376
  result = filterByUsage(result, usageFilter);
411
377
 
412
- if (type === StorageTypes.nodes) {
378
+ if (type === STORAGE_TYPES.nodes) {
413
379
  result = filterNodesByUptime(result, nodesUptimeFilter);
414
380
  }
415
381
 
@@ -417,7 +383,7 @@ export const getFilteredEntities = createSelector(
417
383
  },
418
384
  );
419
385
 
420
- export const getUsageFilterOptions = createSelector(getVisibleEntitiesList, (entities) => {
386
+ export const getUsageFilterOptions = createSelector(getFlatListStorage, (entities) => {
421
387
  const items = {};
422
388
 
423
389
  entities.forEach((entity) => {
@@ -0,0 +1,12 @@
1
+ import type {ValueOf} from '../../../types/common';
2
+
3
+ import {STORAGE_TYPES, VISIBLE_ENTITIES} from './constants';
4
+
5
+ export type VisibleEntities = ValueOf<typeof VISIBLE_ENTITIES>;
6
+ export type StorageType = ValueOf<typeof STORAGE_TYPES>;
7
+
8
+ export interface StorageApiRequestParams {
9
+ tenant?: string;
10
+ nodeId?: string;
11
+ visibleEntities?: VisibleEntities;
12
+ }
@@ -1,3 +1,5 @@
1
+ import {QUERY_ACTIONS, QUERY_MODES} from '../../utils/query';
2
+
1
3
  import type {NetworkError} from '../api/error';
2
4
  import type {
3
5
  KeyValueRow,
@@ -7,6 +9,7 @@ import type {
7
9
  QueryPlan,
8
10
  TKqpStatsQuery,
9
11
  } from '../api/query';
12
+ import type {ValueOf} from '../common';
10
13
 
11
14
  export interface IQueryResult {
12
15
  result?: KeyValueRow[];
@@ -23,12 +26,8 @@ export interface QueryRequestParams {
23
26
 
24
27
  export type QueryError = NetworkError | ErrorResponse;
25
28
 
26
- export enum QueryModes {
27
- scan = 'scan',
28
- script = 'script',
29
- data = 'data',
30
- query = 'query',
31
- }
29
+ export type QueryAction = ValueOf<typeof QUERY_ACTIONS>;
30
+ export type QueryMode = ValueOf<typeof QUERY_MODES>;
32
31
 
33
32
  export interface SavedQuery {
34
33
  name: string;
@@ -105,6 +105,7 @@ export const DEFAULT_TABLE_SETTINGS = {
105
105
  } as const;
106
106
 
107
107
  export const QUERY_INITIAL_MODE_KEY = 'query_initial_mode';
108
+ export const LAST_USED_QUERY_ACTION_KEY = 'last_used_query_action';
108
109
 
109
110
  export const PARTITIONS_HIDDEN_COLUMNS_KEY = 'partitionsHiddenColumns';
110
111
 
@@ -1,6 +1,6 @@
1
1
  import type {TSystemStateInfo} from '../types/api/nodes';
2
2
  import type {TNodeInfo} from '../types/api/nodesList';
3
- import type {INodesPreparedEntity} from '../types/store/nodes';
3
+ import type {NodesPreparedEntity} from '../store/reducers/nodes/types';
4
4
  import type {NodesMap} from '../types/store/nodesList';
5
5
  import {EFlag} from '../types/api/enums';
6
6
 
@@ -14,7 +14,7 @@ export const NodesUptimeFilterTitles = {
14
14
  [NodesUptimeFilterValues.SmallUptime]: 'Uptime < 1h',
15
15
  };
16
16
 
17
- export const isUnavailableNode = (node: INodesPreparedEntity | TSystemStateInfo) =>
17
+ export const isUnavailableNode = (node: NodesPreparedEntity | TSystemStateInfo) =>
18
18
  !node.SystemState || node.SystemState === EFlag.Grey;
19
19
 
20
20
  export type NodeAddress = Pick<TSystemStateInfo, 'Host' | 'Endpoints'>;
@@ -9,6 +9,18 @@ import type {
9
9
  } from '../types/api/query';
10
10
  import type {IQueryResult} from '../types/store/query';
11
11
 
12
+ export const QUERY_ACTIONS = {
13
+ execute: 'execute',
14
+ explain: 'explain',
15
+ } as const;
16
+
17
+ export const QUERY_MODES = {
18
+ scan: 'scan',
19
+ script: 'script',
20
+ data: 'data',
21
+ query: 'query',
22
+ } as const;
23
+
12
24
  // eslint-disable-next-line complexity
13
25
  export const getColumnType = (type: string) => {
14
26
  switch (type.replace(/\?$/, '')) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ydb-embedded-ui",
3
- "version": "4.8.1",
3
+ "version": "4.9.0",
4
4
  "files": [
5
5
  "dist"
6
6
  ],
@@ -1,90 +0,0 @@
1
- import {Button, DropdownMenu} from '@gravity-ui/uikit';
2
- import {useMemo} from 'react';
3
-
4
- import {QueryModes} from '../../../../types/store/query';
5
- import {Icon} from '../../../../components/Icon';
6
-
7
- import SaveQuery from '../SaveQuery/SaveQuery';
8
-
9
- import {QueryEditorControlsProps, b} from './shared';
10
-
11
- import './QueryEditorControls.scss';
12
-
13
- type OldQueryModes = QueryModes.script | QueryModes.scan;
14
-
15
- export const QueryModeSelectorTitles = {
16
- [QueryModes.script]: 'Script',
17
- [QueryModes.scan]: 'Scan',
18
- } as const;
19
-
20
- export const OldQueryEditorControls = ({
21
- onRunButtonClick,
22
- runIsLoading,
23
- onExplainButtonClick,
24
- explainIsLoading,
25
- onSaveQueryClick,
26
- savedQueries,
27
- disabled,
28
- onUpdateQueryMode,
29
- queryMode,
30
- }: QueryEditorControlsProps) => {
31
- const runModeSelectorMenuItems = useMemo(() => {
32
- return Object.entries(QueryModeSelectorTitles).map(([mode, title]) => {
33
- return {
34
- text: `Run ${title}`,
35
- action: () => {
36
- onUpdateQueryMode(mode as OldQueryModes);
37
- },
38
- };
39
- });
40
- }, [onUpdateQueryMode]);
41
-
42
- return (
43
- <div className={b()}>
44
- <div className={b('left')}>
45
- <div className={b('run')}>
46
- <Button
47
- onClick={() => onRunButtonClick(queryMode)}
48
- view="action"
49
- pin="round-brick"
50
- disabled={disabled}
51
- loading={runIsLoading}
52
- >
53
- <Icon name="startPlay" viewBox="0 0 16 16" width={16} height={16} />
54
- {`Run ${QueryModeSelectorTitles[queryMode as OldQueryModes]}`}
55
- </Button>
56
- <DropdownMenu
57
- items={runModeSelectorMenuItems}
58
- popupProps={{className: b('select-query-action-popup')}}
59
- switcher={
60
- <Button
61
- view="action"
62
- pin="brick-round"
63
- disabled={disabled}
64
- loading={runIsLoading}
65
- className={b('select-query-action')}
66
- >
67
- <Icon name="chevron-down" width={16} height={16} />
68
- </Button>
69
- }
70
- />
71
- </div>
72
- <Button
73
- onClick={() => {
74
- // Without defined query mode it sends 'explain' action
75
- onExplainButtonClick();
76
- }}
77
- disabled={disabled}
78
- loading={explainIsLoading}
79
- >
80
- Explain
81
- </Button>
82
- </div>
83
- <SaveQuery
84
- savedQueries={savedQueries}
85
- onSaveQuery={onSaveQueryClick}
86
- saveButtonDisabled={disabled}
87
- />
88
- </div>
89
- );
90
- };
@@ -1,18 +0,0 @@
1
- import block from 'bem-cn-lite';
2
-
3
- import type {QueryModes} from '../../../../types/store/query';
4
-
5
- export const b = block('ydb-query-editor-controls');
6
-
7
- export interface QueryEditorControlsProps {
8
- onRunButtonClick: (mode?: QueryModes) => void;
9
- runIsLoading: boolean;
10
- onExplainButtonClick: (mode?: QueryModes) => void;
11
- explainIsLoading: boolean;
12
- onSaveQueryClick: (queryName: string) => void;
13
- savedQueries: unknown;
14
- disabled: boolean;
15
- onUpdateQueryMode: (mode: QueryModes) => void;
16
- queryMode: QueryModes;
17
- enableQueryModesForExplain: boolean;
18
- }