This commit is contained in:
Guy Ben-Aharon
2024-08-18 11:59:04 +03:00
parent c195104a60
commit 5537f52eb9
11 changed files with 130 additions and 11 deletions

View File

@@ -5,6 +5,7 @@ import { DatabaseType } from '@/lib/domain/database-type';
import { DBField } from '@/lib/domain/db-field'; import { DBField } from '@/lib/domain/db-field';
import { DBIndex } from '@/lib/domain/db-index'; import { DBIndex } from '@/lib/domain/db-index';
import { DBRelationship } from '@/lib/domain/db-relationship'; import { DBRelationship } from '@/lib/domain/db-relationship';
import { Diagram } from '@/lib/domain/diagram';
export interface ChartDBContext { export interface ChartDBContext {
diagramId: string; diagramId: string;
@@ -16,6 +17,7 @@ export interface ChartDBContext {
// General operations // General operations
updateDiagramId: (id: string) => void; updateDiagramId: (id: string) => void;
updateDiagramName: (name: string) => void; updateDiagramName: (name: string) => void;
loadDiagram: (diagramId: string) => Promise<Diagram | null>;
// Database type operations // Database type operations
updateDatabaseType: (databaseType: DatabaseType) => void; updateDatabaseType: (databaseType: DatabaseType) => void;
@@ -80,6 +82,7 @@ export const chartDBContext = createContext<ChartDBContext>({
// General operations // General operations
updateDiagramId: emptyFn, updateDiagramId: emptyFn,
updateDiagramName: emptyFn, updateDiagramName: emptyFn,
loadDiagram: emptyFn,
// Database type operations // Database type operations
updateDatabaseType: emptyFn, updateDatabaseType: emptyFn,

View File

@@ -6,6 +6,7 @@ import { DatabaseType } from '@/lib/domain/database-type';
import { DBField } from '@/lib/domain/db-field'; import { DBField } from '@/lib/domain/db-field';
import { DBIndex } from '@/lib/domain/db-index'; import { DBIndex } from '@/lib/domain/db-index';
import { DBRelationship } from '@/lib/domain/db-relationship'; import { DBRelationship } from '@/lib/domain/db-relationship';
import { Diagram } from '@/lib/domain/diagram';
export const ChartDBProvider: React.FC<React.PropsWithChildren> = ({ export const ChartDBProvider: React.FC<React.PropsWithChildren> = ({
children, children,
@@ -285,6 +286,11 @@ export const ChartDBProvider: React.FC<React.PropsWithChildren> = ({
); );
}; };
const loadDiagram = (diagramId: string) => {
console.log('Loading diagram', diagramId);
return Promise.resolve({} as Diagram);
};
return ( return (
<chartDBContext.Provider <chartDBContext.Provider
value={{ value={{
@@ -295,6 +301,7 @@ export const ChartDBProvider: React.FC<React.PropsWithChildren> = ({
relationships, relationships,
updateDiagramId, updateDiagramId,
updateDiagramName, updateDiagramName,
loadDiagram,
updateDatabaseType, updateDatabaseType,
createTable, createTable,
addTable, addTable,

View File

@@ -0,0 +1,13 @@
import { createContext } from 'react';
import { emptyFn } from '@/lib/utils';
import { ChartDBConfig } from '@/lib/domain/config';
export interface ConfigContext {
config?: ChartDBConfig;
updateConfig: (config: Partial<ChartDBConfig>) => Promise<void>;
}
export const ConfigContext = createContext<ConfigContext>({
config: undefined,
updateConfig: emptyFn,
});

View File

@@ -0,0 +1,36 @@
import React, { useEffect } from 'react';
import { ConfigContext } from './config-context';
import { useData } from '@/hooks/use-data';
import { ChartDBConfig } from '@/lib/domain/config';
export const ConfigProvider: React.FC<React.PropsWithChildren> = ({
children,
}) => {
const { getConfig, updateConfig: updateDataConfig } = useData();
const [config, setConfig] = React.useState<ChartDBConfig | undefined>();
useEffect(() => {
const loadConfig = async () => {
const config = await getConfig();
setConfig(config);
};
loadConfig();
}, [getConfig]);
const updateConfig = async (config: Partial<ChartDBConfig>) => {
await updateDataConfig(config);
setConfig((prevConfig) =>
prevConfig
? { ...prevConfig, ...config }
: { ...{ defaultDiagramId: '' }, ...config }
);
};
return (
<ConfigContext.Provider value={{ config, updateConfig }}>
{children}
</ConfigContext.Provider>
);
};

View File

@@ -3,8 +3,13 @@ import { Diagram } from '@/lib/domain/diagram';
import { emptyFn } from '@/lib/utils'; import { emptyFn } from '@/lib/utils';
import { DBRelationship } from '@/lib/domain/db-relationship'; import { DBRelationship } from '@/lib/domain/db-relationship';
import { DBTable } from '@/lib/domain/db-table'; import { DBTable } from '@/lib/domain/db-table';
import { ChartDBConfig } from '@/lib/domain/config';
export interface DataContext { export interface DataContext {
// Config operations
getConfig: () => Promise<ChartDBConfig | undefined>;
updateConfig: (config: Partial<ChartDBConfig>) => Promise<void>;
// Diagram operations // Diagram operations
addDiagram: (params: { diagram: Diagram }) => Promise<void>; addDiagram: (params: { diagram: Diagram }) => Promise<void>;
listDiagrams: () => Promise<Diagram[]>; listDiagrams: () => Promise<Diagram[]>;
@@ -49,6 +54,9 @@ export interface DataContext {
} }
export const dataContext = createContext<DataContext>({ export const dataContext = createContext<DataContext>({
getConfig: emptyFn,
updateConfig: emptyFn,
addDiagram: emptyFn, addDiagram: emptyFn,
listDiagrams: emptyFn, listDiagrams: emptyFn,
getDiagram: emptyFn, getDiagram: emptyFn,

View File

@@ -4,6 +4,7 @@ import Dexie, { type EntityTable } from 'dexie';
import { Diagram } from '@/lib/domain/diagram'; import { Diagram } from '@/lib/domain/diagram';
import { DBTable } from '@/lib/domain/db-table'; import { DBTable } from '@/lib/domain/db-table';
import { DBRelationship } from '@/lib/domain/db-relationship'; import { DBRelationship } from '@/lib/domain/db-relationship';
import { ChartDBConfig } from '@/lib/domain/config';
export const DataProvider: React.FC<React.PropsWithChildren> = ({ export const DataProvider: React.FC<React.PropsWithChildren> = ({
children, children,
@@ -21,6 +22,10 @@ export const DataProvider: React.FC<React.PropsWithChildren> = ({
DBRelationship & { diagramId: string }, DBRelationship & { diagramId: string },
'id' // primary key "id" (for the typings only) 'id' // primary key "id" (for the typings only)
>; >;
config: EntityTable<
ChartDBConfig & { id: number },
'id' // primary key "id" (for the typings only)
>;
}; };
// Schema declaration: // Schema declaration:
@@ -30,8 +35,28 @@ export const DataProvider: React.FC<React.PropsWithChildren> = ({
'++id, diagramId, name, x, y, fields, indexes, color, createdAt', '++id, diagramId, name, x, y, fields, indexes, color, createdAt',
db_relationships: db_relationships:
'++id, diagramId, name, sourceTableId, targetTableId, sourceFieldId, targetFieldId, type, createdAt', '++id, diagramId, name, sourceTableId, targetTableId, sourceFieldId, targetFieldId, type, createdAt',
config: '++id, defaultDiagramId',
}); });
db.on('ready', async () => {
const config = await getConfig();
if (!config) {
await db.config.add({
id: 1,
defaultDiagramId: '',
});
}
});
const getConfig = async (): Promise<ChartDBConfig | undefined> => {
return await db.config.get(1);
};
const updateConfig = async (config: Partial<ChartDBConfig>) => {
await db.config.update(1, config);
};
const addDiagram = async ({ diagram }: { diagram: Diagram }) => { const addDiagram = async ({ diagram }: { diagram: Diagram }) => {
await db.diagrams.add(diagram); await db.diagrams.add(diagram);
}; };
@@ -167,6 +192,8 @@ export const DataProvider: React.FC<React.PropsWithChildren> = ({
return ( return (
<dataContext.Provider <dataContext.Provider
value={{ value={{
getConfig,
updateConfig,
addDiagram, addDiagram,
listDiagrams, listDiagrams,
getDiagram, getDiagram,

View File

@@ -20,6 +20,7 @@ import { Diagram } from '@/lib/domain/diagram';
import { generateId } from '@/lib/utils'; import { generateId } from '@/lib/utils';
import { useCreateDiagramDialog } from '@/hooks/use-create-diagram-dialog'; import { useCreateDiagramDialog } from '@/hooks/use-create-diagram-dialog';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { useConfig } from '@/hooks/use-config';
enum CreateDiagramDialogStep { enum CreateDiagramDialogStep {
SELECT_DATABASE = 'SELECT_DATABASE', SELECT_DATABASE = 'SELECT_DATABASE',
@@ -37,6 +38,7 @@ export const CreateDiagramDialog: React.FC<CreateDiagramDialogProps> = ({
DatabaseType.GENERIC DatabaseType.GENERIC
); );
const { closeCreateDiagramDialog } = useCreateDiagramDialog(); const { closeCreateDiagramDialog } = useCreateDiagramDialog();
const { updateConfig } = useConfig();
const [scriptResult, setScriptResult] = React.useState(''); const [scriptResult, setScriptResult] = React.useState('');
const [step, setStep] = React.useState<CreateDiagramDialogStep>( const [step, setStep] = React.useState<CreateDiagramDialogStep>(
CreateDiagramDialogStep.SELECT_DATABASE CreateDiagramDialogStep.SELECT_DATABASE
@@ -48,7 +50,6 @@ export const CreateDiagramDialog: React.FC<CreateDiagramDialogProps> = ({
useEffect(() => { useEffect(() => {
const fetchDiagrams = async () => { const fetchDiagrams = async () => {
const diagrams = await listDiagrams(); const diagrams = await listDiagrams();
console.log({ diagrams });
setDiagramNumber(diagrams.length + 1); setDiagramNumber(diagrams.length + 1);
}; };
fetchDiagrams(); fetchDiagrams();
@@ -63,6 +64,7 @@ export const CreateDiagramDialog: React.FC<CreateDiagramDialogProps> = ({
relationships: [], relationships: [],
}; };
await addDiagram({ diagram }); await addDiagram({ diagram });
await updateConfig({ defaultDiagramId: diagram.id });
closeCreateDiagramDialog(); closeCreateDiagramDialog();
navigate(`/diagrams/${diagram.id}`); navigate(`/diagrams/${diagram.id}`);
}, [ }, [
@@ -71,6 +73,7 @@ export const CreateDiagramDialog: React.FC<CreateDiagramDialogProps> = ({
addDiagram, addDiagram,
closeCreateDiagramDialog, closeCreateDiagramDialog,
navigate, navigate,
updateConfig,
]); ]);
const renderDatabaseOption = useCallback((type: DatabaseType) => { const renderDatabaseOption = useCallback((type: DatabaseType) => {

4
src/hooks/use-config.ts Normal file
View File

@@ -0,0 +1,4 @@
import { useContext } from 'react';
import { ConfigContext } from '@/context/config-context/config-context';
export const useConfig = () => useContext(ConfigContext);

3
src/lib/domain/config.ts Normal file
View File

@@ -0,0 +1,3 @@
export interface ChartDBConfig {
defaultDiagramId: string;
}

View File

@@ -8,18 +8,30 @@ import {
} from '@/components/resizable/resizable'; } from '@/components/resizable/resizable';
import { SidePanel } from './side-panel/side-panel'; import { SidePanel } from './side-panel/side-panel';
import { Canvas } from './canvas/canvas'; import { Canvas } from './canvas/canvas';
import { useParams } from 'react-router-dom'; import { useNavigate, useParams } from 'react-router-dom';
import { useCreateDiagramDialog } from '@/hooks/use-create-diagram-dialog'; import { useCreateDiagramDialog } from '@/hooks/use-create-diagram-dialog';
import { useConfig } from '@/hooks/use-config';
export const EditorPage: React.FC = () => { export const EditorPage: React.FC = () => {
const { openCreateDiagramDialog } = useCreateDiagramDialog(); const { openCreateDiagramDialog } = useCreateDiagramDialog();
const { diagramId } = useParams<{ diagramId: string }>(); const { diagramId } = useParams<{ diagramId: string }>();
const { config } = useConfig();
const navigate = useNavigate();
useEffect(() => { useEffect(() => {
if (!diagramId) { if (!config) {
return;
}
if (diagramId) {
// load diagram
console.log('load diagram to memory');
} else if (!diagramId && config.defaultDiagramId) {
navigate(`/diagrams/${config.defaultDiagramId}`);
} else {
openCreateDiagramDialog(); openCreateDiagramDialog();
} }
}, [diagramId, openCreateDiagramDialog]); }, [diagramId, openCreateDiagramDialog, config, navigate]);
return ( return (
<section className="bg-background h-screen w-screen flex flex-col"> <section className="bg-background h-screen w-screen flex flex-col">

View File

@@ -6,12 +6,14 @@ import { ChartDBProvider } from './context/chartdb-context/chartdb-provider';
import { ReactFlowProvider } from '@xyflow/react'; import { ReactFlowProvider } from '@xyflow/react';
import { DataProvider } from './context/data-context/data-provider'; import { DataProvider } from './context/data-context/data-provider';
import { CreateDiagramDialogProvider } from './dialogs/create-diagram-dialog/create-diagram-dialog-provider'; import { CreateDiagramDialogProvider } from './dialogs/create-diagram-dialog/create-diagram-dialog-provider';
import { ConfigProvider } from './context/config-context/config-provider';
const routes: RouteObject[] = [ const routes: RouteObject[] = [
...['', 'diagrams/:diagramId'].map((path) => ({ ...['', 'diagrams/:diagramId'].map((path) => ({
path, path,
element: ( element: (
<DataProvider> <DataProvider>
<ConfigProvider>
<ChartDBProvider> <ChartDBProvider>
<CreateDiagramDialogProvider> <CreateDiagramDialogProvider>
<ReactFlowProvider> <ReactFlowProvider>
@@ -19,6 +21,7 @@ const routes: RouteObject[] = [
</ReactFlowProvider> </ReactFlowProvider>
</CreateDiagramDialogProvider> </CreateDiagramDialogProvider>
</ChartDBProvider> </ChartDBProvider>
</ConfigProvider>
</DataProvider> </DataProvider>
), ),
})), })),