=
>
}
-
)
}
diff --git a/src/pages/database/db-controller/relationship-controller/relationship-controller.tsx b/src/pages/database/db-controller/relationship-controller/relationship-controller.tsx
index 7398bee..e6b76c6 100644
--- a/src/pages/database/db-controller/relationship-controller/relationship-controller.tsx
+++ b/src/pages/database/db-controller/relationship-controller/relationship-controller.tsx
@@ -8,7 +8,7 @@ import RelationshipAccordionBody from "./relationship-accordion-item/relationshi
import Modal from "@/components/modal/modal";
import CreateRelationshipForm from "./create-relationship-form/create-relationship-form";
import { RelationshipInsertType, RelationshipType } from "@/lib/schemas/relationship-schema";
-import { useDatabase } from "@/providers/database-provider/database-provider";
+import { useDatabase, useDatabaseOperations } from "@/providers/database-provider/database-provider";
import { v4 } from "uuid";
import { useDiagram } from "@/providers/diagram-provider/diagram-provider";
@@ -24,8 +24,9 @@ const RelationshipController: React.FC
= ({ }) => {
const [relationship, setRelationship] = useState(undefined);
const [isValid, setIsValid] = useState(false);
const { isOpen, onOpen, onOpenChange } = useDisclosure();
- const { createRelationship, database } = useDatabase();
- const { relationships } = database ;
+ const { database } = useDatabase();
+ const { createRelationship, } = useDatabaseOperations();
+ const { relationships } = database;
const { t } = useTranslation();
const [selectedRelationship, setSelectedRelationship] = useState(new Set([]));
@@ -37,7 +38,7 @@ const RelationshipController: React.FC = ({ }) => {
createRelationship({
id: newRelationshipId,
- ...relationship,
+ ...relationship,
} as RelationshipInsertType);
setSelectedRelationship(new Set([newRelationshipId]) as any);
diff --git a/src/pages/database/db-controller/tables-controller/table-accordion-item/field/field-item.tsx b/src/pages/database/db-controller/tables-controller/table-accordion-item/field/field-item.tsx
index a6f8254..3e774ab 100644
--- a/src/pages/database/db-controller/tables-controller/table-accordion-item/field/field-item.tsx
+++ b/src/pages/database/db-controller/tables-controller/table-accordion-item/field/field-item.tsx
@@ -7,7 +7,7 @@ import { useTranslation } from "react-i18next";
import { CSS } from "@dnd-kit/utilities";
import { FieldInsertType, FieldType } from "@/lib/schemas/field-schema";
import { Key, useEffect, useState } from "react";
-import { useDatabase } from "@/providers/database-provider/database-provider";
+import { useDatabase, useDatabaseOperations } from "@/providers/database-provider/database-provider";
import Autocomplete from "@/components/auto-complete/auto-complete";
import ToggleButton from "@/components/toggle/toggle";
interface Props {
@@ -21,8 +21,9 @@ const FieldItem: React.FC = ({ field }) => {
const [fieldName, setFieldName] = useState(field.name);
const [popOverOpen, setPopOverOpen] = useState(false);
- const { deleteField, editField, data_types } = useDatabase();
-
+ const { data_types } = useDatabase();
+ const {deleteField, editField} = useDatabaseOperations() ;
+
const [note, setNote] = useState(field.note as string | undefined);
const [selectedType, setSelectedType] = useState(field.typeId as string | undefined);
const { t } = useTranslation();
diff --git a/src/pages/database/db-controller/tables-controller/table-accordion-item/field/field-list.tsx b/src/pages/database/db-controller/tables-controller/table-accordion-item/field/field-list.tsx
index d8969c8..147d4e5 100644
--- a/src/pages/database/db-controller/tables-controller/table-accordion-item/field/field-list.tsx
+++ b/src/pages/database/db-controller/tables-controller/table-accordion-item/field/field-list.tsx
@@ -8,7 +8,7 @@ import { arrayMove, SortableContext, verticalListSortingStrategy } from "@dnd-ki
import { FieldType } from "@/lib/schemas/field-schema";
import { TableType } from "@/lib/schemas/table-schema";
import { useCallback, useEffect, useState } from "react";
-import { useDatabase } from "@/providers/database-provider/database-provider";
+import { useDatabase, useDatabaseOperations } from "@/providers/database-provider/database-provider";
import { v4 } from "uuid";
import { getNextSequence } from "@/utils/field";
@@ -22,7 +22,7 @@ const FieldList: React.FC = ({ table }) => {
const { t } = useTranslation();
const [fields, setFields] = useState(table.fields);
- const { createField, orderTableFields } = useDatabase();
+ const { createField, orderTableFields } = useDatabaseOperations();
useEffect(() => {
setFields(table.fields)
diff --git a/src/pages/database/db-controller/tables-controller/table-accordion-item/table-accordion-body.tsx b/src/pages/database/db-controller/tables-controller/table-accordion-item/table-accordion-body.tsx
index be30ec0..c622d7a 100644
--- a/src/pages/database/db-controller/tables-controller/table-accordion-item/table-accordion-body.tsx
+++ b/src/pages/database/db-controller/tables-controller/table-accordion-item/table-accordion-body.tsx
@@ -8,7 +8,7 @@ import ColorPicker from "@/components/color-picker/color-picker";
import FieldList from "./field/field-list";
import IndexesList from "./index/indexes-list";
import { TableType } from "@/lib/schemas/table-schema";
-import { useDatabase } from "@/providers/database-provider/database-provider";
+import { useDatabase, useDatabaseOperations } from "@/providers/database-provider/database-provider";
import { getNextSequence } from "@/utils/field";
import { v4 } from "uuid";
@@ -22,7 +22,7 @@ const TableAccordionBody: React.FC = ({ table }) => {
const [selectedKeys, setSelectedKeys] = useState(new Set(["fields"]));
const [note, setNote] = useState(table.note ? table.note : "");
const { t } = useTranslation();
- const { editTable, createField } = useDatabase();
+ const { editTable, createField } = useDatabaseOperations();
const onColorChange = useCallback((color: string | undefined) => {
diff --git a/src/pages/database/db-controller/tables-controller/table-accordion-item/table-accordion-header.tsx b/src/pages/database/db-controller/tables-controller/table-accordion-item/table-accordion-header.tsx
index ecd1a9c..996f027 100644
--- a/src/pages/database/db-controller/tables-controller/table-accordion-item/table-accordion-header.tsx
+++ b/src/pages/database/db-controller/tables-controller/table-accordion-item/table-accordion-header.tsx
@@ -6,7 +6,7 @@ import { useCallback, useEffect, useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
import { TableInsertType, TableType } from "@/lib/schemas/table-schema";
-import { useDatabase } from "@/providers/database-provider/database-provider";
+import { useDatabase, useDatabaseOperations } from "@/providers/database-provider/database-provider";
import { v4 } from "uuid";
import { getNextSequence } from "@/utils/field";
import { useDiagram } from "@/providers/diagram-provider/diagram-provider";
@@ -18,7 +18,7 @@ export interface TableAccordionHeaderProps {
const TableAccordionHeader: React.FC = ({ table, isOpen }) => {
- const { editTable, deleteTable, createField } = useDatabase();
+ const { editTable, deleteTable, createField } = useDatabaseOperations();
const [popOverOpen, setPopOverOpen] = useState(false);
const [tableName, setTableName] = useState(table.name);
diff --git a/src/pages/database/db-controller/tables-controller/tables-controller.tsx b/src/pages/database/db-controller/tables-controller/tables-controller.tsx
index 1158906..2005be5 100644
--- a/src/pages/database/db-controller/tables-controller/tables-controller.tsx
+++ b/src/pages/database/db-controller/tables-controller/tables-controller.tsx
@@ -5,7 +5,7 @@ import { useTranslation } from "react-i18next";
import { useCallback, useEffect, useState } from "react";
import TableAccordionHeader from "./table-accordion-item/table-accordion-header";
import TableAccordionBody from "./table-accordion-item/table-accordion-body";
-import { useDatabase } from "@/providers/database-provider/database-provider";
+import { useDatabase, useDatabaseOperations } from "@/providers/database-provider/database-provider";
import { TableInsertType, TableType } from "@/lib/schemas/table-schema";
import { v4 } from "uuid";
import { useDiagram } from "@/providers/diagram-provider/diagram-provider";
@@ -17,8 +17,8 @@ interface Props { }
const TablesController: React.FC = ({ }) => {
- const { database, createTable } = useDatabase();
-
+ const { database } = useDatabase();
+ const {createTable} = useDatabaseOperations() ;
const { tables } = database ;
const { t } = useTranslation();
const [selectedTable, setSelectedTable] = useState(new Set([]));
diff --git a/src/pages/database/table/field.tsx b/src/pages/database/table/field.tsx
index 2084784..e55d45c 100644
--- a/src/pages/database/table/field.tsx
+++ b/src/pages/database/table/field.tsx
@@ -1,6 +1,6 @@
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/tooltip/tooltip";
import { FieldType } from "@/lib/schemas/field-schema";
-import { useDatabase } from "@/providers/database-provider/database-provider";
+import { useDatabase, useDatabaseOperations } from "@/providers/database-provider/database-provider";
import { useDiagram } from "@/providers/diagram-provider/diagram-provider";
import { Button, cn, select } from "@heroui/react";
import { Handle, Position, useConnection } from "@xyflow/react";
@@ -12,8 +12,8 @@ import React, { useEffect, useState } from "react";
interface Props {
field: FieldType,
showHandles?: boolean,
- highlight?: boolean ,
- showTargetHandle? : boolean
+ highlight?: boolean,
+ showTargetHandle?: boolean
}
@@ -25,21 +25,18 @@ export const TARGET_PREFIX = "target_";
const Field: React.FC = ({ field, showHandles, highlight }) => {
const [editMode, setEditMode] = useState(false);
- const { deleteField, editField } = useDatabase();
+ const { deleteField, editField } = useDatabaseOperations();
const [fieldName, setFieldName] = useState(field.name);
- const {isConnectionInProgress} = useDiagram() ;
+ const { isConnectionInProgress } = useDiagram();
useEffect(() => {
setFieldName(field.name);
}, [field.name]);
-
-
const removeField = () => {
deleteField(field.id)
}
-
const saveFieldName = () => {
editField({
id: field.id,
@@ -48,11 +45,11 @@ const Field: React.FC = ({ field, showHandles, highlight }) => {
setEditMode(false);
}
-
-
+ // console.log("render field ", field.name)
+
return (
{
@@ -125,12 +122,12 @@ const Field: React.FC
= ({ field, showHandles, highlight }) => {
type="source"
position={Position.Left}
id={LEFT_PREFIX + field.id}
- className="w-4 h-4 border-4 bg-primary dark:border-default-900"
+ className="w-4 h-4 border-3 bg-primary dark:border-default-900"
/>
diff --git a/src/pages/database/table/relationship.tsx b/src/pages/database/table/relationship.tsx
index 97101a3..4683861 100644
--- a/src/pages/database/table/relationship.tsx
+++ b/src/pages/database/table/relationship.tsx
@@ -113,6 +113,7 @@ const Relationship: React.FC> = (props) => {
}
}, [data?.relationship.cardinality, selected]);
+ // console.log ("render relationship " , props.data?.relationship.sourceTable.name , props.data?.relationship.targetTable.name)
return (
<>
diff --git a/src/pages/database/table/table.tsx b/src/pages/database/table/table.tsx
index 7cf5b25..22f1cfc 100644
--- a/src/pages/database/table/table.tsx
+++ b/src/pages/database/table/table.tsx
@@ -14,26 +14,28 @@ import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/tooltip/to
import FieldComponent from "./field";
import { FieldType } from "@/lib/schemas/field-schema";
import { TableInsertType, TableType } from "@/lib/schemas/table-schema";
-import { useDatabase } from "@/providers/database-provider/database-provider";
+import { useDatabase, useDatabaseOperations } from "@/providers/database-provider/database-provider";
import { useTranslation } from "react-i18next";
import { RelationshipType } from "@/lib/schemas/relationship-schema";
import { useDiagram } from "@/providers/diagram-provider/diagram-provider";
-
+import useGetRelatedEdges from "@/hooks/use-get-related-edges";
export type TableProps = Node<{
table: TableType,
+ overlapping?: boolean,
+ pulsing?: boolean,
}>
-const Table: React.FC> = ({ selected, data: { table } }) => {
-
+const Table: React.FC> = (props) => {
+ const { selected, data: { table, overlapping = false, pulsing = false } } = props;
const [editMode, setEditMode] = useState(false);
const [tableName, setTableName] = useState(table.name);
- const { editTable } = useDatabase();
-
+ const { editTable } = useDatabaseOperations();
+ const edges = useGetRelatedEdges(table.id as string);
const { focusOnTable } = useDiagram();
- const { t } = useTranslation();
+ const { t } = useTranslation();
- useEffect(() => {
+ useEffect(() => {
setTableName(table.name);
}, [table.name])
@@ -46,8 +48,6 @@ const Table: React.FC> = ({ selected, data: { table } }) =
focusOnTable(table.id, false);
}, [table])
- const edges = useStore((store) => store.edges) as Edge[];
-
const highlightedEdges: Edge[] = useMemo(() => {
return edges.filter((edge: Edge) => edge.animated || edge.selected);
}, [edges]);
@@ -68,86 +68,102 @@ const Table: React.FC> = ({ selected, data: { table } }) =
}, [table.fields, selected, highlightedEdges]);
+ useEffect(() => {
+ console.log("re-render ", table.name)
+
+ }, [useDatabase]) ;
+
return (
-
-
-
-
-
- {
- editMode && <>
-
setTableName(event.target.value)}
- value={tableName}
- onBlur={saveTableName}
- type="text"
- className="rounded-md outline-none px-2 py-0.5 w-full border-[0.5px] border-primary-700 font-bold bg-slate-100 focus-visible:ring-0 text-sm dark:bg-transparent dark:text-white"
- />
+
+
+
+
+
+ {
+ editMode && <>
+
setTableName(event.target.value)}
+ value={tableName}
+ onBlur={saveTableName}
+ type="text"
+ className="rounded-md outline-none px-2 py-0.5 w-full border-[0.5px] border-primary-700 font-bold bg-slate-100 focus-visible:ring-0 text-sm dark:bg-transparent dark:text-white"
+ />
+
+ >
+ }
+ {
+ !editMode &&
+ <>
+
+
+
+
+
+ {t("table.double_click")}
+
+
+
+
+
- >
- }
- {
- !editMode &&
- <>
-
-
-
-
-
- {t("table.double_click")}
-
-
+
+ >
+ }
+
+
+ {fields}
+
+
-
-
-
-
- >
- }
-
-
- {fields}
-
-
-
)
};
export default React.memo(Table)
-
\ No newline at end of file
diff --git a/src/providers/database-history/database-history-provider.tsx b/src/providers/database-history/database-history-provider.tsx
index 0e8f134..9598c8d 100644
--- a/src/providers/database-history/database-history-provider.tsx
+++ b/src/providers/database-history/database-history-provider.tsx
@@ -1,7 +1,7 @@
import { useCallback, useContext, useEffect, useRef } from "react";
import DatabaseHistoryContext from "./database-history-context";
import useUndo from 'use-undo';
-import { useDatabase } from "../database-provider/database-provider";
+import { useDatabase, useDatabaseOperations } from "../database-provider/database-provider";
import hash from 'object-hash';
import { DBDiffOperation, mapDiffToDBDiffOperation, normalizeDatabase } from "@/utils/database";
import { compare } from 'fast-json-patch';
@@ -12,7 +12,9 @@ interface Props { children: React.ReactNode };
const DatabaseHistoryProvider: React.FC = ({ children }) => {
const udpateDbFlag = useRef(false);
- const { database, executeDbDiffOps } = useDatabase();
+ const { database } = useDatabase();
+ const { executeDbDiffOps} = useDatabaseOperations() ;
+
const [datatbaseState, { set, undo: undoChanges, redo: redoChanges, canUndo, canRedo }] = useUndo(database);
useEffect(() => {
@@ -21,8 +23,6 @@ const DatabaseHistoryProvider: React.FC = ({ children }) => {
const databaseHash: string = hash(database, { algorithm: 'sha1' });
if (presentHash != databaseHash)
set(database);
-
-
}, [database]);
@@ -47,15 +47,11 @@ const DatabaseHistoryProvider: React.FC = ({ children }) => {
const differences = compare(normalizedDatabase, normalizedPresent);
if (differences && differences.length > 0) {
-
const operations: DBDiffOperation[] = mapDiffToDBDiffOperation(differences);
executeDbDiffOps(operations)
}
}, [datatbaseState.present]);
-
-
-
return (
Promise,
editTable: (table: TableInsertType) => Promise,
deleteTable: (id: string) => Promise,
- updateTablePositions: (tables: TableInsertType[]) => Promise ,
+ updateTablePositions: (tables: TableInsertType[]) => Promise,
deleteMultiTables: (ids: string[]) => Promise
// field operations
createField: (field: FieldInsertType) => Promise,
editField: (field: FieldInsertType) => Promise,
deleteField: (id: string) => Promise,
orderTableFields: (fields: FieldType[]) => Promise,
+ getField: (tableId: string, id: string) => FieldType | undefined,
// relationship operations
createRelationship: (relationship: RelationshipInsertType) => Promise,
editRelationship: (relationship: RelationshipInsertType) => Promise,
deleteRelationship: (id: string) => Promise,
- deleteMultiRelationships: (ids: string[]) => Promise ,
-
- executeDbDiffOps : ( operations : DBDiffOperation[]) => void ,
-
+ deleteMultiRelationships: (ids: string[]) => Promise,
+ // execute the diff operation whenver user click in undo or redo
+ executeDbDiffOps: (operations: DBDiffOperation[]) => void,
}
+export const DatabaseDataContext = createContext({} as DatabaseDataContextType);
+export const DatabaseOperationsContext = createContext({} as DatabaseOperationsContextType);
-export default createContext({} as DatabaseContextType);
-
diff --git a/src/providers/database-provider/database-provider.tsx b/src/providers/database-provider/database-provider.tsx
index fc50df7..79351b4 100644
--- a/src/providers/database-provider/database-provider.tsx
+++ b/src/providers/database-provider/database-provider.tsx
@@ -1,8 +1,8 @@
-import DatabaseContext from "./database-context";
+import { DatabaseDataContext, DatabaseOperationsContext } from "./database-context";
import { useCallback, useContext, useEffect, useState } from "react";
import { db, powerSyncDb } from "../sync-provider/sync-provider";
-import { TableInsertType, tables } from "@/lib/schemas/table-schema";
+import { TableInsertType, tables, TableType } from "@/lib/schemas/table-schema";
import { useQuery } from "@powersync/react";
import { toCompilableQuery } from "@powersync/drizzle-driver";
import { asc, desc, eq, inArray, or } from "drizzle-orm";
@@ -113,6 +113,13 @@ const DatabaseProvider: React.FC = ({ children }) => {
})
}, [db]);
+
+ const getField = useCallback((tableId: string, id: string) => {
+ const table: TableType | undefined = (database as any).tables.find((table: TableType) => table.id == tableId);
+ if (table)
+ return table.fields.find((field: FieldType) => field.id == id);
+ }, [database])
+
const orderTableFields = useCallback(async (fieldsList: FieldType[]): Promise => {
const caseStatements = fieldsList
.map((field, index) => `WHEN '${field.id}' THEN ${index}`)
@@ -188,7 +195,7 @@ const DatabaseProvider: React.FC = ({ children }) => {
await tx.insert(fields).values(Object.values(operation.table.fields));
}
else if (operation.type === "UPDATE_TABLE") {
-
+
await tx.update(tables).set(operation.changes).where(eq(tables.id, operation.tableId));
} else if (operation.type === "DELETE_TABLE") {
@@ -216,43 +223,52 @@ const DatabaseProvider: React.FC = ({ children }) => {
}
})
- }, [db, currentDatabaseId])
+ }, [db, currentDatabaseId]);
+
return (
-
- {
- !isLoading && database &&
-
- {children}
-
- }
-
+
+
+
+ {
+ !isLoading && database &&
+
+ {children}
+
+ }
+
+
)
}
-export const useDatabase = () => useContext(DatabaseContext);
+export const useDatabase = () => useContext(DatabaseDataContext);
+export const useDatabaseOperations = () => useContext(DatabaseOperationsContext);
export default DatabaseProvider;
diff --git a/tailwind.config.js b/tailwind.config.js
index 32bcc5a..95d86d7 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -6,7 +6,7 @@ export default {
"./index.html",
"./src/**/*.{js,ts,jsx,tsx}",
"./node_modules/@nextui-org/theme/dist/**/*.{js,ts,jsx,tsx}",
- "./node_modules/@heroui/theme/dist/components/(button|code|dropdown|input|kbd|link|navbar|snippet|toggle|popover|ripple|spinner|menu|divider|form|modal).js",
+ "./node_modules/@heroui/theme/dist/components/(button|code|dropdown|input|kbd|link|navbar|snippet|toggle|popover|ripple|spinner|menu|divider|form|modal|toast).js",
],
darkMode: "class",