SYNC: widget configuration saved to storage

This commit is contained in:
SPRINX0\prochazka
2025-12-10 15:57:39 +01:00
committed by Diflow
parent b12c79462e
commit 149611041e
12 changed files with 81 additions and 53 deletions

View File

@@ -141,11 +141,10 @@
/>
</svelte:fragment>
<svelte:fragment slot="2">
<WidgetColumnBar>
<WidgetColumnBar storageName="diagramSettingsWidget">
<WidgetColumnBarItem
title="Settings"
name="diagramSettings"
storageName="diagramSettingsWidget"
onClose={() => {
styleStore.update(x => ({ ...x, settingsVisible: false }));
}}

View File

@@ -1,6 +1,7 @@
const cache = {};
export function getLocalStorage(key, defaultValue = undefined) {
if (!key) return defaultValue;
if (key in cache) return cache[key];
const item = localStorage.getItem(key);
if (item) {
@@ -16,11 +17,13 @@ export function getLocalStorage(key, defaultValue = undefined) {
}
export function setLocalStorage(key, value) {
if (!key) return;
localStorage.setItem(key, JSON.stringify(value));
delete cache[key];
}
export function removeLocalStorage(key) {
if (!key) return;
localStorage.removeItem(key);
delete cache[key];
}

View File

@@ -7,11 +7,11 @@
import WidgetColumnBarItem from './WidgetColumnBarItem.svelte';
</script>
<WidgetColumnBar>
<WidgetColumnBarItem title="Archive folders, DB models" name="folders" height="50%" storageName='archiveFoldersWidget'>
<WidgetColumnBar storageName="archiveWidget">
<WidgetColumnBarItem title="Archive folders, DB models" name="folders" height="50%">
<ArchiveFolderList />
</WidgetColumnBarItem>
<WidgetColumnBarItem title="Files, Tables, Views, Functions" name="files" storageName='archiveFilesWidget'>
<WidgetColumnBarItem title="Files, Tables, Views, Functions" name="files">
<ArchiveFilesList />
</WidgetColumnBarItem>
</WidgetColumnBar>

View File

@@ -17,14 +17,9 @@
$: cloudContentList = useCloudContentList();
</script>
<WidgetColumnBar {hidden}>
<WidgetColumnBar {hidden} storageName="databaseWidget">
{#if $config?.singleConnection}
<WidgetColumnBarItem
title={_t('widget.databases', { defaultMessage: 'Databases' })}
name="databases"
height="35%"
storageName="databasesWidget"
>
<WidgetColumnBarItem title={_t('widget.databases', { defaultMessage: 'Databases' })} name="databases" height="35%">
<SingleConnectionDatabaseList connection={$config?.singleConnection} />
</WidgetColumnBarItem>
{:else if !$config?.singleDbConnection}
@@ -32,7 +27,6 @@
title={_t('common.connections', { defaultMessage: 'Connections' })}
name="connections"
height="35%"
storageName="connectionsWidget"
>
<ConnectionList
passProps={{

View File

@@ -34,7 +34,6 @@
title={_t('widget.pinned', { defaultMessage: 'Pinned' })}
name="pinned"
height="15%"
storageName="pinnedItemsWidget"
skip={!_.compact($pinnedDatabases).length &&
!$pinnedTables.some(x => x && x.conid == conid && x.database == $currentDatabase?.name)}
positiveCondition={correctCloudStatus}
@@ -47,7 +46,6 @@
? _t('widget.collectionsContainers', { defaultMessage: 'Collections/containers' })
: _t('widget.tablesViewsFunctions', { defaultMessage: 'Tables, views, functions' })}
name="dbObjectsSql"
storageName="dbObjectsWidget"
skip={!(
conid &&
(database || singleDatabase) &&
@@ -61,7 +59,6 @@
<WidgetColumnBarItem
title={_t('widget.keys', { defaultMessage: 'Keys' })}
name="dbObjectsKeyValue"
storageName="dbObjectsWidget"
skip={!(conid && (database || singleDatabase) && driver?.databaseEngineTypes?.includes('keyvalue'))}
positiveCondition={correctCloudStatus}
>
@@ -71,7 +68,6 @@
<WidgetColumnBarItem
title={_t('widget.databaseContent', { defaultMessage: 'Database content' })}
name="dbObjectsFocused"
storageName="dbObjectsWidget"
skip={conid && (database || singleDatabase)}
positiveCondition={correctCloudStatus}
>
@@ -85,7 +81,6 @@
<WidgetColumnBarItem
title={_t('widget.databaseContent', { defaultMessage: 'Database content' })}
name="dbObjectsError"
storageName="dbObjectsWidget"
skip={!(conid && (database || singleDatabase) && !driver)}
positiveCondition={correctCloudStatus}
>
@@ -102,7 +97,6 @@
title={_t('widget.databaseContent', { defaultMessage: 'Database content' })}
name="incorrectClaudStatus"
height="15%"
storageName="incorrectClaudStatusWidget"
skip={correctCloudStatus}
>
<WidgetsInnerContainer>

View File

@@ -18,13 +18,13 @@
$: favorites = useFavorites();
</script>
<WidgetColumnBar>
<WidgetColumnBarItem title={_t('files.savedFiles', { defaultMessage: "Saved files" })} name="files" height="70%" storageName="savedFilesWidget">
<WidgetColumnBar storageName="filesWidget">
<WidgetColumnBarItem title={_t('files.savedFiles', { defaultMessage: 'Saved files' })} name="files" height="70%">
<SavedFilesList />
</WidgetColumnBarItem>
{#if hasPermission('files/favorites/read')}
<WidgetColumnBarItem title={_t('files.favorites', { defaultMessage: "Favorites" })} name="favorites" storageName="favoritesWidget">
<WidgetColumnBarItem title={_t('files.favorites', { defaultMessage: 'Favorites' })} name="favorites">
<WidgetsInnerContainer>
<AppObjectList list={$favorites || []} module={favoriteFileAppObject} />
</WidgetsInnerContainer>

View File

@@ -16,11 +16,13 @@
import { _t } from '../translations';
$: favorites = useFavorites();
</script>
<WidgetColumnBar>
<WidgetColumnBarItem title={_t('history.recentlyClosedTabs', { defaultMessage: "Recently closed tabs" })} name="closedTabs" storageName='closedTabsWidget'>
<WidgetColumnBar storageName="historyWidget">
<WidgetColumnBarItem
title={_t('history.recentlyClosedTabs', { defaultMessage: 'Recently closed tabs' })}
name="closedTabs"
>
<WidgetsInnerContainer>
<AppObjectList
list={_.sortBy(
@@ -31,7 +33,7 @@
/>
</WidgetsInnerContainer>
</WidgetColumnBarItem>
<WidgetColumnBarItem title={_t('history.queryHistory', { defaultMessage: "Query history" })} name="queryHistory" storageName='queryHistoryWidget'>
<WidgetColumnBarItem title={_t('history.queryHistory', { defaultMessage: 'Query history' })} name="queryHistory">
<QueryHistoryList />
</WidgetColumnBarItem>
</WidgetColumnBar>

View File

@@ -8,11 +8,15 @@
import { _t } from '../translations';
</script>
<WidgetColumnBar>
<WidgetColumnBarItem title={_t('widgets.installedExtensions', { defaultMessage: 'Installed extensions' })} name="installed" height="50%" storageName='installedPluginsWidget'>
<WidgetColumnBar storageName="pluginsWidget">
<WidgetColumnBarItem
title={_t('widgets.installedExtensions', { defaultMessage: 'Installed extensions' })}
name="installed"
height="50%"
>
<InstalledPluginsList />
</WidgetColumnBarItem>
<WidgetColumnBarItem title={_t('widgets.availableExtensions', { defaultMessage: 'Available extensions' })} name="all" storageName='allPluginsWidget'>
<WidgetColumnBarItem title={_t('widgets.availableExtensions', { defaultMessage: 'Available extensions' })} name="all">
<AvailablePluginsList />
</WidgetColumnBarItem>
</WidgetColumnBar>

View File

@@ -162,7 +162,9 @@
text: _t('privateCloudWidget.addExistingFolder', { defaultMessage: 'Add existing folder (from link)' }),
onClick: () => {
showModal(InputTextModal, {
label: _t('privateCloudWidget.yourInviteLink', { defaultMessage: 'Your invite link (in form dbgate://folder/xxx)' }),
label: _t('privateCloudWidget.yourInviteLink', {
defaultMessage: 'Your invite link (in form dbgate://folder/xxx)',
}),
header: _t('privateCloudWidget.addExistingSharedFolder', { defaultMessage: 'Add existing shared folder' }),
onConfirm: async newFolder => {
apiCall('cloud/grant-folder', {
@@ -192,7 +194,10 @@
const handleDelete = () => {
showModal(ConfirmModal, {
message: _t('privateCloudWidget.deleteFolderConfirm', { defaultMessage: 'Really delete folder {folder}? All folder content will be deleted!', values: { folder: contentGroupMap[folder]?.name } }),
message: _t('privateCloudWidget.deleteFolderConfirm', {
defaultMessage: 'Really delete folder {folder}? All folder content will be deleted!',
values: { folder: contentGroupMap[folder]?.name },
}),
header: _t('privateCloudWidget.deleteFolder', { defaultMessage: 'Delete folder' }),
onConfirm: () => {
apiCall('cloud/delete-folder', {
@@ -240,19 +245,26 @@
}
</script>
<WidgetColumnBar>
<WidgetColumnBarItem
title="DbGate Cloud"
name="privateCloud"
height="50%"
storageName="privateCloudItems"
skip={!$cloudSigninTokenHolder}
>
<WidgetColumnBar storageName="privateCloudItems">
<WidgetColumnBarItem title="DbGate Cloud" name="privateCloud" height="50%" skip={!$cloudSigninTokenHolder}>
<SearchBoxWrapper>
<SearchInput placeholder={_t('privateCloudWidget.searchPlaceholder', { defaultMessage: 'Search cloud connections and files' })} bind:value={filter} />
<SearchInput
placeholder={_t('privateCloudWidget.searchPlaceholder', {
defaultMessage: 'Search cloud connections and files',
})}
bind:value={filter}
/>
<CloseSearchButton bind:filter />
<DropDownButton icon="icon plus-thick" menu={createAddItemMenu} title={_t('privateCloudWidget.addNewConnectionOrFile', { defaultMessage: 'Add new connection or file' })} />
<DropDownButton icon="icon add-folder" menu={createAddFolderMenu} title={_t('privateCloudWidget.addNewFolder', { defaultMessage: 'Add new folder' })} />
<DropDownButton
icon="icon plus-thick"
menu={createAddItemMenu}
title={_t('privateCloudWidget.addNewConnectionOrFile', { defaultMessage: 'Add new connection or file' })}
/>
<DropDownButton
icon="icon add-folder"
menu={createAddFolderMenu}
title={_t('privateCloudWidget.addNewFolder', { defaultMessage: 'Add new folder' })}
/>
<InlineButton
on:click={handleRefreshContent}
title={_t('privateCloudWidget.refreshFiles', { defaultMessage: 'Refresh files' })}
@@ -289,7 +301,10 @@
/>
{#if !cloudContentFlat?.length}
<ErrorInfo message={_t('privateCloudWidget.noContent', { defaultMessage: 'You have no content on DbGate cloud' })} icon="img info" />
<ErrorInfo
message={_t('privateCloudWidget.noContent', { defaultMessage: 'You have no content on DbGate cloud' })}
icon="img info"
/>
<div class="error-info">
<div class="m-1"></div>
<FormStyledButton

View File

@@ -26,15 +26,21 @@
}
</script>
<WidgetColumnBar>
<WidgetColumnBarItem title={_t('publicCloudWidget.publicKnowledgeBase', { defaultMessage: "Public Knowledge Base" })} name="publicCloud" storageName="publicCloudItems">
<WidgetColumnBar storageName="publicCloudItems">
<WidgetColumnBarItem
title={_t('publicCloudWidget.publicKnowledgeBase', { defaultMessage: 'Public Knowledge Base' })}
name="publicCloud"
>
<WidgetsInnerContainer>
<SearchBoxWrapper>
<SearchInput placeholder={_t('publicCloudWidget.searchPublicFiles', { defaultMessage: "Search public files" })} bind:value={filter} />
<SearchInput
placeholder={_t('publicCloudWidget.searchPublicFiles', { defaultMessage: 'Search public files' })}
bind:value={filter}
/>
<CloseSearchButton bind:filter />
<InlineButton
on:click={handleRefreshPublic}
title={_t('publicCloudWidget.refreshFiles', { defaultMessage: "Refresh files" })}
title={_t('publicCloudWidget.refreshFiles', { defaultMessage: 'Refresh files' })}
data-testid="CloudItemsWidget_buttonRefreshPublic"
>
<FontIcon icon="icon refresh" />
@@ -49,12 +55,21 @@
/>
{#if !$publicFiles?.length}
<ErrorInfo message={_t('publicCloudWidget.noFilesFound', { defaultMessage: "No files found for your configuration" })} />
<ErrorInfo
message={_t('publicCloudWidget.noFilesFound', { defaultMessage: 'No files found for your configuration' })}
/>
<div class="error-info">
<div class="m-1">
{_t('publicCloudWidget.onlyRelevantFilesListed', { defaultMessage: "Only files relevant for your connections, platform and DbGate edition are listed. Please define connections at first." })}
{_t('publicCloudWidget.onlyRelevantFilesListed', {
defaultMessage:
'Only files relevant for your connections, platform and DbGate edition are listed. Please define connections at first.',
})}
</div>
<FormStyledButton value={_t('publicCloudWidget.refreshList', { defaultMessage: "Refresh list" })} skipWidth on:click={handleRefreshPublic} />
<FormStyledButton
value={_t('publicCloudWidget.refreshList', { defaultMessage: 'Refresh list' })}
skipWidth
on:click={handleRefreshPublic}
/>
</div>
{/if}
</WidgetsInnerContainer>

View File

@@ -2,6 +2,7 @@
import { onMount, setContext } from 'svelte';
import { writable } from 'svelte/store';
import _ from 'lodash';
import { getLocalStorage, setLocalStorage } from '../utility/storageCache';
export let hidden = false;
export let storageName = null;
@@ -12,7 +13,10 @@
// const widgetColumnBarHeight = writable(0);
const widgetColumnBarComputed = writable({});
let deltaHeights = {};
const fromStorage = getLocalStorage(storageName);
let deltaHeights = fromStorage?.deltaHeights || {};
$: setLocalStorage(storageName, { deltaHeights });
// setContext('widgetColumnBarHeight', widgetColumnBarHeight);
setContext('pushWidgetItemDefinition', (name, item) => {

View File

@@ -3,8 +3,6 @@
import { getContext } from 'svelte';
import { writable } from 'svelte/store';
import WidgetTitle from './WidgetTitle.svelte';
import splitterDrag from '../utility/splitterDrag';
import { getLocalStorage, setLocalStorage } from '../utility/storageCache';