feat: add keys & bucket permissions management

This commit is contained in:
2024-08-16 23:10:19 +07:00
parent dfb4e30e23
commit 43af9c8658
30 changed files with 948 additions and 53 deletions
+37 -20
View File
@@ -1,8 +1,23 @@
import { Cylinder, HardDrive, LayoutDashboard } from "lucide-react";
import { cn } from "@/lib/utils";
import {
ArchiveIcon,
HardDrive,
KeySquare,
LayoutDashboard,
} from "lucide-react";
import { Menu } from "react-daisyui";
import { Link } from "react-router-dom";
import { Link, useLocation } from "react-router-dom";
const pages = [
{ icon: LayoutDashboard, title: "Dashboard", path: "/", exact: true },
{ icon: HardDrive, title: "Cluster", path: "/cluster" },
{ icon: ArchiveIcon, title: "Buckets", path: "/buckets" },
{ icon: KeySquare, title: "Keys", path: "/keys" },
];
const Sidebar = () => {
const { pathname } = useLocation();
return (
<aside className="bg-base-100 border-r border-base-300/30 w-[220px] overflow-y-auto">
<div className="p-4">
@@ -14,24 +29,26 @@ const Sidebar = () => {
<p className="text-sm font-medium text-center">WebUI</p>
</div>
<Menu className="gap-y-1">
<Menu.Item>
<Link to="/">
<LayoutDashboard />
<p>Dashboard</p>
</Link>
</Menu.Item>
<Menu.Item>
<Link to="/cluster">
<HardDrive />
<p>Cluster</p>
</Link>
</Menu.Item>
<Menu.Item>
<Link to="/buckets">
<Cylinder />
<p>Buckets</p>
</Link>
</Menu.Item>
{pages.map((page) => {
const isActive = page.exact
? pathname === page.path
: pathname.startsWith(page.path);
return (
<Menu.Item key={page.path}>
<Link
to={page.path}
className={cn(
"h-12 flex items-center px-6",
isActive &&
"bg-primary text-primary-content hover:bg-primary/60 focus:bg-primary"
)}
>
<page.icon size={18} />
<p>{page.title}</p>
</Link>
</Menu.Item>
);
})}
</Menu>
</aside>
);
+4 -1
View File
@@ -40,7 +40,10 @@ const Header = () => {
<ArrowLeft />
</Button>
) : null}
<h1 className="text-xl">{page?.title || "Dashboard"}</h1>
<h1 className="text-xl flex-1 truncate">{page?.title || "Dashboard"}</h1>
{page?.actions}
</header>
);
};
+8 -2
View File
@@ -1,3 +1,4 @@
import { LucideIcon } from "lucide-react";
import { ComponentPropsWithoutRef, forwardRef } from "react";
import { Button as BaseButton } from "react-daisyui";
import { Link } from "react-router-dom";
@@ -5,17 +6,22 @@ import { Link } from "react-router-dom";
type ButtonProps = ComponentPropsWithoutRef<typeof BaseButton> & {
href?: string;
target?: "_blank" | "_self" | "_parent" | "_top";
icon?: LucideIcon;
};
const Button = forwardRef<HTMLButtonElement, ButtonProps>(
({ href, ...props }, ref) => {
({ href, children, icon: Icon, shape, ...props }, ref) => {
return (
<BaseButton
ref={ref}
tag={href ? Link : undefined}
shape={Icon && !children ? "circle" : shape}
{...props}
{...(href ? { to: href } : {})}
/>
>
{Icon ? <Icon size={18} className={children ? "-ml-1" : ""} /> : null}
{children}
</BaseButton>
);
}
);
+64
View File
@@ -0,0 +1,64 @@
import { cn } from "@/lib/utils";
import React, { forwardRef } from "react";
import { Checkbox as BaseCheckbox } from "react-daisyui";
import FormControl from "./form-control";
import { FieldValues } from "react-hook-form";
type CheckboxProps = Omit<
React.ComponentPropsWithoutRef<typeof BaseCheckbox>,
"form"
> & {
label?: string;
inputClassName?: string;
};
const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(
({ label, className, inputClassName, ...props }, ref) => {
return (
<label
className={cn(
"label label-text inline-flex items-center justify-start gap-2 cursor-pointer",
className
)}
>
<BaseCheckbox
ref={ref}
color="primary"
size="sm"
className={inputClassName}
{...props}
/>
{label}
</label>
);
}
);
type CheckboxFieldProps<T extends FieldValues> = Omit<
React.ComponentPropsWithoutRef<typeof FormControl<T>>,
"render"
> &
CheckboxProps;
export const CheckboxField = <T extends FieldValues>({
form,
name,
...props
}: CheckboxFieldProps<T>) => {
return (
<FormControl
form={form}
name={name}
render={(field) => (
<Checkbox
{...props}
{...field}
checked={field.value}
onChange={(e) => field.onChange(e.target.checked)}
/>
)}
/>
);
};
export default Checkbox;
+44
View File
@@ -0,0 +1,44 @@
import React, { forwardRef } from "react";
import { Input as BaseInput } from "react-daisyui";
import FormControl from "./form-control";
import { FieldValues } from "react-hook-form";
type InputProps = Omit<
React.ComponentPropsWithoutRef<typeof BaseInput>,
"form"
>;
const Input = forwardRef<HTMLInputElement, InputProps>(({ ...props }, ref) => {
return <BaseInput ref={ref} {...props} />;
});
type InputFieldProps<T extends FieldValues> = Omit<
React.ComponentPropsWithoutRef<typeof FormControl<T>>,
"render"
> &
InputProps & {
inputClassName?: string;
};
export const InputField = <T extends FieldValues>({
form,
name,
title,
className,
inputClassName,
...props
}: InputFieldProps<T>) => {
return (
<FormControl
form={form}
name={name}
title={title}
className={className}
render={(field) => (
<Input {...props} {...field} className={inputClassName} />
)}
/>
);
};
export default Input;