Skip to content

Commit 9919358

Browse files
authored
feat(user-settings): sync user settings with LS (#951)
1 parent 190992e commit 9919358

File tree

10 files changed

+72
-115
lines changed

10 files changed

+72
-115
lines changed

src/containers/Nodes/Nodes.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,11 @@ import {selectAutoRefreshInterval} from '../../store/reducers/autoRefreshControl
1717
import {nodesApi} from '../../store/reducers/nodes/nodes';
1818
import {filterNodes} from '../../store/reducers/nodes/selectors';
1919
import type {NodesSortParams} from '../../store/reducers/nodes/types';
20-
import {ProblemFilterValues, changeFilter} from '../../store/reducers/settings/settings';
20+
import {
21+
ProblemFilterValues,
22+
changeFilter,
23+
selectProblemFilter,
24+
} from '../../store/reducers/settings/settings';
2125
import type {ProblemFilterValue} from '../../store/reducers/settings/types';
2226
import type {AdditionalNodesProps} from '../../types/additionalProps';
2327
import {cn} from '../../utils/cn';
@@ -58,7 +62,7 @@ export const Nodes = ({path, additionalNodesProps = {}}: NodesProps) => {
5862

5963
const isClusterNodes = !path;
6064

61-
const problemFilter = useTypedSelector((state) => state.settings.problemFilter);
65+
const problemFilter = useTypedSelector(selectProblemFilter);
6266
const autorefresh = useTypedSelector(selectAutoRefreshInterval);
6367

6468
const [useNodesEndpoint] = useSetting(USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY);

src/containers/Nodes/VirtualNodes.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,11 @@ import type {
1717
} from '../../components/VirtualTable';
1818
import {ResizeableVirtualTable} from '../../components/VirtualTable/ResizeableVirtualTable';
1919
import type {NodesPreparedEntity} from '../../store/reducers/nodes/types';
20-
import {ProblemFilterValues, changeFilter} from '../../store/reducers/settings/settings';
20+
import {
21+
ProblemFilterValues,
22+
changeFilter,
23+
selectProblemFilter,
24+
} from '../../store/reducers/settings/settings';
2125
import type {ProblemFilterValue} from '../../store/reducers/settings/types';
2226
import type {AdditionalNodesProps} from '../../types/additionalProps';
2327
import {cn} from '../../utils/cn';
@@ -56,7 +60,7 @@ export const VirtualNodes = ({path, parentContainer, additionalNodesProps}: Node
5660

5761
const dispatch = useTypedDispatch();
5862

59-
const problemFilter = useTypedSelector((state) => state.settings.problemFilter);
63+
const problemFilter = useTypedSelector(selectProblemFilter);
6064

6165
const filters = React.useMemo(() => {
6266
return [path, searchValue, problemFilter, uptimeFilter];

src/containers/Tenant/Diagnostics/HotKeys/HotKeys.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {hotKeysApi} from '../../../../store/reducers/hotKeys/hotKeys';
1111
import {schemaApi} from '../../../../store/reducers/schema/schema';
1212
import type {HotKey} from '../../../../types/api/hotkeys';
1313
import {cn} from '../../../../utils/cn';
14-
import {DEFAULT_TABLE_SETTINGS, IS_HOTKEYS_HELP_HIDDDEN_KEY} from '../../../../utils/constants';
14+
import {DEFAULT_TABLE_SETTINGS, IS_HOTKEYS_HELP_HIDDEN_KEY} from '../../../../utils/constants';
1515
import {useSetting} from '../../../../utils/hooks';
1616

1717
import i18n from './i18n';
@@ -108,7 +108,7 @@ export function HotKeys({path}: HotKeysProps) {
108108
}
109109

110110
function HelpCard() {
111-
const [helpHidden, setHelpHidden] = useSetting(IS_HOTKEYS_HELP_HIDDDEN_KEY);
111+
const [helpHidden, setHelpHidden] = useSetting(IS_HOTKEYS_HELP_HIDDEN_KEY);
112112

113113
if (helpHidden) {
114114
return null;

src/containers/Tenant/Query/QueryEditor/QueryEditor.tsx

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ import {
3232
import {useQueryModes, useSetting} from '../../../../utils/hooks';
3333
import {LANGUAGE_YQL_ID} from '../../../../utils/monaco/yql/constants';
3434
import {QUERY_ACTIONS} from '../../../../utils/query';
35-
import {parseJson} from '../../../../utils/utils';
3635
import type {InitialPaneState} from '../../utils/paneVisibilityToggleHelpers';
3736
import {
3837
PaneVisibilityActionTypes,
@@ -146,20 +145,6 @@ function QueryEditor(props: QueryEditorProps) {
146145
};
147146
}, []);
148147

149-
React.useEffect(() => {
150-
const storageEventHandler = (event: StorageEvent) => {
151-
if (event.key === SAVED_QUERIES_KEY) {
152-
const v = parseJson(event.newValue);
153-
setSavedQueries(v);
154-
}
155-
};
156-
157-
window.addEventListener('storage', storageEventHandler);
158-
return () => {
159-
window.removeEventListener('storage', storageEventHandler);
160-
};
161-
}, [setSavedQueries]);
162-
163148
React.useEffect(() => {
164149
dispatchResultVisibilityState(PaneVisibilityActionTypes.triggerCollapse);
165150
}, []);

src/lib.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export {default as appRoutes} from './routes';
1111
export {createApi, YdbEmbeddedAPI, YdbWebVersionAPI} from './services/api';
1212
export {settingsManager} from './services/settings';
1313
export {settings as userSettings} from './containers/UserSettings/settings';
14-
export {setUserSettings} from './store/reducers/settings/settings';
14+
export {setSettingValue, getSettingValue} from './store/reducers/settings/settings';
1515

1616
export {componentsRegistry} from './components/ComponentsProvider/componentsRegistry';
1717
export {useSetting, useTypedSelector} from './utils/hooks';

src/services/settings.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
BINARY_DATA_IN_PLAIN_TEXT_DISPLAY,
66
ENABLE_AUTOCOMPLETE,
77
INVERTED_DISKS_KEY,
8-
IS_HOTKEYS_HELP_HIDDDEN_KEY,
8+
IS_HOTKEYS_HELP_HIDDEN_KEY,
99
LANGUAGE_KEY,
1010
LAST_USED_QUERY_ACTION_KEY,
1111
PARTITIONS_HIDDEN_COLUMNS_KEY,
@@ -41,7 +41,7 @@ export const DEFAULT_USER_SETTINGS = {
4141
[USE_CLUSTER_BALANCER_AS_BACKEND_KEY]: true,
4242
[ENABLE_AUTOCOMPLETE]: true,
4343
[AUTOCOMPLETE_ON_ENTER]: true,
44-
[IS_HOTKEYS_HELP_HIDDDEN_KEY]: false,
44+
[IS_HOTKEYS_HELP_HIDDEN_KEY]: false,
4545
} as const satisfies SettingsObject;
4646

4747
class SettingsManager {

src/store/configureStore.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {createApi} from '../services/api';
99
import {getUrlData} from './getUrlData';
1010
import rootReducer from './reducers';
1111
import {api as storeApi} from './reducers/api';
12+
import {syncUserSettingsFromLS} from './reducers/settings/settings';
1213
import {UPDATE_REF} from './reducers/tooltip';
1314
import getLocationMiddleware from './state-url-mapping';
1415

@@ -37,6 +38,8 @@ function _configureStore<
3738
}).concat(locationMiddleware, ...middleware),
3839
});
3940

41+
syncUserSettingsFromLS(store);
42+
4043
return store;
4144
}
4245

Lines changed: 50 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,11 @@
1-
import type {Reducer, ThunkAction} from '@reduxjs/toolkit';
1+
import type {Store} from '@reduxjs/toolkit';
2+
import {createSlice} from '@reduxjs/toolkit';
23

3-
import type {RootState} from '../..';
4-
import type {SettingsObject} from '../../../services/settings';
54
import {DEFAULT_USER_SETTINGS, settingsManager} from '../../../services/settings';
5+
import {parseJson} from '../../../utils/utils';
6+
import type {AppDispatch} from '../../defaultStore';
67

7-
import type {
8-
ProblemFilterValue,
9-
SetSettingValueAction,
10-
SettingsAction,
11-
SettingsRootStateSlice,
12-
SettingsState,
13-
} from './types';
14-
15-
const CHANGE_PROBLEM_FILTER = 'settings/CHANGE_PROBLEM_FILTER';
16-
export const SET_SETTING_VALUE = 'settings/SET_VALUE';
17-
export const SET_USER_SETTINGS = 'settings/SET_USER_SETTINGS';
8+
import type {ProblemFilterValue, SettingsState} from './types';
189

1910
export const ProblemFilterValues = {
2011
ALL: 'All',
@@ -24,71 +15,60 @@ export const ProblemFilterValues = {
2415
const userSettings = settingsManager.extractSettingsFromLS(DEFAULT_USER_SETTINGS);
2516
const systemSettings = window.systemSettings || {};
2617

27-
export const initialState = {
18+
export const initialState: SettingsState = {
2819
problemFilter: ProblemFilterValues.ALL,
2920
userSettings,
3021
systemSettings,
3122
};
3223

33-
const settings: Reducer<SettingsState, SettingsAction> = (state = initialState, action) => {
34-
switch (action.type) {
35-
case CHANGE_PROBLEM_FILTER:
36-
return {
37-
...state,
38-
problemFilter: action.data,
39-
};
40-
41-
case SET_SETTING_VALUE: {
42-
const newSettings = {
43-
...state.userSettings,
44-
[action.data.name]: action.data.value,
45-
};
46-
47-
return {
48-
...state,
49-
userSettings: newSettings,
50-
};
51-
}
52-
case SET_USER_SETTINGS: {
53-
return {
54-
...state,
55-
userSettings: {
56-
...state.userSettings,
57-
...action.data,
58-
},
59-
};
60-
}
61-
default:
62-
return state;
63-
}
64-
};
65-
66-
export const setSettingValue = (
67-
name: string,
68-
value: unknown,
69-
): ThunkAction<void, RootState, unknown, SetSettingValueAction> => {
70-
return (dispatch) => {
71-
dispatch({type: SET_SETTING_VALUE, data: {name, value}});
24+
const settingsSlice = createSlice({
25+
name: 'settings',
26+
initialState,
27+
reducers: (create) => ({
28+
changeFilter: create.reducer<ProblemFilterValue>((state, action) => {
29+
state.problemFilter = action.payload;
30+
}),
31+
setSettingValue: create.reducer<{name: string; value: unknown}>((state, action) => {
32+
state.userSettings[action.payload.name] = action.payload.value;
33+
}),
34+
}),
35+
selectors: {
36+
getSettingValue: (state, name: string) => state.userSettings[name],
37+
selectProblemFilter: (state) => state.problemFilter,
38+
},
39+
});
40+
41+
export const {changeFilter} = settingsSlice.actions;
42+
export const {getSettingValue, selectProblemFilter} = settingsSlice.selectors;
43+
44+
export const setSettingValue = (name: string, value: unknown) => {
45+
return (dispatch: AppDispatch) => {
46+
dispatch(settingsSlice.actions.setSettingValue({name, value}));
7247

7348
settingsManager.setUserSettingsValue(name, value);
7449
};
7550
};
7651

77-
export const setUserSettings = (data: SettingsObject) => {
78-
return {type: SET_USER_SETTINGS, data} as const;
79-
};
80-
81-
export const getSettingValue = (state: SettingsRootStateSlice, name: string) => {
82-
return state.settings.userSettings[name];
83-
};
84-
85-
export const changeFilter = (filter: ProblemFilterValue) => {
86-
return {
87-
type: CHANGE_PROBLEM_FILTER,
88-
data: filter,
89-
} as const;
90-
};
52+
export function syncUserSettingsFromLS(store: Store) {
53+
if (typeof window === 'undefined') {
54+
return;
55+
}
9156

92-
export const selectProblemFilter = (state: SettingsRootStateSlice) => state.settings.problemFilter;
57+
window.addEventListener('storage', (event) => {
58+
if (event.key && event.key in DEFAULT_USER_SETTINGS) {
59+
const name = event.key as keyof typeof DEFAULT_USER_SETTINGS;
60+
let value = DEFAULT_USER_SETTINGS[name];
61+
if (event.newValue !== null) {
62+
value = parseJson(event.newValue);
63+
}
64+
store.dispatch(
65+
settingsSlice.actions.setSettingValue({
66+
name,
67+
value,
68+
}),
69+
);
70+
}
71+
});
72+
}
9373

94-
export default settings;
74+
export default settingsSlice.reducer;
Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,7 @@
11
import type {SettingsObject} from '../../../services/settings';
22
import type {ValueOf} from '../../../types/common';
33

4-
import type {
5-
ProblemFilterValues,
6-
SET_SETTING_VALUE,
7-
changeFilter,
8-
setUserSettings,
9-
} from './settings';
4+
import type {ProblemFilterValues} from './settings';
105

116
export type ProblemFilterValue = ValueOf<typeof ProblemFilterValues>;
127

@@ -15,17 +10,3 @@ export interface SettingsState {
1510
userSettings: SettingsObject;
1611
systemSettings: SettingsObject;
1712
}
18-
19-
export type SetSettingValueAction = {
20-
type: typeof SET_SETTING_VALUE;
21-
data: {name: string; value: unknown};
22-
};
23-
24-
export type SettingsAction =
25-
| ReturnType<typeof changeFilter>
26-
| ReturnType<typeof setUserSettings>
27-
| SetSettingValueAction;
28-
29-
export interface SettingsRootStateSlice {
30-
settings: SettingsState;
31-
}

src/utils/constants.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,4 +138,4 @@ export const ENABLE_AUTOCOMPLETE = 'enableAutocomplete';
138138

139139
export const AUTOCOMPLETE_ON_ENTER = 'autocompleteOnEnter';
140140

141-
export const IS_HOTKEYS_HELP_HIDDDEN_KEY = 'isHotKeysHelpHidden';
141+
export const IS_HOTKEYS_HELP_HIDDEN_KEY = 'isHotKeysHelpHidden';

0 commit comments

Comments
 (0)