feat: support create views (#868)

* feat: support create views

* fix

* fix

* fix

* fix

* fix
This commit is contained in:
Guy Ben-Aharon
2025-08-25 16:14:28 +03:00
committed by GitHub
parent 7e0fdd1595
commit 0a5874a69b
33 changed files with 478 additions and 108 deletions

View File

@@ -0,0 +1,112 @@
import React from 'react';
import { ChevronDownIcon } from '@radix-ui/react-icons';
import { Slot } from '@radix-ui/react-slot';
import { type VariantProps } from 'class-variance-authority';
import { cn } from '@/lib/utils';
import { buttonVariants } from './button-variants';
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from '@/components/dropdown-menu/dropdown-menu';
export interface ButtonWithAlternativesProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {
asChild?: boolean;
alternatives: Array<{
label: string;
onClick: () => void;
disabled?: boolean;
icon?: React.ReactNode;
className?: string;
}>;
dropdownTriggerClassName?: string;
chevronDownIconClassName?: string;
}
const ButtonWithAlternatives = React.forwardRef<
HTMLButtonElement,
ButtonWithAlternativesProps
>(
(
{
className,
variant,
size,
asChild = false,
alternatives,
children,
onClick,
dropdownTriggerClassName,
chevronDownIconClassName,
...props
},
ref
) => {
const Comp = asChild ? Slot : 'button';
const hasAlternatives = (alternatives?.length ?? 0) > 0;
return (
<div className="inline-flex items-stretch">
<Comp
className={cn(
buttonVariants({ variant, size }),
{ 'rounded-r-none': hasAlternatives },
className
)}
ref={ref}
onClick={onClick}
{...props}
>
{children}
</Comp>
{hasAlternatives ? (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<button
className={cn(
buttonVariants({ variant, size }),
'rounded-l-none border-l border-l-primary/5 px-2 min-w-0',
className?.includes('h-') &&
className.match(/h-\d+/)?.[0],
className?.includes('text-') &&
className.match(/text-\w+/)?.[0],
dropdownTriggerClassName
)}
type="button"
>
<ChevronDownIcon
className={cn(
'size-4 shrink-0',
chevronDownIconClassName
)}
/>
</button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
{alternatives.map((alternative, index) => (
<DropdownMenuItem
key={index}
onClick={alternative.onClick}
disabled={alternative.disabled}
className={cn(alternative.className)}
>
<span className="flex w-full items-center justify-between gap-2">
{alternative.label}
{alternative.icon}
</span>
</DropdownMenuItem>
))}
</DropdownMenuContent>
</DropdownMenu>
) : null}
</div>
);
}
);
ButtonWithAlternatives.displayName = 'ButtonWithAlternatives';
export { ButtonWithAlternatives };

View File

@@ -1,7 +1,7 @@
import React, { useCallback, useMemo, useState } from 'react';
import type { DBTable } from '@/lib/domain/db-table';
import { deepCopy, generateId } from '@/lib/utils';
import { defaultTableColor, defaultAreaColor } from '@/lib/colors';
import { defaultTableColor, defaultAreaColor, viewColor } from '@/lib/colors';
import type { ChartDBContext, ChartDBEvent } from './chartdb-context';
import { chartDBContext } from './chartdb-context';
import { DatabaseType } from '@/lib/domain/database-type';
@@ -342,7 +342,7 @@ export const ChartDBProvider: React.FC<
},
],
indexes: [],
color: defaultTableColor,
color: attributes?.isView ? viewColor : defaultTableColor,
createdAt: Date.now(),
isView: false,
order: tables.length,

View File

@@ -11,6 +11,9 @@ export interface LocalConfigContext {
scrollAction: ScrollAction;
setScrollAction: (action: ScrollAction) => void;
showDBViews: boolean;
setShowDBViews: (showViews: boolean) => void;
showCardinality: boolean;
setShowCardinality: (showCardinality: boolean) => void;
@@ -23,9 +26,6 @@ export interface LocalConfigContext {
starUsDialogLastOpen: number;
setStarUsDialogLastOpen: (lastOpen: number) => void;
showDependenciesOnCanvas: boolean;
setShowDependenciesOnCanvas: (showDependenciesOnCanvas: boolean) => void;
showMiniMapOnCanvas: boolean;
setShowMiniMapOnCanvas: (showMiniMapOnCanvas: boolean) => void;
}
@@ -37,6 +37,9 @@ export const LocalConfigContext = createContext<LocalConfigContext>({
scrollAction: 'pan',
setScrollAction: emptyFn,
showDBViews: false,
setShowDBViews: emptyFn,
showCardinality: true,
setShowCardinality: emptyFn,
@@ -49,9 +52,6 @@ export const LocalConfigContext = createContext<LocalConfigContext>({
starUsDialogLastOpen: 0,
setStarUsDialogLastOpen: emptyFn,
showDependenciesOnCanvas: false,
setShowDependenciesOnCanvas: emptyFn,
showMiniMapOnCanvas: false,
setShowMiniMapOnCanvas: emptyFn,
});

View File

@@ -9,8 +9,8 @@ const showCardinalityKey = 'show_cardinality';
const showFieldAttributesKey = 'show_field_attributes';
const githubRepoOpenedKey = 'github_repo_opened';
const starUsDialogLastOpenKey = 'star_us_dialog_last_open';
const showDependenciesOnCanvasKey = 'show_dependencies_on_canvas';
const showMiniMapOnCanvasKey = 'show_minimap_on_canvas';
const showDBViewsKey = 'show_db_views';
export const LocalConfigProvider: React.FC<React.PropsWithChildren> = ({
children,
@@ -23,6 +23,10 @@ export const LocalConfigProvider: React.FC<React.PropsWithChildren> = ({
(localStorage.getItem(scrollActionKey) as ScrollAction) || 'pan'
);
const [showDBViews, setShowDBViews] = React.useState<boolean>(
(localStorage.getItem(showDBViewsKey) || 'false') === 'true'
);
const [showCardinality, setShowCardinality] = React.useState<boolean>(
(localStorage.getItem(showCardinalityKey) || 'true') === 'true'
);
@@ -41,12 +45,6 @@ export const LocalConfigProvider: React.FC<React.PropsWithChildren> = ({
parseInt(localStorage.getItem(starUsDialogLastOpenKey) || '0')
);
const [showDependenciesOnCanvas, setShowDependenciesOnCanvas] =
React.useState<boolean>(
(localStorage.getItem(showDependenciesOnCanvasKey) || 'false') ===
'true'
);
const [showMiniMapOnCanvas, setShowMiniMapOnCanvas] =
React.useState<boolean>(
(localStorage.getItem(showMiniMapOnCanvasKey) || 'true') === 'true'
@@ -72,15 +70,12 @@ export const LocalConfigProvider: React.FC<React.PropsWithChildren> = ({
}, [scrollAction]);
useEffect(() => {
localStorage.setItem(showCardinalityKey, showCardinality.toString());
}, [showCardinality]);
localStorage.setItem(showDBViewsKey, showDBViews.toString());
}, [showDBViews]);
useEffect(() => {
localStorage.setItem(
showDependenciesOnCanvasKey,
showDependenciesOnCanvas.toString()
);
}, [showDependenciesOnCanvas]);
localStorage.setItem(showCardinalityKey, showCardinality.toString());
}, [showCardinality]);
useEffect(() => {
localStorage.setItem(
@@ -96,6 +91,8 @@ export const LocalConfigProvider: React.FC<React.PropsWithChildren> = ({
setTheme,
scrollAction,
setScrollAction,
showDBViews,
setShowDBViews,
showCardinality,
setShowCardinality,
showFieldAttributes,
@@ -104,8 +101,6 @@ export const LocalConfigProvider: React.FC<React.PropsWithChildren> = ({
githubRepoOpened,
starUsDialogLastOpen,
setStarUsDialogLastOpen,
showDependenciesOnCanvas,
setShowDependenciesOnCanvas,
showMiniMapOnCanvas,
setShowMiniMapOnCanvas,
}}

View File

@@ -37,6 +37,7 @@ export const ar: LanguageTranslation = {
hide_field_attributes: 'إخفاء خصائص الحقل',
show_field_attributes: 'إظهار خصائص الحقل',
zoom_on_scroll: 'تكبير/تصغير عند التمرير',
show_views: 'عروض قاعدة البيانات',
theme: 'المظهر',
show_dependencies: 'إظهار الاعتمادات',
hide_dependencies: 'إخفاء الاعتمادات',
@@ -118,6 +119,7 @@ export const ar: LanguageTranslation = {
tables_section: {
tables: 'الجداول',
add_table: 'إضافة جدول',
add_view: 'إضافة عرض',
filter: 'تصفية',
collapse: 'طي الكل',
// TODO: Translate
@@ -471,6 +473,7 @@ export const ar: LanguageTranslation = {
canvas_context_menu: {
new_table: 'جدول جديد',
new_view: 'عرض جديد',
new_relationship: 'علاقة جديدة',
// TODO: Translate
new_area: 'New Area',
@@ -492,6 +495,8 @@ export const ar: LanguageTranslation = {
language_select: {
change_language: 'اللغة',
},
on: 'تشغيل',
off: 'إيقاف',
},
};

View File

@@ -37,6 +37,7 @@ export const bn: LanguageTranslation = {
hide_field_attributes: 'ফিল্ড অ্যাট্রিবিউট লুকান',
show_field_attributes: 'ফিল্ড অ্যাট্রিবিউট দেখান',
zoom_on_scroll: 'স্ক্রলে জুম করুন',
show_views: 'ডাটাবেস ভিউ',
theme: 'থিম',
show_dependencies: 'নির্ভরতাগুলি দেখান',
hide_dependencies: 'নির্ভরতাগুলি লুকান',
@@ -119,6 +120,7 @@ export const bn: LanguageTranslation = {
tables_section: {
tables: 'টেবিল',
add_table: 'টেবিল যোগ করুন',
add_view: 'ভিউ যোগ করুন',
filter: 'ফিল্টার',
collapse: 'সব ভাঁজ করুন',
// TODO: Translate
@@ -476,6 +478,7 @@ export const bn: LanguageTranslation = {
canvas_context_menu: {
new_table: 'নতুন টেবিল',
new_view: 'নতুন ভিউ',
new_relationship: 'নতুন সম্পর্ক',
// TODO: Translate
new_area: 'New Area',
@@ -497,6 +500,9 @@ export const bn: LanguageTranslation = {
language_select: {
change_language: 'ভাষা পরিবর্তন করুন',
},
on: 'চালু',
off: 'বন্ধ',
},
};

View File

@@ -37,6 +37,7 @@ export const de: LanguageTranslation = {
hide_field_attributes: 'Feldattribute ausblenden',
show_field_attributes: 'Feldattribute anzeigen',
zoom_on_scroll: 'Zoom beim Scrollen',
show_views: 'Datenbankansichten',
theme: 'Stil',
show_dependencies: 'Abhängigkeiten anzeigen',
hide_dependencies: 'Abhängigkeiten ausblenden',
@@ -120,6 +121,7 @@ export const de: LanguageTranslation = {
tables_section: {
tables: 'Tabellen',
add_table: 'Tabelle hinzufügen',
add_view: 'Ansicht hinzufügen',
filter: 'Filter',
collapse: 'Alle einklappen',
// TODO: Translate
@@ -480,6 +482,7 @@ export const de: LanguageTranslation = {
canvas_context_menu: {
new_table: 'Neue Tabelle',
new_view: 'Neue Ansicht',
new_relationship: 'Neue Beziehung',
// TODO: Translate
new_area: 'New Area',
@@ -502,6 +505,9 @@ export const de: LanguageTranslation = {
language_select: {
change_language: 'Sprache',
},
on: 'Ein',
off: 'Aus',
},
};

View File

@@ -37,6 +37,7 @@ export const en = {
hide_field_attributes: 'Hide Field Attributes',
show_field_attributes: 'Show Field Attributes',
zoom_on_scroll: 'Zoom on Scroll',
show_views: 'Database Views',
theme: 'Theme',
show_dependencies: 'Show Dependencies',
hide_dependencies: 'Hide Dependencies',
@@ -117,6 +118,7 @@ export const en = {
tables_section: {
tables: 'Tables',
add_table: 'Add Table',
add_view: 'Add View',
filter: 'Filter',
collapse: 'Collapse All',
clear: 'Clear Filter',
@@ -466,6 +468,7 @@ export const en = {
canvas_context_menu: {
new_table: 'New Table',
new_view: 'New View',
new_relationship: 'New Relationship',
new_area: 'New Area',
},
@@ -486,6 +489,9 @@ export const en = {
language_select: {
change_language: 'Language',
},
on: 'On',
off: 'Off',
},
};

View File

@@ -37,6 +37,7 @@ export const es: LanguageTranslation = {
show_sidebar: 'Mostrar Barra Lateral',
hide_sidebar: 'Ocultar Barra Lateral',
zoom_on_scroll: 'Zoom al Desplazarse',
show_views: 'Vistas de Base de Datos',
theme: 'Tema',
show_dependencies: 'Mostrar dependencias',
hide_dependencies: 'Ocultar dependencias',
@@ -118,6 +119,7 @@ export const es: LanguageTranslation = {
tables_section: {
tables: 'Tablas',
add_table: 'Agregar Tabla',
add_view: 'Agregar Vista',
filter: 'Filtrar',
collapse: 'Colapsar Todo',
// TODO: Translate
@@ -478,6 +480,7 @@ export const es: LanguageTranslation = {
canvas_context_menu: {
new_table: 'Nueva Tabla',
new_view: 'Nueva Vista',
new_relationship: 'Nueva Relación',
// TODO: Translate
new_area: 'New Area',
@@ -500,6 +503,9 @@ export const es: LanguageTranslation = {
language_select: {
change_language: 'Idioma',
},
on: 'Encendido',
off: 'Apagado',
},
};

View File

@@ -37,6 +37,7 @@ export const fr: LanguageTranslation = {
hide_field_attributes: 'Masquer les Attributs de Champ',
show_field_attributes: 'Afficher les Attributs de Champ',
zoom_on_scroll: 'Zoom sur le Défilement',
show_views: 'Vues de Base de Données',
theme: 'Thème',
show_dependencies: 'Afficher les Dépendances',
hide_dependencies: 'Masquer les Dépendances',
@@ -117,6 +118,7 @@ export const fr: LanguageTranslation = {
tables_section: {
tables: 'Tables',
add_table: 'Ajouter une Table',
add_view: 'Ajouter une Vue',
filter: 'Filtrer',
collapse: 'Réduire Tout',
clear: 'Effacer le Filtre',
@@ -474,6 +476,7 @@ export const fr: LanguageTranslation = {
canvas_context_menu: {
new_table: 'Nouvelle Table',
new_view: 'Nouvelle Vue',
new_relationship: 'Nouvelle Relation',
// TODO: Translate
new_area: 'New Area',
@@ -496,6 +499,9 @@ export const fr: LanguageTranslation = {
language_select: {
change_language: 'Langue',
},
on: 'Activé',
off: 'Désactivé',
},
};

View File

@@ -37,6 +37,7 @@ export const gu: LanguageTranslation = {
hide_field_attributes: 'ફીલ્ડ અટ્રિબ્યુટ્સ છુપાવો',
show_field_attributes: 'ફીલ્ડ અટ્રિબ્યુટ્સ બતાવો',
zoom_on_scroll: 'સ્ક્રોલ પર ઝૂમ કરો',
show_views: 'ડેટાબેઝ વ્યૂઝ',
theme: 'થિમ',
show_dependencies: 'નિર્ભરતાઓ બતાવો',
hide_dependencies: 'નિર્ભરતાઓ છુપાવો',
@@ -119,6 +120,7 @@ export const gu: LanguageTranslation = {
tables_section: {
tables: 'ટેબલ્સ',
add_table: 'ટેબલ ઉમેરો',
add_view: 'વ્યૂ ઉમેરો',
filter: 'ફિલ્ટર',
collapse: 'બધાને સકુચિત કરો',
// TODO: Translate
@@ -477,6 +479,7 @@ export const gu: LanguageTranslation = {
canvas_context_menu: {
new_table: 'નવું ટેબલ',
new_view: 'નવું વ્યૂ',
new_relationship: 'નવો સંબંધ',
// TODO: Translate
new_area: 'New Area',
@@ -498,6 +501,9 @@ export const gu: LanguageTranslation = {
language_select: {
change_language: 'ભાષા બદલો',
},
on: 'ચાલુ',
off: 'બંધ',
},
};

View File

@@ -37,6 +37,7 @@ export const hi: LanguageTranslation = {
hide_field_attributes: 'फ़ील्ड विशेषताएँ छिपाएँ',
show_field_attributes: 'फ़ील्ड विशेषताएँ दिखाएँ',
zoom_on_scroll: 'स्क्रॉल पर ज़ूम',
show_views: 'डेटाबेस व्यू',
theme: 'थीम',
show_dependencies: 'निर्भरता दिखाएँ',
hide_dependencies: 'निर्भरता छिपाएँ',
@@ -119,6 +120,7 @@ export const hi: LanguageTranslation = {
tables_section: {
tables: 'तालिकाएँ',
add_table: 'तालिका जोड़ें',
add_view: 'व्यू जोड़ें',
filter: 'फ़िल्टर',
collapse: 'सभी को संक्षिप्त करें',
// TODO: Translate
@@ -480,6 +482,7 @@ export const hi: LanguageTranslation = {
canvas_context_menu: {
new_table: 'नई तालिका',
new_view: 'नया व्यू',
new_relationship: 'नया संबंध',
// TODO: Translate
new_area: 'New Area',
@@ -502,6 +505,9 @@ export const hi: LanguageTranslation = {
language_select: {
change_language: 'भाषा बदलें',
},
on: 'चालू',
off: 'बंद',
},
};

View File

@@ -37,6 +37,7 @@ export const hr: LanguageTranslation = {
hide_field_attributes: 'Sakrij atribute polja',
show_field_attributes: 'Prikaži atribute polja',
zoom_on_scroll: 'Zumiranje pri skrolanju',
show_views: 'Pogledi Baze Podataka',
theme: 'Tema',
show_dependencies: 'Prikaži ovisnosti',
hide_dependencies: 'Sakrij ovisnosti',
@@ -117,6 +118,7 @@ export const hr: LanguageTranslation = {
tables_section: {
tables: 'Tablice',
add_table: 'Dodaj tablicu',
add_view: 'Dodaj Pogled',
filter: 'Filtriraj',
collapse: 'Sažmi sve',
clear: 'Očisti filter',
@@ -471,6 +473,7 @@ export const hr: LanguageTranslation = {
canvas_context_menu: {
new_table: 'Nova tablica',
new_view: 'Novi Pogled',
new_relationship: 'Nova veza',
new_area: 'Novo područje',
},
@@ -491,6 +494,9 @@ export const hr: LanguageTranslation = {
language_select: {
change_language: 'Jezik',
},
on: 'Uključeno',
off: 'Isključeno',
},
};

View File

@@ -37,6 +37,7 @@ export const id_ID: LanguageTranslation = {
hide_field_attributes: 'Sembunyikan Atribut Kolom',
show_field_attributes: 'Tampilkan Atribut Kolom',
zoom_on_scroll: 'Perbesar saat Scroll',
show_views: 'Tampilan Database',
theme: 'Tema',
show_dependencies: 'Tampilkan Dependensi',
hide_dependencies: 'Sembunyikan Dependensi',
@@ -118,6 +119,7 @@ export const id_ID: LanguageTranslation = {
tables_section: {
tables: 'Tabel',
add_table: 'Tambah Tabel',
add_view: 'Tambah Tampilan',
filter: 'Saring',
collapse: 'Lipat Semua',
// TODO: Translate
@@ -476,6 +478,7 @@ export const id_ID: LanguageTranslation = {
canvas_context_menu: {
new_table: 'Tabel Baru',
new_view: 'Tampilan Baru',
new_relationship: 'Hubungan Baru',
// TODO: Translate
new_area: 'New Area',
@@ -497,6 +500,9 @@ export const id_ID: LanguageTranslation = {
language_select: {
change_language: 'Bahasa',
},
on: 'Aktif',
off: 'Nonaktif',
},
};

View File

@@ -37,6 +37,7 @@ export const ja: LanguageTranslation = {
hide_field_attributes: 'フィールド属性を非表示',
show_field_attributes: 'フィールド属性を表示',
zoom_on_scroll: 'スクロールでズーム',
show_views: 'データベースビュー',
theme: 'テーマ',
// TODO: Translate
show_dependencies: 'Show Dependencies',
@@ -122,6 +123,7 @@ export const ja: LanguageTranslation = {
tables_section: {
tables: 'テーブル',
add_table: 'テーブルを追加',
add_view: 'ビューを追加',
filter: 'フィルタ',
collapse: 'すべて折りたたむ',
// TODO: Translate
@@ -482,6 +484,7 @@ export const ja: LanguageTranslation = {
canvas_context_menu: {
new_table: '新しいテーブル',
new_view: '新しいビュー',
new_relationship: '新しいリレーションシップ',
// TODO: Translate
new_area: 'New Area',
@@ -504,6 +507,9 @@ export const ja: LanguageTranslation = {
language_select: {
change_language: '言語',
},
on: 'オン',
off: 'オフ',
},
};

View File

@@ -37,6 +37,7 @@ export const ko_KR: LanguageTranslation = {
hide_field_attributes: '필드 속성 숨기기',
show_field_attributes: '필드 속성 보이기',
zoom_on_scroll: '스크롤 시 확대',
show_views: '데이터베이스 뷰',
theme: '테마',
show_dependencies: '종속성 보이기',
hide_dependencies: '종속성 숨기기',
@@ -118,6 +119,7 @@ export const ko_KR: LanguageTranslation = {
tables_section: {
tables: '테이블',
add_table: '테이블 추가',
add_view: '뷰 추가',
filter: '필터',
collapse: '모두 접기',
// TODO: Translate
@@ -473,6 +475,7 @@ export const ko_KR: LanguageTranslation = {
canvas_context_menu: {
new_table: '새 테이블',
new_view: '새 뷰',
new_relationship: '새 연관관계',
// TODO: Translate
new_area: 'New Area',
@@ -494,6 +497,9 @@ export const ko_KR: LanguageTranslation = {
language_select: {
change_language: '언어',
},
on: '켜기',
off: '끄기',
},
};

View File

@@ -37,6 +37,7 @@ export const mr: LanguageTranslation = {
hide_field_attributes: 'फील्ड गुणधर्म लपवा',
show_field_attributes: 'फील्ड गुणधर्म दाखवा',
zoom_on_scroll: 'स्क्रोलवर झूम करा',
show_views: 'डेटाबेस व्ह्यूज',
theme: 'थीम',
show_dependencies: 'डिपेंडेन्सि दाखवा',
hide_dependencies: 'डिपेंडेन्सि लपवा',
@@ -121,6 +122,7 @@ export const mr: LanguageTranslation = {
tables_section: {
tables: 'टेबल्स',
add_table: 'टेबल जोडा',
add_view: 'व्ह्यू जोडा',
filter: 'फिल्टर',
collapse: 'सर्व संकुचित करा',
// TODO: Translate
@@ -486,6 +488,7 @@ export const mr: LanguageTranslation = {
canvas_context_menu: {
new_table: 'नवीन टेबल',
new_view: 'नवीन व्ह्यू',
new_relationship: 'नवीन रिलेशनशिप',
// TODO: Translate
new_area: 'New Area',
@@ -509,6 +512,9 @@ export const mr: LanguageTranslation = {
language_select: {
change_language: 'भाषा बदला',
},
on: 'चालू',
off: 'बंद',
},
};

View File

@@ -37,6 +37,7 @@ export const ne: LanguageTranslation = {
hide_field_attributes: 'फिल्ड विशेषताहरू लुकाउनुहोस्',
show_field_attributes: 'फिल्ड विशेषताहरू देखाउनुहोस्',
zoom_on_scroll: 'स्क्रोलमा जुम गर्नुहोस्',
show_views: 'डाटाबेस भ्यूहरू',
theme: 'थिम',
show_dependencies: 'डिपेन्डेन्सीहरू देखाउनुहोस्',
hide_dependencies: 'डिपेन्डेन्सीहरू लुकाउनुहोस्',
@@ -119,6 +120,7 @@ export const ne: LanguageTranslation = {
tables_section: {
tables: 'तालिकाहरू',
add_table: 'तालिका थप्नुहोस्',
add_view: 'भ्यू थप्नुहोस्',
filter: 'फिल्टर',
collapse: 'सबै लुकाउनुहोस्',
// TODO: Translate
@@ -480,6 +482,7 @@ export const ne: LanguageTranslation = {
canvas_context_menu: {
new_table: 'नयाँ तालिका',
new_view: 'नयाँ भ्यू',
new_relationship: 'नयाँ सम्बन्ध',
// TODO: Translate
new_area: 'New Area',
@@ -501,6 +504,9 @@ export const ne: LanguageTranslation = {
language_select: {
change_language: 'भाषा परिवर्तन गर्नुहोस्',
},
on: 'सक्रिय',
off: 'निष्क्रिय',
},
};

View File

@@ -37,6 +37,7 @@ export const pt_BR: LanguageTranslation = {
hide_field_attributes: 'Ocultar Atributos de Campo',
show_field_attributes: 'Mostrar Atributos de Campo',
zoom_on_scroll: 'Zoom ao Rolar',
show_views: 'Visualizações do Banco de Dados',
theme: 'Tema',
show_dependencies: 'Mostrar Dependências',
hide_dependencies: 'Ocultar Dependências',
@@ -119,6 +120,7 @@ export const pt_BR: LanguageTranslation = {
tables_section: {
tables: 'Tabelas',
add_table: 'Adicionar Tabela',
add_view: 'Adicionar Visualização',
filter: 'Filtrar',
collapse: 'Colapsar Todas',
// TODO: Translate
@@ -478,6 +480,7 @@ export const pt_BR: LanguageTranslation = {
canvas_context_menu: {
new_table: 'Nova Tabela',
new_view: 'Nova Visualização',
new_relationship: 'Novo Relacionamento',
// TODO: Translate
new_area: 'New Area',
@@ -500,6 +503,9 @@ export const pt_BR: LanguageTranslation = {
language_select: {
change_language: 'Idioma',
},
on: 'Ligado',
off: 'Desligado',
},
};

View File

@@ -37,6 +37,7 @@ export const ru: LanguageTranslation = {
show_field_attributes: 'Показать атрибуты поля',
hide_field_attributes: 'Скрыть атрибуты поля',
zoom_on_scroll: 'Увеличение при прокрутке',
show_views: 'Представления базы данных',
theme: 'Тема',
show_dependencies: 'Показать зависимости',
hide_dependencies: 'Скрыть зависимости',
@@ -116,6 +117,7 @@ export const ru: LanguageTranslation = {
tables_section: {
tables: 'Таблицы',
add_table: 'Добавить таблицу',
add_view: 'Добавить представление',
filter: 'Фильтр',
collapse: 'Свернуть все',
clear: 'Очистить фильтр',
@@ -474,6 +476,7 @@ export const ru: LanguageTranslation = {
canvas_context_menu: {
new_table: 'Создать таблицу',
new_view: 'Новое представление',
new_relationship: 'Создать отношение',
new_area: 'Новая область',
},
@@ -495,6 +498,9 @@ export const ru: LanguageTranslation = {
language_select: {
change_language: 'Сменить язык',
},
on: 'Вкл',
off: 'Выкл',
},
};

View File

@@ -37,6 +37,7 @@ export const te: LanguageTranslation = {
show_field_attributes: 'ఫీల్డ్ గుణాలను చూపించు',
hide_field_attributes: 'ఫీల్డ్ గుణాలను దాచండి',
zoom_on_scroll: 'స్క్రోల్‌పై జూమ్',
show_views: 'డేటాబేస్ వ్యూలు',
theme: 'థీమ్',
show_dependencies: 'ఆధారాలు చూపించండి',
hide_dependencies: 'ఆధారాలను దాచండి',
@@ -119,6 +120,7 @@ export const te: LanguageTranslation = {
tables_section: {
tables: 'పట్టికలు',
add_table: 'పట్టికను జోడించు',
add_view: 'వ్యూ జోడించండి',
filter: 'ఫిల్టర్',
collapse: 'అన్ని కూల్ చేయి',
// TODO: Translate
@@ -482,6 +484,7 @@ export const te: LanguageTranslation = {
canvas_context_menu: {
new_table: 'కొత్త పట్టిక',
new_view: 'కొత్త వ్యూ',
new_relationship: 'కొత్త సంబంధం',
// TODO: Translate
new_area: 'New Area',
@@ -505,6 +508,9 @@ export const te: LanguageTranslation = {
language_select: {
change_language: 'భాష మార్చు',
},
on: 'ఆన్',
off: 'ఆఫ్',
},
};

View File

@@ -37,6 +37,7 @@ export const tr: LanguageTranslation = {
show_field_attributes: 'Alan Özelliklerini Göster',
hide_field_attributes: 'Alan Özelliklerini Gizle',
zoom_on_scroll: 'Kaydırarak Yakınlaştır',
show_views: 'Veritabanı Görünümleri',
theme: 'Tema',
show_dependencies: 'Bağımlılıkları Göster',
hide_dependencies: 'Bağımlılıkları Gizle',
@@ -118,6 +119,7 @@ export const tr: LanguageTranslation = {
tables_section: {
tables: 'Tablolar',
add_table: 'Tablo Ekle',
add_view: 'Görünüm Ekle',
filter: 'Filtrele',
collapse: 'Hepsini Daralt',
// TODO: Translate
@@ -467,6 +469,7 @@ export const tr: LanguageTranslation = {
},
canvas_context_menu: {
new_table: 'Yeni Tablo',
new_view: 'Yeni Görünüm',
new_relationship: 'Yeni İlişki',
// TODO: Translate
new_area: 'New Area',
@@ -489,6 +492,9 @@ export const tr: LanguageTranslation = {
language_select: {
change_language: 'Dil',
},
on: 'Açık',
off: 'Kapalı',
},
};

View File

@@ -37,6 +37,7 @@ export const uk: LanguageTranslation = {
show_field_attributes: 'Показати атрибути полів',
hide_field_attributes: 'Приховати атрибути полів',
zoom_on_scroll: 'Масштабувати прокручуванням',
show_views: 'Представлення бази даних',
theme: 'Тема',
show_dependencies: 'Показати залежності',
hide_dependencies: 'Приховати залежності',
@@ -117,6 +118,7 @@ export const uk: LanguageTranslation = {
tables_section: {
tables: 'Таблиці',
add_table: 'Додати таблицю',
add_view: 'Додати представлення',
filter: 'Фільтр',
collapse: 'Згорнути все',
// TODO: Translate
@@ -473,6 +475,7 @@ export const uk: LanguageTranslation = {
canvas_context_menu: {
new_table: 'Нова таблиця',
new_view: 'Нове представлення',
new_relationship: 'Новий звʼязок',
// TODO: Translate
new_area: 'New Area',
@@ -494,6 +497,9 @@ export const uk: LanguageTranslation = {
language_select: {
change_language: 'Мова',
},
on: 'Увімк',
off: 'Вимк',
},
};

View File

@@ -37,6 +37,7 @@ export const vi: LanguageTranslation = {
show_field_attributes: 'Hiển thị thuộc tính trường',
hide_field_attributes: 'Ẩn thuộc tính trường',
zoom_on_scroll: 'Thu phóng khi cuộn',
show_views: 'Chế độ xem Cơ sở dữ liệu',
theme: 'Chủ đề',
show_dependencies: 'Hiển thị các phụ thuộc',
hide_dependencies: 'Ẩn các phụ thuộc',
@@ -118,6 +119,7 @@ export const vi: LanguageTranslation = {
tables_section: {
tables: 'Bảng',
add_table: 'Thêm bảng',
add_view: 'Thêm Chế độ xem',
filter: 'Lọc',
collapse: 'Thu gọn tất cả',
// TODO: Translate
@@ -474,6 +476,7 @@ export const vi: LanguageTranslation = {
canvas_context_menu: {
new_table: 'Tạo bảng mới',
new_view: 'Chế độ xem Mới',
new_relationship: 'Tạo quan hệ mới',
// TODO: Translate
new_area: 'New Area',
@@ -495,6 +498,9 @@ export const vi: LanguageTranslation = {
language_select: {
change_language: 'Ngôn ngữ',
},
on: 'Bật',
off: 'Tắt',
},
};

View File

@@ -37,6 +37,7 @@ export const zh_CN: LanguageTranslation = {
show_field_attributes: '展示字段属性',
hide_field_attributes: '隐藏字段属性',
zoom_on_scroll: '滚动缩放',
show_views: '数据库视图',
theme: '主题',
show_dependencies: '展示依赖',
hide_dependencies: '隐藏依赖',
@@ -115,6 +116,7 @@ export const zh_CN: LanguageTranslation = {
tables_section: {
tables: '表',
add_table: '添加表',
add_view: '添加视图',
filter: '筛选',
collapse: '全部折叠',
// TODO: Translate
@@ -469,6 +471,7 @@ export const zh_CN: LanguageTranslation = {
canvas_context_menu: {
new_table: '新建表',
new_view: '新建视图',
new_relationship: '新建关系',
// TODO: Translate
new_area: 'New Area',
@@ -490,6 +493,9 @@ export const zh_CN: LanguageTranslation = {
language_select: {
change_language: '语言',
},
on: '开启',
off: '关闭',
},
};

View File

@@ -37,6 +37,7 @@ export const zh_TW: LanguageTranslation = {
hide_field_attributes: '隱藏欄位屬性',
show_field_attributes: '顯示欄位屬性',
zoom_on_scroll: '滾動縮放',
show_views: '資料庫檢視',
theme: '主題',
show_dependencies: '顯示相依性',
hide_dependencies: '隱藏相依性',
@@ -115,6 +116,7 @@ export const zh_TW: LanguageTranslation = {
tables_section: {
tables: '表格',
add_table: '新增表格',
add_view: '新增檢視',
filter: '篩選',
collapse: '全部摺疊',
// TODO: Translate
@@ -469,6 +471,7 @@ export const zh_TW: LanguageTranslation = {
canvas_context_menu: {
new_table: '新建表格',
new_view: '新檢視',
new_relationship: '新建關聯',
// TODO: Translate
new_area: 'New Area',
@@ -490,6 +493,9 @@ export const zh_TW: LanguageTranslation = {
language_select: {
change_language: '變更語言',
},
on: '開啟',
off: '關閉',
},
};

View File

@@ -10,8 +10,9 @@ import { useDialog } from '@/hooks/use-dialog';
import { useReactFlow } from '@xyflow/react';
import React, { useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { Table, Workflow, Group } from 'lucide-react';
import { Table, Workflow, Group, View } from 'lucide-react';
import { useDiagramFilter } from '@/context/diagram-filter-context/use-diagram-filter';
import { useLocalConfig } from '@/hooks/use-local-config';
export const CanvasContextMenu: React.FC<React.PropsWithChildren> = ({
children,
@@ -21,6 +22,7 @@ export const CanvasContextMenu: React.FC<React.PropsWithChildren> = ({
const { openCreateRelationshipDialog, openTableSchemaDialog } = useDialog();
const { screenToFlowPosition } = useReactFlow();
const { t } = useTranslation();
const { showDBViews } = useLocalConfig();
const { isMd: isDesktop } = useBreakpoint('md');
@@ -61,6 +63,45 @@ export const CanvasContextMenu: React.FC<React.PropsWithChildren> = ({
]
);
const createViewHandler = useCallback(
(event: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
const position = screenToFlowPosition({
x: event.clientX,
y: event.clientY,
});
if (schemasDisplayed.length > 1) {
openTableSchemaDialog({
onConfirm: ({ schema }) =>
createTable({
x: position.x,
y: position.y,
schema: schema.name,
isView: true,
}),
schemas: schemasDisplayed,
});
} else {
const schema =
schemasDisplayed?.length === 1
? schemasDisplayed[0]?.name
: undefined;
createTable({
x: position.x,
y: position.y,
schema,
isView: true,
});
}
},
[
createTable,
screenToFlowPosition,
openTableSchemaDialog,
schemasDisplayed,
]
);
const createAreaHandler = useCallback(
(event: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
const position = screenToFlowPosition({
@@ -97,6 +138,15 @@ export const CanvasContextMenu: React.FC<React.PropsWithChildren> = ({
{t('canvas_context_menu.new_table')}
<Table className="size-3.5" />
</ContextMenuItem>
{showDBViews ? (
<ContextMenuItem
onClick={createViewHandler}
className="flex justify-between gap-4"
>
{t('canvas_context_menu.new_view')}
<View className="size-3.5" />
</ContextMenuItem>
) : null}
<ContextMenuItem
onClick={createRelationshipHandler}
className="flex justify-between gap-4"

View File

@@ -27,6 +27,7 @@ import { generateTreeDataByAreas, generateTreeDataBySchemas } from './utils';
import { FilterItemActions } from './filter-item-actions';
import { databasesWithSchemas } from '@/lib/domain';
import { getOperatingSystem } from '@/lib/utils';
import { useLocalConfig } from '@/hooks/use-local-config';
export interface CanvasFilterProps {
onClose: () => void;
@@ -50,17 +51,20 @@ export const CanvasFilter: React.FC<CanvasFilterProps> = ({ onClose }) => {
const [isFilterVisible, setIsFilterVisible] = useState(false);
const [groupingMode, setGroupingMode] = useState<GroupingMode>('schema');
const searchInputRef = useRef<HTMLInputElement>(null);
const { showDBViews } = useLocalConfig();
// Extract only the properties needed for tree data
const relevantTableData = useMemo<RelevantTableData[]>(
() =>
tables.map((table) => ({
tables
.filter((table) => (showDBViews ? true : !table.isView))
.map((table) => ({
id: table.id,
name: table.name,
schema: table.schema,
parentAreaId: table.parentAreaId,
})),
[tables]
[tables, showDBViews]
);
const databaseWithSchemas = useMemo(

View File

@@ -80,7 +80,7 @@ import {
TARGET_DEP_PREFIX,
TOP_SOURCE_HANDLE_ID_PREFIX,
} from './table-node/table-node-dependency-indicator';
import { DatabaseType } from '@/lib/domain/database-type';
import type { DatabaseType } from '@/lib/domain/database-type';
import { useAlert } from '@/context/alert-context/alert-context';
import { useCanvas } from '@/hooks/use-canvas';
import type { AreaNodeType } from './area-node/area-node';
@@ -123,10 +123,12 @@ const tableToTableNode = (
filter,
databaseType,
filterLoading,
showDBViews,
}: {
filter?: DiagramFilter;
databaseType: DatabaseType;
filterLoading: boolean;
showDBViews?: boolean;
}
): TableNodeType => {
// Always use absolute position for now
@@ -146,7 +148,9 @@ const tableToTableNode = (
table: { id: table.id, schema: table.schema },
filter,
options: { defaultSchema: defaultSchemas[databaseType] },
}) || filterLoading,
}) ||
filterLoading ||
(!showDBViews && table.isView),
};
};
@@ -226,8 +230,7 @@ export const Canvas: React.FC<CanvasProps> = ({ initialTables }) => {
} = useChartDB();
const { showSidePanel } = useLayout();
const { effectiveTheme } = useTheme();
const { scrollAction, showDependenciesOnCanvas, showMiniMapOnCanvas } =
useLocalConfig();
const { scrollAction, showDBViews, showMiniMapOnCanvas } = useLocalConfig();
const { showAlert } = useAlert();
const { isMd: isDesktop } = useBreakpoint('md');
const [highlightOverlappingTables, setHighlightOverlappingTables] =
@@ -246,7 +249,12 @@ export const Canvas: React.FC<CanvasProps> = ({ initialTables }) => {
const [nodes, setNodes, onNodesChange] = useNodesState<NodeType>(
initialTables.map((table) =>
tableToTableNode(table, { filter, databaseType, filterLoading })
tableToTableNode(table, {
filter,
databaseType,
filterLoading,
showDBViews,
})
)
);
const [edges, setEdges, onEdgesChange] =
@@ -260,12 +268,24 @@ export const Canvas: React.FC<CanvasProps> = ({ initialTables }) => {
useEffect(() => {
const initialNodes = initialTables.map((table) =>
tableToTableNode(table, { filter, databaseType, filterLoading })
tableToTableNode(table, {
filter,
databaseType,
filterLoading,
showDBViews,
})
);
if (equal(initialNodes, nodes)) {
setIsInitialLoadingNodes(false);
}
}, [initialTables, nodes, filter, databaseType, filterLoading]);
}, [
initialTables,
nodes,
filter,
databaseType,
filterLoading,
showDBViews,
]);
useEffect(() => {
if (!isInitialLoadingNodes) {
@@ -319,19 +339,11 @@ export const Canvas: React.FC<CanvasProps> = ({ initialTables }) => {
targetHandle: `${TARGET_DEP_PREFIX}${targetDepIndexes[dep.tableId]++}_${dep.tableId}`,
type: 'dependency-edge',
data: { dependency: dep },
hidden:
!showDependenciesOnCanvas &&
databaseType !== DatabaseType.CLICKHOUSE,
hidden: !showDBViews,
})
),
]);
}, [
relationships,
dependencies,
setEdges,
showDependenciesOnCanvas,
databaseType,
]);
}, [relationships, dependencies, setEdges, showDBViews]);
useEffect(() => {
const selectedNodesIds = nodes
@@ -432,6 +444,7 @@ export const Canvas: React.FC<CanvasProps> = ({ initialTables }) => {
filter,
databaseType,
filterLoading,
showDBViews,
});
// Check if table uses the highlighted custom type
@@ -481,6 +494,7 @@ export const Canvas: React.FC<CanvasProps> = ({ initialTables }) => {
highlightOverlappingTables,
highlightedCustomType,
filterLoading,
showDBViews,
]);
const prevFilter = useRef<DiagramFilter | undefined>(undefined);

View File

@@ -30,6 +30,7 @@ import { useChartDB } from '@/hooks/use-chartdb';
import { DatabaseType } from '@/lib/domain/database-type';
import { useDialog } from '@/hooks/use-dialog';
import { Separator } from '@/components/separator/separator';
import { useLocalConfig } from '@/hooks/use-local-config';
export interface SidebarItem {
title: string;
@@ -47,7 +48,8 @@ export const EditorSidebar: React.FC<EditorSidebarProps> = () => {
const { t } = useTranslation();
const { isMd: isDesktop } = useBreakpoint('md');
const { effectiveTheme } = useTheme();
const { dependencies, databaseType } = useChartDB();
const { databaseType } = useChartDB();
const { showDBViews } = useLocalConfig();
const { openCreateDiagramDialog, openOpenDiagramDialog } = useDialog();
const diagramItems: SidebarItem[] = useMemo(
@@ -110,7 +112,7 @@ export const EditorSidebar: React.FC<EditorSidebarProps> = () => {
},
active: selectedSidebarSection === 'areas',
},
...(dependencies && dependencies.length > 0
...(showDBViews
? [
{
title: t('editor_sidebar.dependencies'),
@@ -142,8 +144,8 @@ export const EditorSidebar: React.FC<EditorSidebarProps> = () => {
selectedSidebarSection,
t,
showSidePanel,
dependencies,
databaseType,
showDBViews,
]
);

View File

@@ -281,10 +281,15 @@ export const TableListItemContent: React.FC<TableListItemContentProps> = ({
</Accordion>
<Separator className="" />
<div className="flex flex-1 items-center justify-between">
{!table.isView ? (
<ColorPicker
color={color}
onChange={(color) => updateTable(table.id, { color })}
/>
) : (
<div />
)}
<div className="flex gap-1">
<Button
variant="outline"

View File

@@ -1,7 +1,7 @@
import React, { useCallback, useMemo } from 'react';
import { TableList } from './table-list/table-list';
import { Button } from '@/components/button/button';
import { Table, X } from 'lucide-react';
import { Table, View, X } from 'lucide-react';
import { Input } from '@/components/input/input';
import type { DBTable } from '@/lib/domain/db-table';
import { useChartDB } from '@/hooks/use-chartdb';
@@ -15,6 +15,8 @@ import type { DBSchema } from '@/lib/domain';
import { useDiagramFilter } from '@/context/diagram-filter-context/use-diagram-filter';
import { filterTable } from '@/lib/domain/diagram-filter/filter';
import { defaultSchemas } from '@/lib/data/default-schemas';
import { ButtonWithAlternatives } from '@/components/button/button-with-alternatives';
import { useLocalConfig } from '@/hooks/use-local-config';
export interface TablesSectionProps {}
@@ -26,6 +28,7 @@ export const TablesSection: React.FC<TablesSectionProps> = () => {
const { t } = useTranslation();
const { openTableFromSidebar } = useLayout();
const [filterText, setFilterText] = React.useState('');
const { showDBViews } = useLocalConfig();
const filterInputRef = React.useRef<HTMLInputElement>(null);
const filteredTables = useMemo(() => {
@@ -45,16 +48,26 @@ export const TablesSection: React.FC<TablesSectionProps> = () => {
},
});
return tables.filter(filterTables).filter(filterTableName);
}, [tables, filterText, filter, databaseType]);
const filterViews: (table: DBTable) => boolean = (table) =>
showDBViews ? true : !table.isView;
return tables
.filter(filterTables)
.filter(filterTableName)
.filter(filterViews);
}, [tables, filterText, filter, databaseType, showDBViews]);
const getCenterLocation = useCallback(() => {
const padding = 80;
const centerX = -viewport.x / viewport.zoom + padding / viewport.zoom;
const centerY = -viewport.y / viewport.zoom + padding / viewport.zoom;
return { centerX, centerY };
}, [viewport.x, viewport.y, viewport.zoom]);
const createTableWithLocation = useCallback(
async ({ schema }: { schema?: DBSchema }) => {
const padding = 80;
const centerX =
-viewport.x / viewport.zoom + padding / viewport.zoom;
const centerY =
-viewport.y / viewport.zoom + padding / viewport.zoom;
const { centerX, centerY } = getCenterLocation();
const table = await createTable({
x: centerX,
y: centerY,
@@ -62,34 +75,55 @@ export const TablesSection: React.FC<TablesSectionProps> = () => {
});
openTableFromSidebar(table.id);
},
[
createTable,
openTableFromSidebar,
viewport.x,
viewport.y,
viewport.zoom,
]
[createTable, openTableFromSidebar, getCenterLocation]
);
const handleCreateTable = useCallback(async () => {
const createViewWithLocation = useCallback(
async ({ schema }: { schema?: DBSchema }) => {
const { centerX, centerY } = getCenterLocation();
const table = await createTable({
x: centerX,
y: centerY,
schema: schema?.name,
isView: true,
});
openTableFromSidebar(table.id);
},
[createTable, openTableFromSidebar, getCenterLocation]
);
const handleCreateTable = useCallback(
async ({ view }: { view?: boolean }) => {
setFilterText('');
if (schemasDisplayed.length > 1) {
openTableSchemaDialog({
onConfirm: createTableWithLocation,
onConfirm: view
? createViewWithLocation
: createTableWithLocation,
schemas: schemasDisplayed,
});
} else {
const schema =
schemasDisplayed.length === 1 ? schemasDisplayed[0] : undefined;
schemasDisplayed.length === 1
? schemasDisplayed[0]
: undefined;
if (view) {
createViewWithLocation({ schema });
} else {
createTableWithLocation({ schema });
}
}, [
}
},
[
createViewWithLocation,
createTableWithLocation,
schemasDisplayed,
openTableSchemaDialog,
setFilterText,
]);
]
);
const handleClearFilter = useCallback(() => {
setFilterText('');
@@ -111,14 +145,31 @@ export const TablesSection: React.FC<TablesSectionProps> = () => {
onChange={(e) => setFilterText(e.target.value)}
/>
</div>
<Button
<ButtonWithAlternatives
variant="secondary"
className="h-8 p-2 text-xs"
onClick={handleCreateTable}
onClick={() => handleCreateTable({ view: false })}
dropdownTriggerClassName="px-1"
chevronDownIconClassName="!size-3.5"
alternatives={
showDBViews
? [
{
label: t(
'side_panel.tables_section.add_view'
),
onClick: () =>
handleCreateTable({ view: true }),
icon: <View className="size-4" />,
className: 'text-xs',
},
]
: []
}
>
<Table className="h-4" />
{t('side_panel.tables_section.add_table')}
</Button>
</ButtonWithAlternatives>
</div>
<div className="flex flex-1 flex-col overflow-hidden">
<ScrollArea className="h-full">

View File

@@ -37,7 +37,6 @@ export const Menu: React.FC<MenuProps> = () => {
deleteDiagram,
updateDiagramUpdatedAt,
databaseType,
dependencies,
} = useChartDB();
const {
openCreateDiagramDialog,
@@ -59,10 +58,10 @@ export const Menu: React.FC<MenuProps> = () => {
showCardinality,
setShowFieldAttributes,
showFieldAttributes,
setShowDependenciesOnCanvas,
showDependenciesOnCanvas,
setShowMiniMapOnCanvas,
showMiniMapOnCanvas,
showDBViews,
setShowDBViews,
} = useLocalConfig();
const { t } = useTranslation();
const { redo, undo, hasRedo, hasUndo } = useHistory();
@@ -143,10 +142,6 @@ export const Menu: React.FC<MenuProps> = () => {
setShowFieldAttributes(!showFieldAttributes);
}, [showFieldAttributes, setShowFieldAttributes]);
const showOrHideDependencies = useCallback(() => {
setShowDependenciesOnCanvas(!showDependenciesOnCanvas);
}, [showDependenciesOnCanvas, setShowDependenciesOnCanvas]);
const showOrHideMiniMap = useCallback(() => {
setShowMiniMapOnCanvas(!showMiniMapOnCanvas);
}, [showMiniMapOnCanvas, setShowMiniMapOnCanvas]);
@@ -433,15 +428,6 @@ export const Menu: React.FC<MenuProps> = () => {
? t('menu.view.hide_field_attributes')
: t('menu.view.show_field_attributes')}
</MenubarItem>
{databaseType !== DatabaseType.CLICKHOUSE &&
dependencies &&
dependencies.length > 0 ? (
<MenubarItem onClick={showOrHideDependencies}>
{showDependenciesOnCanvas
? t('menu.view.hide_dependencies')
: t('menu.view.show_dependencies')}
</MenubarItem>
) : null}
<MenubarItem onClick={showOrHideMiniMap}>
{showMiniMapOnCanvas
? t('menu.view.hide_minimap')
@@ -468,6 +454,26 @@ export const Menu: React.FC<MenuProps> = () => {
</MenubarSubContent>
</MenubarSub>
<MenubarSeparator />
<MenubarSub>
<MenubarSubTrigger>
{t('menu.view.show_views')}
</MenubarSubTrigger>
<MenubarSubContent>
<MenubarCheckboxItem
checked={showDBViews}
onClick={() => setShowDBViews(true)}
>
{t('on')}
</MenubarCheckboxItem>
<MenubarCheckboxItem
checked={!showDBViews}
onClick={() => setShowDBViews(false)}
>
{t('off')}
</MenubarCheckboxItem>
</MenubarSubContent>
</MenubarSub>
<MenubarSeparator />
<MenubarSub>
<MenubarSubTrigger className="flex items-center gap-1">
<span>{t('menu.view.theme')}</span>