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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -37,6 +37,7 @@ export const es: LanguageTranslation = {
show_sidebar: 'Mostrar Barra Lateral', show_sidebar: 'Mostrar Barra Lateral',
hide_sidebar: 'Ocultar Barra Lateral', hide_sidebar: 'Ocultar Barra Lateral',
zoom_on_scroll: 'Zoom al Desplazarse', zoom_on_scroll: 'Zoom al Desplazarse',
show_views: 'Vistas de Base de Datos',
theme: 'Tema', theme: 'Tema',
show_dependencies: 'Mostrar dependencias', show_dependencies: 'Mostrar dependencias',
hide_dependencies: 'Ocultar dependencias', hide_dependencies: 'Ocultar dependencias',
@@ -118,6 +119,7 @@ export const es: LanguageTranslation = {
tables_section: { tables_section: {
tables: 'Tablas', tables: 'Tablas',
add_table: 'Agregar Tabla', add_table: 'Agregar Tabla',
add_view: 'Agregar Vista',
filter: 'Filtrar', filter: 'Filtrar',
collapse: 'Colapsar Todo', collapse: 'Colapsar Todo',
// TODO: Translate // TODO: Translate
@@ -478,6 +480,7 @@ export const es: LanguageTranslation = {
canvas_context_menu: { canvas_context_menu: {
new_table: 'Nueva Tabla', new_table: 'Nueva Tabla',
new_view: 'Nueva Vista',
new_relationship: 'Nueva Relación', new_relationship: 'Nueva Relación',
// TODO: Translate // TODO: Translate
new_area: 'New Area', new_area: 'New Area',
@@ -500,6 +503,9 @@ export const es: LanguageTranslation = {
language_select: { language_select: {
change_language: 'Idioma', 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', hide_field_attributes: 'Masquer les Attributs de Champ',
show_field_attributes: 'Afficher les Attributs de Champ', show_field_attributes: 'Afficher les Attributs de Champ',
zoom_on_scroll: 'Zoom sur le Défilement', zoom_on_scroll: 'Zoom sur le Défilement',
show_views: 'Vues de Base de Données',
theme: 'Thème', theme: 'Thème',
show_dependencies: 'Afficher les Dépendances', show_dependencies: 'Afficher les Dépendances',
hide_dependencies: 'Masquer les Dépendances', hide_dependencies: 'Masquer les Dépendances',
@@ -117,6 +118,7 @@ export const fr: LanguageTranslation = {
tables_section: { tables_section: {
tables: 'Tables', tables: 'Tables',
add_table: 'Ajouter une Table', add_table: 'Ajouter une Table',
add_view: 'Ajouter une Vue',
filter: 'Filtrer', filter: 'Filtrer',
collapse: 'Réduire Tout', collapse: 'Réduire Tout',
clear: 'Effacer le Filtre', clear: 'Effacer le Filtre',
@@ -474,6 +476,7 @@ export const fr: LanguageTranslation = {
canvas_context_menu: { canvas_context_menu: {
new_table: 'Nouvelle Table', new_table: 'Nouvelle Table',
new_view: 'Nouvelle Vue',
new_relationship: 'Nouvelle Relation', new_relationship: 'Nouvelle Relation',
// TODO: Translate // TODO: Translate
new_area: 'New Area', new_area: 'New Area',
@@ -496,6 +499,9 @@ export const fr: LanguageTranslation = {
language_select: { language_select: {
change_language: 'Langue', change_language: 'Langue',
}, },
on: 'Activé',
off: 'Désactivé',
}, },
}; };

View File

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

View File

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

View File

@@ -37,6 +37,7 @@ export const hr: LanguageTranslation = {
hide_field_attributes: 'Sakrij atribute polja', hide_field_attributes: 'Sakrij atribute polja',
show_field_attributes: 'Prikaži atribute polja', show_field_attributes: 'Prikaži atribute polja',
zoom_on_scroll: 'Zumiranje pri skrolanju', zoom_on_scroll: 'Zumiranje pri skrolanju',
show_views: 'Pogledi Baze Podataka',
theme: 'Tema', theme: 'Tema',
show_dependencies: 'Prikaži ovisnosti', show_dependencies: 'Prikaži ovisnosti',
hide_dependencies: 'Sakrij ovisnosti', hide_dependencies: 'Sakrij ovisnosti',
@@ -117,6 +118,7 @@ export const hr: LanguageTranslation = {
tables_section: { tables_section: {
tables: 'Tablice', tables: 'Tablice',
add_table: 'Dodaj tablicu', add_table: 'Dodaj tablicu',
add_view: 'Dodaj Pogled',
filter: 'Filtriraj', filter: 'Filtriraj',
collapse: 'Sažmi sve', collapse: 'Sažmi sve',
clear: 'Očisti filter', clear: 'Očisti filter',
@@ -471,6 +473,7 @@ export const hr: LanguageTranslation = {
canvas_context_menu: { canvas_context_menu: {
new_table: 'Nova tablica', new_table: 'Nova tablica',
new_view: 'Novi Pogled',
new_relationship: 'Nova veza', new_relationship: 'Nova veza',
new_area: 'Novo područje', new_area: 'Novo područje',
}, },
@@ -491,6 +494,9 @@ export const hr: LanguageTranslation = {
language_select: { language_select: {
change_language: 'Jezik', 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', hide_field_attributes: 'Sembunyikan Atribut Kolom',
show_field_attributes: 'Tampilkan Atribut Kolom', show_field_attributes: 'Tampilkan Atribut Kolom',
zoom_on_scroll: 'Perbesar saat Scroll', zoom_on_scroll: 'Perbesar saat Scroll',
show_views: 'Tampilan Database',
theme: 'Tema', theme: 'Tema',
show_dependencies: 'Tampilkan Dependensi', show_dependencies: 'Tampilkan Dependensi',
hide_dependencies: 'Sembunyikan Dependensi', hide_dependencies: 'Sembunyikan Dependensi',
@@ -118,6 +119,7 @@ export const id_ID: LanguageTranslation = {
tables_section: { tables_section: {
tables: 'Tabel', tables: 'Tabel',
add_table: 'Tambah Tabel', add_table: 'Tambah Tabel',
add_view: 'Tambah Tampilan',
filter: 'Saring', filter: 'Saring',
collapse: 'Lipat Semua', collapse: 'Lipat Semua',
// TODO: Translate // TODO: Translate
@@ -476,6 +478,7 @@ export const id_ID: LanguageTranslation = {
canvas_context_menu: { canvas_context_menu: {
new_table: 'Tabel Baru', new_table: 'Tabel Baru',
new_view: 'Tampilan Baru',
new_relationship: 'Hubungan Baru', new_relationship: 'Hubungan Baru',
// TODO: Translate // TODO: Translate
new_area: 'New Area', new_area: 'New Area',
@@ -497,6 +500,9 @@ export const id_ID: LanguageTranslation = {
language_select: { language_select: {
change_language: 'Bahasa', change_language: 'Bahasa',
}, },
on: 'Aktif',
off: 'Nonaktif',
}, },
}; };

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -37,6 +37,7 @@ export const uk: LanguageTranslation = {
show_field_attributes: 'Показати атрибути полів', show_field_attributes: 'Показати атрибути полів',
hide_field_attributes: 'Приховати атрибути полів', hide_field_attributes: 'Приховати атрибути полів',
zoom_on_scroll: 'Масштабувати прокручуванням', zoom_on_scroll: 'Масштабувати прокручуванням',
show_views: 'Представлення бази даних',
theme: 'Тема', theme: 'Тема',
show_dependencies: 'Показати залежності', show_dependencies: 'Показати залежності',
hide_dependencies: 'Приховати залежності', hide_dependencies: 'Приховати залежності',
@@ -117,6 +118,7 @@ export const uk: LanguageTranslation = {
tables_section: { tables_section: {
tables: 'Таблиці', tables: 'Таблиці',
add_table: 'Додати таблицю', add_table: 'Додати таблицю',
add_view: 'Додати представлення',
filter: 'Фільтр', filter: 'Фільтр',
collapse: 'Згорнути все', collapse: 'Згорнути все',
// TODO: Translate // TODO: Translate
@@ -473,6 +475,7 @@ export const uk: LanguageTranslation = {
canvas_context_menu: { canvas_context_menu: {
new_table: 'Нова таблиця', new_table: 'Нова таблиця',
new_view: 'Нове представлення',
new_relationship: 'Новий звʼязок', new_relationship: 'Новий звʼязок',
// TODO: Translate // TODO: Translate
new_area: 'New Area', new_area: 'New Area',
@@ -494,6 +497,9 @@ export const uk: LanguageTranslation = {
language_select: { language_select: {
change_language: 'Мова', 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', show_field_attributes: 'Hiển thị thuộc tính trường',
hide_field_attributes: 'Ẩn 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', zoom_on_scroll: 'Thu phóng khi cuộn',
show_views: 'Chế độ xem Cơ sở dữ liệu',
theme: 'Chủ đề', theme: 'Chủ đề',
show_dependencies: 'Hiển thị các phụ thuộc', show_dependencies: 'Hiển thị các phụ thuộc',
hide_dependencies: 'Ẩn các phụ thuộc', hide_dependencies: 'Ẩn các phụ thuộc',
@@ -118,6 +119,7 @@ export const vi: LanguageTranslation = {
tables_section: { tables_section: {
tables: 'Bảng', tables: 'Bảng',
add_table: 'Thêm bảng', add_table: 'Thêm bảng',
add_view: 'Thêm Chế độ xem',
filter: 'Lọc', filter: 'Lọc',
collapse: 'Thu gọn tất cả', collapse: 'Thu gọn tất cả',
// TODO: Translate // TODO: Translate
@@ -474,6 +476,7 @@ export const vi: LanguageTranslation = {
canvas_context_menu: { canvas_context_menu: {
new_table: 'Tạo bảng mới', new_table: 'Tạo bảng mới',
new_view: 'Chế độ xem Mới',
new_relationship: 'Tạo quan hệ mới', new_relationship: 'Tạo quan hệ mới',
// TODO: Translate // TODO: Translate
new_area: 'New Area', new_area: 'New Area',
@@ -495,6 +498,9 @@ export const vi: LanguageTranslation = {
language_select: { language_select: {
change_language: 'Ngôn ngữ', 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: '展示字段属性', show_field_attributes: '展示字段属性',
hide_field_attributes: '隐藏字段属性', hide_field_attributes: '隐藏字段属性',
zoom_on_scroll: '滚动缩放', zoom_on_scroll: '滚动缩放',
show_views: '数据库视图',
theme: '主题', theme: '主题',
show_dependencies: '展示依赖', show_dependencies: '展示依赖',
hide_dependencies: '隐藏依赖', hide_dependencies: '隐藏依赖',
@@ -115,6 +116,7 @@ export const zh_CN: LanguageTranslation = {
tables_section: { tables_section: {
tables: '表', tables: '表',
add_table: '添加表', add_table: '添加表',
add_view: '添加视图',
filter: '筛选', filter: '筛选',
collapse: '全部折叠', collapse: '全部折叠',
// TODO: Translate // TODO: Translate
@@ -469,6 +471,7 @@ export const zh_CN: LanguageTranslation = {
canvas_context_menu: { canvas_context_menu: {
new_table: '新建表', new_table: '新建表',
new_view: '新建视图',
new_relationship: '新建关系', new_relationship: '新建关系',
// TODO: Translate // TODO: Translate
new_area: 'New Area', new_area: 'New Area',
@@ -490,6 +493,9 @@ export const zh_CN: LanguageTranslation = {
language_select: { language_select: {
change_language: '语言', change_language: '语言',
}, },
on: '开启',
off: '关闭',
}, },
}; };

View File

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

View File

@@ -10,8 +10,9 @@ import { useDialog } from '@/hooks/use-dialog';
import { useReactFlow } from '@xyflow/react'; import { useReactFlow } from '@xyflow/react';
import React, { useCallback } from 'react'; import React, { useCallback } from 'react';
import { useTranslation } from 'react-i18next'; 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 { useDiagramFilter } from '@/context/diagram-filter-context/use-diagram-filter';
import { useLocalConfig } from '@/hooks/use-local-config';
export const CanvasContextMenu: React.FC<React.PropsWithChildren> = ({ export const CanvasContextMenu: React.FC<React.PropsWithChildren> = ({
children, children,
@@ -21,6 +22,7 @@ export const CanvasContextMenu: React.FC<React.PropsWithChildren> = ({
const { openCreateRelationshipDialog, openTableSchemaDialog } = useDialog(); const { openCreateRelationshipDialog, openTableSchemaDialog } = useDialog();
const { screenToFlowPosition } = useReactFlow(); const { screenToFlowPosition } = useReactFlow();
const { t } = useTranslation(); const { t } = useTranslation();
const { showDBViews } = useLocalConfig();
const { isMd: isDesktop } = useBreakpoint('md'); 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( const createAreaHandler = useCallback(
(event: React.MouseEvent<HTMLDivElement, MouseEvent>) => { (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
const position = screenToFlowPosition({ const position = screenToFlowPosition({
@@ -97,6 +138,15 @@ export const CanvasContextMenu: React.FC<React.PropsWithChildren> = ({
{t('canvas_context_menu.new_table')} {t('canvas_context_menu.new_table')}
<Table className="size-3.5" /> <Table className="size-3.5" />
</ContextMenuItem> </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 <ContextMenuItem
onClick={createRelationshipHandler} onClick={createRelationshipHandler}
className="flex justify-between gap-4" className="flex justify-between gap-4"

View File

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

View File

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

View File

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

View File

@@ -1,7 +1,7 @@
import React, { useCallback, useMemo } 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, X } from 'lucide-react'; import { Table, View, 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';
@@ -15,6 +15,8 @@ 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';
import { defaultSchemas } from '@/lib/data/default-schemas'; 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 {} export interface TablesSectionProps {}
@@ -26,6 +28,7 @@ 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 { showDBViews } = useLocalConfig();
const filterInputRef = React.useRef<HTMLInputElement>(null); const filterInputRef = React.useRef<HTMLInputElement>(null);
const filteredTables = useMemo(() => { const filteredTables = useMemo(() => {
@@ -45,16 +48,26 @@ export const TablesSection: React.FC<TablesSectionProps> = () => {
}, },
}); });
return tables.filter(filterTables).filter(filterTableName); const filterViews: (table: DBTable) => boolean = (table) =>
}, [tables, filterText, filter, databaseType]); 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( const createTableWithLocation = useCallback(
async ({ schema }: { schema?: DBSchema }) => { async ({ schema }: { schema?: DBSchema }) => {
const padding = 80; const { centerX, centerY } = getCenterLocation();
const centerX =
-viewport.x / viewport.zoom + padding / viewport.zoom;
const centerY =
-viewport.y / viewport.zoom + padding / viewport.zoom;
const table = await createTable({ const table = await createTable({
x: centerX, x: centerX,
y: centerY, y: centerY,
@@ -62,34 +75,55 @@ export const TablesSection: React.FC<TablesSectionProps> = () => {
}); });
openTableFromSidebar(table.id); openTableFromSidebar(table.id);
}, },
[ [createTable, openTableFromSidebar, getCenterLocation]
createTable,
openTableFromSidebar,
viewport.x,
viewport.y,
viewport.zoom,
]
); );
const handleCreateTable = useCallback(async () => { const createViewWithLocation = useCallback(
setFilterText(''); async ({ schema }: { schema?: DBSchema }) => {
const { centerX, centerY } = getCenterLocation();
if (schemasDisplayed.length > 1) { const table = await createTable({
openTableSchemaDialog({ x: centerX,
onConfirm: createTableWithLocation, y: centerY,
schemas: schemasDisplayed, schema: schema?.name,
isView: true,
}); });
} else { openTableFromSidebar(table.id);
const schema = },
schemasDisplayed.length === 1 ? schemasDisplayed[0] : undefined; [createTable, openTableFromSidebar, getCenterLocation]
createTableWithLocation({ schema }); );
}
}, [ const handleCreateTable = useCallback(
createTableWithLocation, async ({ view }: { view?: boolean }) => {
schemasDisplayed, setFilterText('');
openTableSchemaDialog,
setFilterText, if (schemasDisplayed.length > 1) {
]); openTableSchemaDialog({
onConfirm: view
? createViewWithLocation
: createTableWithLocation,
schemas: schemasDisplayed,
});
} else {
const schema =
schemasDisplayed.length === 1
? schemasDisplayed[0]
: undefined;
if (view) {
createViewWithLocation({ schema });
} else {
createTableWithLocation({ schema });
}
}
},
[
createViewWithLocation,
createTableWithLocation,
schemasDisplayed,
openTableSchemaDialog,
setFilterText,
]
);
const handleClearFilter = useCallback(() => { const handleClearFilter = useCallback(() => {
setFilterText(''); setFilterText('');
@@ -111,14 +145,31 @@ export const TablesSection: React.FC<TablesSectionProps> = () => {
onChange={(e) => setFilterText(e.target.value)} onChange={(e) => setFilterText(e.target.value)}
/> />
</div> </div>
<Button <ButtonWithAlternatives
variant="secondary" variant="secondary"
className="h-8 p-2 text-xs" 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" /> <Table className="h-4" />
{t('side_panel.tables_section.add_table')} {t('side_panel.tables_section.add_table')}
</Button> </ButtonWithAlternatives>
</div> </div>
<div className="flex flex-1 flex-col overflow-hidden"> <div className="flex flex-1 flex-col overflow-hidden">
<ScrollArea className="h-full"> <ScrollArea className="h-full">

View File

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