diff --git a/src/context/canvas-context/canvas-provider.tsx b/src/context/canvas-context/canvas-provider.tsx index ab819991..0401148b 100644 --- a/src/context/canvas-context/canvas-provider.tsx +++ b/src/context/canvas-context/canvas-provider.tsx @@ -1,4 +1,11 @@ -import React, { type ReactNode, useCallback, useState } from 'react'; +import React, { + type ReactNode, + useCallback, + useState, + useMemo, + useEffect, + useRef, +} from 'react'; import { canvasContext } from './canvas-context'; import { useChartDB } from '@/hooks/use-chartdb'; import { @@ -15,13 +22,49 @@ interface CanvasProviderProps { } export const CanvasProvider = ({ children }: CanvasProviderProps) => { - const { tables, relationships, updateTablesState, filteredSchemas } = - useChartDB(); + const { + tables, + relationships, + updateTablesState, + filteredSchemas, + hiddenTableIds, + schemas, + } = useChartDB(); const { fitView } = useReactFlow(); const [overlapGraph, setOverlapGraph] = useState>(createGraph()); + // Check if there are any filtered items to determine initial showFilter state + const hasFilteredItems = useMemo(() => { + const hasHiddenTables = (hiddenTableIds ?? []).length > 0; + const hasSchemasFilter = + filteredSchemas && + schemas.length > 0 && + filteredSchemas.length < schemas.length; + return hasHiddenTables || hasSchemasFilter; + }, [filteredSchemas, hiddenTableIds, schemas]); + const [showFilter, setShowFilter] = useState(false); + const hasInitialized = useRef(false); + + // Only auto-show filter on initial load if there are filtered items + // Wait for data to be defined (not just empty arrays) before initializing + useEffect(() => { + const dataLoaded = + filteredSchemas !== undefined && hiddenTableIds !== undefined; + + if (!hasInitialized.current && dataLoaded) { + // Add 2 seconds delay to ensure all data is fully loaded + const timer = setTimeout(() => { + if (hasFilteredItems) { + setShowFilter(true); + } + hasInitialized.current = true; + }, 2000); + + return () => clearTimeout(timer); + } + }, [hasFilteredItems, filteredSchemas, hiddenTableIds]); const reorderTables = useCallback( ( diff --git a/src/context/chartdb-context/chartdb-provider.tsx b/src/context/chartdb-context/chartdb-provider.tsx index d7d68f11..2214eec6 100644 --- a/src/context/chartdb-context/chartdb-provider.tsx +++ b/src/context/chartdb-context/chartdb-provider.tsx @@ -155,17 +155,18 @@ export const ChartDBProvider: React.FC< return undefined; } - const schemasFilterFromCache = - (schemasFilter[diagramId] ?? []).length === 0 - ? undefined // in case of empty filter, skip cache - : schemasFilter[diagramId]; + const schemasFilterFromCache = schemasFilter[diagramId]; - return ( - schemasFilterFromCache ?? [ - schemas.find((s) => s.name === defaultSchemaName)?.id ?? - schemas[0]?.id, - ] - ); + // If there's an explicit filter set (even if empty), use it + if (schemasFilterFromCache !== undefined) { + return schemasFilterFromCache; + } + + // Only default to showing schemas if no filter has been set + return [ + schemas.find((s) => s.name === defaultSchemaName)?.id ?? + schemas[0]?.id, + ]; }, [schemasFilter, diagramId, schemas, defaultSchemaName]); const currentDiagram: Diagram = useMemo( diff --git a/src/context/layout-context/layout-context.tsx b/src/context/layout-context/layout-context.tsx index 12885e5a..a3c2df1a 100644 --- a/src/context/layout-context/layout-context.tsx +++ b/src/context/layout-context/layout-context.tsx @@ -36,10 +36,6 @@ export interface LayoutContext { hideSidePanel: () => void; showSidePanel: () => void; toggleSidePanel: () => void; - - isSelectSchemaOpen: boolean; - openSelectSchema: () => void; - closeSelectSchema: () => void; } export const layoutContext = createContext({ @@ -70,8 +66,4 @@ export const layoutContext = createContext({ hideSidePanel: emptyFn, showSidePanel: emptyFn, toggleSidePanel: emptyFn, - - isSelectSchemaOpen: false, - openSelectSchema: emptyFn, - closeSelectSchema: emptyFn, }); diff --git a/src/context/layout-context/layout-provider.tsx b/src/context/layout-context/layout-provider.tsx index d1db4cb3..c7aec87e 100644 --- a/src/context/layout-context/layout-provider.tsx +++ b/src/context/layout-context/layout-provider.tsx @@ -23,8 +23,6 @@ export const LayoutProvider: React.FC = ({ React.useState('tables'); const [isSidePanelShowed, setIsSidePanelShowed] = React.useState(isDesktop); - const [isSelectSchemaOpen, setIsSelectSchemaOpen] = - React.useState(false); const closeAllTablesInSidebar: LayoutContext['closeAllTablesInSidebar'] = () => setOpenedTableInSidebar(''); @@ -88,11 +86,6 @@ export const LayoutProvider: React.FC = ({ setOpenedTableInSidebar(customTypeId); }; - const openSelectSchema: LayoutContext['openSelectSchema'] = () => - setIsSelectSchemaOpen(true); - - const closeSelectSchema: LayoutContext['closeSelectSchema'] = () => - setIsSelectSchemaOpen(false); return ( = ({ hideSidePanel, showSidePanel, toggleSidePanel, - isSelectSchemaOpen, - openSelectSchema, - closeSelectSchema, openedDependencyInSidebar, openDependencyFromSidebar, closeAllDependenciesInSidebar, diff --git a/src/context/local-config-context/local-config-context.tsx b/src/context/local-config-context/local-config-context.tsx index c0f2fb0d..cebe90a8 100644 --- a/src/context/local-config-context/local-config-context.tsx +++ b/src/context/local-config-context/local-config-context.tsx @@ -22,11 +22,6 @@ export interface LocalConfigContext { showFieldAttributes: boolean; setShowFieldAttributes: (showFieldAttributes: boolean) => void; - hideMultiSchemaNotification: boolean; - setHideMultiSchemaNotification: ( - hideMultiSchemaNotification: boolean - ) => void; - githubRepoOpened: boolean; setGithubRepoOpened: (githubRepoOpened: boolean) => void; @@ -56,9 +51,6 @@ export const LocalConfigContext = createContext({ showFieldAttributes: true, setShowFieldAttributes: emptyFn, - hideMultiSchemaNotification: false, - setHideMultiSchemaNotification: emptyFn, - githubRepoOpened: false, setGithubRepoOpened: emptyFn, diff --git a/src/context/local-config-context/local-config-provider.tsx b/src/context/local-config-context/local-config-provider.tsx index b582e03a..9d0a47ec 100644 --- a/src/context/local-config-context/local-config-provider.tsx +++ b/src/context/local-config-context/local-config-provider.tsx @@ -8,7 +8,6 @@ const scrollActionKey = 'scroll_action'; const schemasFilterKey = 'schemas_filter'; const showCardinalityKey = 'show_cardinality'; const showFieldAttributesKey = 'show_field_attributes'; -const hideMultiSchemaNotificationKey = 'hide_multi_schema_notification'; const githubRepoOpenedKey = 'github_repo_opened'; const starUsDialogLastOpenKey = 'star_us_dialog_last_open'; const showDependenciesOnCanvasKey = 'show_dependencies_on_canvas'; @@ -40,12 +39,6 @@ export const LocalConfigProvider: React.FC = ({ (localStorage.getItem(showFieldAttributesKey) || 'true') === 'true' ); - const [hideMultiSchemaNotification, setHideMultiSchemaNotification] = - React.useState( - (localStorage.getItem(hideMultiSchemaNotificationKey) || - 'false') === 'true' - ); - const [githubRepoOpened, setGithubRepoOpened] = React.useState( (localStorage.getItem(githubRepoOpenedKey) || 'false') === 'true' ); @@ -77,13 +70,6 @@ export const LocalConfigProvider: React.FC = ({ localStorage.setItem(githubRepoOpenedKey, githubRepoOpened.toString()); }, [githubRepoOpened]); - useEffect(() => { - localStorage.setItem( - hideMultiSchemaNotificationKey, - hideMultiSchemaNotification.toString() - ); - }, [hideMultiSchemaNotification]); - useEffect(() => { localStorage.setItem(themeKey, theme); }, [theme]); @@ -127,8 +113,6 @@ export const LocalConfigProvider: React.FC = ({ setShowCardinality, showFieldAttributes, setShowFieldAttributes, - hideMultiSchemaNotification, - setHideMultiSchemaNotification, setGithubRepoOpened, githubRepoOpened, starUsDialogLastOpen, diff --git a/src/i18n/locales/ar.ts b/src/i18n/locales/ar.ts index 03511107..f4baa9b9 100644 --- a/src/i18n/locales/ar.ts +++ b/src/i18n/locales/ar.ts @@ -128,6 +128,8 @@ export const ar: LanguageTranslation = { // TODO: Translate clear: 'Clear Filter', no_results: 'No tables found matching your filter.', + all_tables_filtered: 'All tables are filtered.', + open_filter: 'Open Filter', // TODO: Translate show_list: 'Show Table List', show_dbml: 'Show DBML Editor', diff --git a/src/i18n/locales/bn.ts b/src/i18n/locales/bn.ts index e3a0745c..19c46cf3 100644 --- a/src/i18n/locales/bn.ts +++ b/src/i18n/locales/bn.ts @@ -129,6 +129,8 @@ export const bn: LanguageTranslation = { // TODO: Translate clear: 'Clear Filter', no_results: 'No tables found matching your filter.', + all_tables_filtered: 'All tables are filtered.', + open_filter: 'Open Filter', // TODO: Translate show_list: 'Show Table List', show_dbml: 'Show DBML Editor', diff --git a/src/i18n/locales/de.ts b/src/i18n/locales/de.ts index d920f36b..b3b96f2c 100644 --- a/src/i18n/locales/de.ts +++ b/src/i18n/locales/de.ts @@ -130,6 +130,8 @@ export const de: LanguageTranslation = { // TODO: Translate clear: 'Clear Filter', no_results: 'No tables found matching your filter.', + all_tables_filtered: 'All tables are filtered.', + open_filter: 'Open Filter', // TODO: Translate show_list: 'Show Table List', show_dbml: 'Show DBML Editor', diff --git a/src/i18n/locales/en.ts b/src/i18n/locales/en.ts index cafdc417..ad4746e9 100644 --- a/src/i18n/locales/en.ts +++ b/src/i18n/locales/en.ts @@ -125,6 +125,8 @@ export const en = { collapse: 'Collapse All', clear: 'Clear Filter', no_results: 'No tables found matching your filter.', + all_tables_filtered: 'All tables are filtered.', + open_filter: 'Open Filter', show_list: 'Show Table List', show_dbml: 'Show DBML Editor', diff --git a/src/i18n/locales/es.ts b/src/i18n/locales/es.ts index 71dc0427..3910ef48 100644 --- a/src/i18n/locales/es.ts +++ b/src/i18n/locales/es.ts @@ -119,6 +119,8 @@ export const es: LanguageTranslation = { // TODO: Translate clear: 'Clear Filter', no_results: 'No tables found matching your filter.', + all_tables_filtered: 'All tables are filtered.', + open_filter: 'Open Filter', // TODO: Translate show_list: 'Show Table List', show_dbml: 'Show DBML Editor', diff --git a/src/i18n/locales/fr.ts b/src/i18n/locales/fr.ts index fc2d79bd..850b9d2c 100644 --- a/src/i18n/locales/fr.ts +++ b/src/i18n/locales/fr.ts @@ -118,6 +118,8 @@ export const fr: LanguageTranslation = { clear: 'Effacer le Filtre', no_results: 'Aucune table trouvée correspondant à votre filtre.', + all_tables_filtered: 'All tables are filtered.', + open_filter: 'Open Filter', show_list: 'Afficher la Liste des Tableaux', show_dbml: "Afficher l'éditeur DBML", diff --git a/src/i18n/locales/gu.ts b/src/i18n/locales/gu.ts index 8ffb8fe3..92b4cb4f 100644 --- a/src/i18n/locales/gu.ts +++ b/src/i18n/locales/gu.ts @@ -129,6 +129,8 @@ export const gu: LanguageTranslation = { // TODO: Translate clear: 'Clear Filter', no_results: 'No tables found matching your filter.', + all_tables_filtered: 'All tables are filtered.', + open_filter: 'Open Filter', // TODO: Translate show_list: 'Show Table List', show_dbml: 'Show DBML Editor', diff --git a/src/i18n/locales/hi.ts b/src/i18n/locales/hi.ts index 3b661b66..067c4a57 100644 --- a/src/i18n/locales/hi.ts +++ b/src/i18n/locales/hi.ts @@ -129,6 +129,8 @@ export const hi: LanguageTranslation = { // TODO: Translate clear: 'Clear Filter', no_results: 'No tables found matching your filter.', + all_tables_filtered: 'All tables are filtered.', + open_filter: 'Open Filter', // TODO: Translate show_list: 'Show Table List', show_dbml: 'Show DBML Editor', diff --git a/src/i18n/locales/hr.ts b/src/i18n/locales/hr.ts index 371618d9..0db52a69 100644 --- a/src/i18n/locales/hr.ts +++ b/src/i18n/locales/hr.ts @@ -126,6 +126,8 @@ export const hr: LanguageTranslation = { clear: 'Očisti filter', no_results: 'Nema pronađenih tablica koje odgovaraju vašem filteru.', + all_tables_filtered: 'All tables are filtered.', + open_filter: 'Open Filter', show_list: 'Prikaži popis tablica', show_dbml: 'Prikaži DBML uređivač', diff --git a/src/i18n/locales/id_ID.ts b/src/i18n/locales/id_ID.ts index 7eee0558..4a002620 100644 --- a/src/i18n/locales/id_ID.ts +++ b/src/i18n/locales/id_ID.ts @@ -128,6 +128,8 @@ export const id_ID: LanguageTranslation = { // TODO: Translate clear: 'Clear Filter', no_results: 'No tables found matching your filter.', + all_tables_filtered: 'All tables are filtered.', + open_filter: 'Open Filter', // TODO: Translate show_list: 'Show Table List', show_dbml: 'Show DBML Editor', diff --git a/src/i18n/locales/ja.ts b/src/i18n/locales/ja.ts index d705e54f..e81b289b 100644 --- a/src/i18n/locales/ja.ts +++ b/src/i18n/locales/ja.ts @@ -132,6 +132,8 @@ export const ja: LanguageTranslation = { // TODO: Translate clear: 'Clear Filter', no_results: 'No tables found matching your filter.', + all_tables_filtered: 'All tables are filtered.', + open_filter: 'Open Filter', // TODO: Translate show_list: 'Show Table List', show_dbml: 'Show DBML Editor', diff --git a/src/i18n/locales/ko_KR.ts b/src/i18n/locales/ko_KR.ts index c7090b2f..e6f49923 100644 --- a/src/i18n/locales/ko_KR.ts +++ b/src/i18n/locales/ko_KR.ts @@ -128,6 +128,8 @@ export const ko_KR: LanguageTranslation = { // TODO: Translate clear: 'Clear Filter', no_results: 'No tables found matching your filter.', + all_tables_filtered: 'All tables are filtered.', + open_filter: 'Open Filter', // TODO: Translate show_list: 'Show Table List', show_dbml: 'Show DBML Editor', diff --git a/src/i18n/locales/mr.ts b/src/i18n/locales/mr.ts index 77920c65..ea64f0c1 100644 --- a/src/i18n/locales/mr.ts +++ b/src/i18n/locales/mr.ts @@ -131,6 +131,8 @@ export const mr: LanguageTranslation = { // TODO: Translate clear: 'Clear Filter', no_results: 'No tables found matching your filter.', + all_tables_filtered: 'All tables are filtered.', + open_filter: 'Open Filter', // TODO: Translate show_list: 'Show Table List', show_dbml: 'Show DBML Editor', diff --git a/src/i18n/locales/ne.ts b/src/i18n/locales/ne.ts index f07d05cf..62b62cd9 100644 --- a/src/i18n/locales/ne.ts +++ b/src/i18n/locales/ne.ts @@ -130,6 +130,9 @@ export const ne: LanguageTranslation = { clear: 'Clear Filter', no_results: 'No tables found matching your filter.', // TODO: Translate + all_tables_filtered: 'All tables are filtered.', + open_filter: 'Open Filter', + // TODO: Translate show_list: 'Show Table List', show_dbml: 'Show DBML Editor', diff --git a/src/i18n/locales/pt_BR.ts b/src/i18n/locales/pt_BR.ts index c74d1f31..67ab54a6 100644 --- a/src/i18n/locales/pt_BR.ts +++ b/src/i18n/locales/pt_BR.ts @@ -129,6 +129,8 @@ export const pt_BR: LanguageTranslation = { // TODO: Translate clear: 'Clear Filter', no_results: 'No tables found matching your filter.', + all_tables_filtered: 'All tables are filtered.', + open_filter: 'Open Filter', // TODO: Translate show_list: 'Show Table List', show_dbml: 'Show DBML Editor', diff --git a/src/i18n/locales/ru.ts b/src/i18n/locales/ru.ts index a8bacc32..3e56f111 100644 --- a/src/i18n/locales/ru.ts +++ b/src/i18n/locales/ru.ts @@ -127,6 +127,8 @@ export const ru: LanguageTranslation = { no_results: 'Таблицы не найдены, соответствующие вашему фильтру.', + all_tables_filtered: 'All tables are filtered.', + open_filter: 'Open Filter', show_list: 'Переключиться на список таблиц', show_dbml: 'Переключиться на редактор DBML', diff --git a/src/i18n/locales/te.ts b/src/i18n/locales/te.ts index 1d3fa1ac..e299c4f9 100644 --- a/src/i18n/locales/te.ts +++ b/src/i18n/locales/te.ts @@ -129,6 +129,8 @@ export const te: LanguageTranslation = { // TODO: Translate clear: 'Clear Filter', no_results: 'No tables found matching your filter.', + all_tables_filtered: 'All tables are filtered.', + open_filter: 'Open Filter', // TODO: Translate show_list: 'Show Table List', show_dbml: 'Show DBML Editor', diff --git a/src/i18n/locales/tr.ts b/src/i18n/locales/tr.ts index 30d4ceee..f30b8656 100644 --- a/src/i18n/locales/tr.ts +++ b/src/i18n/locales/tr.ts @@ -128,6 +128,8 @@ export const tr: LanguageTranslation = { // TODO: Translate clear: 'Clear Filter', no_results: 'No tables found matching your filter.', + all_tables_filtered: 'All tables are filtered.', + open_filter: 'Open Filter', // TODO: Translate show_list: 'Show Table List', show_dbml: 'Show DBML Editor', diff --git a/src/i18n/locales/uk.ts b/src/i18n/locales/uk.ts index 93f0f3c7..d0245e84 100644 --- a/src/i18n/locales/uk.ts +++ b/src/i18n/locales/uk.ts @@ -127,6 +127,8 @@ export const uk: LanguageTranslation = { // TODO: Translate clear: 'Clear Filter', no_results: 'No tables found matching your filter.', + all_tables_filtered: 'All tables are filtered.', + open_filter: 'Open Filter', // TODO: Translate show_list: 'Show Table List', show_dbml: 'Show DBML Editor', diff --git a/src/i18n/locales/vi.ts b/src/i18n/locales/vi.ts index 36ecea09..da5efb8f 100644 --- a/src/i18n/locales/vi.ts +++ b/src/i18n/locales/vi.ts @@ -128,6 +128,8 @@ export const vi: LanguageTranslation = { // TODO: Translate clear: 'Clear Filter', no_results: 'No tables found matching your filter.', + all_tables_filtered: 'All tables are filtered.', + open_filter: 'Open Filter', // TODO: Translate show_list: 'Show Table List', show_dbml: 'Show DBML Editor', diff --git a/src/i18n/locales/zh_CN.ts b/src/i18n/locales/zh_CN.ts index a621557e..1e388fcd 100644 --- a/src/i18n/locales/zh_CN.ts +++ b/src/i18n/locales/zh_CN.ts @@ -125,6 +125,8 @@ export const zh_CN: LanguageTranslation = { // TODO: Translate clear: 'Clear Filter', no_results: 'No tables found matching your filter.', + all_tables_filtered: 'All tables are filtered.', + open_filter: 'Open Filter', // TODO: Translate show_list: 'Show Table List', show_dbml: 'Show DBML Editor', diff --git a/src/i18n/locales/zh_TW.ts b/src/i18n/locales/zh_TW.ts index 3d2d8d9a..10acb37b 100644 --- a/src/i18n/locales/zh_TW.ts +++ b/src/i18n/locales/zh_TW.ts @@ -125,6 +125,8 @@ export const zh_TW: LanguageTranslation = { // TODO: Translate clear: 'Clear Filter', no_results: 'No tables found matching your filter.', + all_tables_filtered: 'All tables are filtered.', + open_filter: 'Open Filter', // TODO: Translate show_list: 'Show Table List', show_dbml: 'Show DBML Editor', diff --git a/src/pages/editor-page/canvas/canvas-filter/canvas-filter.tsx b/src/pages/editor-page/canvas/canvas-filter/canvas-filter.tsx index 005d559c..be4071e2 100644 --- a/src/pages/editor-page/canvas/canvas-filter/canvas-filter.tsx +++ b/src/pages/editor-page/canvas/canvas-filter/canvas-filter.tsx @@ -93,9 +93,18 @@ export const CanvasFilter: React.FC = ({ onClose }) => { tablesBySchema.forEach((schemaTables, schemaName) => { const schemaId = schemaNameToSchemaId(schemaName); - const schemaHidden = filteredSchemas + const schemaFilteredOut = filteredSchemas ? !filteredSchemas.includes(schemaId) : false; + + // Pre-calculate if all tables in this schema are hidden + const allTablesHidden = schemaTables.every( + (table) => hiddenTableIds?.includes(table.id) ?? false + ); + + // Schema appears hidden if filtered out OR all tables are hidden + const schemaHidden = schemaFilteredOut || allTablesHidden; + const schemaNode: TreeNode = { id: `schema-${schemaName}`, name: `${schemaName} (${schemaTables.length})`, @@ -136,13 +145,24 @@ export const CanvasFilter: React.FC = ({ onClose }) => { return nodes; }, [relevantTableData, databaseType, hiddenTableIds, filteredSchemas]); - // Initialize expanded state with all schemas expanded - useMemo(() => { - const initialExpanded: Record = {}; - treeData.forEach((node) => { - initialExpanded[node.id] = true; + // Initialize expanded state - collapse if multiple schemas, expand if single schema + useEffect(() => { + setExpanded((prevExpanded) => { + const hasMultipleSchemas = treeData.length > 1; + const newExpanded: Record = {}; + + treeData.forEach((node) => { + // Preserve existing expanded state if it exists, otherwise set based on schema count + if (node.id in prevExpanded) { + newExpanded[node.id] = prevExpanded[node.id]; + } else { + // If there are multiple schemas, start collapsed; otherwise expanded + newExpanded[node.id] = !hasMultipleSchemas; + } + }); + + return newExpanded; }); - setExpanded(initialExpanded); }, [treeData]); // Filter tree data based on search query @@ -222,10 +242,19 @@ export const CanvasFilter: React.FC = ({ onClose }) => { if (node.type === 'schema') { const schemaContext = node.context as SchemaContext; const schemaId = schemaNameToSchemaId(schemaContext.name); - const schemaHidden = filteredSchemas + const schemaFilteredOut = filteredSchemas ? !filteredSchemas.includes(schemaId) : false; + // Check if all tables in this schema are hidden + const allTablesHidden = + node.children?.every((child) => + hiddenTableIds?.includes(child.id) + ) ?? false; + + // Schema is "hidden" if filtered out OR all tables are hidden + const schemaHidden = schemaFilteredOut || allTablesHidden; + return (