mirror of
https://github.com/Portabase/portabase.git
synced 2026-07-14 11:16:13 +02:00
fix: azure form (#341)
This commit is contained in:
@@ -9,53 +9,117 @@ import {
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import { PasswordInput } from "@/components/ui/password-input";
|
||||
import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs";
|
||||
|
||||
type StorageBlobFormProps = {
|
||||
form: UseFormReturn<any, any, any>;
|
||||
};
|
||||
|
||||
export const StorageBlobForm = ({ form }: StorageBlobFormProps) => {
|
||||
const storedMode = form.watch("config.authMode");
|
||||
// Derive mode for legacy records saved before authMode existed: if no
|
||||
// connection string but account credentials are present, open Account Details.
|
||||
const derivedMode: "connectionString" | "accountKey" =
|
||||
!form.watch("config.connectionString") &&
|
||||
(form.watch("config.accountName") || form.watch("config.accountKey"))
|
||||
? "accountKey"
|
||||
: "connectionString";
|
||||
const authMode: "connectionString" | "accountKey" = storedMode ?? derivedMode;
|
||||
|
||||
const handleModeChange = (value: string) => {
|
||||
form.setValue("config.authMode", value, { shouldValidate: false });
|
||||
// Clear errors of the now-inactive mode so stale messages don't linger.
|
||||
if (value === "connectionString") {
|
||||
form.clearErrors(["config.accountName", "config.accountKey"]);
|
||||
} else {
|
||||
form.clearErrors(["config.connectionString"]);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Separator className="my-1" />
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="config.accountName"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Account Name *</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} placeholder="e.g. mystorageaccount" />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="config.accountKey"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Account Key</FormLabel>
|
||||
<FormControl>
|
||||
<PasswordInput {...field} placeholder="e.g. base64-encoded-key" />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="config.connectionString"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Connection String</FormLabel>
|
||||
<FormControl>
|
||||
<PasswordInput {...field} placeholder="e.g. DefaultEndpointsProtocol=https;..." />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<Tabs value={authMode} onValueChange={handleModeChange} className="w-full">
|
||||
<TabsList className="w-full">
|
||||
<TabsTrigger value="connectionString">Connection String</TabsTrigger>
|
||||
<TabsTrigger value="accountKey">Account Details</TabsTrigger>
|
||||
</TabsList>
|
||||
|
||||
<TabsContent value="connectionString" className="flex flex-col gap-3">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="config.connectionString"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Connection String *</FormLabel>
|
||||
<FormControl>
|
||||
<PasswordInput
|
||||
{...field}
|
||||
value={field.value ?? ""}
|
||||
placeholder="e.g. DefaultEndpointsProtocol=https;..."
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="accountKey" className="flex flex-col gap-3">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="config.accountName"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Account Name *</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
{...field}
|
||||
value={field.value ?? ""}
|
||||
placeholder="e.g. mystorageaccount"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="config.accountKey"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Account Key *</FormLabel>
|
||||
<FormControl>
|
||||
<PasswordInput
|
||||
{...field}
|
||||
value={field.value ?? ""}
|
||||
placeholder="e.g. base64-encoded-key"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="config.endpointUrl"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Endpoint URL</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
{...field}
|
||||
value={field.value ?? ""}
|
||||
placeholder="e.g. https://myaccount.blob.core.windows.net"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="config.containerName"
|
||||
@@ -63,20 +127,11 @@ export const StorageBlobForm = ({ form }: StorageBlobFormProps) => {
|
||||
<FormItem>
|
||||
<FormLabel>Container Name *</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} placeholder="e.g. backups-prod" />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="config.endpointUrl"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Endpoint URL</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} placeholder="e.g. https://myaccount.blob.core.windows.net" />
|
||||
<Input
|
||||
{...field}
|
||||
value={field.value ?? ""}
|
||||
placeholder="e.g. backups-prod"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import {z} from "zod";
|
||||
|
||||
export const BlobChannelConfigSchema = z.object({
|
||||
accountName: z.string().min(1, "Account name is required"),
|
||||
authMode: z.enum(["connectionString", "accountKey"]).default("connectionString"),
|
||||
accountName: z.string().optional(),
|
||||
accountKey: z.string().optional(),
|
||||
connectionString: z.string().optional(),
|
||||
containerName: z.string().min(1, "Container name is required"),
|
||||
@@ -9,7 +10,29 @@ export const BlobChannelConfigSchema = z.object({
|
||||
(v) => (v === "" ? undefined : v),
|
||||
z.string().url("Endpoint URL must be a valid URL").optional(),
|
||||
),
|
||||
}).refine(
|
||||
(data) => data.accountKey || data.connectionString,
|
||||
{message: "Either account key or connection string is required"}
|
||||
);
|
||||
}).superRefine((data, ctx) => {
|
||||
if (data.authMode === "connectionString") {
|
||||
if (!data.connectionString) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
path: ["connectionString"],
|
||||
message: "Connection string is required",
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (!data.accountName) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
path: ["accountName"],
|
||||
message: "Account name is required",
|
||||
});
|
||||
}
|
||||
if (!data.accountKey) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
path: ["accountKey"],
|
||||
message: "Account key is required",
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user