-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #26 from bruinenxyz/hungle/bru-1047-create-databas…
…e-management-page BRU-1047 Create database management page
- Loading branch information
Showing
4 changed files
with
350 additions
and
0 deletions.
There are no files selected for viewing
121 changes: 121 additions & 0 deletions
121
frontend/src/app/databases/[databaseId]/database-details.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<boolean>(false); | ||
const nameField = useField<string>(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 ( | ||
<> | ||
<div className="flex flex-row items-center justify-between mb-2"> | ||
<H6 className="mb-0">Database Details</H6> | ||
<Button | ||
small | ||
minimal | ||
icon="edit" | ||
text="Edit" | ||
onClick={() => setEditDetails(true)} | ||
/> | ||
</div> | ||
<div className="flex flex-col gap-2 mt-1"> | ||
<div className="flex flex-row justify-between"> | ||
<Text>Name</Text> | ||
<Text className="ml-2 bp5-text-muted">{database.name}</Text> | ||
</div> | ||
</div> | ||
</> | ||
); | ||
} | ||
|
||
function renderEditableDetails() { | ||
return ( | ||
<> | ||
<H6 className="my-1">Database Details</H6> | ||
{isMutating ? ( | ||
<Loading /> | ||
) : ( | ||
<div className="flex flex-col gap-3 mt-2"> | ||
<div className="flex flex-row items-center justify-between"> | ||
<Text>Name</Text> | ||
<InputGroup id="name-input" {...nameField} /> | ||
</div> | ||
<div className="flex flex-row items-center justify-end gap-2"> | ||
<Button | ||
small | ||
outlined | ||
icon="cross" | ||
intent="danger" | ||
text="Cancel" | ||
onClick={() => { | ||
setEditDetails(false); | ||
resetFields(); | ||
}} | ||
/> | ||
<Button | ||
small | ||
icon="tick" | ||
intent="primary" | ||
text="Save" | ||
disabled={!isValidDatabaseUpdate()} | ||
onClick={handleUpdateDatabase} | ||
/> | ||
</div> | ||
</div> | ||
)} | ||
</> | ||
); | ||
} | ||
|
||
return ( | ||
<div className="flex flex-col h-full p-3 overflow-y-auto"> | ||
{editDetails ? renderEditableDetails() : renderDatabaseDetails()} | ||
</div> | ||
); | ||
}; | ||
|
||
export default DatabaseDetails; |
93 changes: 93 additions & 0 deletions
93
frontend/src/app/databases/[databaseId]/delete-database.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<string>(""); | ||
|
||
async function submitDelete() { | ||
setIsOpen(false); | ||
setIsSubmitting(true); | ||
await deleteDatabase(); | ||
mutate(`/databases`); | ||
setIsSubmitting(false); | ||
onClose(false); | ||
router.push(`/databases`); | ||
} | ||
|
||
return ( | ||
<> | ||
<Dialog isOpen={isSubmitting} title="Deleting database..."> | ||
<DialogBody> | ||
<Spinner size={SpinnerSize.STANDARD} /> | ||
</DialogBody> | ||
</Dialog> | ||
<Dialog | ||
isOpen={isOpen} | ||
isCloseButtonShown | ||
title="Delete database" | ||
onClose={() => { | ||
onClose(false); | ||
}} | ||
> | ||
<DialogBody> | ||
<div className="flex flex-row"> | ||
<Text>Name:</Text> | ||
<Text className="ml-2 bp5-text-muted">{database.name}</Text> | ||
</div> | ||
<Divider className="my-2" /> | ||
<Callout | ||
intent="warning" | ||
icon="warning-sign" | ||
title="Database deletion is permanent" | ||
/> | ||
<Text className="mt-2 text-center"> | ||
To confirm deletion, please type the database name in the field | ||
below before clicking submit. | ||
</Text> | ||
<FormGroup className="mt-2"> | ||
<InputGroup | ||
id="confirm-input" | ||
{...confirmField} | ||
autoFocus={false} | ||
/> | ||
</FormGroup> | ||
</DialogBody> | ||
<DialogFooter | ||
actions={ | ||
<Button | ||
intent="danger" | ||
text="Delete" | ||
disabled={confirmField.value !== database.name} | ||
onClick={() => submitDelete()} | ||
/> | ||
} | ||
/> | ||
</Dialog> | ||
</> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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>( | ||
DatabaseTabEnum.DETAILS, | ||
); | ||
const [deleteDatabaseOpen, setDeleteDatabaseOpen] = useState<boolean>(false); | ||
//const hasPermissionEditOntology = useUserPermission(ONTOLOGY_EDIT_PERMISSION); | ||
|
||
const { | ||
data: database, | ||
isLoading: isLoadingDatabase, | ||
error: databaseError, | ||
} = useDatabase(params.databaseId); | ||
|
||
if (isLoadingDatabase) { | ||
return <Loading />; | ||
} | ||
|
||
if (databaseError || !database) { | ||
console.log("Database error", databaseError); | ||
return ( | ||
<ErrorDisplay | ||
title="Cannot get database details" | ||
description={databaseError.message} | ||
/> | ||
); | ||
} | ||
|
||
function renderRightElement() { | ||
return ( | ||
<div className="flex flex-row items-center shrink-0"> | ||
<Tabs | ||
animate | ||
selectedTabId={currentTab} | ||
id="section-tabs" | ||
key="horizontal" | ||
renderActiveTabPanelOnly={true} | ||
onChange={(tabId: DatabaseTabEnum) => setCurrentTab(tabId)} | ||
> | ||
<Tab | ||
id={DatabaseTabEnum.DETAILS} | ||
title={ | ||
<Button | ||
className="bp5-minimal" | ||
icon="application" | ||
text="Details" | ||
/> | ||
} | ||
/> | ||
</Tabs> | ||
<Popover | ||
placement="bottom-start" | ||
content={ | ||
<Menu className="flex flex-col"> | ||
<MenuItem | ||
icon="trash" | ||
text="Delete database" | ||
onClick={() => setDeleteDatabaseOpen(true)} | ||
/> | ||
</Menu> | ||
} | ||
> | ||
<Button | ||
className="ml-3" | ||
alignText="left" | ||
rightIcon="caret-down" | ||
text="Options" | ||
/> | ||
</Popover> | ||
</div> | ||
); | ||
} | ||
|
||
function renderObjectContent() { | ||
switch (currentTab) { | ||
default: | ||
return <DatabaseDetails database={database!} />; | ||
} | ||
} | ||
|
||
return ( | ||
<Section | ||
className="flex flex-col max-h-full col-span-2" | ||
icon={ | ||
<SquareIcon icon={"cube"} color={"gray"} size={SquareIconSize.LARGE} /> | ||
} | ||
title={<H4 className="m-0">{database!.name}</H4>} | ||
subtitle={database?.created_at.toString().split("T")[0]} | ||
rightElement={renderRightElement()} | ||
> | ||
{renderObjectContent()} | ||
{deleteDatabaseOpen && ( | ||
<DeleteDatabase database={database!} onClose={setDeleteDatabaseOpen} /> | ||
)} | ||
</Section> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters