mirror of
https://github.com/chartdb/chartdb.git
synced 2026-02-14 15:39:09 -06:00
delete diagram + modal
This commit is contained in:
@@ -24,6 +24,7 @@ export interface ChartDBContext {
|
||||
loadDiagram: (diagramId: string) => Promise<Diagram | undefined>;
|
||||
updateDiagramUpdatedAt: () => Promise<void>;
|
||||
clearDiagramData: () => Promise<void>;
|
||||
deleteDiagram: () => Promise<void>;
|
||||
|
||||
// Database type operations
|
||||
updateDatabaseType: (databaseType: DatabaseType) => Promise<void>;
|
||||
@@ -140,12 +141,12 @@ export const chartDBContext = createContext<ChartDBContext>({
|
||||
updateDiagramUpdatedAt: emptyFn,
|
||||
loadDiagram: emptyFn,
|
||||
clearDiagramData: emptyFn,
|
||||
deleteDiagram: emptyFn,
|
||||
|
||||
// Database type operations
|
||||
updateDatabaseType: emptyFn,
|
||||
|
||||
// Table operations
|
||||
// updateTables: emptyFn,
|
||||
createTable: emptyFn,
|
||||
getTable: emptyFn,
|
||||
addTable: emptyFn,
|
||||
|
||||
@@ -10,11 +10,13 @@ import { DBRelationship } from '@/lib/domain/db-relationship';
|
||||
import { useStorage } from '@/hooks/use-storage';
|
||||
import { useRedoUndoStack } from '@/hooks/use-redo-undo-stack';
|
||||
import { Diagram } from '@/lib/domain/diagram';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
export const ChartDBProvider: React.FC<React.PropsWithChildren> = ({
|
||||
children,
|
||||
}) => {
|
||||
const db = useStorage();
|
||||
const navigate = useNavigate();
|
||||
const { addUndoAction, resetRedoStack, resetUndoStack } =
|
||||
useRedoUndoStack();
|
||||
const [diagramId, setDiagramId] = useState('');
|
||||
@@ -65,6 +67,29 @@ export const ChartDBProvider: React.FC<React.PropsWithChildren> = ({
|
||||
]);
|
||||
}, [db, diagramId, resetRedoStack, resetUndoStack]);
|
||||
|
||||
const deleteDiagram: ChartDBContext['deleteDiagram'] =
|
||||
useCallback(async () => {
|
||||
const [config] = await Promise.all([
|
||||
db.getConfig(),
|
||||
db.deleteDiagramTables(diagramId),
|
||||
db.deleteDiagramRelationships(diagramId),
|
||||
db.deleteDiagram(diagramId),
|
||||
]);
|
||||
|
||||
if (config?.defaultDiagramId === diagramId) {
|
||||
const diagrams = await db.listDiagrams();
|
||||
|
||||
if (diagrams.length > 0) {
|
||||
const defaultDiagramId = diagrams[0].id;
|
||||
await db.updateConfig({ defaultDiagramId });
|
||||
navigate(`/diagrams/${defaultDiagramId}`);
|
||||
} else {
|
||||
await db.updateConfig({ defaultDiagramId: '' });
|
||||
navigate('/diagrams');
|
||||
}
|
||||
}
|
||||
}, [db, diagramId, navigate]);
|
||||
|
||||
const updateDiagramUpdatedAt: ChartDBContext['updateDiagramUpdatedAt'] =
|
||||
useCallback(async () => {
|
||||
const updatedAt = new Date();
|
||||
@@ -947,6 +972,7 @@ export const ChartDBProvider: React.FC<React.PropsWithChildren> = ({
|
||||
loadDiagram,
|
||||
updateDatabaseType,
|
||||
clearDiagramData,
|
||||
deleteDiagram,
|
||||
updateDiagramUpdatedAt,
|
||||
createTable,
|
||||
addTable,
|
||||
|
||||
@@ -14,6 +14,16 @@ export interface DialogContext {
|
||||
// Export SQL dialog
|
||||
openExportSQLDialog: (params: { targetDatabaseType: DatabaseType }) => void;
|
||||
closeExportSQLDialog: () => void;
|
||||
|
||||
// Alert dialog
|
||||
showAlert: (params: {
|
||||
onAction: () => void;
|
||||
title: string;
|
||||
description: string;
|
||||
actionLabel: string;
|
||||
closeLabel: string;
|
||||
}) => void;
|
||||
closeAlert: () => void;
|
||||
}
|
||||
|
||||
export const dialogContext = createContext<DialogContext>({
|
||||
@@ -23,4 +33,6 @@ export const dialogContext = createContext<DialogContext>({
|
||||
closeOpenDiagramDialog: emptyFn,
|
||||
openExportSQLDialog: emptyFn,
|
||||
closeExportSQLDialog: emptyFn,
|
||||
closeAlert: emptyFn,
|
||||
showAlert: emptyFn,
|
||||
});
|
||||
|
||||
@@ -4,6 +4,7 @@ import { CreateDiagramDialog } from '@/dialogs/create-diagram-dialog/create-diag
|
||||
import { OpenDiagramDialog } from '@/dialogs/open-diagram-dialog/open-diagram-dialog';
|
||||
import { ExportSQLDialog } from '@/dialogs/export-sql-dialog/export-sql-dialog';
|
||||
import { DatabaseType } from '@/lib/domain/database-type';
|
||||
import { BaseAlertDialog } from '@/dialogs/base-alert-dialog/base-alert-dialog';
|
||||
|
||||
export const DialogProvider: React.FC<React.PropsWithChildren> = ({
|
||||
children,
|
||||
@@ -14,6 +15,20 @@ export const DialogProvider: React.FC<React.PropsWithChildren> = ({
|
||||
const [openExportSQLDialogParams, setOpenExportSQLDialogParams] = useState<{
|
||||
targetDatabaseType: DatabaseType;
|
||||
}>({ targetDatabaseType: DatabaseType.GENERIC });
|
||||
const [showAlert, setShowAlert] = useState(false);
|
||||
const [alertParams, setAlertParams] = useState<{
|
||||
onAction: () => void;
|
||||
title: string;
|
||||
description: string;
|
||||
actionLabel: string;
|
||||
closeLabel: string;
|
||||
}>({
|
||||
onAction: () => {},
|
||||
title: '',
|
||||
description: '',
|
||||
actionLabel: '',
|
||||
closeLabel: '',
|
||||
});
|
||||
|
||||
const openExportSQLDialogHandler: DialogContext['openExportSQLDialog'] =
|
||||
useCallback(
|
||||
@@ -24,6 +39,24 @@ export const DialogProvider: React.FC<React.PropsWithChildren> = ({
|
||||
[setOpenExportSQLDialog]
|
||||
);
|
||||
|
||||
const showAlertHandler: DialogContext['showAlert'] = useCallback(
|
||||
({ onAction, title, description, actionLabel, closeLabel }) => {
|
||||
setAlertParams({
|
||||
onAction,
|
||||
title,
|
||||
description,
|
||||
actionLabel,
|
||||
closeLabel,
|
||||
});
|
||||
setShowAlert(true);
|
||||
},
|
||||
[setShowAlert, setAlertParams]
|
||||
);
|
||||
|
||||
const closeAlertHandler = useCallback(() => {
|
||||
setShowAlert(false);
|
||||
}, [setShowAlert]);
|
||||
|
||||
return (
|
||||
<dialogContext.Provider
|
||||
value={{
|
||||
@@ -33,6 +66,8 @@ export const DialogProvider: React.FC<React.PropsWithChildren> = ({
|
||||
closeOpenDiagramDialog: () => setOpenOpenDiagramDialog(false),
|
||||
openExportSQLDialog: openExportSQLDialogHandler,
|
||||
closeExportSQLDialog: () => setOpenExportSQLDialog(false),
|
||||
showAlert: showAlertHandler,
|
||||
closeAlert: closeAlertHandler,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
@@ -42,6 +77,7 @@ export const DialogProvider: React.FC<React.PropsWithChildren> = ({
|
||||
dialog={{ open: openExportSQLDialog }}
|
||||
{...openExportSQLDialogParams}
|
||||
/>
|
||||
<BaseAlertDialog dialog={{ open: showAlert }} {...alertParams} />
|
||||
</dialogContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
64
src/dialogs/base-alert-dialog/base-alert-dialog.tsx
Normal file
64
src/dialogs/base-alert-dialog/base-alert-dialog.tsx
Normal file
@@ -0,0 +1,64 @@
|
||||
import React, { useCallback } from 'react';
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
AlertDialogCancel,
|
||||
AlertDialogContent,
|
||||
AlertDialogDescription,
|
||||
AlertDialogFooter,
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
} from '@/components/alert-dialog/alert-dialog';
|
||||
import { AlertDialogProps } from '@radix-ui/react-alert-dialog';
|
||||
import { useDialog } from '@/hooks/use-dialog';
|
||||
|
||||
export interface BaseAlertDialogProps {
|
||||
title: string;
|
||||
description: string;
|
||||
actionLabel: string;
|
||||
closeLabel: string;
|
||||
onAction: () => void;
|
||||
dialog: AlertDialogProps;
|
||||
}
|
||||
|
||||
export const BaseAlertDialog: React.FC<BaseAlertDialogProps> = ({
|
||||
title,
|
||||
description,
|
||||
actionLabel,
|
||||
closeLabel,
|
||||
onAction,
|
||||
dialog,
|
||||
}) => {
|
||||
const { closeAlert } = useDialog();
|
||||
const alertHandler = useCallback(() => {
|
||||
onAction();
|
||||
closeAlert();
|
||||
}, [onAction, closeAlert]);
|
||||
return (
|
||||
<AlertDialog
|
||||
{...dialog}
|
||||
onOpenChange={(open) => {
|
||||
if (!open) {
|
||||
closeAlert();
|
||||
}
|
||||
}}
|
||||
>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>{title}</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
{description}
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel onClick={closeAlert}>
|
||||
{closeLabel}
|
||||
</AlertDialogCancel>
|
||||
<AlertDialogAction onClick={alertHandler}>
|
||||
{actionLabel}
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
);
|
||||
};
|
||||
@@ -33,6 +33,7 @@ export const OpenDiagramDialog: React.FC<OpenDiagramDialogProps> = ({
|
||||
dialog,
|
||||
}) => {
|
||||
const { closeOpenDiagramDialog } = useDialog();
|
||||
const { updateConfig } = useStorage();
|
||||
const navigate = useNavigate();
|
||||
const { listDiagrams } = useStorage();
|
||||
const [diagrams, setDiagrams] = useState<Diagram[]>([]);
|
||||
@@ -57,7 +58,8 @@ export const OpenDiagramDialog: React.FC<OpenDiagramDialogProps> = ({
|
||||
}, [listDiagrams, setDiagrams, dialog.open]);
|
||||
|
||||
const openDiagram = (diagramId: string) => {
|
||||
if (selectedDiagramId) {
|
||||
if (diagramId) {
|
||||
updateConfig({ defaultDiagramId: diagramId });
|
||||
navigate(`/diagrams/${diagramId}`);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -32,28 +32,23 @@ import {
|
||||
databaseTypeToLabelMap,
|
||||
} from '@/lib/databases';
|
||||
import { DatabaseType } from '@/lib/domain/database-type';
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
AlertDialogCancel,
|
||||
AlertDialogContent,
|
||||
AlertDialogDescription,
|
||||
AlertDialogFooter,
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
} from '@/components/alert-dialog/alert-dialog';
|
||||
|
||||
export interface TopNavbarProps {}
|
||||
|
||||
export const TopNavbar: React.FC<TopNavbarProps> = () => {
|
||||
const { diagramName, updateDiagramName, currentDiagram, clearDiagramData } =
|
||||
useChartDB();
|
||||
const {
|
||||
diagramName,
|
||||
updateDiagramName,
|
||||
currentDiagram,
|
||||
clearDiagramData,
|
||||
deleteDiagram,
|
||||
} = useChartDB();
|
||||
const {
|
||||
openCreateDiagramDialog,
|
||||
openOpenDiagramDialog,
|
||||
openExportSQLDialog,
|
||||
showAlert,
|
||||
} = useDialog();
|
||||
const [showClearAlert, setShowClearAlert] = useState(false);
|
||||
const [editMode, setEditMode] = useState(false);
|
||||
const { exportImage } = useExportImage();
|
||||
const [editedDiagramName, setEditedDiagramName] =
|
||||
@@ -91,11 +86,6 @@ export const TopNavbar: React.FC<TopNavbarProps> = () => {
|
||||
setEditMode(true);
|
||||
};
|
||||
|
||||
const clearDiagramDataHandler = useCallback(async () => {
|
||||
setShowClearAlert(false);
|
||||
await clearDiagramData();
|
||||
}, [clearDiagramData]);
|
||||
|
||||
const exportPNG = useCallback(() => {
|
||||
exportImage('png');
|
||||
}, [exportImage]);
|
||||
@@ -120,279 +110,256 @@ export const TopNavbar: React.FC<TopNavbarProps> = () => {
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<nav className="flex flex-row items-center justify-between px-4 h-12 border-b">
|
||||
<div className="flex flex-1 justify-start gap-x-3">
|
||||
<div className="flex font-primary items-center">
|
||||
<a
|
||||
href="https://chartdb.io"
|
||||
target="_blank"
|
||||
className="cursor-pointer"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<img
|
||||
src={ChartDBLogo}
|
||||
alt="chartDB"
|
||||
className="h-4 max-w-fit"
|
||||
/>
|
||||
</a>
|
||||
</div>
|
||||
<div>
|
||||
<Menubar className="border-none shadow-none">
|
||||
<MenubarMenu>
|
||||
<MenubarTrigger>File</MenubarTrigger>
|
||||
<MenubarContent>
|
||||
<MenubarItem onClick={createNewDiagram}>
|
||||
New
|
||||
<MenubarShortcut>⌘T</MenubarShortcut>
|
||||
</MenubarItem>
|
||||
<MenubarItem onClick={openDiagram}>
|
||||
Open
|
||||
</MenubarItem>
|
||||
<MenubarSeparator />
|
||||
<MenubarSub>
|
||||
<MenubarSubTrigger>
|
||||
Export SQL
|
||||
</MenubarSubTrigger>
|
||||
<MenubarSubContent>
|
||||
<MenubarItem
|
||||
onClick={() =>
|
||||
openExportSQLDialog({
|
||||
targetDatabaseType:
|
||||
DatabaseType.GENERIC,
|
||||
})
|
||||
}
|
||||
>
|
||||
{
|
||||
databaseTypeToLabelMap[
|
||||
'generic'
|
||||
]
|
||||
}
|
||||
</MenubarItem>
|
||||
<MenubarItem
|
||||
onClick={() =>
|
||||
openExportSQLDialog({
|
||||
targetDatabaseType:
|
||||
DatabaseType.POSTGRESQL,
|
||||
})
|
||||
}
|
||||
>
|
||||
{
|
||||
databaseTypeToLabelMap[
|
||||
'postgresql'
|
||||
]
|
||||
}
|
||||
</MenubarItem>
|
||||
<MenubarItem
|
||||
onClick={() =>
|
||||
openExportSQLDialog({
|
||||
targetDatabaseType:
|
||||
DatabaseType.MYSQL,
|
||||
})
|
||||
}
|
||||
>
|
||||
{
|
||||
databaseTypeToLabelMap[
|
||||
'mysql'
|
||||
]
|
||||
}
|
||||
</MenubarItem>
|
||||
<MenubarItem
|
||||
onClick={() =>
|
||||
openExportSQLDialog({
|
||||
targetDatabaseType:
|
||||
DatabaseType.SQL_SERVER,
|
||||
})
|
||||
}
|
||||
>
|
||||
{
|
||||
databaseTypeToLabelMap[
|
||||
'sql_server'
|
||||
]
|
||||
}
|
||||
</MenubarItem>
|
||||
<MenubarItem
|
||||
onClick={() =>
|
||||
openExportSQLDialog({
|
||||
targetDatabaseType:
|
||||
DatabaseType.MARIADB,
|
||||
})
|
||||
}
|
||||
>
|
||||
{
|
||||
databaseTypeToLabelMap[
|
||||
'mariadb'
|
||||
]
|
||||
}
|
||||
</MenubarItem>
|
||||
<MenubarItem
|
||||
onClick={() =>
|
||||
openExportSQLDialog({
|
||||
targetDatabaseType:
|
||||
DatabaseType.SQLITE,
|
||||
})
|
||||
}
|
||||
>
|
||||
{
|
||||
databaseTypeToLabelMap[
|
||||
'sqlite'
|
||||
]
|
||||
}
|
||||
</MenubarItem>
|
||||
</MenubarSubContent>
|
||||
</MenubarSub>
|
||||
<MenubarSub>
|
||||
<MenubarSubTrigger>
|
||||
Export as
|
||||
</MenubarSubTrigger>
|
||||
<MenubarSubContent>
|
||||
<MenubarItem onClick={exportPNG}>
|
||||
PNG
|
||||
</MenubarItem>
|
||||
<MenubarItem onClick={exportJPG}>
|
||||
JPG
|
||||
</MenubarItem>
|
||||
<MenubarItem onClick={exportSVG}>
|
||||
SVG
|
||||
</MenubarItem>
|
||||
</MenubarSubContent>
|
||||
</MenubarSub>
|
||||
<MenubarSeparator />
|
||||
<MenubarItem>Exit</MenubarItem>
|
||||
</MenubarContent>
|
||||
</MenubarMenu>
|
||||
<MenubarMenu>
|
||||
<MenubarTrigger>Edit</MenubarTrigger>
|
||||
<MenubarContent>
|
||||
<MenubarItem>
|
||||
Undo{' '}
|
||||
<MenubarShortcut>⌘Z</MenubarShortcut>
|
||||
</MenubarItem>
|
||||
<MenubarItem>
|
||||
Redo{' '}
|
||||
<MenubarShortcut>⇧⌘Z</MenubarShortcut>
|
||||
</MenubarItem>
|
||||
<MenubarSeparator />
|
||||
<MenubarItem
|
||||
onClick={() => setShowClearAlert(true)}
|
||||
>
|
||||
Clear
|
||||
</MenubarItem>
|
||||
</MenubarContent>
|
||||
</MenubarMenu>
|
||||
<MenubarMenu>
|
||||
<MenubarTrigger>Help</MenubarTrigger>
|
||||
<MenubarContent>
|
||||
<MenubarItem onClick={openChartDBIO}>
|
||||
Visit ChartDB
|
||||
</MenubarItem>
|
||||
<MenubarItem onClick={openJoinSlack}>
|
||||
Join us on Slack
|
||||
</MenubarItem>
|
||||
</MenubarContent>
|
||||
</MenubarMenu>
|
||||
</Menubar>
|
||||
</div>
|
||||
<nav className="flex flex-row items-center justify-between px-4 h-12 border-b">
|
||||
<div className="flex flex-1 justify-start gap-x-3">
|
||||
<div className="flex font-primary items-center">
|
||||
<a
|
||||
href="https://chartdb.io"
|
||||
target="_blank"
|
||||
className="cursor-pointer"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<img
|
||||
src={ChartDBLogo}
|
||||
alt="chartDB"
|
||||
className="h-4 max-w-fit"
|
||||
/>
|
||||
</a>
|
||||
</div>
|
||||
<div className="flex flex-row flex-1 justify-center items-center group gap-2">
|
||||
<Tooltip>
|
||||
<TooltipTrigger>
|
||||
<img
|
||||
src={
|
||||
databaseSecondaryLogoMap[
|
||||
currentDiagram.databaseType
|
||||
]
|
||||
}
|
||||
className="h-5 max-w-fit"
|
||||
alt="database"
|
||||
/>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
{
|
||||
databaseTypeToLabelMap[
|
||||
<div>
|
||||
<Menubar className="border-none shadow-none">
|
||||
<MenubarMenu>
|
||||
<MenubarTrigger>File</MenubarTrigger>
|
||||
<MenubarContent>
|
||||
<MenubarItem onClick={createNewDiagram}>
|
||||
New
|
||||
<MenubarShortcut>⌘T</MenubarShortcut>
|
||||
</MenubarItem>
|
||||
<MenubarItem onClick={openDiagram}>
|
||||
Open
|
||||
</MenubarItem>
|
||||
<MenubarSeparator />
|
||||
<MenubarSub>
|
||||
<MenubarSubTrigger>
|
||||
Export SQL
|
||||
</MenubarSubTrigger>
|
||||
<MenubarSubContent>
|
||||
<MenubarItem
|
||||
onClick={() =>
|
||||
openExportSQLDialog({
|
||||
targetDatabaseType:
|
||||
DatabaseType.GENERIC,
|
||||
})
|
||||
}
|
||||
>
|
||||
{databaseTypeToLabelMap['generic']}
|
||||
</MenubarItem>
|
||||
<MenubarItem
|
||||
onClick={() =>
|
||||
openExportSQLDialog({
|
||||
targetDatabaseType:
|
||||
DatabaseType.POSTGRESQL,
|
||||
})
|
||||
}
|
||||
>
|
||||
{
|
||||
databaseTypeToLabelMap[
|
||||
'postgresql'
|
||||
]
|
||||
}
|
||||
</MenubarItem>
|
||||
<MenubarItem
|
||||
onClick={() =>
|
||||
openExportSQLDialog({
|
||||
targetDatabaseType:
|
||||
DatabaseType.MYSQL,
|
||||
})
|
||||
}
|
||||
>
|
||||
{databaseTypeToLabelMap['mysql']}
|
||||
</MenubarItem>
|
||||
<MenubarItem
|
||||
onClick={() =>
|
||||
openExportSQLDialog({
|
||||
targetDatabaseType:
|
||||
DatabaseType.SQL_SERVER,
|
||||
})
|
||||
}
|
||||
>
|
||||
{
|
||||
databaseTypeToLabelMap[
|
||||
'sql_server'
|
||||
]
|
||||
}
|
||||
</MenubarItem>
|
||||
<MenubarItem
|
||||
onClick={() =>
|
||||
openExportSQLDialog({
|
||||
targetDatabaseType:
|
||||
DatabaseType.MARIADB,
|
||||
})
|
||||
}
|
||||
>
|
||||
{databaseTypeToLabelMap['mariadb']}
|
||||
</MenubarItem>
|
||||
<MenubarItem
|
||||
onClick={() =>
|
||||
openExportSQLDialog({
|
||||
targetDatabaseType:
|
||||
DatabaseType.SQLITE,
|
||||
})
|
||||
}
|
||||
>
|
||||
{databaseTypeToLabelMap['sqlite']}
|
||||
</MenubarItem>
|
||||
</MenubarSubContent>
|
||||
</MenubarSub>
|
||||
<MenubarSub>
|
||||
<MenubarSubTrigger>
|
||||
Export as
|
||||
</MenubarSubTrigger>
|
||||
<MenubarSubContent>
|
||||
<MenubarItem onClick={exportPNG}>
|
||||
PNG
|
||||
</MenubarItem>
|
||||
<MenubarItem onClick={exportJPG}>
|
||||
JPG
|
||||
</MenubarItem>
|
||||
<MenubarItem onClick={exportSVG}>
|
||||
SVG
|
||||
</MenubarItem>
|
||||
</MenubarSubContent>
|
||||
</MenubarSub>
|
||||
<MenubarSeparator />
|
||||
<MenubarItem
|
||||
onClick={() =>
|
||||
showAlert({
|
||||
title: 'Delete Diagram',
|
||||
description:
|
||||
'This action cannot be undone. This will permanently delete the diagram.',
|
||||
actionLabel: 'Delete',
|
||||
closeLabel: 'Cancel',
|
||||
onAction: deleteDiagram,
|
||||
})
|
||||
}
|
||||
>
|
||||
Delete Diagram
|
||||
</MenubarItem>
|
||||
<MenubarSeparator />
|
||||
<MenubarItem>Exit</MenubarItem>
|
||||
</MenubarContent>
|
||||
</MenubarMenu>
|
||||
<MenubarMenu>
|
||||
<MenubarTrigger>Edit</MenubarTrigger>
|
||||
<MenubarContent>
|
||||
<MenubarItem>
|
||||
Undo <MenubarShortcut>⌘Z</MenubarShortcut>
|
||||
</MenubarItem>
|
||||
<MenubarItem>
|
||||
Redo <MenubarShortcut>⇧⌘Z</MenubarShortcut>
|
||||
</MenubarItem>
|
||||
<MenubarSeparator />
|
||||
<MenubarItem
|
||||
onClick={() =>
|
||||
showAlert({
|
||||
title: 'Clear Diagram',
|
||||
description:
|
||||
'This action cannot be undone. This will permanently delete all the data in the diagram.',
|
||||
actionLabel: 'Clear',
|
||||
closeLabel: 'Cancel',
|
||||
onAction: clearDiagramData,
|
||||
})
|
||||
}
|
||||
>
|
||||
Clear
|
||||
</MenubarItem>
|
||||
</MenubarContent>
|
||||
</MenubarMenu>
|
||||
<MenubarMenu>
|
||||
<MenubarTrigger>Help</MenubarTrigger>
|
||||
<MenubarContent>
|
||||
<MenubarItem onClick={openChartDBIO}>
|
||||
Visit ChartDB
|
||||
</MenubarItem>
|
||||
<MenubarItem onClick={openJoinSlack}>
|
||||
Join us on Slack
|
||||
</MenubarItem>
|
||||
</MenubarContent>
|
||||
</MenubarMenu>
|
||||
</Menubar>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-row flex-1 justify-center items-center group gap-2">
|
||||
<Tooltip>
|
||||
<TooltipTrigger>
|
||||
<img
|
||||
src={
|
||||
databaseSecondaryLogoMap[
|
||||
currentDiagram.databaseType
|
||||
]
|
||||
}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<div className="flex">
|
||||
<Label>Diagrams/</Label>
|
||||
</div>
|
||||
<div className="flex flex-row items-center gap-1">
|
||||
{editMode ? (
|
||||
<>
|
||||
<Input
|
||||
ref={inputRef}
|
||||
autoFocus
|
||||
type="text"
|
||||
placeholder={diagramName}
|
||||
value={editedDiagramName}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
onChange={(e) =>
|
||||
setEditedDiagramName(e.target.value)
|
||||
}
|
||||
className="h-7 focus-visible:ring-0"
|
||||
/>
|
||||
<Button
|
||||
variant="ghost"
|
||||
className="hover:bg-primary-foreground p-2 w-7 h-7 text-slate-500 hover:text-slate-700 hidden group-hover:flex"
|
||||
onClick={editDiagramName}
|
||||
>
|
||||
<Check />
|
||||
</Button>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Label>{diagramName}</Label>
|
||||
<Button
|
||||
variant="ghost"
|
||||
className="hover:bg-primary-foreground p-2 w-7 h-7 text-slate-500 hover:text-slate-700 hidden group-hover:flex"
|
||||
onClick={enterEditMode}
|
||||
>
|
||||
<Pencil />
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
className="h-5 max-w-fit"
|
||||
alt="database"
|
||||
/>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
{databaseTypeToLabelMap[currentDiagram.databaseType]}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<div className="flex">
|
||||
<Label>Diagrams/</Label>
|
||||
</div>
|
||||
<div className="hidden flex-1 justify-end sm:flex">
|
||||
<Tooltip>
|
||||
<TooltipTrigger>
|
||||
<Badge variant="secondary" className="flex gap-1">
|
||||
<Save className="h-4" />
|
||||
Last saved
|
||||
<TimeAgo datetime={currentDiagram.updatedAt} />
|
||||
</Badge>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
{currentDiagram.updatedAt.toLocaleString()}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<div className="flex flex-row items-center gap-1">
|
||||
{editMode ? (
|
||||
<>
|
||||
<Input
|
||||
ref={inputRef}
|
||||
autoFocus
|
||||
type="text"
|
||||
placeholder={diagramName}
|
||||
value={editedDiagramName}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
onChange={(e) =>
|
||||
setEditedDiagramName(e.target.value)
|
||||
}
|
||||
className="h-7 focus-visible:ring-0"
|
||||
/>
|
||||
<Button
|
||||
variant="ghost"
|
||||
className="hover:bg-primary-foreground p-2 w-7 h-7 text-slate-500 hover:text-slate-700 hidden group-hover:flex"
|
||||
onClick={editDiagramName}
|
||||
>
|
||||
<Check />
|
||||
</Button>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Label>{diagramName}</Label>
|
||||
<Button
|
||||
variant="ghost"
|
||||
className="hover:bg-primary-foreground p-2 w-7 h-7 text-slate-500 hover:text-slate-700 hidden group-hover:flex"
|
||||
onClick={enterEditMode}
|
||||
>
|
||||
<Pencil />
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</nav>
|
||||
<AlertDialog open={showClearAlert}>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>
|
||||
Are you absolutely sure?
|
||||
</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
This action cannot be undone. This will permanently
|
||||
delete all the data in the diagram.
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel
|
||||
onClick={() => setShowClearAlert(false)}
|
||||
>
|
||||
Cancel
|
||||
</AlertDialogCancel>
|
||||
<AlertDialogAction onClick={clearDiagramDataHandler}>
|
||||
Clear
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
</>
|
||||
</div>
|
||||
<div className="hidden flex-1 justify-end sm:flex">
|
||||
<Tooltip>
|
||||
<TooltipTrigger>
|
||||
<Badge variant="secondary" className="flex gap-1">
|
||||
<Save className="h-4" />
|
||||
Last saved
|
||||
<TimeAgo datetime={currentDiagram.updatedAt} />
|
||||
</Badge>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
{currentDiagram.updatedAt.toLocaleString()}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</nav>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user