@hed-hog/core 0.0.279 → 0.0.286
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/auth/auth.controller.d.ts +3 -3
- package/dist/auth/auth.service.d.ts +8 -8
- package/dist/file/file.controller.d.ts +2 -2
- package/dist/file/file.service.d.ts +4 -4
- package/dist/role/guards/role.guard.d.ts.map +1 -1
- package/dist/role/guards/role.guard.js +1 -1
- package/dist/role/guards/role.guard.js.map +1 -1
- package/dist/session/session.controller.d.ts +1 -1
- package/dist/session/session.service.d.ts +3 -3
- package/dist/setting/setting.controller.d.ts +3 -0
- package/dist/setting/setting.controller.d.ts.map +1 -1
- package/dist/setting/setting.controller.js +10 -0
- package/dist/setting/setting.controller.js.map +1 -1
- package/dist/setting/setting.service.d.ts +2 -1
- package/dist/setting/setting.service.d.ts.map +1 -1
- package/dist/setting/setting.service.js +51 -12
- package/dist/setting/setting.service.js.map +1 -1
- package/dist/user/user.controller.d.ts +2 -2
- package/dist/user/user.service.d.ts +6 -6
- package/hedhog/data/route.yaml +8 -0
- package/hedhog/frontend/app/ai_agent/page.tsx.ejs +72 -65
- package/hedhog/frontend/app/configurations/[slug]/components/setting-field.tsx.ejs +1 -92
- package/hedhog/frontend/app/dashboard/page.tsx.ejs +2 -2
- package/hedhog/frontend/app/mail/log/page.tsx.ejs +37 -42
- package/hedhog/frontend/app/mail/template/page.tsx.ejs +176 -126
- package/hedhog/frontend/app/menu/page.tsx.ejs +45 -39
- package/hedhog/frontend/app/preferences/page.tsx.ejs +34 -121
- package/hedhog/frontend/app/roles/page.tsx.ejs +45 -46
- package/hedhog/frontend/app/users/page.tsx.ejs +71 -68
- package/hedhog/frontend/messages/en.json +7 -0
- package/hedhog/frontend/messages/pt.json +7 -0
- package/package.json +2 -2
- package/src/role/guards/role.guard.ts +9 -8
- package/src/setting/setting.controller.ts +21 -16
- package/src/setting/setting.service.ts +63 -17
|
@@ -24,6 +24,7 @@ export default function PreferencesPage() {
|
|
|
24
24
|
const {
|
|
25
25
|
currentTheme,
|
|
26
26
|
setCurrentTheme,
|
|
27
|
+
refreshUserSettings,
|
|
27
28
|
request,
|
|
28
29
|
getSettingValue,
|
|
29
30
|
setSettingValue,
|
|
@@ -32,115 +33,7 @@ export default function PreferencesPage() {
|
|
|
32
33
|
} = useApp();
|
|
33
34
|
const t = useTranslations('core.PreferencesPage');
|
|
34
35
|
|
|
35
|
-
|
|
36
|
-
themeMode?: 'light' | 'dark' | 'system'
|
|
37
|
-
) => {
|
|
38
|
-
try {
|
|
39
|
-
const response: any = await request({
|
|
40
|
-
url: '/setting/initial',
|
|
41
|
-
method: 'GET',
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
const newSettings = response.data?.setting || {};
|
|
45
|
-
localStorage.setItem('settings', JSON.stringify(newSettings));
|
|
46
|
-
|
|
47
|
-
const root = document.documentElement;
|
|
48
|
-
const effectiveTheme = themeMode || currentTheme || 'system';
|
|
49
|
-
let resolvedTheme: 'light' | 'dark' = 'light';
|
|
50
|
-
|
|
51
|
-
if (effectiveTheme === 'system') {
|
|
52
|
-
const prefersDark = window.matchMedia(
|
|
53
|
-
'(prefers-color-scheme: dark)'
|
|
54
|
-
).matches;
|
|
55
|
-
resolvedTheme = prefersDark ? 'dark' : 'light';
|
|
56
|
-
} else {
|
|
57
|
-
resolvedTheme = effectiveTheme as 'light' | 'dark';
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
root.classList.remove('light', 'dark');
|
|
61
|
-
root.classList.add(resolvedTheme);
|
|
62
|
-
|
|
63
|
-
const existingStyle = document.getElementById('theme-custom-styles');
|
|
64
|
-
if (existingStyle) {
|
|
65
|
-
existingStyle.remove();
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const styleTag = document.createElement('style');
|
|
69
|
-
styleTag.id = 'theme-custom-styles';
|
|
70
|
-
let cssRules = '';
|
|
71
|
-
|
|
72
|
-
const addRule = (varName: string, settingKey: string) => {
|
|
73
|
-
const hexColor = newSettings[settingKey];
|
|
74
|
-
if (
|
|
75
|
-
hexColor &&
|
|
76
|
-
typeof hexColor === 'string' &&
|
|
77
|
-
hexColor.startsWith('#')
|
|
78
|
-
) {
|
|
79
|
-
cssRules += ` ${varName}: ${hexColor} !important;\n`;
|
|
80
|
-
}
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
if (resolvedTheme === 'light') {
|
|
84
|
-
cssRules += '@supports (color: lab(0% 0 0)) {\n';
|
|
85
|
-
cssRules += ' html.light, .light, :root.light {\n';
|
|
86
|
-
addRule('--primary', 'theme-primary-light');
|
|
87
|
-
addRule('--bprogress-color', 'theme-primary-light');
|
|
88
|
-
addRule('--primary-foreground', 'theme-primary-foreground-light');
|
|
89
|
-
addRule('--secondary', 'theme-secondary-light');
|
|
90
|
-
addRule('--secondary-foreground', 'theme-secondary-foreground-light');
|
|
91
|
-
addRule('--accent', 'theme-accent-light');
|
|
92
|
-
addRule('--accent-foreground', 'theme-accent-foreground-light');
|
|
93
|
-
addRule('--muted', 'theme-muted-light');
|
|
94
|
-
addRule('--muted-foreground', 'theme-muted-foreground-light');
|
|
95
|
-
addRule('--background', 'theme-background-light');
|
|
96
|
-
addRule('--foreground', 'theme-background-foreground-light');
|
|
97
|
-
addRule('--card', 'theme-card-light');
|
|
98
|
-
addRule('--card-foreground', 'theme-card-foreground-light');
|
|
99
|
-
} else {
|
|
100
|
-
cssRules += '@supports (color: lab(0% 0 0)) {\n';
|
|
101
|
-
cssRules += ' html.dark, .dark, :root.dark {\n';
|
|
102
|
-
addRule('--primary', 'theme-primary-dark');
|
|
103
|
-
addRule('--bprogress-color', 'theme-primary-dark');
|
|
104
|
-
addRule('--primary-foreground', 'theme-primary-foreground-dark');
|
|
105
|
-
addRule('--secondary', 'theme-secondary-dark');
|
|
106
|
-
addRule('--secondary-foreground', 'theme-secondary-foreground-dark');
|
|
107
|
-
addRule('--accent', 'theme-accent-dark');
|
|
108
|
-
addRule('--accent-foreground', 'theme-accent-foreground-dark');
|
|
109
|
-
addRule('--muted', 'theme-muted-dark');
|
|
110
|
-
addRule('--muted-foreground', 'theme-muted-foreground-dark');
|
|
111
|
-
addRule('--background', 'theme-background-dark');
|
|
112
|
-
addRule('--foreground', 'theme-background-foreground-dark');
|
|
113
|
-
addRule('--card', 'theme-card-dark');
|
|
114
|
-
addRule('--card-foreground', 'theme-card-foreground-dark');
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
if (newSettings['theme-radius']) {
|
|
118
|
-
cssRules += ` --radius: ${newSettings['theme-radius']}rem !important;\n`;
|
|
119
|
-
}
|
|
120
|
-
if (newSettings['theme-text-size']) {
|
|
121
|
-
cssRules += ` font-size: ${newSettings['theme-text-size']}rem !important;\n`;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
cssRules += ' }\n';
|
|
125
|
-
cssRules += '}\n';
|
|
126
|
-
|
|
127
|
-
if (newSettings['theme-font']) {
|
|
128
|
-
cssRules += `:root {\n`;
|
|
129
|
-
cssRules += ` --font-sans: ${newSettings['theme-font']} !important;\n`;
|
|
130
|
-
cssRules += `}\n`;
|
|
131
|
-
cssRules += `html {\n`;
|
|
132
|
-
cssRules += ` font-family: ${newSettings['theme-font']} !important;\n`;
|
|
133
|
-
cssRules += `}\n`;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
styleTag.textContent = cssRules;
|
|
137
|
-
document.head.appendChild(styleTag);
|
|
138
|
-
} catch (error) {
|
|
139
|
-
console.error('Error applying theme settings:', error);
|
|
140
|
-
}
|
|
141
|
-
};
|
|
142
|
-
|
|
143
|
-
// Busca as settings do grupo de localization
|
|
36
|
+
// Buspnpm grupo de localization
|
|
144
37
|
const { data: localizationSettings, isLoading } = useQuery<
|
|
145
38
|
PaginatedResult<Setting>
|
|
146
39
|
>({
|
|
@@ -182,21 +75,41 @@ export default function PreferencesPage() {
|
|
|
182
75
|
});
|
|
183
76
|
|
|
184
77
|
const handleThemeChange = async (value: 'light' | 'dark' | 'system') => {
|
|
78
|
+
const previousTheme = currentTheme;
|
|
185
79
|
setCurrentTheme(value);
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
80
|
+
|
|
81
|
+
try {
|
|
82
|
+
await request({
|
|
83
|
+
url: '/profile/preferences',
|
|
84
|
+
method: 'PUT',
|
|
85
|
+
data: { theme: value },
|
|
86
|
+
});
|
|
87
|
+
await refreshUserSettings();
|
|
88
|
+
} catch (error) {
|
|
89
|
+
setCurrentTheme(previousTheme);
|
|
90
|
+
await refreshUserSettings();
|
|
91
|
+
showToastHandler(
|
|
92
|
+
'error',
|
|
93
|
+
t('themeUpdateError') || 'Failed to update theme'
|
|
94
|
+
);
|
|
95
|
+
}
|
|
192
96
|
};
|
|
193
97
|
|
|
194
|
-
const handleLanguageChange = (code: string) => {
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
98
|
+
const handleLanguageChange = async (code: string) => {
|
|
99
|
+
try {
|
|
100
|
+
await request({
|
|
101
|
+
url: '/profile/preferences',
|
|
102
|
+
method: 'PUT',
|
|
103
|
+
data: { language: code },
|
|
104
|
+
});
|
|
105
|
+
await refreshUserSettings();
|
|
106
|
+
} catch (error) {
|
|
107
|
+
showToastHandler(
|
|
108
|
+
'error',
|
|
109
|
+
t('languageUpdateError') || 'Failed to update language'
|
|
110
|
+
);
|
|
111
|
+
throw error;
|
|
112
|
+
}
|
|
200
113
|
};
|
|
201
114
|
|
|
202
115
|
const handleDateFormatChange = async (value: string) => {
|
|
@@ -1,12 +1,24 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
|
+
EmptyState,
|
|
5
|
+
Page,
|
|
4
6
|
PageHeader,
|
|
5
7
|
PaginationFooter,
|
|
6
8
|
SearchBar,
|
|
7
9
|
StatsCards,
|
|
8
10
|
} from '@/components/entity-list';
|
|
9
11
|
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';
|
|
12
|
+
import {
|
|
13
|
+
AlertDialog,
|
|
14
|
+
AlertDialogAction,
|
|
15
|
+
AlertDialogCancel,
|
|
16
|
+
AlertDialogContent,
|
|
17
|
+
AlertDialogDescription,
|
|
18
|
+
AlertDialogFooter,
|
|
19
|
+
AlertDialogHeader,
|
|
20
|
+
AlertDialogTitle,
|
|
21
|
+
} from '@/components/ui/alert-dialog';
|
|
10
22
|
import { Button } from '@/components/ui/button';
|
|
11
23
|
import {
|
|
12
24
|
Card,
|
|
@@ -15,13 +27,6 @@ import {
|
|
|
15
27
|
CardHeader,
|
|
16
28
|
CardTitle,
|
|
17
29
|
} from '@/components/ui/card';
|
|
18
|
-
import {
|
|
19
|
-
Dialog,
|
|
20
|
-
DialogContent,
|
|
21
|
-
DialogDescription,
|
|
22
|
-
DialogHeader,
|
|
23
|
-
DialogTitle,
|
|
24
|
-
} from '@/components/ui/dialog';
|
|
25
30
|
import {
|
|
26
31
|
Form,
|
|
27
32
|
FormControl,
|
|
@@ -367,7 +372,7 @@ export default function RolePage() {
|
|
|
367
372
|
};
|
|
368
373
|
|
|
369
374
|
return (
|
|
370
|
-
<
|
|
375
|
+
<Page>
|
|
371
376
|
<PageHeader
|
|
372
377
|
breadcrumbs={[{ label: 'Home', href: '/' }, { label: t('roles') }]}
|
|
373
378
|
actions={[
|
|
@@ -423,7 +428,13 @@ export default function RolePage() {
|
|
|
423
428
|
|
|
424
429
|
{!isLoading &&
|
|
425
430
|
(!rolesResponse?.data || rolesResponse.data.length === 0) ? (
|
|
426
|
-
<
|
|
431
|
+
<EmptyState
|
|
432
|
+
icon={<ShieldCheck className="h-12 w-12" />}
|
|
433
|
+
title={t('noRolesFound')}
|
|
434
|
+
description={t('description')}
|
|
435
|
+
actionLabel={t('buttonAddRole')}
|
|
436
|
+
onAction={() => setIsDialogOpen(true)}
|
|
437
|
+
/>
|
|
427
438
|
) : (
|
|
428
439
|
<div className="grid gap-4 grid-cols-1 lg:grid-cols-2 xl:grid-cols-3">
|
|
429
440
|
{(rolesResponse?.data as (Role & { role_id: number })[])?.map(
|
|
@@ -504,19 +515,18 @@ export default function RolePage() {
|
|
|
504
515
|
/>
|
|
505
516
|
</div>
|
|
506
517
|
|
|
507
|
-
<
|
|
508
|
-
<
|
|
509
|
-
<
|
|
510
|
-
<
|
|
511
|
-
<
|
|
518
|
+
<Sheet open={isDialogOpen} onOpenChange={setIsDialogOpen}>
|
|
519
|
+
<SheetContent className="w-full sm:max-w-lg overflow-y-auto gap-0">
|
|
520
|
+
<SheetHeader>
|
|
521
|
+
<SheetTitle>{t('dialogAddRoleTitle')}</SheetTitle>
|
|
522
|
+
<SheetDescription>
|
|
512
523
|
{t('dialogAddRoleDescription')}
|
|
513
|
-
</
|
|
514
|
-
</
|
|
515
|
-
<div className="w-full border-t pt-1 mt-1" />
|
|
524
|
+
</SheetDescription>
|
|
525
|
+
</SheetHeader>
|
|
516
526
|
<Form {...form}>
|
|
517
527
|
<form
|
|
518
528
|
onSubmit={form.handleSubmit(onSubmit)}
|
|
519
|
-
className="space-y-4"
|
|
529
|
+
className="space-y-4 px-4 pt-2"
|
|
520
530
|
>
|
|
521
531
|
<FormField
|
|
522
532
|
control={form.control}
|
|
@@ -586,8 +596,8 @@ export default function RolePage() {
|
|
|
586
596
|
</Button>
|
|
587
597
|
</form>
|
|
588
598
|
</Form>
|
|
589
|
-
</
|
|
590
|
-
</
|
|
599
|
+
</SheetContent>
|
|
600
|
+
</Sheet>
|
|
591
601
|
|
|
592
602
|
{editingRole && (
|
|
593
603
|
<Sheet open={!!editingRole} onOpenChange={() => setEditingRole(null)}>
|
|
@@ -783,34 +793,23 @@ export default function RolePage() {
|
|
|
783
793
|
</Sheet>
|
|
784
794
|
)}
|
|
785
795
|
|
|
786
|
-
<
|
|
787
|
-
<
|
|
788
|
-
<
|
|
789
|
-
<
|
|
790
|
-
<
|
|
796
|
+
<AlertDialog open={openDeleteModal} onOpenChange={setOpenDeleteModal}>
|
|
797
|
+
<AlertDialogContent>
|
|
798
|
+
<AlertDialogHeader>
|
|
799
|
+
<AlertDialogTitle>{t('dialogDeleteRoleTitle')}</AlertDialogTitle>
|
|
800
|
+
<AlertDialogDescription>
|
|
791
801
|
{t('dialogDeleteRoleDescription')}
|
|
792
|
-
</
|
|
793
|
-
</
|
|
794
|
-
<
|
|
795
|
-
|
|
796
|
-
<
|
|
797
|
-
type="button"
|
|
798
|
-
className="px-4 w-28 h-12 py-2 bg-gray-300 text-black hover:bg-gray-300 hover:text-black rounded-sm mr-2 text-md"
|
|
799
|
-
onClick={() => setOpenDeleteModal(false)}
|
|
800
|
-
>
|
|
801
|
-
{t('deleteRoleCancel')}
|
|
802
|
-
</Button>
|
|
803
|
-
<Button
|
|
804
|
-
onClick={onDelete}
|
|
805
|
-
variant="destructive"
|
|
806
|
-
className="px-4 w-32 h-12 py-2 text-white hover:text-white rounded-sm text-md cursor-pointer"
|
|
807
|
-
>
|
|
802
|
+
</AlertDialogDescription>
|
|
803
|
+
</AlertDialogHeader>
|
|
804
|
+
<AlertDialogFooter>
|
|
805
|
+
<AlertDialogCancel>{t('deleteRoleCancel')}</AlertDialogCancel>
|
|
806
|
+
<AlertDialogAction onClick={onDelete}>
|
|
808
807
|
{t('deleteRoleConfirm')}
|
|
809
|
-
</
|
|
810
|
-
</
|
|
811
|
-
</
|
|
812
|
-
</
|
|
808
|
+
</AlertDialogAction>
|
|
809
|
+
</AlertDialogFooter>
|
|
810
|
+
</AlertDialogContent>
|
|
811
|
+
</AlertDialog>
|
|
813
812
|
</div>
|
|
814
|
-
</
|
|
813
|
+
</Page>
|
|
815
814
|
);
|
|
816
815
|
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
|
+
EmptyState,
|
|
5
|
+
Page,
|
|
4
6
|
PageHeader,
|
|
5
7
|
PaginationFooter,
|
|
6
8
|
SearchBar,
|
|
@@ -25,13 +27,6 @@ import {
|
|
|
25
27
|
CardHeader,
|
|
26
28
|
CardTitle,
|
|
27
29
|
} from '@/components/ui/card';
|
|
28
|
-
import {
|
|
29
|
-
Dialog,
|
|
30
|
-
DialogContent,
|
|
31
|
-
DialogDescription,
|
|
32
|
-
DialogHeader,
|
|
33
|
-
DialogTitle,
|
|
34
|
-
} from '@/components/ui/dialog';
|
|
35
30
|
import {
|
|
36
31
|
Form,
|
|
37
32
|
FormControl,
|
|
@@ -220,16 +215,22 @@ export default function UserPage() {
|
|
|
220
215
|
const chars: string[] = [];
|
|
221
216
|
|
|
222
217
|
groups.forEach((group, index) => {
|
|
223
|
-
|
|
218
|
+
const randomValue = randomValues[index] ?? 0;
|
|
219
|
+
chars.push(group.charAt(randomValue % group.length));
|
|
224
220
|
});
|
|
225
221
|
|
|
226
222
|
for (let i = groups.length; i < randomValues.length; i++) {
|
|
227
|
-
|
|
223
|
+
const randomValue = randomValues[i] ?? 0;
|
|
224
|
+
chars.push(allChars.charAt(randomValue % allChars.length));
|
|
228
225
|
}
|
|
229
226
|
|
|
230
227
|
for (let i = chars.length - 1; i > 0; i--) {
|
|
231
|
-
const
|
|
232
|
-
|
|
228
|
+
const randomValue = randomValues[i] ?? 0;
|
|
229
|
+
const j = randomValue % (i + 1);
|
|
230
|
+
const currentChar = chars[i]!;
|
|
231
|
+
const swapChar = chars[j]!;
|
|
232
|
+
chars[i] = swapChar;
|
|
233
|
+
chars[j] = currentChar;
|
|
233
234
|
}
|
|
234
235
|
|
|
235
236
|
return chars.slice(0, length).join('');
|
|
@@ -422,7 +423,7 @@ export default function UserPage() {
|
|
|
422
423
|
];
|
|
423
424
|
|
|
424
425
|
return (
|
|
425
|
-
<
|
|
426
|
+
<Page>
|
|
426
427
|
<PageHeader
|
|
427
428
|
breadcrumbs={[{ label: 'Home', href: '/' }, { label: t('users') }]}
|
|
428
429
|
actions={[
|
|
@@ -487,10 +488,9 @@ export default function UserPage() {
|
|
|
487
488
|
{ label: t('filterOptionBlocked'), value: 'blocked' },
|
|
488
489
|
],
|
|
489
490
|
}}
|
|
490
|
-
className="mt-4"
|
|
491
491
|
/>
|
|
492
492
|
|
|
493
|
-
<div className="flex-1
|
|
493
|
+
<div className="flex-1 ">
|
|
494
494
|
{isLoading && (
|
|
495
495
|
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
|
496
496
|
{Array.from({ length: 3 }).map((_, i) => (
|
|
@@ -522,7 +522,13 @@ export default function UserPage() {
|
|
|
522
522
|
)}
|
|
523
523
|
|
|
524
524
|
{(paginate?.data?.length || 0) === 0 ? (
|
|
525
|
-
<
|
|
525
|
+
<EmptyState
|
|
526
|
+
icon={<Users className="h-12 w-12" />}
|
|
527
|
+
title={t('noUsersFound')}
|
|
528
|
+
description={t('description')}
|
|
529
|
+
actionLabel={t('buttonAddUser')}
|
|
530
|
+
onAction={() => setIsDialogOpen(true)}
|
|
531
|
+
/>
|
|
526
532
|
) : (
|
|
527
533
|
<div className="grid gap-4 grid-cols-1 lg:grid-cols-2 xl:grid-cols-3">
|
|
528
534
|
{paginate?.data?.map((user: User) => (
|
|
@@ -1157,36 +1163,29 @@ export default function UserPage() {
|
|
|
1157
1163
|
</Button>
|
|
1158
1164
|
</div>
|
|
1159
1165
|
|
|
1160
|
-
<
|
|
1166
|
+
<AlertDialog
|
|
1161
1167
|
open={openDeleteModal}
|
|
1162
1168
|
onOpenChange={setOpenDeleteModal}
|
|
1163
1169
|
>
|
|
1164
|
-
<
|
|
1165
|
-
<
|
|
1166
|
-
<
|
|
1167
|
-
|
|
1170
|
+
<AlertDialogContent>
|
|
1171
|
+
<AlertDialogHeader>
|
|
1172
|
+
<AlertDialogTitle>
|
|
1173
|
+
{t('dialogDeleteUserTitle')}
|
|
1174
|
+
</AlertDialogTitle>
|
|
1175
|
+
<AlertDialogDescription>
|
|
1168
1176
|
{t('dialogDeleteUserDescription')}
|
|
1169
|
-
</
|
|
1170
|
-
</
|
|
1171
|
-
<
|
|
1172
|
-
|
|
1173
|
-
<Button
|
|
1174
|
-
type="button"
|
|
1175
|
-
className="px-4 w-28 h-12 py-2 bg-gray-300 text-black hover:bg-gray-300 hover:text-black rounded-sm mr-2 text-md"
|
|
1176
|
-
onClick={() => setOpenDeleteModal(false)}
|
|
1177
|
-
>
|
|
1177
|
+
</AlertDialogDescription>
|
|
1178
|
+
</AlertDialogHeader>
|
|
1179
|
+
<AlertDialogFooter>
|
|
1180
|
+
<AlertDialogCancel>
|
|
1178
1181
|
{t('deleteUserCancel')}
|
|
1179
|
-
</
|
|
1180
|
-
<
|
|
1181
|
-
onClick={onDelete}
|
|
1182
|
-
variant="destructive"
|
|
1183
|
-
className="px-4 w-32 h-12 py-2 text-white hover:text-white rounded-sm text-md cursor-pointer"
|
|
1184
|
-
>
|
|
1182
|
+
</AlertDialogCancel>
|
|
1183
|
+
<AlertDialogAction onClick={onDelete}>
|
|
1185
1184
|
{t('deleteUserConfirm')}
|
|
1186
|
-
</
|
|
1187
|
-
</
|
|
1188
|
-
</
|
|
1189
|
-
</
|
|
1185
|
+
</AlertDialogAction>
|
|
1186
|
+
</AlertDialogFooter>
|
|
1187
|
+
</AlertDialogContent>
|
|
1188
|
+
</AlertDialog>
|
|
1190
1189
|
</TabsContent>
|
|
1191
1190
|
|
|
1192
1191
|
<TabsContent value="edit" className="space-y-4 mt-4 p-4 pt-0">
|
|
@@ -1232,27 +1231,29 @@ export default function UserPage() {
|
|
|
1232
1231
|
value="credentials"
|
|
1233
1232
|
className="space-y-4 mt-4 p-4 pt-0"
|
|
1234
1233
|
>
|
|
1235
|
-
<
|
|
1236
|
-
<
|
|
1237
|
-
<
|
|
1234
|
+
<div className="space-y-3 rounded-lg border p-4">
|
|
1235
|
+
<div>
|
|
1236
|
+
<h4 className="text-sm font-semibold">
|
|
1238
1237
|
{t('passwordResetTitle')}
|
|
1239
|
-
</
|
|
1240
|
-
<
|
|
1238
|
+
</h4>
|
|
1239
|
+
<p className="text-xs text-muted-foreground mt-1">
|
|
1241
1240
|
{t('passwordResetDescription')}
|
|
1242
|
-
</
|
|
1243
|
-
</
|
|
1244
|
-
<
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
<
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1241
|
+
</p>
|
|
1242
|
+
</div>
|
|
1243
|
+
<p className="text-xs text-muted-foreground">
|
|
1244
|
+
{t('passwordResetNotice')}
|
|
1245
|
+
</p>
|
|
1246
|
+
<div className="flex flex-col gap-2">
|
|
1247
|
+
<Button
|
|
1248
|
+
type="button"
|
|
1249
|
+
onClick={openResetPasswordDialog}
|
|
1250
|
+
className="w-full sm:w-fit"
|
|
1251
|
+
>
|
|
1252
|
+
<RefreshCcw className="h-4 w-4 mr-2" />
|
|
1253
|
+
{t('buttonResetPassword')}
|
|
1254
|
+
</Button>
|
|
1255
|
+
</div>
|
|
1256
|
+
</div>
|
|
1256
1257
|
|
|
1257
1258
|
<div className="space-y-3">
|
|
1258
1259
|
<h4 className="text-sm font-medium">
|
|
@@ -1422,7 +1423,7 @@ export default function UserPage() {
|
|
|
1422
1423
|
</AlertDialogContent>
|
|
1423
1424
|
</AlertDialog>
|
|
1424
1425
|
|
|
1425
|
-
<
|
|
1426
|
+
<AlertDialog
|
|
1426
1427
|
open={isResetResultDialogOpen}
|
|
1427
1428
|
onOpenChange={(open) => {
|
|
1428
1429
|
setIsResetResultDialogOpen(open);
|
|
@@ -1432,13 +1433,15 @@ export default function UserPage() {
|
|
|
1432
1433
|
}
|
|
1433
1434
|
}}
|
|
1434
1435
|
>
|
|
1435
|
-
<
|
|
1436
|
-
<
|
|
1437
|
-
<
|
|
1438
|
-
|
|
1436
|
+
<AlertDialogContent>
|
|
1437
|
+
<AlertDialogHeader>
|
|
1438
|
+
<AlertDialogTitle>
|
|
1439
|
+
{t('passwordResultTitle')}
|
|
1440
|
+
</AlertDialogTitle>
|
|
1441
|
+
<AlertDialogDescription>
|
|
1439
1442
|
{t('passwordResultDescription')}
|
|
1440
|
-
</
|
|
1441
|
-
</
|
|
1443
|
+
</AlertDialogDescription>
|
|
1444
|
+
</AlertDialogHeader>
|
|
1442
1445
|
|
|
1443
1446
|
<div className="space-y-3">
|
|
1444
1447
|
<div className="relative">
|
|
@@ -1484,8 +1487,8 @@ export default function UserPage() {
|
|
|
1484
1487
|
</Button>
|
|
1485
1488
|
</div>
|
|
1486
1489
|
</div>
|
|
1487
|
-
</
|
|
1488
|
-
</
|
|
1490
|
+
</AlertDialogContent>
|
|
1491
|
+
</AlertDialog>
|
|
1489
1492
|
</TabsContent>
|
|
1490
1493
|
|
|
1491
1494
|
<TabsContent
|
|
@@ -1573,6 +1576,6 @@ export default function UserPage() {
|
|
|
1573
1576
|
</Sheet>
|
|
1574
1577
|
)}
|
|
1575
1578
|
</div>
|
|
1576
|
-
</
|
|
1579
|
+
</Page>
|
|
1577
1580
|
);
|
|
1578
1581
|
}
|
|
@@ -104,6 +104,8 @@
|
|
|
104
104
|
"localization": "Localization",
|
|
105
105
|
"language": "Language",
|
|
106
106
|
"setPreferredLanguage": "Set your preferred language",
|
|
107
|
+
"themeUpdateError": "Failed to update theme",
|
|
108
|
+
"languageUpdateError": "Failed to update language",
|
|
107
109
|
"dateFormat": "Date Format",
|
|
108
110
|
"dateAndTimeFormat": "Date and Time Format",
|
|
109
111
|
"setPreferredDateFormat": "Set your preferred date format",
|
|
@@ -329,6 +331,9 @@
|
|
|
329
331
|
"newTemplate": "New Template",
|
|
330
332
|
"title": "Email Templates",
|
|
331
333
|
"description": "Manage your email templates",
|
|
334
|
+
"searchPlaceholder": "Search templates by slug or subject...",
|
|
335
|
+
"noTemplatesFound": "No templates found",
|
|
336
|
+
"noTemplatesHint": "Create your first template to start sending emails.",
|
|
332
337
|
"tableSlug": "Slug",
|
|
333
338
|
"tableSubject": "Subject",
|
|
334
339
|
"tableVariables": "Variables",
|
|
@@ -849,6 +854,8 @@
|
|
|
849
854
|
"noLogsFound": "No email logs found",
|
|
850
855
|
"adjustSearch": "Try adjusting your search terms",
|
|
851
856
|
"noEmailsSent": "No emails have been sent yet",
|
|
857
|
+
"clearSearch": "Clear search",
|
|
858
|
+
"refreshList": "Refresh list",
|
|
852
859
|
"viewDetails": "View Details",
|
|
853
860
|
"emailDetails": "Email Details",
|
|
854
861
|
"detailsDescription": "Complete information about the sent email",
|
|
@@ -104,6 +104,8 @@
|
|
|
104
104
|
"localization": "Localização",
|
|
105
105
|
"language": "Idioma",
|
|
106
106
|
"setPreferredLanguage": "Defina seu idioma preferido",
|
|
107
|
+
"themeUpdateError": "Falha ao atualizar o tema",
|
|
108
|
+
"languageUpdateError": "Falha ao atualizar o idioma",
|
|
107
109
|
"dateFormat": "Formato de Data",
|
|
108
110
|
"dateAndTimeFormat": "Formato de Data e Hora",
|
|
109
111
|
"setPreferredDateFormat": "Defina seu formato de data preferido",
|
|
@@ -329,6 +331,9 @@
|
|
|
329
331
|
"newTemplate": "Novo Template",
|
|
330
332
|
"title": "Templates de E-mail",
|
|
331
333
|
"description": "Gerencie seus templates de e-mail",
|
|
334
|
+
"searchPlaceholder": "Buscar templates por slug ou assunto...",
|
|
335
|
+
"noTemplatesFound": "Nenhum template encontrado",
|
|
336
|
+
"noTemplatesHint": "Crie o primeiro template para começar a enviar e-mails.",
|
|
332
337
|
"tableSlug": "Slug",
|
|
333
338
|
"tableSubject": "Assunto",
|
|
334
339
|
"tableVariables": "Variáveis",
|
|
@@ -852,6 +857,8 @@
|
|
|
852
857
|
"noLogsFound": "Nenhum log de e-mail encontrado",
|
|
853
858
|
"adjustSearch": "Tente ajustar seus termos de busca",
|
|
854
859
|
"noEmailsSent": "Nenhum e-mail foi enviado ainda",
|
|
860
|
+
"clearSearch": "Limpar busca",
|
|
861
|
+
"refreshList": "Atualizar lista",
|
|
855
862
|
"viewDetails": "Ver Detalhes",
|
|
856
863
|
"emailDetails": "Detalhes do E-mail",
|
|
857
864
|
"detailsDescription": "Informações completas sobre o e-mail enviado",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hed-hog/core",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.286",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"dependencies": {
|
|
@@ -32,9 +32,9 @@
|
|
|
32
32
|
"uuid": "^11.1.0",
|
|
33
33
|
"@hed-hog/api-pagination": "0.0.6",
|
|
34
34
|
"@hed-hog/api-types": "0.0.1",
|
|
35
|
+
"@hed-hog/api-prisma": "0.0.5",
|
|
35
36
|
"@hed-hog/api-locale": "0.0.13",
|
|
36
37
|
"@hed-hog/api-mail": "0.0.8",
|
|
37
|
-
"@hed-hog/api-prisma": "0.0.5",
|
|
38
38
|
"@hed-hog/api": "0.0.4"
|
|
39
39
|
},
|
|
40
40
|
"exports": {
|
|
@@ -2,13 +2,14 @@ import { IS_PUBLIC_KEY, WITH_ROLE } from '@hed-hog/api';
|
|
|
2
2
|
import { getLocaleText } from '@hed-hog/api-locale';
|
|
3
3
|
import { PrismaService } from '@hed-hog/api-prisma';
|
|
4
4
|
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
5
|
+
CanActivate,
|
|
6
|
+
ExecutionContext,
|
|
7
|
+
ForbiddenException,
|
|
8
|
+
forwardRef,
|
|
9
|
+
Inject,
|
|
10
|
+
Injectable,
|
|
11
|
+
RequestMethod,
|
|
12
|
+
UnauthorizedException,
|
|
12
13
|
} from '@nestjs/common';
|
|
13
14
|
import { METHOD_METADATA } from '@nestjs/common/constants';
|
|
14
15
|
import { Reflector } from '@nestjs/core';
|
|
@@ -130,7 +131,7 @@ export class RoleGuard implements CanActivate {
|
|
|
130
131
|
.replace('{{method}}', httpMethod)
|
|
131
132
|
.replace('{{path}}', fullPath);
|
|
132
133
|
|
|
133
|
-
throw new
|
|
134
|
+
throw new ForbiddenException(message);
|
|
134
135
|
}
|
|
135
136
|
|
|
136
137
|
const hasPendingPasswordReset = await this.prisma.user_credential.findFirst({
|