From 59b09e580e896770c96974c048ae8e1e8c2fb2d3 Mon Sep 17 00:00:00 2001 From: mbecker20 Date: Sun, 24 Mar 2024 17:33:09 -0700 Subject: [PATCH] api key page --- frontend/src/components/layouts.tsx | 1 + frontend/src/components/updates/header.tsx | 5 +- frontend/src/components/updates/resource.tsx | 4 +- frontend/src/components/util.tsx | 81 +++++++++++++++----- frontend/src/lib/utils.ts | 2 +- frontend/src/pages/keys.tsx | 71 +++++++++++++++++ frontend/src/router.tsx | 2 + 7 files changed, 141 insertions(+), 25 deletions(-) create mode 100644 frontend/src/pages/keys.tsx diff --git a/frontend/src/components/layouts.tsx b/frontend/src/components/layouts.tsx index 7e60bfcb8..b612ff6d1 100644 --- a/frontend/src/components/layouts.tsx +++ b/frontend/src/components/layouts.tsx @@ -50,6 +50,7 @@ export const Layout = () => { + {/* */} diff --git a/frontend/src/components/updates/header.tsx b/frontend/src/components/updates/header.tsx index aa457e526..9e1bdf3b7 100644 --- a/frontend/src/components/updates/header.tsx +++ b/frontend/src/components/updates/header.tsx @@ -10,12 +10,9 @@ import { Button } from "@ui/button"; import { Calendar, User } from "lucide-react"; import { UpdateDetails, UpdateUser } from "./details"; import { ResourceComponents } from "@components/resources"; -import { cn, fmt_version } from "@lib/utils"; +import { cn, fmt_date, fmt_version } from "@lib/utils"; import { Types } from "@monitor/client"; -const fmt_date = (d: Date) => - `${d.getDate()}/${d.getMonth() + 1} @ ${d.getHours()}:${d.getMinutes()}`; - export const SingleUpdate = ({ update }: { update: Types.UpdateListItem }) => { const Components = update.target.type !== "System" diff --git a/frontend/src/components/updates/resource.tsx b/frontend/src/components/updates/resource.tsx index 37cf4bda9..699a2c5aa 100644 --- a/frontend/src/components/updates/resource.tsx +++ b/frontend/src/components/updates/resource.tsx @@ -13,7 +13,7 @@ import { import { Link } from "react-router-dom"; import { Types } from "@monitor/client"; import { Section } from "@components/layouts"; -import { fmt_update_date, fmt_version } from "@lib/utils"; +import { fmt_date, fmt_version } from "@lib/utils"; import { UpdateDetails, UpdateUser } from "./details"; import { UpdateStatus } from "@monitor/client/dist/types"; @@ -57,7 +57,7 @@ const UpdateCard = ({ update }: { update: Types.UpdateListItem }) => {
- {fmt_update_date(new Date(update.start_ts))} + {fmt_date(new Date(update.start_ts))}
diff --git a/frontend/src/components/util.tsx b/frontend/src/components/util.tsx index 86ad0d9bd..6786616d4 100644 --- a/frontend/src/components/util.tsx +++ b/frontend/src/components/util.tsx @@ -7,7 +7,9 @@ import { Loader2, LogOut, Moon, + Settings, SunMedium, + User, } from "lucide-react"; import { Input } from "../ui/input"; import { @@ -35,7 +37,6 @@ import { DropdownMenuTrigger, } from "@ui/dropdown-menu"; import { ResourceComponents } from "./resources"; -import { WsStatusIndicator } from "@lib/socket"; export const WithLoading = ({ children, @@ -95,6 +96,16 @@ export const ThemeToggle = () => { export const ActionButton = forwardRef< HTMLButtonElement, { + variant?: + | "link" + | "default" + | "destructive" + | "outline" + | "secondary" + | "ghost" + | null + | undefined; + size?: "default" | "sm" | "lg" | "icon" | null | undefined; title: string; icon: ReactNode; disabled?: boolean; @@ -102,17 +113,23 @@ export const ActionButton = forwardRef< onClick?: () => void; loading?: boolean; } ->(({ title, icon, disabled, className, loading, onClick }, ref) => ( - -)); +>( + ( + { variant, size, title, icon, disabled, className, loading, onClick }, + ref + ) => ( + + ) +); export const ActionWithDialog = ({ name, @@ -235,12 +252,24 @@ export const CopyResource = ({ }; export const ConfirmButton = ({ + variant, + size, title, icon, disabled, loading, onClick, }: { + variant?: + | "link" + | "default" + | "destructive" + | "outline" + | "secondary" + | "ghost" + | null + | undefined; + size?: "default" | "sm" | "lg" | "icon" | null | undefined; title: string; icon: ReactNode; onClick: () => void; @@ -252,6 +281,8 @@ export const ConfirmButton = ({ return ( <> : icon} disabled={disabled} @@ -309,6 +340,12 @@ export const ResourceTypeDropdown = () => { ); })} + + + + Api Keys + + @@ -374,18 +411,26 @@ export const Logout = () => ( ); -export const UserDropdown = () => { - const user = useRead("GetUser", {}).data; +export const UserSettings = () => ( + + + +); +export const UserDropdown = () => { + // const user = useRead("GetUser", {}).data; return ( - - + + + ); }; diff --git a/frontend/src/lib/utils.ts b/frontend/src/lib/utils.ts index 56f344ab3..5715944aa 100644 --- a/frontend/src/lib/utils.ts +++ b/frontend/src/lib/utils.ts @@ -20,7 +20,7 @@ export const RESOURCE_TARGETS: UsableResource[] = [ "Procedure", ]; -export const fmt_update_date = (d: Date) => { +export const fmt_date = (d: Date) => { return `${d.getDate()}/${d.getMonth() + 1} @ ${d.getHours()}:${d.getMinutes()}`; }; diff --git a/frontend/src/pages/keys.tsx b/frontend/src/pages/keys.tsx new file mode 100644 index 000000000..71371f7cd --- /dev/null +++ b/frontend/src/pages/keys.tsx @@ -0,0 +1,71 @@ +import { Page, Section } from "@components/layouts"; +import { ConfirmButton } from "@components/util"; +import { useInvalidate, useRead, useWrite } from "@lib/hooks"; +import { fmt_date } from "@lib/utils"; +import { + Card, + CardContent, + CardHeader, + CardTitle, +} from "@ui/card"; +import { useToast } from "@ui/use-toast"; +import { Key, Trash } from "lucide-react"; + +export const Keys = () => { + return ( + + + + ); +}; + +export const ApiKeysList = () => { + const keys = useRead("ListApiKeys", {}).data; + return ( +
}> +
+ {keys?.map((key) => ( + + + {key.name} + + + +
created at: {fmt_date(new Date(key.created_at))}
+
+ expires:{" "} + {key.expires === 0 ? "never" : fmt_date(new Date(key.expires))} +
+
{key.key}
+
+
+ ))} +
+
+ ); +}; + +const DeleteKey = ({ api_key }: { api_key: string }) => { + const invalidate = useInvalidate(); + const { toast } = useToast(); + const { mutate, isPending } = useWrite("DeleteApiKey", { + onSuccess: () => { + invalidate(["ListApiKeys"]); + toast({ title: "Api Key Deleted" }); + }, + onError: () => { + toast({ title: "Failed to delte api key", }) + } + }); + return ( + } + onClick={() => mutate({ key: api_key })} + loading={isPending} + /> + ); +}; diff --git a/frontend/src/router.tsx b/frontend/src/router.tsx index 6efaecc6e..67bbceeb7 100644 --- a/frontend/src/router.tsx +++ b/frontend/src/router.tsx @@ -4,6 +4,7 @@ import { Dashboard } from "@pages/dashboard"; import { Login } from "@pages/login"; import { Resource } from "@pages/resource"; import { Resources } from "@pages/resources"; +import { Keys } from "@pages/keys"; import { RouterProvider, createBrowserRouter } from "react-router-dom"; const router = createBrowserRouter([ @@ -12,6 +13,7 @@ const router = createBrowserRouter([ element: , children: [ { path: "", element: }, + { path: "keys", element: }, { path: ":type", children: [