mirror of
https://github.com/Fabio286/antares.git
synced 2025-06-05 21:59:22 +02:00
refactor: ts and composition api on more components
This commit is contained in:
@ -8,7 +8,8 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, Prop, Ref, ref, toRef, watch } from 'vue';
|
||||
import * as ace from 'ace-builds';
|
||||
import 'ace-builds/webpack-resolver';
|
||||
import '../libs/ext-language_tools';
|
||||
@ -16,329 +17,330 @@ import { storeToRefs } from 'pinia';
|
||||
import { uidGen } from 'common/libs/uidGen';
|
||||
import { useApplicationStore } from '@/stores/application';
|
||||
import { useSettingsStore } from '@/stores/settings';
|
||||
import { Workspace } from '@/stores/workspaces';
|
||||
import Tables from '@/ipc-api/Tables';
|
||||
|
||||
export default {
|
||||
name: 'QueryEditor',
|
||||
props: {
|
||||
modelValue: String,
|
||||
workspace: Object,
|
||||
isSelected: Boolean,
|
||||
schema: { type: String, default: '' },
|
||||
autoFocus: { type: Boolean, default: false },
|
||||
readOnly: { type: Boolean, default: false },
|
||||
height: { type: Number, default: 200 }
|
||||
},
|
||||
emits: ['update:modelValue'],
|
||||
setup () {
|
||||
const editor = null;
|
||||
const applicationStore = useApplicationStore();
|
||||
const settingsStore = useSettingsStore();
|
||||
const editor: Ref<ace.Ace.Editor> = ref(null);
|
||||
const applicationStore = useApplicationStore();
|
||||
const settingsStore = useSettingsStore();
|
||||
|
||||
const { setBaseCompleters } = applicationStore;
|
||||
const { setBaseCompleters } = applicationStore;
|
||||
|
||||
const { baseCompleter } = storeToRefs(applicationStore);
|
||||
const {
|
||||
editorTheme,
|
||||
editorFontSize,
|
||||
autoComplete,
|
||||
lineWrap
|
||||
} = storeToRefs(settingsStore);
|
||||
const { baseCompleter } = storeToRefs(applicationStore);
|
||||
const {
|
||||
editorTheme,
|
||||
editorFontSize,
|
||||
autoComplete,
|
||||
lineWrap
|
||||
} = storeToRefs(settingsStore);
|
||||
|
||||
return {
|
||||
editor,
|
||||
baseCompleter,
|
||||
setBaseCompleters,
|
||||
editorTheme,
|
||||
editorFontSize,
|
||||
autoComplete,
|
||||
lineWrap
|
||||
};
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
cursorPosition: 0,
|
||||
fields: [],
|
||||
customCompleter: [],
|
||||
id: uidGen(),
|
||||
lastSchema: null
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
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'
|
||||
};
|
||||
})
|
||||
: [];
|
||||
},
|
||||
functions () {
|
||||
return this.workspace
|
||||
? this.workspace.structure.filter(schema => schema.name === this.schema)
|
||||
.reduce((acc, curr) => {
|
||||
acc.push(...curr.functions);
|
||||
return acc;
|
||||
}, []).map(func => {
|
||||
return {
|
||||
name: `${func.name}()`,
|
||||
type: 'function'
|
||||
};
|
||||
})
|
||||
: [];
|
||||
},
|
||||
schedulers () {
|
||||
return this.workspace
|
||||
? this.workspace.structure.filter(schema => schema.name === this.schema)
|
||||
.reduce((acc, curr) => {
|
||||
acc.push(...curr.schedulers);
|
||||
return acc;
|
||||
}, []).map(scheduler => {
|
||||
return {
|
||||
name: scheduler.name,
|
||||
type: 'scheduler'
|
||||
};
|
||||
})
|
||||
: [];
|
||||
},
|
||||
mode () {
|
||||
switch (this.workspace.client) {
|
||||
case 'mysql':
|
||||
case 'maria':
|
||||
return 'mysql';
|
||||
case 'mssql':
|
||||
return 'sqlserver';
|
||||
case 'pg':
|
||||
return 'pgsql';
|
||||
default:
|
||||
return 'sql';
|
||||
}
|
||||
},
|
||||
lastWord () {
|
||||
const charsBefore = this.modelValue.slice(0, this.cursorPosition);
|
||||
const words = charsBefore.replaceAll('\n', ' ').split(' ').filter(Boolean);
|
||||
return words.pop();
|
||||
},
|
||||
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);
|
||||
}
|
||||
};
|
||||
const props = defineProps({
|
||||
modelValue: String,
|
||||
workspace: Object as Prop<Workspace>,
|
||||
isSelected: Boolean,
|
||||
schema: { type: String, default: '' },
|
||||
autoFocus: { type: Boolean, default: false },
|
||||
readOnly: { type: Boolean, default: false },
|
||||
height: { type: Number, default: 200 }
|
||||
});
|
||||
|
||||
const emit = defineEmits(['update:modelValue']);
|
||||
|
||||
const cursorPosition = ref(0);
|
||||
const fields = ref([]);
|
||||
const customCompleter = ref([]);
|
||||
const id = ref(uidGen());
|
||||
const lastSchema: Ref<string> = ref(null);
|
||||
|
||||
const tables = computed(() => {
|
||||
return props.workspace
|
||||
? props.workspace.structure.filter(schema => schema.name === props.schema)
|
||||
.reduce((acc, curr) => {
|
||||
acc.push(...curr.tables);
|
||||
return acc;
|
||||
}, []).map(table => {
|
||||
return {
|
||||
name: table.name as string,
|
||||
type: table.type as string,
|
||||
fields: []
|
||||
};
|
||||
})
|
||||
: [];
|
||||
});
|
||||
|
||||
const triggers = computed(() => {
|
||||
return props.workspace
|
||||
? props.workspace.structure.filter(schema => schema.name === props.schema)
|
||||
.reduce((acc, curr) => {
|
||||
acc.push(...curr.triggers);
|
||||
return acc;
|
||||
}, []).map(trigger => {
|
||||
return {
|
||||
name: trigger.name as string,
|
||||
type: 'trigger'
|
||||
};
|
||||
})
|
||||
: [];
|
||||
});
|
||||
|
||||
const procedures = computed(() => {
|
||||
return props.workspace
|
||||
? props.workspace.structure.filter(schema => schema.name === props.schema)
|
||||
.reduce((acc, curr) => {
|
||||
acc.push(...curr.procedures);
|
||||
return acc;
|
||||
}, []).map(procedure => {
|
||||
return {
|
||||
name: `${procedure.name}()`,
|
||||
type: 'routine'
|
||||
};
|
||||
})
|
||||
: [];
|
||||
});
|
||||
|
||||
const functions = computed(() => {
|
||||
return props.workspace
|
||||
? props.workspace.structure.filter(schema => schema.name === props.schema)
|
||||
.reduce((acc, curr) => {
|
||||
acc.push(...curr.functions);
|
||||
return acc;
|
||||
}, []).map(func => {
|
||||
return {
|
||||
name: `${func.name}()`,
|
||||
type: 'function'
|
||||
};
|
||||
})
|
||||
: [];
|
||||
});
|
||||
|
||||
const schedulers = computed(() => {
|
||||
return props.workspace
|
||||
? props.workspace.structure.filter(schema => schema.name === props.schema)
|
||||
.reduce((acc, curr) => {
|
||||
acc.push(...curr.schedulers);
|
||||
return acc;
|
||||
}, []).map(scheduler => {
|
||||
return {
|
||||
name: scheduler.name as string,
|
||||
type: 'scheduler'
|
||||
};
|
||||
})
|
||||
: [];
|
||||
});
|
||||
|
||||
const mode = computed(() => {
|
||||
switch (props.workspace.client) {
|
||||
case 'mysql':
|
||||
case 'maria':
|
||||
return 'mysql';
|
||||
case 'mssql':
|
||||
return 'sqlserver';
|
||||
case 'pg':
|
||||
return 'pgsql';
|
||||
default:
|
||||
return 'sql';
|
||||
}
|
||||
});
|
||||
|
||||
const lastWord = computed(() => {
|
||||
const charsBefore = props.modelValue.slice(0, cursorPosition.value);
|
||||
const words = charsBefore.replaceAll('\n', ' ').split(' ').filter(Boolean);
|
||||
return words.pop();
|
||||
});
|
||||
|
||||
const isLastWordATable = computed(() => /\w+\.\w*/gm.test(lastWord.value));
|
||||
|
||||
const fieldsCompleter = computed(() => {
|
||||
return {
|
||||
getCompletions: (editor: never, session: never, pos: never, prefix: never, callback: (err: null, response: ace.Ace.Completion[]) => void) => {
|
||||
const completions: ace.Ace.Completion[] = [];
|
||||
fields.value.forEach(field => {
|
||||
completions.push({
|
||||
value: field,
|
||||
meta: 'column',
|
||||
score: 1000
|
||||
});
|
||||
});
|
||||
callback(null, completions);
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
modelValue () {
|
||||
this.cursorPosition = this.editor.session.doc.positionToIndex(this.editor.getCursorPosition());
|
||||
},
|
||||
editorTheme () {
|
||||
if (this.editor)
|
||||
this.editor.setTheme(`ace/theme/${this.editorTheme}`);
|
||||
},
|
||||
editorFontSize () {
|
||||
const sizes = {
|
||||
small: '12px',
|
||||
medium: '14px',
|
||||
large: '16px'
|
||||
};
|
||||
};
|
||||
});
|
||||
|
||||
if (this.editor) {
|
||||
this.editor.setOptions({
|
||||
fontSize: sizes[this.editorFontSize]
|
||||
const setCustomCompleter = () => {
|
||||
editor.value.completers.push({
|
||||
getCompletions: (editor, session, pos, prefix, callback: (err: null, response: ace.Ace.Completion[]) => void) => {
|
||||
const completions: ace.Ace.Completion[] = [];
|
||||
[
|
||||
...tables.value,
|
||||
...triggers.value,
|
||||
...procedures.value,
|
||||
...functions.value,
|
||||
...schedulers.value
|
||||
].forEach(el => {
|
||||
completions.push({
|
||||
value: el.name,
|
||||
meta: el.type,
|
||||
score: 1000
|
||||
});
|
||||
}
|
||||
},
|
||||
autoComplete () {
|
||||
if (this.editor) {
|
||||
this.editor.setOptions({
|
||||
enableLiveAutocompletion: this.autoComplete
|
||||
});
|
||||
}
|
||||
},
|
||||
lineWrap () {
|
||||
if (this.editor) {
|
||||
this.editor.setOptions({
|
||||
wrap: this.lineWrap
|
||||
});
|
||||
}
|
||||
},
|
||||
isSelected () {
|
||||
if (this.isSelected) {
|
||||
this.lastSchema = this.schema;
|
||||
this.editor.resize();
|
||||
}
|
||||
},
|
||||
height () {
|
||||
setTimeout(() => {
|
||||
this.editor.resize();
|
||||
}, 20);
|
||||
},
|
||||
lastSchema () {
|
||||
if (this.editor) {
|
||||
this.editor.completers = this.baseCompleter.map(el => Object.assign({}, el));
|
||||
this.setCustomCompleter();
|
||||
}
|
||||
});
|
||||
callback(null, completions);
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.lastSchema = this.schema;
|
||||
},
|
||||
mounted () {
|
||||
this.editor = ace.edit(`editor-${this.id}`, {
|
||||
mode: `ace/mode/${this.mode}`,
|
||||
theme: `ace/theme/${this.editorTheme}`,
|
||||
value: this.modelValue,
|
||||
fontSize: '14px',
|
||||
printMargin: false,
|
||||
readOnly: this.readOnly
|
||||
});
|
||||
|
||||
customCompleter.value = editor.value.completers;
|
||||
};
|
||||
|
||||
watch(() => props.modelValue, () => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
cursorPosition.value = (editor.value.session as any).doc.positionToIndex(editor.value.getCursorPosition());
|
||||
});
|
||||
|
||||
watch(editorTheme, () => {
|
||||
if (editor.value)
|
||||
editor.value.setTheme(`ace/theme/${editorTheme.value}`);
|
||||
});
|
||||
|
||||
watch(editorFontSize, () => {
|
||||
const sizes = {
|
||||
small: '12px',
|
||||
medium: '14px',
|
||||
large: '16px'
|
||||
};
|
||||
|
||||
if (editor.value) {
|
||||
editor.value.setOptions({
|
||||
fontSize: sizes[editorFontSize.value]
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
this.editor.setOptions({
|
||||
enableBasicAutocompletion: true,
|
||||
wrap: this.lineWrap,
|
||||
enableSnippets: true,
|
||||
enableLiveAutocompletion: this.autoComplete
|
||||
watch(autoComplete, () => {
|
||||
if (editor.value) {
|
||||
editor.value.setOptions({
|
||||
enableLiveAutocompletion: autoComplete.value
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
if (!this.baseCompleter.length)
|
||||
this.setBaseCompleters(this.editor.completers.map(el => Object.assign({}, el)));
|
||||
watch(lineWrap, () => {
|
||||
if (editor.value) {
|
||||
editor.value.setOptions({
|
||||
wrap: lineWrap.value
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
this.setCustomCompleter();
|
||||
watch(() => props.isSelected, () => {
|
||||
if (props.isSelected) {
|
||||
lastSchema.value = props.schema;
|
||||
editor.value.resize();
|
||||
}
|
||||
});
|
||||
|
||||
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().trim());
|
||||
watch(() => props.height, () => {
|
||||
setTimeout(() => {
|
||||
editor.value.resize();
|
||||
}, 20);
|
||||
});
|
||||
|
||||
if (table) {
|
||||
const params = {
|
||||
uid: this.workspace.uid,
|
||||
schema: this.schema,
|
||||
table: table.name
|
||||
};
|
||||
watch(lastSchema, () => {
|
||||
if (editor.value) {
|
||||
editor.value.completers = baseCompleter.value.map(el => Object.assign({}, el));
|
||||
setCustomCompleter();
|
||||
}
|
||||
});
|
||||
|
||||
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.customCompleter;
|
||||
lastSchema.value = toRef(props, 'schema').value;
|
||||
|
||||
onMounted(() => {
|
||||
editor.value = ace.edit(`editor-${id.value}`, {
|
||||
mode: `ace/mode/${mode.value}`,
|
||||
theme: `ace/theme/${editorTheme.value}`,
|
||||
value: props.modelValue,
|
||||
fontSize: 14,
|
||||
printMargin: false,
|
||||
readOnly: props.readOnly
|
||||
});
|
||||
|
||||
editor.value.setOptions({
|
||||
enableBasicAutocompletion: true,
|
||||
wrap: lineWrap.value,
|
||||
enableSnippets: true,
|
||||
enableLiveAutocompletion: autoComplete.value
|
||||
});
|
||||
|
||||
if (!baseCompleter.value.length)
|
||||
setBaseCompleters(editor.value.completers.map(el => Object.assign({}, el)));
|
||||
|
||||
setCustomCompleter();
|
||||
|
||||
editor.value.commands.on('afterExec', (e: { args: string; command: { name: string } }) => {
|
||||
if (['insertstring', 'backspace', 'del'].includes(e.command.name)) {
|
||||
if (isLastWordATable.value || e.args === '.') {
|
||||
if (e.args !== ' ') {
|
||||
const table = tables.value.find(t => t.name === lastWord.value.split('.').pop().trim());
|
||||
|
||||
if (table) {
|
||||
const params = {
|
||||
uid: props.workspace.uid,
|
||||
schema: props.schema,
|
||||
table: table.name
|
||||
};
|
||||
|
||||
Tables.getTableColumns(params).then(res => {
|
||||
if (res.response.length)
|
||||
fields.value = res.response.map((field: { name: string }) => field.name);
|
||||
editor.value.completers = [fieldsCompleter.value];
|
||||
editor.value.execCommand('startAutocomplete');
|
||||
}).catch(console.log);
|
||||
}
|
||||
else
|
||||
this.editor.completers = this.customCompleter;
|
||||
editor.value.completers = customCompleter.value;
|
||||
}
|
||||
else
|
||||
this.editor.completers = this.customCompleter;
|
||||
editor.value.completers = customCompleter.value;
|
||||
}
|
||||
});
|
||||
|
||||
this.editor.session.on('change', () => {
|
||||
const content = this.editor.getValue();
|
||||
this.$emit('update:modelValue', content);
|
||||
});
|
||||
|
||||
this.editor.on('guttermousedown', e => {
|
||||
const target = e.domEvent.target;
|
||||
if (target.className.indexOf('ace_gutter-cell') === -1)
|
||||
return;
|
||||
if (e.clientX > 25 + target.getBoundingClientRect().left)
|
||||
return;
|
||||
|
||||
const row = e.getDocumentPosition().row;
|
||||
const breakpoints = e.editor.session.getBreakpoints(row, 0);
|
||||
if (typeof breakpoints[row] === typeof undefined)
|
||||
e.editor.session.setBreakpoint(row);
|
||||
else
|
||||
e.editor.session.clearBreakpoint(row);
|
||||
e.stop();
|
||||
});
|
||||
|
||||
if (this.autoFocus) {
|
||||
setTimeout(() => {
|
||||
this.editor.focus();
|
||||
this.editor.resize();
|
||||
}, 20);
|
||||
editor.value.completers = customCompleter.value;
|
||||
}
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(editor.value.session as any).on('change', () => {
|
||||
const content = editor.value.getValue();
|
||||
emit('update:modelValue', content);
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(editor.value as any).on('guttermousedown', (e: any) => {
|
||||
const target = e.domEvent.target;
|
||||
if (target.className.indexOf('ace_gutter-cell') === -1)
|
||||
return;
|
||||
if (e.clientX > 25 + target.getBoundingClientRect().left)
|
||||
return;
|
||||
|
||||
const row = e.getDocumentPosition().row;
|
||||
const breakpoints = e.editor.value.session.getBreakpoints(row, 0);
|
||||
if (typeof breakpoints[row] === typeof undefined)
|
||||
e.editor.value.session.setBreakpoint(row);
|
||||
else
|
||||
e.editor.value.session.clearBreakpoint(row);
|
||||
e.stop();
|
||||
});
|
||||
|
||||
if (props.autoFocus) {
|
||||
setTimeout(() => {
|
||||
this.editor.resize();
|
||||
editor.value.focus();
|
||||
editor.value.resize();
|
||||
}, 20);
|
||||
},
|
||||
methods: {
|
||||
setCustomCompleter () {
|
||||
this.editor.completers.push({
|
||||
getCompletions: (editor, session, pos, prefix, callback) => {
|
||||
const completions = [];
|
||||
[
|
||||
...this.tables,
|
||||
...this.triggers,
|
||||
...this.procedures,
|
||||
...this.functions,
|
||||
...this.schedulers
|
||||
].forEach(el => {
|
||||
completions.push({
|
||||
value: el.name,
|
||||
meta: el.type
|
||||
});
|
||||
});
|
||||
callback(null, completions);
|
||||
}
|
||||
});
|
||||
|
||||
this.customCompleter = this.editor.completers;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
setTimeout(() => {
|
||||
editor.value.resize();
|
||||
}, 20);
|
||||
});
|
||||
|
||||
defineExpose({ editor });
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
Reference in New Issue
Block a user