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 +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
|
|