feat: update bucket types and management logic for website access and quotas

- Refactored `Bucket` and `UpdateBucket` types to include detailed website configuration and quota properties.
- Updated hooks to utilize the new `UpdateBucket` type for mutation functions.
- Adjusted form schemas and management logic to reflect changes in website access and quota handling.
- Enhanced default values and reset logic in forms for better user experience.
This commit is contained in:
Adekabang 2025-07-31 15:42:59 -04:00
parent 6528cb759c
commit 621761aeb6
5 changed files with 89 additions and 43 deletions

View File

@ -5,7 +5,7 @@ import {
UseMutationOptions,
useQuery,
} from "@tanstack/react-query";
import { Bucket, Permissions } from "../types";
import { Bucket, Permissions, UpdateBucket } from "../types";
export const useBucket = (id?: string | null) => {
return useQuery({
@ -17,8 +17,11 @@ export const useBucket = (id?: string | null) => {
export const useUpdateBucket = (id?: string | null) => {
return useMutation({
mutationFn: (values: Partial<Bucket>) => {
return api.put<Bucket>("/v2/UpdateBucket", { params: { id }, body: values });
mutationFn: (values: Partial<UpdateBucket>) => {
return api.post<Bucket>("/v2/UpdateBucket", {
params: { id },
body: values,
});
},
});
};

View File

@ -13,35 +13,48 @@ const QuotaSection = () => {
const form = useForm<QuotaSchema>({
resolver: zodResolver(quotaSchema),
defaultValues: {
enabled: false,
maxObjects: null,
maxSize: null,
},
});
const isEnabled = useWatch({ control: form.control, name: "enabled" });
const updateMutation = useUpdateBucket(data?.id);
const onChange = useDebounce((values: DeepPartial<QuotaSchema>) => {
const handleChange = useDebounce((values: DeepPartial<QuotaSchema>) => {
const { enabled } = values;
const maxObjects = Number(values.maxObjects);
const maxSize = Math.round(Number(values.maxSize) * 1024 ** 3);
const data = {
const quotaData = {
maxObjects: enabled && maxObjects > 0 ? maxObjects : null,
maxSize: enabled && maxSize > 0 ? maxSize : null,
};
updateMutation.mutate({ quotas: data });
updateMutation.mutate({ quotas: quotaData });
});
// Reset form when data changes without triggering watch
useEffect(() => {
form.reset({
enabled:
data?.quotas?.maxSize != null || data?.quotas?.maxObjects != null,
maxSize: data?.quotas?.maxSize ? data?.quotas?.maxSize / 1024 ** 3 : null,
maxObjects: data?.quotas?.maxObjects || null,
});
if (!data) return;
const { unsubscribe } = form.watch((values) => onChange(values));
return unsubscribe;
}, [data]);
const formValues = {
enabled:
data.quotas?.maxSize != null || data.quotas?.maxObjects != null,
maxSize: data.quotas?.maxSize ? data.quotas?.maxSize / 1024 ** 3 : null,
maxObjects: data.quotas?.maxObjects || null,
};
form.reset(formValues, { keepDirty: false });
}, [data, form]);
// Set up form watcher
useEffect(() => {
const subscription = form.watch(handleChange);
return () => subscription.unsubscribe();
}, [form, handleChange]);
return (
<div className="mt-8">

View File

@ -16,6 +16,11 @@ const WebsiteAccessSection = () => {
const { data: config } = useConfig();
const form = useForm<WebsiteConfigSchema>({
resolver: zodResolver(websiteConfigSchema),
defaultValues: {
websiteAccess: false,
indexDocument: "index.html",
errorDocument: "error/400.html",
},
});
const isEnabled = useWatch({ control: form.control, name: "websiteAccess" });
@ -24,38 +29,46 @@ const WebsiteAccessSection = () => {
const updateMutation = useUpdateBucket(data?.id);
const onChange = useDebounce((values: DeepPartial<WebsiteConfigSchema>) => {
const handleChange = useDebounce((values: DeepPartial<WebsiteConfigSchema>) => {
const websiteData = {
enabled: values.websiteAccess,
indexDocument: values.websiteAccess
? values.websiteConfig?.indexDocument
? values.indexDocument
: undefined,
errorDocument: values.websiteAccess
? values.websiteConfig?.errorDocument
? values.errorDocument
: undefined,
};
updateMutation.mutate({
websiteAccess: values.websiteAccess,
websiteConfig: values.websiteAccess && websiteData.indexDocument && websiteData.errorDocument ? {
indexDocument: websiteData.indexDocument,
errorDocument: websiteData.errorDocument,
} : null,
websiteAccess: {
enabled: values.websiteAccess ?? false,
indexDocument: values.websiteAccess
? websiteData.indexDocument ?? "index.html"
: null,
errorDocument: values.websiteAccess
? websiteData.errorDocument ?? "error/400.html"
: null,
}
});
});
// Reset form when data changes without triggering watch
useEffect(() => {
if (!data) return;
form.reset({
websiteAccess: data?.websiteAccess,
websiteConfig: {
websiteAccess: data?.websiteAccess ?? false,
indexDocument: data?.websiteConfig?.indexDocument || "index.html",
errorDocument: data?.websiteConfig?.errorDocument || "error/400.html",
},
});
}, { keepDirty: false });
}, [data, form]);
const { unsubscribe } = form.watch((values) => onChange(values));
return unsubscribe;
}, [data, form, onChange]);
// Set up form watcher
useEffect(() => {
const subscription = form.watch(handleChange);
return () => subscription.unsubscribe();
}, [form, handleChange]);
return (
<div className="mt-8">
@ -79,12 +92,12 @@ const WebsiteAccessSection = () => {
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<InputField
form={form}
name="websiteConfig.indexDocument"
name="indexDocument"
title="Index Document"
/>
<InputField
form={form}
name="websiteConfig.errorDocument"
name="errorDocument"
title="Error Document"
/>
</div>

View File

@ -8,9 +8,8 @@ export type AddAliasSchema = z.infer<typeof addAliasSchema>;
export const websiteConfigSchema = z.object({
websiteAccess: z.boolean(),
websiteConfig: z
.object({ indexDocument: z.string(), errorDocument: z.string() })
.nullish(),
indexDocument: z.string().nullish(),
errorDocument: z.string().nullish(),
});
export type WebsiteConfigSchema = z.infer<typeof websiteConfigSchema>;

View File

@ -7,7 +7,29 @@ export type Bucket = {
globalAliases: string[];
localAliases: LocalAlias[];
websiteAccess: boolean;
websiteConfig?: WebsiteConfig | null;
websiteConfig: {
indexDocument: string | null;
errorDocument: string | null;
};
keys: Key[];
objects: number;
bytes: number;
unfinishedUploads: number;
unfinishedMultipartUploads: number;
unfinishedMultipartUploadParts: number;
unfinishedMultipartUploadBytes: number;
quotas: Quotas;
};
export type UpdateBucket = {
id: string;
globalAliases: string[];
localAliases: LocalAlias[];
websiteAccess: {
enabled: boolean;
indexDocument: string | null;
errorDocument: string | null;
};
keys: Key[];
objects: number;
bytes: number;
@ -36,10 +58,6 @@ export type Permissions = {
owner: boolean;
};
export type WebsiteConfig = {
indexDocument: string;
errorDocument: string;
};
export type Quotas = {
maxSize: number | null;