ydb-embedded-ui 4.7.0 → 4.8.1

Sign up to get free protection for your applications and to get access to all the features.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## [4.8.1](https://github.com/ydb-platform/ydb-embedded-ui/compare/v4.8.0...v4.8.1) (2023-06-26)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * **Tenants:** fix tenant link ([#439](https://github.com/ydb-platform/ydb-embedded-ui/issues/439)) ([432c621](https://github.com/ydb-platform/ydb-embedded-ui/commit/432c621eb2fb2ffd5a747299af930236d5cc06f7))
9
+
10
+ ## [4.8.0](https://github.com/ydb-platform/ydb-embedded-ui/compare/v4.7.0...v4.8.0) (2023-06-26)
11
+
12
+
13
+ ### Features
14
+
15
+ * **Tenant:** transform general tabs into left navigation items ([#431](https://github.com/ydb-platform/ydb-embedded-ui/issues/431)) ([7117b96](https://github.com/ydb-platform/ydb-embedded-ui/commit/7117b9622d5f6469dcc2bcc1c0d5cb71d4f94c0b))
16
+
3
17
  ## [4.7.0](https://github.com/ydb-platform/ydb-embedded-ui/compare/v4.6.0...v4.7.0) (2023-06-23)
4
18
 
5
19
 
@@ -7,6 +7,9 @@ import cn from 'bem-cn-lite';
7
7
  import {Icon, Button} from '@gravity-ui/uikit';
8
8
  import {AsideHeader, MenuItem as AsideHeaderMenuItem, FooterItem} from '@gravity-ui/navigation';
9
9
 
10
+ import squareChartBarIcon from '@gravity-ui/icons/svgs/square-chart-bar.svg';
11
+ import pulseIcon from '@gravity-ui/icons/svgs/pulse.svg';
12
+
10
13
  import signOutIcon from '../../assets/icons/signOut.svg';
11
14
  import signInIcon from '../../assets/icons/signIn.svg';
12
15
  import ydbLogoIcon from '../../assets/icons/ydb.svg';
@@ -15,18 +18,20 @@ import userChecked from '../../assets/icons/user-check.svg';
15
18
  import settingsIcon from '../../assets/icons/settings.svg';
16
19
  import supportIcon from '../../assets/icons/support.svg';
17
20
 
18
- import {UserSettings} from '../UserSettings/UserSettings';
19
-
20
- import routes, {createHref} from '../../routes';
21
-
22
21
  import {logout} from '../../store/reducers/authentication';
23
22
  import {getParsedSettingValue, setSettingValue} from '../../store/reducers/settings/settings';
23
+ import {TENANT_PAGE, TENANT_PAGES_IDS} from '../../store/reducers/tenant/constants';
24
+ import routes, {TENANT, createHref, parseQuery} from '../../routes';
25
+ import {useSetting, useTypedSelector} from '../../utils/hooks';
26
+ import {ASIDE_HEADER_COMPACT_KEY, TENANT_INITIAL_PAGE_KEY} from '../../utils/constants';
24
27
 
25
- import {ASIDE_HEADER_COMPACT_KEY} from '../../utils/constants';
28
+ import {getTenantPath} from '../Tenant/TenantPages';
29
+ import {UserSettings} from '../UserSettings/UserSettings';
26
30
 
27
31
  import './AsideNavigation.scss';
28
32
 
29
33
  const b = cn('kv-navigation');
34
+
30
35
  interface MenuItem {
31
36
  id: string;
32
37
  title: string;
@@ -111,32 +116,53 @@ interface AsideNavigationProps {
111
116
  setSettingValue: (name: string, value: string) => void;
112
117
  }
113
118
 
114
- // FIXME: add items or delete
115
- const items: MenuItem[] = [];
116
-
117
119
  enum Panel {
118
120
  UserSettings = 'UserSettings',
119
121
  }
120
122
 
121
- function AsideNavigation(props: AsideNavigationProps) {
123
+ export const useGetLeftNavigationItems = () => {
122
124
  const location = useLocation();
123
125
  const history = useHistory();
124
126
 
125
- const [visiblePanel, setVisiblePanel] = useState<Panel>();
127
+ const [initialTenantPage, setInitialTenantPage] = useSetting<string>(TENANT_INITIAL_PAGE_KEY);
128
+ const {tenantPage = initialTenantPage} = useTypedSelector((state) => state.tenant);
126
129
 
127
- const setIsCompact = (compact: boolean) => {
128
- props.setSettingValue(ASIDE_HEADER_COMPACT_KEY, JSON.stringify(compact));
129
- };
130
+ const {pathname} = location;
131
+ const queryParams = parseQuery(location);
132
+
133
+ const isTenantPage = pathname === `/${TENANT}`;
130
134
 
131
135
  const menuItems: AsideHeaderMenuItem[] = React.useMemo(() => {
132
- const {pathname} = location;
133
- const menuItems: AsideHeaderMenuItem[] = items.map((item) => {
134
- const locationKeysCoincidence = item.locationKeys?.filter((key) =>
135
- pathname.startsWith(key),
136
- );
137
- const current =
138
- (locationKeysCoincidence && locationKeysCoincidence.length > 0) ||
139
- item.location.startsWith(pathname);
136
+ if (!isTenantPage) {
137
+ return [];
138
+ }
139
+
140
+ const items: MenuItem[] = [
141
+ {
142
+ id: TENANT_PAGES_IDS.diagnostics,
143
+ title: 'Diagnostics',
144
+ icon: squareChartBarIcon,
145
+ iconSize: 20,
146
+ location: getTenantPath({
147
+ ...queryParams,
148
+ [TENANT_PAGE]: TENANT_PAGES_IDS.diagnostics,
149
+ }),
150
+ },
151
+ {
152
+ id: TENANT_PAGES_IDS.query,
153
+ title: 'Query',
154
+ icon: pulseIcon,
155
+ iconSize: 20,
156
+ location: getTenantPath({
157
+ ...queryParams,
158
+ [TENANT_PAGE]: TENANT_PAGES_IDS.query,
159
+ }),
160
+ },
161
+ ];
162
+
163
+ return items.map((item) => {
164
+ const current = item.id === tenantPage;
165
+
140
166
  return {
141
167
  id: item.id,
142
168
  title: item.title,
@@ -144,12 +170,26 @@ function AsideNavigation(props: AsideNavigationProps) {
144
170
  iconSize: item.iconSize,
145
171
  current,
146
172
  onItemClick: () => {
173
+ setInitialTenantPage(item.id);
147
174
  history.push(item.location);
148
175
  },
149
176
  };
150
177
  });
151
- return menuItems;
152
- }, [location, history]);
178
+ }, [tenantPage, isTenantPage, setInitialTenantPage, history, queryParams]);
179
+
180
+ return menuItems;
181
+ };
182
+
183
+ function AsideNavigation(props: AsideNavigationProps) {
184
+ const history = useHistory();
185
+
186
+ const [visiblePanel, setVisiblePanel] = useState<Panel>();
187
+
188
+ const setIsCompact = (compact: boolean) => {
189
+ props.setSettingValue(ASIDE_HEADER_COMPACT_KEY, JSON.stringify(compact));
190
+ };
191
+
192
+ const menuItems = useGetLeftNavigationItems();
153
193
 
154
194
  return (
155
195
  <React.Fragment>
@@ -11,9 +11,9 @@ import type {EPathType} from '../../../types/api/schema';
11
11
 
12
12
  import {useTypedSelector} from '../../../utils/hooks';
13
13
  import routes, {createHref} from '../../../routes';
14
- import type {TenantDiagnosticsTab, TenantGeneralTab} from '../../../store/reducers/tenant/types';
14
+ import type {TenantDiagnosticsTab} from '../../../store/reducers/tenant/types';
15
15
  import {enableAutorefresh, disableAutorefresh} from '../../../store/reducers/schema/schema';
16
- import {setTopLevelTab, setDiagnosticsTab} from '../../../store/reducers/tenant/tenant';
16
+ import { setDiagnosticsTab} from '../../../store/reducers/tenant/tenant';
17
17
  import {TENANT_DIAGNOSTICS_TABS_IDS} from '../../../store/reducers/tenant/constants';
18
18
 
19
19
  import {Loader} from '../../../components/Loader';
@@ -96,10 +96,6 @@ function Diagnostics(props: DiagnosticsProps) {
96
96
  }
97
97
  };
98
98
 
99
- const forwardToGeneralTab = (tab: TenantGeneralTab) => {
100
- dispatch(setTopLevelTab(tab));
101
- };
102
-
103
99
  const renderTabContent = () => {
104
100
  const {type} = props;
105
101
 
@@ -116,13 +112,7 @@ function Diagnostics(props: DiagnosticsProps) {
116
112
  );
117
113
  }
118
114
  case TENANT_DIAGNOSTICS_TABS_IDS.topQueries: {
119
- return (
120
- <TopQueries
121
- path={tenantNameString}
122
- changeSchemaTab={forwardToGeneralTab}
123
- type={type}
124
- />
125
- );
115
+ return <TopQueries path={tenantNameString} type={type} />;
126
116
  }
127
117
  case TENANT_DIAGNOSTICS_TABS_IDS.topShards: {
128
118
  return <TopShards tenantPath={tenantNameString} type={type} />;
@@ -22,12 +22,8 @@ import type {KeyValueRow} from '../../../../types/api/query';
22
22
  import type {EPathType} from '../../../../types/api/schema';
23
23
  import type {ITopQueriesFilters} from '../../../../types/store/executeTopQueries';
24
24
  import type {IQueryResult} from '../../../../types/store/query';
25
- import type {TenantGeneralTab} from '../../../../store/reducers/tenant/types';
26
25
 
27
- import {
28
- TENANT_GENERAL_TABS_IDS,
29
- TENANT_QUERY_TABS_ID,
30
- } from '../../../../store/reducers/tenant/constants';
26
+ import {TENANT_PAGE, TENANT_PAGES_IDS, TENANT_QUERY_TABS_ID} from '../../../../store/reducers/tenant/constants';
31
27
  import {formatDateTime, formatNumber} from '../../../../utils';
32
28
  import {HOUR_IN_SECONDS} from '../../../../utils/constants';
33
29
  import {useAutofetcher, useTypedSelector} from '../../../../utils/hooks';
@@ -85,7 +81,6 @@ const COLUMNS: Column<KeyValueRow>[] = [
85
81
 
86
82
  interface TopQueriesProps {
87
83
  path: string;
88
- changeSchemaTab: (tab: TenantGeneralTab) => void;
89
84
  type?: EPathType;
90
85
  }
91
86
 
@@ -177,7 +172,7 @@ export const TopQueries = ({path, type}: TopQueriesProps) => {
177
172
 
178
173
  const queryPath = getTenantPath({
179
174
  ...queryParams,
180
- [TenantTabsGroups.general]: TENANT_GENERAL_TABS_IDS.query,
175
+ [TENANT_PAGE]: TENANT_PAGES_IDS.query,
181
176
  [TenantTabsGroups.queryTab]: TENANT_QUERY_TABS_ID.newQuery,
182
177
  });
183
178
 
@@ -1,11 +1,13 @@
1
- import qs from 'qs';
2
1
  import {useLocation} from 'react-router';
3
2
  import cn from 'bem-cn-lite';
4
3
 
5
4
  import {useThemeValue} from '@gravity-ui/uikit';
6
5
 
7
6
  import type {EPathType} from '../../../types/api/schema';
8
- import {TENANT_GENERAL_TABS_IDS} from '../../../store/reducers/tenant/constants';
7
+ import {TENANT_PAGES_IDS} from '../../../store/reducers/tenant/constants';
8
+ import {useSetting} from '../../../utils/hooks';
9
+ import {TENANT_INITIAL_PAGE_KEY} from '../../../utils/constants';
10
+ import {parseQuery} from '../../../routes';
9
11
 
10
12
  import {Query} from '../Query/Query';
11
13
  import Diagnostics from '../Diagnostics/Diagnostics';
@@ -22,19 +24,17 @@ interface ObjectGeneralProps {
22
24
 
23
25
  function ObjectGeneral(props: ObjectGeneralProps) {
24
26
  const location = useLocation();
25
-
26
27
  const theme = useThemeValue();
27
28
 
28
- const queryParams = qs.parse(location.search, {
29
- ignoreQueryPrefix: true,
30
- });
29
+ const [initialPage] = useSetting<string>(TENANT_INITIAL_PAGE_KEY);
31
30
 
32
- const {name: tenantName, general: generalTab} = queryParams;
31
+ const queryParams = parseQuery(location);
32
+ const {name: tenantName, tenantPage = initialPage} = queryParams;
33
33
 
34
34
  const renderTabContent = () => {
35
35
  const {type, additionalTenantInfo, additionalNodesInfo} = props;
36
- switch (generalTab) {
37
- case TENANT_GENERAL_TABS_IDS.query: {
36
+ switch (tenantPage) {
37
+ case TENANT_PAGES_IDS.query: {
38
38
  return <Query path={tenantName as string} theme={theme} type={type} />;
39
39
  }
40
40
  default: {
@@ -47,9 +47,9 @@ import {
47
47
  PaneVisibilityToggleButtons,
48
48
  } from '../utils/paneVisibilityToggleHelpers';
49
49
  import {setShowPreview} from '../../../store/reducers/schema/schema';
50
- import {setQueryTab, setTopLevelTab} from '../../../store/reducers/tenant/tenant';
50
+ import {setQueryTab, setTenantPage} from '../../../store/reducers/tenant/tenant';
51
51
  import {
52
- TENANT_GENERAL_TABS_IDS,
52
+ TENANT_PAGES_IDS,
53
53
  TENANT_QUERY_TABS_ID,
54
54
  } from '../../../store/reducers/tenant/constants';
55
55
 
@@ -278,7 +278,7 @@ function ObjectSummary(props: ObjectSummaryProps) {
278
278
 
279
279
  const onOpenPreview = () => {
280
280
  dispatch(setShowPreview(true));
281
- dispatch(setTopLevelTab(TENANT_GENERAL_TABS_IDS.query));
281
+ dispatch(setTenantPage(TENANT_PAGES_IDS.query));
282
282
  dispatch(setQueryTab(TENANT_QUERY_TABS_ID.newQuery));
283
283
  };
284
284
 
@@ -15,6 +15,7 @@ import {
15
15
  goToNextQuery,
16
16
  MONACO_HOT_KEY_ACTIONS,
17
17
  setMonacoHotKey,
18
+ setTenantPath,
18
19
  } from '../../../../store/reducers/executeQuery';
19
20
  import {getExplainQuery, getExplainQueryAst} from '../../../../store/reducers/explainQuery';
20
21
  import {getParsedSettingValue, setSettingValue} from '../../../../store/reducers/settings/settings';
@@ -75,6 +76,7 @@ const propTypes = {
75
76
  theme: PropTypes.string,
76
77
  type: PropTypes.string,
77
78
  initialQueryMode: PropTypes.string,
79
+ setTenantPath: PropTypes.func,
78
80
  };
79
81
 
80
82
  const initialTenantCommonInfoState = {
@@ -83,6 +85,9 @@ const initialTenantCommonInfoState = {
83
85
  collapsed: true,
84
86
  };
85
87
  function QueryEditor(props) {
88
+ const {path, executeQuery, theme, setTenantPath, changeUserInput} = props;
89
+ const {tenantPath: savedPath} = executeQuery;
90
+
86
91
  const [resultType, setResultType] = useState(RESULT_TYPES.EXECUTE);
87
92
 
88
93
  const [isResultLoaded, setIsResultLoaded] = useState(false);
@@ -96,6 +101,13 @@ function QueryEditor(props) {
96
101
  }
97
102
  }, [enableAdditionalQueryModes, queryMode, setQueryMode]);
98
103
 
104
+ useEffect(() => {
105
+ if (savedPath !== path) {
106
+ setTenantPath(path);
107
+ changeUserInput({input: ''});
108
+ }
109
+ }, [changeUserInput, setTenantPath, path, savedPath]);
110
+
99
111
  const [resultVisibilityState, dispatchResultVisibilityState] = useReducer(
100
112
  paneVisibilityToggleReducerCreator(DEFAULT_IS_QUERY_RESULT_COLLAPSED),
101
113
  initialTenantCommonInfoState,
@@ -507,7 +519,6 @@ function QueryEditor(props) {
507
519
  );
508
520
  };
509
521
 
510
- const {executeQuery, theme} = props;
511
522
  const result = renderResult();
512
523
 
513
524
  return (
@@ -569,6 +580,7 @@ const mapDispatchToProps = {
569
580
  setSettingValue,
570
581
  setShowPreview,
571
582
  setMonacoHotKey,
583
+ setTenantPath,
572
584
  };
573
585
 
574
586
  QueryEditor.propTypes = propTypes;
@@ -6,12 +6,4 @@
6
6
  font-size: var(--yc-text-body-2-font-size);
7
7
  line-height: var(--yc-text-body-2-line-height);
8
8
  @include flex-container();
9
-
10
- .yc-tabs {
11
- overflow: initial;
12
- }
13
-
14
- &__tab-content {
15
- height: calc(100% - 56px); // general tabs height
16
- }
17
9
  }
@@ -15,7 +15,6 @@ import {getSchemaAcl} from '../../store/reducers/schemaAcl/schemaAcl';
15
15
  import SplitPane from '../../components/SplitPane';
16
16
  import {AccessDenied} from '../../components/Errors/403';
17
17
 
18
- import ObjectGeneralTabs from './ObjectGeneralTabs/ObjectGeneralTabs';
19
18
  import ObjectSummary from './ObjectSummary/ObjectSummary';
20
19
  import ObjectGeneral from './ObjectGeneral/ObjectGeneral';
21
20
 
@@ -111,33 +110,28 @@ function Tenant(props: TenantProps) {
111
110
  {showBlockingError ? (
112
111
  <AccessDenied />
113
112
  ) : (
114
- <>
115
- <ObjectGeneralTabs />
116
- <div className={b('tab-content')}>
117
- <SplitPane
118
- defaultSizePaneKey={DEFAULT_SIZE_TENANT_KEY}
119
- defaultSizes={[25, 75]}
120
- triggerCollapse={summaryVisibilityState.triggerCollapse}
121
- triggerExpand={summaryVisibilityState.triggerExpand}
122
- minSize={[36, 200]}
123
- onSplitStartDragAdditional={onSplitStartDragAdditional}
124
- >
125
- <ObjectSummary
126
- type={preloadedPathType || currentPathType}
127
- subType={preloadedPathSubType || currentPathSubType}
128
- onCollapseSummary={onCollapseSummaryHandler}
129
- onExpandSummary={onExpandSummaryHandler}
130
- isCollapsed={summaryVisibilityState.collapsed}
131
- additionalTenantInfo={props.additionalTenantInfo}
132
- />
133
- <ObjectGeneral
134
- type={preloadedPathType || currentPathType}
135
- additionalTenantInfo={props.additionalTenantInfo}
136
- additionalNodesInfo={props.additionalNodesInfo}
137
- />
138
- </SplitPane>
139
- </div>
140
- </>
113
+ <SplitPane
114
+ defaultSizePaneKey={DEFAULT_SIZE_TENANT_KEY}
115
+ defaultSizes={[25, 75]}
116
+ triggerCollapse={summaryVisibilityState.triggerCollapse}
117
+ triggerExpand={summaryVisibilityState.triggerExpand}
118
+ minSize={[36, 200]}
119
+ onSplitStartDragAdditional={onSplitStartDragAdditional}
120
+ >
121
+ <ObjectSummary
122
+ type={preloadedPathType || currentPathType}
123
+ subType={preloadedPathSubType || currentPathSubType}
124
+ onCollapseSummary={onCollapseSummaryHandler}
125
+ onExpandSummary={onExpandSummaryHandler}
126
+ isCollapsed={summaryVisibilityState.collapsed}
127
+ additionalTenantInfo={props.additionalTenantInfo}
128
+ />
129
+ <ObjectGeneral
130
+ type={preloadedPathType || currentPathType}
131
+ additionalTenantInfo={props.additionalTenantInfo}
132
+ additionalNodesInfo={props.additionalNodesInfo}
133
+ />
134
+ </SplitPane>
141
135
  )}
142
136
  </div>
143
137
  );
@@ -1,6 +1,4 @@
1
- import {TENANT_GENERAL_TABS_IDS} from '../../store/reducers/tenant/constants';
2
1
  import routes, {createHref} from '../../routes';
3
- import {Icon} from '../../components/Icon';
4
2
 
5
3
  export enum TenantInfoTabsIds {
6
4
  overview = 'overview',
@@ -10,23 +8,10 @@ export enum TenantInfoTabsIds {
10
8
 
11
9
  export enum TenantTabsGroups {
12
10
  info = 'info',
13
- general = 'general',
14
11
  queryTab = 'queryTab',
15
12
  diagnosticsTab = 'diagnosticsTab',
16
13
  }
17
14
 
18
- export const TENANT_GENERAL_TABS = [
19
- {
20
- id: TENANT_GENERAL_TABS_IDS.query,
21
- title: 'Query',
22
- icon: <Icon name="query" viewBox="0 0 16 16" />,
23
- },
24
- {
25
- id: TENANT_GENERAL_TABS_IDS.diagnostics,
26
- title: 'Diagnostics',
27
- icon: <Icon name="diagnostics" viewBox="0 0 17 16" />,
28
- },
29
- ];
30
15
  export const TENANT_INFO_TABS = [
31
16
  {
32
17
  id: TenantInfoTabsIds.overview,
@@ -3,10 +3,10 @@ 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 {setQueryTab, setTopLevelTab} from '../../../store/reducers/tenant/tenant';
6
+ import {setQueryTab, setTenantPage} from '../../../store/reducers/tenant/tenant';
7
7
  import {
8
8
  TENANT_QUERY_TABS_ID,
9
- TENANT_GENERAL_TABS_IDS,
9
+ TENANT_PAGES_IDS,
10
10
  } from '../../../store/reducers/tenant/constants';
11
11
  import createToast from '../../../utils/createToast';
12
12
 
@@ -40,7 +40,7 @@ const bindActions = (
40
40
  ) => {
41
41
  const inputQuery = (tmpl: (path: string) => string) => () => {
42
42
  dispatch(changeUserInput({input: tmpl(path)}));
43
- dispatch(setTopLevelTab(TENANT_GENERAL_TABS_IDS.query));
43
+ dispatch(setTenantPage(TENANT_PAGES_IDS.query));
44
44
  dispatch(setQueryTab(TENANT_QUERY_TABS_ID.newQuery));
45
45
  setActivePath(path);
46
46
  };
@@ -70,7 +70,7 @@ const bindActions = (
70
70
  },
71
71
  openPreview: () => {
72
72
  dispatch(setShowPreview(true));
73
- dispatch(setTopLevelTab(TENANT_GENERAL_TABS_IDS.query));
73
+ dispatch(setTenantPage(TENANT_PAGES_IDS.query));
74
74
  dispatch(setQueryTab(TENANT_QUERY_TABS_ID.newQuery));
75
75
  setActivePath(path);
76
76
  },
@@ -18,16 +18,12 @@ import {AutoFetcher} from '../../utils/autofetcher';
18
18
  import routes, {createHref} from '../../routes';
19
19
  import {formatCPU, formatBytesToGigabyte, formatNumber} from '../../utils';
20
20
  import {withSearch} from '../../HOCS';
21
- import {DEFAULT_TABLE_SETTINGS, TENANT_INITIAL_TAB_KEY} from '../../utils/constants';
21
+ import {DEFAULT_TABLE_SETTINGS} from '../../utils/constants';
22
22
  import {getTenantsInfo} from '../../store/reducers/tenants/tenants';
23
- import {
24
- changeFilter,
25
- getSettingValue,
26
- ProblemFilterValues,
27
- } from '../../store/reducers/settings/settings';
23
+ import {changeFilter, ProblemFilterValues} from '../../store/reducers/settings/settings';
28
24
 
29
25
  import {clusterName} from '../../store';
30
- import {TenantTabsGroups, TENANT_GENERAL_TABS, TENANT_INFO_TABS} from '../Tenant/TenantPages';
26
+ import {TenantTabsGroups, TENANT_INFO_TABS} from '../Tenant/TenantPages';
31
27
 
32
28
  import './Tenants.scss';
33
29
 
@@ -114,7 +110,6 @@ class Tenants extends React.Component {
114
110
  filter,
115
111
  handleSearchQuery,
116
112
  additionalTenantsInfo = {},
117
- savedTenantInitialTab,
118
113
  } = this.props;
119
114
 
120
115
  const filteredTenantsBySearch = tenants.filter((item) => {
@@ -123,7 +118,6 @@ class Tenants extends React.Component {
123
118
  });
124
119
  const filteredTenants = Tenants.filterTenants(filteredTenantsBySearch, filter);
125
120
 
126
- const initialTenantGeneralTab = savedTenantInitialTab || TENANT_GENERAL_TABS[0].id;
127
121
  const initialTenantInfoTab = TENANT_INFO_TABS[0].id;
128
122
 
129
123
  const getTenantBackend = (tenant) => {
@@ -153,7 +147,6 @@ class Tenants extends React.Component {
153
147
  name: value,
154
148
  backend,
155
149
  [TenantTabsGroups.info]: initialTenantInfoTab,
156
- [TenantTabsGroups.general]: initialTenantGeneralTab,
157
150
  })}
158
151
  />
159
152
  {additionalTenantsInfo.name && additionalTenantsInfo.name(value, row)}
@@ -359,7 +352,6 @@ const mapStateToProps = (state) => {
359
352
  loading,
360
353
  error,
361
354
  filter: state.settings.problemFilter,
362
- savedTenantInitialTab: getSettingValue(state, TENANT_INITIAL_TAB_KEY),
363
355
  };
364
356
  };
365
357
 
package/dist/routes.ts CHANGED
@@ -5,13 +5,18 @@ import isEmpty from 'lodash/isEmpty';
5
5
 
6
6
  import {backend, clusterName, webVersion} from './store';
7
7
 
8
+ export const CLUSTER = 'cluster';
9
+ export const TENANT = 'tenant';
10
+ export const NODE = 'node';
11
+ export const TABLET = 'tablet';
12
+
8
13
  const routes = {
9
- cluster: '/cluster/:activeTab?',
10
- tenant: '/tenant',
11
- node: '/node/:id/:activeTab?',
12
- tablet: '/tablet/:id',
13
- tabletsFilters: '/tabletsFilters',
14
- auth: '/auth',
14
+ cluster: `/${CLUSTER}/:activeTab?`,
15
+ tenant: `/${TENANT}`,
16
+ node: `/${NODE}/:id/:activeTab?`,
17
+ tablet: `/${TABLET}/:id`,
18
+ tabletsFilters: `/tabletsFilters`,
19
+ auth: `/auth`,
15
20
  };
16
21
 
17
22
  export const parseQuery = (location: Location) => {
@@ -23,7 +23,8 @@ const CHANGE_USER_INPUT = 'query/CHANGE_USER_INPUT';
23
23
  const SAVE_QUERY_TO_HISTORY = 'query/SAVE_QUERY_TO_HISTORY';
24
24
  const GO_TO_PREVIOUS_QUERY = 'query/GO_TO_PREVIOUS_QUERY';
25
25
  const GO_TO_NEXT_QUERY = 'query/GO_TO_NEXT_QUERY';
26
- const MONACO_HOT_KEY = 'query/MONACO_HOT_KEY';
26
+ const SET_MONACO_HOT_KEY = 'query/SET_MONACO_HOT_KEY';
27
+ const SET_TENANT_PATH = 'query/SET_TENANT_PATH';
27
28
 
28
29
  const queriesHistoryInitial: string[] = parseJson(getValueFromLS(QUERIES_HISTORY_KEY, '[]'));
29
30
 
@@ -128,12 +129,18 @@ const executeQuery: Reducer<ExecuteQueryState, ExecuteQueryAction> = (
128
129
  };
129
130
  }
130
131
 
131
- case MONACO_HOT_KEY: {
132
+ case SET_MONACO_HOT_KEY: {
132
133
  return {
133
134
  ...state,
134
135
  monacoHotKey: action.data,
135
136
  };
136
137
  }
138
+ case SET_TENANT_PATH: {
139
+ return {
140
+ ...state,
141
+ tenantPath: action.data,
142
+ };
143
+ }
137
144
 
138
145
  default:
139
146
  return state;
@@ -188,7 +195,14 @@ export const changeUserInput = ({input}: {input: string}) => {
188
195
 
189
196
  export const setMonacoHotKey = (value: MonacoHotKeyAction | null) => {
190
197
  return {
191
- type: MONACO_HOT_KEY,
198
+ type: SET_MONACO_HOT_KEY,
199
+ data: value,
200
+ } as const;
201
+ };
202
+
203
+ export const setTenantPath = (value: string) => {
204
+ return {
205
+ type: SET_TENANT_PATH,
192
206
  data: value,
193
207
  } as const;
194
208
  };
@@ -5,7 +5,7 @@ import type {ValueOf} from '../../../types/common';
5
5
  import {
6
6
  SAVED_QUERIES_KEY,
7
7
  THEME_KEY,
8
- TENANT_INITIAL_TAB_KEY,
8
+ TENANT_INITIAL_PAGE_KEY,
9
9
  INVERTED_DISKS_KEY,
10
10
  ASIDE_HEADER_COMPACT_KEY,
11
11
  USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY,
@@ -18,6 +18,8 @@ import '../../../services/api';
18
18
  import {getValueFromLS, parseJson} from '../../../utils/utils';
19
19
  import {QueryModes} from '../../../types/store/query';
20
20
 
21
+ import {TENANT_PAGES_IDS} from '../tenant/constants';
22
+
21
23
  import type {RootState} from '..';
22
24
  import type {
23
25
  SetSettingValueAction,
@@ -58,7 +60,10 @@ export const initialState = {
58
60
  'false',
59
61
  ),
60
62
  [SAVED_QUERIES_KEY]: readSavedSettingsValue(SAVED_QUERIES_KEY, '[]'),
61
- [TENANT_INITIAL_TAB_KEY]: readSavedSettingsValue(TENANT_INITIAL_TAB_KEY),
63
+ [TENANT_INITIAL_PAGE_KEY]: readSavedSettingsValue(
64
+ TENANT_INITIAL_PAGE_KEY,
65
+ TENANT_PAGES_IDS.query,
66
+ ),
62
67
  [QUERY_INITIAL_MODE_KEY]: readSavedSettingsValue(QUERY_INITIAL_MODE_KEY, QueryModes.script),
63
68
  [ASIDE_HEADER_COMPACT_KEY]: readSavedSettingsValue(ASIDE_HEADER_COMPACT_KEY, 'true'),
64
69
  [PARTITIONS_HIDDEN_COLUMNS_KEY]: readSavedSettingsValue(PARTITIONS_HIDDEN_COLUMNS_KEY),
@@ -1,4 +1,6 @@
1
- export const TENANT_GENERAL_TABS_IDS = {
1
+ export const TENANT_PAGE = 'tenantPage';
2
+
3
+ export const TENANT_PAGES_IDS = {
2
4
  query: 'query',
3
5
  diagnostics: 'diagnostics',
4
6
  } as const;
@@ -4,7 +4,7 @@ import type {TTenant} from '../../../types/api/tenant';
4
4
  import type {
5
5
  TenantAction,
6
6
  TenantDiagnosticsTab,
7
- TenantGeneralTab,
7
+ TenantPage,
8
8
  TenantQueryTab,
9
9
  TenantState,
10
10
  } from './types';
@@ -60,7 +60,7 @@ const tenantReducer: Reducer<TenantState, TenantAction> = (state = initialState,
60
60
  case SET_TOP_LEVEL_TAB: {
61
61
  return {
62
62
  ...state,
63
- topLevelTab: action.data,
63
+ tenantPage: action.data,
64
64
  };
65
65
  }
66
66
  case SET_QUERY_TAB: {
@@ -95,10 +95,10 @@ export const clearTenant = () => {
95
95
  return {type: CLEAR_TENANT} as const;
96
96
  };
97
97
 
98
- export function setTopLevelTab(tab: TenantGeneralTab) {
98
+ export function setTenantPage(page: TenantPage) {
99
99
  return {
100
100
  type: SET_TOP_LEVEL_TAB,
101
- data: tab,
101
+ data: page,
102
102
  } as const;
103
103
  }
104
104
 
@@ -3,21 +3,18 @@ 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 {
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';
6
+ import {TENANT_QUERY_TABS_ID, TENANT_DIAGNOSTICS_TABS_IDS, TENANT_PAGES_IDS} from './constants';
7
+ import {FETCH_TENANT, clearTenant, setDiagnosticsTab, setQueryTab, setTenantPage} from './tenant';
8
+
9
+ export type TenantPage = ValueOf<typeof TENANT_PAGES_IDS>;
12
10
 
13
- export type TenantGeneralTab = ValueOf<typeof TENANT_GENERAL_TABS_IDS>;
14
11
  export type TenantQueryTab = ValueOf<typeof TENANT_QUERY_TABS_ID>;
15
12
  export type TenantDiagnosticsTab = ValueOf<typeof TENANT_DIAGNOSTICS_TABS_IDS>;
16
13
 
17
14
  export interface TenantState {
18
15
  loading: boolean;
19
16
  wasLoaded: boolean;
20
- topLevelTab?: TenantGeneralTab;
17
+ tenantPage?: TenantPage;
21
18
  queryTab?: TenantQueryTab;
22
19
  diagnosticsTab?: TenantDiagnosticsTab;
23
20
  tenant?: TTenant;
@@ -27,6 +24,6 @@ export interface TenantState {
27
24
  export type TenantAction =
28
25
  | ApiRequestAction<typeof FETCH_TENANT, TTenant | undefined, IResponseError>
29
26
  | ReturnType<typeof clearTenant>
30
- | ReturnType<typeof setTopLevelTab>
27
+ | ReturnType<typeof setTenantPage>
31
28
  | ReturnType<typeof setQueryTab>
32
29
  | ReturnType<typeof setDiagnosticsTab>;
@@ -42,8 +42,8 @@ const paramSetup = {
42
42
  stateKey: 'tablets.typeFilter',
43
43
  type: 'array',
44
44
  },
45
- general: {
46
- stateKey: 'tenant.topLevelTab',
45
+ tenantPage: {
46
+ stateKey: 'tenant.tenantPage',
47
47
  },
48
48
  queryTab: {
49
49
  stateKey: 'tenant.queryTab',
@@ -5,6 +5,7 @@ import {
5
5
  goToPreviousQuery,
6
6
  setMonacoHotKey,
7
7
  goToNextQuery,
8
+ setTenantPath,
8
9
  MONACO_HOT_KEY_ACTIONS,
9
10
  } from '../../store/reducers/executeQuery';
10
11
  import type {ApiRequestAction} from '../../store/utils';
@@ -22,6 +23,7 @@ export interface ExecuteQueryState {
22
23
  currentIndex: number;
23
24
  };
24
25
  monacoHotKey: null | MonacoHotKeyAction;
26
+ tenantPath?: string;
25
27
  data?: IQueryResult;
26
28
  stats?: IQueryResult['stats'];
27
29
  error?: string | ErrorResponse;
@@ -35,4 +37,5 @@ export type ExecuteQueryAction =
35
37
  | ReturnType<typeof goToPreviousQuery>
36
38
  | ReturnType<typeof changeUserInput>
37
39
  | ReturnType<typeof saveQueryToHistory>
38
- | ReturnType<typeof setMonacoHotKey>;
40
+ | ReturnType<typeof setMonacoHotKey>
41
+ | ReturnType<typeof setTenantPath>;
@@ -104,9 +104,11 @@ export const DEFAULT_TABLE_SETTINGS = {
104
104
  highlightRows: true,
105
105
  } as const;
106
106
 
107
- export const TENANT_INITIAL_TAB_KEY = 'saved_tenant_initial_tab';
108
107
  export const QUERY_INITIAL_MODE_KEY = 'query_initial_mode';
109
108
 
110
109
  export const PARTITIONS_HIDDEN_COLUMNS_KEY = 'partitionsHiddenColumns';
111
110
 
112
111
  export const CLUSTER_INFO_HIDDEN_KEY = 'clusterInfoHidden';
112
+
113
+ // Remain "tab" in key name for backward compatibility
114
+ export const TENANT_INITIAL_PAGE_KEY = 'saved_tenant_initial_tab';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ydb-embedded-ui",
3
- "version": "4.7.0",
3
+ "version": "4.8.1",
4
4
  "files": [
5
5
  "dist"
6
6
  ],
@@ -1,9 +0,0 @@
1
- @import '../../../styles/mixins.scss';
2
-
3
- .object-general-tabs {
4
- padding: 12px 20px 0 12px;
5
-
6
- &__tab {
7
- text-decoration: none;
8
- }
9
- }
@@ -1,68 +0,0 @@
1
- import qs from 'qs';
2
- import {connect} from 'react-redux';
3
- import {useLocation} from 'react-router';
4
- import {Link} from 'react-router-dom';
5
- import cn from 'bem-cn-lite';
6
-
7
- import {Tabs} from '@gravity-ui/uikit';
8
-
9
- import routes, {createHref} from '../../../routes';
10
- import {TENANT_INITIAL_TAB_KEY} from '../../../utils/constants';
11
- import {setSettingValue} from '../../../store/reducers/settings/settings';
12
-
13
- import {TenantTabsGroups, TENANT_GENERAL_TABS} from '../TenantPages';
14
-
15
- import './ObjectGeneralTabs.scss';
16
-
17
- const b = cn('object-general-tabs');
18
-
19
- interface ObjectGeneralTabsProps {
20
- setSettingValue: (name: string, value: string) => void;
21
- }
22
-
23
- function ObjectGeneralTabs(props: ObjectGeneralTabsProps) {
24
- const location = useLocation();
25
-
26
- const queryParams = qs.parse(location.search, {
27
- ignoreQueryPrefix: true,
28
- });
29
-
30
- const {name: tenantName, general: generalTab} = queryParams;
31
-
32
- const renderContent = () => {
33
- if (!tenantName) {
34
- return null;
35
- }
36
- return (
37
- <div className={b()}>
38
- <Tabs
39
- size="xl"
40
- items={TENANT_GENERAL_TABS}
41
- activeTab={generalTab as string}
42
- wrapTo={({id}, node) => {
43
- const path = createHref(routes.tenant, undefined, {
44
- ...queryParams,
45
- name: tenantName as string,
46
- [TenantTabsGroups.general]: id,
47
- });
48
- return (
49
- <Link to={path} key={id} className={b('tab')}>
50
- {node}
51
- </Link>
52
- );
53
- }}
54
- allowNotSelected
55
- onSelectTab={(id) => props.setSettingValue(TENANT_INITIAL_TAB_KEY, id)}
56
- />
57
- </div>
58
- );
59
- };
60
-
61
- return renderContent();
62
- }
63
-
64
- const mapDispatchToProps = {
65
- setSettingValue,
66
- };
67
-
68
- export default connect(null, mapDispatchToProps)(ObjectGeneralTabs);