diff --git a/src/dialogs/table-schema-dialog/table-schema-dialog.tsx b/src/dialogs/table-schema-dialog/table-schema-dialog.tsx index c890d819..285dfa70 100644 --- a/src/dialogs/table-schema-dialog/table-schema-dialog.tsx +++ b/src/dialogs/table-schema-dialog/table-schema-dialog.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, useEffect, useMemo } from 'react'; +import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { useDialog } from '@/hooks/use-dialog'; import { Dialog, @@ -17,11 +17,23 @@ import type { DBSchema } from '@/lib/domain/db-schema'; import { schemaNameToSchemaId } from '@/lib/domain/db-schema'; import type { BaseDialogProps } from '../common/base-dialog-props'; import { useTranslation } from 'react-i18next'; +import { Input } from '@/components/input/input'; +import { Separator } from '@/components/separator/separator'; +import { Group, SquarePlus } from 'lucide-react'; +import { + Tooltip, + TooltipContent, + TooltipTrigger, +} from '@/components/tooltip/tooltip'; +import { useChartDB } from '@/hooks/use-chartdb'; +import { defaultSchemas } from '@/lib/data/default-schemas'; +import { Label } from '@/components/label/label'; export interface TableSchemaDialogProps extends BaseDialogProps { table?: DBTable; schemas: DBSchema[]; onConfirm: ({ schema }: { schema: DBSchema }) => void; + allowSchemaCreation?: boolean; } export const TableSchemaDialog: React.FC = ({ @@ -29,13 +41,32 @@ export const TableSchemaDialog: React.FC = ({ table, schemas, onConfirm, + allowSchemaCreation = false, }) => { const { t } = useTranslation(); - const [selectedSchemaId, setSelectedSchemaId] = React.useState( + const { databaseType, filteredSchemas, filterSchemas } = useChartDB(); + const [selectedSchemaId, setSelectedSchemaId] = useState( table?.schema ? schemaNameToSchemaId(table.schema) : (schemas?.[0]?.id ?? '') ); + const allowSchemaSelection = useMemo( + () => schemas && schemas.length > 0, + [schemas] + ); + + const defaultSchemaName = useMemo( + () => defaultSchemas?.[databaseType], + [databaseType] + ); + + const [isCreatingNew, setIsCreatingNew] = + useState(!allowSchemaSelection); + const [newSchemaName, setNewSchemaName] = useState( + allowSchemaCreation && !allowSchemaSelection + ? (defaultSchemaName ?? '') + : '' + ); useEffect(() => { if (!dialog.open) return; @@ -44,15 +75,56 @@ export const TableSchemaDialog: React.FC = ({ ? schemaNameToSchemaId(table.schema) : (schemas?.[0]?.id ?? '') ); - }, [dialog.open, schemas, table?.schema]); + setIsCreatingNew(!allowSchemaSelection); + setNewSchemaName( + allowSchemaCreation && !allowSchemaSelection + ? (defaultSchemaName ?? '') + : '' + ); + }, [ + defaultSchemaName, + dialog.open, + schemas, + table?.schema, + allowSchemaSelection, + allowSchemaCreation, + ]); + const { closeTableSchemaDialog } = useDialog(); const handleConfirm = useCallback(() => { - const schema = schemas.find((s) => s.id === selectedSchemaId); - if (!schema) return; + let createdSchemaId: string; + if (isCreatingNew && newSchemaName.trim()) { + const newSchema: DBSchema = { + id: schemaNameToSchemaId(newSchemaName.trim()), + name: newSchemaName.trim(), + tableCount: 0, + }; - onConfirm({ schema }); - }, [onConfirm, selectedSchemaId, schemas]); + createdSchemaId = newSchema.id; + + onConfirm({ schema: newSchema }); + } else { + const schema = schemas.find((s) => s.id === selectedSchemaId); + if (!schema) return; + + createdSchemaId = schema.id; + onConfirm({ schema }); + } + + filterSchemas([ + ...(filteredSchemas ?? schemas.map((s) => s.id)), + createdSchemaId, + ]); + }, [ + onConfirm, + selectedSchemaId, + schemas, + isCreatingNew, + newSchemaName, + filteredSchemas, + filterSchemas, + ]); const schemaOptions: SelectBoxOption[] = useMemo( () => @@ -63,6 +135,25 @@ export const TableSchemaDialog: React.FC = ({ [schemas] ); + const renderSwitchCreateOrSelectButton = useCallback( + () => ( + + ), + [isCreatingNew, allowSchemaSelection, allowSchemaCreation] + ); + return ( = ({ - {table - ? t('update_table_schema_dialog.title') - : t('new_table_schema_dialog.title')} + {!allowSchemaSelection && allowSchemaCreation + ? t('create_table_schema_dialog.title') + : table + ? t('update_table_schema_dialog.title') + : t('new_table_schema_dialog.title')} - {table - ? t('update_table_schema_dialog.description', { - tableName: table.name, - }) - : t('new_table_schema_dialog.description')} + {!allowSchemaSelection && allowSchemaCreation + ? t('create_table_schema_dialog.description') + : table + ? t('update_table_schema_dialog.description', { + tableName: table.name, + }) + : t('new_table_schema_dialog.description')}
- - setSelectedSchemaId(value as string) - } - /> + {!isCreatingNew ? ( + + setSelectedSchemaId(value as string) + } + /> + ) : ( +
+ {allowSchemaCreation && + !allowSchemaSelection ? ( + + ) : null} + + setNewSchemaName(e.target.value) + } + placeholder={`Enter schema name.${defaultSchemaName ? ` e.g. ${defaultSchemaName}.` : ''}`} + autoFocus + /> +
+ )} + + {allowSchemaCreation && allowSchemaSelection ? ( + <> +
+ + + or + +
+ {allowSchemaSelection ? ( + renderSwitchCreateOrSelectButton() + ) : ( + + + + {renderSwitchCreateOrSelectButton()} + + + +

No existing schemas available

+
+
+ )} + + ) : null}
- diff --git a/src/i18n/locales/ar.ts b/src/i18n/locales/ar.ts index a87eba44..03511107 100644 --- a/src/i18n/locales/ar.ts +++ b/src/i18n/locales/ar.ts @@ -414,6 +414,13 @@ export const ar: LanguageTranslation = { cancel: 'إلغاء', confirm: 'تغيير', }, + create_table_schema_dialog: { + title: 'إنشاء مخطط جديد', + description: + 'لا توجد مخططات حتى الآن. قم بإنشاء أول مخطط لتنظيم جداولك.', + create: 'إنشاء', + cancel: 'إلغاء', + }, star_us_dialog: { title: '!ساعدنا على التحسن', diff --git a/src/i18n/locales/bn.ts b/src/i18n/locales/bn.ts index 8d0b3edf..e3a0745c 100644 --- a/src/i18n/locales/bn.ts +++ b/src/i18n/locales/bn.ts @@ -416,6 +416,13 @@ export const bn: LanguageTranslation = { cancel: 'বাতিল করুন', confirm: 'পরিবর্তন করুন', }, + create_table_schema_dialog: { + title: 'নতুন স্কিমা তৈরি করুন', + description: + 'এখনও কোনো স্কিমা নেই। আপনার টেবিলগুলি সংগঠিত করতে আপনার প্রথম স্কিমা তৈরি করুন।', + create: 'তৈরি করুন', + cancel: 'বাতিল করুন', + }, star_us_dialog: { title: 'আমাদের উন্নত করতে সাহায্য করুন!', diff --git a/src/i18n/locales/de.ts b/src/i18n/locales/de.ts index aa36ba11..d920f36b 100644 --- a/src/i18n/locales/de.ts +++ b/src/i18n/locales/de.ts @@ -420,6 +420,13 @@ export const de: LanguageTranslation = { cancel: 'Abbrechen', confirm: 'Ändern', }, + create_table_schema_dialog: { + title: 'Neues Schema erstellen', + description: + 'Es existieren noch keine Schemas. Erstellen Sie Ihr erstes Schema, um Ihre Tabellen zu organisieren.', + create: 'Erstellen', + cancel: 'Abbrechen', + }, star_us_dialog: { title: 'Hilf uns, uns zu verbessern!', diff --git a/src/i18n/locales/en.ts b/src/i18n/locales/en.ts index b208f9d0..cafdc417 100644 --- a/src/i18n/locales/en.ts +++ b/src/i18n/locales/en.ts @@ -406,6 +406,14 @@ export const en = { confirm: 'Change', }, + create_table_schema_dialog: { + title: 'Create New Schema', + description: + 'No schemas exist yet. Create your first schema to organize your tables.', + create: 'Create', + cancel: 'Cancel', + }, + star_us_dialog: { title: 'Help us improve!', description: diff --git a/src/i18n/locales/es.ts b/src/i18n/locales/es.ts index 043f04c5..71dc0427 100644 --- a/src/i18n/locales/es.ts +++ b/src/i18n/locales/es.ts @@ -408,6 +408,13 @@ export const es: LanguageTranslation = { cancel: 'Cancelar', confirm: 'Cambiar', }, + create_table_schema_dialog: { + title: 'Crear Nuevo Esquema', + description: + 'Aún no existen esquemas. Crea tu primer esquema para organizar tus tablas.', + create: 'Crear', + cancel: 'Cancelar', + }, star_us_dialog: { title: '¡Ayúdanos a mejorar!', diff --git a/src/i18n/locales/fr.ts b/src/i18n/locales/fr.ts index ff3535f3..fc2d79bd 100644 --- a/src/i18n/locales/fr.ts +++ b/src/i18n/locales/fr.ts @@ -388,6 +388,13 @@ export const fr: LanguageTranslation = { cancel: 'Annuler', confirm: 'Modifier', }, + create_table_schema_dialog: { + title: 'Créer un Nouveau Schéma', + description: + "Aucun schéma n'existe encore. Créez votre premier schéma pour organiser vos tables.", + create: 'Créer', + cancel: 'Annuler', + }, create_relationship_dialog: { title: 'Créer une Relation', diff --git a/src/i18n/locales/gu.ts b/src/i18n/locales/gu.ts index 96598002..8ffb8fe3 100644 --- a/src/i18n/locales/gu.ts +++ b/src/i18n/locales/gu.ts @@ -417,6 +417,14 @@ export const gu: LanguageTranslation = { confirm: 'બદલો', }, + create_table_schema_dialog: { + title: 'નવું સ્કીમા બનાવો', + description: + 'હજી સુધી કોઈ સ્કીમા અસ્તિત્વમાં નથી. તમારા ટેબલ્સ ને વ્યવસ્થિત કરવા માટે તમારું પહેલું સ્કીમા બનાવો.', + create: 'બનાવો', + cancel: 'રદ કરો', + }, + star_us_dialog: { title: 'અમને સુધારવામાં મદદ કરો!', description: diff --git a/src/i18n/locales/hi.ts b/src/i18n/locales/hi.ts index 796f184b..3b661b66 100644 --- a/src/i18n/locales/hi.ts +++ b/src/i18n/locales/hi.ts @@ -420,6 +420,14 @@ export const hi: LanguageTranslation = { confirm: 'बदलें', }, + create_table_schema_dialog: { + title: 'नया स्कीमा बनाएं', + description: + 'अभी तक कोई स्कीमा मौजूद नहीं है। अपनी तालिकाओं को व्यवस्थित करने के लिए अपना पहला स्कीमा बनाएं।', + create: 'बनाएं', + cancel: 'रद्द करें', + }, + star_us_dialog: { title: 'हमें सुधारने में मदद करें!', description: diff --git a/src/i18n/locales/id_ID.ts b/src/i18n/locales/id_ID.ts index fa4eabae..7eee0558 100644 --- a/src/i18n/locales/id_ID.ts +++ b/src/i18n/locales/id_ID.ts @@ -415,6 +415,14 @@ export const id_ID: LanguageTranslation = { confirm: 'Ubah', }, + create_table_schema_dialog: { + title: 'Buat Skema Baru', + description: + 'Belum ada skema yang tersedia. Buat skema pertama Anda untuk mengatur tabel-tabel Anda.', + create: 'Buat', + cancel: 'Batal', + }, + star_us_dialog: { title: 'Bantu kami meningkatkan!', description: diff --git a/src/i18n/locales/ja.ts b/src/i18n/locales/ja.ts index 078a9c67..d705e54f 100644 --- a/src/i18n/locales/ja.ts +++ b/src/i18n/locales/ja.ts @@ -422,6 +422,14 @@ export const ja: LanguageTranslation = { confirm: '変更', }, + create_table_schema_dialog: { + title: '新しいスキーマを作成', + description: + 'スキーマがまだ存在しません。テーブルを整理するために最初のスキーマを作成してください。', + create: '作成', + cancel: 'キャンセル', + }, + star_us_dialog: { title: '改善をサポートしてください!', description: diff --git a/src/i18n/locales/ko_KR.ts b/src/i18n/locales/ko_KR.ts index 2fe6e08a..c7090b2f 100644 --- a/src/i18n/locales/ko_KR.ts +++ b/src/i18n/locales/ko_KR.ts @@ -415,6 +415,14 @@ export const ko_KR: LanguageTranslation = { confirm: '변경', }, + create_table_schema_dialog: { + title: '새 스키마 생성', + description: + '아직 스키마가 없습니다. 테이블을 정리하기 위해 첫 번째 스키마를 생성하세요.', + create: '생성', + cancel: '취소', + }, + star_us_dialog: { title: '개선할 수 있도록 도와주세요!', description: diff --git a/src/i18n/locales/mr.ts b/src/i18n/locales/mr.ts index d875c452..77920c65 100644 --- a/src/i18n/locales/mr.ts +++ b/src/i18n/locales/mr.ts @@ -423,6 +423,14 @@ export const mr: LanguageTranslation = { confirm: 'बदला', }, + create_table_schema_dialog: { + title: 'नवीन स्कीमा तयार करा', + description: + 'अजून कोणतीही स्कीमा अस्तित्वात नाही. आपल्या टेबल्स व्यवस्थित करण्यासाठी आपली पहिली स्कीमा तयार करा.', + create: 'तयार करा', + cancel: 'रद्द करा', + }, + star_us_dialog: { title: 'आम्हाला सुधारण्यास मदत करा!', description: diff --git a/src/i18n/locales/ne.ts b/src/i18n/locales/ne.ts index 8ec0de9b..f07d05cf 100644 --- a/src/i18n/locales/ne.ts +++ b/src/i18n/locales/ne.ts @@ -420,6 +420,14 @@ export const ne: LanguageTranslation = { confirm: 'परिवर्तन गर्नुहोस्', }, + create_table_schema_dialog: { + title: 'नयाँ स्कीम सिर्जना गर्नुहोस्', + description: + 'अहिलेसम्म कुनै स्कीम अस्तित्वमा छैन। आफ्ना तालिकाहरू व्यवस्थित गर्न आफ्नो पहिलो स्कीम सिर्जना गर्नुहोस्।', + create: 'सिर्जना गर्नुहोस्', + cancel: 'रद्द गर्नुहोस्', + }, + star_us_dialog: { title: 'हामीलाई अझ राम्रो हुन मदत गर्नुहोस!', description: diff --git a/src/i18n/locales/pt_BR.ts b/src/i18n/locales/pt_BR.ts index 65662b64..c74d1f31 100644 --- a/src/i18n/locales/pt_BR.ts +++ b/src/i18n/locales/pt_BR.ts @@ -418,6 +418,14 @@ export const pt_BR: LanguageTranslation = { confirm: 'Alterar', }, + create_table_schema_dialog: { + title: 'Criar Novo Esquema', + description: + 'Ainda não existem esquemas. Crie seu primeiro esquema para organizar suas tabelas.', + create: 'Criar', + cancel: 'Cancelar', + }, + star_us_dialog: { title: 'Ajude-nos a melhorar!', description: diff --git a/src/i18n/locales/ru.ts b/src/i18n/locales/ru.ts index a6486682..a8bacc32 100644 --- a/src/i18n/locales/ru.ts +++ b/src/i18n/locales/ru.ts @@ -415,6 +415,14 @@ export const ru: LanguageTranslation = { confirm: 'Изменить', }, + create_table_schema_dialog: { + title: 'Создать новую схему', + description: + 'Схемы еще не существуют. Создайте вашу первую схему, чтобы организовать таблицы.', + create: 'Создать', + cancel: 'Отменить', + }, + star_us_dialog: { title: 'Помогите нам стать лучше!', description: diff --git a/src/i18n/locales/te.ts b/src/i18n/locales/te.ts index 9c1647bc..1d3fa1ac 100644 --- a/src/i18n/locales/te.ts +++ b/src/i18n/locales/te.ts @@ -419,6 +419,14 @@ export const te: LanguageTranslation = { confirm: 'మార్చు', }, + create_table_schema_dialog: { + title: 'కొత్త స్కీమా సృష్టించండి', + description: + 'ఇంకా ఏ స్కీమాలు లేవు. మీ పట్టికలను వ్యవస్థీకరించడానికి మీ మొదటి స్కీమాను సృష్టించండి.', + create: 'సృష్టించు', + cancel: 'రద్దు', + }, + star_us_dialog: { title: 'మా సహాయంతో మెరుగుపరచండి!', description: diff --git a/src/i18n/locales/tr.ts b/src/i18n/locales/tr.ts index 065cee3e..30d4ceee 100644 --- a/src/i18n/locales/tr.ts +++ b/src/i18n/locales/tr.ts @@ -408,6 +408,14 @@ export const tr: LanguageTranslation = { cancel: 'İptal', confirm: 'Değiştir', }, + + create_table_schema_dialog: { + title: 'Yeni Şema Oluştur', + description: + 'Henüz hiç şema mevcut değil. Tablolarınızı düzenlemek için ilk şemanızı oluşturun.', + create: 'Oluştur', + cancel: 'İptal', + }, star_us_dialog: { title: 'Bize yardım et!', description: diff --git a/src/i18n/locales/uk.ts b/src/i18n/locales/uk.ts index 19a76d8b..93f0f3c7 100644 --- a/src/i18n/locales/uk.ts +++ b/src/i18n/locales/uk.ts @@ -416,6 +416,14 @@ export const uk: LanguageTranslation = { confirm: 'Змінити', }, + create_table_schema_dialog: { + title: 'Створити нову схему', + description: + 'Поки що не існує жодної схеми. Створіть свою першу схему, щоб організувати ваші таблиці.', + create: 'Створити', + cancel: 'Скасувати', + }, + star_us_dialog: { title: 'Допоможіть нам покращитися!', description: 'Поставне на зірку на GitHub? Це лише один клік!', diff --git a/src/i18n/locales/vi.ts b/src/i18n/locales/vi.ts index 106db0d1..36ecea09 100644 --- a/src/i18n/locales/vi.ts +++ b/src/i18n/locales/vi.ts @@ -415,6 +415,14 @@ export const vi: LanguageTranslation = { confirm: 'Xác nhận', }, + create_table_schema_dialog: { + title: 'Tạo lược đồ mới', + description: + 'Chưa có lược đồ nào. Tạo lược đồ đầu tiên của bạn để tổ chức các bảng.', + create: 'Tạo', + cancel: 'Hủy', + }, + star_us_dialog: { title: 'Hãy giúp chúng tôi cải thiện!', description: diff --git a/src/i18n/locales/zh_CN.ts b/src/i18n/locales/zh_CN.ts index 76fc7137..a621557e 100644 --- a/src/i18n/locales/zh_CN.ts +++ b/src/i18n/locales/zh_CN.ts @@ -411,6 +411,13 @@ export const zh_CN: LanguageTranslation = { confirm: '更改', }, + create_table_schema_dialog: { + title: '创建新模式', + description: '尚未存在任何模式。创建您的第一个模式来组织您的表。', + create: '创建', + cancel: '取消', + }, + star_us_dialog: { title: '帮助我们改进!', description: '您想在 GitHub 上为我们加注星标吗?只需点击一下即可!', diff --git a/src/i18n/locales/zh_TW.ts b/src/i18n/locales/zh_TW.ts index 9cffe335..3d2d8d9a 100644 --- a/src/i18n/locales/zh_TW.ts +++ b/src/i18n/locales/zh_TW.ts @@ -410,6 +410,14 @@ export const zh_TW: LanguageTranslation = { confirm: '變更', }, + create_table_schema_dialog: { + title: '建立新 Schema', + description: + '尚未存在任何 Schema。建立您的第一個 Schema 來組織您的表格。', + create: '建立', + cancel: '取消', + }, + star_us_dialog: { title: '協助我們改善!', description: '請在 GitHub 上給我們一顆星,只需點擊一下!', diff --git a/src/pages/editor-page/side-panel/tables-section/table-list/table-list-item/table-list-item-header/table-list-item-header.tsx b/src/pages/editor-page/side-panel/tables-section/table-list/table-list-item/table-list-item-header/table-list-item-header.tsx index 93503e1a..1b6d5d0e 100644 --- a/src/pages/editor-page/side-panel/tables-section/table-list/table-list-item/table-list-item-header/table-list-item-header.tsx +++ b/src/pages/editor-page/side-panel/tables-section/table-list/table-list-item/table-list-item-header/table-list-item-header.tsx @@ -38,6 +38,7 @@ import { } from '@/components/tooltip/tooltip'; import { cloneTable } from '@/lib/clone'; import type { DBSchema } from '@/lib/domain'; +import { defaultSchemas } from '@/lib/data/default-schemas'; export interface TableListItemHeaderProps { table: DBTable; @@ -48,12 +49,14 @@ export const TableListItemHeader: React.FC = ({ }) => { const { updateTable, + updateTablesState, removeTable, createIndex, createField, createTable, schemas, filteredSchemas, + databaseType, } = useChartDB(); const { openTableSchemaDialog } = useDialog(); const { t } = useTranslation(); @@ -128,9 +131,15 @@ export const TableListItemHeader: React.FC = ({ const updateTableSchema = useCallback( ({ schema }: { schema: DBSchema }) => { - updateTable(table.id, { schema: schema.name }); + updateTablesState((currentTables) => + currentTables.map((t) => + t.id === table.id || !t.schema + ? { ...t, schema: schema.name } + : t + ) + ); }, - [table.id, updateTable] + [table.id, updateTablesState] ); const changeSchema = useCallback(() => { @@ -138,6 +147,7 @@ export const TableListItemHeader: React.FC = ({ table, schemas, onConfirm: updateTableSchema, + allowSchemaCreation: true, }); }, [openTableSchemaDialog, table, schemas, updateTableSchema]); @@ -170,7 +180,7 @@ export const TableListItemHeader: React.FC = ({ )} - {schemas.length > 0 ? ( + {schemas.length > 0 || defaultSchemas?.[databaseType] ? ( <> = ({ t, changeSchema, schemas.length, + databaseType, ] );