diff --git a/package.json b/package.json index 5445fb4..485a9e7 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "@radix-ui/react-tooltip": "^1.2.3", "@react-aria/visually-hidden": "3.8.21", "@react-types/shared": "3.28.0", + "@reecelucas/react-use-hotkeys": "^2.0.0", "@uiw/react-codemirror": "^4.23.12", "@xyflow/react": "^12.6.3", "date-fns": "^4.1.0", @@ -36,6 +37,7 @@ "node-sql-parser": "^5.3.9", "object-hash": "^3.0.0", "pgsql-ast-parser": "^12.0.1", + "pluralize": "^8.0.0", "react": "18.3.1", "react-dom": "18.3.1", "react-i18next": "^15.5.1", @@ -52,6 +54,7 @@ "@types/better-sqlite3": "^7.6.13", "@types/node": "20.5.7", "@types/object-hash": "^3.0.6", + "@types/pluralize": "^0.0.33", "@types/react": "18.3.3", "@types/react-dom": "18.3.0", "@typescript-eslint/eslint-plugin": "8.11.0", diff --git a/src/App.tsx b/src/App.tsx index 4fe803a..9d64dba 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -10,6 +10,7 @@ import DiagramProvider from "./providers/diagram-provider/diagram-provider"; import { ToastProvider } from "@heroui/react"; import { ModalProvider } from "./providers/modal-provider/modal-provider"; +import DatabaseHotkeysProvider from "./providers/database-hotkeys/database-hotkeys-provider"; @@ -26,7 +27,9 @@ function App() { - {appRoutes} + + {appRoutes} + diff --git a/src/components/icon/discord.tsx b/src/components/icon/discord.tsx new file mode 100644 index 0000000..c796b63 --- /dev/null +++ b/src/components/icon/discord.tsx @@ -0,0 +1,18 @@ +import { SVGProps } from "react"; + +export function Discord(props: SVGProps) { + return ( + + + + + ) +} + diff --git a/src/components/icon/x.tsx b/src/components/icon/x.tsx new file mode 100644 index 0000000..1947272 --- /dev/null +++ b/src/components/icon/x.tsx @@ -0,0 +1,26 @@ + +import { SVGProps } from "react"; + +export function X(props: SVGProps) { + return ( + + + + ) +} + + + + + + + diff --git a/src/components/menu/menu.tsx b/src/components/menu/menu.tsx index 94e6f8e..c19509b 100644 --- a/src/components/menu/menu.tsx +++ b/src/components/menu/menu.tsx @@ -146,9 +146,11 @@ const Menu: React.FC = ({ }) => { id: "menu.help", title: t("menu.help"), children: [ - - { id: "menu.show_docs", title: t("menu.show_docs") }, - { id: "menu.join_discord", title: t("menu.join_discord") }, + { id: "menu.join_discord", title: t("menu.join_discord") , + clickHandler : () => { + window.open("https://discord.gg/DsN8RcPR6Y", "_blank") + } + }, ], }, ], [t, canRedo, canUndo, undo, redo, deleteMultiTables, database, showController, openController ,changeCardinalityStyle , cardinalityStyle, resolvedTheme]); diff --git a/src/components/modal/modal.tsx b/src/components/modal/modal.tsx index 0d774f0..19d8fc8 100644 --- a/src/components/modal/modal.tsx +++ b/src/components/modal/modal.tsx @@ -48,6 +48,9 @@ const Modal: React.FC = ({ isOpen, onOpenChange, className, backdrop } } + + + return ( = ({ }) => {
{database && }
- diff --git a/src/components/sidebar/sidebar-item.tsx b/src/components/sidebar/sidebar-item.tsx index d81dab4..4ab344e 100644 --- a/src/components/sidebar/sidebar-item.tsx +++ b/src/components/sidebar/sidebar-item.tsx @@ -10,29 +10,50 @@ export interface SidebarItemProps { title?: string; icon?: React.ReactNode; href?: string; - isActive? : boolean + isActive?: boolean, + newTab?: boolean } -const SidebarItem: React.FC = ({ title, icon, href , type = "item" , isActive}) => { +const SidebarItem: React.FC = ({ title, icon, href, type = "item", isActive, newTab }) => { + if (type == "item") return ( - - - {icon} - - + { + !newTab && + + + + {icon} + + + } + { + newTab && + + + {icon} + + + } + {title} - + ) else { diff --git a/src/components/sidebar/sidebar.tsx b/src/components/sidebar/sidebar.tsx index 8bda1de..2bfb434 100644 --- a/src/components/sidebar/sidebar.tsx +++ b/src/components/sidebar/sidebar.tsx @@ -1,8 +1,10 @@ -import { BookOpen, EarthLock, GitCommitHorizontal, Github, Settings, Sparkles, TableProperties, Waypoints, Workflow, Zap } from "lucide-react"; +import { Github, TableProperties, Workflow } from "lucide-react"; import SidebarItem, { SidebarItemProps } from "./sidebar-item"; import { useMemo } from "react"; import { useLocation } from "react-router-dom"; import { useTranslation } from 'react-i18next'; +import { Discord } from "../icon/discord"; +import { X } from "../icon/x"; interface SidebarProps { children?: React.ReactNode @@ -11,9 +13,8 @@ interface SidebarProps { const sidebarItemClass: string = "text-font size-4 data-[active=true]:text-primary-900"; const Sidebar: React.FC = ({ }) => { + const { t } = useTranslation(); - - const location = useLocation(); const sidebarItems: SidebarItemProps[] = useMemo(() => [ @@ -29,68 +30,34 @@ const Sidebar: React.FC = ({ }) => { href: "/database/relationships", isActive: location.pathname.endsWith("/database/relationships") }, - - { - title: "AI", - icon: , - href: "/database/bot", - isActive: location.pathname.endsWith("/database/bot") - }, - { - type: "divider" - }, - { - title: "API", - icon: , - href: "/database/ai-bot", - }, - { - title: "Authentication", - icon: , - href: "/database/ai-bot", - }, - { - title: "Controllers", - icon: , - href: "/database/ai-bot", - }, - { - type: "divider" - }, - { - title: "Git", - icon: , - href: "/database/ai-bot", - }, - { - type: "divider" - }, - { - title: "Project Setting", - icon: , - href: "/database/ai-bot", - }, ], [location]) const bottomSidebarItems: SidebarItemProps[] = useMemo(() => [ { - title: "Github", - icon: , - href: "/database/ai-bot", + title: "X", + icon: , + href: "https://github.com/KarimTamani/stackrender", + newTab : true , }, { - title: "Docs", - icon: , - href: "/database/ai-bot", + title: "Discord", + icon: , + href: "https://discord.gg/DsN8RcPR6Y", + newTab : true , + }, + { + title: "Github", + icon: , + href: "https://github.com/KarimTamani/stackrender", + newTab : true , }, ], []); return ( -