diff --git a/frontend/src/app/databases/[databaseId]/database-details.tsx b/frontend/src/app/databases/[databaseId]/database-details.tsx new file mode 100644 index 0000000..56d5fff --- /dev/null +++ b/frontend/src/app/databases/[databaseId]/database-details.tsx @@ -0,0 +1,121 @@ +"use client"; +import { + Button, + Divider, + H6, + Icon, + IconName, + InputGroup, + MenuItem, + Text, + TextArea, +} from "@blueprintjs/core"; +import { Select } from "@blueprintjs/select"; +import Loading from "@/app/loading"; +import { ErrorDisplay } from "@/components/error-display"; +import ColorPicker from "@/components/color-picker"; +import IconPicker from "@/components/icon-picker"; +import { useState } from "react"; +import { useField } from "@/utils/use-field"; +import * as _ from "lodash"; +import { CleanDatabase, UpdateDatabaseSchema } from "@/definitions"; +import { useUpdateDatabase } from "@/data/use-database"; + +const DatabaseDetails = ({ database }: { database: CleanDatabase }) => { + const [editDetails, setEditDetails] = useState(false); + const nameField = useField(database.name); + + const { trigger: updateDatabase, isMutating } = useUpdateDatabase( + database.id, + ); + + function resetFields() { + nameField.onValueChange(database.name); + } + + function isValidDatabaseUpdate() { + const result = UpdateDatabaseSchema.safeParse({ + name: !nameField.value ? undefined : nameField.value, + }); + return result.success; + } + + async function handleUpdateDatabase() { + const pendingUpdate = { + name: nameField.value, + }; + const parsedUpdate = UpdateDatabaseSchema.parse(pendingUpdate); + await updateDatabase(parsedUpdate); + setEditDetails(false); + } + + function renderDatabaseDetails() { + return ( + <> +
+
Database Details
+
+
+
+ Name + {database.name} +
+
+ + ); + } + + function renderEditableDetails() { + return ( + <> +
Database Details
+ {isMutating ? ( + + ) : ( +
+
+ Name + +
+
+
+
+ )} + + ); + } + + return ( +
+ {editDetails ? renderEditableDetails() : renderDatabaseDetails()} +
+ ); +}; + +export default DatabaseDetails; diff --git a/frontend/src/app/databases/[databaseId]/delete-database.tsx b/frontend/src/app/databases/[databaseId]/delete-database.tsx new file mode 100644 index 0000000..51f7b10 --- /dev/null +++ b/frontend/src/app/databases/[databaseId]/delete-database.tsx @@ -0,0 +1,93 @@ +import { useField } from "@/utils/use-field"; +import { useRouter } from "next/navigation"; +import { + Button, + Dialog, + DialogBody, + DialogFooter, + Divider, + Callout, + FormGroup, + InputGroup, + Spinner, + SpinnerSize, + Text, +} from "@blueprintjs/core"; +import { useState } from "react"; +import { useSWRConfig } from "swr"; +import { useDeleteDatabase } from "@/data/use-database"; + +export default function DeleteDatabase({ database, onClose }: any) { + const router = useRouter(); + const { mutate } = useSWRConfig(); + const [isOpen, setIsOpen] = useState(true); + const [isSubmitting, setIsSubmitting] = useState(false); + + const { isMutating, trigger: deleteDatabase } = useDeleteDatabase( + database.id, + ); + + const confirmField = useField(""); + + async function submitDelete() { + setIsOpen(false); + setIsSubmitting(true); + await deleteDatabase(); + mutate(`/databases`); + setIsSubmitting(false); + onClose(false); + router.push(`/databases`); + } + + return ( + <> + + + + + + { + onClose(false); + }} + > + +
+ Name: + {database.name} +
+ + + + To confirm deletion, please type the database name in the field + below before clicking submit. + + + + +
+ submitDelete()} + /> + } + /> +
+ + ); +} diff --git a/frontend/src/app/databases/[databaseId]/page.tsx b/frontend/src/app/databases/[databaseId]/page.tsx new file mode 100644 index 0000000..119b1a5 --- /dev/null +++ b/frontend/src/app/databases/[databaseId]/page.tsx @@ -0,0 +1,122 @@ +"use client"; +import { + Button, + IconName, + Menu, + MenuItem, + Popover, + Section, + Tab, + Tabs, + Tooltip, + H4, +} from "@blueprintjs/core"; +import Loading from "@/app/loading"; +import { ErrorDisplay } from "@/components/error-display"; +import SquareIcon, { SquareIconSize } from "@/components/icon/square-icon"; +import DatabaseDetails from "./database-details"; +import React, { useState } from "react"; +import * as _ from "lodash"; +import DeleteDatabase from "./delete-database"; +import { useDatabase } from "@/data/use-database"; + +enum DatabaseTabEnum { + DETAILS = "DETAILS", +} + +export default function Page({ params }: { params: { databaseId: string } }) { + const [currentTab, setCurrentTab] = useState( + DatabaseTabEnum.DETAILS, + ); + const [deleteDatabaseOpen, setDeleteDatabaseOpen] = useState(false); + //const hasPermissionEditOntology = useUserPermission(ONTOLOGY_EDIT_PERMISSION); + + const { + data: database, + isLoading: isLoadingDatabase, + error: databaseError, + } = useDatabase(params.databaseId); + + if (isLoadingDatabase) { + return ; + } + + if (databaseError || !database) { + console.log("Database error", databaseError); + return ( + + ); + } + + function renderRightElement() { + return ( +
+ setCurrentTab(tabId)} + > + + } + /> + + + setDeleteDatabaseOpen(true)} + /> + + } + > +
+ ); + } + + function renderObjectContent() { + switch (currentTab) { + default: + return ; + } + } + + return ( +
+ } + title={

{database!.name}

} + subtitle={database?.created_at.toString().split("T")[0]} + rightElement={renderRightElement()} + > + {renderObjectContent()} + {deleteDatabaseOpen && ( + + )} +
+ ); +} diff --git a/frontend/src/data/use-database.ts b/frontend/src/data/use-database.ts index 4ec7f06..0173550 100644 --- a/frontend/src/data/use-database.ts +++ b/frontend/src/data/use-database.ts @@ -20,6 +20,12 @@ export const useDatabases = () => { return { data, error, isLoading, isValidating, mutate }; }; +export const useDatabase = (id?: string) => { + const { data, error, isLoading, isValidating, mutate } = + useSWR(id ? `/databases/${id}` : null, backendGet); + return { data, error, isLoading, isValidating, mutate }; +}; + export const useCreateDatabase = () => { const { data, error, trigger, isMutating } = useSWRMutation( "/databases", @@ -50,3 +56,11 @@ export const useUpdateDatabase = (id: string) => { return { data, error, trigger, isMutating }; }; + +export const useDeleteDatabase = (id?: string) => { + const { data, error, trigger, isMutating } = useSWRMutation( + id ? `/databases/${id}` : null, + backendDelete, + ); + return { data, error, trigger, isMutating }; +};