diff --git a/packages/web/src/appobj/SavedFileAppObject.js b/packages/web/src/appobj/SavedFileAppObject.js index f2b4a39ae..23baaec71 100644 --- a/packages/web/src/appobj/SavedFileAppObject.js +++ b/packages/web/src/appobj/SavedFileAppObject.js @@ -109,6 +109,8 @@ export function SavedSqlFileAppObject({ data, commonProps }) { newQuery({ title: file, initialData: data, + // @ts-ignore + savedFile: file, }); }} /> @@ -131,6 +133,9 @@ export function SavedShellFileAppObject({ data, commonProps }) { title: file, icon: 'img shell', tabComponent: 'ShellTab', + props: { + savedFile: file, + }, }, data ); @@ -165,6 +170,7 @@ export function SavedChartFileAppObject({ data, commonProps }) { props: { conid: connection._id, database, + savedFile: file, }, tabComponent: 'ChartTab', }, @@ -201,6 +207,9 @@ export function SavedMarkdownFileAppObject({ data, commonProps }) { title: file, icon: 'img markdown', tabComponent: 'MarkdownEditorTab', + props: { + savedFile: file, + }, }, data ); diff --git a/packages/web/src/modals/SaveTabModal.js b/packages/web/src/modals/SaveTabModal.js index 50e29c1c3..0a9f55e85 100644 --- a/packages/web/src/modals/SaveTabModal.js +++ b/packages/web/src/modals/SaveTabModal.js @@ -8,8 +8,13 @@ export default function SaveTabModal({ data, folder, format, modalState, tabid, const setOpenedTabs = useSetOpenedTabs(); const openedTabs = useOpenedTabs(); - const name = openedTabs.find((x) => x.tabid == tabid).title; - const onSave = (name) => changeTab(tabid, setOpenedTabs, (tab) => ({ ...tab, title: name })); + const { savedFile } = openedTabs.find((x) => x.tabid == tabid).props || {}; + const onSave = (name) => + changeTab(tabid, setOpenedTabs, (tab) => ({ + ...tab, + title: name, + props: { ...tab.props, savedFile: name }, + })); const handleKeyboard = React.useCallback( (e) => { @@ -31,6 +36,13 @@ export default function SaveTabModal({ data, folder, format, modalState, tabid, }, [tabVisible, handleKeyboard]); return ( - + ); } diff --git a/packages/web/src/tabs/ArchiveFileTab.js b/packages/web/src/tabs/ArchiveFileTab.js index 0328d1063..ebde08373 100644 --- a/packages/web/src/tabs/ArchiveFileTab.js +++ b/packages/web/src/tabs/ArchiveFileTab.js @@ -4,3 +4,5 @@ import JslDataGrid from '../sqleditor/JslDataGrid'; export default function ArchiveFileTab({ archiveFolder, archiveFile, tabVisible, toolbarPortalRef, tabid }) { return ; } + +ArchiveFileTab.matchingProps = ['archiveFile', 'archiveFolder']; diff --git a/packages/web/src/tabs/TableDataTab.js b/packages/web/src/tabs/TableDataTab.js index b295f95db..cd67a3a33 100644 --- a/packages/web/src/tabs/TableDataTab.js +++ b/packages/web/src/tabs/TableDataTab.js @@ -26,3 +26,5 @@ export default function TableDataTab({ conid, database, schemaName, pureName, ta /> ); } + +TableDataTab.matchingProps = ['conid', 'database', 'schemaName', 'pureName']; diff --git a/packages/web/src/tabs/ViewDataTab.js b/packages/web/src/tabs/ViewDataTab.js index c3787fed3..949e65d0a 100644 --- a/packages/web/src/tabs/ViewDataTab.js +++ b/packages/web/src/tabs/ViewDataTab.js @@ -54,3 +54,5 @@ export default function ViewDataTab({ conid, database, schemaName, pureName, tab /> ); } + +ViewDataTab.matchingProps = ['conid', 'database', 'schemaName', 'pureName']; \ No newline at end of file diff --git a/packages/web/src/utility/useOpenNewTab.js b/packages/web/src/utility/useOpenNewTab.js index f1aec4754..24d33f5e5 100644 --- a/packages/web/src/utility/useOpenNewTab.js +++ b/packages/web/src/utility/useOpenNewTab.js @@ -1,13 +1,49 @@ import uuidv1 from 'uuid/v1'; import React from 'react'; import localforage from 'localforage'; -import { useSetOpenedTabs } from './globalState'; +import stableStringify from 'json-stable-stringify'; +import _ from 'lodash'; +import { useOpenedTabs, useSetOpenedTabs } from './globalState'; +import tabs from '../tabs'; export default function useOpenNewTab() { const setOpenedTabs = useSetOpenedTabs(); + const openedTabs = useOpenedTabs(); const openNewTab = React.useCallback( async (newTab, initialData = undefined) => { + let existing = null; + + const { savedFile } = newTab.props || {}; + if (savedFile) { + existing = openedTabs.find( + (x) => + x.props && x.tabComponent == newTab.tabComponent && x.closedTime == null && x.props.savedFile == savedFile + ); + } + + const component = tabs[newTab.tabComponent]; + if (!existing && component && component.matchingProps) { + const testString = stableStringify(_.pick(newTab.props || {}, component.matchingProps)); + existing = openedTabs.find( + (x) => + x.props && + x.tabComponent == newTab.tabComponent && + x.closedTime == null && + stableStringify(_.pick(x.props || {}, component.matchingProps)) == testString + ); + } + + if (existing) { + setOpenedTabs((tabs) => + tabs.map((x) => ({ + ...x, + selected: x.tabid == existing.tabid, + })) + ); + return; + } + const tabid = uuidv1(); if (initialData) { await localforage.setItem(`tabdata_${tabid}`, initialData);