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 {
expandedColumns: string[];
@ -28,6 +28,7 @@ export interface PerspectiveFilterColumnInfo {
foreignKey: ForeignKeyInfo;
}
export interface PerspectiveConfig extends PerspectiveConfigColumns {
rootObject: { schemaName?: string; pureName: string };
filters: { [uniqueName: string]: string };
filterInfos: { [uniqueName: string]: PerspectiveFilterColumnInfo };
sort: {
@ -39,7 +40,7 @@ export interface PerspectiveConfig extends PerspectiveConfigColumns {
customJoins: PerspectiveCustomJoinConfig[];
}
export function createPerspectiveConfig(): PerspectiveConfig {
export function createPerspectiveConfig(rootObject: { schemaName?: string; pureName: string }): PerspectiveConfig {
return {
expandedColumns: [],
checkedColumns: [],
@ -48,6 +49,7 @@ export function createPerspectiveConfig(): PerspectiveConfig {
filters: {},
filterInfos: {},
sort: {},
rootObject,
};
}

View File

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

View File

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

View File

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

View File

@ -13,14 +13,24 @@
onClick: () => getCurrentEditor().refresh(),
});
registerFileCommands({
idPrefix: 'perspective',
category: 'Perspective',
getCurrentEditor,
folder: 'perspectives',
format: 'json',
fileExtension: 'perspective',
undoRedo: true,
});
export const allowAddToFavorites = props => true;
</script>
<script lang="ts">
import { PerspectiveCache } from 'dbgate-datalib';
import { createPerspectiveConfig, PerspectiveCache } from 'dbgate-datalib';
import PerspectiveView from '../perspectives/PerspectiveView.svelte';
import usePerspectiveConfig from '../utility/usePerspectiveConfig';
import { writable } from 'svelte/store';
import registerCommand from '../commands/registerCommand';
import createActivator, { getActiveComponent } from '../utility/createActivator';
@ -29,6 +39,12 @@
import { findEngineDriver } from 'dbgate-tools';
import { useConnectionInfo } from '../utility/metadataLoaders';
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 conid;
@ -41,7 +57,49 @@
$: connection = useConnectionInfo({ conid });
$: 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 loadedCounts = writable({});
@ -55,15 +113,20 @@
<PerspectiveView
{conid}
{database}
{schemaName}
{pureName}
{driver}
config={$config}
config={$modelState.value}
setConfig={(value, reload) => {
if (reload) {
cache.clear();
}
config.update(value);
dispatchModel({
type: 'compute',
// useMerge: skipUndoChain,
compute: v => (_.isFunction(value) ? value(v) : value),
});
invalidateCommands();
// config.update(value);
// loadedCounts.set({});
}}
{cache}
@ -73,5 +136,8 @@
<svelte:fragment slot="toolstrip">
<ToolStripCommandButton command="perspective.refresh" />
<ToolStripCommandButton command="perspective.customJoin" />
<ToolStripSaveButton idPrefix="perspective" />
<ToolStripCommandButton command="perspective.undo" />
<ToolStripCommandButton command="perspective.redo" />
</svelte:fragment>
</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 sqliteFiles = useFiles({ folder: 'sqlite' });
const diagramFiles = useFiles({ folder: 'diagrams' });
const perspectiveFiles = useFiles({ folder: 'perspectives' });
$: files = [
...($sqlFiles || []),
@ -29,10 +30,13 @@
...($queryFiles || []),
...($sqliteFiles || []),
...($diagramFiles || []),
...($perspectiveFiles || []),
];
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>