save perspective to file

This commit is contained in:
Jan Prochazka 2022-08-06 17:43:49 +02:00
parent cc019281d4
commit 563a35560b
7 changed files with 101 additions and 48 deletions

View File

@ -1,4 +1,4 @@
import { DatabaseInfo, ForeignKeyInfo } from 'dbgate-types'; import { DatabaseInfo, ForeignKeyInfo, NamedObjectInfo } from 'dbgate-types';
export interface PerspectiveConfigColumns { export interface PerspectiveConfigColumns {
expandedColumns: string[]; expandedColumns: string[];
@ -28,6 +28,7 @@ export interface PerspectiveFilterColumnInfo {
foreignKey: ForeignKeyInfo; foreignKey: ForeignKeyInfo;
} }
export interface PerspectiveConfig extends PerspectiveConfigColumns { export interface PerspectiveConfig extends PerspectiveConfigColumns {
rootObject: { schemaName?: string; pureName: string };
filters: { [uniqueName: string]: string }; filters: { [uniqueName: string]: string };
filterInfos: { [uniqueName: string]: PerspectiveFilterColumnInfo }; filterInfos: { [uniqueName: string]: PerspectiveFilterColumnInfo };
sort: { sort: {
@ -39,7 +40,7 @@ export interface PerspectiveConfig extends PerspectiveConfigColumns {
customJoins: PerspectiveCustomJoinConfig[]; customJoins: PerspectiveCustomJoinConfig[];
} }
export function createPerspectiveConfig(): PerspectiveConfig { export function createPerspectiveConfig(rootObject: { schemaName?: string; pureName: string }): PerspectiveConfig {
return { return {
expandedColumns: [], expandedColumns: [],
checkedColumns: [], checkedColumns: [],
@ -48,6 +49,7 @@ export function createPerspectiveConfig(): PerspectiveConfig {
filters: {}, filters: {},
filterInfos: {}, filterInfos: {},
sort: {}, sort: {},
rootObject,
}; };
} }

View File

@ -12,7 +12,7 @@ test('test flat view', () => {
const root = new PerspectiveTableNode( const root = new PerspectiveTableNode(
artistTable, artistTable,
{ conid: { db: chinookDbInfo } }, { conid: { db: chinookDbInfo } },
createPerspectiveConfig(), createPerspectiveConfig({ pureName: 'Artist' }),
null, null,
null, null,
{ conid: 'conid', database: 'db' }, { conid: 'conid', database: 'db' },
@ -38,7 +38,7 @@ test('test one level nesting', () => {
const root = new PerspectiveTableNode( const root = new PerspectiveTableNode(
artistTable, artistTable,
{ conid: { db: chinookDbInfo } }, { conid: { db: chinookDbInfo } },
{ ...createPerspectiveConfig(), checkedColumns: ['Artist.Album'] }, { ...createPerspectiveConfig({ pureName: 'Artist' }), checkedColumns: ['Artist.Album'] },
null, null,
null, null,
{ conid: 'conid', database: 'db' }, { conid: 'conid', database: 'db' },
@ -88,7 +88,7 @@ test('test two level nesting', () => {
const root = new PerspectiveTableNode( const root = new PerspectiveTableNode(
artistTable, artistTable,
{ conid: { db: chinookDbInfo } }, { conid: { db: chinookDbInfo } },
{ ...createPerspectiveConfig(), checkedColumns: ['Artist.Album', 'Artist.Album.Track'] }, { ...createPerspectiveConfig({ pureName: 'Artist' }), checkedColumns: ['Artist.Album', 'Artist.Album.Track'] },
null, null,
null, null,
{ conid: 'conid', database: 'db' }, { conid: 'conid', database: 'db' },

View File

@ -65,6 +65,14 @@
currentConnection: true, currentConnection: true,
}; };
const perspectives: FileTypeHandler = {
icon: 'img perspective',
format: 'json',
tabComponent: 'PerspectiveTab',
folder: 'pesrpectives',
currentConnection: true,
};
export const SAVED_FILE_HANDLERS = { export const SAVED_FILE_HANDLERS = {
sql, sql,
shell, shell,
@ -73,10 +81,14 @@
query, query,
sqlite, sqlite,
diagrams, diagrams,
perspectives,
}; };
export const extractKey = data => data.file; export const extractKey = data => data.file;
export const createMatcher = ({ file }) => filter => filterName(filter, file); export const createMatcher =
({ file }) =>
filter =>
filterName(filter, file);
</script> </script>
<script lang="ts"> <script lang="ts">

View File

@ -60,8 +60,6 @@
export let conid; export let conid;
export let database; export let database;
export let schemaName;
export let pureName;
export let driver; export let driver;
export let config: PerspectiveConfig; export let config: PerspectiveConfig;
@ -96,9 +94,9 @@
}); });
} }
const dbInfos = useMultipleDatabaseInfo(extractPerspectiveDatabases({ conid, database }, config)); $: dbInfos = useMultipleDatabaseInfo(extractPerspectiveDatabases({ conid, database }, config));
const tableInfo = useTableInfo({ conid, database, schemaName, pureName }); $: tableInfo = useTableInfo({ conid, database, ...config?.rootObject });
const viewInfo = useViewInfo({ conid, database, schemaName, pureName }); $: viewInfo = useViewInfo({ conid, database, ...config?.rootObject });
$: dataProvider = new PerspectiveDataProvider(cache, loader); $: dataProvider = new PerspectiveDataProvider(cache, loader);
$: loader = new PerspectiveDataLoader(apiCall); $: loader = new PerspectiveDataLoader(apiCall);
@ -114,8 +112,6 @@
null null
) )
: null; : null;
// $: console.log('CONFIG', config);
</script> </script>
<HorizontalSplitter initialValue={getInitialManagerSize()} bind:size={managerSize}> <HorizontalSplitter initialValue={getInitialManagerSize()} bind:size={managerSize}>

View File

@ -13,14 +13,24 @@
onClick: () => getCurrentEditor().refresh(), onClick: () => getCurrentEditor().refresh(),
}); });
registerFileCommands({
idPrefix: 'perspective',
category: 'Perspective',
getCurrentEditor,
folder: 'perspectives',
format: 'json',
fileExtension: 'perspective',
undoRedo: true,
});
export const allowAddToFavorites = props => true; export const allowAddToFavorites = props => true;
</script> </script>
<script lang="ts"> <script lang="ts">
import { PerspectiveCache } from 'dbgate-datalib'; import { createPerspectiveConfig, PerspectiveCache } from 'dbgate-datalib';
import PerspectiveView from '../perspectives/PerspectiveView.svelte'; import PerspectiveView from '../perspectives/PerspectiveView.svelte';
import usePerspectiveConfig from '../utility/usePerspectiveConfig';
import { writable } from 'svelte/store'; import { writable } from 'svelte/store';
import registerCommand from '../commands/registerCommand'; import registerCommand from '../commands/registerCommand';
import createActivator, { getActiveComponent } from '../utility/createActivator'; import createActivator, { getActiveComponent } from '../utility/createActivator';
@ -29,6 +39,12 @@
import { findEngineDriver } from 'dbgate-tools'; import { findEngineDriver } from 'dbgate-tools';
import { useConnectionInfo } from '../utility/metadataLoaders'; import { useConnectionInfo } from '../utility/metadataLoaders';
import { extensions } from '../stores'; import { extensions } from '../stores';
import invalidateCommands from '../commands/invalidateCommands';
import useEditorData from '../query/useEditorData';
import createUndoReducer from '../utility/createUndoReducer';
import { registerFileCommands } from '../commands/stdCommands';
import _ from 'lodash';
import ToolStripSaveButton from '../buttons/ToolStripSaveButton.svelte';
export let tabid; export let tabid;
export let conid; export let conid;
@ -41,7 +57,49 @@
$: connection = useConnectionInfo({ conid }); $: connection = useConnectionInfo({ conid });
$: driver = findEngineDriver($connection, $extensions); $: driver = findEngineDriver($connection, $extensions);
const config = usePerspectiveConfig(tabid); $: setEditorData($modelState.value);
export function getTabId() {
return tabid;
}
export function getData() {
return $editorState.value || '';
}
export function canUndo() {
return $modelState.canUndo;
}
export function undo() {
dispatchModel({ type: 'undo' });
invalidateCommands();
}
export function canRedo() {
return $modelState.canRedo;
}
export function redo() {
dispatchModel({ type: 'redo' });
invalidateCommands();
}
const { editorState, editorValue, setEditorData } = useEditorData({
tabid,
onInitialData: value => {
dispatchModel({ type: 'reset', value });
invalidateCommands();
},
});
const [modelState, dispatchModel] = createUndoReducer(
createPerspectiveConfig({
schemaName,
pureName,
})
);
const cache = new PerspectiveCache(); const cache = new PerspectiveCache();
const loadedCounts = writable({}); const loadedCounts = writable({});
@ -55,15 +113,20 @@
<PerspectiveView <PerspectiveView
{conid} {conid}
{database} {database}
{schemaName}
{pureName}
{driver} {driver}
config={$config} config={$modelState.value}
setConfig={(value, reload) => { setConfig={(value, reload) => {
if (reload) { if (reload) {
cache.clear(); cache.clear();
} }
config.update(value); dispatchModel({
type: 'compute',
// useMerge: skipUndoChain,
compute: v => (_.isFunction(value) ? value(v) : value),
});
invalidateCommands();
// config.update(value);
// loadedCounts.set({}); // loadedCounts.set({});
}} }}
{cache} {cache}
@ -73,5 +136,8 @@
<svelte:fragment slot="toolstrip"> <svelte:fragment slot="toolstrip">
<ToolStripCommandButton command="perspective.refresh" /> <ToolStripCommandButton command="perspective.refresh" />
<ToolStripCommandButton command="perspective.customJoin" /> <ToolStripCommandButton command="perspective.customJoin" />
<ToolStripSaveButton idPrefix="perspective" />
<ToolStripCommandButton command="perspective.undo" />
<ToolStripCommandButton command="perspective.redo" />
</svelte:fragment> </svelte:fragment>
</ToolStripContainer> </ToolStripContainer>

View File

@ -1,27 +0,0 @@
import { createPerspectiveConfig } from 'dbgate-datalib';
import { writable } from 'svelte/store';
import { onDestroy } from 'svelte';
function doLoadPerspectiveConfigFunc(tabid) {
try {
const existing = localStorage.getItem(`tabdata_perspective_${tabid}`);
if (existing) {
return {
...createPerspectiveConfig(),
...JSON.parse(existing),
};
}
} catch (err) {
console.warn('Error loading perspective config:', err.message);
}
return createPerspectiveConfig();
}
export default function usePerspectiveConfig(tabid) {
const config = writable(doLoadPerspectiveConfigFunc(tabid));
const unsubscribe = config.subscribe(value =>
localStorage.setItem(`tabdata_perspective_${tabid}`, JSON.stringify(value))
);
onDestroy(unsubscribe);
return config;
}

View File

@ -20,6 +20,7 @@
const queryFiles = useFiles({ folder: 'query' }); const queryFiles = useFiles({ folder: 'query' });
const sqliteFiles = useFiles({ folder: 'sqlite' }); const sqliteFiles = useFiles({ folder: 'sqlite' });
const diagramFiles = useFiles({ folder: 'diagrams' }); const diagramFiles = useFiles({ folder: 'diagrams' });
const perspectiveFiles = useFiles({ folder: 'perspectives' });
$: files = [ $: files = [
...($sqlFiles || []), ...($sqlFiles || []),
@ -29,10 +30,13 @@
...($queryFiles || []), ...($queryFiles || []),
...($sqliteFiles || []), ...($sqliteFiles || []),
...($diagramFiles || []), ...($diagramFiles || []),
...($perspectiveFiles || []),
]; ];
function handleRefreshFiles() { function handleRefreshFiles() {
apiCall('files/refresh', { folders: ['sql', 'shell', 'markdown', 'charts', 'query', 'sqlite', 'diagrams'] }); apiCall('files/refresh', {
folders: ['sql', 'shell', 'markdown', 'charts', 'query', 'sqlite', 'diagrams', 'perspectives'],
});
} }
</script> </script>