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 +14 -0
- package/dist/components/ProblemFilter/ProblemFilter.tsx +9 -4
- package/dist/containers/App/Content.js +1 -1
- package/dist/containers/AsideNavigation/AsideNavigation.tsx +2 -2
- package/dist/containers/Nodes/Nodes.tsx +9 -9
- package/dist/containers/Tenant/Diagnostics/Network/Network.js +8 -7
- package/dist/containers/Tenant/ObjectGeneralTabs/ObjectGeneralTabs.tsx +1 -1
- package/dist/containers/Tenant/QueryEditor/QueryEditor.js +1 -1
- package/dist/containers/Tenants/Tenants.js +8 -4
- package/dist/containers/UserSettings/Setting.tsx +4 -4
- package/dist/containers/UserSettings/UserSettings.tsx +23 -85
- package/dist/containers/UserSettings/i18n/en.json +20 -0
- package/dist/containers/UserSettings/i18n/index.ts +11 -0
- package/dist/containers/UserSettings/i18n/ru.json +20 -0
- package/dist/containers/UserSettings/settings.ts +91 -0
- package/dist/store/reducers/index.ts +1 -1
- package/dist/store/reducers/nodes.ts +5 -3
- package/dist/store/reducers/partitions/utils.ts +1 -1
- package/dist/store/reducers/{settings.js → settings/settings.ts} +33 -14
- package/dist/store/reducers/settings/types.ts +19 -0
- package/dist/store/state-url-mapping.js +1 -1
- package/dist/utils/constants.ts +0 -5
- package/dist/utils/hooks/useSetting.ts +1 -1
- package/package.json +1 -1
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 {
|
3
|
+
import type {ValueOf} from '../../types/common';
|
4
|
+
import {ProblemFilterValues} from '../../store/reducers/settings/settings';
|
4
5
|
|
5
6
|
interface ProblemFilterProps {
|
6
|
-
value:
|
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}>
|
15
|
-
|
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 {
|
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:
|
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 (
|
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 {
|
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 &&
|
182
|
-
|
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 &&
|
222
|
-
|
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 {
|
22
|
+
import {DEFAULT_TABLE_SETTINGS, TENANT_INITIAL_TAB_KEY} from '../../utils/constants';
|
23
23
|
import {getTenantsInfo} from '../../store/reducers/tenants/tenants';
|
24
|
-
import {
|
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
|
-
|
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
|
-
|
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 (!
|
55
|
+
if (!options) {
|
56
56
|
return null;
|
57
57
|
}
|
58
58
|
|
59
59
|
return (
|
60
60
|
<RadioButton value={String(settingValue)} onUpdate={setValue}>
|
61
|
-
{
|
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
|
6
|
-
import
|
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?:
|
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
|
-
|
55
|
-
id=
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
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 {
|
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:
|
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 '
|
13
|
-
import '
|
14
|
-
import {getValueFromLS, parseJson} from '
|
15
|
-
import {QueryModes} from '
|
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 = (
|
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 = {
|
package/dist/utils/constants.ts
CHANGED
@@ -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
|
|