@hed-hog/core 0.0.297 → 0.0.298
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 +10 -10
- package/dist/auth/auth.service.d.ts +10 -10
- package/dist/dashboard/dashboard-core/dashboard-core.controller.d.ts +14 -0
- package/dist/dashboard/dashboard-core/dashboard-core.controller.d.ts.map +1 -1
- package/dist/dashboard/dashboard-core/dashboard-core.controller.js +9 -0
- package/dist/dashboard/dashboard-core/dashboard-core.controller.js.map +1 -1
- package/dist/dashboard/dashboard-core/dashboard-core.module.d.ts.map +1 -1
- package/dist/dashboard/dashboard-core/dashboard-core.module.js +6 -1
- package/dist/dashboard/dashboard-core/dashboard-core.module.js.map +1 -1
- package/dist/dashboard/dashboard-core/dashboard-core.service.d.ts +173 -1
- package/dist/dashboard/dashboard-core/dashboard-core.service.d.ts.map +1 -1
- package/dist/dashboard/dashboard-core/dashboard-core.service.js +531 -5
- package/dist/dashboard/dashboard-core/dashboard-core.service.js.map +1 -1
- package/dist/file/file.controller.d.ts.map +1 -1
- package/dist/file/file.controller.js +16 -0
- package/dist/file/file.controller.js.map +1 -1
- package/dist/file/file.service.d.ts +7 -1
- package/dist/file/file.service.d.ts.map +1 -1
- package/dist/file/file.service.js +38 -1
- package/dist/file/file.service.js.map +1 -1
- package/dist/file/provider/s3.provider.d.ts +1 -0
- package/dist/file/provider/s3.provider.d.ts.map +1 -1
- package/dist/file/provider/s3.provider.js +38 -29
- package/dist/file/provider/s3.provider.js.map +1 -1
- package/dist/oauth/oauth.service.d.ts.map +1 -1
- package/dist/oauth/oauth.service.js +2 -1
- package/dist/oauth/oauth.service.js.map +1 -1
- package/dist/user/constants/user.constants.d.ts +1 -0
- package/dist/user/constants/user.constants.d.ts.map +1 -1
- package/dist/user/constants/user.constants.js +2 -1
- package/dist/user/constants/user.constants.js.map +1 -1
- package/dist/user/user.controller.d.ts +10 -10
- package/dist/user/user.service.d.ts +30 -30
- package/dist/user/user.service.d.ts.map +1 -1
- package/dist/user/user.service.js +2 -1
- package/dist/user/user.service.js.map +1 -1
- package/hedhog/data/dashboard_item.yaml +11 -11
- package/hedhog/data/route.yaml +8 -0
- package/hedhog/frontend/app/dashboard/[slug]/dashboard-content.tsx.ejs +76 -15
- package/hedhog/frontend/app/dashboard/components/widgets/email-notifications.tsx.ejs +85 -61
- package/hedhog/frontend/app/dashboard/components/widgets/locale-config.tsx.ejs +139 -280
- package/hedhog/frontend/app/dashboard/components/widgets/mail-config.tsx.ejs +161 -407
- package/hedhog/frontend/app/dashboard/components/widgets/oauth-config.tsx.ejs +150 -271
- package/hedhog/frontend/app/dashboard/components/widgets/profile-card.tsx.ejs +3 -3
- package/hedhog/frontend/app/dashboard/components/widgets/storage-config.tsx.ejs +161 -305
- package/hedhog/frontend/app/dashboard/components/widgets/theme-config.tsx.ejs +184 -246
- package/hedhog/frontend/app/dashboard/components/widgets/user-roles.tsx.ejs +12 -14
- package/hedhog/frontend/messages/en.json +90 -0
- package/hedhog/frontend/messages/pt.json +90 -0
- package/hedhog/table/mail_sent_user.yaml +75 -0
- package/package.json +5 -5
- package/src/dashboard/dashboard-core/dashboard-core.controller.ts +5 -0
- package/src/dashboard/dashboard-core/dashboard-core.module.ts +6 -1
- package/src/dashboard/dashboard-core/dashboard-core.service.ts +766 -3
- package/src/file/file.controller.ts +37 -13
- package/src/file/file.service.ts +47 -5
- package/src/file/provider/s3.provider.ts +39 -29
- package/src/oauth/oauth.service.ts +8 -7
- package/src/user/constants/user.constants.ts +1 -0
- package/src/user/user.service.ts +2 -1
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { Badge } from '@/components/ui/badge';
|
|
4
|
-
import { Button } from '@/components/ui/button';
|
|
5
4
|
import {
|
|
6
5
|
Card,
|
|
7
6
|
CardContent,
|
|
@@ -9,437 +8,192 @@ import {
|
|
|
9
8
|
CardHeader,
|
|
10
9
|
CardTitle,
|
|
11
10
|
} from '@/components/ui/card';
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
} from '@/components/ui/select';
|
|
21
|
-
import { Switch } from '@/components/ui/switch';
|
|
22
|
-
import { AlertCircle, CheckCircle2, Mail, Send, Server } from 'lucide-react';
|
|
23
|
-
import { useState } from 'react';
|
|
24
|
-
|
|
25
|
-
type EmailProvider = 'smtp' | 'gmail' | 'aws_ses';
|
|
26
|
-
|
|
27
|
-
interface SmtpConfig {
|
|
28
|
-
host: string;
|
|
29
|
-
port: string;
|
|
30
|
-
username: string;
|
|
31
|
-
password: string;
|
|
32
|
-
encryption: 'tls' | 'ssl' | 'none';
|
|
33
|
-
fromName: string;
|
|
34
|
-
fromEmail: string;
|
|
35
|
-
}
|
|
11
|
+
import { useWidgetData } from '@/hooks/use-widget-data';
|
|
12
|
+
import type {
|
|
13
|
+
DashboardCoreConfigOverviewData,
|
|
14
|
+
MailConfigWidgetData,
|
|
15
|
+
} from '@/types/widget-data';
|
|
16
|
+
import { CheckCircle2, Mail, Send, Server } from 'lucide-react';
|
|
17
|
+
import { useTranslations } from 'next-intl';
|
|
18
|
+
import { WidgetWrapper } from '../widget-wrapper';
|
|
36
19
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
20
|
+
const defaultMailConfigData: MailConfigWidgetData = {
|
|
21
|
+
status: {
|
|
22
|
+
isConfigured: false,
|
|
23
|
+
selectedProvider: null,
|
|
24
|
+
configuredProvider: null,
|
|
25
|
+
},
|
|
26
|
+
sender: {
|
|
27
|
+
from: null,
|
|
28
|
+
},
|
|
29
|
+
metrics: {
|
|
30
|
+
templateCount: 0,
|
|
31
|
+
sentCount: 0,
|
|
32
|
+
sentLast30Days: 0,
|
|
33
|
+
},
|
|
34
|
+
providers: [],
|
|
35
|
+
};
|
|
44
36
|
|
|
45
|
-
interface
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
region: string;
|
|
49
|
-
fromName: string;
|
|
50
|
-
fromEmail: string;
|
|
37
|
+
interface MailConfigProps {
|
|
38
|
+
widget?: { name?: string };
|
|
39
|
+
onRemove?: () => void;
|
|
51
40
|
}
|
|
52
41
|
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
password: '',
|
|
58
|
-
encryption: 'tls',
|
|
59
|
-
fromName: 'HeroAdmin',
|
|
60
|
-
fromEmail: 'noreply@empresa.com',
|
|
42
|
+
const iconByProvider: Record<string, React.ElementType> = {
|
|
43
|
+
SMTP: Server,
|
|
44
|
+
GMAIL: Mail,
|
|
45
|
+
SES: Send,
|
|
61
46
|
};
|
|
62
47
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
clientSecret: '',
|
|
66
|
-
refreshToken: '',
|
|
67
|
-
fromName: 'HeroAdmin',
|
|
68
|
-
fromEmail: '',
|
|
69
|
-
};
|
|
48
|
+
export default function MailConfig({ widget, onRemove }: MailConfigProps) {
|
|
49
|
+
const t = useTranslations('core.DashboardPage.mailConfig');
|
|
70
50
|
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
51
|
+
const { data, isLoading, isError, isAccessDenied } = useWidgetData<
|
|
52
|
+
DashboardCoreConfigOverviewData,
|
|
53
|
+
MailConfigWidgetData
|
|
54
|
+
>({
|
|
55
|
+
endpoint: '/dashboard-core/config/overview',
|
|
56
|
+
queryKey: 'dashboard-core-config-overview',
|
|
57
|
+
select: (d) => d.mailConfig,
|
|
58
|
+
});
|
|
78
59
|
|
|
79
|
-
const
|
|
80
|
-
value: EmailProvider;
|
|
81
|
-
label: string;
|
|
82
|
-
icon: React.ReactNode;
|
|
83
|
-
description: string;
|
|
84
|
-
}[] = [
|
|
85
|
-
{
|
|
86
|
-
value: 'smtp',
|
|
87
|
-
label: 'SMTP',
|
|
88
|
-
icon: <Server className="h-4 w-4" />,
|
|
89
|
-
description: 'Servidor SMTP personalizado',
|
|
90
|
-
},
|
|
91
|
-
{
|
|
92
|
-
value: 'gmail',
|
|
93
|
-
label: 'Gmail',
|
|
94
|
-
icon: <Mail className="h-4 w-4" />,
|
|
95
|
-
description: 'API do Google Gmail',
|
|
96
|
-
},
|
|
97
|
-
{
|
|
98
|
-
value: 'aws_ses',
|
|
99
|
-
label: 'AWS SES',
|
|
100
|
-
icon: <Send className="h-4 w-4" />,
|
|
101
|
-
description: 'Amazon Simple Email Service',
|
|
102
|
-
},
|
|
103
|
-
];
|
|
104
|
-
|
|
105
|
-
export default function EmailConfig() {
|
|
106
|
-
const [provider, setProvider] = useState<EmailProvider>('smtp');
|
|
107
|
-
const [smtp, setSmtp] = useState(initialSmtp);
|
|
108
|
-
const [gmail, setGmail] = useState(initialGmail);
|
|
109
|
-
const [awsSes, setAwsSes] = useState(initialAwsSes);
|
|
110
|
-
const [testSent, setTestSent] = useState(false);
|
|
60
|
+
const mailData = data ?? defaultMailConfigData;
|
|
111
61
|
|
|
112
62
|
return (
|
|
113
|
-
<
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
</div>
|
|
127
|
-
<Badge variant="secondary" className="bg-emerald-50 text-emerald-700">
|
|
128
|
-
<CheckCircle2 className="mr-1 h-3 w-3" />
|
|
129
|
-
Ativo
|
|
130
|
-
</Badge>
|
|
131
|
-
</div>
|
|
132
|
-
</CardHeader>
|
|
133
|
-
<CardContent className="space-y-6">
|
|
134
|
-
{/* Provider Selector */}
|
|
135
|
-
<div className="grid grid-cols-3 gap-3">
|
|
136
|
-
{providers.map((p) => (
|
|
137
|
-
<button
|
|
138
|
-
key={p.value}
|
|
139
|
-
type="button"
|
|
140
|
-
onClick={() => setProvider(p.value)}
|
|
141
|
-
className={`flex flex-col items-center gap-2 rounded-lg border-2 p-4 text-center transition-all ${
|
|
142
|
-
provider === p.value
|
|
143
|
-
? 'border-foreground bg-foreground/3'
|
|
144
|
-
: 'border-border hover:border-foreground/20'
|
|
145
|
-
}`}
|
|
146
|
-
>
|
|
147
|
-
<div
|
|
148
|
-
className={`flex h-9 w-9 items-center justify-center rounded-full ${
|
|
149
|
-
provider === p.value
|
|
150
|
-
? 'bg-foreground text-background'
|
|
151
|
-
: 'bg-muted text-muted-foreground'
|
|
152
|
-
}`}
|
|
153
|
-
>
|
|
154
|
-
{p.icon}
|
|
155
|
-
</div>
|
|
156
|
-
<span className="text-sm font-medium">{p.label}</span>
|
|
157
|
-
<span className="text-xs text-muted-foreground">
|
|
158
|
-
{p.description}
|
|
159
|
-
</span>
|
|
160
|
-
</button>
|
|
161
|
-
))}
|
|
162
|
-
</div>
|
|
163
|
-
|
|
164
|
-
{/* SMTP Fields */}
|
|
165
|
-
{provider === 'smtp' && (
|
|
166
|
-
<div className="space-y-4">
|
|
167
|
-
<div className="grid gap-4 sm:grid-cols-2">
|
|
168
|
-
<div className="space-y-2">
|
|
169
|
-
<Label htmlFor="smtp-host">Servidor SMTP</Label>
|
|
170
|
-
<Input
|
|
171
|
-
id="smtp-host"
|
|
172
|
-
value={smtp.host}
|
|
173
|
-
onChange={(e) => setSmtp({ ...smtp, host: e.target.value })}
|
|
174
|
-
placeholder="smtp.exemplo.com"
|
|
175
|
-
/>
|
|
63
|
+
<WidgetWrapper
|
|
64
|
+
isLoading={isLoading}
|
|
65
|
+
isError={isError}
|
|
66
|
+
isAccessDenied={isAccessDenied}
|
|
67
|
+
widgetName={widget?.name ?? t('title')}
|
|
68
|
+
onRemove={onRemove}
|
|
69
|
+
>
|
|
70
|
+
<Card className="flex h-full min-h-0 flex-col overflow-hidden">
|
|
71
|
+
<CardHeader className="shrink-0">
|
|
72
|
+
<div className="flex items-center justify-between gap-3">
|
|
73
|
+
<div className="flex items-center gap-3">
|
|
74
|
+
<div className="flex h-10 w-10 items-center justify-center rounded-lg bg-blue-50">
|
|
75
|
+
<Mail className="h-5 w-5 text-blue-600" />
|
|
176
76
|
</div>
|
|
177
|
-
<div
|
|
178
|
-
<
|
|
179
|
-
<
|
|
180
|
-
id="smtp-port"
|
|
181
|
-
value={smtp.port}
|
|
182
|
-
onChange={(e) => setSmtp({ ...smtp, port: e.target.value })}
|
|
183
|
-
placeholder="587"
|
|
184
|
-
/>
|
|
77
|
+
<div>
|
|
78
|
+
<CardTitle className="text-base">{t('title')}</CardTitle>
|
|
79
|
+
<CardDescription>{t('description')}</CardDescription>
|
|
185
80
|
</div>
|
|
186
81
|
</div>
|
|
187
|
-
<
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
/>
|
|
209
|
-
</div>
|
|
82
|
+
<Badge
|
|
83
|
+
variant="secondary"
|
|
84
|
+
className={
|
|
85
|
+
mailData.status.isConfigured
|
|
86
|
+
? 'bg-emerald-50 text-emerald-700'
|
|
87
|
+
: 'bg-amber-50 text-amber-700'
|
|
88
|
+
}
|
|
89
|
+
>
|
|
90
|
+
{mailData.status.isConfigured ? t('configured') : t('pending')}
|
|
91
|
+
</Badge>
|
|
92
|
+
</div>
|
|
93
|
+
</CardHeader>
|
|
94
|
+
<CardContent className="flex min-h-0 flex-1 flex-col gap-4 overflow-hidden pt-0">
|
|
95
|
+
<div className="grid grid-cols-3 gap-2">
|
|
96
|
+
<div className="rounded-lg border bg-muted/30 p-3 text-center">
|
|
97
|
+
<p className="text-[11px] text-muted-foreground">
|
|
98
|
+
{t('templates')}
|
|
99
|
+
</p>
|
|
100
|
+
<p className="mt-1 text-lg font-semibold">
|
|
101
|
+
{mailData.metrics.templateCount}
|
|
102
|
+
</p>
|
|
210
103
|
</div>
|
|
211
|
-
<div className="
|
|
212
|
-
<
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
>
|
|
219
|
-
<SelectTrigger>
|
|
220
|
-
<SelectValue />
|
|
221
|
-
</SelectTrigger>
|
|
222
|
-
<SelectContent>
|
|
223
|
-
<SelectItem value="tls">TLS (Recomendado)</SelectItem>
|
|
224
|
-
<SelectItem value="ssl">SSL</SelectItem>
|
|
225
|
-
<SelectItem value="none">Nenhuma</SelectItem>
|
|
226
|
-
</SelectContent>
|
|
227
|
-
</Select>
|
|
104
|
+
<div className="rounded-lg border bg-muted/30 p-3 text-center">
|
|
105
|
+
<p className="text-[11px] text-muted-foreground">
|
|
106
|
+
{t('sentTotal')}
|
|
107
|
+
</p>
|
|
108
|
+
<p className="mt-1 text-lg font-semibold">
|
|
109
|
+
{mailData.metrics.sentCount}
|
|
110
|
+
</p>
|
|
228
111
|
</div>
|
|
229
|
-
<div className="
|
|
230
|
-
<
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
setSmtp({ ...smtp, fromName: e.target.value })
|
|
237
|
-
}
|
|
238
|
-
/>
|
|
239
|
-
</div>
|
|
240
|
-
<div className="space-y-2">
|
|
241
|
-
<Label htmlFor="smtp-from-email">E-mail do remetente</Label>
|
|
242
|
-
<Input
|
|
243
|
-
id="smtp-from-email"
|
|
244
|
-
type="email"
|
|
245
|
-
value={smtp.fromEmail}
|
|
246
|
-
onChange={(e) =>
|
|
247
|
-
setSmtp({ ...smtp, fromEmail: e.target.value })
|
|
248
|
-
}
|
|
249
|
-
/>
|
|
250
|
-
</div>
|
|
112
|
+
<div className="rounded-lg border bg-muted/30 p-3 text-center">
|
|
113
|
+
<p className="text-[11px] text-muted-foreground">
|
|
114
|
+
{t('sent30Days')}
|
|
115
|
+
</p>
|
|
116
|
+
<p className="mt-1 text-lg font-semibold">
|
|
117
|
+
{mailData.metrics.sentLast30Days}
|
|
118
|
+
</p>
|
|
251
119
|
</div>
|
|
252
120
|
</div>
|
|
253
|
-
)}
|
|
254
121
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
<AlertCircle className="mt-0.5 h-4 w-4 text-amber-600" />
|
|
261
|
-
<p className="text-xs text-amber-800">
|
|
262
|
-
Configure as credenciais OAuth2 no Google Cloud Console.
|
|
263
|
-
Habilite a API do Gmail e gere o Client ID e Secret.
|
|
264
|
-
</p>
|
|
265
|
-
</div>
|
|
266
|
-
</div>
|
|
267
|
-
<div className="space-y-2">
|
|
268
|
-
<Label htmlFor="gmail-client-id">Client ID</Label>
|
|
269
|
-
<Input
|
|
270
|
-
id="gmail-client-id"
|
|
271
|
-
value={gmail.clientId}
|
|
272
|
-
onChange={(e) =>
|
|
273
|
-
setGmail({ ...gmail, clientId: e.target.value })
|
|
274
|
-
}
|
|
275
|
-
placeholder="xxxxx.apps.googleusercontent.com"
|
|
276
|
-
className="font-mono text-sm"
|
|
277
|
-
/>
|
|
278
|
-
</div>
|
|
279
|
-
<div className="space-y-2">
|
|
280
|
-
<Label htmlFor="gmail-client-secret">Client Secret</Label>
|
|
281
|
-
<Input
|
|
282
|
-
id="gmail-client-secret"
|
|
283
|
-
type="password"
|
|
284
|
-
value={gmail.clientSecret}
|
|
285
|
-
onChange={(e) =>
|
|
286
|
-
setGmail({ ...gmail, clientSecret: e.target.value })
|
|
287
|
-
}
|
|
288
|
-
placeholder="GOCSPX-..."
|
|
289
|
-
className="font-mono text-sm"
|
|
290
|
-
/>
|
|
291
|
-
</div>
|
|
292
|
-
<div className="space-y-2">
|
|
293
|
-
<Label htmlFor="gmail-refresh-token">Refresh Token</Label>
|
|
294
|
-
<Input
|
|
295
|
-
id="gmail-refresh-token"
|
|
296
|
-
type="password"
|
|
297
|
-
value={gmail.refreshToken}
|
|
298
|
-
onChange={(e) =>
|
|
299
|
-
setGmail({ ...gmail, refreshToken: e.target.value })
|
|
300
|
-
}
|
|
301
|
-
className="font-mono text-sm"
|
|
302
|
-
/>
|
|
303
|
-
</div>
|
|
304
|
-
<div className="grid gap-4 sm:grid-cols-2">
|
|
305
|
-
<div className="space-y-2">
|
|
306
|
-
<Label htmlFor="gmail-from-name">Nome do remetente</Label>
|
|
307
|
-
<Input
|
|
308
|
-
id="gmail-from-name"
|
|
309
|
-
value={gmail.fromName}
|
|
310
|
-
onChange={(e) =>
|
|
311
|
-
setGmail({ ...gmail, fromName: e.target.value })
|
|
312
|
-
}
|
|
313
|
-
/>
|
|
314
|
-
</div>
|
|
315
|
-
<div className="space-y-2">
|
|
316
|
-
<Label htmlFor="gmail-from-email">E-mail do remetente</Label>
|
|
317
|
-
<Input
|
|
318
|
-
id="gmail-from-email"
|
|
319
|
-
type="email"
|
|
320
|
-
value={gmail.fromEmail}
|
|
321
|
-
onChange={(e) =>
|
|
322
|
-
setGmail({ ...gmail, fromEmail: e.target.value })
|
|
323
|
-
}
|
|
324
|
-
placeholder="email@gmail.com"
|
|
325
|
-
/>
|
|
326
|
-
</div>
|
|
327
|
-
</div>
|
|
122
|
+
<div className="rounded-lg border p-3">
|
|
123
|
+
<p className="mb-2 text-xs text-muted-foreground">{t('sender')}</p>
|
|
124
|
+
<p className="truncate text-sm font-medium">
|
|
125
|
+
{mailData.sender.from || t('notSet')}
|
|
126
|
+
</p>
|
|
328
127
|
</div>
|
|
329
|
-
)}
|
|
330
128
|
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
onChange={(e) =>
|
|
340
|
-
setAwsSes({ ...awsSes, accessKeyId: e.target.value })
|
|
341
|
-
}
|
|
342
|
-
placeholder="AKIAIOSFODNN7EXAMPLE"
|
|
343
|
-
className="font-mono text-sm"
|
|
344
|
-
/>
|
|
345
|
-
</div>
|
|
346
|
-
<div className="space-y-2">
|
|
347
|
-
<Label htmlFor="ses-secret-key">Secret Access Key</Label>
|
|
348
|
-
<Input
|
|
349
|
-
id="ses-secret-key"
|
|
350
|
-
type="password"
|
|
351
|
-
value={awsSes.secretAccessKey}
|
|
352
|
-
onChange={(e) =>
|
|
353
|
-
setAwsSes({ ...awsSes, secretAccessKey: e.target.value })
|
|
354
|
-
}
|
|
355
|
-
className="font-mono text-sm"
|
|
356
|
-
/>
|
|
129
|
+
<div className="min-h-0 flex-1 rounded-lg border p-3">
|
|
130
|
+
<div className="mb-2 flex items-center justify-between">
|
|
131
|
+
<p className="text-xs text-muted-foreground">{t('providers')}</p>
|
|
132
|
+
<Badge variant="outline" className="text-[10px]">
|
|
133
|
+
{t('selectedProvider', {
|
|
134
|
+
provider: mailData.status.selectedProvider || t('none'),
|
|
135
|
+
})}
|
|
136
|
+
</Badge>
|
|
357
137
|
</div>
|
|
358
138
|
<div className="space-y-2">
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
<SelectValue />
|
|
366
|
-
</SelectTrigger>
|
|
367
|
-
<SelectContent>
|
|
368
|
-
<SelectItem value="us-east-1">
|
|
369
|
-
US East (N. Virginia)
|
|
370
|
-
</SelectItem>
|
|
371
|
-
<SelectItem value="us-west-2">US West (Oregon)</SelectItem>
|
|
372
|
-
<SelectItem value="eu-west-1">EU (Ireland)</SelectItem>
|
|
373
|
-
<SelectItem value="eu-central-1">EU (Frankfurt)</SelectItem>
|
|
374
|
-
<SelectItem value="sa-east-1">
|
|
375
|
-
South America (Sao Paulo)
|
|
376
|
-
</SelectItem>
|
|
377
|
-
<SelectItem value="ap-southeast-1">
|
|
378
|
-
Asia Pacific (Singapore)
|
|
379
|
-
</SelectItem>
|
|
380
|
-
</SelectContent>
|
|
381
|
-
</Select>
|
|
382
|
-
</div>
|
|
383
|
-
<div className="grid gap-4 sm:grid-cols-2">
|
|
384
|
-
<div className="space-y-2">
|
|
385
|
-
<Label htmlFor="ses-from-name">Nome do remetente</Label>
|
|
386
|
-
<Input
|
|
387
|
-
id="ses-from-name"
|
|
388
|
-
value={awsSes.fromName}
|
|
389
|
-
onChange={(e) =>
|
|
390
|
-
setAwsSes({ ...awsSes, fromName: e.target.value })
|
|
391
|
-
}
|
|
392
|
-
/>
|
|
393
|
-
</div>
|
|
394
|
-
<div className="space-y-2">
|
|
395
|
-
<Label htmlFor="ses-from-email">E-mail do remetente</Label>
|
|
396
|
-
<Input
|
|
397
|
-
id="ses-from-email"
|
|
398
|
-
type="email"
|
|
399
|
-
value={awsSes.fromEmail}
|
|
400
|
-
onChange={(e) =>
|
|
401
|
-
setAwsSes({ ...awsSes, fromEmail: e.target.value })
|
|
402
|
-
}
|
|
403
|
-
placeholder="noreply@seudominio.com"
|
|
404
|
-
/>
|
|
405
|
-
</div>
|
|
406
|
-
</div>
|
|
407
|
-
</div>
|
|
408
|
-
)}
|
|
139
|
+
{mailData.providers.length > 0 ? (
|
|
140
|
+
mailData.providers.map((provider) => {
|
|
141
|
+
const Icon = iconByProvider[provider.id] ?? Mail;
|
|
142
|
+
const statusClass = provider.configured
|
|
143
|
+
? 'bg-emerald-50 text-emerald-700'
|
|
144
|
+
: 'bg-muted text-muted-foreground';
|
|
409
145
|
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
146
|
+
return (
|
|
147
|
+
<div
|
|
148
|
+
key={provider.id}
|
|
149
|
+
className="flex items-center justify-between rounded-lg border p-2"
|
|
150
|
+
>
|
|
151
|
+
<div className="flex min-w-0 items-center gap-2">
|
|
152
|
+
<div className="flex h-7 w-7 items-center justify-center rounded-md bg-muted/60">
|
|
153
|
+
<Icon className="h-3.5 w-3.5" />
|
|
154
|
+
</div>
|
|
155
|
+
<div className="min-w-0">
|
|
156
|
+
<p className="truncate text-sm font-medium">
|
|
157
|
+
{provider.label}
|
|
158
|
+
</p>
|
|
159
|
+
<p className="truncate text-[11px] text-muted-foreground">
|
|
160
|
+
{provider.missingKeys.length > 0
|
|
161
|
+
? t('missingKeys', {
|
|
162
|
+
count: provider.missingKeys.length,
|
|
163
|
+
})
|
|
164
|
+
: t('allKeysPresent')}
|
|
165
|
+
</p>
|
|
166
|
+
</div>
|
|
167
|
+
</div>
|
|
168
|
+
<div className="flex items-center gap-1.5">
|
|
169
|
+
{provider.selected && (
|
|
170
|
+
<Badge variant="outline" className="text-[10px]">
|
|
171
|
+
{t('selected')}
|
|
172
|
+
</Badge>
|
|
173
|
+
)}
|
|
174
|
+
<Badge variant="secondary" className={statusClass}>
|
|
175
|
+
{provider.configured ? (
|
|
176
|
+
<>
|
|
177
|
+
<CheckCircle2 className="mr-1 h-3 w-3" />
|
|
178
|
+
{t('configured')}
|
|
179
|
+
</>
|
|
180
|
+
) : (
|
|
181
|
+
t('pending')
|
|
182
|
+
)}
|
|
183
|
+
</Badge>
|
|
184
|
+
</div>
|
|
185
|
+
</div>
|
|
186
|
+
);
|
|
187
|
+
})
|
|
435
188
|
) : (
|
|
436
|
-
|
|
189
|
+
<p className="text-xs text-muted-foreground">
|
|
190
|
+
{t('noProviders')}
|
|
191
|
+
</p>
|
|
437
192
|
)}
|
|
438
|
-
</
|
|
439
|
-
<Button size="sm">Salvar</Button>
|
|
193
|
+
</div>
|
|
440
194
|
</div>
|
|
441
|
-
</
|
|
442
|
-
</
|
|
443
|
-
</
|
|
195
|
+
</CardContent>
|
|
196
|
+
</Card>
|
|
197
|
+
</WidgetWrapper>
|
|
444
198
|
);
|
|
445
199
|
}
|