aboutsummaryrefslogtreecommitdiffstats
path: root/ui/src/components/runbooks/List.tsx
diff options
context:
space:
mode:
authorEllie Huxtable <ellie@atuin.sh>2024-07-15 19:12:01 +0100
committerGitHub <noreply@github.com>2024-07-15 19:12:01 +0100
commit7eb985b616c12aed261fbef74a47c5a928c03e61 (patch)
treefe3088dc687c640176bf376b4ca8baf2088bd69f /ui/src/components/runbooks/List.tsx
parentchore(deps): bump cachix/install-nix-action from 20 to 27 (#2268) (diff)
downloadatuin-7eb985b616c12aed261fbef74a47c5a928c03e61.zip
feat(gui): add runbook list, ability to create and delete, sql storage (#2282)
* wip * saving works :)) * functioning delete button * persist selection properly
Diffstat (limited to 'ui/src/components/runbooks/List.tsx')
-rw-r--r--ui/src/components/runbooks/List.tsx120
1 files changed, 120 insertions, 0 deletions
diff --git a/ui/src/components/runbooks/List.tsx b/ui/src/components/runbooks/List.tsx
new file mode 100644
index 00000000..be6e84f5
--- /dev/null
+++ b/ui/src/components/runbooks/List.tsx
@@ -0,0 +1,120 @@
+import { useEffect, useState } from "react";
+import {
+ Input,
+ Button,
+ ButtonGroup,
+ Card,
+ CardBody,
+ CardHeader,
+ Divider,
+ Tooltip,
+ Listbox,
+ ListboxItem,
+ Dropdown,
+ DropdownTrigger,
+ DropdownMenu,
+ DropdownItem,
+} from "@nextui-org/react";
+
+import { EllipsisVerticalIcon } from "lucide-react";
+
+import { DateTime } from "luxon";
+
+import { NotebookPenIcon } from "lucide-react";
+import Runbook from "@/state/runbooks/runbook";
+import { useStore } from "@/state/store";
+
+const NoteSidebar = () => {
+ const runbooks = useStore((state) => state.runbooks);
+ const refreshRunbooks = useStore((state) => state.refreshRunbooks);
+
+ const currentRunbook = useStore((state) => state.currentRunbook);
+ const setCurrentRunbook = useStore((state) => state.setCurrentRunbook);
+
+ useEffect(() => {
+ refreshRunbooks();
+ }, []);
+
+ return (
+ <div className="min-w-48 h-screen flex flex-col border-r-1">
+ <div className="overflow-y-auto flex-grow">
+ <Listbox
+ hideSelectedIcon
+ items={runbooks}
+ variant="flat"
+ aria-label="Runbook list"
+ selectionMode="single"
+ selectedKeys={[currentRunbook]}
+ itemClasses={{ base: "data-[selected=true]:bg-gray-200" }}
+ topContent={
+ <ButtonGroup>
+ <Tooltip showArrow content="New Runbook" closeDelay={50}>
+ <Button
+ isIconOnly
+ aria-label="New note"
+ variant="light"
+ size="sm"
+ onPress={async () => {
+ let runbook = await Runbook.create();
+ setCurrentRunbook(runbook.id);
+ refreshRunbooks();
+ }}
+ >
+ <NotebookPenIcon className="p-[0.15rem]" />
+ </Button>
+ </Tooltip>
+ </ButtonGroup>
+ }
+ >
+ {(runbook) => (
+ <ListboxItem
+ key={runbook.id}
+ onPress={() => {
+ setCurrentRunbook(runbook.id);
+ }}
+ textValue={runbook.name || "Untitled"}
+ endContent={
+ <Dropdown>
+ <DropdownTrigger className="bg-transparent">
+ <Button isIconOnly>
+ <EllipsisVerticalIcon
+ size="16px"
+ className="bg-transparent"
+ />
+ </Button>
+ </DropdownTrigger>
+ <DropdownMenu aria-label="Dynamic Actions">
+ <DropdownItem
+ key={"delete"}
+ color="danger"
+ className="text-danger"
+ onPress={async () => {
+ await Runbook.delete(runbook.id);
+ refreshRunbooks();
+ }}
+ >
+ Delete
+ </DropdownItem>
+ </DropdownMenu>
+ </Dropdown>
+ }
+ >
+ <div className="flex flex-col">
+ <div className="text-md">{runbook.name || "Untitled"}</div>
+ <div className="text-xs text-gray-500">
+ <em>
+ {DateTime.fromJSDate(runbook.updated).toLocaleString(
+ DateTime.DATETIME_SIMPLE,
+ )}
+ </em>
+ </div>
+ </div>
+ </ListboxItem>
+ )}
+ </Listbox>
+ </div>
+ </div>
+ );
+};
+
+export default NoteSidebar;