feat(UI): run routines/functions from settings tab

This commit is contained in:
Fabio Di Stasio 2021-02-25 12:39:50 +01:00
parent 3aa2159a1a
commit 7e8167154f
3 changed files with 178 additions and 12 deletions

View File

@ -0,0 +1,102 @@
<template>
<ConfirmModal
:confirm-text="$t('word.run')"
:cancel-text="$t('word.cancel')"
size="400"
@confirm="runRoutine"
@hide="closeModal"
>
<template slot="header">
<div class="d-flex">
<i class="mdi mdi-24px mdi-play mr-1" /> {{ $t('word.parameters') }}: {{ localRoutine.name }}
</div>
</template>
<div slot="body">
<div class="content">
<form class="form-horizontal">
<div
v-for="(parameter, i) in localRoutine.parameters"
:key="parameter._id"
class="form-group"
>
<div class="col-3">
<label class="form-label">{{ parameter.name }}</label>
</div>
<div class="col-9">
<div class="input-group">
<input
:ref="i === 0 ? 'firstInput' : ''"
v-model="values[parameter.name]"
class="form-input"
type="text"
>
<span class="input-group-addon field-type" :class="`type-${parameter.type.toLowerCase()}`">
{{ parameter.type }} {{ parameter.length | wrapNumber }}
</span>
</div>
</div>
</div>
</form>
</div>
</div>
</ConfirmModal>
</template>
<script>
import ConfirmModal from '@/components/BaseConfirmModal';
export default {
name: 'ModalAskParameters',
components: {
ConfirmModal
},
filters: {
wrapNumber (num) {
if (!num) return '';
return `(${num})`;
}
},
props: {
localRoutine: Object
},
data () {
return {
values: {}
};
},
created () {
window.addEventListener('keydown', this.onKey);
setTimeout(() => {
this.$refs.firstInput[0].focus();
}, 20);
},
beforeDestroy () {
window.removeEventListener('keydown', this.onKey);
},
methods: {
runRoutine () {
const valArr = Object.keys(this.values).reduce((acc, curr) => {
const value = isNaN(this.values[curr]) ? `"${this.values[curr]}"` : this.values[curr];
acc.push(value);
return acc;
}, []);
this.$emit('confirm', valArr);
},
closeModal () {
this.$emit('close');
},
onKey (e) {
e.stopPropagation();
if (e.key === 'Escape')
this.closeModal();
}
}
};
</script>
<style scoped>
.field-type {
font-size: 0.6rem;
}
</style>

View File

@ -25,9 +25,9 @@
<div class="divider-vert py-3" /> <div class="divider-vert py-3" />
<button <button
class="btn btn-dark btn-sm disabled" class="btn btn-dark btn-sm"
:disabled="isChanged" :disabled="isChanged"
@click="false" @click="runFunctionCheck"
> >
<span>{{ $t('word.run') }}</span> <span>{{ $t('word.run') }}</span>
<i class="mdi mdi-24px mdi-play ml-1" /> <i class="mdi mdi-24px mdi-play ml-1" />
@ -70,6 +70,12 @@
@hide="hideParamsModal" @hide="hideParamsModal"
@parameters-update="parametersUpdate" @parameters-update="parametersUpdate"
/> />
<ModalAskParameters
v-if="isAskingParameters"
:local-routine="localFunction"
@confirm="runFunction"
@close="hideAskParamsModal"
/>
</div> </div>
</template> </template>
@ -80,6 +86,7 @@ import BaseLoader from '@/components/BaseLoader';
import QueryEditor from '@/components/QueryEditor'; import QueryEditor from '@/components/QueryEditor';
import WorkspacePropsFunctionOptionsModal from '@/components/WorkspacePropsFunctionOptionsModal'; import WorkspacePropsFunctionOptionsModal from '@/components/WorkspacePropsFunctionOptionsModal';
import WorkspacePropsFunctionParamsModal from '@/components/WorkspacePropsFunctionParamsModal'; import WorkspacePropsFunctionParamsModal from '@/components/WorkspacePropsFunctionParamsModal';
import ModalAskParameters from '@/components/ModalAskParameters';
import Functions from '@/ipc-api/Functions'; import Functions from '@/ipc-api/Functions';
export default { export default {
@ -88,7 +95,8 @@ export default {
BaseLoader, BaseLoader,
QueryEditor, QueryEditor,
WorkspacePropsFunctionOptionsModal, WorkspacePropsFunctionOptionsModal,
WorkspacePropsFunctionParamsModal WorkspacePropsFunctionParamsModal,
ModalAskParameters
}, },
props: { props: {
connection: Object, connection: Object,
@ -101,6 +109,7 @@ export default {
isSaving: false, isSaving: false,
isOptionsModal: false, isOptionsModal: false,
isParamsModal: false, isParamsModal: false,
isAskingParameters: false,
originalFunction: null, originalFunction: null,
localFunction: { sql: '' }, localFunction: { sql: '' },
lastFunction: null, lastFunction: null,
@ -166,7 +175,8 @@ export default {
addNotification: 'notifications/addNotification', addNotification: 'notifications/addNotification',
refreshStructure: 'workspaces/refreshStructure', refreshStructure: 'workspaces/refreshStructure',
setUnsavedChanges: 'workspaces/setUnsavedChanges', setUnsavedChanges: 'workspaces/setUnsavedChanges',
changeBreadcrumbs: 'workspaces/changeBreadcrumbs' changeBreadcrumbs: 'workspaces/changeBreadcrumbs',
newTab: 'workspaces/newTab'
}), }),
async getFunctionData () { async getFunctionData () {
if (!this.function) return; if (!this.function) return;
@ -257,6 +267,31 @@ export default {
parametersUpdate (parameters) { parametersUpdate (parameters) {
this.localFunction = { ...this.localFunction, parameters }; this.localFunction = { ...this.localFunction, parameters };
}, },
runFunctionCheck () {
if (this.localFunction.parameters.length)
this.showAskParamsModal();
else
this.runFunction();
},
runFunction (params) {
if (!params) params = [];
let sql;
switch (this.connection.client) { // TODO: move in a better place
case 'maria':
case 'mysql':
case 'pg':
sql = `SELECT \`${this.originalFunction.name}\` (${params.join(',')})`;
break;
case 'mssql':
sql = `SELECT ${this.originalFunction.name} ${params.join(',')}`;
break;
default:
sql = `SELECT \`${this.originalFunction.name}\` (${params.join(',')})`;
}
this.newTab({ uid: this.connection.uid, content: sql, autorun: true });
},
showOptionsModal () { showOptionsModal () {
this.isOptionsModal = true; this.isOptionsModal = true;
}, },
@ -268,6 +303,12 @@ export default {
}, },
hideParamsModal () { hideParamsModal () {
this.isParamsModal = false; this.isParamsModal = false;
},
showAskParamsModal () {
this.isAskingParameters = true;
},
hideAskParamsModal () {
this.isAskingParameters = false;
} }
} }
}; };

View File

@ -25,9 +25,9 @@
<div class="divider-vert py-3" /> <div class="divider-vert py-3" />
<button <button
class="btn btn-dark btn-sm disabled" class="btn btn-dark btn-sm"
:disabled="isChanged" :disabled="isChanged"
@click="runRoutine" @click="runRoutineCheck"
> >
<span>{{ $t('word.run') }}</span> <span>{{ $t('word.run') }}</span>
<i class="mdi mdi-24px mdi-play ml-1" /> <i class="mdi mdi-24px mdi-play ml-1" />
@ -70,6 +70,12 @@
@hide="hideParamsModal" @hide="hideParamsModal"
@parameters-update="parametersUpdate" @parameters-update="parametersUpdate"
/> />
<ModalAskParameters
v-if="isAskingParameters"
:local-routine="localRoutine"
@confirm="runRoutine"
@close="hideAskParamsModal"
/>
</div> </div>
</template> </template>
@ -80,6 +86,7 @@ import QueryEditor from '@/components/QueryEditor';
import BaseLoader from '@/components/BaseLoader'; import BaseLoader from '@/components/BaseLoader';
import WorkspacePropsRoutineOptionsModal from '@/components/WorkspacePropsRoutineOptionsModal'; import WorkspacePropsRoutineOptionsModal from '@/components/WorkspacePropsRoutineOptionsModal';
import WorkspacePropsRoutineParamsModal from '@/components/WorkspacePropsRoutineParamsModal'; import WorkspacePropsRoutineParamsModal from '@/components/WorkspacePropsRoutineParamsModal';
import ModalAskParameters from '@/components/ModalAskParameters';
import Routines from '@/ipc-api/Routines'; import Routines from '@/ipc-api/Routines';
export default { export default {
@ -88,7 +95,8 @@ export default {
QueryEditor, QueryEditor,
BaseLoader, BaseLoader,
WorkspacePropsRoutineOptionsModal, WorkspacePropsRoutineOptionsModal,
WorkspacePropsRoutineParamsModal WorkspacePropsRoutineParamsModal,
ModalAskParameters
}, },
props: { props: {
connection: Object, connection: Object,
@ -101,6 +109,7 @@ export default {
isSaving: false, isSaving: false,
isOptionsModal: false, isOptionsModal: false,
isParamsModal: false, isParamsModal: false,
isAskingParameters: false,
originalRoutine: null, originalRoutine: null,
localRoutine: { sql: '' }, localRoutine: { sql: '' },
lastRoutine: null, lastRoutine: null,
@ -257,22 +266,30 @@ export default {
parametersUpdate (parameters) { parametersUpdate (parameters) {
this.localRoutine = { ...this.localRoutine, parameters }; this.localRoutine = { ...this.localRoutine, parameters };
}, },
runRoutine () { // TODO: create ask for params modal runRoutineCheck () {
if (this.localRoutine.parameters.length)
this.showAskParamsModal();
else
this.runRoutine();
},
runRoutine (params) {
if (!params) params = [];
let sql; let sql;
switch (this.connection.client) { // TODO: move in a better place switch (this.connection.client) { // TODO: move in a better place
case 'maria': case 'maria':
case 'mysql': case 'mysql':
case 'pg': case 'pg':
sql = `CALL \`${this.originalRoutine.name}\` ()`; sql = `CALL \`${this.originalRoutine.name}\` (${params.join(',')})`;
break; break;
case 'mssql': case 'mssql':
sql = `EXEC ${this.originalRoutine.name}`; sql = `EXEC ${this.originalRoutine.name} ${params.join(',')}`;
break; break;
default: default:
sql = `CALL \`${this.originalRoutine.name}\` ()`; sql = `CALL \`${this.originalRoutine.name}\` (${params.join(',')})`;
} }
this.newTab({ uid: this.connection.uid, content: sql, autorun: !this.originalRoutine.parameters.length }); this.newTab({ uid: this.connection.uid, content: sql, autorun: true });
}, },
showOptionsModal () { showOptionsModal () {
this.isOptionsModal = true; this.isOptionsModal = true;
@ -285,6 +302,12 @@ export default {
}, },
hideParamsModal () { hideParamsModal () {
this.isParamsModal = false; this.isParamsModal = false;
},
showAskParamsModal () {
this.isAskingParameters = true;
},
hideAskParamsModal () {
this.isAskingParameters = false;
} }
} }
}; };