antares/src/renderer/components/QueryEditor.vue

253 lines
6.9 KiB
Vue
Raw Normal View History

2020-05-07 17:45:04 +02:00
<template>
<div class="editor-wrapper">
2020-12-23 18:07:50 +01:00
<div
ref="editor"
class="editor"
:style="{height: `${height}px`}"
/>
2020-05-07 17:45:04 +02:00
</div>
</template>
<script>
import * as ace from 'ace-builds';
import 'ace-builds/webpack-resolver';
import '../libs/ext-language_tools';
2020-12-23 18:07:50 +01:00
import { mapGetters } from 'vuex';
import Tables from '@/ipc-api/Tables';
2020-05-07 17:45:04 +02:00
export default {
name: 'QueryEditor',
props: {
2020-12-11 15:55:18 +01:00
value: String,
2020-12-23 18:07:50 +01:00
workspace: Object,
schema: { type: String, default: '' },
autoFocus: { type: Boolean, default: false },
2020-12-23 18:07:50 +01:00
readOnly: { type: Boolean, default: false },
height: { type: Number, default: 200 }
2020-05-07 17:45:04 +02:00
},
data () {
return {
editor: null,
fields: [],
baseCompleter: []
2020-05-07 17:45:04 +02:00
};
},
computed: {
2020-12-23 18:07:50 +01:00
...mapGetters({
editorTheme: 'settings/getEditorTheme',
2020-12-24 15:33:51 +01:00
autoComplete: 'settings/getAutoComplete',
lineWrap: 'settings/getLineWrap'
2020-12-23 18:07:50 +01:00
}),
tables () {
return this.workspace
? this.workspace.structure.filter(schema => schema.name === this.schema)
.reduce((acc, curr) => {
acc.push(...curr.tables);
return acc;
}, []).map(table => {
return {
name: table.name,
type: table.type,
fields: []
};
})
: [];
},
triggers () {
return this.workspace
? this.workspace.structure.filter(schema => schema.name === this.schema)
.reduce((acc, curr) => {
acc.push(...curr.triggers);
return acc;
}, []).map(trigger => {
return {
name: trigger.name,
type: 'trigger'
};
})
: [];
},
procedures () {
return this.workspace
? this.workspace.structure.filter(schema => schema.name === this.schema)
.reduce((acc, curr) => {
acc.push(...curr.procedures);
return acc;
}, []).map(procedure => {
return {
name: `${procedure.name}()`,
type: 'routine'
};
})
: [];
},
mode () {
switch (this.workspace.client) {
case 'mysql':
case 'maria':
return 'mysql';
case 'mssql':
return 'sqlserver';
case 'pg':
return 'pgsql';
default:
return 'sql';
}
},
lastWord () {
const words = this.value.split(' ');
return words[words.length - 1];
},
isLastWordATable () {
return /\w+\.\w*/gm.test(this.lastWord);
},
fieldsCompleter () {
return {
getCompletions: (editor, session, pos, prefix, callback) => {
const completions = [];
this.fields.forEach(field => {
completions.push({
value: field,
meta: 'column',
score: 1000
});
});
callback(null, completions);
}
};
}
},
2020-12-23 18:07:50 +01:00
watch: {
editorTheme () {
if (this.editor)
this.editor.setTheme(`ace/theme/${this.editorTheme}`);
},
autoComplete () {
if (this.editor) {
this.editor.setOptions({
enableLiveAutocompletion: this.autoComplete
});
}
2020-12-24 15:33:51 +01:00
},
lineWrap () {
if (this.editor) {
this.editor.setOptions({
wrap: this.lineWrap
});
}
2020-12-23 18:07:50 +01:00
}
},
2020-05-07 17:45:04 +02:00
mounted () {
this.editor = ace.edit(this.$refs.editor, {
mode: `ace/mode/${this.mode}`,
2020-12-23 18:07:50 +01:00
theme: `ace/theme/${this.editorTheme}`,
2020-08-20 18:06:02 +02:00
value: this.value,
fontSize: '14px',
2020-12-23 18:07:50 +01:00
printMargin: false,
readOnly: this.readOnly
2020-08-20 18:06:02 +02:00
});
2020-05-07 17:45:04 +02:00
this.editor.setOptions({
enableBasicAutocompletion: true,
2020-12-24 15:33:51 +01:00
wrap: this.lineWrap,
enableSnippets: true,
enableLiveAutocompletion: this.autoComplete
});
this.editor.completers.push({
getCompletions: (editor, session, pos, prefix, callback) => {
const completions = [];
[
...this.tables,
...this.triggers,
...this.procedures
].forEach(el => {
completions.push({
value: el.name,
meta: el.type
});
});
callback(null, completions);
}
});
this.baseCompleter = this.editor.completers;
this.editor.commands.on('afterExec', e => {
if (['insertstring', 'backspace', 'del'].includes(e.command.name)) {
if (this.isLastWordATable || e.args === '.') {
if (e.args !== ' ') {
const table = this.tables.find(t => t.name === this.lastWord.split('.').pop());
if (table) {
const params = {
uid: this.workspace.uid,
schema: this.schema,
table: table.name
};
Tables.getTableColumns(params).then(res => {
if (res.response.length)
this.fields = res.response.map(field => field.name);
this.editor.completers = [this.fieldsCompleter];
this.editor.execCommand('startAutocomplete');
}).catch(console.log);
}
else
this.editor.completers = this.baseCompleter;
}
else
this.editor.completers = this.baseCompleter;
}
else
this.editor.completers = this.baseCompleter;
}
});
this.editor.session.on('change', () => {
2020-08-20 18:06:02 +02:00
const content = this.editor.getValue();
this.$emit('update:value', content);
});
2020-12-11 15:55:18 +01:00
if (this.autoFocus) {
setTimeout(() => {
this.editor.focus();
2020-12-26 15:37:34 +01:00
this.editor.resize();
2020-12-11 15:55:18 +01:00
}, 20);
}
2020-12-26 15:37:34 +01:00
setTimeout(() => {
this.editor.resize();
}, 20);
2020-05-07 17:45:04 +02:00
}
};
</script>
2020-06-05 21:00:15 +02:00
<style lang="scss">
.editor-wrapper {
border-bottom: 1px solid #444;
2020-08-20 18:06:02 +02:00
.editor {
width: 100%;
2020-07-31 18:16:28 +02:00
}
}
.ace_.mdi {
display: inline-block;
width: 17px;
}
.ace_dark.ace_editor.ace_autocomplete .ace_marker-layer .ace_active-line {
background-color: #c9561a99;
}
.ace_dark.ace_editor.ace_autocomplete .ace_marker-layer .ace_line-hover {
background-color: #c9571a33;
border: none;
}
.ace_dark.ace_editor.ace_autocomplete .ace_completion-highlight {
color: #e0d00c;
}
2020-05-07 17:45:04 +02:00
</style>