diff --git a/public/icons/backends/alibaba.svg b/public/icons/backends/alibaba.svg new file mode 100644 index 0000000..90fa403 --- /dev/null +++ b/public/icons/backends/alibaba.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/icons/backends/aws-light.svg b/public/icons/backends/aws-light.svg new file mode 100644 index 0000000..711a93a --- /dev/null +++ b/public/icons/backends/aws-light.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/icons/backends/azure.ico b/public/icons/backends/azure.ico new file mode 100644 index 0000000..bfe873e Binary files /dev/null and b/public/icons/backends/azure.ico differ diff --git a/public/icons/backends/baiducloud-color.svg b/public/icons/backends/baiducloud-color.svg new file mode 100644 index 0000000..40565ef --- /dev/null +++ b/public/icons/backends/baiducloud-color.svg @@ -0,0 +1 @@ +BaiduCloud \ No newline at end of file diff --git a/public/icons/backends/bunny.svg b/public/icons/backends/bunny.svg new file mode 100644 index 0000000..2ea31fa --- /dev/null +++ b/public/icons/backends/bunny.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/icons/backends/cloudflare.svg b/public/icons/backends/cloudflare.svg new file mode 100644 index 0000000..66cc020 --- /dev/null +++ b/public/icons/backends/cloudflare.svg @@ -0,0 +1 @@ +Cloudflare \ No newline at end of file diff --git a/public/icons/backends/cpanel.svg b/public/icons/backends/cpanel.svg new file mode 100644 index 0000000..4bfc2ac --- /dev/null +++ b/public/icons/backends/cpanel.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/icons/backends/digital-ocean.svg b/public/icons/backends/digital-ocean.svg new file mode 100644 index 0000000..fbc40ee --- /dev/null +++ b/public/icons/backends/digital-ocean.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/icons/backends/dnsimple.svg b/public/icons/backends/dnsimple.svg new file mode 100644 index 0000000..9b30e91 --- /dev/null +++ b/public/icons/backends/dnsimple.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/icons/backends/duckdns.svg b/public/icons/backends/duckdns.svg new file mode 100644 index 0000000..925ef6f --- /dev/null +++ b/public/icons/backends/duckdns.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/icons/backends/foundationdb.svg b/public/icons/backends/foundationdb.svg new file mode 100644 index 0000000..c6814a5 --- /dev/null +++ b/public/icons/backends/foundationdb.svg @@ -0,0 +1,124 @@ + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/icons/backends/google.svg b/public/icons/backends/google.svg new file mode 100644 index 0000000..e9576f7 --- /dev/null +++ b/public/icons/backends/google.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/icons/backends/ibm.svg b/public/icons/backends/ibm.svg new file mode 100644 index 0000000..d97f8d0 --- /dev/null +++ b/public/icons/backends/ibm.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/icons/backends/ionos.svg b/public/icons/backends/ionos.svg new file mode 100644 index 0000000..8c429cc --- /dev/null +++ b/public/icons/backends/ionos.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/icons/backends/mysql.svg b/public/icons/backends/mysql.svg new file mode 100644 index 0000000..3245e88 --- /dev/null +++ b/public/icons/backends/mysql.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/icons/backends/ovh.svg b/public/icons/backends/ovh.svg new file mode 100644 index 0000000..9daa905 --- /dev/null +++ b/public/icons/backends/ovh.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/icons/backends/porkbun.png b/public/icons/backends/porkbun.png new file mode 100644 index 0000000..f34914c Binary files /dev/null and b/public/icons/backends/porkbun.png differ diff --git a/public/icons/backends/postgresql.svg b/public/icons/backends/postgresql.svg new file mode 100644 index 0000000..abacb8f --- /dev/null +++ b/public/icons/backends/postgresql.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/icons/backends/quad9.svg b/public/icons/backends/quad9.svg new file mode 100644 index 0000000..97b1f8c --- /dev/null +++ b/public/icons/backends/quad9.svg @@ -0,0 +1 @@ +Quad9 \ No newline at end of file diff --git a/public/icons/backends/redis.svg b/public/icons/backends/redis.svg new file mode 100644 index 0000000..1981b34 --- /dev/null +++ b/public/icons/backends/redis.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/icons/backends/rocksdb.svg b/public/icons/backends/rocksdb.svg new file mode 100644 index 0000000..7fc4e76 --- /dev/null +++ b/public/icons/backends/rocksdb.svg @@ -0,0 +1 @@ +RocksDB \ No newline at end of file diff --git a/public/icons/backends/sqlite.svg b/public/icons/backends/sqlite.svg new file mode 100644 index 0000000..3bfccb8 --- /dev/null +++ b/public/icons/backends/sqlite.svg @@ -0,0 +1 @@ +SQLite \ No newline at end of file diff --git a/public/icons/backends/tencentcloud-color.svg b/public/icons/backends/tencentcloud-color.svg new file mode 100644 index 0000000..4e7d033 --- /dev/null +++ b/public/icons/backends/tencentcloud-color.svg @@ -0,0 +1 @@ +TencentCloud \ No newline at end of file diff --git a/public/icons/backends/valkey.svg b/public/icons/backends/valkey.svg new file mode 100644 index 0000000..81d8d3b --- /dev/null +++ b/public/icons/backends/valkey.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/icons/backends/vercel.svg b/public/icons/backends/vercel.svg new file mode 100644 index 0000000..45ca605 --- /dev/null +++ b/public/icons/backends/vercel.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/icons/backends/vultr.svg b/public/icons/backends/vultr.svg new file mode 100644 index 0000000..b1899a2 --- /dev/null +++ b/public/icons/backends/vultr.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/icons/backends/yandex.svg b/public/icons/backends/yandex.svg new file mode 100644 index 0000000..0f3d997 --- /dev/null +++ b/public/icons/backends/yandex.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/common/BackendIcon.tsx b/src/components/common/BackendIcon.tsx new file mode 100644 index 0000000..c6b7dac --- /dev/null +++ b/src/components/common/BackendIcon.tsx @@ -0,0 +1,69 @@ +/* + * SPDX-FileCopyrightText: 2020 Stalwart Labs LLC + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL + */ + +import React from 'react'; + +const BACKEND_ICONS: Record = { + alibaba: { path: '/icons/backends/alibaba.svg' }, + alibabacloud: { path: '/icons/backends/alibaba.svg' }, + aws: { path: '/icons/backends/aws-light.svg' }, + amazonwebservices: { path: '/icons/backends/aws-light.svg' }, + azure: { path: '/icons/backends/azure.ico', isIco: true }, + baidu: { path: '/icons/backends/baiducloud-color.svg' }, + baiducloud: { path: '/icons/backends/baiducloud-color.svg' }, + bunny: { path: '/icons/backends/bunny.svg' }, + bunnynet: { path: '/icons/backends/bunny.svg' }, + cloudflare: { path: '/icons/backends/cloudflare.svg' }, + digitalocean: { path: '/icons/backends/digital-ocean.svg' }, + dnsimple: { path: '/icons/backends/dnsimple.svg' }, + foundationdb: { path: '/icons/backends/foundationdb.svg' }, + google: { path: '/icons/backends/google.svg' }, + googlecloud: { path: '/icons/backends/google.svg' }, + mariadb: { path: '/icons/backends/mysql.svg' }, + mysql: { path: '/icons/backends/mysql.svg' }, + ovh: { path: '/icons/backends/ovh.svg' }, + porkbun: { path: '/icons/backends/porkbun.png' }, + postgres: { path: '/icons/backends/postgresql.svg' }, + postgresql: { path: '/icons/backends/postgresql.svg' }, + quad9: { path: '/icons/backends/quad9.svg' }, + redis: { path: '/icons/backends/redis.svg' }, + rediscluster: { path: '/icons/backends/redis.svg' }, + redissentinel: { path: '/icons/backends/redis.svg' }, + redisvalkey: { path: '/icons/backends/redis.svg' }, + rocksdb: { path: '/icons/backends/rocksdb.svg' }, + sqlite: { path: '/icons/backends/sqlite.svg' }, + valkey: { path: '/icons/backends/valkey.svg' }, + vercel: { path: '/icons/backends/vercel.svg' }, +}; + +interface BackendIconProps { + backend: string | null | undefined; + className?: string; + fallback?: React.ReactNode; +} + +export function BackendIcon({ backend, className, fallback = null }: BackendIconProps): React.ReactElement | null { + if (!backend) return null; + + const key = backend.toLowerCase().replace(/[^a-z0-9]/g, ''); + const icon = BACKEND_ICONS[key] ?? BACKEND_ICONS[backend.toLowerCase()]; + if (!icon) return fallback as React.ReactElement | null; + + return ( + {`${backend} + ); +} + +export function isBackendIconKnown(backend: string | null | undefined): boolean { + if (!backend) return false; + const key = backend.toLowerCase().replace(/[^a-z0-9]/g, ''); + return Boolean(BACKEND_ICONS[key] ?? BACKEND_ICONS[backend.toLowerCase()]); +} diff --git a/src/components/forms/DynamicForm.tsx b/src/components/forms/DynamicForm.tsx index 469425e..ed49f6a 100644 --- a/src/components/forms/DynamicForm.tsx +++ b/src/components/forms/DynamicForm.tsx @@ -11,7 +11,7 @@ import { useTranslation } from 'react-i18next'; import { Button } from '@/components/ui/button'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Label } from '@/components/ui/label'; -import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; +import { Select, SelectContent, SelectItem, SelectTrigger } from '@/components/ui/select'; import { AlertDialog, AlertDialogAction, @@ -53,6 +53,7 @@ import { SECRET_MASK } from '@/lib/jmapUtils'; import { toast } from '@/hooks/use-toast'; import { logFormChange } from '@/lib/debug'; import { FieldWidget } from '@/components/forms/FieldWidget'; +import { BackendIcon } from '@/components/common/BackendIcon'; import type { Field, Fields, Form, FormField, Schema } from '@/types/schema'; import type { JmapSetResponse, JmapSetError, JmapMethodCall } from '@/types/jmap'; @@ -773,17 +774,26 @@ export function DynamicForm({ viewName, objectId }: DynamicFormProps) { if (!visible) return null; if (formField.name === '@type' && sch.type === 'multiple') { + const selectedVariantLabel = sch.variants.find((v) => v.name === selectedVariant)?.label; return (
- + + + + {selectedVariantLabel || t('form.selectType', 'Select type...')} + + {resolvedSchema.variants.map((v) => ( - {v.label} + + + {v.label} + ))}