feat: fix responsive layout, add theme switcher

This commit is contained in:
2024-08-17 00:21:23 +07:00
parent 43af9c8658
commit f503b261f5
22 changed files with 349 additions and 100 deletions
@@ -27,7 +27,7 @@ const MenuButton = () => {
return (
<Dropdown end>
<Dropdown.Toggle button={false}>
<Button icon={EllipsisVertical} />
<Button icon={EllipsisVertical} color="ghost" />
</Dropdown.Toggle>
<Dropdown.Menu>
@@ -1,32 +1,111 @@
import { Button } from "react-daisyui";
import { Modal } from "react-daisyui";
import { Plus } from "lucide-react";
import Chips from "@/components/ui/chips";
import { Bucket } from "../../types";
import { useDisclosure } from "@/hooks/useDisclosure";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { AddAliasSchema, addAliasSchema } from "../schema";
import Button from "@/components/ui/button";
import { useAddAlias, useRemoveAlias } from "../hooks";
import { toast } from "sonner";
import { handleError } from "@/lib/utils";
import { InputField } from "@/components/ui/input";
import { useEffect } from "react";
import { useQueryClient } from "@tanstack/react-query";
type Props = {
data?: Bucket;
};
const AliasesSection = ({ data }: Props) => {
const aliases = data?.globalAliases?.slice(1);
const queryClient = useQueryClient();
const removeAlias = useRemoveAlias(data?.id, {
onSuccess: () => {
toast.success("Alias removed!");
queryClient.invalidateQueries({ queryKey: ["bucket", data?.id] });
},
onError: handleError,
});
const onRemoveAlias = (alias: string) => {
if (window.confirm("Are you sure you want to remove this alias?")) {
removeAlias.mutate(alias);
}
};
const aliases = data?.globalAliases || [];
return (
<div className="mt-2">
<p className="inline label label-text">Aliases</p>
<div className="flex flex-row flex-wrap gap-2 mt-1">
{aliases?.map((alias: string) => (
<Chips key={alias} onRemove={() => {}}>
<div className="flex flex-row flex-wrap gap-2 mt-2">
{aliases.map((alias: string) => (
<Chips key={alias} onRemove={() => onRemoveAlias(alias)}>
{alias}
</Chips>
))}
<Button size="sm">
<Plus className="-ml-1" size={18} />
Add Alias
</Button>
<AddAliasDialog id={data?.id} />
</div>
</div>
);
};
const AddAliasDialog = ({ id }: { id?: string }) => {
const { dialogRef, isOpen, onOpen, onClose } = useDisclosure();
const form = useForm<AddAliasSchema>({
resolver: zodResolver(addAliasSchema),
defaultValues: { alias: "" },
});
const queryClient = useQueryClient();
useEffect(() => {
if (isOpen) form.setFocus("alias");
}, [isOpen]);
const addAlias = useAddAlias(id, {
onSuccess: () => {
form.reset();
onClose();
toast.success("Alias added!");
queryClient.invalidateQueries({ queryKey: ["bucket", id] });
},
onError: handleError,
});
const onSubmit = form.handleSubmit((values) => {
addAlias.mutate(values.alias);
});
return (
<>
<Button size="sm" onClick={onOpen} icon={Plus}>
Add Alias
</Button>
<Modal ref={dialogRef} open={isOpen}>
<Modal.Header>Add Alias</Modal.Header>
<Modal.Body>
<form onSubmit={onSubmit}>
<InputField form={form} name="alias" title="Name" />
</form>
</Modal.Body>
<Modal.Actions>
<Button onClick={onClose}>Cancel</Button>
<Button
color="primary"
onClick={onSubmit}
disabled={addAlias.isPending}
>
Submit
</Button>
</Modal.Actions>
</Modal>
</>
);
};
export default AliasesSection;
@@ -1,12 +1,12 @@
import { Controller, DeepPartial, useForm, useWatch } from "react-hook-form";
import { DeepPartial, useForm, useWatch } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { QuotaSchema, quotaSchema } from "../schema";
import { useEffect } from "react";
import { Input, Toggle } from "react-daisyui";
import FormControl from "@/components/ui/form-control";
import { useDebounce } from "@/hooks/useDebounce";
import { useUpdateBucket } from "../hooks";
import { Bucket } from "../../types";
import { InputField } from "@/components/ui/input";
import { ToggleField } from "@/components/ui/toggle";
type Props = {
data?: Bucket;
@@ -49,44 +49,22 @@ const QuotaSection = ({ data }: Props) => {
return (
<div className="mt-8">
<p className="label label-text py-0">Quotas</p>
<label className="inline-flex label label-text gap-2 cursor-pointer">
<Controller
control={form.control}
name="enabled"
render={({ field }) => (
<Toggle {...(field as any)} checked={field.value} />
)}
/>
Enabled
</label>
<ToggleField form={form} name="enabled" title="Quotas" label="Enabled" />
{isEnabled && (
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<FormControl
<InputField
form={form}
name="maxObjects"
title="Max Objects"
render={(field) => (
<Input
{...field}
type="number"
value={String(field.value || "")}
/>
)}
type="number"
/>
<FormControl
<InputField
form={form}
name="maxSize"
title="Max Size (GB)"
render={(field) => (
<Input
{...field}
type="number"
value={String(field.value || "")}
/>
)}
type="number"
/>
</div>
)}
@@ -1,15 +1,15 @@
import { Controller, DeepPartial, useForm, useWatch } from "react-hook-form";
import { DeepPartial, useForm, useWatch } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { websiteConfigSchema, WebsiteConfigSchema } from "../schema";
import { useEffect } from "react";
import { Input, Toggle } from "react-daisyui";
import FormControl from "@/components/ui/form-control";
import { useDebounce } from "@/hooks/useDebounce";
import { useUpdateBucket } from "../hooks";
import { useConfig } from "@/hooks/useConfig";
import { Info, LinkIcon } from "lucide-react";
import Button from "@/components/ui/button";
import { Bucket } from "../../types";
import { InputField } from "@/components/ui/input";
import { ToggleField } from "@/components/ui/toggle";
type Props = {
data?: Bucket;
@@ -72,39 +72,24 @@ const WebsiteAccessSection = ({ data }: Props) => {
</Button>
</div>
<label className="inline-flex label label-text gap-2 cursor-pointer">
<Controller
control={form.control}
name="websiteAccess"
render={({ field }) => (
<Toggle {...(field as any)} checked={field.value} />
)}
/>
Enabled
</label>
<ToggleField form={form} name="websiteAccess" label="Enabled" />
{isEnabled && (
<>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<FormControl
<InputField
form={form}
name="websiteConfig.indexDocument"
title="Index Document"
render={(field) => (
<Input {...field} value={String(field.value || "")} />
)}
/>
<FormControl
<InputField
form={form}
name="websiteConfig.errorDocument"
title="Error Document"
render={(field) => (
<Input {...field} value={String(field.value || "")} />
)}
/>
</div>
<div className="mt-4 alert flex flex-row flex-wrap">
<div className="mt-4 alert flex flex-row flex-wrap text-sm gap-x-2 gap-y-1">
<a
href={`http://${bucketName}`}
className="inline-flex items-center flex-row gap-2 font-medium hover:link"