diff --git a/packages/api/src/controllers/apps.js b/packages/api/src/controllers/apps.js index cc92f8836..80ee2e653 100644 --- a/packages/api/src/controllers/apps.js +++ b/packages/api/src/controllers/apps.js @@ -18,9 +18,10 @@ module.exports = { createFolder_meta: true, async createFolder({ folder }) { - await fs.mkdir(path.join(appdir(), folder)); + const name = await this.getNewAppFolder({ name: folder }); + await fs.mkdir(path.join(appdir(), name)); socket.emitChanged('app-folders-changed'); - return true; + return name; }, files_meta: true, @@ -45,7 +46,7 @@ module.exports = { .map(name => ({ name: 'virtual-references.json', label: 'virtual-references.json', - type: 'vfk', + type: 'vfk.json', })); } @@ -186,4 +187,46 @@ module.exports = { return res; }, + + saveVfk_meta: true, + async saveVfk({ appFolder, schemaName, pureName, refSchemaName, refTableName, columns }) { + const file = path.join(appdir(), appFolder, 'virtual-references.json'); + + let json; + try { + json = JSON.parse(await fs.readFile(file, { encoding: 'utf-8' })); + } catch (err) { + json = []; + } + + if (columns.length == 1) { + json = json.filter( + x => + !( + x.schemaName == schemaName && + x.pureName == pureName && + x.columns.length == 1 && + x.columns[0].columnName == columns[0].columnName + ) + ); + } + + json = [ + ...json, + { + schemaName, + pureName, + refSchemaName, + refTableName, + columns, + }, + ]; + + await fs.writeFile(file, JSON.stringify(json, undefined, 2)); + + socket.emitChanged(`app-files-changed-${appFolder}`); + socket.emitChanged('used-apps-changed'); + + return true; + }, }; diff --git a/packages/web/src/appobj/AppFileAppObject.svelte b/packages/web/src/appobj/AppFileAppObject.svelte index 7a92be33d..1c962b71d 100644 --- a/packages/web/src/appobj/AppFileAppObject.svelte +++ b/packages/web/src/appobj/AppFileAppObject.svelte @@ -3,9 +3,11 @@ const connProps: any = {}; let tooltip = undefined; + const savedFile = fileType == 'vfk.json' ? fileName : fileName + '.' + fileType; + const resp = await apiCall('files/load', { folder: 'app:' + folderName, - file: fileName + '.' + fileType, + file: savedFile, format: 'text', }); @@ -16,7 +18,7 @@ tabComponent, tooltip, props: { - savedFile: fileName + '.' + fileType, + savedFile, savedFolder: 'app:' + folderName, savedFormat: 'text', appFolder: folderName, @@ -30,6 +32,7 @@ export const extractKey = data => data.fileName; export const createMatcher = ({ fileName }) => filter => filterName(filter, fileName); const APP_ICONS = { + 'vfk.json': 'img json', 'command.sql': 'img app-command', 'query.sql': 'img app-query', }; @@ -85,12 +88,15 @@ if (data.fileType.endsWith('.sql')) { handleOpenSqlFile(); } + if (data.fileType.endsWith('.json')) { + handleOpenJsonFile(); + } }; const handleOpenSqlFile = () => { openTextFile(data.fileName, data.fileType, data.folderName, 'QueryTab', 'img sql-file'); }; - const handleOpenYamlFile = () => { - openTextFile(data.fileName, data.fileType, data.folderName, 'YamlEditorTab', 'img yaml'); + const handleOpenJsonFile = () => { + openTextFile(data.fileName, data.fileType, data.folderName, 'JsonEditorTab', 'img json'); }; function createMenu() { @@ -98,6 +104,7 @@ { text: 'Delete', onClick: handleDelete }, { text: 'Rename', onClick: handleRename }, data.fileType.endsWith('.sql') && { text: 'Open SQL', onClick: handleOpenSqlFile }, + data.fileType.endsWith('.json') && { text: 'Open JSON', onClick: handleOpenJsonFile }, // data.fileType.endsWith('.yaml') && { text: 'Open YAML', onClick: handleOpenYamlFile }, ]; diff --git a/packages/web/src/elements/TargetApplicationSelect.svelte b/packages/web/src/elements/TargetApplicationSelect.svelte index 12bd9232d..fbaa71658 100644 --- a/packages/web/src/elements/TargetApplicationSelect.svelte +++ b/packages/web/src/elements/TargetApplicationSelect.svelte @@ -1,18 +1,69 @@ + + { + value = e.detail; + }} options={[ - { label: '(New application linked to current DB)', value: 'new' }, - ...($apps || []).map(app => ({ + { label: '(New application linked to current DB)', value: '#new' }, + ...($appFolders || []).map(app => ({ label: app.name, value: app.name, })), diff --git a/packages/web/src/tableeditor/ForeignKeyEditorModal.svelte b/packages/web/src/tableeditor/ForeignKeyEditorModal.svelte index c13fb04c9..4c8a8f1d5 100644 --- a/packages/web/src/tableeditor/ForeignKeyEditorModal.svelte +++ b/packages/web/src/tableeditor/ForeignKeyEditorModal.svelte @@ -81,7 +81,7 @@ value={fullNameToString({ pureName: refTableName, schemaName: refSchemaName })} isNative notSelected - options={(dbInfo?.tables || []).map(tbl => ({ + options={_.sortBy(dbInfo?.tables || [], ['schemaName', 'pureName']).map(tbl => ({ label: fullNameToLabel(tbl), value: fullNameToString(tbl), }))} diff --git a/packages/web/src/tableeditor/VirtualForeignKeyEditorModal.svelte b/packages/web/src/tableeditor/VirtualForeignKeyEditorModal.svelte index 1fe57733d..6f345d97e 100644 --- a/packages/web/src/tableeditor/VirtualForeignKeyEditorModal.svelte +++ b/packages/web/src/tableeditor/VirtualForeignKeyEditorModal.svelte @@ -1,32 +1,17 @@ + + + + setEditorData(e.detail)} + on:focus={() => { + activator.activate(); + invalidateCommands(); + }} + bind:this={domEditor} + mode="json" +/> diff --git a/packages/web/src/tabs/YamlEditorTab.svelte b/packages/web/src/tabs/YamlEditorTab.svelte index 6cab222f6..1540137b4 100644 --- a/packages/web/src/tabs/YamlEditorTab.svelte +++ b/packages/web/src/tabs/YamlEditorTab.svelte @@ -31,7 +31,7 @@ const tabVisible: any = getContext('tabVisible'); - export const activator = createActivator('MarkdownEditorTab', false); + export const activator = createActivator('YamlEditorTab', false); let domEditor; @@ -63,8 +63,6 @@ function createMenu() { return [ - { command: 'yaml.preview' }, - { divider: true }, { command: 'yaml.toggleComment' }, { divider: true }, { command: 'yaml.save' }, diff --git a/packages/web/src/tabs/index.js b/packages/web/src/tabs/index.js index e3002e0d4..b0d7f7144 100644 --- a/packages/web/src/tabs/index.js +++ b/packages/web/src/tabs/index.js @@ -15,6 +15,7 @@ import * as FavoriteEditorTab from './FavoriteEditorTab.svelte'; import * as QueryDesignTab from './QueryDesignTab.svelte'; import * as CommandListTab from './CommandListTab.svelte'; import * as YamlEditorTab from './YamlEditorTab.svelte'; +import * as JsonEditorTab from './JsonEditorTab.svelte'; import * as CompareModelTab from './CompareModelTab.svelte'; import * as JsonTab from './JsonTab.svelte'; import * as ChangelogTab from './ChangelogTab.svelte'; @@ -38,6 +39,7 @@ export default { QueryDesignTab, CommandListTab, YamlEditorTab, + JsonEditorTab, CompareModelTab, JsonTab, ChangelogTab,