mirror of
https://github.com/chartdb/chartdb.git
synced 2025-10-24 16:43:59 +00:00
fix: move dbml into sections menu (#862)
This commit is contained in:
@@ -2,6 +2,7 @@ import { emptyFn } from '@/lib/utils';
|
|||||||
import { createContext } from 'react';
|
import { createContext } from 'react';
|
||||||
|
|
||||||
export type SidebarSection =
|
export type SidebarSection =
|
||||||
|
| 'dbml'
|
||||||
| 'tables'
|
| 'tables'
|
||||||
| 'relationships'
|
| 'relationships'
|
||||||
| 'dependencies'
|
| 'dependencies'
|
||||||
|
|||||||
@@ -10,7 +10,14 @@ import {
|
|||||||
SidebarMenuButton,
|
SidebarMenuButton,
|
||||||
SidebarMenuItem,
|
SidebarMenuItem,
|
||||||
} from '@/components/sidebar/sidebar';
|
} from '@/components/sidebar/sidebar';
|
||||||
import { BookOpen, Group, FileType, Plus, FolderOpen } from 'lucide-react';
|
import {
|
||||||
|
BookOpen,
|
||||||
|
Group,
|
||||||
|
FileType,
|
||||||
|
Plus,
|
||||||
|
FolderOpen,
|
||||||
|
CodeXml,
|
||||||
|
} from 'lucide-react';
|
||||||
import { SquareStack, Table, Workflow } from 'lucide-react';
|
import { SquareStack, Table, Workflow } from 'lucide-react';
|
||||||
import { useLayout } from '@/hooks/use-layout';
|
import { useLayout } from '@/hooks/use-layout';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
@@ -76,6 +83,15 @@ export const EditorSidebar: React.FC<EditorSidebarProps> = () => {
|
|||||||
},
|
},
|
||||||
active: selectedSidebarSection === 'tables',
|
active: selectedSidebarSection === 'tables',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: 'DBML',
|
||||||
|
icon: CodeXml,
|
||||||
|
onClick: () => {
|
||||||
|
showSidePanel();
|
||||||
|
selectSidebarSection('dbml');
|
||||||
|
},
|
||||||
|
active: selectedSidebarSection === 'dbml',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: t('editor_sidebar.relationships'),
|
title: t('editor_sidebar.relationships'),
|
||||||
icon: Workflow,
|
icon: Workflow,
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { TableDBML } from './table-dbml/table-dbml';
|
||||||
|
|
||||||
|
export interface DBMLSectionProps {}
|
||||||
|
|
||||||
|
export const DBMLSection: React.FC<DBMLSectionProps> = () => {
|
||||||
|
return (
|
||||||
|
<section
|
||||||
|
className="flex flex-1 flex-col overflow-hidden px-2"
|
||||||
|
data-vaul-no-drag
|
||||||
|
>
|
||||||
|
<div className="flex flex-1 flex-col overflow-hidden">
|
||||||
|
<TableDBML />
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -5,7 +5,6 @@ import React, {
|
|||||||
useCallback,
|
useCallback,
|
||||||
useRef,
|
useRef,
|
||||||
} from 'react';
|
} from 'react';
|
||||||
import type { DBTable } from '@/lib/domain/db-table';
|
|
||||||
import { useChartDB } from '@/hooks/use-chartdb';
|
import { useChartDB } from '@/hooks/use-chartdb';
|
||||||
import { useTheme } from '@/hooks/use-theme';
|
import { useTheme } from '@/hooks/use-theme';
|
||||||
import { CodeSnippet } from '@/components/code-snippet/code-snippet';
|
import { CodeSnippet } from '@/components/code-snippet/code-snippet';
|
||||||
@@ -36,9 +35,7 @@ import type * as monaco from 'monaco-editor';
|
|||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useFullScreenLoader } from '@/hooks/use-full-screen-spinner';
|
import { useFullScreenLoader } from '@/hooks/use-full-screen-spinner';
|
||||||
|
|
||||||
export interface TableDBMLProps {
|
export interface TableDBMLProps {}
|
||||||
filteredTables: DBTable[];
|
|
||||||
}
|
|
||||||
|
|
||||||
const getEditorTheme = (theme: EffectiveTheme) => {
|
const getEditorTheme = (theme: EffectiveTheme) => {
|
||||||
return theme === 'dark' ? 'dbml-dark' : 'dbml-light';
|
return theme === 'dark' ? 'dbml-dark' : 'dbml-light';
|
||||||
@@ -18,6 +18,7 @@ import { useBreakpoint } from '@/hooks/use-breakpoint';
|
|||||||
import { AreasSection } from './areas-section/areas-section';
|
import { AreasSection } from './areas-section/areas-section';
|
||||||
import { CustomTypesSection } from './custom-types-section/custom-types-section';
|
import { CustomTypesSection } from './custom-types-section/custom-types-section';
|
||||||
import { DatabaseType } from '@/lib/domain/database-type';
|
import { DatabaseType } from '@/lib/domain/database-type';
|
||||||
|
import { DBMLSection } from './dbml-section/dbml-section';
|
||||||
|
|
||||||
export interface SidePanelProps {}
|
export interface SidePanelProps {}
|
||||||
|
|
||||||
@@ -75,6 +76,8 @@ export const SidePanel: React.FC<SidePanelProps> = () => {
|
|||||||
) : null}
|
) : null}
|
||||||
{selectedSidebarSection === 'tables' ? (
|
{selectedSidebarSection === 'tables' ? (
|
||||||
<TablesSection />
|
<TablesSection />
|
||||||
|
) : selectedSidebarSection === 'dbml' ? (
|
||||||
|
<DBMLSection />
|
||||||
) : selectedSidebarSection === 'relationships' ? (
|
) : selectedSidebarSection === 'relationships' ? (
|
||||||
<RelationshipsSection />
|
<RelationshipsSection />
|
||||||
) : selectedSidebarSection === 'dependencies' ? (
|
) : selectedSidebarSection === 'dependencies' ? (
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React, { useCallback, useMemo, useState } from 'react';
|
import React, { useCallback, useMemo } from 'react';
|
||||||
import { TableList } from './table-list/table-list';
|
import { TableList } from './table-list/table-list';
|
||||||
import { Button } from '@/components/button/button';
|
import { Button } from '@/components/button/button';
|
||||||
import { Table, List, X, Code } from 'lucide-react';
|
import { Table, X } from 'lucide-react';
|
||||||
import { Input } from '@/components/input/input';
|
import { Input } from '@/components/input/input';
|
||||||
import type { DBTable } from '@/lib/domain/db-table';
|
import type { DBTable } from '@/lib/domain/db-table';
|
||||||
import { useChartDB } from '@/hooks/use-chartdb';
|
import { useChartDB } from '@/hooks/use-chartdb';
|
||||||
@@ -9,16 +9,8 @@ import { useLayout } from '@/hooks/use-layout';
|
|||||||
import { EmptyState } from '@/components/empty-state/empty-state';
|
import { EmptyState } from '@/components/empty-state/empty-state';
|
||||||
import { ScrollArea } from '@/components/scroll-area/scroll-area';
|
import { ScrollArea } from '@/components/scroll-area/scroll-area';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import {
|
|
||||||
Tooltip,
|
|
||||||
TooltipContent,
|
|
||||||
TooltipTrigger,
|
|
||||||
} from '@/components/tooltip/tooltip';
|
|
||||||
import { useViewport } from '@xyflow/react';
|
import { useViewport } from '@xyflow/react';
|
||||||
import { useDialog } from '@/hooks/use-dialog';
|
import { useDialog } from '@/hooks/use-dialog';
|
||||||
import { TableDBML } from './table-dbml/table-dbml';
|
|
||||||
import { useHotkeys } from 'react-hotkeys-hook';
|
|
||||||
import { getOperatingSystem } from '@/lib/utils';
|
|
||||||
import type { DBSchema } from '@/lib/domain';
|
import type { DBSchema } from '@/lib/domain';
|
||||||
import { useDiagramFilter } from '@/context/diagram-filter-context/use-diagram-filter';
|
import { useDiagramFilter } from '@/context/diagram-filter-context/use-diagram-filter';
|
||||||
import { filterTable } from '@/lib/domain/diagram-filter/filter';
|
import { filterTable } from '@/lib/domain/diagram-filter/filter';
|
||||||
@@ -34,7 +26,6 @@ export const TablesSection: React.FC<TablesSectionProps> = () => {
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { openTableFromSidebar } = useLayout();
|
const { openTableFromSidebar } = useLayout();
|
||||||
const [filterText, setFilterText] = React.useState('');
|
const [filterText, setFilterText] = React.useState('');
|
||||||
const [showDBML, setShowDBML] = useState(false);
|
|
||||||
const filterInputRef = React.useRef<HTMLInputElement>(null);
|
const filterInputRef = React.useRef<HTMLInputElement>(null);
|
||||||
|
|
||||||
const filteredTables = useMemo(() => {
|
const filteredTables = useMemo(() => {
|
||||||
@@ -104,52 +95,12 @@ export const TablesSection: React.FC<TablesSectionProps> = () => {
|
|||||||
setFilterText('');
|
setFilterText('');
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const operatingSystem = useMemo(() => getOperatingSystem(), []);
|
|
||||||
|
|
||||||
useHotkeys(
|
|
||||||
operatingSystem === 'mac' ? 'meta+p' : 'ctrl+p',
|
|
||||||
() => {
|
|
||||||
setShowDBML((value) => !value);
|
|
||||||
},
|
|
||||||
{
|
|
||||||
preventDefault: true,
|
|
||||||
},
|
|
||||||
[setShowDBML]
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section
|
<section
|
||||||
className="flex flex-1 flex-col overflow-hidden px-2"
|
className="flex flex-1 flex-col overflow-hidden px-2"
|
||||||
data-vaul-no-drag
|
data-vaul-no-drag
|
||||||
>
|
>
|
||||||
<div className="flex items-center justify-between gap-4 py-1">
|
<div className="flex items-center justify-between gap-4 py-1">
|
||||||
<div>
|
|
||||||
<Tooltip>
|
|
||||||
<TooltipTrigger asChild>
|
|
||||||
<span>
|
|
||||||
<Button
|
|
||||||
variant="ghost"
|
|
||||||
className="size-8 p-0"
|
|
||||||
onClick={() =>
|
|
||||||
setShowDBML((value) => !value)
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{showDBML ? (
|
|
||||||
<List className="size-4" />
|
|
||||||
) : (
|
|
||||||
<Code className="size-4" />
|
|
||||||
)}
|
|
||||||
</Button>
|
|
||||||
</span>
|
|
||||||
</TooltipTrigger>
|
|
||||||
<TooltipContent>
|
|
||||||
{showDBML
|
|
||||||
? t('side_panel.tables_section.show_list')
|
|
||||||
: t('side_panel.tables_section.show_dbml')}
|
|
||||||
{operatingSystem === 'mac' ? ' (⌘P)' : ' (Ctrl+P)'}
|
|
||||||
</TooltipContent>
|
|
||||||
</Tooltip>
|
|
||||||
</div>
|
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
<Input
|
<Input
|
||||||
ref={filterInputRef}
|
ref={filterInputRef}
|
||||||
@@ -170,40 +121,36 @@ export const TablesSection: React.FC<TablesSectionProps> = () => {
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-1 flex-col overflow-hidden">
|
<div className="flex flex-1 flex-col overflow-hidden">
|
||||||
{showDBML ? (
|
<ScrollArea className="h-full">
|
||||||
<TableDBML filteredTables={filteredTables} />
|
{tables.length === 0 ? (
|
||||||
) : (
|
<EmptyState
|
||||||
<ScrollArea className="h-full">
|
title={t(
|
||||||
{tables.length === 0 ? (
|
'side_panel.tables_section.empty_state.title'
|
||||||
<EmptyState
|
)}
|
||||||
title={t(
|
description={t(
|
||||||
'side_panel.tables_section.empty_state.title'
|
'side_panel.tables_section.empty_state.description'
|
||||||
)}
|
)}
|
||||||
description={t(
|
className="mt-20"
|
||||||
'side_panel.tables_section.empty_state.description'
|
/>
|
||||||
)}
|
) : filterText && filteredTables.length === 0 ? (
|
||||||
className="mt-20"
|
<div className="mt-10 flex flex-col items-center gap-2">
|
||||||
/>
|
<div className="text-sm text-muted-foreground">
|
||||||
) : filterText && filteredTables.length === 0 ? (
|
{t('side_panel.tables_section.no_results')}
|
||||||
<div className="mt-10 flex flex-col items-center gap-2">
|
|
||||||
<div className="text-sm text-muted-foreground">
|
|
||||||
{t('side_panel.tables_section.no_results')}
|
|
||||||
</div>
|
|
||||||
<Button
|
|
||||||
variant="outline"
|
|
||||||
size="sm"
|
|
||||||
onClick={handleClearFilter}
|
|
||||||
className="gap-1"
|
|
||||||
>
|
|
||||||
<X className="size-3.5" />
|
|
||||||
{t('side_panel.tables_section.clear')}
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
) : (
|
<Button
|
||||||
<TableList tables={filteredTables} />
|
variant="outline"
|
||||||
)}
|
size="sm"
|
||||||
</ScrollArea>
|
onClick={handleClearFilter}
|
||||||
)}
|
className="gap-1"
|
||||||
|
>
|
||||||
|
<X className="size-3.5" />
|
||||||
|
{t('side_panel.tables_section.clear')}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<TableList tables={filteredTables} />
|
||||||
|
)}
|
||||||
|
</ScrollArea>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user