mirror of
https://github.com/chartdb/chartdb.git
synced 2025-11-04 14:03:15 +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 React from 'react';
|
||||||
import { NodeProps, Node } from '@xyflow/react';
|
import { NodeProps, Node } from '@xyflow/react';
|
||||||
import { Button } from '@/components/button/button';
|
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 { Label } from '@/components/label/label';
|
||||||
import { DBTable } from '@/lib/domain/db-table';
|
import { DBTable } from '@/lib/domain/db-table';
|
||||||
import { TableNodeField } from './table-node-field';
|
import { TableNodeField } from './table-node-field';
|
||||||
|
import { useLayout } from '@/hooks/use-layout';
|
||||||
|
|
||||||
export type TableNodeType = Node<
|
export type TableNodeType = Node<
|
||||||
{
|
{
|
||||||
@@ -19,8 +20,14 @@ export const TableNode: React.FC<NodeProps<TableNodeType>> = ({
|
|||||||
id,
|
id,
|
||||||
data: { table },
|
data: { table },
|
||||||
}) => {
|
}) => {
|
||||||
|
const { openTableFromSidebar, selectSidebarSection } = useLayout();
|
||||||
const focused = !!selected && !dragging;
|
const focused = !!selected && !dragging;
|
||||||
|
|
||||||
|
const openTableInEditor = () => {
|
||||||
|
selectSidebarSection('tables');
|
||||||
|
openTableFromSidebar(table.id);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={`flex flex-col w-56 bg-background border ${selected ? 'border-slate-400' : ''} rounded-lg shadow-sm`}
|
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
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
className="hover:bg-primary-foreground p-0 w-6 h-6 text-slate-500 hover:text-slate-700"
|
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>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -9,17 +9,22 @@ import {
|
|||||||
} from '@/components/select/select';
|
} from '@/components/select/select';
|
||||||
import { TablesSection } from './tables-section/tables-section';
|
import { TablesSection } from './tables-section/tables-section';
|
||||||
import { RelationshipsSection } from './relationships-section/relationships-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 interface SidePanelProps {}
|
||||||
|
|
||||||
export const SidePanel: React.FC<SidePanelProps> = () => {
|
export const SidePanel: React.FC<SidePanelProps> = () => {
|
||||||
const [selected, setSelected] = React.useState('tables');
|
// const [selected, setSelected] = React.useState('tables');
|
||||||
|
const { selectSidebarSection, selectedSidebarSection } = useLayout();
|
||||||
return (
|
return (
|
||||||
<aside className="flex h-full flex-col overflow-hidden">
|
<aside className="flex h-full flex-col overflow-hidden">
|
||||||
<div className="flex justify-center border-b pt-0.5">
|
<div className="flex justify-center border-b pt-0.5">
|
||||||
<Select
|
<Select
|
||||||
value={selected}
|
value={selectedSidebarSection}
|
||||||
onValueChange={(value) => setSelected(value)}
|
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">
|
<SelectTrigger className="border-none rounded-none shadow-none focus:border-transparent focus:ring-0 hover:underline hover:bg-secondary font-semibold">
|
||||||
<SelectValue />
|
<SelectValue />
|
||||||
@@ -34,7 +39,7 @@ export const SidePanel: React.FC<SidePanelProps> = () => {
|
|||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
{selected === 'tables' ? (
|
{selectedSidebarSection === 'tables' ? (
|
||||||
<TablesSection />
|
<TablesSection />
|
||||||
) : (
|
) : (
|
||||||
<RelationshipsSection />
|
<RelationshipsSection />
|
||||||
|
|||||||
@@ -2,17 +2,21 @@ import React from 'react';
|
|||||||
import { Accordion } from '@/components/accordion/accordion';
|
import { Accordion } from '@/components/accordion/accordion';
|
||||||
import { TableListItem } from './table-list-item/table-list-item';
|
import { TableListItem } from './table-list-item/table-list-item';
|
||||||
import { DBTable } from '@/lib/domain/db-table';
|
import { DBTable } from '@/lib/domain/db-table';
|
||||||
|
import { useLayout } from '@/hooks/use-layout';
|
||||||
|
|
||||||
export interface TableListProps {
|
export interface TableListProps {
|
||||||
tables: DBTable[];
|
tables: DBTable[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const TableList: React.FC<TableListProps> = ({ tables }) => {
|
export const TableList: React.FC<TableListProps> = ({ tables }) => {
|
||||||
|
const { openTableFromSidebar, openedTableInSidebar } = useLayout();
|
||||||
return (
|
return (
|
||||||
<Accordion
|
<Accordion
|
||||||
type="single"
|
type="single"
|
||||||
collapsible
|
collapsible
|
||||||
className="flex flex-col w-full gap-1"
|
className="flex flex-col w-full gap-1"
|
||||||
|
value={openedTableInSidebar}
|
||||||
|
onValueChange={openTableFromSidebar}
|
||||||
>
|
>
|
||||||
{tables.map((table) => (
|
{tables.map((table) => (
|
||||||
<TableListItem key={table.id} table={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 { ConfigProvider } from './context/config-context/config-provider';
|
||||||
import { HistoryProvider } from './context/history-context/history-provider';
|
import { HistoryProvider } from './context/history-context/history-provider';
|
||||||
import { RedoUndoStackProvider } from './context/history-context/redo-undo-stack-provider';
|
import { RedoUndoStackProvider } from './context/history-context/redo-undo-stack-provider';
|
||||||
|
import { LayoutProvider } from './context/layout-context/layout-provider';
|
||||||
|
|
||||||
const routes: RouteObject[] = [
|
const routes: RouteObject[] = [
|
||||||
...['', 'diagrams/:diagramId'].map((path) => ({
|
...['', 'diagrams/:diagramId'].map((path) => ({
|
||||||
path,
|
path,
|
||||||
element: (
|
element: (
|
||||||
<StorageProvider>
|
<LayoutProvider>
|
||||||
<ConfigProvider>
|
<StorageProvider>
|
||||||
<RedoUndoStackProvider>
|
<ConfigProvider>
|
||||||
<ChartDBProvider>
|
<RedoUndoStackProvider>
|
||||||
<HistoryProvider>
|
<ChartDBProvider>
|
||||||
<CreateDiagramDialogProvider>
|
<HistoryProvider>
|
||||||
<ReactFlowProvider>
|
<CreateDiagramDialogProvider>
|
||||||
<EditorPage />
|
<ReactFlowProvider>
|
||||||
</ReactFlowProvider>
|
<EditorPage />
|
||||||
</CreateDiagramDialogProvider>
|
</ReactFlowProvider>
|
||||||
</HistoryProvider>
|
</CreateDiagramDialogProvider>
|
||||||
</ChartDBProvider>
|
</HistoryProvider>
|
||||||
</RedoUndoStackProvider>
|
</ChartDBProvider>
|
||||||
</ConfigProvider>
|
</RedoUndoStackProvider>
|
||||||
</StorageProvider>
|
</ConfigProvider>
|
||||||
|
</StorageProvider>
|
||||||
|
</LayoutProvider>
|
||||||
),
|
),
|
||||||
})),
|
})),
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user