diff --git a/src/components/layout/app-sidebar/data/sidebar-data.tsx b/src/components/layout/app-sidebar/data/sidebar-data.tsx index 741c0d2..3a474c2 100644 --- a/src/components/layout/app-sidebar/data/sidebar-data.tsx +++ b/src/components/layout/app-sidebar/data/sidebar-data.tsx @@ -10,6 +10,7 @@ import { import type { SidebarData } from '../../types'; import { useTranslation } from 'react-i18next'; import { useMemo } from 'react'; +import { BookIcon } from 'lucide-react'; export const useSidebarData = () => { @@ -37,13 +38,7 @@ export const useSidebarData = () => { ], footerNavGroups:[ { title: '', - items: [ - { - title: "X", - url: "https://x.com/Iam_The_Dev", - icon: IconBrandX, - newTab : true - }, + items: [ { title: "Discord", url: "https://discord.gg/4dv26jR4Pj", @@ -56,6 +51,12 @@ export const useSidebarData = () => { icon: IconBrandGithub, newTab : true }, + { + title : t("sidebar.documentation") , + url : "https://www.stackrender.io/docs" , + icon : BookIcon, + newTab : true + } ], }] diff --git a/src/components/layout/menu/data/menu-data.tsx b/src/components/layout/menu/data/menu-data.tsx index 8d8c234..ee1cb29 100644 --- a/src/components/layout/menu/data/menu-data.tsx +++ b/src/components/layout/menu/data/menu-data.tsx @@ -124,11 +124,9 @@ export const useMenuData = () => { openController(!showController) } }, - { id: "menu.theme", title: t("menu.theme"), - children: [ { id: "light", @@ -150,6 +148,12 @@ export const useMenuData = () => { id: "menu.help", title: t("menu.help"), children: [ + { + id: "menu.documentation", title: t("sidebar.documentation"), + clickHandler: () => { + window.open("https://www.stackrender.io/docs", "_blank") + } + }, { id: "menu.join_discord", title: t("menu.join_discord"), clickHandler: () => { diff --git a/src/features/database/components/db-controller/relationship-controller/index.tsx b/src/features/database/components/db-controller/relationship-controller/index.tsx index 4b17191..d567f8f 100644 --- a/src/features/database/components/db-controller/relationship-controller/index.tsx +++ b/src/features/database/components/db-controller/relationship-controller/index.tsx @@ -14,6 +14,7 @@ import { IconFilter2Up, IconPlus } from "@tabler/icons-react"; import { Accordion } from "@/components/ui/accordion"; import RelationshipAccordionItem from "./relationship-accordion-item/relationship-accordion-item"; import { ScrollArea } from "@/components/ui/scroll-area"; +import { Separator } from "@/components/ui/separator"; const RelationshipController: React.FC = ({ }) => { @@ -22,32 +23,28 @@ const RelationshipController: React.FC = ({ }) => { const { database } = useDatabase(); const { relationships: allRelationships } = database || { relationships: [] }; const [relationships, setRelationships] = useState(allRelationships); - const nameRef: Ref = useRef(null); - const { t } = useTranslation(); - const [selectedRelationship, setSelectedRelationship] = useState(); - const { focusedRelationshipId } = useDiagram(); + const { t } = useTranslation(); + const { focusedRelationshipId , setFocusedRelationshipId } = useDiagram(); useEffect(() => searchRelationships(), [allRelationships]); useEffect(() => { - if (focusedRelationshipId) { - setSelectedRelationship(focusedRelationshipId); + if (focusedRelationshipId) { const accordionItem = document.getElementById(focusedRelationshipId) if (accordionItem) accordionItem?.scrollIntoView({ - behavior: 'smooth', block: 'center' + behavior: 'smooth', block: "nearest" }) } }, [focusedRelationshipId]); const onOpen = useCallback(() => { open(Modals.CREATE_RELATIONSHIP, { - onRlationshipCreated: (id: string) => setSelectedRelationship(id) + onRlationshipCreated: (id: string) => setFocusedRelationshipId(id) }) }, []); - const searchRelationships = useCallback(() => { const keyword: string | undefined = nameRef.current?.value; if (keyword !== undefined) { @@ -66,13 +63,12 @@ const RelationshipController: React.FC = ({ }) => { }, [nameRef, allRelationships]); const collapseAll = useCallback(() => { - setSelectedRelationship(""); + setFocusedRelationshipId(undefined); }, []); return ( -
- -
+
+
- } - diff --git a/src/features/database/components/db-controller/tables-controller/index.tsx b/src/features/database/components/db-controller/tables-controller/index.tsx index e6f29d9..b51c02a 100644 --- a/src/features/database/components/db-controller/tables-controller/index.tsx +++ b/src/features/database/components/db-controller/tables-controller/index.tsx @@ -9,8 +9,7 @@ import { v4 } from "uuid"; import { useDiagram } from "@/providers/diagram-provider/diagram-provider"; import { useReactFlow } from "@xyflow/react"; import SqlPreview from "../sql-preview"; -import EmptyList from "@/components/empty-list"; -import { useModal } from "@/providers/modal-provider/modal-provider"; +import EmptyList from "@/components/empty-list"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { IconListDetails, IconPlus } from "@tabler/icons-react"; @@ -28,6 +27,7 @@ import { ScrollArea } from "@/components/ui/scroll-area"; import { closestCenter, DndContext, PointerSensor, useSensor, useSensors } from "@dnd-kit/core"; import { arrayMove, SortableContext, verticalListSortingStrategy } from "@dnd-kit/sortable"; import { getTableNextSequence } from "@/utils/tables"; +import { Separator } from "@/components/ui/separator"; const TablesController: React.FC = ({ }) => { @@ -38,9 +38,9 @@ const TablesController: React.FC = ({ }) => { const { tables: allTables } = database || { tables: [] }; const [tables, setTables] = useState(allTables); const { t } = useTranslation(); - const [selectedTable, setSelectedTable] = useState(undefined); + const [showSqlPreview, setShowSqlPreview] = useState(false); - const { focusedTableId } = useDiagram(); + const { focusedTableId , setFocusedTableId} = useDiagram(); const nameRef: Ref = useRef(null); const sensors = useSensors( @@ -59,7 +59,7 @@ const TablesController: React.FC = ({ }) => { const newIndex = items.findIndex((item: TableType) => item.id == over.id); const tables = arrayMove(items, oldIndex, newIndex); - + orderTables(tables) return tables; @@ -72,7 +72,7 @@ const TablesController: React.FC = ({ }) => { useEffect(() => searchTables(), [allTables]); const addNewTable = useCallback(async () => { - + const newTableId: string = v4(); const viewport = getViewport(); const { x, y, zoom } = viewport; @@ -96,17 +96,15 @@ const TablesController: React.FC = ({ }) => { }] } as TableInsertType); - setSelectedTable(newTableId); + setFocusedTableId(newTableId); }, [database, tables, getViewport, getInteger]); useEffect(() => { - if (focusedTableId) { - setSelectedTable(focusedTableId); - setShowSqlPreview(false); + if (focusedTableId) { const accordionItem = document.getElementById(focusedTableId) if (accordionItem) accordionItem?.scrollIntoView({ - behavior: 'smooth', block: 'center' + behavior: 'smooth', block: "nearest" }) } }, [focusedTableId]); @@ -128,8 +126,8 @@ const TablesController: React.FC = ({ }) => { }, [tables]); return ( -
-
+
+
{ allTables.length > 0 && !showSqlPreview && - + { > {tables.map((table: TableType) => ( - + <> + + + ))} @@ -213,7 +214,7 @@ const TablesController: React.FC = ({ }) => { } { (allTables.length == 0) && -
+
= ({ field }) => { if (!dataType) return; + if (dataType.id == field.typeId) + return; if (key != null) { editField({ id: field.id, @@ -98,6 +100,13 @@ const FieldItem: React.FC = ({ field }) => { onChange={(event: any) => setFieldName(event.target.value)} onBlur={saveFieldName} className=" flex flex-1 !bg-transparent" + onKeyDown={(e : any) => { + if (e.key === "Enter") { + e.preventDefault(); + saveFieldName() ; + e.target.blur() ; + } + }} /> = ({ field }) => { @@ -130,8 +139,8 @@ const FieldItem: React.FC = ({ field }) => { diff --git a/src/features/database/components/db-controller/tables-controller/table-accordion-item/table-accordion-content.tsx b/src/features/database/components/db-controller/tables-controller/table-accordion-item/table-accordion-content.tsx index 724cd48..a411ae0 100644 --- a/src/features/database/components/db-controller/tables-controller/table-accordion-item/table-accordion-content.tsx +++ b/src/features/database/components/db-controller/tables-controller/table-accordion-item/table-accordion-content.tsx @@ -91,7 +91,7 @@ const TableAccordionContent: React.FC = ({ table, keys > - +
{t("db_controller.fields")} @@ -103,7 +103,7 @@ const TableAccordionContent: React.FC = ({ table, keys - +
{t("db_controller.indexes")} @@ -115,7 +115,7 @@ const TableAccordionContent: React.FC = ({ table, keys - +
{t("db_controller.note")} @@ -133,7 +133,7 @@ const TableAccordionContent: React.FC = ({ table, keys -
+
( return ( - +
diff --git a/src/features/database/components/db-controller/tables-controller/table-accordion-item/table-accordion-trigger.tsx b/src/features/database/components/db-controller/tables-controller/table-accordion-item/table-accordion-trigger.tsx index 59e9806..4464aec 100644 --- a/src/features/database/components/db-controller/tables-controller/table-accordion-item/table-accordion-trigger.tsx +++ b/src/features/database/components/db-controller/tables-controller/table-accordion-item/table-accordion-trigger.tsx @@ -126,14 +126,14 @@ const TableAccordionHeader: React.FC = ({ table, isOp
- - @@ -164,7 +171,7 @@ const TableAccordionHeader: React.FC = ({ table, isOp - diff --git a/src/features/database/components/field.tsx b/src/features/database/components/field.tsx index 15e94f5..cd973b0 100644 --- a/src/features/database/components/field.tsx +++ b/src/features/database/components/field.tsx @@ -98,6 +98,13 @@ const Field: React.FC = (props) => { onClick={(e) => e.stopPropagation()} onChange={(e) => setFieldName(e.target.value)} className="h-6 font-bold pb-1.5 rounded-sm px-1" + onKeyDown={(e: any) => { + if (e.key === "Enter") { + e.preventDefault(); + saveFieldName(); + e.target.blur(); + } + }} /> } diff --git a/src/features/database/components/table.tsx b/src/features/database/components/table.tsx index 4ee41c1..9d3ed35 100644 --- a/src/features/database/components/table.tsx +++ b/src/features/database/components/table.tsx @@ -4,7 +4,7 @@ import { Edge, Node, NodeProps } from "@xyflow/react"; import hash from 'object-hash'; import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { - Check, + Check, ChevronUp, ChevronDown, } from 'lucide-react'; @@ -15,14 +15,12 @@ import { useDatabaseOperations } from "@/providers/database-provider/database-pr import { useTranslation } from "react-i18next"; import { RelationshipType } from "@/lib/schemas/relationship-schema"; import { useDiagramOps } from "@/providers/diagram-provider/diagram-provider"; -import { Card, CardContent , CardHeader } from "@/components/ui/card"; +import { Card, CardContent, CardHeader } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; -import { IconFocus2, IconPencil, IconTableFilled } from "@tabler/icons-react"; +import { IconFocus2, IconPencil, IconTableFilled } from "@tabler/icons-react"; import { Input } from "@/components/ui/input"; import { cn } from "@/lib/utils"; - - export type TableProps = Node<{ table: TableType, overlapping?: boolean, @@ -102,6 +100,8 @@ const Table: React.FC> = (props) => { } : undefined } + onDoubleClick={focus} + > > = (props) => { value={tableName} onBlur={saveTableName} style={{ color: table.color as string }} + onKeyDown={(e: any) => { + if (e.key === "Enter") { + e.preventDefault(); + saveTableName(); + e.target.blur(); + } + }} />