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,