mirror of https://github.com/Fabio286/antares.git
feat: query editor auto-completer for tables and columns
This commit is contained in:
parent
0014f48079
commit
cb1fce6f99
|
@ -7,22 +7,78 @@
|
|||
<script>
|
||||
import * as ace from 'ace-builds';
|
||||
import 'ace-builds/webpack-resolver';
|
||||
import 'ace-builds/src-noconflict/ext-language_tools';
|
||||
import '../libs/ext-language_tools';
|
||||
import Tables from '@/ipc-api/Tables';
|
||||
|
||||
export default {
|
||||
name: 'QueryEditor',
|
||||
props: {
|
||||
value: String,
|
||||
autoFocus: { type: Boolean, default: false }
|
||||
schema: String,
|
||||
autoFocus: { type: Boolean, default: false },
|
||||
workspace: Object
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
editor: null
|
||||
editor: null,
|
||||
fields: [],
|
||||
baseCompleter: []
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
tables () {
|
||||
return this.workspace.structure.filter(schema => schema.name === this.schema)
|
||||
.reduce((acc, curr) => {
|
||||
acc.push(...curr.tables);
|
||||
return acc;
|
||||
}, []).map(table => {
|
||||
return {
|
||||
name: table.name,
|
||||
comment: table.comment,
|
||||
type: table.type,
|
||||
fields: ['TODO']
|
||||
};
|
||||
});
|
||||
},
|
||||
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);
|
||||
}
|
||||
};
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.editor = ace.edit(this.$refs.editor, {
|
||||
mode: 'ace/mode/sql',
|
||||
mode: `ace/mode/${this.mode}`,
|
||||
theme: 'ace/theme/twilight',
|
||||
value: this.value,
|
||||
fontSize: '14px',
|
||||
|
@ -35,6 +91,53 @@ export default {
|
|||
enableLiveAutocompletion: true
|
||||
});
|
||||
|
||||
this.editor.completers.push({
|
||||
getCompletions: (editor, session, pos, prefix, callback) => {
|
||||
const completions = [];
|
||||
this.tables.forEach(table => {
|
||||
completions.push({
|
||||
value: table.name,
|
||||
meta: table.type,
|
||||
caption: table.comment
|
||||
});
|
||||
});
|
||||
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', () => {
|
||||
const content = this.editor.getValue();
|
||||
this.$emit('update:value', content);
|
||||
|
@ -50,12 +153,30 @@ export default {
|
|||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.editor-wrapper {
|
||||
border-bottom: 1px solid #444;
|
||||
.editor-wrapper {
|
||||
border-bottom: 1px solid #444;
|
||||
|
||||
.editor {
|
||||
height: 200px;
|
||||
width: 100%;
|
||||
}
|
||||
.editor {
|
||||
height: 200px;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
v-if="isSelected"
|
||||
:auto-focus="true"
|
||||
:value.sync="query"
|
||||
:workspace="workspace"
|
||||
:schema="schema"
|
||||
/>
|
||||
<div class="workspace-query-runner-footer">
|
||||
<div class="workspace-query-buttons">
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue