ydb-embedded-ui 4.4.0 → 4.4.2

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.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
  ],