@digitaldefiance/express-suite-react-components 2.5.7 → 2.5.9
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 +14 -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 +81 -121
- 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,20 @@ MIT © Digital Defiance
|
|
|
362
362
|
|
|
363
363
|
## ChangeLog
|
|
364
364
|
|
|
365
|
+
### Version 2.5.9
|
|
366
|
+
|
|
367
|
+
- Fix /user/verify loop
|
|
368
|
+
|
|
369
|
+
### Version 2.5.8
|
|
370
|
+
|
|
371
|
+
#### Changed
|
|
372
|
+
|
|
373
|
+
- **User Settings Storage** - Removed localStorage for userSettings (never read, server is source of truth)
|
|
374
|
+
- User settings are now only stored in-memory and persisted to the server via API
|
|
375
|
+
- Settings are loaded from the server on login/token verification
|
|
376
|
+
- Eliminates risk of stale data from localStorage
|
|
377
|
+
- Reduces unnecessary localStorage operations
|
|
378
|
+
|
|
365
379
|
### Version 2.5.7
|
|
366
380
|
|
|
367
381
|
- 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.9",
|
|
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) {
|
|
@@ -165,7 +139,8 @@ const AuthProviderInner = ({ children, baseUrl, constants, eciesConfig, onLogout
|
|
|
165
139
|
setLoading(false);
|
|
166
140
|
setIsCheckingAuth(false);
|
|
167
141
|
}
|
|
168
|
-
|
|
142
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
143
|
+
}, [authState]); // Only run when authState changes (login/logout), not when checkAuth is recreated
|
|
169
144
|
const directLogin = (0, react_1.useCallback)(async (mnemonic, username, email, expireMnemonicSeconds, expireWalletSeconds) => {
|
|
170
145
|
setLoading(true);
|
|
171
146
|
const loginResult = await authService.directLogin(mnemonic, username, email);
|
|
@@ -181,14 +156,18 @@ const AuthProviderInner = ({ children, baseUrl, constants, eciesConfig, onLogout
|
|
|
181
156
|
setAuthState((prev) => prev + 1);
|
|
182
157
|
localStorage.setItem('authToken', loginResult.token);
|
|
183
158
|
localStorage.setItem('user', JSON.stringify(loginResult.user));
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
159
|
+
await setUserSettingAndUpdateSettings({
|
|
160
|
+
darkMode: loginResult.user.darkMode,
|
|
161
|
+
currency: new i18n_lib_1.CurrencyCode(loginResult.user.currency),
|
|
162
|
+
timezone: new i18n_lib_1.Timezone(loginResult.user.timezone),
|
|
163
|
+
siteLanguage: loginResult.user.siteLanguage,
|
|
164
|
+
email: new ecies_lib_1.EmailString(loginResult.user.email),
|
|
165
|
+
directChallenge: loginResult.user.directChallenge,
|
|
166
|
+
});
|
|
188
167
|
return loginResult;
|
|
189
168
|
}
|
|
190
169
|
return loginResult;
|
|
191
|
-
}, [authService, setMnemonic, setWallet,
|
|
170
|
+
}, [authService, setMnemonic, setWallet, setUserSettingAndUpdateSettings]);
|
|
192
171
|
const emailChallengeLogin = (0, react_1.useCallback)(async (mnemonic, token, username, email, expireMnemonicSeconds, expireWalletSeconds) => {
|
|
193
172
|
setLoading(true);
|
|
194
173
|
const loginResult = await authService.emailChallengeLogin(mnemonic, token, username, email);
|
|
@@ -204,24 +183,28 @@ const AuthProviderInner = ({ children, baseUrl, constants, eciesConfig, onLogout
|
|
|
204
183
|
setAuthState((prev) => prev + 1);
|
|
205
184
|
localStorage.setItem('authToken', loginResult.token);
|
|
206
185
|
localStorage.setItem('user', JSON.stringify(loginResult.user));
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
186
|
+
await setUserSettingAndUpdateSettings({
|
|
187
|
+
darkMode: loginResult.user.darkMode,
|
|
188
|
+
currency: new i18n_lib_1.CurrencyCode(loginResult.user.currency),
|
|
189
|
+
timezone: new i18n_lib_1.Timezone(loginResult.user.timezone),
|
|
190
|
+
siteLanguage: loginResult.user.siteLanguage,
|
|
191
|
+
email: new ecies_lib_1.EmailString(loginResult.user.email),
|
|
192
|
+
directChallenge: loginResult.user.directChallenge,
|
|
193
|
+
});
|
|
211
194
|
return loginResult;
|
|
212
195
|
}
|
|
213
196
|
return loginResult;
|
|
214
|
-
}, [authService, setMnemonic, setWallet,
|
|
197
|
+
}, [authService, setMnemonic, setWallet, setUserSettingAndUpdateSettings]);
|
|
215
198
|
const getPasswordLoginService = (0, react_1.useCallback)(() => {
|
|
216
199
|
const eciesService = new ecies_lib_1.ECIESService(eciesConfig);
|
|
217
200
|
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
201
|
}, [eciesConfig]);
|
|
219
|
-
const
|
|
202
|
+
const isBrowserPasswordLoginAvailable = (0, react_1.useCallback)(() => {
|
|
220
203
|
const storedEncryptedPassword = localStorage.getItem('encryptedPassword');
|
|
221
204
|
return !!storedEncryptedPassword;
|
|
222
205
|
}, []);
|
|
223
206
|
const passwordLogin = (0, react_1.useCallback)(async (password, username, email) => {
|
|
224
|
-
if (!
|
|
207
|
+
if (!isBrowserPasswordLoginAvailable()) {
|
|
225
208
|
return { error: tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_1.SuiteCoreStringKey.Error_Login_PasswordLoginNotSetup), errorType: 'PasswordLoginNotSetup' };
|
|
226
209
|
}
|
|
227
210
|
setLoading(true);
|
|
@@ -233,12 +216,17 @@ const AuthProviderInner = ({ children, baseUrl, constants, eciesConfig, onLogout
|
|
|
233
216
|
setMnemonic(mnemonic);
|
|
234
217
|
// Set theme based on user's darkMode preference if login succeeded
|
|
235
218
|
if ('user' in loginResult) {
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
219
|
+
await setUserSettingAndUpdateSettings({
|
|
220
|
+
darkMode: loginResult.user.darkMode,
|
|
221
|
+
currency: new i18n_lib_1.CurrencyCode(loginResult.user.currency),
|
|
222
|
+
timezone: new i18n_lib_1.Timezone(loginResult.user.timezone),
|
|
223
|
+
siteLanguage: loginResult.user.siteLanguage,
|
|
224
|
+
email: new ecies_lib_1.EmailString(loginResult.user.email),
|
|
225
|
+
directChallenge: loginResult.user.directChallenge,
|
|
226
|
+
});
|
|
239
227
|
}
|
|
240
228
|
return loginResult;
|
|
241
|
-
}, [authService, getPasswordLoginService, setMnemonic, setWallet, t, tComponent,
|
|
229
|
+
}, [authService, getPasswordLoginService, setMnemonic, setWallet, t, tComponent, isBrowserPasswordLoginAvailable, setUserSettingAndUpdateSettings]);
|
|
242
230
|
const refreshToken = (0, react_1.useCallback)(async () => {
|
|
243
231
|
try {
|
|
244
232
|
const result = await authService.refreshToken();
|
|
@@ -266,7 +254,7 @@ const AuthProviderInner = ({ children, baseUrl, constants, eciesConfig, onLogout
|
|
|
266
254
|
setLoading(false);
|
|
267
255
|
return result;
|
|
268
256
|
}, [baseUrl]);
|
|
269
|
-
const
|
|
257
|
+
const setUpBrowserPasswordLogin = (0, react_1.useCallback)(async (mnemonic, password, username, email) => {
|
|
270
258
|
setLoading(true);
|
|
271
259
|
const passwordLoginService = getPasswordLoginService();
|
|
272
260
|
try {
|
|
@@ -290,10 +278,14 @@ const AuthProviderInner = ({ children, baseUrl, constants, eciesConfig, onLogout
|
|
|
290
278
|
if (loginResult.user) {
|
|
291
279
|
setUser(loginResult.user);
|
|
292
280
|
setIsAuthenticated(true);
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
281
|
+
await setUserSettingAndUpdateSettings({
|
|
282
|
+
darkMode: loginResult.user.darkMode,
|
|
283
|
+
currency: new i18n_lib_1.CurrencyCode(loginResult.user.currency),
|
|
284
|
+
timezone: new i18n_lib_1.Timezone(loginResult.user.timezone),
|
|
285
|
+
siteLanguage: loginResult.user.siteLanguage,
|
|
286
|
+
email: new ecies_lib_1.EmailString(loginResult.user.email),
|
|
287
|
+
directChallenge: loginResult.user.directChallenge,
|
|
288
|
+
});
|
|
297
289
|
}
|
|
298
290
|
setAuthState((prev) => prev + 1);
|
|
299
291
|
return {
|
|
@@ -304,7 +296,7 @@ const AuthProviderInner = ({ children, baseUrl, constants, eciesConfig, onLogout
|
|
|
304
296
|
};
|
|
305
297
|
}
|
|
306
298
|
return loginResult;
|
|
307
|
-
}, [
|
|
299
|
+
}, [authService, setUserSettingAndUpdateSettings]);
|
|
308
300
|
const logout = (0, react_1.useCallback)(async () => {
|
|
309
301
|
localStorage.removeItem('user');
|
|
310
302
|
localStorage.removeItem('authToken');
|
|
@@ -312,22 +304,18 @@ const AuthProviderInner = ({ children, baseUrl, constants, eciesConfig, onLogout
|
|
|
312
304
|
setUser(null);
|
|
313
305
|
clearWallet();
|
|
314
306
|
setIsAuthenticated(false);
|
|
315
|
-
|
|
316
|
-
setTimezone(undefined);
|
|
317
|
-
setCurrencyCode(undefined);
|
|
307
|
+
await setUserSettingAndUpdateSettings(undefined);
|
|
318
308
|
setAuthState((prev) => prev + 1);
|
|
319
309
|
// Call the optional navigation callback if provided
|
|
320
310
|
if (onLogout) {
|
|
321
311
|
onLogout();
|
|
322
312
|
}
|
|
323
|
-
}, [onLogout, clearMnemonic, clearWallet]);
|
|
313
|
+
}, [onLogout, clearMnemonic, clearWallet, setUserSettingAndUpdateSettings]);
|
|
324
314
|
const verifyToken = (0, react_1.useCallback)(async (token) => {
|
|
325
315
|
const requestUser = await authService.verifyToken(token);
|
|
326
316
|
if (typeof requestUser === 'object' && 'error' in requestUser) {
|
|
327
317
|
setIsAuthenticated(false);
|
|
328
|
-
|
|
329
|
-
setTimezone(undefined);
|
|
330
|
-
setCurrencyCode(undefined);
|
|
318
|
+
await setUserSettingAndUpdateSettings(undefined);
|
|
331
319
|
return false;
|
|
332
320
|
}
|
|
333
321
|
else {
|
|
@@ -335,9 +323,9 @@ const AuthProviderInner = ({ children, baseUrl, constants, eciesConfig, onLogout
|
|
|
335
323
|
setIsAuthenticated(true);
|
|
336
324
|
return true;
|
|
337
325
|
}
|
|
338
|
-
}, [
|
|
326
|
+
}, [authService, setUserSettingAndUpdateSettings]);
|
|
339
327
|
const changePassword = (0, react_1.useCallback)(async (currentPassword, newPassword) => {
|
|
340
|
-
if (!
|
|
328
|
+
if (!isBrowserPasswordLoginAvailable()) {
|
|
341
329
|
return { error: tComponent(suite_core_lib_1.SuiteCoreComponentId, suite_core_lib_1.SuiteCoreStringKey.Error_Login_PasswordLoginNotSetup), errorType: 'PasswordLoginNotSetup' };
|
|
342
330
|
}
|
|
343
331
|
setLoading(true);
|
|
@@ -358,26 +346,12 @@ const AuthProviderInner = ({ children, baseUrl, constants, eciesConfig, onLogout
|
|
|
358
346
|
setLoading(false);
|
|
359
347
|
return { error: 'Password change failed' };
|
|
360
348
|
}
|
|
361
|
-
}, [setMnemonic, setWallet, t, tComponent,
|
|
349
|
+
}, [setMnemonic, setWallet, t, tComponent, isBrowserPasswordLoginAvailable]);
|
|
362
350
|
const contextValue = (0, react_1.useMemo)(() => {
|
|
363
|
-
const
|
|
351
|
+
const setUserAndIsAuthenticated = async (newUser) => {
|
|
364
352
|
setUser(newUser);
|
|
365
353
|
setIsAuthenticated(!!newUser);
|
|
366
354
|
};
|
|
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
355
|
return {
|
|
382
356
|
admin: isGlobalAdmin,
|
|
383
357
|
authState,
|
|
@@ -386,16 +360,13 @@ const AuthProviderInner = ({ children, baseUrl, constants, eciesConfig, onLogout
|
|
|
386
360
|
checkAuth,
|
|
387
361
|
clearMnemonic,
|
|
388
362
|
clearWallet,
|
|
389
|
-
colorMode,
|
|
390
|
-
currencyCode,
|
|
391
363
|
directLogin,
|
|
392
364
|
emailChallengeLogin,
|
|
393
365
|
getMnemonicRemainingTime,
|
|
394
366
|
getWalletRemainingTime,
|
|
395
367
|
isAuthenticated,
|
|
396
368
|
isCheckingAuth,
|
|
397
|
-
|
|
398
|
-
language: currentLanguage,
|
|
369
|
+
isBrowserPasswordLoginAvailable,
|
|
399
370
|
loading,
|
|
400
371
|
logout,
|
|
401
372
|
mnemonic: mnemonicManager.value,
|
|
@@ -405,21 +376,17 @@ const AuthProviderInner = ({ children, baseUrl, constants, eciesConfig, onLogout
|
|
|
405
376
|
register,
|
|
406
377
|
requestEmailLogin,
|
|
407
378
|
serverPublicKey,
|
|
408
|
-
setColorMode: setColorModeAndUpdateStorage,
|
|
409
|
-
setCurrencyCode: setCurrencyCodeAndUpdateStorage,
|
|
410
|
-
setLanguage: setLanguageAndUpdateUser,
|
|
411
379
|
setMnemonic,
|
|
412
380
|
setMnemonicExpirationSeconds,
|
|
413
|
-
|
|
414
|
-
setUser:
|
|
415
|
-
|
|
381
|
+
setUpBrowserPasswordLogin,
|
|
382
|
+
setUser: setUserAndIsAuthenticated,
|
|
383
|
+
setUserSetting: setUserSettingAndUpdateSettings,
|
|
416
384
|
setWallet,
|
|
417
385
|
setWalletExpirationSeconds,
|
|
418
|
-
timezone,
|
|
419
|
-
toggleColorMode,
|
|
420
386
|
token,
|
|
421
387
|
user: frontendUser,
|
|
422
388
|
userData: user,
|
|
389
|
+
userSettings,
|
|
423
390
|
verifyToken,
|
|
424
391
|
wallet: walletManager.value,
|
|
425
392
|
walletExpirationSeconds,
|
|
@@ -428,14 +395,10 @@ const AuthProviderInner = ({ children, baseUrl, constants, eciesConfig, onLogout
|
|
|
428
395
|
authenticatedApi,
|
|
429
396
|
authState,
|
|
430
397
|
backupCodeLogin,
|
|
431
|
-
changeLanguage,
|
|
432
398
|
changePassword,
|
|
433
399
|
checkAuth,
|
|
434
400
|
clearMnemonic,
|
|
435
401
|
clearWallet,
|
|
436
|
-
colorMode,
|
|
437
|
-
currencyCode,
|
|
438
|
-
currentLanguage,
|
|
439
402
|
directLogin,
|
|
440
403
|
emailChallengeLogin,
|
|
441
404
|
frontendUser,
|
|
@@ -444,7 +407,7 @@ const AuthProviderInner = ({ children, baseUrl, constants, eciesConfig, onLogout
|
|
|
444
407
|
isAuthenticated,
|
|
445
408
|
isCheckingAuth,
|
|
446
409
|
isGlobalAdmin,
|
|
447
|
-
|
|
410
|
+
isBrowserPasswordLoginAvailable,
|
|
448
411
|
loading,
|
|
449
412
|
logout,
|
|
450
413
|
mnemonicManager.value,
|
|
@@ -454,18 +417,15 @@ const AuthProviderInner = ({ children, baseUrl, constants, eciesConfig, onLogout
|
|
|
454
417
|
register,
|
|
455
418
|
requestEmailLogin,
|
|
456
419
|
serverPublicKey,
|
|
457
|
-
setColorModeAndUpdateStorage,
|
|
458
|
-
setCurrencyCodeAndUpdateStorage,
|
|
459
420
|
setMnemonic,
|
|
460
421
|
setMnemonicExpirationSeconds,
|
|
461
|
-
|
|
462
|
-
|
|
422
|
+
setUpBrowserPasswordLogin,
|
|
423
|
+
setUserSettingAndUpdateSettings,
|
|
463
424
|
setWallet,
|
|
464
425
|
setWalletExpirationSeconds,
|
|
465
|
-
timezone,
|
|
466
|
-
toggleColorMode,
|
|
467
426
|
token,
|
|
468
427
|
user,
|
|
428
|
+
userSettings,
|
|
469
429
|
verifyToken,
|
|
470
430
|
walletManager.value,
|
|
471
431
|
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);
|