From ed13965f61d5622517c9e3c8e31c810aa1eaa26b Mon Sep 17 00:00:00 2001 From: KarimTamani Date: Mon, 26 May 2025 18:19:50 +0100 Subject: [PATCH] search for table & relationships functionalities implemented --- src/hooks/use-relationship-name.tsx | 12 +++-- src/i18/languages/en.ts | 8 ++- src/pages/database/database-page.tsx | 2 +- .../database/db-controller/db-controller.tsx | 2 +- .../relationship-accordion-body.tsx | 10 +--- .../relationship-controller.tsx | 49 ++++++++++++++----- .../table-accordion-header.tsx | 26 +++++++--- .../tables-controller/tables-controller.tsx | 26 ++++++---- src/pages/database/table/field.tsx | 19 ++++++- src/pages/database/table/table.tsx | 37 ++++++++++++-- src/utils/field.ts | 10 ++++ src/utils/tables.ts | 24 ++++++++- 12 files changed, 174 insertions(+), 51 deletions(-) diff --git a/src/hooks/use-relationship-name.tsx b/src/hooks/use-relationship-name.tsx index 5b28a13..a9726d7 100644 --- a/src/hooks/use-relationship-name.tsx +++ b/src/hooks/use-relationship-name.tsx @@ -6,11 +6,17 @@ import { useTranslation } from "react-i18next"; export const useRelationshipName = (relationship: RelationshipType) => { const { t } = useTranslation(); const name: string = useMemo(() => { - if ( !relationship.sourceTable || !relationship.targetTable || !relationship.sourceField || !relationship.targetField) - return "" ; - return `${relationship.sourceTable?.name}_${relationship.sourceField?.name} - ${relationship.targetTable?.name}_${relationship.targetField?.name}_fk` + return getDefaultRelationshipName(relationship) ; }, [relationship, t]) return { name } +} + + +export const getDefaultRelationshipName = (relationship: RelationshipType) => { + + if (!relationship.sourceTable || !relationship.targetTable || !relationship.sourceField || !relationship.targetField) + return ""; + return `${relationship.sourceTable?.name}_${relationship.sourceField?.name} - ${relationship.targetTable?.name}_${relationship.targetField?.name}_fk` } \ No newline at end of file diff --git a/src/i18/languages/en.ts b/src/i18/languages/en.ts index 5f3db10..a3f6187 100644 --- a/src/i18/languages/en.ts +++ b/src/i18/languages/en.ts @@ -20,6 +20,8 @@ export const en = { add_table: "Add Table", add_field: "Add Field", add_index: "Add Index", + delete_table : "Delete Table" , + duplicate : "Duplicate" , add_relationship: "Add Relationship", show_code: "Show code", fields: "Fields", @@ -55,7 +57,7 @@ export const en = { }, delete: "Delete", field_setting: "Field Setting", - table_actions: "Field Actions", + table_actions: "Table Actions", actions: "Actions", field_note: "Field note", @@ -71,7 +73,9 @@ export const en = { }, table: { double_click: "Double click to edit" , - overlapping_tables : "Overlapping Tables" + overlapping_tables : "Overlapping Tables" , + show_more : "Show more" , + show_less : "Show less" }, control_buttons: { redo: "Redo", diff --git a/src/pages/database/database-page.tsx b/src/pages/database/database-page.tsx index 5868e56..69d3426 100644 --- a/src/pages/database/database-page.tsx +++ b/src/pages/database/database-page.tsx @@ -157,7 +157,7 @@ const DatabasePage: React.FC = () => { return (
-
+
diff --git a/src/pages/database/db-controller/db-controller.tsx b/src/pages/database/db-controller/db-controller.tsx index 408795b..a176709 100644 --- a/src/pages/database/db-controller/db-controller.tsx +++ b/src/pages/database/db-controller/db-controller.tsx @@ -21,7 +21,7 @@ const DBController: React.FC = ({ }) => { return ( = ({ r }, [relationship.cardinality]) - - - useEffect(() => { - console.log("re-render relationship controlelr", name); - - }, [relationship]) - - if (!relationship.sourceTable || !relationship.targetTable) return; @@ -103,7 +95,7 @@ const RelationshipAccordionBody: React.FC = ({ r className="w-full" size="sm" variant="bordered" - label="cardinality" + aria-label="cardinality" selectedKeys={cardinality} onSelectionChange={changeCardinality} 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 882f8c7..f9ea6d5 100644 --- a/src/pages/database/db-controller/relationship-controller/relationship-controller.tsx +++ b/src/pages/database/db-controller/relationship-controller/relationship-controller.tsx @@ -1,7 +1,7 @@ import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/tooltip/tooltip" import { Accordion, AccordionItem, Button, Input, useDisclosure } from "@heroui/react" import { Code, List, ListCollapse, Table, Workflow } from "lucide-react" -import { useCallback, useEffect, useMemo, useState } from "react"; +import { Ref, useCallback, useEffect, useMemo, useRef, useState } from "react"; import { useTranslation } from "react-i18next"; import RelationshipAccordionHeader from "./relationship-accordion-item/relationship-accordion-header"; import RelationshipAccordionBody from "./relationship-accordion-item/relationship-accordion-body"; @@ -11,6 +11,7 @@ import { RelationshipInsertType, RelationshipType } from "@/lib/schemas/relation import { useDatabase, useDatabaseOperations } from "@/providers/database-provider/database-provider"; import { v4 } from "uuid"; import { useDiagram } from "@/providers/diagram-provider/diagram-provider"; +import { getDefaultRelationshipName } from "@/hooks/use-relationship-name"; @@ -25,13 +26,17 @@ const RelationshipController: React.FC = ({ }) => { const [isValid, setIsValid] = useState(false); const { isOpen, onOpen, onOpenChange } = useDisclosure(); const { database } = useDatabase(); - const { createRelationship } = useDatabaseOperations(); - const { relationships } = database; + const { createRelationship } = useDatabaseOperations(); + const { relationships: allRelationships } = database; + const [relationships, setRelationships] = useState(allRelationships); + const nameRef: Ref = useRef(null); const { t } = useTranslation(); const [selectedRelationship, setSelectedRelationship] = useState(new Set([])); const { focusedRelationshipId } = useDiagram(); + useEffect(() => setRelationships(allRelationships), [allRelationships]); + const addRelationship = useCallback(() => { const newRelationshipId: string = v4(); @@ -50,7 +55,28 @@ const RelationshipController: React.FC = ({ }) => { setSelectedRelationship(new Set([focusedRelationshipId]) as any); } - }, [focusedRelationshipId]) ; + }, [focusedRelationshipId]); + + + const searchRelationships = useCallback(() => { + const keyword: string | undefined = nameRef.current?.value; + if (keyword !== undefined) { + + setRelationships(() => { + return allRelationships.filter((relationship: RelationshipType) => { + if (relationship.name) + return relationship.name.toLowerCase().trim().includes(keyword.toLocaleLowerCase().trim()); + else + return getDefaultRelationshipName(relationship).trim().toLocaleLowerCase().includes( + keyword.trim().toLocaleLowerCase() + ) + }) + }) + } + }, [nameRef, allRelationships]); + + + const selectedRelationshipId = selectedRelationship.values().next().value; return (
@@ -80,17 +106,16 @@ const RelationshipController: React.FC = ({ }) => {
setFilterText(e.target.value)} + className="h-8 w-full focus-visible:ring-0" + onKeyUp={searchRelationships} + />
-
- {fields} -
+ + { + !showMore ? fields.slice(0, MAX_FIELDS) : fields + } + + {fields.length > MAX_FIELDS && ( +
+ {showMore ? ( + <> + + {t('table.show_less')} + + ) : ( + <> + + {t('table.show_more')} + + )} +
+ )} diff --git a/src/utils/field.ts b/src/utils/field.ts index 5bcf60f..6698e63 100644 --- a/src/utils/field.ts +++ b/src/utils/field.ts @@ -1,4 +1,5 @@ import { FieldType } from "@/lib/schemas/field-schema"; +import { v4 } from "uuid"; @@ -16,4 +17,13 @@ export const getNextSequence = (fields: FieldType[]): number => { +export const cloneField = ( field : FieldType) : FieldType => { + return { + ...field , + id : v4() , + } as FieldType ; +} + + + \ No newline at end of file diff --git a/src/utils/tables.ts b/src/utils/tables.ts index aac764a..a15db5b 100644 --- a/src/utils/tables.ts +++ b/src/utils/tables.ts @@ -1,8 +1,12 @@ +import { FieldType } from "@/lib/schemas/field-schema"; import { RelationshipType } from "@/lib/schemas/relationship-schema"; import { TableType } from "@/lib/schemas/table-schema"; import { Node } from "@xyflow/react"; import ELK from "elkjs/lib/elk.bundled.js"; +import { cloneField } from "./field"; +import { v4 } from "uuid"; +import { getTimestamp } from "./utils"; const elk = new ELK(); @@ -87,9 +91,27 @@ const getDefaultTableOverlapping = (table: TableType, tables: TableType[]): bool return false; } + + +const cloneTable = ( table: TableType) : TableType => { + + return { + ...table , + id : v4() , + name : `${table.name}_copy` , + fields : table.fields.map((field : FieldType) => cloneField(field)) , + posX : table.posX - 360 , + + createdAt : getTimestamp() + + } + +} + export { adjustTablesPositions, getDefaultTableOverlapping , - isTablesOverlapping + isTablesOverlapping , + cloneTable } \ No newline at end of file