@dashadmin/dash-admin 1.3.50 → 1.3.52
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/dist/components/avatar/Avatar.js +10 -1
- package/dist/components/currency/Format.js +3 -1
- package/dist/components/i18n/BridgedLocalesMenuButton.js +4 -2
- package/dist/components/misc/NoResults.js +3 -1
- package/dist/components/permission/PermissionsSelector.js +34 -14
- package/dist/components/permission/PermissionsSelectorList.js +11 -1
- package/dist/components/selects/RASearchableSelect.js +8 -6
- package/dist/components/selects/RASearchableSelectChips.js +8 -6
- package/dist/components/selects/SearchableSelect.js +8 -6
- package/dist/components/subscription/PlanAddonsSettings.js +88 -17
- package/dist/components/subscription/PlanAuditLog.js +41 -21
- package/dist/components/subscription/PlanFeaturesSettings.js +35 -6
- package/dist/components/subscription/PlanMetadataSettings.js +78 -42
- package/dist/components/subscription/PlanPricesSettings.js +20 -8
- package/dist/components/tenant/TenantSelector.js +8 -6
- package/dist/components/user/UserPreferences.js +77 -22
- package/dist/default-theme/DashThemeContext.js +3 -8
- package/dist/pages/DASHLightWeightLogin.js +7 -5
- package/dist/pages/Profile.js +5 -3
- package/dist/pages/RecoverPassword.js +28 -14
- package/dist/schemas/subscription/components/SubscriptionPaymentHistory.js +14 -2
- package/dist/schemas/subscription/components/SubscriptionPlanFeatures.js +37 -25
- package/dist/schemas/subscription/components/SubscriptionPlanPreview.js +47 -28
- package/dist/schemas/subscription/components/SubscriptionPlanStats.js +127 -37
- package/package.json +3 -3
- package/src/DASHAdmin.tsx +1 -0
- package/src/components/avatar/Avatar.tsx +8 -4
- package/src/components/currency/Format.tsx +8 -6
- package/src/components/i18n/BridgedLocalesMenuButton.tsx +4 -2
- package/src/components/misc/DASHGlobalErrorHandler.tsx +1 -1
- package/src/components/misc/NoResults.tsx +7 -4
- package/src/components/permission/AvailablePermissionsContext.tsx +1 -1
- package/src/components/permission/PermissionsSelector.tsx +48 -33
- package/src/components/permission/PermissionsSelectorList.tsx +7 -2
- package/src/components/selects/RASearchableSelect.tsx +22 -19
- package/src/components/selects/RASearchableSelectChips.tsx +23 -19
- package/src/components/selects/SearchableSelect.tsx +22 -18
- package/src/components/subscription/PlanAddonsSettings.tsx +61 -20
- package/src/components/subscription/PlanAuditLog.tsx +22 -8
- package/src/components/subscription/PlanFeaturesSettings.tsx +28 -8
- package/src/components/subscription/PlanMetadataSettings.tsx +29 -7
- package/src/components/subscription/PlanPricesSettings.tsx +30 -18
- package/src/components/tenant/TenantAttributesContext.tsx +1 -1
- package/src/components/tenant/TenantSelector.tsx +20 -17
- package/src/components/tenant/TenantSettingsContext.tsx +1 -1
- package/src/components/user/UserPreferences.tsx +56 -21
- package/src/contexts/SystemRequestsCache.tsx +1 -1
- package/src/default-theme/DASHAppProviders.tsx +1 -1
- package/src/default-theme/DashThemeContext.tsx +5 -14
- package/src/default-theme/menu/AppMenuComponents/expanded/CollapsableSidebarMenu.tsx +3 -3
- package/src/default-theme/menu/SidebarActions.tsx +6 -6
- package/src/pages/DASHLightWeightLogin.tsx +8 -7
- package/src/pages/Profile.tsx +10 -9
- package/src/pages/RecoverPassword.tsx +15 -6
- package/src/schemas/subscription/components/SubscriptionPaymentHistory.tsx +9 -2
- package/src/schemas/subscription/components/SubscriptionPlanFeatures.tsx +10 -3
- package/src/schemas/subscription/components/SubscriptionPlanPreview.tsx +25 -12
- package/src/schemas/subscription/components/SubscriptionPlanStats.tsx +64 -14
- package/src/theme/AppSidebarLogo.tsx +7 -7
|
@@ -42,9 +42,13 @@ const PlanFeaturesView: React.FC<IDashAutoAdminCustomFieldComponent> = () => {
|
|
|
42
42
|
|
|
43
43
|
if (!features.length) {
|
|
44
44
|
return (
|
|
45
|
-
<Typography
|
|
46
|
-
|
|
47
|
-
|
|
45
|
+
<Typography
|
|
46
|
+
variant="body2"
|
|
47
|
+
sx={{
|
|
48
|
+
color: "text.secondary",
|
|
49
|
+
py: 2
|
|
50
|
+
}}>No features configured
|
|
51
|
+
</Typography>
|
|
48
52
|
);
|
|
49
53
|
}
|
|
50
54
|
|
|
@@ -78,11 +82,17 @@ const PlanFeaturesList: React.FC<IDashAutoAdminCustomFieldComponent> = () => {
|
|
|
78
82
|
const features = record?.features || [];
|
|
79
83
|
|
|
80
84
|
if (!features.length) {
|
|
81
|
-
return
|
|
85
|
+
return (
|
|
86
|
+
<Typography variant="body2" sx={{
|
|
87
|
+
color: "text.secondary"
|
|
88
|
+
}}>—</Typography>
|
|
89
|
+
);
|
|
82
90
|
}
|
|
83
91
|
|
|
84
92
|
return (
|
|
85
|
-
<Stack direction="row" spacing={0.5}
|
|
93
|
+
<Stack direction="row" spacing={0.5} useFlexGap sx={{
|
|
94
|
+
flexWrap: "wrap"
|
|
95
|
+
}}>
|
|
86
96
|
{features.slice(0, 3).map((feature, index) => (
|
|
87
97
|
<Chip
|
|
88
98
|
key={index}
|
|
@@ -151,7 +161,13 @@ const PlanFeaturesEdit: React.FC<IDashAutoAdminCustomFieldComponent> = () => {
|
|
|
151
161
|
<Typography variant="subtitle2" gutterBottom>
|
|
152
162
|
Plan Features
|
|
153
163
|
</Typography>
|
|
154
|
-
<Typography
|
|
164
|
+
<Typography
|
|
165
|
+
variant="caption"
|
|
166
|
+
sx={{
|
|
167
|
+
color: "text.secondary",
|
|
168
|
+
display: "block",
|
|
169
|
+
mb: 2
|
|
170
|
+
}}>
|
|
155
171
|
Add feature keys that are enabled for this plan (e.g., "api_access", "custom_branding")
|
|
156
172
|
</Typography>
|
|
157
173
|
|
|
@@ -177,7 +193,9 @@ const PlanFeaturesEdit: React.FC<IDashAutoAdminCustomFieldComponent> = () => {
|
|
|
177
193
|
{/* Display current features */}
|
|
178
194
|
{features.length > 0 ? (
|
|
179
195
|
<Paper variant="outlined" sx={{ p: 1 }}>
|
|
180
|
-
<Stack direction="row" spacing={1}
|
|
196
|
+
<Stack direction="row" spacing={1} useFlexGap sx={{
|
|
197
|
+
flexWrap: "wrap"
|
|
198
|
+
}}>
|
|
181
199
|
{features.map((feature, index) => (
|
|
182
200
|
<Chip
|
|
183
201
|
key={index}
|
|
@@ -191,7 +209,9 @@ const PlanFeaturesEdit: React.FC<IDashAutoAdminCustomFieldComponent> = () => {
|
|
|
191
209
|
</Stack>
|
|
192
210
|
</Paper>
|
|
193
211
|
) : (
|
|
194
|
-
<Typography variant="body2"
|
|
212
|
+
<Typography variant="body2" sx={{
|
|
213
|
+
color: "text.secondary"
|
|
214
|
+
}}>
|
|
195
215
|
No features added yet
|
|
196
216
|
</Typography>
|
|
197
217
|
)}
|
|
@@ -48,9 +48,13 @@ const PlanMetadataView: React.FC<IDashAutoAdminCustomFieldComponent> = () => {
|
|
|
48
48
|
|
|
49
49
|
if (!entries.length) {
|
|
50
50
|
return (
|
|
51
|
-
<Typography
|
|
52
|
-
|
|
53
|
-
|
|
51
|
+
<Typography
|
|
52
|
+
variant="body2"
|
|
53
|
+
sx={{
|
|
54
|
+
color: "text.secondary",
|
|
55
|
+
py: 2
|
|
56
|
+
}}>No metadata configured
|
|
57
|
+
</Typography>
|
|
54
58
|
);
|
|
55
59
|
}
|
|
56
60
|
|
|
@@ -87,7 +91,11 @@ const PlanMetadataList: React.FC<IDashAutoAdminCustomFieldComponent> = () => {
|
|
|
87
91
|
const count = Object.keys(metadata).length;
|
|
88
92
|
|
|
89
93
|
if (!count) {
|
|
90
|
-
return
|
|
94
|
+
return (
|
|
95
|
+
<Typography variant="body2" sx={{
|
|
96
|
+
color: "text.secondary"
|
|
97
|
+
}}>—</Typography>
|
|
98
|
+
);
|
|
91
99
|
}
|
|
92
100
|
|
|
93
101
|
return (
|
|
@@ -177,12 +185,24 @@ const PlanMetadataEdit: React.FC<IDashAutoAdminCustomFieldComponent> = () => {
|
|
|
177
185
|
<Typography variant="subtitle2" gutterBottom>
|
|
178
186
|
Plan Metadata
|
|
179
187
|
</Typography>
|
|
180
|
-
<Typography
|
|
188
|
+
<Typography
|
|
189
|
+
variant="caption"
|
|
190
|
+
sx={{
|
|
191
|
+
color: "text.secondary",
|
|
192
|
+
display: "block",
|
|
193
|
+
mb: 2
|
|
194
|
+
}}>
|
|
181
195
|
Add key-value pairs for additional plan configuration
|
|
182
196
|
</Typography>
|
|
183
197
|
|
|
184
198
|
{/* Add new pair input */}
|
|
185
|
-
<Stack
|
|
199
|
+
<Stack
|
|
200
|
+
direction="row"
|
|
201
|
+
spacing={1}
|
|
202
|
+
sx={{
|
|
203
|
+
alignItems: "flex-start",
|
|
204
|
+
mb: 2
|
|
205
|
+
}}>
|
|
186
206
|
<TextField
|
|
187
207
|
value={newKey}
|
|
188
208
|
onChange={(e) => {
|
|
@@ -252,7 +272,9 @@ const PlanMetadataEdit: React.FC<IDashAutoAdminCustomFieldComponent> = () => {
|
|
|
252
272
|
</Table>
|
|
253
273
|
</TableContainer>
|
|
254
274
|
) : (
|
|
255
|
-
<Typography variant="body2"
|
|
275
|
+
<Typography variant="body2" sx={{
|
|
276
|
+
color: "text.secondary"
|
|
277
|
+
}}>
|
|
256
278
|
No metadata added yet
|
|
257
279
|
</Typography>
|
|
258
280
|
)}
|
|
@@ -69,9 +69,10 @@ const PlanPricesView: React.FC<IDashAutoAdminCustomFieldComponent> = () => {
|
|
|
69
69
|
|
|
70
70
|
if (!prices || Object.keys(prices).length === 0) {
|
|
71
71
|
return (
|
|
72
|
-
<Typography variant="body2"
|
|
73
|
-
|
|
74
|
-
|
|
72
|
+
<Typography variant="body2" sx={{
|
|
73
|
+
color: "text.secondary"
|
|
74
|
+
}}>No prices configured
|
|
75
|
+
</Typography>
|
|
75
76
|
);
|
|
76
77
|
}
|
|
77
78
|
|
|
@@ -101,7 +102,9 @@ const PlanPricesView: React.FC<IDashAutoAdminCustomFieldComponent> = () => {
|
|
|
101
102
|
color={currency?.is_default ? 'primary' : 'default'}
|
|
102
103
|
/>
|
|
103
104
|
{currency?.is_default && (
|
|
104
|
-
<Typography variant="caption"
|
|
105
|
+
<Typography variant="caption" sx={{
|
|
106
|
+
color: "text.secondary"
|
|
107
|
+
}}>
|
|
105
108
|
(Default)
|
|
106
109
|
</Typography>
|
|
107
110
|
)}
|
|
@@ -127,7 +130,11 @@ const PlanPricesList: React.FC<IDashAutoAdminCustomFieldComponent> = () => {
|
|
|
127
130
|
const prices = plan?.prices;
|
|
128
131
|
|
|
129
132
|
if (!prices || Object.keys(prices).length === 0) {
|
|
130
|
-
return
|
|
133
|
+
return (
|
|
134
|
+
<Typography variant="body2" sx={{
|
|
135
|
+
color: "text.secondary"
|
|
136
|
+
}}>—</Typography>
|
|
137
|
+
);
|
|
131
138
|
}
|
|
132
139
|
|
|
133
140
|
return (
|
|
@@ -215,18 +222,21 @@ const PlanPricesEdit: React.FC<IDashAutoAdminCustomFieldComponent> = ({ method }
|
|
|
215
222
|
|
|
216
223
|
if (!currencies || currencies.length === 0) {
|
|
217
224
|
return (
|
|
218
|
-
<Typography variant="body2"
|
|
219
|
-
|
|
220
|
-
|
|
225
|
+
<Typography variant="body2" sx={{
|
|
226
|
+
color: "text.secondary"
|
|
227
|
+
}}>No currencies available. Please configure currencies first.
|
|
228
|
+
</Typography>
|
|
221
229
|
);
|
|
222
230
|
}
|
|
223
231
|
|
|
224
232
|
return (
|
|
225
233
|
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
|
|
226
|
-
<Typography variant="subtitle2"
|
|
234
|
+
<Typography variant="subtitle2" sx={{
|
|
235
|
+
color: "text.secondary"
|
|
236
|
+
}}>
|
|
227
237
|
Set the price for each available currency (in cents/smallest unit)
|
|
228
238
|
</Typography>
|
|
229
|
-
|
|
239
|
+
|
|
230
240
|
{currencies.map((currency) => {
|
|
231
241
|
const currentValue = currentPrices[currency.code] ?? '';
|
|
232
242
|
|
|
@@ -237,13 +247,6 @@ const PlanPricesEdit: React.FC<IDashAutoAdminCustomFieldComponent> = ({ method }
|
|
|
237
247
|
type="number"
|
|
238
248
|
value={currentValue}
|
|
239
249
|
onChange={(e) => handlePriceChange(currency.code, e.target.value)}
|
|
240
|
-
InputProps={{
|
|
241
|
-
startAdornment: (
|
|
242
|
-
<InputAdornment position="start">
|
|
243
|
-
{currency.symbol}
|
|
244
|
-
</InputAdornment>
|
|
245
|
-
),
|
|
246
|
-
}}
|
|
247
250
|
helperText={
|
|
248
251
|
currency.format
|
|
249
252
|
? `Format: ${currency.format} • Example: ${currency.symbol}${numeral(29900).format(currency.format)}`
|
|
@@ -259,10 +262,19 @@ const PlanPricesEdit: React.FC<IDashAutoAdminCustomFieldComponent> = ({ method }
|
|
|
259
262
|
}
|
|
260
263
|
} : {}
|
|
261
264
|
}}
|
|
265
|
+
slotProps={{
|
|
266
|
+
input: {
|
|
267
|
+
startAdornment: (
|
|
268
|
+
<InputAdornment position="start">
|
|
269
|
+
{currency.symbol}
|
|
270
|
+
</InputAdornment>
|
|
271
|
+
),
|
|
272
|
+
}
|
|
273
|
+
}}
|
|
262
274
|
/>
|
|
263
275
|
);
|
|
264
276
|
})}
|
|
265
|
-
|
|
277
|
+
|
|
266
278
|
{/* Hidden input to ensure prices gets submitted */}
|
|
267
279
|
<input
|
|
268
280
|
type="hidden"
|
|
@@ -71,7 +71,7 @@ export const TenantAttributesFormatsProvider: React.FC<{children: React.ReactNod
|
|
|
71
71
|
if (!LAST_FETCH_TIME) {
|
|
72
72
|
try {
|
|
73
73
|
// Try to get last fetch time from IndexedDB
|
|
74
|
-
LAST_FETCH_TIME = await idbGet("tenant_attributes_cache") || 0;
|
|
74
|
+
LAST_FETCH_TIME = (await idbGet("tenant_attributes_cache")) || 0;
|
|
75
75
|
} catch (error) {
|
|
76
76
|
console.error("Error reading from IndexedDB:", error);
|
|
77
77
|
}
|
|
@@ -77,9 +77,8 @@ const TenantSelector = React.forwardRef<
|
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
return (
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
<Autocomplete
|
|
80
|
+
<>Cliente impersonado: {selectedTenantInput}
|
|
81
|
+
<Autocomplete
|
|
83
82
|
fullWidth
|
|
84
83
|
loading={isLoading && open}
|
|
85
84
|
sx={{ width: 300 }}
|
|
@@ -117,23 +116,27 @@ const TenantSelector = React.forwardRef<
|
|
|
117
116
|
handleSearch(ev.target.value);
|
|
118
117
|
}
|
|
119
118
|
}}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
119
|
+
slotProps={{
|
|
120
|
+
...params.slotProps,
|
|
121
|
+
|
|
122
|
+
input: {
|
|
123
|
+
...params.slotProps.input,
|
|
124
|
+
autoComplete: 'new-password',
|
|
125
|
+
endAdornment: (
|
|
126
|
+
<>
|
|
127
|
+
{isLoading ? (
|
|
128
|
+
<CircularProgress color='inherit' size={20} />
|
|
129
|
+
) : null}
|
|
130
|
+
{params.slotProps.input.endAdornment}
|
|
131
|
+
</>
|
|
132
|
+
),
|
|
133
|
+
}
|
|
134
|
+
}}
|
|
132
135
|
/>
|
|
133
136
|
)}
|
|
134
137
|
/>
|
|
135
|
-
|
|
136
|
-
|
|
138
|
+
</>
|
|
139
|
+
);
|
|
137
140
|
});
|
|
138
141
|
|
|
139
142
|
export default TenantSelector;
|
|
@@ -71,7 +71,7 @@ export const TenantSettingsFormatsProvider: React.FC<{children: React.ReactNode}
|
|
|
71
71
|
if (!LAST_FETCH_TIME) {
|
|
72
72
|
try {
|
|
73
73
|
// Try to get last fetch time from IndexedDB
|
|
74
|
-
LAST_FETCH_TIME = await idbGet("tenant_settings_cache") || 0;
|
|
74
|
+
LAST_FETCH_TIME = (await idbGet("tenant_settings_cache")) || 0;
|
|
75
75
|
} catch (error) {
|
|
76
76
|
console.error("Error reading from IndexedDB:", error);
|
|
77
77
|
}
|
|
@@ -332,7 +332,9 @@ const UserPreferences: React.FC = () => {
|
|
|
332
332
|
<Box>
|
|
333
333
|
<Typography variant="subtitle1">{format.label}</Typography>
|
|
334
334
|
{format.description && (
|
|
335
|
-
<Typography variant="caption"
|
|
335
|
+
<Typography variant="caption" sx={{
|
|
336
|
+
color: "text.secondary"
|
|
337
|
+
}}>
|
|
336
338
|
{format.description}
|
|
337
339
|
</Typography>
|
|
338
340
|
)}
|
|
@@ -352,7 +354,13 @@ const UserPreferences: React.FC = () => {
|
|
|
352
354
|
<CardContent>
|
|
353
355
|
<Typography variant="subtitle1" gutterBottom>{format.label}</Typography>
|
|
354
356
|
{format.description && (
|
|
355
|
-
<Typography
|
|
357
|
+
<Typography
|
|
358
|
+
variant="caption"
|
|
359
|
+
sx={{
|
|
360
|
+
color: "text.secondary",
|
|
361
|
+
display: "block",
|
|
362
|
+
mb: 2
|
|
363
|
+
}}>
|
|
356
364
|
{format.description}
|
|
357
365
|
</Typography>
|
|
358
366
|
)}
|
|
@@ -371,12 +379,14 @@ const UserPreferences: React.FC = () => {
|
|
|
371
379
|
value={value ?? format.default_value ?? 0}
|
|
372
380
|
onChange={(e) => handleGenericPreferenceChange(format.id, parseInt(e.target.value, 10))}
|
|
373
381
|
disabled={saving || !format.editable}
|
|
374
|
-
inputProps={{
|
|
375
|
-
min: format.min ?? 0,
|
|
376
|
-
max: format.max ?? 100,
|
|
377
|
-
}}
|
|
378
382
|
sx={{ width: 80 }}
|
|
379
383
|
size="small"
|
|
384
|
+
slotProps={{
|
|
385
|
+
htmlInput: {
|
|
386
|
+
min: format.min ?? 0,
|
|
387
|
+
max: format.max ?? 100,
|
|
388
|
+
}
|
|
389
|
+
}}
|
|
380
390
|
/>
|
|
381
391
|
</Box>
|
|
382
392
|
</CardContent>
|
|
@@ -389,7 +399,13 @@ const UserPreferences: React.FC = () => {
|
|
|
389
399
|
<CardContent>
|
|
390
400
|
<Typography variant="subtitle1" gutterBottom>{format.label}</Typography>
|
|
391
401
|
{format.description && (
|
|
392
|
-
<Typography
|
|
402
|
+
<Typography
|
|
403
|
+
variant="caption"
|
|
404
|
+
sx={{
|
|
405
|
+
color: "text.secondary",
|
|
406
|
+
display: "block",
|
|
407
|
+
mb: 2
|
|
408
|
+
}}>
|
|
393
409
|
{format.description}
|
|
394
410
|
</Typography>
|
|
395
411
|
)}
|
|
@@ -398,15 +414,17 @@ const UserPreferences: React.FC = () => {
|
|
|
398
414
|
value={value ?? ''}
|
|
399
415
|
onChange={(e) => handleGenericPreferenceChange(format.id, e.target.value)}
|
|
400
416
|
disabled={saving || !format.editable}
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
417
|
+
slotProps={{
|
|
418
|
+
input: format.maxLength ? {
|
|
419
|
+
endAdornment: (
|
|
420
|
+
<InputAdornment position="end">
|
|
421
|
+
{(value?.length || 0)}/{format.maxLength}
|
|
422
|
+
</InputAdornment>
|
|
423
|
+
),
|
|
424
|
+
} : undefined,
|
|
425
|
+
|
|
426
|
+
htmlInput: { maxLength: format.maxLength }
|
|
427
|
+
}} />
|
|
410
428
|
</CardContent>
|
|
411
429
|
</Card>
|
|
412
430
|
);
|
|
@@ -417,7 +435,13 @@ const UserPreferences: React.FC = () => {
|
|
|
417
435
|
<CardContent>
|
|
418
436
|
<Typography variant="subtitle1" gutterBottom>{format.label}</Typography>
|
|
419
437
|
{format.description && (
|
|
420
|
-
<Typography
|
|
438
|
+
<Typography
|
|
439
|
+
variant="caption"
|
|
440
|
+
sx={{
|
|
441
|
+
color: "text.secondary",
|
|
442
|
+
display: "block",
|
|
443
|
+
mb: 2
|
|
444
|
+
}}>
|
|
421
445
|
{format.description}
|
|
422
446
|
</Typography>
|
|
423
447
|
)}
|
|
@@ -428,8 +452,10 @@ const UserPreferences: React.FC = () => {
|
|
|
428
452
|
value={value ?? ''}
|
|
429
453
|
onChange={(e) => handleGenericPreferenceChange(format.id, e.target.value)}
|
|
430
454
|
disabled={saving || !format.editable}
|
|
431
|
-
inputProps={{ maxLength: format.maxLength }}
|
|
432
455
|
helperText={format.maxLength ? `${(value?.length || 0)}/${format.maxLength} characters` : undefined}
|
|
456
|
+
slotProps={{
|
|
457
|
+
htmlInput: { maxLength: format.maxLength }
|
|
458
|
+
}}
|
|
433
459
|
/>
|
|
434
460
|
</CardContent>
|
|
435
461
|
</Card>
|
|
@@ -462,7 +488,9 @@ const UserPreferences: React.FC = () => {
|
|
|
462
488
|
<Typography variant="subtitle1">
|
|
463
489
|
{formatNotificationName(pref.name)}
|
|
464
490
|
</Typography>
|
|
465
|
-
<Typography variant="caption"
|
|
491
|
+
<Typography variant="caption" sx={{
|
|
492
|
+
color: "text.secondary"
|
|
493
|
+
}}>
|
|
466
494
|
{pref.name}
|
|
467
495
|
</Typography>
|
|
468
496
|
</Box>
|
|
@@ -497,7 +525,9 @@ const UserPreferences: React.FC = () => {
|
|
|
497
525
|
)}
|
|
498
526
|
|
|
499
527
|
{!config?.hasEmail && !config?.hasPush && (
|
|
500
|
-
<Typography variant="caption"
|
|
528
|
+
<Typography variant="caption" sx={{
|
|
529
|
+
color: "text.secondary"
|
|
530
|
+
}}>
|
|
501
531
|
(No configurable channels)
|
|
502
532
|
</Typography>
|
|
503
533
|
)}
|
|
@@ -518,7 +548,12 @@ const UserPreferences: React.FC = () => {
|
|
|
518
548
|
return (
|
|
519
549
|
<Box sx={{ pt: 2 }}>
|
|
520
550
|
{groupConfig?.description && (
|
|
521
|
-
<Typography
|
|
551
|
+
<Typography
|
|
552
|
+
variant="body2"
|
|
553
|
+
sx={{
|
|
554
|
+
color: "text.secondary",
|
|
555
|
+
mb: 3
|
|
556
|
+
}}>
|
|
522
557
|
{groupConfig.description}
|
|
523
558
|
</Typography>
|
|
524
559
|
)}
|
|
@@ -101,7 +101,7 @@ export const SystemRequestsCacheProvider: React.FC<SystemRequestsCacheProviderPr
|
|
|
101
101
|
const now = Date.now();
|
|
102
102
|
if (!GLOBALS.current.lastFetchTime) {
|
|
103
103
|
try {
|
|
104
|
-
GLOBALS.current.lastFetchTime = await idbGet(cacheKey) || 0;
|
|
104
|
+
GLOBALS.current.lastFetchTime = (await idbGet(cacheKey)) || 0;
|
|
105
105
|
if (DEBUG_SYSTEM_REQUESTS_CACHE) {
|
|
106
106
|
console.log(`[SystemRequestsCache] Loaded lastFetchTime from IndexedDB: ${GLOBALS.current.lastFetchTime}`);
|
|
107
107
|
}
|
|
@@ -51,9 +51,9 @@ interface DashThemeProviderProps {
|
|
|
51
51
|
|
|
52
52
|
export const DashThemeProvider: React.FC<DashThemeProviderProps> = ({ extendedOptions, children }) => {
|
|
53
53
|
// Track current theme mode from data-theme attribute
|
|
54
|
-
const [currentMode, setCurrentMode] = useState<string>(() =>
|
|
55
|
-
document.documentElement.getAttribute('data-theme') || 'dark'
|
|
56
|
-
);
|
|
54
|
+
const [currentMode, setCurrentMode] = useState<string>(() => {
|
|
55
|
+
return document.documentElement.getAttribute('data-theme') || 'dark';
|
|
56
|
+
});
|
|
57
57
|
|
|
58
58
|
const [themeOptions, setThemeOptions] = useState<ReturnType<typeof appTheme>>(() => {
|
|
59
59
|
// Read persisted tenant settings on initialization to include tenant colors
|
|
@@ -97,8 +97,6 @@ export const DashThemeProvider: React.FC<DashThemeProviderProps> = ({ extendedOp
|
|
|
97
97
|
//const themeMode = mode || currentMode;
|
|
98
98
|
const themeMode = mode || document.documentElement.getAttribute('data-theme') || 'dark';
|
|
99
99
|
|
|
100
|
-
console.log('Recreating MUI theme with tenant settings:', settings, 'mode:', themeMode);
|
|
101
|
-
|
|
102
100
|
const newThemeOptions = appTheme(
|
|
103
101
|
extendedOptions,
|
|
104
102
|
{
|
|
@@ -112,14 +110,14 @@ export const DashThemeProvider: React.FC<DashThemeProviderProps> = ({ extendedOp
|
|
|
112
110
|
|
|
113
111
|
setThemeOptions(newThemeOptions);
|
|
114
112
|
setTheme(newTheme);
|
|
115
|
-
|
|
113
|
+
|
|
116
114
|
|
|
117
115
|
setAntTheme(getAntTheme({
|
|
118
116
|
tenantSettings: settings,
|
|
119
117
|
colors: settings?.colors,
|
|
120
118
|
currentMode: themeMode,
|
|
121
119
|
}));
|
|
122
|
-
|
|
120
|
+
|
|
123
121
|
updateDomCssVariables(themeMode, settings?.colors, settings?.values);
|
|
124
122
|
/*if (settings?.colors || settings?.values) {
|
|
125
123
|
updateDomCssVariables(themeMode, settings?.colors, settings?.values);
|
|
@@ -133,12 +131,8 @@ export const DashThemeProvider: React.FC<DashThemeProviderProps> = ({ extendedOp
|
|
|
133
131
|
if (mutation.type === 'attributes' && mutation.attributeName === 'data-theme') {
|
|
134
132
|
const newMode = document.documentElement.getAttribute('data-theme') || 'dark';
|
|
135
133
|
if (newMode !== currentMode) {
|
|
136
|
-
console.log('Theme mode changed from', currentMode, 'to', newMode);
|
|
137
134
|
setCurrentMode(newMode);
|
|
138
135
|
const settings = getTenantSettings();
|
|
139
|
-
|
|
140
|
-
console.log('Updating theme with new mode:', newMode, 'and settings:', settings);
|
|
141
|
-
|
|
142
136
|
updateDomCssVariables(newMode, settings?.colors, settings?.values);
|
|
143
137
|
}
|
|
144
138
|
}
|
|
@@ -157,7 +151,6 @@ export const DashThemeProvider: React.FC<DashThemeProviderProps> = ({ extendedOp
|
|
|
157
151
|
|
|
158
152
|
// React to mode changes
|
|
159
153
|
useEffect(() => {
|
|
160
|
-
console.log('Current mode updated to:', currentMode);
|
|
161
154
|
const tenantSettings = getTenantSettings();
|
|
162
155
|
recreateTheme(tenantSettings, currentMode);
|
|
163
156
|
}, [currentMode]);
|
|
@@ -165,9 +158,7 @@ export const DashThemeProvider: React.FC<DashThemeProviderProps> = ({ extendedOp
|
|
|
165
158
|
// Initial setup
|
|
166
159
|
useEffect(() => {
|
|
167
160
|
const tenantSettings = getTenantSettings();
|
|
168
|
-
|
|
169
161
|
if (tenantSettings) {
|
|
170
|
-
console.log("Recreating MUI theme on mount");
|
|
171
162
|
recreateTheme(tenantSettings, currentMode);
|
|
172
163
|
}
|
|
173
164
|
}, []);
|
|
@@ -231,7 +231,7 @@ const CollapsableSidebarMenu = ({
|
|
|
231
231
|
// onClick above does closest('.expand-icon') to tell "clicked the arrow"
|
|
232
232
|
// from "clicked the row" — if only the svg had it, clicking the circle's
|
|
233
233
|
// padding (outside the svg's own box) would miss the check and navigate.
|
|
234
|
-
<div className="expand-icon expand-icon-wrapper" onClick={handleExpandClick}>
|
|
234
|
+
(<div className="expand-icon expand-icon-wrapper" onClick={handleExpandClick}>
|
|
235
235
|
{/* For bottom position, invert icons since submenu opens upward */}
|
|
236
236
|
{sidebarPosition === "bottom" ? (
|
|
237
237
|
localOpen ?
|
|
@@ -242,11 +242,11 @@ const CollapsableSidebarMenu = ({
|
|
|
242
242
|
<ExpandLessOutlinedIcon className='expand-icon less' /> :
|
|
243
243
|
<ExpandMoreOutlinedIcon className='expand-icon more' />
|
|
244
244
|
)}
|
|
245
|
-
</div>
|
|
245
|
+
</div>)
|
|
246
246
|
)}
|
|
247
247
|
</ListItemButton>
|
|
248
248
|
</div>
|
|
249
|
-
|
|
249
|
+
|
|
250
250
|
{/* Portal submenu for all positions */}
|
|
251
251
|
{/* Vertical mode (Left/Right) - Inline Expansion using Collapse */}
|
|
252
252
|
{!isHorizontal && (
|
|
@@ -62,20 +62,20 @@ const SidebarActions: React.FC<SidebarActionsProps> = ({
|
|
|
62
62
|
),
|
|
63
63
|
}}
|
|
64
64
|
>
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
65
|
+
{authContext?.authenticated && authContext.user?.id !== 'guest' && (
|
|
66
|
+
<AvatarComponent sidebarPosition={sidebarPosition} />
|
|
67
|
+
)}
|
|
68
68
|
|
|
69
69
|
{HeaderToolBar && headerToolBarReplace ? (
|
|
70
70
|
// Replace mode: Only render the custom HeaderToolBar
|
|
71
|
-
<HeaderToolBar />
|
|
71
|
+
(<HeaderToolBar />)
|
|
72
72
|
) : (
|
|
73
73
|
// Default mode: Render all actions
|
|
74
|
-
<>
|
|
74
|
+
(<>
|
|
75
75
|
{HeaderToolBar && <HeaderToolBar />}
|
|
76
76
|
{authContext?.authenticated ? <BridgedLocalesMenuButton /> : <LangSwitcher />}
|
|
77
77
|
<DarkToggleMode />
|
|
78
|
-
</>
|
|
78
|
+
</>)
|
|
79
79
|
)}
|
|
80
80
|
</Box>
|
|
81
81
|
);
|
|
@@ -403,13 +403,14 @@ const DASHLightWeightLogin: React.FC<DASHLightWeightLoginProps> = (props) => {
|
|
|
403
403
|
|
|
404
404
|
>
|
|
405
405
|
<Container maxWidth="sm" sx={{ p: 1 }}>
|
|
406
|
-
<Box
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
406
|
+
<Box
|
|
407
|
+
sx={{
|
|
408
|
+
display: "flex",
|
|
409
|
+
justifyContent: "center",
|
|
410
|
+
alignItems: "center",
|
|
411
|
+
minHeight: "50vh",
|
|
412
|
+
textAlign: "center"
|
|
413
|
+
}}>
|
|
413
414
|
<div>Cargando...</div>
|
|
414
415
|
</Box>
|
|
415
416
|
</Container>
|