ydb-embedded-ui 4.26.0 → 4.27.1
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/containers/App/Content.js +5 -4
- package/dist/containers/AsideNavigation/AsideNavigation.tsx +12 -27
- package/dist/containers/Tenant/Diagnostics/Partitions/Partitions.tsx +1 -4
- package/dist/containers/Tenant/Query/QueryEditor/QueryEditor.js +4 -8
- package/dist/services/api.ts +4 -3
- package/dist/services/settings.ts +109 -0
- package/dist/store/reducers/executeQuery.ts +6 -3
- package/dist/store/reducers/settings/settings.ts +21 -75
- package/dist/store/reducers/settings/types.ts +9 -5
- package/dist/types/window.d.ts +2 -2
- package/dist/utils/hooks/useSetting.ts +6 -7
- package/dist/utils/i18n/i18n.ts +2 -2
- package/package.json +1 -1
- package/dist/utils/settings.ts +0 -13
package/CHANGELOG.md
CHANGED
@@ -1,5 +1,19 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## [4.27.1](https://github.com/ydb-platform/ydb-embedded-ui/compare/v4.27.0...v4.27.1) (2024-01-10)
|
4
|
+
|
5
|
+
|
6
|
+
### Bug Fixes
|
7
|
+
|
8
|
+
* enable extract and set user settings manually ([#629](https://github.com/ydb-platform/ydb-embedded-ui/issues/629)) ([5eecd58](https://github.com/ydb-platform/ydb-embedded-ui/commit/5eecd58249688b4a8b3ecad766564f7b404e839c))
|
9
|
+
|
10
|
+
## [4.27.0](https://github.com/ydb-platform/ydb-embedded-ui/compare/v4.26.0...v4.27.0) (2023-12-28)
|
11
|
+
|
12
|
+
|
13
|
+
### Features
|
14
|
+
|
15
|
+
* migrate from external settings api ([#621](https://github.com/ydb-platform/ydb-embedded-ui/issues/621)) ([ae2fbbe](https://github.com/ydb-platform/ydb-embedded-ui/commit/ae2fbbef66d9aba150012027baf8b89bf79cd741))
|
16
|
+
|
3
17
|
## [4.26.0](https://github.com/ydb-platform/ydb-embedded-ui/compare/v4.25.0...v4.26.0) (2023-12-14)
|
4
18
|
|
5
19
|
|
@@ -16,8 +16,8 @@ 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/settings';
|
20
19
|
import {THEME_KEY} from '../../utils/constants';
|
20
|
+
import {useSetting} from '../../utils/hooks';
|
21
21
|
|
22
22
|
import './App.scss';
|
23
23
|
import PropTypes from 'prop-types';
|
@@ -72,7 +72,10 @@ Content.propTypes = {
|
|
72
72
|
};
|
73
73
|
|
74
74
|
function ContentWrapper(props) {
|
75
|
-
const {
|
75
|
+
const {singleClusterMode, isAuthenticated} = props;
|
76
|
+
|
77
|
+
const [theme] = useSetting(THEME_KEY);
|
78
|
+
|
76
79
|
return (
|
77
80
|
<HistoryContext.Consumer>
|
78
81
|
{(history) => (
|
@@ -96,7 +99,6 @@ function ContentWrapper(props) {
|
|
96
99
|
}
|
97
100
|
|
98
101
|
ContentWrapper.propTypes = {
|
99
|
-
theme: PropTypes.string,
|
100
102
|
singleClusterMode: PropTypes.bool,
|
101
103
|
isAuthenticated: PropTypes.bool,
|
102
104
|
children: PropTypes.node,
|
@@ -104,7 +106,6 @@ ContentWrapper.propTypes = {
|
|
104
106
|
|
105
107
|
function mapStateToProps(state) {
|
106
108
|
return {
|
107
|
-
theme: getParsedSettingValue(state, THEME_KEY),
|
108
109
|
isAuthenticated: state.authentication.isAuthenticated,
|
109
110
|
singleClusterMode: state.singleClusterMode,
|
110
111
|
};
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import React, {useState} from 'react';
|
2
|
-
import {
|
2
|
+
import {useDispatch} from 'react-redux';
|
3
3
|
import {useLocation} from 'react-router';
|
4
4
|
import {useHistory} from 'react-router-dom';
|
5
5
|
import cn from 'bem-cn-lite';
|
@@ -19,7 +19,6 @@ import settingsIcon from '../../assets/icons/settings.svg';
|
|
19
19
|
import supportIcon from '../../assets/icons/support.svg';
|
20
20
|
|
21
21
|
import {logout} from '../../store/reducers/authentication/authentication';
|
22
|
-
import {getParsedSettingValue, setSettingValue} from '../../store/reducers/settings/settings';
|
23
22
|
import {TENANT_PAGE, TENANT_PAGES_IDS} from '../../store/reducers/tenant/constants';
|
24
23
|
import routes, {TENANT, createHref, parseQuery} from '../../routes';
|
25
24
|
import {useSetting, useTypedSelector} from '../../utils/hooks';
|
@@ -117,10 +116,6 @@ function YdbUserDropdown({isCompact, popupAnchor, ydbUser}: YdbUserDropdownProps
|
|
117
116
|
|
118
117
|
interface AsideNavigationProps {
|
119
118
|
children: React.ReactNode;
|
120
|
-
ydbUser: string;
|
121
|
-
compact: boolean;
|
122
|
-
logout: VoidFunction;
|
123
|
-
setSettingValue: (name: string, value: string) => void;
|
124
119
|
}
|
125
120
|
|
126
121
|
enum Panel {
|
@@ -189,15 +184,19 @@ export const useGetLeftNavigationItems = () => {
|
|
189
184
|
|
190
185
|
function AsideNavigation(props: AsideNavigationProps) {
|
191
186
|
const history = useHistory();
|
187
|
+
const dispatch = useDispatch();
|
192
188
|
|
193
189
|
const [visiblePanel, setVisiblePanel] = useState<Panel>();
|
194
190
|
|
195
|
-
const
|
196
|
-
|
197
|
-
};
|
191
|
+
const {user: ydbUser} = useTypedSelector((state) => state.authentication);
|
192
|
+
const [compact, setIsCompact] = useSetting<boolean>(ASIDE_HEADER_COMPACT_KEY);
|
198
193
|
|
199
194
|
const menuItems = useGetLeftNavigationItems();
|
200
195
|
|
196
|
+
const onLogout = () => {
|
197
|
+
dispatch(logout());
|
198
|
+
};
|
199
|
+
|
201
200
|
return (
|
202
201
|
<React.Fragment>
|
203
202
|
<AsideHeader
|
@@ -207,7 +206,7 @@ function AsideNavigation(props: AsideNavigationProps) {
|
|
207
206
|
onClick: () => history.push('/'),
|
208
207
|
}}
|
209
208
|
menuItems={menuItems}
|
210
|
-
compact={
|
209
|
+
compact={compact}
|
211
210
|
onChangeCompact={setIsCompact}
|
212
211
|
className={b()}
|
213
212
|
renderContent={() => props.children}
|
@@ -248,8 +247,8 @@ function AsideNavigation(props: AsideNavigationProps) {
|
|
248
247
|
isCompact={compact}
|
249
248
|
popupAnchor={asideRef}
|
250
249
|
ydbUser={{
|
251
|
-
login:
|
252
|
-
logout:
|
250
|
+
login: ydbUser,
|
251
|
+
logout: onLogout,
|
253
252
|
}}
|
254
253
|
/>
|
255
254
|
</React.Fragment>
|
@@ -269,18 +268,4 @@ function AsideNavigation(props: AsideNavigationProps) {
|
|
269
268
|
);
|
270
269
|
}
|
271
270
|
|
272
|
-
|
273
|
-
const {user: ydbUser} = state.authentication;
|
274
|
-
|
275
|
-
return {
|
276
|
-
ydbUser,
|
277
|
-
compact: getParsedSettingValue(state, ASIDE_HEADER_COMPACT_KEY),
|
278
|
-
};
|
279
|
-
};
|
280
|
-
|
281
|
-
const mapDispatchToProps = {
|
282
|
-
logout,
|
283
|
-
setSettingValue,
|
284
|
-
};
|
285
|
-
|
286
|
-
export default connect(mapStateToProps, mapDispatchToProps)(AsideNavigation);
|
271
|
+
export default AsideNavigation;
|
@@ -70,10 +70,7 @@ export const Partitions = ({path}: PartitionsProps) => {
|
|
70
70
|
error: nodesError,
|
71
71
|
} = useTypedSelector((state) => state.nodesList);
|
72
72
|
|
73
|
-
const [hiddenColumns, setHiddenColumns] = useSetting<string[]>(
|
74
|
-
PARTITIONS_HIDDEN_COLUMNS_KEY,
|
75
|
-
[],
|
76
|
-
);
|
73
|
+
const [hiddenColumns, setHiddenColumns] = useSetting<string[]>(PARTITIONS_HIDDEN_COLUMNS_KEY);
|
77
74
|
|
78
75
|
const [columns, columnsIdsForSelector] = useGetPartitionsColumns(selectedConsumer);
|
79
76
|
|
@@ -17,7 +17,6 @@ import {
|
|
17
17
|
setTenantPath,
|
18
18
|
} from '../../../../store/reducers/executeQuery';
|
19
19
|
import {getExplainQuery, getExplainQueryAst} from '../../../../store/reducers/explainQuery';
|
20
|
-
import {getParsedSettingValue, setSettingValue} from '../../../../store/reducers/settings/settings';
|
21
20
|
import {setShowPreview} from '../../../../store/reducers/schema/schema';
|
22
21
|
import {
|
23
22
|
DEFAULT_IS_QUERY_RESULT_COLLAPSED,
|
@@ -86,6 +85,7 @@ function QueryEditor(props) {
|
|
86
85
|
const [queryMode, setQueryMode] = useQueryModes();
|
87
86
|
const [useMultiSchema] = useSetting(QUERY_USE_MULTI_SCHEMA_KEY);
|
88
87
|
const [lastUsedQueryAction, setLastUsedQueryAction] = useSetting(LAST_USED_QUERY_ACTION_KEY);
|
88
|
+
const [savedQueries, setSavedQueries] = useSetting(SAVED_QUERIES_KEY);
|
89
89
|
|
90
90
|
useEffect(() => {
|
91
91
|
if (savedPath !== path) {
|
@@ -417,7 +417,7 @@ function QueryEditor(props) {
|
|
417
417
|
|
418
418
|
const storageEventHandler = (event) => {
|
419
419
|
if (event.key === SAVED_QUERIES_KEY) {
|
420
|
-
|
420
|
+
setSavedQueries(event.newValue);
|
421
421
|
}
|
422
422
|
};
|
423
423
|
|
@@ -430,8 +430,6 @@ function QueryEditor(props) {
|
|
430
430
|
const onSaveQueryHandler = (queryName) => {
|
431
431
|
const {
|
432
432
|
executeQuery: {input},
|
433
|
-
savedQueries = [],
|
434
|
-
setSettingValue,
|
435
433
|
} = props;
|
436
434
|
|
437
435
|
const queryIndex = savedQueries.findIndex(
|
@@ -445,11 +443,11 @@ function QueryEditor(props) {
|
|
445
443
|
newSavedQueries.push(newQuery);
|
446
444
|
}
|
447
445
|
|
448
|
-
|
446
|
+
setSavedQueries(newSavedQueries);
|
449
447
|
};
|
450
448
|
|
451
449
|
const renderControls = () => {
|
452
|
-
const {executeQuery, explainQuery
|
450
|
+
const {executeQuery, explainQuery} = props;
|
453
451
|
|
454
452
|
return (
|
455
453
|
<QueryEditorControls
|
@@ -511,7 +509,6 @@ const mapStateToProps = (state) => {
|
|
511
509
|
return {
|
512
510
|
executeQuery: state.executeQuery,
|
513
511
|
explainQuery: state.explainQuery,
|
514
|
-
savedQueries: getParsedSettingValue(state, SAVED_QUERIES_KEY),
|
515
512
|
showPreview: state.schema.showPreview,
|
516
513
|
currentSchema: state.schema.currentSchema,
|
517
514
|
monacoHotKey: state.executeQuery?.monacoHotKey,
|
@@ -525,7 +522,6 @@ const mapDispatchToProps = {
|
|
525
522
|
goToNextQuery,
|
526
523
|
getExplainQuery,
|
527
524
|
getExplainQueryAst,
|
528
|
-
setSettingValue,
|
529
525
|
setShowPreview,
|
530
526
|
setMonacoHotKey,
|
531
527
|
setTenantPath,
|
package/dist/services/api.ts
CHANGED
@@ -34,7 +34,6 @@ import type {StorageApiRequestParams} from '../store/reducers/storage/types';
|
|
34
34
|
|
35
35
|
import {backend as BACKEND} from '../store';
|
36
36
|
import {prepareSortValue} from '../utils/filters';
|
37
|
-
import {settingsApi} from '../utils/settings';
|
38
37
|
|
39
38
|
const config = {withCredentials: !window.custom_backend};
|
40
39
|
|
@@ -378,10 +377,12 @@ export class YdbEmbeddedAPI extends AxiosWrapper {
|
|
378
377
|
path_id: tenantId?.PathId,
|
379
378
|
});
|
380
379
|
}
|
381
|
-
|
380
|
+
|
381
|
+
/** @deprecated use localStorage instead */
|
382
|
+
postSetting(settingsApi: string, name: string, value: string) {
|
382
383
|
return this.request({
|
383
384
|
method: 'PATCH',
|
384
|
-
url: settingsApi
|
385
|
+
url: settingsApi,
|
385
386
|
data: {[name]: value},
|
386
387
|
});
|
387
388
|
}
|
@@ -0,0 +1,109 @@
|
|
1
|
+
import {TENANT_PAGES_IDS} from '../store/reducers/tenant/constants';
|
2
|
+
|
3
|
+
import {
|
4
|
+
ASIDE_HEADER_COMPACT_KEY,
|
5
|
+
CLUSTER_INFO_HIDDEN_KEY,
|
6
|
+
INVERTED_DISKS_KEY,
|
7
|
+
LANGUAGE_KEY,
|
8
|
+
LAST_USED_QUERY_ACTION_KEY,
|
9
|
+
PARTITIONS_HIDDEN_COLUMNS_KEY,
|
10
|
+
QUERY_INITIAL_MODE_KEY,
|
11
|
+
QUERY_USE_MULTI_SCHEMA_KEY,
|
12
|
+
SAVED_QUERIES_KEY,
|
13
|
+
TENANT_INITIAL_PAGE_KEY,
|
14
|
+
THEME_KEY,
|
15
|
+
USE_BACKEND_PARAMS_FOR_TABLES_KEY,
|
16
|
+
USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY,
|
17
|
+
} from '../utils/constants';
|
18
|
+
import {QUERY_ACTIONS, QUERY_MODES} from '../utils/query';
|
19
|
+
import {parseJson} from '../utils/utils';
|
20
|
+
|
21
|
+
export type SettingsObject = Record<string, unknown>;
|
22
|
+
|
23
|
+
const USE_LOCAL_STORAGE_FOR_SETTINGS_KEY = 'useLocalStorageForSettings';
|
24
|
+
|
25
|
+
/** User settings keys and their default values */
|
26
|
+
export const DEFAULT_USER_SETTINGS: SettingsObject = {
|
27
|
+
[THEME_KEY]: 'system',
|
28
|
+
[LANGUAGE_KEY]: undefined,
|
29
|
+
[INVERTED_DISKS_KEY]: false,
|
30
|
+
[USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY]: false,
|
31
|
+
[QUERY_USE_MULTI_SCHEMA_KEY]: false,
|
32
|
+
[SAVED_QUERIES_KEY]: [],
|
33
|
+
[TENANT_INITIAL_PAGE_KEY]: TENANT_PAGES_IDS.query,
|
34
|
+
[QUERY_INITIAL_MODE_KEY]: QUERY_MODES.script,
|
35
|
+
[LAST_USED_QUERY_ACTION_KEY]: QUERY_ACTIONS.execute,
|
36
|
+
[ASIDE_HEADER_COMPACT_KEY]: true,
|
37
|
+
[PARTITIONS_HIDDEN_COLUMNS_KEY]: [],
|
38
|
+
[CLUSTER_INFO_HIDDEN_KEY]: true,
|
39
|
+
[USE_BACKEND_PARAMS_FOR_TABLES_KEY]: false,
|
40
|
+
};
|
41
|
+
|
42
|
+
class SettingsManager {
|
43
|
+
constructor() {
|
44
|
+
// Migrate settings to LS if external API was used before
|
45
|
+
const settingsApi = window.web_version ? window.systemSettings?.settingsApi : undefined;
|
46
|
+
|
47
|
+
const useLocalStorage = this.readUserSettingsValue(USE_LOCAL_STORAGE_FOR_SETTINGS_KEY);
|
48
|
+
|
49
|
+
if (settingsApi && !useLocalStorage) {
|
50
|
+
const externalUserSettings = window.userSettings;
|
51
|
+
|
52
|
+
if (externalUserSettings) {
|
53
|
+
Object.entries(externalUserSettings).forEach(([key, value]) =>
|
54
|
+
this.setUserSettingsValue(key, value),
|
55
|
+
);
|
56
|
+
}
|
57
|
+
|
58
|
+
this.setUserSettingsValue(USE_LOCAL_STORAGE_FOR_SETTINGS_KEY, true);
|
59
|
+
}
|
60
|
+
}
|
61
|
+
|
62
|
+
/**
|
63
|
+
* Returns parsed settings value.
|
64
|
+
* If value cannot be parsed, returns initially stored string.
|
65
|
+
* If there is no value, return default value
|
66
|
+
*/
|
67
|
+
readUserSettingsValue(key: string, defaultValue?: unknown) {
|
68
|
+
return this.readValueFromLS(key) ?? defaultValue;
|
69
|
+
}
|
70
|
+
|
71
|
+
/**
|
72
|
+
* Stringify value and set it to LS
|
73
|
+
*/
|
74
|
+
setUserSettingsValue(key: string, value: unknown) {
|
75
|
+
return this.setValueToLS(key, value);
|
76
|
+
}
|
77
|
+
|
78
|
+
/**
|
79
|
+
* Extract values by provided settings object
|
80
|
+
*/
|
81
|
+
extractSettingsFromLS = (settings: SettingsObject) => {
|
82
|
+
return Object.entries(settings).reduce<SettingsObject>((acc, [key, value]) => {
|
83
|
+
acc[key] = this.readUserSettingsValue(key, value);
|
84
|
+
return acc;
|
85
|
+
}, {});
|
86
|
+
};
|
87
|
+
|
88
|
+
private readValueFromLS = (key: string): unknown => {
|
89
|
+
try {
|
90
|
+
const value = localStorage.getItem(key);
|
91
|
+
|
92
|
+
return parseJson(value);
|
93
|
+
} catch {
|
94
|
+
return undefined;
|
95
|
+
}
|
96
|
+
};
|
97
|
+
|
98
|
+
private setValueToLS = (key: string, value: unknown): void => {
|
99
|
+
try {
|
100
|
+
if (typeof value === 'string') {
|
101
|
+
localStorage.setItem(key, value);
|
102
|
+
} else {
|
103
|
+
localStorage.setItem(key, JSON.stringify(value));
|
104
|
+
}
|
105
|
+
} catch {}
|
106
|
+
};
|
107
|
+
}
|
108
|
+
|
109
|
+
export const settingsManager = new SettingsManager();
|
@@ -9,10 +9,10 @@ import type {
|
|
9
9
|
QueryInHistory,
|
10
10
|
} from '../../types/store/executeQuery';
|
11
11
|
import type {QueryRequestParams, QueryMode, QuerySyntax} from '../../types/store/query';
|
12
|
-
import {getValueFromLS, parseJson} from '../../utils/utils';
|
13
12
|
import {QUERIES_HISTORY_KEY} from '../../utils/constants';
|
14
13
|
import {QUERY_MODES, QUERY_SYNTAX, parseQueryAPIExecuteResponse} from '../../utils/query';
|
15
14
|
import {parseQueryError} from '../../utils/error';
|
15
|
+
import {settingsManager} from '../../services/settings';
|
16
16
|
import '../../services/api';
|
17
17
|
|
18
18
|
import {createRequestActionTypes, createApiRequest} from '../utils';
|
@@ -28,7 +28,10 @@ const GO_TO_NEXT_QUERY = 'query/GO_TO_NEXT_QUERY';
|
|
28
28
|
const SET_MONACO_HOT_KEY = 'query/SET_MONACO_HOT_KEY';
|
29
29
|
const SET_TENANT_PATH = 'query/SET_TENANT_PATH';
|
30
30
|
|
31
|
-
const queriesHistoryInitial
|
31
|
+
const queriesHistoryInitial = settingsManager.readUserSettingsValue(
|
32
|
+
QUERIES_HISTORY_KEY,
|
33
|
+
[],
|
34
|
+
) as string[];
|
32
35
|
|
33
36
|
const sliceLimit = queriesHistoryInitial.length - MAXIMUM_QUERIES_IN_HISTORY;
|
34
37
|
|
@@ -97,7 +100,7 @@ const executeQuery: Reducer<ExecuteQueryState, ExecuteQueryAction> = (
|
|
97
100
|
const newQueries = [...state.history.queries, {queryText, syntax}].slice(
|
98
101
|
state.history.queries.length >= MAXIMUM_QUERIES_IN_HISTORY ? 1 : 0,
|
99
102
|
);
|
100
|
-
|
103
|
+
settingsManager.setUserSettingsValue(QUERIES_HISTORY_KEY, newQueries);
|
101
104
|
const currentIndex = newQueries.length - 1;
|
102
105
|
|
103
106
|
return {
|
@@ -1,32 +1,8 @@
|
|
1
1
|
import type {Reducer} from 'redux';
|
2
2
|
import type {ThunkAction} from 'redux-thunk';
|
3
3
|
|
4
|
-
import {
|
5
|
-
SAVED_QUERIES_KEY,
|
6
|
-
THEME_KEY,
|
7
|
-
TENANT_INITIAL_PAGE_KEY,
|
8
|
-
INVERTED_DISKS_KEY,
|
9
|
-
ASIDE_HEADER_COMPACT_KEY,
|
10
|
-
USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY,
|
11
|
-
PARTITIONS_HIDDEN_COLUMNS_KEY,
|
12
|
-
QUERY_INITIAL_MODE_KEY,
|
13
|
-
CLUSTER_INFO_HIDDEN_KEY,
|
14
|
-
LAST_USED_QUERY_ACTION_KEY,
|
15
|
-
USE_BACKEND_PARAMS_FOR_TABLES_KEY,
|
16
|
-
LANGUAGE_KEY,
|
17
|
-
QUERY_USE_MULTI_SCHEMA_KEY,
|
18
|
-
} from '../../../utils/constants';
|
19
4
|
import '../../../services/api';
|
20
|
-
import {
|
21
|
-
import {QUERY_ACTIONS, QUERY_MODES} from '../../../utils/query';
|
22
|
-
import {
|
23
|
-
readSavedSettingsValue,
|
24
|
-
settingsApi,
|
25
|
-
systemSettings,
|
26
|
-
userSettings,
|
27
|
-
} from '../../../utils/settings';
|
28
|
-
|
29
|
-
import {TENANT_PAGES_IDS} from '../tenant/constants';
|
5
|
+
import {DEFAULT_USER_SETTINGS, SettingsObject, settingsManager} from '../../../services/settings';
|
30
6
|
|
31
7
|
import type {RootState} from '..';
|
32
8
|
import type {
|
@@ -39,45 +15,19 @@ import type {
|
|
39
15
|
|
40
16
|
const CHANGE_PROBLEM_FILTER = 'settings/CHANGE_PROBLEM_FILTER';
|
41
17
|
export const SET_SETTING_VALUE = 'settings/SET_VALUE';
|
18
|
+
export const SET_USER_SETTINGS = 'settings/SET_USER_SETTINGS';
|
42
19
|
|
43
20
|
export const ProblemFilterValues = {
|
44
21
|
ALL: 'All',
|
45
22
|
PROBLEMS: 'With problems',
|
46
23
|
} as const;
|
47
24
|
|
25
|
+
const userSettings = settingsManager.extractSettingsFromLS(DEFAULT_USER_SETTINGS);
|
26
|
+
const systemSettings = window.systemSettings || {};
|
27
|
+
|
48
28
|
export const initialState = {
|
49
29
|
problemFilter: ProblemFilterValues.ALL,
|
50
|
-
userSettings
|
51
|
-
...userSettings,
|
52
|
-
[THEME_KEY]: readSavedSettingsValue(THEME_KEY, 'system'),
|
53
|
-
[LANGUAGE_KEY]: readSavedSettingsValue(LANGUAGE_KEY),
|
54
|
-
[INVERTED_DISKS_KEY]: readSavedSettingsValue(INVERTED_DISKS_KEY, 'false'),
|
55
|
-
[USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY]: readSavedSettingsValue(
|
56
|
-
USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY,
|
57
|
-
'false',
|
58
|
-
),
|
59
|
-
[QUERY_USE_MULTI_SCHEMA_KEY]: readSavedSettingsValue(QUERY_USE_MULTI_SCHEMA_KEY, 'false'),
|
60
|
-
[SAVED_QUERIES_KEY]: readSavedSettingsValue(SAVED_QUERIES_KEY, '[]'),
|
61
|
-
[TENANT_INITIAL_PAGE_KEY]: readSavedSettingsValue(
|
62
|
-
TENANT_INITIAL_PAGE_KEY,
|
63
|
-
TENANT_PAGES_IDS.query,
|
64
|
-
),
|
65
|
-
[QUERY_INITIAL_MODE_KEY]: readSavedSettingsValue(
|
66
|
-
QUERY_INITIAL_MODE_KEY,
|
67
|
-
QUERY_MODES.script,
|
68
|
-
),
|
69
|
-
[LAST_USED_QUERY_ACTION_KEY]: readSavedSettingsValue(
|
70
|
-
LAST_USED_QUERY_ACTION_KEY,
|
71
|
-
QUERY_ACTIONS.execute,
|
72
|
-
),
|
73
|
-
[ASIDE_HEADER_COMPACT_KEY]: readSavedSettingsValue(ASIDE_HEADER_COMPACT_KEY, 'true'),
|
74
|
-
[PARTITIONS_HIDDEN_COLUMNS_KEY]: readSavedSettingsValue(PARTITIONS_HIDDEN_COLUMNS_KEY),
|
75
|
-
[CLUSTER_INFO_HIDDEN_KEY]: readSavedSettingsValue(CLUSTER_INFO_HIDDEN_KEY, 'true'),
|
76
|
-
[USE_BACKEND_PARAMS_FOR_TABLES_KEY]: readSavedSettingsValue(
|
77
|
-
USE_BACKEND_PARAMS_FOR_TABLES_KEY,
|
78
|
-
'false',
|
79
|
-
),
|
80
|
-
},
|
30
|
+
userSettings,
|
81
31
|
systemSettings,
|
82
32
|
};
|
83
33
|
|
@@ -100,7 +50,15 @@ const settings: Reducer<SettingsState, SettingsAction> = (state = initialState,
|
|
100
50
|
userSettings: newSettings,
|
101
51
|
};
|
102
52
|
}
|
103
|
-
|
53
|
+
case SET_USER_SETTINGS: {
|
54
|
+
return {
|
55
|
+
...state,
|
56
|
+
userSettings: {
|
57
|
+
...state.userSettings,
|
58
|
+
...action.data,
|
59
|
+
},
|
60
|
+
};
|
61
|
+
}
|
104
62
|
default:
|
105
63
|
return state;
|
106
64
|
}
|
@@ -108,33 +66,21 @@ const settings: Reducer<SettingsState, SettingsAction> = (state = initialState,
|
|
108
66
|
|
109
67
|
export const setSettingValue = (
|
110
68
|
name: string,
|
111
|
-
value:
|
69
|
+
value: unknown,
|
112
70
|
): ThunkAction<void, RootState, unknown, SetSettingValueAction> => {
|
113
71
|
return (dispatch) => {
|
114
72
|
dispatch({type: SET_SETTING_VALUE, data: {name, value}});
|
115
73
|
|
116
|
-
|
117
|
-
if (settingsApi) {
|
118
|
-
window.api.postSetting(name, value);
|
119
|
-
} else {
|
120
|
-
try {
|
121
|
-
localStorage.setItem(name, value);
|
122
|
-
} catch {}
|
123
|
-
}
|
74
|
+
settingsManager.setUserSettingsValue(name, value);
|
124
75
|
};
|
125
76
|
};
|
126
77
|
|
127
|
-
export const
|
128
|
-
return
|
78
|
+
export const setUserSettings = (data: SettingsObject) => {
|
79
|
+
return {type: SET_USER_SETTINGS, data} as const;
|
129
80
|
};
|
130
81
|
|
131
|
-
|
132
|
-
|
133
|
-
* If value cannot be parsed, returns initially stored string
|
134
|
-
*/
|
135
|
-
export const getParsedSettingValue = (state: SettingsRootStateSlice, name: string) => {
|
136
|
-
const value = state.settings.userSettings[name];
|
137
|
-
return parseJson(value);
|
82
|
+
export const getSettingValue = (state: SettingsRootStateSlice, name: string) => {
|
83
|
+
return state.settings.userSettings[name];
|
138
84
|
};
|
139
85
|
|
140
86
|
export const changeFilter = (filter: ProblemFilterValue) => {
|
@@ -1,20 +1,24 @@
|
|
1
1
|
import type {ValueOf} from '../../../types/common';
|
2
|
-
import {
|
2
|
+
import type {SettingsObject} from '../../../services/settings';
|
3
|
+
import {changeFilter, setUserSettings, ProblemFilterValues, SET_SETTING_VALUE} from './settings';
|
3
4
|
|
4
5
|
export type ProblemFilterValue = ValueOf<typeof ProblemFilterValues>;
|
5
6
|
|
6
7
|
export interface SettingsState {
|
7
8
|
problemFilter: ProblemFilterValue;
|
8
|
-
userSettings:
|
9
|
-
systemSettings:
|
9
|
+
userSettings: SettingsObject;
|
10
|
+
systemSettings: SettingsObject;
|
10
11
|
}
|
11
12
|
|
12
13
|
export type SetSettingValueAction = {
|
13
14
|
type: typeof SET_SETTING_VALUE;
|
14
|
-
data: {name: string; value:
|
15
|
+
data: {name: string; value: unknown};
|
15
16
|
};
|
16
17
|
|
17
|
-
export type SettingsAction =
|
18
|
+
export type SettingsAction =
|
19
|
+
| ReturnType<typeof changeFilter>
|
20
|
+
| ReturnType<typeof setUserSettings>
|
21
|
+
| SetSettingValueAction;
|
18
22
|
|
19
23
|
export interface SettingsRootStateSlice {
|
20
24
|
settings: SettingsState;
|
package/dist/types/window.d.ts
CHANGED
@@ -39,8 +39,8 @@ interface Window {
|
|
39
39
|
__REDUX_DEVTOOLS_EXTENSION_COMPOSE__?: typeof import('redux').compose;
|
40
40
|
store?: import('redux').Store;
|
41
41
|
|
42
|
-
userSettings?:
|
43
|
-
systemSettings?:
|
42
|
+
userSettings?: import('../services/settings').SettingsObject;
|
43
|
+
systemSettings?: import('../services/settings').SettingsObject;
|
44
44
|
|
45
45
|
api: import('../services/api').YdbEmbeddedAPI;
|
46
46
|
}
|
@@ -1,22 +1,21 @@
|
|
1
1
|
import {useCallback} from 'react';
|
2
2
|
import {useDispatch} from 'react-redux';
|
3
3
|
|
4
|
-
import {
|
4
|
+
import {getSettingValue, setSettingValue} from '../../store/reducers/settings/settings';
|
5
5
|
|
6
6
|
import {useTypedSelector} from './useTypedSelector';
|
7
7
|
|
8
8
|
export const useSetting = <T>(key: string, defaultValue?: T): [T, (value: T) => void] => {
|
9
9
|
const dispatch = useDispatch();
|
10
10
|
|
11
|
-
const settingValue
|
12
|
-
|
13
|
-
|
11
|
+
const settingValue = useTypedSelector((state) => {
|
12
|
+
// Since we type setter value as T, we assume that received value is also T
|
13
|
+
return (getSettingValue(state, key) ?? defaultValue) as T;
|
14
|
+
});
|
14
15
|
|
15
16
|
const setValue = useCallback(
|
16
17
|
(value: T) => {
|
17
|
-
|
18
|
-
|
19
|
-
dispatch(setSettingValue(key, preparedValue));
|
18
|
+
dispatch(setSettingValue(key, value));
|
20
19
|
},
|
21
20
|
[dispatch, key],
|
22
21
|
);
|
package/dist/utils/i18n/i18n.ts
CHANGED
@@ -3,7 +3,7 @@ import {configure as configureUiKit} from '@gravity-ui/uikit';
|
|
3
3
|
import {configure as configureYdbUiComponents} from 'ydb-ui-components';
|
4
4
|
|
5
5
|
import {LANGUAGE_KEY} from '../constants';
|
6
|
-
import {
|
6
|
+
import {settingsManager} from '../../services/settings';
|
7
7
|
|
8
8
|
enum Lang {
|
9
9
|
En = 'en',
|
@@ -11,7 +11,7 @@ enum Lang {
|
|
11
11
|
}
|
12
12
|
|
13
13
|
const defaultLang = Lang.En;
|
14
|
-
const currentLang =
|
14
|
+
const currentLang = settingsManager.readUserSettingsValue(LANGUAGE_KEY, defaultLang) as Lang;
|
15
15
|
|
16
16
|
const i18n = new I18N();
|
17
17
|
|
package/package.json
CHANGED
package/dist/utils/settings.ts
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
import {getValueFromLS} from './utils';
|
2
|
-
|
3
|
-
export const userSettings = window.userSettings || {};
|
4
|
-
export const systemSettings = window.systemSettings || {};
|
5
|
-
|
6
|
-
export const settingsApi = window.web_version ? systemSettings.settingsApi : undefined;
|
7
|
-
|
8
|
-
export function readSavedSettingsValue(key: string, defaultValue?: string) {
|
9
|
-
// If there is no settingsApi, use localStorage
|
10
|
-
const savedValue = settingsApi ? userSettings[key] : getValueFromLS(key);
|
11
|
-
|
12
|
-
return savedValue ?? defaultValue;
|
13
|
-
}
|