ydb-embedded-ui 4.4.0 → 4.4.2

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## [4.4.2](https://github.com/ydb-platform/ydb-embedded-ui/compare/v4.4.1...v4.4.2) (2023-05-29)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * **Partitions:** fix offsets calculation ([#402](https://github.com/ydb-platform/ydb-embedded-ui/issues/402)) ([fd4741f](https://github.com/ydb-platform/ydb-embedded-ui/commit/fd4741f8761aa6aa9ec31681522c4d261a83273f))
9
+
10
+ ## [4.4.1](https://github.com/ydb-platform/ydb-embedded-ui/compare/v4.4.0...v4.4.1) (2023-05-25)
11
+
12
+
13
+ ### Bug Fixes
14
+
15
+ * **Nodes:** fix endpoint setting ([#397](https://github.com/ydb-platform/ydb-embedded-ui/issues/397)) ([4aea8a2](https://github.com/ydb-platform/ydb-embedded-ui/commit/4aea8a2597909338e31ac51577989a4d82ec93cf))
16
+
3
17
  ## [4.4.0](https://github.com/ydb-platform/ydb-embedded-ui/compare/v4.3.0...v4.4.0) (2023-05-25)
4
18
 
5
19
 
@@ -1,9 +1,10 @@
1
1
  import {RadioButton} from '@gravity-ui/uikit';
2
2
 
3
- import {ALL, PROBLEMS, IProblemFilterValues} from '../../utils/constants';
3
+ import type {ValueOf} from '../../types/common';
4
+ import {ProblemFilterValues} from '../../store/reducers/settings/settings';
4
5
 
5
6
  interface ProblemFilterProps {
6
- value: IProblemFilterValues;
7
+ value: ValueOf<typeof ProblemFilterValues>;
7
8
  onChange: (value: string) => void;
8
9
  className?: string;
9
10
  }
@@ -11,8 +12,12 @@ interface ProblemFilterProps {
11
12
  export const ProblemFilter = ({value, onChange, className}: ProblemFilterProps) => {
12
13
  return (
13
14
  <RadioButton value={value} onUpdate={onChange} className={className}>
14
- <RadioButton.Option value={ALL}>{ALL}</RadioButton.Option>
15
- <RadioButton.Option value={PROBLEMS}>{PROBLEMS}</RadioButton.Option>
15
+ <RadioButton.Option value={ProblemFilterValues.ALL}>
16
+ {ProblemFilterValues.ALL}
17
+ </RadioButton.Option>
18
+ <RadioButton.Option value={ProblemFilterValues.PROBLEMS}>
19
+ {ProblemFilterValues.PROBLEMS}
20
+ </RadioButton.Option>
16
21
  </RadioButton>
17
22
  );
18
23
  };
@@ -16,7 +16,7 @@ import ReduxTooltip from '../ReduxTooltip/ReduxTooltip';
16
16
  import Header from '../Header/Header';
17
17
  import AppIcons from '../AppIcons/AppIcons';
18
18
 
19
- import {getParsedSettingValue} from '../../store/reducers/settings';
19
+ import {getParsedSettingValue} from '../../store/reducers/settings/settings';
20
20
  import {THEME_KEY} from '../../utils/constants';
21
21
 
22
22
  import './App.scss';
@@ -24,7 +24,7 @@ import {UserSettings} from '../UserSettings/UserSettings';
24
24
  import routes, {createHref, CLUSTER_PAGES} from '../../routes';
25
25
 
26
26
  import {logout} from '../../store/reducers/authentication';
27
- import {getSettingValue, setSettingValue} from '../../store/reducers/settings';
27
+ import {getParsedSettingValue, setSettingValue} from '../../store/reducers/settings/settings';
28
28
 
29
29
  import {ASIDE_HEADER_COMPACT_KEY} from '../../utils/constants';
30
30
 
@@ -273,7 +273,7 @@ const mapStateToProps = (state: any) => {
273
273
 
274
274
  return {
275
275
  ydbUser,
276
- compact: JSON.parse(getSettingValue(state, ASIDE_HEADER_COMPACT_KEY)),
276
+ compact: getParsedSettingValue(state, ASIDE_HEADER_COMPACT_KEY),
277
277
  };
278
278
  };
279
279
 
@@ -5,6 +5,7 @@ import {useDispatch} from 'react-redux';
5
5
  import DataTable from '@gravity-ui/react-data-table';
6
6
 
7
7
  import type {EPathType} from '../../types/api/schema';
8
+ import type {ValueOf} from '../../types/common';
8
9
 
9
10
  import {AccessDenied} from '../../components/Errors/403';
10
11
  import {Illustration} from '../../components/Illustration';
@@ -16,11 +17,7 @@ import {EntitiesCount} from '../../components/EntitiesCount';
16
17
 
17
18
  import routes, {CLUSTER_PAGES, createHref} from '../../routes';
18
19
 
19
- import {
20
- ALL,
21
- DEFAULT_TABLE_SETTINGS,
22
- USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY,
23
- } from '../../utils/constants';
20
+ import {DEFAULT_TABLE_SETTINGS, USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY} from '../../utils/constants';
24
21
  import {useAutofetcher, useSetting, useTypedSelector} from '../../utils/hooks';
25
22
  import {AdditionalNodesInfo, isUnavailableNode, NodesUptimeFilterValues} from '../../utils/nodes';
26
23
 
@@ -33,7 +30,7 @@ import {
33
30
  resetNodesState,
34
31
  getComputeNodes,
35
32
  } from '../../store/reducers/nodes';
36
- import {changeFilter} from '../../store/reducers/settings';
33
+ import {changeFilter, ProblemFilterValues} from '../../store/reducers/settings/settings';
37
34
  import {hideTooltip, showTooltip} from '../../store/reducers/tooltip';
38
35
 
39
36
  import {isDatabaseEntityType} from '../Tenant/utils/schema';
@@ -77,7 +74,7 @@ export const Nodes = ({path, type, className, additionalNodesInfo = {}}: NodesPr
77
74
  const fetchNodes = useCallback(() => {
78
75
  // For not DB entities we always use /compute endpoint instead of /nodes
79
76
  // since /nodes can return data only for tenants
80
- if (path && (useNodesEndpoint || !isDatabaseEntityType(type))) {
77
+ if (path && (!useNodesEndpoint || !isDatabaseEntityType(type))) {
81
78
  dispatch(getComputeNodes(path));
82
79
  } else {
83
80
  dispatch(getNodes({tenant: path}));
@@ -104,7 +101,7 @@ export const Nodes = ({path, type, className, additionalNodesInfo = {}}: NodesPr
104
101
  };
105
102
 
106
103
  const handleProblemFilterChange = (value: string) => {
107
- dispatch(changeFilter(value));
104
+ dispatch(changeFilter(value as ValueOf<typeof ProblemFilterValues>));
108
105
  };
109
106
 
110
107
  const handleUptimeFilterChange = (value: string) => {
@@ -148,7 +145,10 @@ export const Nodes = ({path, type, className, additionalNodesInfo = {}}: NodesPr
148
145
  });
149
146
 
150
147
  if (nodes && nodes.length === 0) {
151
- if (problemFilter !== ALL || nodesUptimeFilter !== NodesUptimeFilterValues.All) {
148
+ if (
149
+ problemFilter !== ProblemFilterValues.ALL ||
150
+ nodesUptimeFilter !== NodesUptimeFilterValues.All
151
+ ) {
152
152
  return <Illustration name="thumbsUp" width="200" />;
153
153
  }
154
154
  }
@@ -14,8 +14,7 @@ import {Illustration} from '../../../../components/Illustration';
14
14
 
15
15
  import {getNetworkInfo, setDataWasNotLoaded} from '../../../../store/reducers/network';
16
16
  import {hideTooltip, showTooltip} from '../../../../store/reducers/tooltip';
17
- import {ALL, PROBLEMS} from '../../../../utils/constants';
18
- import {changeFilter} from '../../../../store/reducers/settings';
17
+ import {changeFilter, ProblemFilterValues} from '../../../../store/reducers/settings/settings';
19
18
  import {AutoFetcher} from '../../../../utils/autofetcher';
20
19
  import {getDefaultNodePath} from '../../../Node/NodePages';
21
20
 
@@ -178,8 +177,9 @@ class Network extends React.Component {
178
177
  }
179
178
 
180
179
  if (
181
- (filter === PROBLEMS && capacity !== connected) ||
182
- filter === ALL ||
180
+ (filter === ProblemFilterValues.PROBLEMS &&
181
+ capacity !== connected) ||
182
+ filter === ProblemFilterValues.ALL ||
183
183
  isRight
184
184
  ) {
185
185
  problemNodesCount++;
@@ -218,8 +218,9 @@ class Network extends React.Component {
218
218
  }
219
219
 
220
220
  if (
221
- (filter === PROBLEMS && capacity !== connected) ||
222
- filter === ALL ||
221
+ (filter === ProblemFilterValues.PROBLEMS &&
222
+ capacity !== connected) ||
223
+ filter === ProblemFilterValues.ALL ||
223
224
  isRight
224
225
  ) {
225
226
  problemNodesCount++;
@@ -254,7 +255,7 @@ class Network extends React.Component {
254
255
  );
255
256
  });
256
257
 
257
- if (filter === PROBLEMS && problemNodesCount === 0) {
258
+ if (filter === ProblemFilterValues.PROBLEMS && problemNodesCount === 0) {
258
259
  return <Illustration name="thumbsUp" width="200" />;
259
260
  } else {
260
261
  return result;
@@ -8,7 +8,7 @@ import {Tabs} from '@gravity-ui/uikit';
8
8
 
9
9
  import routes, {createHref} from '../../../routes';
10
10
  import {TENANT_INITIAL_TAB_KEY} from '../../../utils/constants';
11
- import {setSettingValue} from '../../../store/reducers/settings';
11
+ import {setSettingValue} from '../../../store/reducers/settings/settings';
12
12
 
13
13
  import {TenantTabsGroups, TENANT_GENERAL_TABS} from '../TenantPages';
14
14
 
@@ -24,7 +24,7 @@ import {
24
24
  setMonacoHotKey,
25
25
  } from '../../../store/reducers/executeQuery';
26
26
  import {getExplainQuery, getExplainQueryAst} from '../../../store/reducers/explainQuery';
27
- import {getParsedSettingValue, setSettingValue} from '../../../store/reducers/settings';
27
+ import {getParsedSettingValue, setSettingValue} from '../../../store/reducers/settings/settings';
28
28
  import {
29
29
  DEFAULT_IS_QUERY_RESULT_COLLAPSED,
30
30
  DEFAULT_SIZE_RESULT_PANE_KEY,
@@ -19,9 +19,13 @@ import routes, {CLUSTER_PAGES, createHref} from '../../routes';
19
19
  import {formatCPU, formatBytesToGigabyte, formatNumber} from '../../utils';
20
20
  import {hideTooltip, showTooltip} from '../../store/reducers/tooltip';
21
21
  import {withSearch} from '../../HOCS';
22
- import {ALL, DEFAULT_TABLE_SETTINGS, TENANT_INITIAL_TAB_KEY} from '../../utils/constants';
22
+ import {DEFAULT_TABLE_SETTINGS, TENANT_INITIAL_TAB_KEY} from '../../utils/constants';
23
23
  import {getTenantsInfo} from '../../store/reducers/tenants/tenants';
24
- import {changeFilter, getSettingValue} from '../../store/reducers/settings';
24
+ import {
25
+ changeFilter,
26
+ getSettingValue,
27
+ ProblemFilterValues,
28
+ } from '../../store/reducers/settings/settings';
25
29
  import {setHeader} from '../../store/reducers/header';
26
30
 
27
31
  import {clusterName} from '../../store';
@@ -63,7 +67,7 @@ class Tenants extends React.Component {
63
67
  };
64
68
 
65
69
  static filterTenants(tenants, filter) {
66
- if (filter === ALL) {
70
+ if (filter === ProblemFilterValues.ALL) {
67
71
  return tenants;
68
72
  }
69
73
 
@@ -311,7 +315,7 @@ class Tenants extends React.Component {
311
315
  },
312
316
  ];
313
317
 
314
- if (filteredTenants.length === 0 && filter !== ALL) {
318
+ if (filteredTenants.length === 0 && filter !== ProblemFilterValues.ALL) {
315
319
  return <Illustration name="thumbsUp" width="200" />;
316
320
  }
317
321
 
@@ -16,7 +16,7 @@ export interface SettingProps {
16
16
  title: string;
17
17
  settingKey: string;
18
18
  helpPopoverContent?: ReactNode;
19
- values?: {value: string; content: string}[];
19
+ options?: {value: string; content: string}[];
20
20
  defaultValue?: unknown;
21
21
  }
22
22
 
@@ -25,7 +25,7 @@ export const Setting = ({
25
25
  settingKey,
26
26
  title,
27
27
  helpPopoverContent,
28
- values,
28
+ options,
29
29
  defaultValue,
30
30
  }: SettingProps) => {
31
31
  const [settingValue, setValue] = useSetting(settingKey, defaultValue);
@@ -52,13 +52,13 @@ export const Setting = ({
52
52
  }
53
53
 
54
54
  case 'radio': {
55
- if (!values) {
55
+ if (!options) {
56
56
  return null;
57
57
  }
58
58
 
59
59
  return (
60
60
  <RadioButton value={String(settingValue)} onUpdate={setValue}>
61
- {values.map(({value, content}) => {
61
+ {options.map(({value, content}) => {
62
62
  return (
63
63
  <RadioButton.Option value={value} key={value}>
64
64
  {content}
@@ -2,101 +2,39 @@ import cn from 'bem-cn-lite';
2
2
 
3
3
  import {Settings} from '@gravity-ui/navigation';
4
4
 
5
- import favoriteFilledIcon from '../../assets/icons/star.svg';
6
- import flaskIcon from '../../assets/icons/flask.svg';
7
-
8
- import {
9
- ENABLE_QUERY_MODES_FOR_EXPLAIN,
10
- INVERTED_DISKS_KEY,
11
- THEME_KEY,
12
- USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY,
13
- } from '../../utils/constants';
14
-
15
- import {Setting, SettingProps} from './Setting';
5
+ import {YDBEmbeddedUISettings, settings} from './settings';
6
+ import {Setting} from './Setting';
16
7
 
17
8
  import './UserSettings.scss';
18
9
 
19
10
  export const b = cn('ydb-user-settings');
20
11
 
21
- enum Theme {
22
- light = 'light',
23
- dark = 'dark',
24
- system = 'system',
25
- }
26
-
27
- const themeValues = [
28
- {
29
- value: Theme.system,
30
- content: 'System',
31
- },
32
- {
33
- value: Theme.light,
34
- content: 'Light',
35
- },
36
- {
37
- value: Theme.dark,
38
- content: 'Dark',
39
- },
40
- ];
41
-
42
- export enum SettingsSection {
43
- general = 'general',
44
- experiments = 'experiments',
45
- }
46
-
47
12
  interface UserSettingsProps {
48
- settings?: Partial<Record<SettingsSection, SettingProps[]>>;
13
+ settings?: YDBEmbeddedUISettings;
49
14
  }
50
15
 
51
- export const UserSettings = ({settings}: UserSettingsProps) => {
16
+ export const UserSettings = ({settings: userSettings = settings}: UserSettingsProps) => {
52
17
  return (
53
18
  <Settings>
54
- <Settings.Page
55
- id={SettingsSection.general}
56
- title="General"
57
- icon={{data: favoriteFilledIcon, height: 14, width: 14}}
58
- >
59
- <Settings.Section title="General">
60
- <Setting
61
- settingKey={THEME_KEY}
62
- title="Interface theme"
63
- type="radio"
64
- values={themeValues}
65
- />
66
- {settings?.[SettingsSection.general]?.map((setting) => (
67
- <Setting key={setting.settingKey} {...setting} />
68
- ))}
69
- </Settings.Section>
70
- </Settings.Page>
71
- <Settings.Page
72
- id={SettingsSection.experiments}
73
- title="Experiments"
74
- icon={{data: flaskIcon}}
75
- >
76
- <Settings.Section title="Experiments">
77
- <Setting
78
- settingKey={INVERTED_DISKS_KEY}
79
- title={'Inverted disks space indicators'}
80
- />
81
- <Setting
82
- settingKey={USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY}
83
- title={'Break the Nodes tab in Diagnostics'}
84
- helpPopoverContent={
85
- 'Use /viewer/json/nodes endpoint for Nodes Tab in diagnostics. It returns incorrect data on older versions'
86
- }
87
- />
88
- <Setting
89
- settingKey={ENABLE_QUERY_MODES_FOR_EXPLAIN}
90
- title={'Enable query modes for explain'}
91
- helpPopoverContent={
92
- 'Enable script | scan query mode selector for both run and explain. May not work on some versions'
93
- }
94
- />
95
- {settings?.[SettingsSection.experiments]?.map((setting) => (
96
- <Setting key={setting.settingKey} {...setting} />
97
- ))}
98
- </Settings.Section>
99
- </Settings.Page>
19
+ {userSettings.map((page) => {
20
+ const {id, title, icon, sections = []} = page;
21
+
22
+ return (
23
+ <Settings.Page key={id} id={id} title={title} icon={icon}>
24
+ {sections.map((section) => {
25
+ const {title: sectionTitle, settings: sectionSettings = []} = section;
26
+
27
+ return (
28
+ <Settings.Section key={id} title={sectionTitle}>
29
+ {sectionSettings.map((setting) => {
30
+ return <Setting key={setting.settingKey} {...setting} />;
31
+ })}
32
+ </Settings.Section>
33
+ );
34
+ })}
35
+ </Settings.Page>
36
+ );
37
+ })}
100
38
  </Settings>
101
39
  );
102
40
  };
@@ -0,0 +1,20 @@
1
+ {
2
+ "page.general": "General",
3
+ "section.general": "General",
4
+
5
+ "page.experiments": "Experiments",
6
+ "section.experiments": "Experiments",
7
+
8
+ "settings.theme.title": "Interface theme",
9
+ "settings.theme.option-dark": "Dark",
10
+ "settings.theme.option-light": "Light",
11
+ "settings.theme.option-system": "System",
12
+
13
+ "settings.invertedDisks.title": "Inverted disks space indicators",
14
+
15
+ "settings.useNodesEndpoint.title": "Break the Nodes tab in Diagnostics",
16
+ "settings.useNodesEndpoint.popover": "Use /viewer/json/nodes endpoint for Nodes Tab in diagnostics. It returns incorrect data on versions before 23-1",
17
+
18
+ "settings.enableQueryModesForExplain.title": "Enable query modes for explain",
19
+ "settings.enableQueryModesForExplain.popover": "Enable script | scan query mode selector for both run and explain. May not work on versions before 23-2"
20
+ }
@@ -0,0 +1,11 @@
1
+ import {i18n, Lang} from '../../../utils/i18n';
2
+
3
+ import en from './en.json';
4
+ import ru from './ru.json';
5
+
6
+ const COMPONENT = 'ydb-user-settings';
7
+
8
+ i18n.registerKeyset(Lang.En, COMPONENT, en);
9
+ i18n.registerKeyset(Lang.Ru, COMPONENT, ru);
10
+
11
+ export default i18n.keyset(COMPONENT);
@@ -0,0 +1,20 @@
1
+ {
2
+ "page.general": "Общие",
3
+ "section.general": "Общие",
4
+
5
+ "page.experiments": "Эксперименты",
6
+ "section.experiments": "Эксперименты",
7
+
8
+ "settings.theme.title": "Тема",
9
+ "settings.theme.option-dark": "Тёмная",
10
+ "settings.theme.option-light": "Светлая",
11
+ "settings.theme.option-system": "Системная",
12
+
13
+ "settings.invertedDisks.title": "Инвертированные индикаторы места на дисках",
14
+
15
+ "settings.useNodesEndpoint.title": "Сломать вкладку Nodes в диагностике",
16
+ "settings.useNodesEndpoint.popover": "Использовать эндпоинт /viewer/json/nodes для вкладки Nodes в диагностике. Может возвращать некорректные данные на версиях до 23-1",
17
+
18
+ "settings.enableQueryModesForExplain.title": "Включить режимы выполнения запроса для explain",
19
+ "settings.enableQueryModesForExplain.popover": "Включить общий переключатель script | scan для run и explain. Может работать некорректно на версиях до 23-2"
20
+ }
@@ -0,0 +1,91 @@
1
+ import type {IconProps} from '@gravity-ui/uikit';
2
+
3
+ import favoriteFilledIcon from '../../assets/icons/star.svg';
4
+ import flaskIcon from '../../assets/icons/flask.svg';
5
+
6
+ import {
7
+ ENABLE_QUERY_MODES_FOR_EXPLAIN,
8
+ INVERTED_DISKS_KEY,
9
+ THEME_KEY,
10
+ USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY,
11
+ } from '../../utils/constants';
12
+
13
+ import type {SettingProps} from './Setting';
14
+ import i18n from './i18n';
15
+
16
+ export interface SettingsSection {
17
+ id: string;
18
+ title: string;
19
+ settings: SettingProps[];
20
+ }
21
+
22
+ export interface SettingsPage {
23
+ id: string;
24
+ title: string;
25
+ icon: IconProps;
26
+ sections: SettingsSection[];
27
+ }
28
+
29
+ export type YDBEmbeddedUISettings = SettingsPage[];
30
+
31
+ const themeOptions = [
32
+ {
33
+ value: 'system',
34
+ content: i18n('settings.theme.option-system'),
35
+ },
36
+ {
37
+ value: 'light',
38
+ content: i18n('settings.theme.option-light'),
39
+ },
40
+ {
41
+ value: 'dark',
42
+ content: i18n('settings.theme.option-dark'),
43
+ },
44
+ ];
45
+
46
+ export const themeSetting: SettingProps = {
47
+ settingKey: THEME_KEY,
48
+ title: i18n('settings.theme.title'),
49
+ type: 'radio',
50
+ options: themeOptions,
51
+ };
52
+ export const invertedDisksSetting: SettingProps = {
53
+ settingKey: INVERTED_DISKS_KEY,
54
+ title: i18n('settings.invertedDisks.title'),
55
+ };
56
+ export const useNodesEndpointSetting: SettingProps = {
57
+ settingKey: USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY,
58
+ title: i18n('settings.useNodesEndpoint.title'),
59
+ helpPopoverContent: i18n('settings.useNodesEndpoint.popover'),
60
+ };
61
+ export const enableQueryModesForExplainSetting: SettingProps = {
62
+ settingKey: ENABLE_QUERY_MODES_FOR_EXPLAIN,
63
+ title: i18n('settings.enableQueryModesForExplain.title'),
64
+ helpPopoverContent: i18n('settings.enableQueryModesForExplain.popover'),
65
+ };
66
+
67
+ export const generalSection: SettingsSection = {
68
+ id: 'generalSection',
69
+ title: i18n('section.general'),
70
+ settings: [themeSetting],
71
+ };
72
+ export const experimentsSection: SettingsSection = {
73
+ id: 'experimentsSection',
74
+ title: i18n('section.experiments'),
75
+ settings: [invertedDisksSetting, useNodesEndpointSetting, enableQueryModesForExplainSetting],
76
+ };
77
+
78
+ export const generalPage: SettingsPage = {
79
+ id: 'generalPage',
80
+ title: i18n('page.general'),
81
+ icon: {data: favoriteFilledIcon, height: 14, width: 14},
82
+ sections: [generalSection],
83
+ };
84
+ export const experimentsPage: SettingsPage = {
85
+ id: 'experimentsPage',
86
+ title: i18n('page.experiments'),
87
+ icon: {data: flaskIcon},
88
+ sections: [experimentsSection],
89
+ };
90
+
91
+ export const settings: YDBEmbeddedUISettings = [generalPage, experimentsPage];
@@ -19,7 +19,7 @@ import partitions from './partitions/partitions';
19
19
  import executeQuery from './executeQuery';
20
20
  import explainQuery from './explainQuery';
21
21
  import tabletsFilters from './tabletsFilters';
22
- import settings from './settings';
22
+ import settings from './settings/settings';
23
23
  import preview from './preview';
24
24
  import nodesList from './nodesList';
25
25
  import describe from './describe';
@@ -3,7 +3,7 @@ import {createSelector, Selector} from 'reselect';
3
3
  import {escapeRegExp} from 'lodash/fp';
4
4
 
5
5
  import '../../services/api';
6
- import {ALL, HOUR_IN_SECONDS, IProblemFilterValues} from '../../utils/constants';
6
+ import {HOUR_IN_SECONDS} from '../../utils/constants';
7
7
  import {calcUptime, calcUptimeInSeconds} from '../../utils';
8
8
  import {NodesUptimeFilterValues} from '../../utils/nodes';
9
9
  import type {
@@ -14,9 +14,11 @@ import type {
14
14
  INodesRootStateSlice,
15
15
  INodesState,
16
16
  } from '../../types/store/nodes';
17
+ import type {ValueOf} from '../../types/common';
17
18
  import {EFlag} from '../../types/api/enums';
18
19
 
19
20
  import {createRequestActionTypes, createApiRequest} from '../utils';
21
+ import {ProblemFilterValues} from './settings/settings';
20
22
 
21
23
  export const FETCH_NODES = createRequestActionTypes('nodes', 'FETCH_NODES');
22
24
 
@@ -178,9 +180,9 @@ const getNodesList = (state: INodesRootStateSlice) => state.nodes.data;
178
180
 
179
181
  const filterNodesByProblemsStatus = (
180
182
  nodesList: INodesPreparedEntity[] = [],
181
- problemFilter: IProblemFilterValues,
183
+ problemFilter: ValueOf<typeof ProblemFilterValues>,
182
184
  ) => {
183
- if (problemFilter === ALL) {
185
+ if (problemFilter === ProblemFilterValues.ALL) {
184
186
  return nodesList;
185
187
  }
186
188
 
@@ -57,7 +57,7 @@ export const prepareConsumerPartitions = (
57
57
  const {partition_id = '0', partition_stats, partition_consumer_stats} = partition;
58
58
 
59
59
  const preparedPartitionStats = prepareGeneralPartitionStats(partition_stats);
60
- const endOffset = preparedPartitionStats;
60
+ const {endOffset} = preparedPartitionStats;
61
61
 
62
62
  const {
63
63
  last_read_offset = '0',
@@ -1,5 +1,8 @@
1
+ import type {Reducer} from 'redux';
2
+ import type {ThunkAction} from 'redux-thunk';
3
+
4
+ import type {ValueOf} from '../../../types/common';
1
5
  import {
2
- ALL,
3
6
  SAVED_QUERIES_KEY,
4
7
  THEME_KEY,
5
8
  TENANT_INITIAL_TAB_KEY,
@@ -9,25 +12,38 @@ import {
9
12
  PARTITIONS_HIDDEN_COLUMNS_KEY,
10
13
  QUERY_INITIAL_MODE_KEY,
11
14
  ENABLE_QUERY_MODES_FOR_EXPLAIN,
12
- } from '../../utils/constants';
13
- import '../../services/api';
14
- import {getValueFromLS, parseJson} from '../../utils/utils';
15
- import {QueryModes} from '../../types/store/query';
15
+ } from '../../../utils/constants';
16
+ import '../../../services/api';
17
+ import {getValueFromLS, parseJson} from '../../../utils/utils';
18
+ import {QueryModes} from '../../../types/store/query';
19
+
20
+ import type {RootState} from '..';
21
+ import type {
22
+ SetSettingValueAction,
23
+ SettingsAction,
24
+ SettingsRootStateSlice,
25
+ SettingsState,
26
+ } from './types';
16
27
 
17
28
  const CHANGE_PROBLEM_FILTER = 'settings/CHANGE_PROBLEM_FILTER';
18
- const SET_SETTING_VALUE = 'settings/SET_VALUE';
29
+ export const SET_SETTING_VALUE = 'settings/SET_VALUE';
30
+
31
+ export const ProblemFilterValues = {
32
+ ALL: 'All',
33
+ PROBLEMS: 'With problems',
34
+ } as const;
19
35
 
20
36
  const userSettings = window.userSettings || {};
21
37
  const systemSettings = window.systemSettings || {};
22
38
 
23
- export function readSavedSettingsValue(key, defaultValue) {
39
+ export function readSavedSettingsValue(key: string, defaultValue?: string) {
24
40
  const savedValue = window.web_version ? userSettings[key] : getValueFromLS(key);
25
41
 
26
42
  return savedValue ?? defaultValue;
27
43
  }
28
44
 
29
45
  export const initialState = {
30
- problemFilter: ALL,
46
+ problemFilter: ProblemFilterValues.ALL,
31
47
  userSettings: {
32
48
  ...userSettings,
33
49
  [THEME_KEY]: readSavedSettingsValue(THEME_KEY, 'system'),
@@ -49,7 +65,7 @@ export const initialState = {
49
65
  systemSettings,
50
66
  };
51
67
 
52
- const settings = (state = initialState, action) => {
68
+ const settings: Reducer<SettingsState, SettingsAction> = (state = initialState, action) => {
53
69
  switch (action.type) {
54
70
  case CHANGE_PROBLEM_FILTER:
55
71
  return {
@@ -74,7 +90,10 @@ const settings = (state = initialState, action) => {
74
90
  }
75
91
  };
76
92
 
77
- export const setSettingValue = (name, value) => {
93
+ export const setSettingValue = (
94
+ name: string,
95
+ value: string,
96
+ ): ThunkAction<void, RootState, unknown, SetSettingValueAction> => {
78
97
  return (dispatch, getState) => {
79
98
  dispatch({type: SET_SETTING_VALUE, data: {name, value}});
80
99
  const {singleClusterMode} = getState();
@@ -86,7 +105,7 @@ export const setSettingValue = (name, value) => {
86
105
  };
87
106
  };
88
107
 
89
- export const getSettingValue = (state, name) => {
108
+ export const getSettingValue = (state: SettingsRootStateSlice, name: string) => {
90
109
  return state.settings.userSettings[name];
91
110
  };
92
111
 
@@ -94,16 +113,16 @@ export const getSettingValue = (state, name) => {
94
113
  * Returns parsed settings value.
95
114
  * If value cannot be parsed, returns initially stored string
96
115
  */
97
- export const getParsedSettingValue = (state, name) => {
116
+ export const getParsedSettingValue = (state: SettingsRootStateSlice, name: string) => {
98
117
  const value = state.settings.userSettings[name];
99
118
  return parseJson(value);
100
119
  };
101
120
 
102
- export const changeFilter = (filter) => {
121
+ export const changeFilter = (filter: ValueOf<typeof ProblemFilterValues>) => {
103
122
  return {
104
123
  type: CHANGE_PROBLEM_FILTER,
105
124
  data: filter,
106
- };
125
+ } as const;
107
126
  };
108
127
 
109
128
  export default settings;
@@ -0,0 +1,19 @@
1
+ import type {ValueOf} from '../../../types/common';
2
+ import {changeFilter, ProblemFilterValues, SET_SETTING_VALUE} from './settings';
3
+
4
+ export interface SettingsState {
5
+ problemFilter: ValueOf<typeof ProblemFilterValues>;
6
+ userSettings: Record<string, string | undefined>;
7
+ systemSettings: Record<string, string | undefined>;
8
+ }
9
+
10
+ export type SetSettingValueAction = {
11
+ type: typeof SET_SETTING_VALUE;
12
+ data: {name: string; value: string};
13
+ };
14
+
15
+ export type SettingsAction = ReturnType<typeof changeFilter> | SetSettingValueAction;
16
+
17
+ export interface SettingsRootStateSlice {
18
+ settings: SettingsState;
19
+ }
@@ -6,7 +6,7 @@ import {parseQuery} from 'redux-location-state/lib/parseQuery';
6
6
  import {LOCATION_PUSH, LOCATION_POP} from 'redux-location-state/lib/constants';
7
7
  import {getMatchingDeclaredPath} from 'redux-location-state/lib/helpers';
8
8
 
9
- import {initialState as initialSettingsState} from './reducers/settings';
9
+ import {initialState as initialSettingsState} from './reducers/settings/settings';
10
10
  import {initialState as initialHeatmapState} from './reducers/heatmap';
11
11
 
12
12
  const paramSetup = {
@@ -75,11 +75,6 @@ export const COLORS_PRIORITY = {
75
75
  grey: 1,
76
76
  };
77
77
 
78
- export const ALL = 'All';
79
- export const PROBLEMS = 'With problems';
80
-
81
- export type IProblemFilterValues = typeof ALL | typeof PROBLEMS;
82
-
83
78
  export const THEME_KEY = 'theme';
84
79
  export const INVERTED_DISKS_KEY = 'invertedDisks';
85
80
  export const USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY = 'useNodesEndpointInDiagnostics';
@@ -1,7 +1,7 @@
1
1
  import {useCallback} from 'react';
2
2
  import {useDispatch} from 'react-redux';
3
3
 
4
- import {getParsedSettingValue, setSettingValue} from '../../store/reducers/settings';
4
+ import {getParsedSettingValue, setSettingValue} from '../../store/reducers/settings/settings';
5
5
 
6
6
  import {useTypedSelector} from './useTypedSelector';
7
7
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ydb-embedded-ui",
3
- "version": "4.4.0",
3
+ "version": "4.4.2",
4
4
  "files": [
5
5
  "dist"
6
6
  ],