fix: azure form (#341)

This commit is contained in:
Charles GTE
2026-06-27 20:52:43 +02:00
committed by GitHub
parent 8f44071069
commit f70d86f394
2 changed files with 136 additions and 58 deletions
@@ -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",
});
}
}
});