mirror of
https://github.com/chartdb/chartdb.git
synced 2025-11-02 21:13:23 +00:00
edit table from canvas
This commit is contained in:
18
src/context/layout-context/layout-context.tsx
Normal file
18
src/context/layout-context/layout-context.tsx
Normal file
@@ -0,0 +1,18 @@
|
||||
import { emptyFn } from '@/lib/utils';
|
||||
import { createContext } from 'react';
|
||||
|
||||
export type SidebarSection = 'tables' | 'relationships';
|
||||
|
||||
export interface LayoutContext {
|
||||
openedTableInSidebar: string | undefined;
|
||||
openTableFromSidebar: (tableId: string) => void;
|
||||
selectedSidebarSection: SidebarSection;
|
||||
selectSidebarSection: (section: SidebarSection) => void;
|
||||
}
|
||||
|
||||
export const layoutContext = createContext<LayoutContext>({
|
||||
openedTableInSidebar: undefined,
|
||||
selectedSidebarSection: 'tables',
|
||||
selectSidebarSection: emptyFn,
|
||||
openTableFromSidebar: emptyFn,
|
||||
});
|
||||
25
src/context/layout-context/layout-provider.tsx
Normal file
25
src/context/layout-context/layout-provider.tsx
Normal file
@@ -0,0 +1,25 @@
|
||||
import React from 'react';
|
||||
import { layoutContext, SidebarSection } from './layout-context';
|
||||
|
||||
export const LayoutProvider: React.FC<React.PropsWithChildren> = ({
|
||||
children,
|
||||
}) => {
|
||||
const [openedTableInSidebar, setOpenedTableInSidebar] = React.useState<
|
||||
string | undefined
|
||||
>();
|
||||
const [selectedSidebarSection, setSelectedSidebarSection] =
|
||||
React.useState<SidebarSection>('tables');
|
||||
|
||||
return (
|
||||
<layoutContext.Provider
|
||||
value={{
|
||||
openedTableInSidebar,
|
||||
selectedSidebarSection,
|
||||
openTableFromSidebar: setOpenedTableInSidebar,
|
||||
selectSidebarSection: setSelectedSidebarSection,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</layoutContext.Provider>
|
||||
);
|
||||
};
|
||||
4
src/hooks/use-layout.ts
Normal file
4
src/hooks/use-layout.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
import { useContext } from 'react';
|
||||
import { layoutContext } from '@/context/layout-context/layout-context';
|
||||
|
||||
export const useLayout = () => useContext(layoutContext);
|
||||
@@ -1,10 +1,11 @@
|
||||
import React from 'react';
|
||||
import { NodeProps, Node } from '@xyflow/react';
|
||||
import { Button } from '@/components/button/button';
|
||||
import { Ellipsis, Table2 } from 'lucide-react';
|
||||
import { Pencil, Table2 } from 'lucide-react';
|
||||
import { Label } from '@/components/label/label';
|
||||
import { DBTable } from '@/lib/domain/db-table';
|
||||
import { TableNodeField } from './table-node-field';
|
||||
import { useLayout } from '@/hooks/use-layout';
|
||||
|
||||
export type TableNodeType = Node<
|
||||
{
|
||||
@@ -19,8 +20,14 @@ export const TableNode: React.FC<NodeProps<TableNodeType>> = ({
|
||||
id,
|
||||
data: { table },
|
||||
}) => {
|
||||
const { openTableFromSidebar, selectSidebarSection } = useLayout();
|
||||
const focused = !!selected && !dragging;
|
||||
|
||||
const openTableInEditor = () => {
|
||||
selectSidebarSection('tables');
|
||||
openTableFromSidebar(table.id);
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`flex flex-col w-56 bg-background border ${selected ? 'border-slate-400' : ''} rounded-lg shadow-sm`}
|
||||
@@ -38,8 +45,9 @@ export const TableNode: React.FC<NodeProps<TableNodeType>> = ({
|
||||
<Button
|
||||
variant="ghost"
|
||||
className="hover:bg-primary-foreground p-0 w-6 h-6 text-slate-500 hover:text-slate-700"
|
||||
onClick={openTableInEditor}
|
||||
>
|
||||
<Ellipsis className="h-4 w-4" />
|
||||
<Pencil className="h-4 w-4" />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -9,17 +9,22 @@ import {
|
||||
} from '@/components/select/select';
|
||||
import { TablesSection } from './tables-section/tables-section';
|
||||
import { RelationshipsSection } from './relationships-section/relationships-section';
|
||||
import { useLayout } from '@/hooks/use-layout';
|
||||
import { SidebarSection } from '@/context/layout-context/layout-context';
|
||||
|
||||
export interface SidePanelProps {}
|
||||
|
||||
export const SidePanel: React.FC<SidePanelProps> = () => {
|
||||
const [selected, setSelected] = React.useState('tables');
|
||||
// const [selected, setSelected] = React.useState('tables');
|
||||
const { selectSidebarSection, selectedSidebarSection } = useLayout();
|
||||
return (
|
||||
<aside className="flex h-full flex-col overflow-hidden">
|
||||
<div className="flex justify-center border-b pt-0.5">
|
||||
<Select
|
||||
value={selected}
|
||||
onValueChange={(value) => setSelected(value)}
|
||||
value={selectedSidebarSection}
|
||||
onValueChange={(value) =>
|
||||
selectSidebarSection(value as SidebarSection)
|
||||
}
|
||||
>
|
||||
<SelectTrigger className="border-none rounded-none shadow-none focus:border-transparent focus:ring-0 hover:underline hover:bg-secondary font-semibold">
|
||||
<SelectValue />
|
||||
@@ -34,7 +39,7 @@ export const SidePanel: React.FC<SidePanelProps> = () => {
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
{selected === 'tables' ? (
|
||||
{selectedSidebarSection === 'tables' ? (
|
||||
<TablesSection />
|
||||
) : (
|
||||
<RelationshipsSection />
|
||||
|
||||
@@ -2,17 +2,21 @@ import React from 'react';
|
||||
import { Accordion } from '@/components/accordion/accordion';
|
||||
import { TableListItem } from './table-list-item/table-list-item';
|
||||
import { DBTable } from '@/lib/domain/db-table';
|
||||
import { useLayout } from '@/hooks/use-layout';
|
||||
|
||||
export interface TableListProps {
|
||||
tables: DBTable[];
|
||||
}
|
||||
|
||||
export const TableList: React.FC<TableListProps> = ({ tables }) => {
|
||||
const { openTableFromSidebar, openedTableInSidebar } = useLayout();
|
||||
return (
|
||||
<Accordion
|
||||
type="single"
|
||||
collapsible
|
||||
className="flex flex-col w-full gap-1"
|
||||
value={openedTableInSidebar}
|
||||
onValueChange={openTableFromSidebar}
|
||||
>
|
||||
{tables.map((table) => (
|
||||
<TableListItem key={table.id} table={table} />
|
||||
|
||||
@@ -9,26 +9,29 @@ import { CreateDiagramDialogProvider } from './dialogs/create-diagram-dialog/cre
|
||||
import { ConfigProvider } from './context/config-context/config-provider';
|
||||
import { HistoryProvider } from './context/history-context/history-provider';
|
||||
import { RedoUndoStackProvider } from './context/history-context/redo-undo-stack-provider';
|
||||
import { LayoutProvider } from './context/layout-context/layout-provider';
|
||||
|
||||
const routes: RouteObject[] = [
|
||||
...['', 'diagrams/:diagramId'].map((path) => ({
|
||||
path,
|
||||
element: (
|
||||
<StorageProvider>
|
||||
<ConfigProvider>
|
||||
<RedoUndoStackProvider>
|
||||
<ChartDBProvider>
|
||||
<HistoryProvider>
|
||||
<CreateDiagramDialogProvider>
|
||||
<ReactFlowProvider>
|
||||
<EditorPage />
|
||||
</ReactFlowProvider>
|
||||
</CreateDiagramDialogProvider>
|
||||
</HistoryProvider>
|
||||
</ChartDBProvider>
|
||||
</RedoUndoStackProvider>
|
||||
</ConfigProvider>
|
||||
</StorageProvider>
|
||||
<LayoutProvider>
|
||||
<StorageProvider>
|
||||
<ConfigProvider>
|
||||
<RedoUndoStackProvider>
|
||||
<ChartDBProvider>
|
||||
<HistoryProvider>
|
||||
<CreateDiagramDialogProvider>
|
||||
<ReactFlowProvider>
|
||||
<EditorPage />
|
||||
</ReactFlowProvider>
|
||||
</CreateDiagramDialogProvider>
|
||||
</HistoryProvider>
|
||||
</ChartDBProvider>
|
||||
</RedoUndoStackProvider>
|
||||
</ConfigProvider>
|
||||
</StorageProvider>
|
||||
</LayoutProvider>
|
||||
),
|
||||
})),
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user