ydb-embedded-ui 4.6.0 → 4.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/assets/icons/versions.svg +3 -0
  3. package/dist/components/NodeHostWrapper/NodeHostWrapper.tsx +6 -1
  4. package/dist/components/Tablet/Tablet.tsx +17 -3
  5. package/dist/components/TabletsStatistic/TabletsStatistic.tsx +23 -16
  6. package/dist/containers/App/Content.js +5 -2
  7. package/dist/containers/Cluster/Cluster.tsx +6 -13
  8. package/dist/containers/Cluster/ClusterInfo/ClusterInfo.tsx +3 -3
  9. package/dist/containers/Cluster/{utils.ts → utils.tsx} +11 -0
  10. package/dist/containers/Header/Header.scss +9 -0
  11. package/dist/containers/Header/Header.tsx +70 -14
  12. package/dist/containers/Header/breadcrumbs.ts +146 -0
  13. package/dist/containers/Node/Node.tsx +21 -27
  14. package/dist/containers/Node/NodePages.ts +10 -6
  15. package/dist/containers/Storage/StorageGroups/StorageGroups.tsx +11 -3
  16. package/dist/containers/Tablet/Tablet.tsx +35 -27
  17. package/dist/containers/Tablet/TabletInfo/TabletInfo.tsx +2 -2
  18. package/dist/containers/TabletsFilters/TabletsFilters.js +13 -15
  19. package/dist/containers/Tenant/Diagnostics/Consumers/columns/columns.tsx +1 -1
  20. package/dist/containers/Tenant/Diagnostics/DetailedOverview/DetailedOverview.scss +5 -1
  21. package/dist/containers/Tenant/Diagnostics/Diagnostics.tsx +1 -1
  22. package/dist/containers/Tenant/Diagnostics/Healthcheck/Healthcheck.scss +5 -3
  23. package/dist/containers/Tenant/Diagnostics/Healthcheck/Healthcheck.tsx +1 -1
  24. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.js +2 -1
  25. package/dist/containers/Tenant/Diagnostics/TopQueries/TopQueries.tsx +11 -13
  26. package/dist/containers/Tenant/ObjectGeneral/ObjectGeneral.tsx +2 -2
  27. package/dist/containers/Tenant/ObjectSummary/ObjectSummary.tsx +6 -2
  28. package/dist/containers/Tenant/{QueryEditor/QueryResult/QueryResult.js → Query/ExecuteResult/ExecuteResult.js} +3 -5
  29. package/dist/containers/Tenant/{QueryEditor/QueryResult/QueryResult.scss → Query/ExecuteResult/ExecuteResult.scss} +1 -1
  30. package/dist/containers/Tenant/{QueryEditor/QueryExplain/QueryExplain.js → Query/ExplainResult/ExplainResult.js} +3 -5
  31. package/dist/containers/Tenant/{QueryEditor/QueryExplain/QueryExplain.scss → Query/ExplainResult/ExplainResult.scss} +1 -1
  32. package/dist/containers/Tenant/Query/QueriesHistory/QueriesHistory.scss +20 -0
  33. package/dist/containers/Tenant/Query/QueriesHistory/QueriesHistory.tsx +60 -0
  34. package/dist/containers/Tenant/Query/Query.scss +16 -0
  35. package/dist/containers/Tenant/Query/Query.tsx +73 -0
  36. package/dist/containers/Tenant/{QueryEditor → Query/QueryEditor}/QueryEditor.js +26 -87
  37. package/dist/containers/Tenant/{QueryEditor → Query/QueryEditor}/QueryEditor.scss +7 -23
  38. package/dist/containers/Tenant/{QueryEditor → Query}/QueryEditorControls/QueryEditorControls.scss +1 -4
  39. package/dist/containers/Tenant/Query/QueryTabs/QueryTabs.tsx +59 -0
  40. package/dist/containers/Tenant/{QueryEditor → Query}/SaveQuery/SaveQuery.js +5 -5
  41. package/dist/containers/Tenant/Query/SavedQueries/SavedQueries.scss +55 -0
  42. package/dist/containers/Tenant/Query/SavedQueries/SavedQueries.tsx +150 -0
  43. package/dist/containers/Tenant/Query/i18n/en.json +12 -0
  44. package/dist/containers/Tenant/Query/i18n/ru.json +12 -0
  45. package/dist/containers/Tenant/Query/utils/getPreparedResult.ts +30 -0
  46. package/dist/containers/Tenant/Tenant.tsx +2 -18
  47. package/dist/containers/Tenant/TenantPages.tsx +8 -2
  48. package/dist/containers/Tenant/utils/constants.ts +10 -0
  49. package/dist/containers/Tenant/utils/schemaActions.ts +7 -2
  50. package/dist/containers/Tenants/Tenants.js +21 -9
  51. package/dist/routes.ts +10 -1
  52. package/dist/services/api.ts +9 -5
  53. package/dist/store/reducers/executeQuery.ts +1 -1
  54. package/dist/store/reducers/header/header.ts +31 -0
  55. package/dist/store/reducers/header/types.ts +54 -0
  56. package/dist/store/reducers/index.ts +1 -1
  57. package/dist/store/reducers/node/types.ts +2 -0
  58. package/dist/store/reducers/settings/settings.ts +1 -1
  59. package/dist/store/reducers/tablet.ts +18 -1
  60. package/dist/store/reducers/tenant/constants.ts +6 -0
  61. package/dist/store/reducers/tenant/tenant.ts +21 -2
  62. package/dist/store/reducers/tenant/types.ts +9 -2
  63. package/dist/store/reducers/topic.ts +1 -1
  64. package/dist/store/state-url-mapping.js +4 -1
  65. package/dist/types/store/query.ts +5 -0
  66. package/dist/types/store/tablet.ts +7 -4
  67. package/dist/utils/constants.ts +2 -0
  68. package/package.json +2 -1
  69. package/dist/containers/Tenant/QueryEditor/QueriesHistory/QueriesHistory.scss +0 -85
  70. package/dist/containers/Tenant/QueryEditor/QueriesHistory/QueriesHistory.tsx +0 -95
  71. package/dist/containers/Tenant/QueryEditor/SavedQueries/SavedQueries.js +0 -161
  72. package/dist/containers/Tenant/QueryEditor/SavedQueries/SavedQueries.scss +0 -93
  73. package/dist/containers/Tenant/QueryEditor/i18n/en.json +0 -3
  74. package/dist/containers/Tenant/QueryEditor/i18n/ru.json +0 -3
  75. package/dist/store/reducers/header.ts +0 -26
  76. /package/dist/containers/Tenant/{QueryEditor → Query}/Issues/Issues.scss +0 -0
  77. /package/dist/containers/Tenant/{QueryEditor → Query}/Issues/Issues.tsx +0 -0
  78. /package/dist/containers/Tenant/{QueryEditor → Query}/Issues/models.ts +0 -0
  79. /package/dist/containers/Tenant/{QueryEditor → Query}/QueryDuration/QueryDuration.scss +0 -0
  80. /package/dist/containers/Tenant/{QueryEditor → Query}/QueryDuration/QueryDuration.tsx +0 -0
  81. /package/dist/containers/Tenant/{QueryEditor → Query}/QueryEditorControls/OldQueryEditorControls.tsx +0 -0
  82. /package/dist/containers/Tenant/{QueryEditor → Query}/QueryEditorControls/QueryEditorControls.tsx +0 -0
  83. /package/dist/containers/Tenant/{QueryEditor → Query}/QueryEditorControls/shared.ts +0 -0
  84. /package/dist/containers/Tenant/{QueryEditor → Query}/SaveQuery/SaveQuery.scss +0 -0
  85. /package/dist/containers/Tenant/{QueryEditor → Query}/i18n/index.ts +0 -0
@@ -8,16 +8,13 @@ import type {TEvDescribeSchemeResult} from '../../types/api/schema';
8
8
 
9
9
  import {DEFAULT_IS_TENANT_SUMMARY_COLLAPSED, DEFAULT_SIZE_TENANT_KEY} from '../../utils/constants';
10
10
  import {useTypedSelector} from '../../utils/hooks';
11
- import routes, {createHref} from '../../routes';
12
- import {setHeader} from '../../store/reducers/header';
11
+ import {setHeaderBreadcrumbs} from '../../store/reducers/header/header';
13
12
  import {disableAutorefresh, getSchema} from '../../store/reducers/schema/schema';
14
13
  import {getSchemaAcl} from '../../store/reducers/schemaAcl/schemaAcl';
15
14
 
16
15
  import SplitPane from '../../components/SplitPane';
17
16
  import {AccessDenied} from '../../components/Errors/403';
18
17
 
19
- import {getClusterPath} from '../Cluster/utils';
20
-
21
18
  import ObjectGeneralTabs from './ObjectGeneralTabs/ObjectGeneralTabs';
22
19
  import ObjectSummary from './ObjectSummary/ObjectSummary';
23
20
  import ObjectGeneral from './ObjectGeneral/ObjectGeneral';
@@ -92,20 +89,7 @@ function Tenant(props: TenantProps) {
92
89
 
93
90
  useEffect(() => {
94
91
  if (tenantName) {
95
- dispatch(
96
- setHeader([
97
- {
98
- text: 'Cluster',
99
- link: getClusterPath(),
100
- },
101
- {
102
- text: tenantName.startsWith('/') ? tenantName.slice(1) : tenantName,
103
- link: createHref(routes.tenant, undefined, {
104
- name: tenantName,
105
- }),
106
- },
107
- ]),
108
- );
92
+ dispatch(setHeaderBreadcrumbs('tenant', {tenantName}));
109
93
  }
110
94
  }, [tenantName, dispatch]);
111
95
 
@@ -1,5 +1,6 @@
1
- import {Icon} from '../../components/Icon';
2
1
  import {TENANT_GENERAL_TABS_IDS} from '../../store/reducers/tenant/constants';
2
+ import routes, {createHref} from '../../routes';
3
+ import {Icon} from '../../components/Icon';
3
4
 
4
5
  export enum TenantInfoTabsIds {
5
6
  overview = 'overview',
@@ -10,7 +11,8 @@ export enum TenantInfoTabsIds {
10
11
  export enum TenantTabsGroups {
11
12
  info = 'info',
12
13
  general = 'general',
13
- generalTab = 'generalTab',
14
+ queryTab = 'queryTab',
15
+ diagnosticsTab = 'diagnosticsTab',
14
16
  }
15
17
 
16
18
  export const TENANT_GENERAL_TABS = [
@@ -42,3 +44,7 @@ export const TENANT_SCHEMA_TAB = [
42
44
  title: 'Schema',
43
45
  },
44
46
  ];
47
+
48
+ export const getTenantPath = (query = {}) => {
49
+ return createHref(routes.tenant, undefined, query);
50
+ };
@@ -0,0 +1,10 @@
1
+ import type {Settings} from '@gravity-ui/react-data-table';
2
+
3
+ import {DEFAULT_TABLE_SETTINGS} from '../../../utils/constants';
4
+
5
+ export const MAX_QUERY_HEIGHT = 6;
6
+
7
+ export const QUERY_TABLE_SETTINGS: Settings = {
8
+ ...DEFAULT_TABLE_SETTINGS,
9
+ dynamicRenderType: 'variable',
10
+ };
@@ -3,8 +3,11 @@ import type {NavigationTreeNodeType, NavigationTreeProps} from 'ydb-ui-component
3
3
 
4
4
  import {changeUserInput} from '../../../store/reducers/executeQuery';
5
5
  import {setShowPreview} from '../../../store/reducers/schema/schema';
6
- import {setTopLevelTab} from '../../../store/reducers/tenant/tenant';
7
- import {TENANT_GENERAL_TABS_IDS} from '../../../store/reducers/tenant/constants';
6
+ import {setQueryTab, setTopLevelTab} from '../../../store/reducers/tenant/tenant';
7
+ import {
8
+ TENANT_QUERY_TABS_ID,
9
+ TENANT_GENERAL_TABS_IDS,
10
+ } from '../../../store/reducers/tenant/constants';
8
11
  import createToast from '../../../utils/createToast';
9
12
 
10
13
  const createTableTemplate = (path: string) => {
@@ -38,6 +41,7 @@ const bindActions = (
38
41
  const inputQuery = (tmpl: (path: string) => string) => () => {
39
42
  dispatch(changeUserInput({input: tmpl(path)}));
40
43
  dispatch(setTopLevelTab(TENANT_GENERAL_TABS_IDS.query));
44
+ dispatch(setQueryTab(TENANT_QUERY_TABS_ID.newQuery));
41
45
  setActivePath(path);
42
46
  };
43
47
 
@@ -67,6 +71,7 @@ const bindActions = (
67
71
  openPreview: () => {
68
72
  dispatch(setShowPreview(true));
69
73
  dispatch(setTopLevelTab(TENANT_GENERAL_TABS_IDS.query));
74
+ dispatch(setQueryTab(TENANT_QUERY_TABS_ID.newQuery));
70
75
  setActivePath(path);
71
76
  },
72
77
  };
@@ -126,15 +126,19 @@ class Tenants extends React.Component {
126
126
  const initialTenantGeneralTab = savedTenantInitialTab || TENANT_GENERAL_TABS[0].id;
127
127
  const initialTenantInfoTab = TENANT_INFO_TABS[0].id;
128
128
 
129
+ const getTenantBackend = (tenant) => {
130
+ const backend = tenant.MonitoringEndpoint ?? tenant.backend;
131
+ return additionalTenantsInfo.tenantBackend
132
+ ? additionalTenantsInfo.tenantBackend(backend)
133
+ : undefined;
134
+ };
135
+
129
136
  const columns = [
130
137
  {
131
138
  name: 'Name',
132
139
  header: 'Database',
133
140
  render: ({value, row}) => {
134
- const backend = row.MonitoringEndpoint ?? row.backend;
135
- const tenantBackend = additionalTenantsInfo.tenantBackend
136
- ? additionalTenantsInfo.tenantBackend(backend)
137
- : undefined;
141
+ const backend = getTenantBackend(row);
138
142
  const isExternalLink = Boolean(backend);
139
143
  return (
140
144
  <div className={b('name-wrapper')}>
@@ -147,7 +151,7 @@ class Tenants extends React.Component {
147
151
  hasClipboardButton
148
152
  path={createHref(routes.tenant, undefined, {
149
153
  name: value,
150
- backend: tenantBackend,
154
+ backend,
151
155
  [TenantTabsGroups.info]: initialTenantInfoTab,
152
156
  [TenantTabsGroups.general]: initialTenantGeneralTab,
153
157
  })}
@@ -287,12 +291,20 @@ class Tenants extends React.Component {
287
291
  header: 'Tablets States',
288
292
  sortable: false,
289
293
  width: 430,
290
- render: ({value, row}) =>
291
- value ? (
292
- <TabletsStatistic path={row.Name} tablets={value} nodeIds={row.NodeIds} />
294
+ render: ({value, row}) => {
295
+ const backend = getTenantBackend(row);
296
+
297
+ return value ? (
298
+ <TabletsStatistic
299
+ path={row.Name}
300
+ tablets={value}
301
+ nodeIds={row.NodeIds}
302
+ backend={backend}
303
+ />
293
304
  ) : (
294
305
  '—'
295
- ),
306
+ );
307
+ },
296
308
  },
297
309
  ];
298
310
 
package/dist/routes.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import type {Location} from 'history';
1
2
  import qs from 'qs';
2
3
  import {compile} from 'path-to-regexp';
3
4
  import isEmpty from 'lodash/isEmpty';
@@ -13,10 +14,18 @@ const routes = {
13
14
  auth: '/auth',
14
15
  };
15
16
 
17
+ export const parseQuery = (location: Location) => {
18
+ return qs.parse(location.search, {
19
+ ignoreQueryPrefix: true,
20
+ });
21
+ };
22
+
23
+ export type Query = Record<string | number, string | number | string[] | number[] | undefined>;
24
+
16
25
  export function createHref(
17
26
  route: string,
18
27
  params?: Record<string, string | number>,
19
- query: Record<string | number, string | number | string[] | number[] | undefined> = {},
28
+ query: Query = {},
20
29
  ) {
21
30
  let extendedQuery = query;
22
31
 
@@ -44,11 +44,15 @@ export class YdbEmbeddedAPI extends AxiosWrapper {
44
44
  getPath(path: string) {
45
45
  return `${BACKEND}${path}`;
46
46
  }
47
- getClusterInfo(clusterName?: string) {
48
- return this.get<TClusterInfo>(this.getPath('/viewer/json/cluster'), {
49
- name: clusterName,
50
- tablets: true,
51
- });
47
+ getClusterInfo(clusterName?: string, {concurrentId}: AxiosOptions = {}) {
48
+ return this.get<TClusterInfo>(
49
+ this.getPath('/viewer/json/cluster'),
50
+ {
51
+ name: clusterName,
52
+ tablets: true,
53
+ },
54
+ {concurrentId: concurrentId || `getClusterInfo`},
55
+ );
52
56
  }
53
57
  getClusterNodes({concurrentId}: AxiosOptions = {}) {
54
58
  return this.get<TEvSystemStateResponse>(
@@ -186,7 +186,7 @@ export const changeUserInput = ({input}: {input: string}) => {
186
186
  } as const;
187
187
  };
188
188
 
189
- export const setMonacoHotKey = (value: MonacoHotKeyAction) => {
189
+ export const setMonacoHotKey = (value: MonacoHotKeyAction | null) => {
190
190
  return {
191
191
  type: MONACO_HOT_KEY,
192
192
  data: value,
@@ -0,0 +1,31 @@
1
+ import type {Reducer} from 'redux';
2
+
3
+ import type {HeaderAction, HeaderState, Page, PageBreadcrumbsOptions} from './types';
4
+
5
+ const SET_HEADER_BREADCRUMBS = 'header/SET_HEADER_BREADCRUMBS';
6
+
7
+ const initialState = {
8
+ pageBreadcrumbsOptions: {},
9
+ };
10
+
11
+ const header: Reducer<HeaderState, HeaderAction> = (state = initialState, action) => {
12
+ switch (action.type) {
13
+ case SET_HEADER_BREADCRUMBS:
14
+ return {
15
+ page: action.page,
16
+ pageBreadcrumbsOptions: action.options,
17
+ };
18
+ default:
19
+ return state;
20
+ }
21
+ };
22
+
23
+ export function setHeaderBreadcrumbs<T extends Page>(page: T, options: PageBreadcrumbsOptions<T>) {
24
+ return {
25
+ type: SET_HEADER_BREADCRUMBS,
26
+ page,
27
+ options,
28
+ } as const;
29
+ }
30
+
31
+ export default header;
@@ -0,0 +1,54 @@
1
+ import type {ClusterTab} from '../../../containers/Cluster/utils';
2
+
3
+ import {setHeaderBreadcrumbs} from './header';
4
+
5
+ export type Page = 'cluster' | 'tenant' | 'node' | 'tablets' | 'tablet' | undefined;
6
+
7
+ export interface ClusterBreadcrumbsOptions {
8
+ clusterName?: string;
9
+ clusterTab?: ClusterTab;
10
+ }
11
+
12
+ export interface TenantBreadcrumbsOptions extends ClusterBreadcrumbsOptions {
13
+ tenantName?: string;
14
+ }
15
+
16
+ export interface NodeBreadcrumbsOptions extends TenantBreadcrumbsOptions {
17
+ nodeId?: string | number;
18
+ }
19
+
20
+ export interface TabletsBreadcrumbsOptions extends TenantBreadcrumbsOptions {
21
+ nodeIds?: string[] | number[];
22
+ state?: string;
23
+ type?: string;
24
+ }
25
+
26
+ export interface TabletBreadcrumbsOptions extends TabletsBreadcrumbsOptions {
27
+ tabletId?: string;
28
+ }
29
+
30
+ export type BreadcrumbsOptions =
31
+ | ClusterBreadcrumbsOptions
32
+ | TenantBreadcrumbsOptions
33
+ | NodeBreadcrumbsOptions
34
+ | TabletsBreadcrumbsOptions
35
+ | TabletBreadcrumbsOptions;
36
+
37
+ export type PageBreadcrumbsOptions<T extends Page = undefined> = T extends 'cluster'
38
+ ? ClusterBreadcrumbsOptions
39
+ : T extends 'tenant'
40
+ ? TenantBreadcrumbsOptions
41
+ : T extends 'node'
42
+ ? NodeBreadcrumbsOptions
43
+ : T extends 'tablets'
44
+ ? TabletsBreadcrumbsOptions
45
+ : T extends 'tablet'
46
+ ? TabletBreadcrumbsOptions
47
+ : {};
48
+
49
+ export interface HeaderState {
50
+ page?: Page;
51
+ pageBreadcrumbsOptions: BreadcrumbsOptions;
52
+ }
53
+
54
+ export type HeaderAction = ReturnType<typeof setHeaderBreadcrumbs>;
@@ -31,7 +31,7 @@ import shardsWorkload from './shardsWorkload';
31
31
  import hotKeys from './hotKeys';
32
32
  import olapStats from './olapStats';
33
33
  import authentication from './authentication';
34
- import header from './header';
34
+ import header from './header/header';
35
35
  import saveQuery from './saveQuery';
36
36
  import fullscreen from './fullscreen';
37
37
  import singleClusterMode from './singleClusterMode';
@@ -28,10 +28,12 @@ export interface NodeState {
28
28
  data: TEvSystemStateResponse;
29
29
  loading: boolean;
30
30
  wasLoaded: boolean;
31
+ error?: IResponseError;
31
32
 
32
33
  nodeStructure: TStorageInfo;
33
34
  loadingStructure: boolean;
34
35
  wasLoadedStructure: boolean;
36
+ errorStructure?: IResponseError;
35
37
  }
36
38
 
37
39
  export type NodeAction =
@@ -62,7 +62,7 @@ export const initialState = {
62
62
  [QUERY_INITIAL_MODE_KEY]: readSavedSettingsValue(QUERY_INITIAL_MODE_KEY, QueryModes.script),
63
63
  [ASIDE_HEADER_COMPACT_KEY]: readSavedSettingsValue(ASIDE_HEADER_COMPACT_KEY, 'true'),
64
64
  [PARTITIONS_HIDDEN_COLUMNS_KEY]: readSavedSettingsValue(PARTITIONS_HIDDEN_COLUMNS_KEY),
65
- [CLUSTER_INFO_HIDDEN_KEY]: readSavedSettingsValue(CLUSTER_INFO_HIDDEN_KEY, 'false'),
65
+ [CLUSTER_INFO_HIDDEN_KEY]: readSavedSettingsValue(CLUSTER_INFO_HIDDEN_KEY, 'true'),
66
66
  },
67
67
  systemSettings,
68
68
  };
@@ -16,9 +16,11 @@ import {prepareNodesMap} from '../../utils/nodes';
16
16
  export const FETCH_TABLET = createRequestActionTypes('TABLET', 'FETCH_TABLET');
17
17
  export const FETCH_TABLET_DESCRIBE = createRequestActionTypes('TABLET', 'FETCH_TABLET_DESCRIBE');
18
18
 
19
+ const CLEAR_TABLET_DATA = 'tablet/CLEAR_TABLET_DATA';
20
+
19
21
  const initialState = {
20
22
  loading: false,
21
- tenantPath: '-',
23
+ tenantPath: undefined,
22
24
  };
23
25
 
24
26
  const tablet: Reducer<ITabletState, ITabletAction> = (state = initialState, action) => {
@@ -57,6 +59,15 @@ const tablet: Reducer<ITabletState, ITabletAction> = (state = initialState, acti
57
59
  error: undefined,
58
60
  };
59
61
  }
62
+ case CLEAR_TABLET_DATA: {
63
+ return {
64
+ ...state,
65
+ id: undefined,
66
+ tenantPath: undefined,
67
+ data: undefined,
68
+ history: undefined,
69
+ };
70
+ }
60
71
  default:
61
72
  return state;
62
73
  }
@@ -122,4 +133,10 @@ export const getTabletDescribe = (tenantId: TDomainKey = {}) => {
122
133
  });
123
134
  };
124
135
 
136
+ export const clearTabletData = () => {
137
+ return {
138
+ type: CLEAR_TABLET_DATA,
139
+ } as const;
140
+ };
141
+
125
142
  export default tablet;
@@ -3,6 +3,12 @@ export const TENANT_GENERAL_TABS_IDS = {
3
3
  diagnostics: 'diagnostics',
4
4
  } as const;
5
5
 
6
+ export const TENANT_QUERY_TABS_ID = {
7
+ newQuery: 'newQuery',
8
+ history: 'history',
9
+ saved: 'saved',
10
+ } as const;
11
+
6
12
  export const TENANT_DIAGNOSTICS_TABS_IDS = {
7
13
  overview: 'overview',
8
14
  topQueries: 'topQueries',
@@ -1,7 +1,13 @@
1
1
  import type {Reducer} from 'redux';
2
2
 
3
3
  import type {TTenant} from '../../../types/api/tenant';
4
- import type {TenantAction, TenantDiagnosticsTab, TenantGeneralTab, TenantState} from './types';
4
+ import type {
5
+ TenantAction,
6
+ TenantDiagnosticsTab,
7
+ TenantGeneralTab,
8
+ TenantQueryTab,
9
+ TenantState,
10
+ } from './types';
5
11
 
6
12
  import '../../../services/api';
7
13
  import {createRequestActionTypes, createApiRequest} from '../../utils';
@@ -9,6 +15,7 @@ import {createRequestActionTypes, createApiRequest} from '../../utils';
9
15
  export const FETCH_TENANT = createRequestActionTypes('tenant', 'FETCH_TENANT');
10
16
 
11
17
  const SET_TOP_LEVEL_TAB = 'tenant/SET_TOP_LEVEL_TAB';
18
+ const SET_QUERY_TAB = 'tenant/SET_QUERY_TAB';
12
19
  const SET_DIAGNOSTICS_TAB = 'tenant/SET_DIAGNOSTICS_TAB';
13
20
  const CLEAR_TENANT = 'tenant/CLEAR_TENANT';
14
21
 
@@ -56,7 +63,12 @@ const tenantReducer: Reducer<TenantState, TenantAction> = (state = initialState,
56
63
  topLevelTab: action.data,
57
64
  };
58
65
  }
59
-
66
+ case SET_QUERY_TAB: {
67
+ return {
68
+ ...state,
69
+ queryTab: action.data,
70
+ };
71
+ }
60
72
  case SET_DIAGNOSTICS_TAB: {
61
73
  return {
62
74
  ...state,
@@ -90,6 +102,13 @@ export function setTopLevelTab(tab: TenantGeneralTab) {
90
102
  } as const;
91
103
  }
92
104
 
105
+ export function setQueryTab(tab: TenantQueryTab) {
106
+ return {
107
+ type: SET_QUERY_TAB,
108
+ data: tab,
109
+ } as const;
110
+ }
111
+
93
112
  export function setDiagnosticsTab(tab: TenantDiagnosticsTab) {
94
113
  return {
95
114
  type: SET_DIAGNOSTICS_TAB,
@@ -3,16 +3,22 @@ import type {TTenant} from '../../../types/api/tenant';
3
3
  import type {ValueOf} from '../../../types/common';
4
4
  import type {ApiRequestAction} from '../../utils';
5
5
 
6
- import {TENANT_DIAGNOSTICS_TABS_IDS, TENANT_GENERAL_TABS_IDS} from './constants';
7
- import {FETCH_TENANT, clearTenant, setDiagnosticsTab, setTopLevelTab} from './tenant';
6
+ import {
7
+ TENANT_QUERY_TABS_ID,
8
+ TENANT_DIAGNOSTICS_TABS_IDS,
9
+ TENANT_GENERAL_TABS_IDS,
10
+ } from './constants';
11
+ import {FETCH_TENANT, clearTenant, setDiagnosticsTab, setQueryTab, setTopLevelTab} from './tenant';
8
12
 
9
13
  export type TenantGeneralTab = ValueOf<typeof TENANT_GENERAL_TABS_IDS>;
14
+ export type TenantQueryTab = ValueOf<typeof TENANT_QUERY_TABS_ID>;
10
15
  export type TenantDiagnosticsTab = ValueOf<typeof TENANT_DIAGNOSTICS_TABS_IDS>;
11
16
 
12
17
  export interface TenantState {
13
18
  loading: boolean;
14
19
  wasLoaded: boolean;
15
20
  topLevelTab?: TenantGeneralTab;
21
+ queryTab?: TenantQueryTab;
16
22
  diagnosticsTab?: TenantDiagnosticsTab;
17
23
  tenant?: TTenant;
18
24
  error?: IResponseError;
@@ -22,4 +28,5 @@ export type TenantAction =
22
28
  | ApiRequestAction<typeof FETCH_TENANT, TTenant | undefined, IResponseError>
23
29
  | ReturnType<typeof clearTenant>
24
30
  | ReturnType<typeof setTopLevelTab>
31
+ | ReturnType<typeof setQueryTab>
25
32
  | ReturnType<typeof setDiagnosticsTab>;
@@ -35,7 +35,7 @@ const topic: Reducer<ITopicState, ITopicAction> = (state = initialState, action)
35
35
  };
36
36
  }
37
37
  case FETCH_TOPIC.SUCCESS: {
38
- // On older version it can return HTML page of Internal Viewer with an error
38
+ // On older version it can return HTML page of Developer UI with an error
39
39
  if (typeof action.data !== 'object') {
40
40
  return {...state, loading: false, error: {}};
41
41
  }
@@ -45,7 +45,10 @@ const paramSetup = {
45
45
  general: {
46
46
  stateKey: 'tenant.topLevelTab',
47
47
  },
48
- generalTab: {
48
+ queryTab: {
49
+ stateKey: 'tenant.queryTab',
50
+ },
51
+ diagnosticsTab: {
49
52
  stateKey: 'tenant.diagnosticsTab',
50
53
  },
51
54
  shardsMode: {
@@ -29,3 +29,8 @@ export enum QueryModes {
29
29
  data = 'data',
30
30
  query = 'query',
31
31
  }
32
+
33
+ export interface SavedQuery {
34
+ name: string;
35
+ body: string;
36
+ }
@@ -1,8 +1,8 @@
1
+ import type {ApiRequestAction} from '../../store/utils';
1
2
  import type {IResponseError} from '../api/error';
2
3
  import type {ETabletState, TTabletStateInfo} from '../api/tablet';
3
4
 
4
- import {FETCH_TABLET, FETCH_TABLET_DESCRIBE} from '../../store/reducers/tablet';
5
- import {ApiRequestAction} from '../../store/utils';
5
+ import {FETCH_TABLET, FETCH_TABLET_DESCRIBE, clearTabletData} from '../../store/reducers/tablet';
6
6
 
7
7
  export interface ITabletPreparedHistoryItem {
8
8
  nodeId: string;
@@ -16,7 +16,7 @@ export interface ITabletPreparedHistoryItem {
16
16
 
17
17
  export interface ITabletState {
18
18
  loading: boolean;
19
- tenantPath: string;
19
+ tenantPath?: string;
20
20
  error?: IResponseError;
21
21
  id?: string;
22
22
  history?: ITabletPreparedHistoryItem[];
@@ -44,7 +44,10 @@ type ITabletDescribeApiRequestAction = ApiRequestAction<
44
44
  IResponseError
45
45
  >;
46
46
 
47
- export type ITabletAction = ITabletApiRequestAction | ITabletDescribeApiRequestAction;
47
+ export type ITabletAction =
48
+ | ITabletApiRequestAction
49
+ | ITabletDescribeApiRequestAction
50
+ | ReturnType<typeof clearTabletData>;
48
51
 
49
52
  export interface ITabletRootStateSlice {
50
53
  tablet: ITabletState;
@@ -75,6 +75,8 @@ export const COLORS_PRIORITY = {
75
75
  grey: 1,
76
76
  };
77
77
 
78
+ export const DEVELOPER_UI = 'Developer UI';
79
+
78
80
  export const THEME_KEY = 'theme';
79
81
  export const INVERTED_DISKS_KEY = 'invertedDisks';
80
82
  export const USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY = 'useNodesEndpointInDiagnostics';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ydb-embedded-ui",
3
- "version": "4.6.0",
3
+ "version": "4.7.0",
4
4
  "files": [
5
5
  "dist"
6
6
  ],
@@ -103,6 +103,7 @@
103
103
  "@commitlint/cli": "^15.0.0",
104
104
  "@commitlint/config-conventional": "^15.0.0",
105
105
  "@gravity-ui/eslint-config": "^1.0.2",
106
+ "@gravity-ui/icons": "^2.2.0",
106
107
  "@gravity-ui/prettier-config": "^1.0.1",
107
108
  "@gravity-ui/stylelint-config": "^1.0.1",
108
109
  "@gravity-ui/tsconfig": "^1.0.0",
@@ -1,85 +0,0 @@
1
- $popup-width: 700px;
2
-
3
- .kv-queries-history {
4
- $block: &;
5
- padding: 12px 16px;
6
-
7
- &__empty {
8
- font-weight: 600;
9
- text-align: center;
10
- }
11
- &__popup-wrapper {
12
- overflow: hidden;
13
-
14
- width: $popup-width;
15
- max-width: $popup-width !important;
16
-
17
- border-radius: 4px;
18
- :nth-child(2) {
19
- overflow-y: auto;
20
-
21
- max-height: 50vh;
22
- }
23
-
24
- &::before {
25
- width: $popup-width;
26
-
27
- border-radius: 4px;
28
- }
29
- }
30
- &__saved-queries-row {
31
- display: flex;
32
- align-items: center;
33
-
34
- padding: 8px 5px;
35
-
36
- border-bottom: 1px solid var(--yc-color-line-generic);
37
- &:hover {
38
- cursor: pointer;
39
-
40
- color: var(--yc-color-text-link-hover);
41
- background: var(--yc-color-base-simple-hover);
42
- #{$block}__query-controls {
43
- display: flex;
44
- }
45
- }
46
- &_header {
47
- font-weight: 600;
48
- &:hover {
49
- cursor: auto;
50
-
51
- color: var(--yc-color-text-primary);
52
- background: var(--yc-color-base-background);
53
- }
54
- }
55
- }
56
- &__query-body {
57
- overflow: hidden;
58
- flex-grow: 1;
59
-
60
- white-space: pre;
61
- text-overflow: ellipsis;
62
- &_header {
63
- display: flex;
64
- justify-content: center;
65
- }
66
- }
67
- &__query-controls {
68
- display: none;
69
- }
70
- &__control-button {
71
- display: flex;
72
- justify-content: center;
73
- align-items: center;
74
-
75
- width: 24px;
76
-
77
- color: var(--yc-color-text-hint);
78
- &:hover {
79
- color: var(--yc-color-text-secondary);
80
- }
81
- }
82
- &__dialog-query-name {
83
- font-weight: 500;
84
- }
85
- }