@hed-hog/core 0.0.296 → 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 +14 -14
- package/dist/auth/auth.service.d.ts +14 -14
- package/dist/challenge/challenge.service.d.ts +2 -2
- package/dist/dashboard/dashboard-core/dashboard-core.controller.d.ts +15 -1
- 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 +175 -3
- 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/profile/profile.controller.d.ts +6 -6
- package/dist/profile/profile.service.d.ts +6 -6
- package/dist/session/session.controller.d.ts +2 -2
- package/dist/session/session.service.d.ts +3 -3
- package/dist/setting/setting.controller.d.ts +9 -9
- package/dist/setting/setting.service.d.ts +10 -10
- 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 +15 -15
- package/dist/user/user.service.d.ts +39 -39
- 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 +4 -4
- 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,332 +8,189 @@ 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 {
|
|
22
|
-
AlertCircle,
|
|
23
|
-
CheckCircle2,
|
|
24
|
-
Cloud,
|
|
25
|
-
FolderOpen,
|
|
26
|
-
HardDrive,
|
|
27
|
-
} from 'lucide-react';
|
|
28
|
-
import { useState } from 'react';
|
|
29
|
-
|
|
30
|
-
type StorageProvider = 'local' | 's3' | 'gcs' | 'azure';
|
|
11
|
+
import { useWidgetData } from '@/hooks/use-widget-data';
|
|
12
|
+
import type {
|
|
13
|
+
DashboardCoreConfigOverviewData,
|
|
14
|
+
StorageConfigWidgetData,
|
|
15
|
+
} from '@/types/widget-data';
|
|
16
|
+
import { CheckCircle2, HardDrive } from 'lucide-react';
|
|
17
|
+
import { useTranslations } from 'next-intl';
|
|
18
|
+
import { WidgetWrapper } from '../widget-wrapper';
|
|
31
19
|
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
{
|
|
39
|
-
value: 'local',
|
|
40
|
-
label: 'Local',
|
|
41
|
-
icon: <FolderOpen className="h-4 w-4" />,
|
|
42
|
-
description: 'Disco do servidor',
|
|
43
|
-
},
|
|
44
|
-
{
|
|
45
|
-
value: 's3',
|
|
46
|
-
label: 'AWS S3',
|
|
47
|
-
icon: <Cloud className="h-4 w-4" />,
|
|
48
|
-
description: 'Amazon S3 Bucket',
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
value: 'gcs',
|
|
52
|
-
label: 'Google Cloud',
|
|
53
|
-
icon: <Cloud className="h-4 w-4" />,
|
|
54
|
-
description: 'Google Cloud Storage',
|
|
20
|
+
const defaultStorageConfigData: StorageConfigWidgetData = {
|
|
21
|
+
status: {
|
|
22
|
+
isConfigured: false,
|
|
23
|
+
totalProfiles: 0,
|
|
24
|
+
activeProfiles: 0,
|
|
25
|
+
defaultProfileId: null,
|
|
55
26
|
},
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
icon: <Cloud className="h-4 w-4" />,
|
|
60
|
-
description: 'Azure Blob Storage',
|
|
61
|
-
},
|
|
62
|
-
];
|
|
27
|
+
providers: [],
|
|
28
|
+
profiles: [],
|
|
29
|
+
};
|
|
63
30
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
31
|
+
interface StorageConfigProps {
|
|
32
|
+
widget?: { name?: string };
|
|
33
|
+
onRemove?: () => void;
|
|
34
|
+
}
|
|
68
35
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
const
|
|
36
|
+
export default function StorageConfig({
|
|
37
|
+
widget,
|
|
38
|
+
onRemove,
|
|
39
|
+
}: StorageConfigProps) {
|
|
40
|
+
const t = useTranslations('core.DashboardPage.storageConfig');
|
|
74
41
|
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
42
|
+
const { data, isLoading, isError, isAccessDenied } = useWidgetData<
|
|
43
|
+
DashboardCoreConfigOverviewData,
|
|
44
|
+
StorageConfigWidgetData
|
|
45
|
+
>({
|
|
46
|
+
endpoint: '/dashboard-core/config/overview',
|
|
47
|
+
queryKey: 'dashboard-core-config-overview',
|
|
48
|
+
select: (d) => d.storageConfig,
|
|
49
|
+
});
|
|
78
50
|
|
|
79
|
-
const
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
51
|
+
const storageData = data ?? defaultStorageConfigData;
|
|
52
|
+
const defaultProfile = storageData.profiles.find(
|
|
53
|
+
(profile) => profile.id === storageData.status.defaultProfileId
|
|
54
|
+
);
|
|
83
55
|
|
|
84
56
|
return (
|
|
85
|
-
<
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
<
|
|
97
|
-
|
|
98
|
-
</CardDescription>
|
|
99
|
-
</div>
|
|
100
|
-
</div>
|
|
101
|
-
<Badge variant="secondary" className="bg-emerald-50 text-emerald-700">
|
|
102
|
-
<CheckCircle2 className="mr-1 h-3 w-3" />
|
|
103
|
-
Configurado
|
|
104
|
-
</Badge>
|
|
105
|
-
</div>
|
|
106
|
-
</CardHeader>
|
|
107
|
-
<CardContent className="space-y-6">
|
|
108
|
-
{/* Provider Selector */}
|
|
109
|
-
<div className="grid grid-cols-2 gap-3 sm:grid-cols-4">
|
|
110
|
-
{providerList.map((p) => (
|
|
111
|
-
<button
|
|
112
|
-
key={p.value}
|
|
113
|
-
type="button"
|
|
114
|
-
onClick={() => setProvider(p.value)}
|
|
115
|
-
className={`flex flex-col items-center gap-1.5 rounded-lg border-2 p-3 text-center transition-all ${
|
|
116
|
-
provider === p.value
|
|
117
|
-
? 'border-foreground bg-foreground/3'
|
|
118
|
-
: 'border-border hover:border-foreground/20'
|
|
119
|
-
}`}
|
|
120
|
-
>
|
|
121
|
-
<div
|
|
122
|
-
className={`flex h-8 w-8 items-center justify-center rounded-full ${
|
|
123
|
-
provider === p.value
|
|
124
|
-
? 'bg-foreground text-background'
|
|
125
|
-
: 'bg-muted text-muted-foreground'
|
|
126
|
-
}`}
|
|
127
|
-
>
|
|
128
|
-
{p.icon}
|
|
57
|
+
<WidgetWrapper
|
|
58
|
+
isLoading={isLoading}
|
|
59
|
+
isError={isError}
|
|
60
|
+
isAccessDenied={isAccessDenied}
|
|
61
|
+
widgetName={widget?.name ?? t('title')}
|
|
62
|
+
onRemove={onRemove}
|
|
63
|
+
>
|
|
64
|
+
<Card className="flex h-full min-h-0 flex-col overflow-hidden">
|
|
65
|
+
<CardHeader className="shrink-0">
|
|
66
|
+
<div className="flex items-center justify-between gap-3">
|
|
67
|
+
<div className="flex items-center gap-3">
|
|
68
|
+
<div className="flex h-10 w-10 items-center justify-center rounded-lg bg-violet-50">
|
|
69
|
+
<HardDrive className="h-5 w-5 text-violet-600" />
|
|
129
70
|
</div>
|
|
130
|
-
<
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
</div>
|
|
134
|
-
|
|
135
|
-
{/* Local Fields */}
|
|
136
|
-
{provider === 'local' && (
|
|
137
|
-
<div className="space-y-4">
|
|
138
|
-
<div className="space-y-2">
|
|
139
|
-
<Label htmlFor="local-path">Caminho do diretorio</Label>
|
|
140
|
-
<Input
|
|
141
|
-
id="local-path"
|
|
142
|
-
value={localPath}
|
|
143
|
-
onChange={(e) => setLocalPath(e.target.value)}
|
|
144
|
-
placeholder="/var/data/uploads"
|
|
145
|
-
className="font-mono text-sm"
|
|
146
|
-
/>
|
|
147
|
-
</div>
|
|
148
|
-
<div className="space-y-2">
|
|
149
|
-
<Label htmlFor="local-max-size">
|
|
150
|
-
Tamanho maximo por arquivo (MB)
|
|
151
|
-
</Label>
|
|
152
|
-
<Input
|
|
153
|
-
id="local-max-size"
|
|
154
|
-
type="number"
|
|
155
|
-
value={localMaxSize}
|
|
156
|
-
onChange={(e) => setLocalMaxSize(e.target.value)}
|
|
157
|
-
/>
|
|
158
|
-
</div>
|
|
159
|
-
<div className="rounded-lg border border-blue-200 bg-blue-50 p-3">
|
|
160
|
-
<div className="flex items-start gap-2">
|
|
161
|
-
<AlertCircle className="mt-0.5 h-4 w-4 text-blue-600" />
|
|
162
|
-
<p className="text-xs text-blue-800">
|
|
163
|
-
Certifique-se de que o diretorio existe e que o servidor tem
|
|
164
|
-
permissoes de leitura e escrita.
|
|
165
|
-
</p>
|
|
71
|
+
<div>
|
|
72
|
+
<CardTitle className="text-base">{t('title')}</CardTitle>
|
|
73
|
+
<CardDescription>{t('description')}</CardDescription>
|
|
166
74
|
</div>
|
|
167
75
|
</div>
|
|
76
|
+
<Badge
|
|
77
|
+
variant="secondary"
|
|
78
|
+
className={
|
|
79
|
+
storageData.status.isConfigured
|
|
80
|
+
? 'bg-emerald-50 text-emerald-700'
|
|
81
|
+
: 'bg-amber-50 text-amber-700'
|
|
82
|
+
}
|
|
83
|
+
>
|
|
84
|
+
{storageData.status.isConfigured ? t('configured') : t('pending')}
|
|
85
|
+
</Badge>
|
|
168
86
|
</div>
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
value={s3Bucket}
|
|
180
|
-
onChange={(e) => setS3Bucket(e.target.value)}
|
|
181
|
-
placeholder="meu-bucket"
|
|
182
|
-
className="font-mono text-sm"
|
|
183
|
-
/>
|
|
184
|
-
</div>
|
|
185
|
-
<div className="space-y-2">
|
|
186
|
-
<Label>Regiao</Label>
|
|
187
|
-
<Select value={s3Region} onValueChange={setS3Region}>
|
|
188
|
-
<SelectTrigger>
|
|
189
|
-
<SelectValue />
|
|
190
|
-
</SelectTrigger>
|
|
191
|
-
<SelectContent>
|
|
192
|
-
<SelectItem value="us-east-1">
|
|
193
|
-
US East (N. Virginia)
|
|
194
|
-
</SelectItem>
|
|
195
|
-
<SelectItem value="us-west-2">US West (Oregon)</SelectItem>
|
|
196
|
-
<SelectItem value="eu-west-1">EU (Ireland)</SelectItem>
|
|
197
|
-
<SelectItem value="eu-central-1">EU (Frankfurt)</SelectItem>
|
|
198
|
-
<SelectItem value="sa-east-1">
|
|
199
|
-
South America (Sao Paulo)
|
|
200
|
-
</SelectItem>
|
|
201
|
-
</SelectContent>
|
|
202
|
-
</Select>
|
|
203
|
-
</div>
|
|
204
|
-
</div>
|
|
205
|
-
<div className="space-y-2">
|
|
206
|
-
<Label htmlFor="s3-access-key">Access Key ID</Label>
|
|
207
|
-
<Input
|
|
208
|
-
id="s3-access-key"
|
|
209
|
-
value={s3AccessKey}
|
|
210
|
-
onChange={(e) => setS3AccessKey(e.target.value)}
|
|
211
|
-
placeholder="AKIAIOSFODNN7EXAMPLE"
|
|
212
|
-
className="font-mono text-sm"
|
|
213
|
-
/>
|
|
87
|
+
</CardHeader>
|
|
88
|
+
<CardContent className="flex min-h-0 flex-1 flex-col gap-4 overflow-hidden pt-0">
|
|
89
|
+
<div className="grid grid-cols-3 gap-2">
|
|
90
|
+
<div className="rounded-lg border bg-muted/30 p-3 text-center">
|
|
91
|
+
<p className="text-[11px] text-muted-foreground">
|
|
92
|
+
{t('profiles')}
|
|
93
|
+
</p>
|
|
94
|
+
<p className="mt-1 text-lg font-semibold">
|
|
95
|
+
{storageData.status.totalProfiles}
|
|
96
|
+
</p>
|
|
214
97
|
</div>
|
|
215
|
-
<div className="
|
|
216
|
-
<
|
|
217
|
-
<
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
value={s3SecretKey}
|
|
221
|
-
onChange={(e) => setS3SecretKey(e.target.value)}
|
|
222
|
-
className="font-mono text-sm"
|
|
223
|
-
/>
|
|
98
|
+
<div className="rounded-lg border bg-muted/30 p-3 text-center">
|
|
99
|
+
<p className="text-[11px] text-muted-foreground">{t('active')}</p>
|
|
100
|
+
<p className="mt-1 text-lg font-semibold">
|
|
101
|
+
{storageData.status.activeProfiles}
|
|
102
|
+
</p>
|
|
224
103
|
</div>
|
|
225
|
-
<div className="
|
|
226
|
-
<
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
className="font-mono text-sm"
|
|
233
|
-
/>
|
|
104
|
+
<div className="rounded-lg border bg-muted/30 p-3 text-center">
|
|
105
|
+
<p className="text-[11px] text-muted-foreground">
|
|
106
|
+
{t('providers')}
|
|
107
|
+
</p>
|
|
108
|
+
<p className="mt-1 text-lg font-semibold">
|
|
109
|
+
{storageData.providers.length}
|
|
110
|
+
</p>
|
|
234
111
|
</div>
|
|
235
112
|
</div>
|
|
236
|
-
)}
|
|
237
113
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
</div>
|
|
252
|
-
<div className="space-y-2">
|
|
253
|
-
<Label htmlFor="gcs-bucket">Bucket</Label>
|
|
254
|
-
<Input
|
|
255
|
-
id="gcs-bucket"
|
|
256
|
-
value={gcsBucket}
|
|
257
|
-
onChange={(e) => setGcsBucket(e.target.value)}
|
|
258
|
-
placeholder="meu-bucket-gcs"
|
|
259
|
-
className="font-mono text-sm"
|
|
260
|
-
/>
|
|
261
|
-
</div>
|
|
262
|
-
</div>
|
|
263
|
-
<div className="space-y-2">
|
|
264
|
-
<Label htmlFor="gcs-key-file">
|
|
265
|
-
Chave JSON da Service Account
|
|
266
|
-
</Label>
|
|
267
|
-
<textarea
|
|
268
|
-
id="gcs-key-file"
|
|
269
|
-
className="flex min-h-[100px] w-full rounded-md border border-input bg-background px-3 py-2 font-mono text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
|
|
270
|
-
value={gcsKeyFile}
|
|
271
|
-
onChange={(e) => setGcsKeyFile(e.target.value)}
|
|
272
|
-
placeholder='{"type": "service_account", ...}'
|
|
273
|
-
/>
|
|
274
|
-
</div>
|
|
114
|
+
<div className="rounded-lg border p-3">
|
|
115
|
+
<p className="mb-1 text-xs text-muted-foreground">
|
|
116
|
+
{t('defaultProfile')}
|
|
117
|
+
</p>
|
|
118
|
+
<p className="truncate text-sm font-medium">
|
|
119
|
+
{defaultProfile?.name || t('notSet')}
|
|
120
|
+
</p>
|
|
121
|
+
{defaultProfile && (
|
|
122
|
+
<p className="mt-1 text-[11px] text-muted-foreground">
|
|
123
|
+
{defaultProfile.providerType.toUpperCase()} |{' '}
|
|
124
|
+
{defaultProfile.bucketName}
|
|
125
|
+
</p>
|
|
126
|
+
)}
|
|
275
127
|
</div>
|
|
276
|
-
)}
|
|
277
128
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
<
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
placeholder="arquivos"
|
|
299
|
-
className="font-mono text-sm"
|
|
300
|
-
/>
|
|
129
|
+
<div className="grid gap-2 sm:grid-cols-2">
|
|
130
|
+
{storageData.providers.map((provider) => (
|
|
131
|
+
<div
|
|
132
|
+
key={provider.providerType}
|
|
133
|
+
className="rounded-lg border p-3"
|
|
134
|
+
>
|
|
135
|
+
<div className="flex items-center justify-between">
|
|
136
|
+
<p className="text-sm font-medium">
|
|
137
|
+
{provider.providerType.toUpperCase()}
|
|
138
|
+
</p>
|
|
139
|
+
<Badge variant="outline" className="text-[10px]">
|
|
140
|
+
{provider.defaults} {t('defaults')}
|
|
141
|
+
</Badge>
|
|
142
|
+
</div>
|
|
143
|
+
<p className="mt-1 text-[11px] text-muted-foreground">
|
|
144
|
+
{t('providerSummary', {
|
|
145
|
+
total: provider.total,
|
|
146
|
+
active: provider.active,
|
|
147
|
+
})}
|
|
148
|
+
</p>
|
|
301
149
|
</div>
|
|
302
|
-
|
|
303
|
-
<div className="space-y-2">
|
|
304
|
-
<Label htmlFor="azure-key">Access Key</Label>
|
|
305
|
-
<Input
|
|
306
|
-
id="azure-key"
|
|
307
|
-
type="password"
|
|
308
|
-
value={azureKey}
|
|
309
|
-
onChange={(e) => setAzureKey(e.target.value)}
|
|
310
|
-
className="font-mono text-sm"
|
|
311
|
-
/>
|
|
312
|
-
</div>
|
|
313
|
-
<div className="space-y-2">
|
|
314
|
-
<Label htmlFor="azure-endpoint">
|
|
315
|
-
Endpoint personalizado (opcional)
|
|
316
|
-
</Label>
|
|
317
|
-
<Input
|
|
318
|
-
id="azure-endpoint"
|
|
319
|
-
value={azureEndpoint}
|
|
320
|
-
onChange={(e) => setAzureEndpoint(e.target.value)}
|
|
321
|
-
placeholder="https://meuaccount.blob.core.windows.net"
|
|
322
|
-
className="font-mono text-sm"
|
|
323
|
-
/>
|
|
324
|
-
</div>
|
|
150
|
+
))}
|
|
325
151
|
</div>
|
|
326
|
-
)}
|
|
327
152
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
153
|
+
<div className="min-h-0 flex-1 space-y-2 overflow-auto">
|
|
154
|
+
{storageData.profiles.slice(0, 4).map((profile) => (
|
|
155
|
+
<div key={profile.id} className="rounded-lg border p-3">
|
|
156
|
+
<div className="flex items-center justify-between gap-2">
|
|
157
|
+
<p className="truncate text-sm font-medium">{profile.name}</p>
|
|
158
|
+
<div className="flex items-center gap-1.5">
|
|
159
|
+
{profile.isDefault && (
|
|
160
|
+
<Badge variant="outline" className="text-[10px]">
|
|
161
|
+
{t('defaultTag')}
|
|
162
|
+
</Badge>
|
|
163
|
+
)}
|
|
164
|
+
<Badge
|
|
165
|
+
variant="secondary"
|
|
166
|
+
className={
|
|
167
|
+
profile.isActive
|
|
168
|
+
? 'bg-emerald-50 text-emerald-700'
|
|
169
|
+
: 'bg-muted text-muted-foreground'
|
|
170
|
+
}
|
|
171
|
+
>
|
|
172
|
+
{profile.isActive ? (
|
|
173
|
+
<>
|
|
174
|
+
<CheckCircle2 className="mr-1 h-3 w-3" />
|
|
175
|
+
{t('active')}
|
|
176
|
+
</>
|
|
177
|
+
) : (
|
|
178
|
+
t('inactive')
|
|
179
|
+
)}
|
|
180
|
+
</Badge>
|
|
181
|
+
</div>
|
|
182
|
+
</div>
|
|
183
|
+
<p className="mt-1 truncate text-[11px] text-muted-foreground">
|
|
184
|
+
{profile.providerType.toUpperCase()} | {profile.bucketName}
|
|
185
|
+
</p>
|
|
186
|
+
</div>
|
|
187
|
+
))}
|
|
188
|
+
{storageData.profiles.length === 0 && (
|
|
189
|
+
<p className="text-xs text-muted-foreground">{t('noProfiles')}</p>
|
|
190
|
+
)}
|
|
335
191
|
</div>
|
|
336
|
-
</
|
|
337
|
-
</
|
|
338
|
-
</
|
|
192
|
+
</CardContent>
|
|
193
|
+
</Card>
|
|
194
|
+
</WidgetWrapper>
|
|
339
195
|
);
|
|
340
196
|
}
|