@digitaldefiance/express-suite-react-components 2.5.7 → 2.5.8
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/README.md +10 -0
- package/package.json +3 -3
- package/src/components/UserLanguageSelector.d.ts.map +1 -1
- package/src/components/UserLanguageSelector.js +8 -4
- package/src/contexts/AuthProvider.d.ts +6 -11
- package/src/contexts/AuthProvider.d.ts.map +1 -1
- package/src/contexts/AuthProvider.js +79 -120
- package/src/contexts/MenuContext.d.ts.map +1 -1
- package/src/contexts/MenuContext.js +7 -1
- package/src/hooks/useUserSettings.d.ts +25 -9
- package/src/hooks/useUserSettings.d.ts.map +1 -1
- package/src/hooks/useUserSettings.js +89 -48
- package/src/wrappers/UserSettingsFormWrapper.js +1 -1
package/README.md
CHANGED
|
@@ -362,6 +362,16 @@ MIT © Digital Defiance
|
|
|
362
362
|
|
|
363
363
|
## ChangeLog
|
|
364
364
|
|
|
365
|
+
### Version 2.5.8
|
|
366
|
+
|
|
367
|
+
#### Changed
|
|
368
|
+
|
|
369
|
+
- **User Settings Storage** - Removed localStorage for userSettings (never read, server is source of truth)
|
|
370
|
+
- User settings are now only stored in-memory and persisted to the server via API
|
|
371
|
+
- Settings are loaded from the server on login/token verification
|
|
372
|
+
- Eliminates risk of stale data from localStorage
|
|
373
|
+
- Reduces unnecessary localStorage operations
|
|
374
|
+
|
|
365
375
|
### Version 2.5.7
|
|
366
376
|
|
|
367
377
|
- Relax isRestricted check to default false if no roles available
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@digitaldefiance/express-suite-react-components",
|
|
3
|
-
"version": "2.5.
|
|
3
|
+
"version": "2.5.8",
|
|
4
4
|
"description": "React MUI components for Digital Defiance Express Suite",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"types": "src/index.d.ts",
|
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
"react-router-dom": "6.29.0"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@digitaldefiance/i18n-lib": "3.6.
|
|
29
|
-
"@digitaldefiance/suite-core-lib": "^2.2.
|
|
28
|
+
"@digitaldefiance/i18n-lib": "3.6.4",
|
|
29
|
+
"@digitaldefiance/suite-core-lib": "^2.2.22",
|
|
30
30
|
"@emotion/react": "^11.14.0",
|
|
31
31
|
"@emotion/styled": "^11.14.0",
|
|
32
32
|
"@mui/icons-material": "^7.0.2",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UserLanguageSelector.d.ts","sourceRoot":"","sources":["../../../../../packages/digitaldefiance-express-suite-react-components/src/components/UserLanguageSelector.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,EAAE,
|
|
1
|
+
{"version":3,"file":"UserLanguageSelector.d.ts","sourceRoot":"","sources":["../../../../../packages/digitaldefiance-express-suite-react-components/src/components/UserLanguageSelector.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,EAAE,EAAiC,MAAM,OAAO,CAAC;AAM1D,eAAO,MAAM,oBAAoB,EAAE,EAiClC,CAAC;AAEF,eAAe,oBAAoB,CAAC"}
|
|
@@ -5,10 +5,14 @@ const jsx_runtime_1 = require("react/jsx-runtime");
|
|
|
5
5
|
const i18n_lib_1 = require("@digitaldefiance/i18n-lib");
|
|
6
6
|
const material_1 = require("@mui/material");
|
|
7
7
|
const react_1 = require("react");
|
|
8
|
-
const AuthProvider_1 = require("../contexts/AuthProvider");
|
|
9
8
|
const Flag_1 = require("./Flag");
|
|
9
|
+
const hooks_1 = require("../hooks");
|
|
10
|
+
const services_1 = require("../services");
|
|
11
|
+
const contexts_1 = require("../contexts");
|
|
10
12
|
const UserLanguageSelector = () => {
|
|
11
|
-
const {
|
|
13
|
+
const { baseUrl } = (0, contexts_1.useSuiteConfig)();
|
|
14
|
+
const authenticatedApi = (0, react_1.useMemo)(() => (0, services_1.createAuthenticatedApiClient)(baseUrl), [baseUrl]);
|
|
15
|
+
const { currentLanguage, changeLanguage } = (0, hooks_1.useUserSettings)({ authenticatedApi });
|
|
12
16
|
const [anchorEl, setAnchorEl] = (0, react_1.useState)(null);
|
|
13
17
|
const handleClick = (event) => {
|
|
14
18
|
setAnchorEl(event.currentTarget);
|
|
@@ -17,10 +21,10 @@ const UserLanguageSelector = () => {
|
|
|
17
21
|
setAnchorEl(null);
|
|
18
22
|
};
|
|
19
23
|
const handleLanguageChange = (newLanguage) => {
|
|
20
|
-
|
|
24
|
+
changeLanguage(newLanguage);
|
|
21
25
|
handleClose();
|
|
22
26
|
};
|
|
23
|
-
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(material_1.Button, { onClick: handleClick, children: (0, jsx_runtime_1.jsx)(Flag_1.Flag, { language:
|
|
27
|
+
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(material_1.Button, { onClick: handleClick, children: (0, jsx_runtime_1.jsx)(Flag_1.Flag, { language: currentLanguage }) }), (0, jsx_runtime_1.jsx)(material_1.Menu, { anchorEl: anchorEl, open: Boolean(anchorEl), onClose: handleClose, children: Object.values(i18n_lib_1.LanguageRegistry.getAllLanguages()).map((lang) => ((0, jsx_runtime_1.jsxs)(material_1.MenuItem, { onClick: () => handleLanguageChange(lang.code), children: [(0, jsx_runtime_1.jsx)(Flag_1.Flag, { language: lang.code, sx: { mr: 1 } }), " ", lang.name] }, lang.code))) })] }));
|
|
24
28
|
};
|
|
25
29
|
exports.UserLanguageSelector = UserLanguageSelector;
|
|
26
30
|
exports.default = exports.UserLanguageSelector;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Member as FrontendMember, EmailString, IECIESConfig, SecureString } from '@digitaldefiance/ecies-lib';
|
|
2
|
-
import { CurrencyCode
|
|
2
|
+
import { CurrencyCode } from '@digitaldefiance/i18n-lib';
|
|
3
3
|
import { Wallet } from '@ethereumjs/wallet';
|
|
4
4
|
import { ReactNode } from 'react';
|
|
5
|
-
import { ISuccessMessage, IRequestUserDTO, IConstants } from '@digitaldefiance/suite-core-lib';
|
|
5
|
+
import { ISuccessMessage, IRequestUserDTO, IConstants, IUserSettings } from '@digitaldefiance/suite-core-lib';
|
|
6
6
|
import { PaletteMode } from '@mui/material';
|
|
7
7
|
export interface AuthContextData {
|
|
8
8
|
/**
|
|
@@ -69,8 +69,7 @@ export interface AuthContextData {
|
|
|
69
69
|
}>;
|
|
70
70
|
isAuthenticated: boolean;
|
|
71
71
|
isCheckingAuth: boolean;
|
|
72
|
-
|
|
73
|
-
language: string;
|
|
72
|
+
isBrowserPasswordLoginAvailable?: () => boolean;
|
|
74
73
|
loading: boolean;
|
|
75
74
|
logout: () => void;
|
|
76
75
|
mnemonic?: SecureString;
|
|
@@ -105,8 +104,6 @@ export interface AuthContextData {
|
|
|
105
104
|
}>;
|
|
106
105
|
}>;
|
|
107
106
|
serverPublicKey: string | null;
|
|
108
|
-
setColorMode: (mode?: PaletteMode) => Promise<void>;
|
|
109
|
-
setCurrencyCode: (code?: CurrencyCode) => Promise<void>;
|
|
110
107
|
/**
|
|
111
108
|
* Gets the remaining time in seconds for the mnemonic expiration
|
|
112
109
|
* @returns Number of seconds remaining, or 0 if no mnemonic is set
|
|
@@ -117,12 +114,10 @@ export interface AuthContextData {
|
|
|
117
114
|
* @returns Number of seconds remaining, or 0 if no wallet is set
|
|
118
115
|
*/
|
|
119
116
|
getWalletRemainingTime: () => number;
|
|
120
|
-
setLanguage: (lang: string) => Promise<void>;
|
|
121
117
|
setMnemonic: (mnemonic: SecureString, durationSeconds?: number) => void;
|
|
122
118
|
setMnemonicExpirationSeconds: (seconds: number) => void;
|
|
123
|
-
setTimezone: (timezone?: Timezone) => Promise<void>;
|
|
124
119
|
setWalletExpirationSeconds: (seconds: number) => void;
|
|
125
|
-
|
|
120
|
+
setUpBrowserPasswordLogin: (mnemonic: SecureString, password: SecureString, username?: string, email?: EmailString) => Promise<{
|
|
126
121
|
success: boolean;
|
|
127
122
|
message: string;
|
|
128
123
|
} | {
|
|
@@ -130,11 +125,11 @@ export interface AuthContextData {
|
|
|
130
125
|
errorType?: string;
|
|
131
126
|
}>;
|
|
132
127
|
setUser: (user: IRequestUserDTO | null) => Promise<void>;
|
|
128
|
+
setUserSetting: (setting?: Partial<IUserSettings>) => Promise<void>;
|
|
133
129
|
setWallet: (wallet: Wallet, durationSeconds?: number) => void;
|
|
134
|
-
toggleColorMode: () => Promise<void>;
|
|
135
130
|
user: FrontendMember | null;
|
|
136
131
|
userData: IRequestUserDTO | null;
|
|
137
|
-
|
|
132
|
+
userSettings: IUserSettings | undefined;
|
|
138
133
|
token: string | null;
|
|
139
134
|
wallet?: Wallet;
|
|
140
135
|
walletExpirationSeconds: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuthProvider.d.ts","sourceRoot":"","sources":["../../../../../packages/digitaldefiance-express-suite-react-components/src/contexts/AuthProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,cAAc,EAE/B,WAAW,EACX,YAAY,EACZ,YAAY,EAIb,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAEL,YAAY,
|
|
1
|
+
{"version":3,"file":"AuthProvider.d.ts","sourceRoot":"","sources":["../../../../../packages/digitaldefiance-express-suite-react-components/src/contexts/AuthProvider.tsx"],"names":[],"mappings":"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"}
|
|
@@ -11,10 +11,11 @@ const authService_1 = require("../services/authService");
|
|
|
11
11
|
const authenticatedApi_1 = require("../services/authenticatedApi");
|
|
12
12
|
const useExpiringValue_1 = require("../hooks/useExpiringValue");
|
|
13
13
|
const useLocalStorage_1 = require("../hooks/useLocalStorage");
|
|
14
|
+
const useUserSettings_1 = require("../hooks/useUserSettings");
|
|
14
15
|
const suite_core_lib_1 = require("@digitaldefiance/suite-core-lib");
|
|
15
16
|
exports.AuthContext = (0, react_1.createContext)({});
|
|
16
17
|
const AuthProviderInner = ({ children, baseUrl, constants, eciesConfig, onLogout }) => {
|
|
17
|
-
const {
|
|
18
|
+
const { t, tComponent } = (0, I18nProvider_1.useI18n)();
|
|
18
19
|
const { setColorMode: themeSetPaletteMode } = (0, ThemeProvider_1.useTheme)();
|
|
19
20
|
const authService = (0, react_1.useMemo)(() => (0, authService_1.createAuthService)(constants, baseUrl, eciesConfig), [constants, baseUrl, eciesConfig]);
|
|
20
21
|
const authenticatedApi = (0, react_1.useMemo)(() => (0, authenticatedApi_1.createAuthenticatedApiClient)(baseUrl), [baseUrl]);
|
|
@@ -34,44 +35,10 @@ const AuthProviderInner = ({ children, baseUrl, constants, eciesConfig, onLogout
|
|
|
34
35
|
const [isCheckingAuth, setIsCheckingAuth] = (0, react_1.useState)(true);
|
|
35
36
|
const [token, setToken] = (0, react_1.useState)(null);
|
|
36
37
|
const [authState, setAuthState] = (0, react_1.useState)(0);
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
const [currencyCode, setCurrencyCode] = (0, react_1.useState)(() => {
|
|
41
|
-
return new i18n_lib_1.CurrencyCode(localStorage.getItem('currencyCode') ?? i18n_lib_1.DefaultCurrencyCode);
|
|
42
|
-
});
|
|
43
|
-
const [timezone, setTimezone] = (0, react_1.useState)(() => {
|
|
44
|
-
return new i18n_lib_1.Timezone(localStorage.getItem('timezone') ?? 'UTC');
|
|
38
|
+
// Use the user settings hook for settings management
|
|
39
|
+
const { userSettings, setUserSettingAndUpdateSettings } = (0, useUserSettings_1.useUserSettings)({
|
|
40
|
+
authenticatedApi,
|
|
45
41
|
});
|
|
46
|
-
const setColorModeAndUpdateStorage = (0, react_1.useCallback)(async (mode) => {
|
|
47
|
-
themeSetPaletteMode(mode ?? 'light');
|
|
48
|
-
setColorMode(mode ?? 'light');
|
|
49
|
-
if (!mode) {
|
|
50
|
-
localStorage.removeItem('colorMode');
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
localStorage.setItem('colorMode', mode);
|
|
54
|
-
}, [themeSetPaletteMode]);
|
|
55
|
-
const setCurrencyCodeAndUpdateStorage = (0, react_1.useCallback)(async (code) => {
|
|
56
|
-
setCurrencyCode(code);
|
|
57
|
-
if (!code) {
|
|
58
|
-
localStorage.removeItem('currencyCode');
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
localStorage.setItem('currencyCode', code.value);
|
|
62
|
-
}, []);
|
|
63
|
-
const setTimezoneAndUpdateStorage = (0, react_1.useCallback)(async (code) => {
|
|
64
|
-
setTimezone(code);
|
|
65
|
-
if (!code) {
|
|
66
|
-
localStorage.removeItem('timezone');
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
localStorage.setItem('timezone', code.value);
|
|
70
|
-
}, []);
|
|
71
|
-
const toggleColorMode = (0, react_1.useCallback)(async () => {
|
|
72
|
-
const newMode = colorMode === 'light' ? 'dark' : 'light';
|
|
73
|
-
await setColorModeAndUpdateStorage(newMode);
|
|
74
|
-
}, [colorMode, setColorModeAndUpdateStorage]);
|
|
75
42
|
// Helper functions to calculate remaining time (now provided by the hooks)
|
|
76
43
|
const getMnemonicRemainingTime = mnemonicManager.getRemainingTime;
|
|
77
44
|
const getWalletRemainingTime = walletManager.getRemainingTime;
|
|
@@ -83,8 +50,10 @@ const AuthProviderInner = ({ children, baseUrl, constants, eciesConfig, onLogout
|
|
|
83
50
|
// language changes and inadvertently revert to the older user.siteLanguage,
|
|
84
51
|
// causing a second update request with English US.
|
|
85
52
|
(0, react_1.useEffect)(() => {
|
|
86
|
-
if (user?.siteLanguage
|
|
87
|
-
|
|
53
|
+
if (user?.siteLanguage) {
|
|
54
|
+
(async () => {
|
|
55
|
+
await setUserSettingAndUpdateSettings({ siteLanguage: user.siteLanguage });
|
|
56
|
+
})();
|
|
88
57
|
}
|
|
89
58
|
// We intentionally only react to changes in the user's saved language.
|
|
90
59
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
@@ -119,8 +88,7 @@ const AuthProviderInner = ({ children, baseUrl, constants, eciesConfig, onLogout
|
|
|
119
88
|
setToken(null);
|
|
120
89
|
setFrontendUser(null);
|
|
121
90
|
setServerPublicKey(null);
|
|
122
|
-
|
|
123
|
-
setCurrencyCode(undefined);
|
|
91
|
+
await setUserSettingAndUpdateSettings(undefined);
|
|
124
92
|
themeSetPaletteMode('light');
|
|
125
93
|
clearMnemonic();
|
|
126
94
|
clearWallet();
|
|
@@ -132,28 +100,34 @@ const AuthProviderInner = ({ children, baseUrl, constants, eciesConfig, onLogout
|
|
|
132
100
|
setIsAuthenticated(false);
|
|
133
101
|
setToken(null);
|
|
134
102
|
}
|
|
135
|
-
else {
|
|
136
|
-
|
|
137
|
-
|
|
103
|
+
else if ('id' in userData && 'email' in userData) {
|
|
104
|
+
const userDataDTO = userData;
|
|
105
|
+
setUser(userDataDTO);
|
|
106
|
+
setIsGlobalAdmin((userDataDTO).roles.some((r) => r.admin));
|
|
138
107
|
setIsAuthenticated(true);
|
|
139
108
|
setToken(token);
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
109
|
+
await setUserSettingAndUpdateSettings({
|
|
110
|
+
darkMode: userDataDTO.darkMode,
|
|
111
|
+
currency: new i18n_lib_1.CurrencyCode(userDataDTO.currency),
|
|
112
|
+
timezone: new i18n_lib_1.Timezone(userDataDTO.timezone),
|
|
113
|
+
siteLanguage: userDataDTO.siteLanguage,
|
|
114
|
+
email: new ecies_lib_1.EmailString(userDataDTO.email),
|
|
115
|
+
directChallenge: userDataDTO.directChallenge,
|
|
116
|
+
});
|
|
144
117
|
}
|
|
145
118
|
}
|
|
146
119
|
catch (error) {
|
|
147
120
|
console.error('Token verification failed:', error);
|
|
148
121
|
setUser(null);
|
|
149
122
|
setIsAuthenticated(false);
|
|
123
|
+
await setUserSettingAndUpdateSettings(undefined);
|
|
150
124
|
localStorage.removeItem('authToken');
|
|
151
125
|
}
|
|
152
126
|
finally {
|
|
153
127
|
setLoading(false);
|
|
154
128
|
setIsCheckingAuth(false);
|
|
155
129
|
}
|
|
156
|
-
}, [authService, clearMnemonic, clearWallet,
|
|
130
|
+
}, [authService, clearMnemonic, clearWallet, setUserSettingAndUpdateSettings, themeSetPaletteMode]);
|
|
157
131
|
(0, react_1.useEffect)(() => {
|
|
158
132
|
const token = localStorage.getItem('authToken');
|
|
159
133
|
if (token) {
|
|
@@ -181,14 +155,18 @@ const AuthProviderInner = ({ children, baseUrl, constants, eciesConfig, onLogout
|
|
|
181
155
|
setAuthState((prev) => prev + 1);
|
|
182
156
|
localStorage.setItem('authToken', loginResult.token);
|
|
183
157
|
localStorage.setItem('user', JSON.stringify(loginResult.user));
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
158
|
+
await setUserSettingAndUpdateSettings({
|
|
159
|
+
darkMode: loginResult.user.darkMode,
|
|
160
|
+
currency: new i18n_lib_1.CurrencyCode(loginResult.user.currency),
|
|
161
|
+
timezone: new i18n_lib_1.Timezone(loginResult.user.timezone),
|
|
162
|
+
siteLanguage: loginResult.user.siteLanguage,
|
|
163
|
+
email: new ecies_lib_1.EmailString(loginResult.user.email),
|
|
164
|
+
directChallenge: loginResult.user.directChallenge,
|
|
165
|
+
});
|
|
188
166
|
return loginResult;
|
|
189
167
|
}
|
|
190
168
|
return loginResult;
|
|
191
|
-
}, [authService, setMnemonic, setWallet,
|
|
169
|
+
}, [authService, setMnemonic, setWallet, setUserSettingAndUpdateSettings]);
|
|
192
170
|
const emailChallengeLogin = (0, react_1.useCallback)(async (mnemonic, token, username, email, expireMnemonicSeconds, expireWalletSeconds) => {
|
|
193
171
|
setLoading(true);
|
|
194
172
|
const loginResult = await authService.emailChallengeLogin(mnemonic, token, username, email);
|
|
@@ -204,24 +182,28 @@ const AuthProviderInner = ({ children, baseUrl, constants, eciesConfig, onLogout
|
|
|
204
182
|
setAuthState((prev) => prev + 1);
|
|
205
183
|
localStorage.setItem('authToken', loginResult.token);
|
|
206
184
|
localStorage.setItem('user', JSON.stringify(loginResult.user));
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
185
|
+
await setUserSettingAndUpdateSettings({
|
|
186
|
+
darkMode: loginResult.user.darkMode,
|
|
187
|
+
currency: new i18n_lib_1.CurrencyCode(loginResult.user.currency),
|
|
188
|
+
timezone: new i18n_lib_1.Timezone(loginResult.user.timezone),
|
|
189
|
+
siteLanguage: loginResult.user.siteLanguage,
|
|
190
|
+
email: new ecies_lib_1.EmailString(loginResult.user.email),
|
|
191
|
+
directChallenge: loginResult.user.directChallenge,
|
|
192
|
+
});
|
|
211
193
|
return loginResult;
|
|
212
194
|
}
|
|
213
195
|
return loginResult;
|
|
214
|
-
}, [authService, setMnemonic, setWallet,
|
|
196
|
+
}, [authService, setMnemonic, setWallet, setUserSettingAndUpdateSettings]);
|
|
215
197
|
const getPasswordLoginService = (0, react_1.useCallback)(() => {
|
|
216
198
|
const eciesService = new ecies_lib_1.ECIESService(eciesConfig);
|
|
217
199
|
return new ecies_lib_1.PasswordLoginService(eciesService, new ecies_lib_1.Pbkdf2Service(ecies_lib_1.Constants.PBKDF2_PROFILES, ecies_lib_1.Constants.ECIES, ecies_lib_1.Constants.PBKDF2));
|
|
218
200
|
}, [eciesConfig]);
|
|
219
|
-
const
|
|
201
|
+
const isBrowserPasswordLoginAvailable = (0, react_1.useCallback)(() => {
|
|
220
202
|
const storedEncryptedPassword = localStorage.getItem('encryptedPassword');
|
|
221
203
|
return !!storedEncryptedPassword;
|
|
222
204
|
}, []);
|
|
223
205
|
const passwordLogin = (0, react_1.useCallback)(async (password, username, email) => {
|
|
224
|
-
if (!
|
|
206
|
+
if (!isBrowserPasswordLoginAvailable()) {
|
|
225
207
|
return { error: tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_1.SuiteCoreStringKey.Error_Login_PasswordLoginNotSetup), errorType: 'PasswordLoginNotSetup' };
|
|
226
208
|
}
|
|
227
209
|
setLoading(true);
|
|
@@ -233,12 +215,17 @@ const AuthProviderInner = ({ children, baseUrl, constants, eciesConfig, onLogout
|
|
|
233
215
|
setMnemonic(mnemonic);
|
|
234
216
|
// Set theme based on user's darkMode preference if login succeeded
|
|
235
217
|
if ('user' in loginResult) {
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
218
|
+
await setUserSettingAndUpdateSettings({
|
|
219
|
+
darkMode: loginResult.user.darkMode,
|
|
220
|
+
currency: new i18n_lib_1.CurrencyCode(loginResult.user.currency),
|
|
221
|
+
timezone: new i18n_lib_1.Timezone(loginResult.user.timezone),
|
|
222
|
+
siteLanguage: loginResult.user.siteLanguage,
|
|
223
|
+
email: new ecies_lib_1.EmailString(loginResult.user.email),
|
|
224
|
+
directChallenge: loginResult.user.directChallenge,
|
|
225
|
+
});
|
|
239
226
|
}
|
|
240
227
|
return loginResult;
|
|
241
|
-
}, [authService, getPasswordLoginService, setMnemonic, setWallet, t, tComponent,
|
|
228
|
+
}, [authService, getPasswordLoginService, setMnemonic, setWallet, t, tComponent, isBrowserPasswordLoginAvailable, setUserSettingAndUpdateSettings]);
|
|
242
229
|
const refreshToken = (0, react_1.useCallback)(async () => {
|
|
243
230
|
try {
|
|
244
231
|
const result = await authService.refreshToken();
|
|
@@ -266,7 +253,7 @@ const AuthProviderInner = ({ children, baseUrl, constants, eciesConfig, onLogout
|
|
|
266
253
|
setLoading(false);
|
|
267
254
|
return result;
|
|
268
255
|
}, [baseUrl]);
|
|
269
|
-
const
|
|
256
|
+
const setUpBrowserPasswordLogin = (0, react_1.useCallback)(async (mnemonic, password, username, email) => {
|
|
270
257
|
setLoading(true);
|
|
271
258
|
const passwordLoginService = getPasswordLoginService();
|
|
272
259
|
try {
|
|
@@ -290,10 +277,14 @@ const AuthProviderInner = ({ children, baseUrl, constants, eciesConfig, onLogout
|
|
|
290
277
|
if (loginResult.user) {
|
|
291
278
|
setUser(loginResult.user);
|
|
292
279
|
setIsAuthenticated(true);
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
280
|
+
await setUserSettingAndUpdateSettings({
|
|
281
|
+
darkMode: loginResult.user.darkMode,
|
|
282
|
+
currency: new i18n_lib_1.CurrencyCode(loginResult.user.currency),
|
|
283
|
+
timezone: new i18n_lib_1.Timezone(loginResult.user.timezone),
|
|
284
|
+
siteLanguage: loginResult.user.siteLanguage,
|
|
285
|
+
email: new ecies_lib_1.EmailString(loginResult.user.email),
|
|
286
|
+
directChallenge: loginResult.user.directChallenge,
|
|
287
|
+
});
|
|
297
288
|
}
|
|
298
289
|
setAuthState((prev) => prev + 1);
|
|
299
290
|
return {
|
|
@@ -304,7 +295,7 @@ const AuthProviderInner = ({ children, baseUrl, constants, eciesConfig, onLogout
|
|
|
304
295
|
};
|
|
305
296
|
}
|
|
306
297
|
return loginResult;
|
|
307
|
-
}, [
|
|
298
|
+
}, [authService, setUserSettingAndUpdateSettings]);
|
|
308
299
|
const logout = (0, react_1.useCallback)(async () => {
|
|
309
300
|
localStorage.removeItem('user');
|
|
310
301
|
localStorage.removeItem('authToken');
|
|
@@ -312,22 +303,18 @@ const AuthProviderInner = ({ children, baseUrl, constants, eciesConfig, onLogout
|
|
|
312
303
|
setUser(null);
|
|
313
304
|
clearWallet();
|
|
314
305
|
setIsAuthenticated(false);
|
|
315
|
-
|
|
316
|
-
setTimezone(undefined);
|
|
317
|
-
setCurrencyCode(undefined);
|
|
306
|
+
await setUserSettingAndUpdateSettings(undefined);
|
|
318
307
|
setAuthState((prev) => prev + 1);
|
|
319
308
|
// Call the optional navigation callback if provided
|
|
320
309
|
if (onLogout) {
|
|
321
310
|
onLogout();
|
|
322
311
|
}
|
|
323
|
-
}, [onLogout, clearMnemonic, clearWallet]);
|
|
312
|
+
}, [onLogout, clearMnemonic, clearWallet, setUserSettingAndUpdateSettings]);
|
|
324
313
|
const verifyToken = (0, react_1.useCallback)(async (token) => {
|
|
325
314
|
const requestUser = await authService.verifyToken(token);
|
|
326
315
|
if (typeof requestUser === 'object' && 'error' in requestUser) {
|
|
327
316
|
setIsAuthenticated(false);
|
|
328
|
-
|
|
329
|
-
setTimezone(undefined);
|
|
330
|
-
setCurrencyCode(undefined);
|
|
317
|
+
await setUserSettingAndUpdateSettings(undefined);
|
|
331
318
|
return false;
|
|
332
319
|
}
|
|
333
320
|
else {
|
|
@@ -335,9 +322,9 @@ const AuthProviderInner = ({ children, baseUrl, constants, eciesConfig, onLogout
|
|
|
335
322
|
setIsAuthenticated(true);
|
|
336
323
|
return true;
|
|
337
324
|
}
|
|
338
|
-
}, [
|
|
325
|
+
}, [authService, setUserSettingAndUpdateSettings]);
|
|
339
326
|
const changePassword = (0, react_1.useCallback)(async (currentPassword, newPassword) => {
|
|
340
|
-
if (!
|
|
327
|
+
if (!isBrowserPasswordLoginAvailable()) {
|
|
341
328
|
return { error: tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_1.SuiteCoreStringKey.Error_Login_PasswordLoginNotSetup), errorType: 'PasswordLoginNotSetup' };
|
|
342
329
|
}
|
|
343
330
|
setLoading(true);
|
|
@@ -358,26 +345,12 @@ const AuthProviderInner = ({ children, baseUrl, constants, eciesConfig, onLogout
|
|
|
358
345
|
setLoading(false);
|
|
359
346
|
return { error: 'Password change failed' };
|
|
360
347
|
}
|
|
361
|
-
}, [setMnemonic, setWallet, t, tComponent,
|
|
348
|
+
}, [setMnemonic, setWallet, t, tComponent, isBrowserPasswordLoginAvailable]);
|
|
362
349
|
const contextValue = (0, react_1.useMemo)(() => {
|
|
363
|
-
const
|
|
350
|
+
const setUserAndIsAuthenticated = async (newUser) => {
|
|
364
351
|
setUser(newUser);
|
|
365
352
|
setIsAuthenticated(!!newUser);
|
|
366
353
|
};
|
|
367
|
-
const setLanguageAndUpdateUser = async (newLanguage) => {
|
|
368
|
-
// Change the language in the i18n context
|
|
369
|
-
changeLanguage(newLanguage);
|
|
370
|
-
// Update the user's language preference on the server if authenticated
|
|
371
|
-
const token = localStorage.getItem('authToken');
|
|
372
|
-
if (token) {
|
|
373
|
-
try {
|
|
374
|
-
await authenticatedApi.post('/user/language', { language: newLanguage });
|
|
375
|
-
}
|
|
376
|
-
catch (error) {
|
|
377
|
-
console.error('Failed to update user language:', error);
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
};
|
|
381
354
|
return {
|
|
382
355
|
admin: isGlobalAdmin,
|
|
383
356
|
authState,
|
|
@@ -386,16 +359,13 @@ const AuthProviderInner = ({ children, baseUrl, constants, eciesConfig, onLogout
|
|
|
386
359
|
checkAuth,
|
|
387
360
|
clearMnemonic,
|
|
388
361
|
clearWallet,
|
|
389
|
-
colorMode,
|
|
390
|
-
currencyCode,
|
|
391
362
|
directLogin,
|
|
392
363
|
emailChallengeLogin,
|
|
393
364
|
getMnemonicRemainingTime,
|
|
394
365
|
getWalletRemainingTime,
|
|
395
366
|
isAuthenticated,
|
|
396
367
|
isCheckingAuth,
|
|
397
|
-
|
|
398
|
-
language: currentLanguage,
|
|
368
|
+
isBrowserPasswordLoginAvailable,
|
|
399
369
|
loading,
|
|
400
370
|
logout,
|
|
401
371
|
mnemonic: mnemonicManager.value,
|
|
@@ -405,21 +375,17 @@ const AuthProviderInner = ({ children, baseUrl, constants, eciesConfig, onLogout
|
|
|
405
375
|
register,
|
|
406
376
|
requestEmailLogin,
|
|
407
377
|
serverPublicKey,
|
|
408
|
-
setColorMode: setColorModeAndUpdateStorage,
|
|
409
|
-
setCurrencyCode: setCurrencyCodeAndUpdateStorage,
|
|
410
|
-
setLanguage: setLanguageAndUpdateUser,
|
|
411
378
|
setMnemonic,
|
|
412
379
|
setMnemonicExpirationSeconds,
|
|
413
|
-
|
|
414
|
-
setUser:
|
|
415
|
-
|
|
380
|
+
setUpBrowserPasswordLogin,
|
|
381
|
+
setUser: setUserAndIsAuthenticated,
|
|
382
|
+
setUserSetting: setUserSettingAndUpdateSettings,
|
|
416
383
|
setWallet,
|
|
417
384
|
setWalletExpirationSeconds,
|
|
418
|
-
timezone,
|
|
419
|
-
toggleColorMode,
|
|
420
385
|
token,
|
|
421
386
|
user: frontendUser,
|
|
422
387
|
userData: user,
|
|
388
|
+
userSettings,
|
|
423
389
|
verifyToken,
|
|
424
390
|
wallet: walletManager.value,
|
|
425
391
|
walletExpirationSeconds,
|
|
@@ -428,14 +394,10 @@ const AuthProviderInner = ({ children, baseUrl, constants, eciesConfig, onLogout
|
|
|
428
394
|
authenticatedApi,
|
|
429
395
|
authState,
|
|
430
396
|
backupCodeLogin,
|
|
431
|
-
changeLanguage,
|
|
432
397
|
changePassword,
|
|
433
398
|
checkAuth,
|
|
434
399
|
clearMnemonic,
|
|
435
400
|
clearWallet,
|
|
436
|
-
colorMode,
|
|
437
|
-
currencyCode,
|
|
438
|
-
currentLanguage,
|
|
439
401
|
directLogin,
|
|
440
402
|
emailChallengeLogin,
|
|
441
403
|
frontendUser,
|
|
@@ -444,7 +406,7 @@ const AuthProviderInner = ({ children, baseUrl, constants, eciesConfig, onLogout
|
|
|
444
406
|
isAuthenticated,
|
|
445
407
|
isCheckingAuth,
|
|
446
408
|
isGlobalAdmin,
|
|
447
|
-
|
|
409
|
+
isBrowserPasswordLoginAvailable,
|
|
448
410
|
loading,
|
|
449
411
|
logout,
|
|
450
412
|
mnemonicManager.value,
|
|
@@ -454,18 +416,15 @@ const AuthProviderInner = ({ children, baseUrl, constants, eciesConfig, onLogout
|
|
|
454
416
|
register,
|
|
455
417
|
requestEmailLogin,
|
|
456
418
|
serverPublicKey,
|
|
457
|
-
setColorModeAndUpdateStorage,
|
|
458
|
-
setCurrencyCodeAndUpdateStorage,
|
|
459
419
|
setMnemonic,
|
|
460
420
|
setMnemonicExpirationSeconds,
|
|
461
|
-
|
|
462
|
-
|
|
421
|
+
setUpBrowserPasswordLogin,
|
|
422
|
+
setUserSettingAndUpdateSettings,
|
|
463
423
|
setWallet,
|
|
464
424
|
setWalletExpirationSeconds,
|
|
465
|
-
timezone,
|
|
466
|
-
toggleColorMode,
|
|
467
425
|
token,
|
|
468
426
|
user,
|
|
427
|
+
userSettings,
|
|
469
428
|
verifyToken,
|
|
470
429
|
walletManager.value,
|
|
471
430
|
walletExpirationSeconds,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MenuContext.d.ts","sourceRoot":"","sources":["../../../../../packages/digitaldefiance-express-suite-react-components/src/contexts/MenuContext.tsx"],"names":[],"mappings":"AAiBA,OAAO,EACL,EAAE,EACF,SAAS,EAQV,MAAM,OAAO,CAAC;AAEf,OAAO,EAAE,QAAQ,EAAa,MAAM,mBAAmB,CAAC;AAExD,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"MenuContext.d.ts","sourceRoot":"","sources":["../../../../../packages/digitaldefiance-express-suite-react-components/src/contexts/MenuContext.tsx"],"names":[],"mappings":"AAiBA,OAAO,EACL,EAAE,EACF,SAAS,EAQV,MAAM,OAAO,CAAC;AAEf,OAAO,EAAE,QAAQ,EAAa,MAAM,mBAAmB,CAAC;AAExD,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAKxD,UAAU,iBAAiB;IACzB,QAAQ,EAAE,SAAS,CAAC;IACpB,WAAW,CAAC,EAAE,WAAW,EAAE,CAAC;IAC5B,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,UAAU,eAAe;IACvB,WAAW,EAAE,WAAW,EAAE,CAAC;IAC3B,cAAc,EAAE,CACd,QAAQ,EAAE,QAAQ,EAClB,eAAe,EAAE,OAAO,KACrB,WAAW,EAAE,CAAC;IACnB,kBAAkB,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,MAAM,IAAI,CAAC;IACxD,mBAAmB,EAAE,CAAC,OAAO,EAAE,WAAW,EAAE,KAAK,MAAM,IAAI,CAAC;IAC5D,WAAW,EAAE,MAAM,KAAK,CAAC,WAAW,CAAC,CAAC;CACvC;AAID,eAAO,MAAM,YAAY,EAAE,EAAE,CAAC,iBAAiB,CAmP9C,CAAC;AAEF,eAAO,MAAM,OAAO,QAAO,eAM1B,CAAC"}
|
|
@@ -10,12 +10,18 @@ const react_1 = require("react");
|
|
|
10
10
|
const AuthProvider_1 = require("./AuthProvider");
|
|
11
11
|
const MenuType_1 = require("../types/MenuType");
|
|
12
12
|
const I18nProvider_1 = require("./I18nProvider");
|
|
13
|
+
const hooks_1 = require("../hooks");
|
|
14
|
+
const SuiteConfigProvider_1 = require("./SuiteConfigProvider");
|
|
15
|
+
const services_1 = require("../services");
|
|
13
16
|
const MenuContext = (0, react_1.createContext)(undefined);
|
|
14
17
|
const MenuProvider = ({ children, menuConfigs = [], enableBackupCodes = true }) => {
|
|
15
|
-
const { userData: user, isAuthenticated, mnemonic, clearMnemonic, wallet, clearWallet, colorMode
|
|
18
|
+
const { userData: user, isAuthenticated, mnemonic, clearMnemonic, wallet, clearWallet, colorMode } = (0, AuthProvider_1.useAuth)();
|
|
16
19
|
const registeredMenuOptions = (0, react_1.useRef)(new Set());
|
|
17
20
|
const [registeredOptions, setRegisteredOptions] = (0, react_1.useState)(new Map());
|
|
18
21
|
const { tComponent } = (0, I18nProvider_1.useI18n)();
|
|
22
|
+
const { baseUrl } = (0, SuiteConfigProvider_1.useSuiteConfig)();
|
|
23
|
+
const authenticatedApi = (0, react_1.useMemo)(() => (0, services_1.createAuthenticatedApiClient)(baseUrl), [baseUrl]);
|
|
24
|
+
const { toggleColorMode } = (0, hooks_1.useUserSettings)({ authenticatedApi });
|
|
19
25
|
const registerMenuOption = (0, react_1.useCallback)((option) => {
|
|
20
26
|
const unregister = () => {
|
|
21
27
|
setRegisteredOptions((prev) => {
|
|
@@ -1,13 +1,25 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
darkMode: boolean;
|
|
7
|
-
directChallenge: boolean;
|
|
8
|
-
[key: string]: any;
|
|
1
|
+
import { IUserSettings, IUserSettingsDTO } from '@digitaldefiance/suite-core-lib';
|
|
2
|
+
export interface UseUserSettingsOptions {
|
|
3
|
+
authenticatedApi: {
|
|
4
|
+
post: (url: string, data: any) => Promise<any>;
|
|
5
|
+
};
|
|
9
6
|
}
|
|
10
7
|
export interface UseUserSettingsResult {
|
|
8
|
+
currentLanguage: string;
|
|
9
|
+
changeLanguage: (languageCode: string) => Promise<void>;
|
|
10
|
+
userSettings: IUserSettings | undefined;
|
|
11
|
+
setUserSettingAndUpdateSettings: (setting?: Partial<IUserSettings>) => Promise<void>;
|
|
12
|
+
toggleColorMode: () => Promise<void>;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Hook for managing user settings state and synchronization.
|
|
16
|
+
* Used by AuthProvider to handle user settings logic.
|
|
17
|
+
*/
|
|
18
|
+
export declare const useUserSettings: ({ authenticatedApi, }: UseUserSettingsOptions) => UseUserSettingsResult;
|
|
19
|
+
export interface UserSettingsValues extends IUserSettingsDTO {
|
|
20
|
+
[key: string]: any;
|
|
21
|
+
}
|
|
22
|
+
export interface UseUserSettingsPublicResult {
|
|
11
23
|
settings: UserSettingsValues | null;
|
|
12
24
|
isLoading: boolean;
|
|
13
25
|
error: Error | null;
|
|
@@ -25,5 +37,9 @@ export interface UseUserSettingsResult {
|
|
|
25
37
|
}>;
|
|
26
38
|
refreshSettings: () => Promise<void>;
|
|
27
39
|
}
|
|
28
|
-
|
|
40
|
+
/**
|
|
41
|
+
* Public hook for components to manage user settings.
|
|
42
|
+
* Provides a simpler API for fetching and updating settings.
|
|
43
|
+
*/
|
|
44
|
+
export declare const useUserSettingsPublic: () => UseUserSettingsPublicResult;
|
|
29
45
|
//# sourceMappingURL=useUserSettings.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useUserSettings.d.ts","sourceRoot":"","sources":["../../../../../packages/digitaldefiance-express-suite-react-components/src/hooks/useUserSettings.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useUserSettings.d.ts","sourceRoot":"","sources":["../../../../../packages/digitaldefiance-express-suite-react-components/src/hooks/useUserSettings.ts"],"names":[],"mappings":"AASA,OAAO,EACL,aAAa,EAGb,gBAAgB,EAIjB,MAAM,iCAAiC,CAAC;AAYzC,MAAM,WAAW,sBAAsB;IACrC,gBAAgB,EAAE;QAChB,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;KAChD,CAAC;CACH;AAED,MAAM,WAAW,qBAAqB;IACpC,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACxD,YAAY,EAAE,aAAa,GAAG,SAAS,CAAC;IACxC,+BAA+B,EAAE,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrF,eAAe,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACtC;AAED;;;GAGG;AACH,eAAO,MAAM,eAAe,GAAI,uBAE7B,sBAAsB,KAAG,qBAoD3B,CAAC;AAGF,MAAM,WAAW,kBAAmB,SAAQ,gBAAgB;IAC1D,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,EAAE,kBAAkB,GAAG,IAAI,CAAC;IACpC,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,cAAc,EAAE,CAAC,MAAM,EAAE,kBAAkB,KAAK,OAAO,CAAC;QACtD,OAAO,EAAE,OAAO,CAAC;QACjB,OAAO,EAAE,MAAM,CAAC;KACjB,GAAG;QACF,KAAK,EAAE,MAAM,CAAC;QACd,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,GAAG,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KAC/C,CAAC,CAAC;IACH,eAAe,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACtC;AAED;;;GAGG;AACH,eAAO,MAAM,qBAAqB,QAAO,2BA2ExC,CAAC"}
|
|
@@ -1,17 +1,74 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.useUserSettings = void 0;
|
|
3
|
+
exports.useUserSettingsPublic = exports.useUserSettings = void 0;
|
|
4
4
|
const react_1 = require("react");
|
|
5
|
-
const services_1 = require("../services");
|
|
6
|
-
const contexts_1 = require("../contexts");
|
|
7
|
-
const contexts_2 = require("../contexts");
|
|
8
5
|
const i18n_lib_1 = require("@digitaldefiance/i18n-lib");
|
|
6
|
+
const ecies_lib_1 = require("@digitaldefiance/ecies-lib");
|
|
9
7
|
const suite_core_lib_1 = require("@digitaldefiance/suite-core-lib");
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
8
|
+
const contexts_1 = require("../contexts");
|
|
9
|
+
const defaultUserSettings = {
|
|
10
|
+
darkMode: false,
|
|
11
|
+
currency: new i18n_lib_1.CurrencyCode(i18n_lib_1.DefaultCurrencyCode),
|
|
12
|
+
timezone: new i18n_lib_1.Timezone(i18n_lib_1.DefaultTimezone),
|
|
13
|
+
siteLanguage: i18n_lib_1.DefaultLanguageCode,
|
|
14
|
+
email: new ecies_lib_1.EmailString('bob@example.com'),
|
|
15
|
+
directChallenge: false,
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Hook for managing user settings state and synchronization.
|
|
19
|
+
* Used by AuthProvider to handle user settings logic.
|
|
20
|
+
*/
|
|
21
|
+
const useUserSettings = ({ authenticatedApi, }) => {
|
|
22
|
+
const { isAuthenticated } = (0, contexts_1.useAuth)();
|
|
23
|
+
const { setColorMode: themeSetPaletteMode } = (0, contexts_1.useTheme)();
|
|
24
|
+
const { currentLanguage, changeLanguage } = (0, contexts_1.useI18n)();
|
|
25
|
+
const [userSettings, setUserSettings] = (0, react_1.useState)(undefined);
|
|
26
|
+
const setUserSettingAndUpdateSettings = (0, react_1.useCallback)(async (setting) => {
|
|
27
|
+
if (setting) {
|
|
28
|
+
const newUserSettings = {
|
|
29
|
+
...defaultUserSettings,
|
|
30
|
+
...(userSettings ? userSettings : {}),
|
|
31
|
+
...setting,
|
|
32
|
+
};
|
|
33
|
+
setUserSettings(newUserSettings);
|
|
34
|
+
if (setting.darkMode !== undefined) {
|
|
35
|
+
themeSetPaletteMode(setting.darkMode ? 'dark' : 'light');
|
|
36
|
+
}
|
|
37
|
+
if (setting.siteLanguage !== undefined && setting.siteLanguage !== currentLanguage) {
|
|
38
|
+
changeLanguage(setting.siteLanguage);
|
|
39
|
+
}
|
|
40
|
+
const dehydratedSettings = (0, suite_core_lib_1.dehydrateUserSettings)(newUserSettings);
|
|
41
|
+
if (isAuthenticated) {
|
|
42
|
+
await authenticatedApi.post('/user/settings', dehydratedSettings);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
setUserSettings(undefined);
|
|
47
|
+
themeSetPaletteMode('light');
|
|
48
|
+
}
|
|
49
|
+
}, [isAuthenticated, userSettings, currentLanguage, changeLanguage, themeSetPaletteMode, authenticatedApi]);
|
|
50
|
+
const changeLanguageSetting = (0, react_1.useCallback)(async (languageCode) => {
|
|
51
|
+
await setUserSettingAndUpdateSettings({ siteLanguage: languageCode });
|
|
52
|
+
}, [setUserSettingAndUpdateSettings]);
|
|
53
|
+
const toggleColorMode = async () => {
|
|
54
|
+
const currentSetting = { ...({ darkMode: userSettings?.darkMode ? userSettings.darkMode : true }) };
|
|
55
|
+
await setUserSettingAndUpdateSettings({ ...currentSetting, darkMode: !currentSetting.darkMode });
|
|
56
|
+
};
|
|
57
|
+
return {
|
|
58
|
+
changeLanguage: changeLanguageSetting,
|
|
59
|
+
currentLanguage,
|
|
60
|
+
userSettings,
|
|
61
|
+
setUserSettingAndUpdateSettings,
|
|
62
|
+
toggleColorMode,
|
|
63
|
+
};
|
|
64
|
+
};
|
|
65
|
+
exports.useUserSettings = useUserSettings;
|
|
66
|
+
/**
|
|
67
|
+
* Public hook for components to manage user settings.
|
|
68
|
+
* Provides a simpler API for fetching and updating settings.
|
|
69
|
+
*/
|
|
70
|
+
const useUserSettingsPublic = () => {
|
|
71
|
+
const { userData, setUserSetting, userSettings } = (0, contexts_1.useAuth)();
|
|
15
72
|
const [settings, setSettings] = (0, react_1.useState)(null);
|
|
16
73
|
const [isLoading, setIsLoading] = (0, react_1.useState)(true);
|
|
17
74
|
const [error, setError] = (0, react_1.useState)(null);
|
|
@@ -19,64 +76,48 @@ const useUserSettings = () => {
|
|
|
19
76
|
setIsLoading(true);
|
|
20
77
|
setError(null);
|
|
21
78
|
try {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
setSettings(
|
|
79
|
+
if (userSettings) {
|
|
80
|
+
const dehydratedSettings = (0, suite_core_lib_1.dehydrateUserSettings)(userSettings);
|
|
81
|
+
setSettings(dehydratedSettings);
|
|
25
82
|
}
|
|
26
|
-
else {
|
|
27
|
-
// Fallback to userData - use current value without dependency
|
|
83
|
+
else if (userData) {
|
|
28
84
|
const fallback = {
|
|
29
|
-
email: userData
|
|
30
|
-
timezone: userData
|
|
31
|
-
siteLanguage: userData
|
|
32
|
-
currency: userData
|
|
33
|
-
darkMode: userData
|
|
34
|
-
directChallenge: userData
|
|
85
|
+
email: userData.email || '',
|
|
86
|
+
timezone: userData.timezone || 'UTC',
|
|
87
|
+
siteLanguage: userData.siteLanguage || 'en-US',
|
|
88
|
+
currency: userData.currency || 'USD',
|
|
89
|
+
darkMode: userData.darkMode || false,
|
|
90
|
+
directChallenge: userData.directChallenge || false,
|
|
35
91
|
};
|
|
36
92
|
setSettings(fallback);
|
|
37
93
|
}
|
|
38
94
|
}
|
|
39
95
|
catch (err) {
|
|
40
96
|
setError(err instanceof Error ? err : new suite_core_lib_1.TranslatableSuiteError(suite_core_lib_1.SuiteCoreStringKey.Settings_RetrieveFailure));
|
|
41
|
-
// Use fallback from userData
|
|
42
|
-
const fallback = {
|
|
43
|
-
email: userData?.email || '',
|
|
44
|
-
timezone: userData?.timezone || 'UTC',
|
|
45
|
-
siteLanguage: userData?.siteLanguage || 'en-US',
|
|
46
|
-
currency: userData?.currency || 'USD',
|
|
47
|
-
darkMode: userData?.darkMode || false,
|
|
48
|
-
directChallenge: userData?.directChallenge || false,
|
|
49
|
-
};
|
|
50
|
-
setSettings(fallback);
|
|
51
97
|
}
|
|
52
98
|
finally {
|
|
53
99
|
setIsLoading(false);
|
|
54
100
|
}
|
|
55
|
-
|
|
56
|
-
}, [api]); // userData intentionally omitted to prevent infinite loops
|
|
101
|
+
}, [userSettings, userData]);
|
|
57
102
|
(0, react_1.useEffect)(() => {
|
|
58
103
|
refreshSettings();
|
|
59
104
|
}, [refreshSettings]);
|
|
60
|
-
const updateSettings = async (values) => {
|
|
105
|
+
const updateSettings = (0, react_1.useCallback)(async (values) => {
|
|
61
106
|
setIsLoading(true);
|
|
62
107
|
setError(null);
|
|
63
108
|
try {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
72
|
-
if (values.darkMode !== userData?.darkMode) {
|
|
73
|
-
setColorMode(values.darkMode ? 'dark' : 'light');
|
|
74
|
-
}
|
|
75
|
-
// Update local state
|
|
109
|
+
await setUserSetting({
|
|
110
|
+
darkMode: values.darkMode,
|
|
111
|
+
currency: new i18n_lib_1.CurrencyCode(values.currency),
|
|
112
|
+
timezone: new i18n_lib_1.Timezone(values.timezone),
|
|
113
|
+
siteLanguage: values.siteLanguage,
|
|
114
|
+
email: new ecies_lib_1.EmailString(values.email),
|
|
115
|
+
directChallenge: values.directChallenge,
|
|
116
|
+
});
|
|
76
117
|
setSettings(values);
|
|
77
118
|
return {
|
|
78
119
|
success: true,
|
|
79
|
-
message:
|
|
120
|
+
message: (0, suite_core_lib_1.getSuiteCoreTranslation)(suite_core_lib_1.SuiteCoreStringKey.Settings_SaveSuccess)
|
|
80
121
|
};
|
|
81
122
|
}
|
|
82
123
|
catch (err) {
|
|
@@ -92,7 +133,7 @@ const useUserSettings = () => {
|
|
|
92
133
|
finally {
|
|
93
134
|
setIsLoading(false);
|
|
94
135
|
}
|
|
95
|
-
};
|
|
136
|
+
}, [setUserSetting]);
|
|
96
137
|
return {
|
|
97
138
|
settings,
|
|
98
139
|
isLoading,
|
|
@@ -101,4 +142,4 @@ const useUserSettings = () => {
|
|
|
101
142
|
refreshSettings,
|
|
102
143
|
};
|
|
103
144
|
};
|
|
104
|
-
exports.
|
|
145
|
+
exports.useUserSettingsPublic = useUserSettingsPublic;
|
|
@@ -7,7 +7,7 @@ const contexts_1 = require("../contexts");
|
|
|
7
7
|
const hooks_1 = require("../hooks");
|
|
8
8
|
const suite_core_lib_1 = require("@digitaldefiance/suite-core-lib");
|
|
9
9
|
const UserSettingsFormWrapper = ({ onSuccess, componentProps = {}, }) => {
|
|
10
|
-
const { settings, isLoading, updateSettings } = (0, hooks_1.
|
|
10
|
+
const { settings, isLoading, updateSettings } = (0, hooks_1.useUserSettingsPublic)();
|
|
11
11
|
const { languages } = (0, contexts_1.useSuiteConfig)();
|
|
12
12
|
const handleSubmit = async (values) => {
|
|
13
13
|
const result = await updateSettings(values);
|