1
1
mirror of https://github.com/Fabio286/antares.git synced 2025-02-17 04:00:48 +01:00

fix: issue managing function/routine parameters

This commit is contained in:
Fabio Di Stasio 2021-02-24 12:46:31 +01:00
parent c8545a250b
commit 76d92cd106
11 changed files with 88 additions and 44 deletions

View File

@ -74,8 +74,8 @@ Depending on your distribution, you will need to run the following command:
- [x] MySQL/MariaDB - [x] MySQL/MariaDB
- [ ] PostgreSQL - [ ] PostgreSQL
- [ ] MSSQL
- [ ] SQLite - [ ] SQLite
- [ ] MSSQL
- [ ] OracleDB - [ ] OracleDB
- [ ] More... - [ ] More...

View File

@ -72,23 +72,23 @@
"devDependencies": { "devDependencies": {
"babel-eslint": "^10.1.0", "babel-eslint": "^10.1.0",
"cross-env": "^7.0.2", "cross-env": "^7.0.2",
"electron": "^11.2.1", "electron": "^11.3.0",
"electron-builder": "^22.9.1", "electron-builder": "^22.9.1",
"electron-devtools-installer": "^3.1.1", "electron-devtools-installer": "^3.1.1",
"electron-webpack": "^2.8.2", "electron-webpack": "^2.8.2",
"electron-webpack-vue": "^2.4.0", "electron-webpack-vue": "^2.4.0",
"eslint": "^7.18.0", "eslint": "^7.20.0",
"eslint-config-standard": "^16.0.2", "eslint-config-standard": "^16.0.2",
"eslint-plugin-import": "^2.22.1", "eslint-plugin-import": "^2.22.1",
"eslint-plugin-node": "^11.1.0", "eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.2.1", "eslint-plugin-promise": "^4.3.1",
"eslint-plugin-vue": "^7.5.0", "eslint-plugin-vue": "^7.6.0",
"node-sass": "^5.0.0", "node-sass": "^5.0.0",
"sass-loader": "^10.1.1", "sass-loader": "^10.1.1",
"standard-version": "^9.1.0", "standard-version": "^9.1.0",
"stylelint": "^13.9.0", "stylelint": "^13.9.0",
"stylelint-config-standard": "^20.0.0", "stylelint-config-standard": "^20.0.0",
"stylelint-scss": "^3.18.0", "stylelint-scss": "^3.19.0",
"vue": "^2.6.12", "vue": "^2.6.12",
"vue-template-compiler": "^2.6.12", "vue-template-compiler": "^2.6.12",
"webpack": "^4.46.0" "webpack": "^4.46.0"

View File

@ -0,0 +1 @@
module.exports = [];

View File

@ -561,7 +561,7 @@ export class MySQLClient extends AntaresCore {
return { return {
name: param[1] ? param[1].replaceAll('`', '') : '', name: param[1] ? param[1].replaceAll('`', '') : '',
type: type[0], type: type[0].replaceAll('\n', ''),
length: +type[1], length: +type[1],
context: param[0] ? param[0].replace('\n', '') : '' context: param[0] ? param[0].replace('\n', '') : ''
}; };

View File

@ -109,7 +109,7 @@
<WorkspaceQueryTab <WorkspaceQueryTab
v-for="tab of queryTabs" v-for="tab of queryTabs"
:key="tab.uid" :key="tab.uid"
:tab-uid="tab.uid" :tab="tab"
:is-selected="selectedTab === tab.uid" :is-selected="selectedTab === tab.uid"
:connection="connection" :connection="connection"
/> />
@ -221,7 +221,7 @@ export default {
removeTab: 'workspaces/removeTab' removeTab: 'workspaces/removeTab'
}), }),
addTab () { addTab () {
this.newTab(this.connection.uid); this.newTab({ uid: this.connection.uid });
if (!this.hasWheelEvent) { if (!this.hasWheelEvent) {
this.$refs.tabWrap.addEventListener('wheel', e => { this.$refs.tabWrap.addEventListener('wheel', e => {

View File

@ -2,7 +2,7 @@
<ConfirmModal <ConfirmModal
:confirm-text="$t('word.confirm')" :confirm-text="$t('word.confirm')"
size="medium" size="medium"
@confirm="confirmIndexesChange" @confirm="confirmParametersChange"
@hide="$emit('hide')" @hide="$emit('hide')"
> >
<template :slot="'header'"> <template :slot="'header'">
@ -34,10 +34,10 @@
<div ref="parametersPanel" class="panel-body p-0 pr-1"> <div ref="parametersPanel" class="panel-body p-0 pr-1">
<div <div
v-for="param in parametersProxy" v-for="param in parametersProxy"
:key="param.name" :key="param._id"
class="tile tile-centered c-hand mb-1 p-1" class="tile tile-centered c-hand mb-1 p-1"
:class="{'selected-param': selectedParam === param.name}" :class="{'selected-param': selectedParam === param._id}"
@click="selectParameter($event, param.name)" @click="selectParameter($event, param._id)"
> >
<div class="tile-icon"> <div class="tile-icon">
<div> <div>
@ -54,7 +54,7 @@
<button <button
class="btn btn-link remove-field p-0 mr-2" class="btn btn-link remove-field p-0 mr-2"
:title="$t('word.delete')" :title="$t('word.delete')"
@click.prevent="removeParameter(param.name)" @click.prevent="removeParameter(param._id)"
> >
<i class="mdi mdi-close" /> <i class="mdi mdi-close" />
</button> </button>
@ -139,6 +139,7 @@
</template> </template>
<script> <script>
import { uidGen } from 'common/libs/uidGen';
import ConfirmModal from '@/components/BaseConfirmModal'; import ConfirmModal from '@/components/BaseConfirmModal';
export default { export default {
@ -162,7 +163,7 @@ export default {
}, },
computed: { computed: {
selectedParamObj () { selectedParamObj () {
return this.parametersProxy.find(param => param.name === this.selectedParam); return this.parametersProxy.find(param => param._id === this.selectedParam);
}, },
isChanged () { isChanged () {
return JSON.stringify(this.localParameters) !== JSON.stringify(this.parametersProxy); return JSON.stringify(this.localParameters) !== JSON.stringify(this.parametersProxy);
@ -182,12 +183,12 @@ export default {
window.removeEventListener('resize', this.getModalInnerHeight); window.removeEventListener('resize', this.getModalInnerHeight);
}, },
methods: { methods: {
confirmIndexesChange () { confirmParametersChange () {
this.$emit('parameters-update', this.parametersProxy); this.$emit('parameters-update', this.parametersProxy);
}, },
selectParameter (event, name) { selectParameter (event, uid) {
if (this.selectedParam !== name && !event.target.classList.contains('remove-field')) if (this.selectedParam !== uid && !event.target.classList.contains('remove-field'))
this.selectedParam = name; this.selectedParam = uid;
}, },
getModalInnerHeight () { getModalInnerHeight () {
const modalBody = document.querySelector('.modal-body'); const modalBody = document.querySelector('.modal-body');
@ -196,6 +197,7 @@ export default {
}, },
addParameter () { addParameter () {
this.parametersProxy = [...this.parametersProxy, { this.parametersProxy = [...this.parametersProxy, {
_id: uidGen(),
name: `Param${this.i++}`, name: `Param${this.i++}`,
type: 'INT', type: 'INT',
context: 'IN', context: 'IN',
@ -209,8 +211,8 @@ export default {
this.$refs.parametersPanel.scrollTop = this.$refs.parametersPanel.scrollHeight + 60; this.$refs.parametersPanel.scrollTop = this.$refs.parametersPanel.scrollHeight + 60;
}, 20); }, 20);
}, },
removeParameter (name) { removeParameter (uid) {
this.parametersProxy = this.parametersProxy.filter(param => param.name !== name); this.parametersProxy = this.parametersProxy.filter(param => param._id !== uid);
if (this.selectedParam === name && this.parametersProxy.length) if (this.selectedParam === name && this.parametersProxy.length)
this.resetSelectedID(); this.resetSelectedID();
@ -223,7 +225,7 @@ export default {
this.resetSelectedID(); this.resetSelectedID();
}, },
resetSelectedID () { resetSelectedID () {
this.selectedParam = this.parametersProxy.length ? this.parametersProxy[0].name : ''; this.selectedParam = this.parametersProxy.length ? this.parametersProxy[0]._id : '';
} }
} }
}; };

View File

@ -2,7 +2,7 @@
<ConfirmModal <ConfirmModal
:confirm-text="$t('word.confirm')" :confirm-text="$t('word.confirm')"
size="medium" size="medium"
@confirm="confirmIndexesChange" @confirm="confirmParametersChange"
@hide="$emit('hide')" @hide="$emit('hide')"
> >
<template :slot="'header'"> <template :slot="'header'">
@ -34,10 +34,10 @@
<div ref="parametersPanel" class="panel-body p-0 pr-1"> <div ref="parametersPanel" class="panel-body p-0 pr-1">
<div <div
v-for="param in parametersProxy" v-for="param in parametersProxy"
:key="param.name" :key="param._id"
class="tile tile-centered c-hand mb-1 p-1" class="tile tile-centered c-hand mb-1 p-1"
:class="{'selected-param': selectedParam === param.name}" :class="{'selected-param': selectedParam === param._id}"
@click="selectParameter($event, param.name)" @click="selectParameter($event, param._id)"
> >
<div class="tile-icon"> <div class="tile-icon">
<div> <div>
@ -54,7 +54,7 @@
<button <button
class="btn btn-link remove-field p-0 mr-2" class="btn btn-link remove-field p-0 mr-2"
:title="$t('word.delete')" :title="$t('word.delete')"
@click.prevent="removeParameter(param.name)" @click.prevent="removeParameter(param._id)"
> >
<i class="mdi mdi-close" /> <i class="mdi mdi-close" />
</button> </button>
@ -170,6 +170,7 @@
</template> </template>
<script> <script>
import { uidGen } from 'common/libs/uidGen';
import ConfirmModal from '@/components/BaseConfirmModal'; import ConfirmModal from '@/components/BaseConfirmModal';
export default { export default {
@ -193,7 +194,7 @@ export default {
}, },
computed: { computed: {
selectedParamObj () { selectedParamObj () {
return this.parametersProxy.find(param => param.name === this.selectedParam); return this.parametersProxy.find(param => param._id === this.selectedParam);
}, },
isChanged () { isChanged () {
return JSON.stringify(this.localParameters) !== JSON.stringify(this.parametersProxy); return JSON.stringify(this.localParameters) !== JSON.stringify(this.parametersProxy);
@ -213,12 +214,12 @@ export default {
window.removeEventListener('resize', this.getModalInnerHeight); window.removeEventListener('resize', this.getModalInnerHeight);
}, },
methods: { methods: {
confirmIndexesChange () { confirmParametersChange () {
this.$emit('parameters-update', this.parametersProxy); this.$emit('parameters-update', this.parametersProxy);
}, },
selectParameter (event, name) { selectParameter (event, uid) {
if (this.selectedParam !== name && !event.target.classList.contains('remove-field')) if (this.selectedParam !== uid && !event.target.classList.contains('remove-field'))
this.selectedParam = name; this.selectedParam = uid;
}, },
getModalInnerHeight () { getModalInnerHeight () {
const modalBody = document.querySelector('.modal-body'); const modalBody = document.querySelector('.modal-body');
@ -227,6 +228,7 @@ export default {
}, },
addParameter () { addParameter () {
this.parametersProxy = [...this.parametersProxy, { this.parametersProxy = [...this.parametersProxy, {
_id: uidGen(),
name: `Param${this.i++}`, name: `Param${this.i++}`,
type: 'INT', type: 'INT',
context: 'IN', context: 'IN',
@ -240,8 +242,8 @@ export default {
this.$refs.parametersPanel.scrollTop = this.$refs.parametersPanel.scrollHeight + 60; this.$refs.parametersPanel.scrollTop = this.$refs.parametersPanel.scrollHeight + 60;
}, 20); }, 20);
}, },
removeParameter (name) { removeParameter (uid) {
this.parametersProxy = this.parametersProxy.filter(param => param.name !== name); this.parametersProxy = this.parametersProxy.filter(param => param._id !== uid);
if (this.selectedParam === name && this.parametersProxy.length) if (this.selectedParam === name && this.parametersProxy.length)
this.resetSelectedID(); this.resetSelectedID();
@ -254,7 +256,7 @@ export default {
this.resetSelectedID(); this.resetSelectedID();
}, },
resetSelectedID () { resetSelectedID () {
this.selectedParam = this.parametersProxy.length ? this.parametersProxy[0].name : ''; this.selectedParam = this.parametersProxy.length ? this.parametersProxy[0]._id : '';
} }
} }
}; };

View File

@ -75,6 +75,7 @@
<script> <script>
import { mapGetters, mapActions } from 'vuex'; import { mapGetters, mapActions } from 'vuex';
import { uidGen } from 'common/libs/uidGen';
import BaseLoader from '@/components/BaseLoader'; 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';
@ -183,6 +184,12 @@ export default {
const { status, response } = await Functions.getFunctionInformations(params); const { status, response } = await Functions.getFunctionInformations(params);
if (status === 'success') { if (status === 'success') {
this.originalFunction = response; this.originalFunction = response;
this.originalFunction.parameters = [...this.originalFunction.parameters.map(param => {
param._id = uidGen();
return param;
})];
this.localFunction = JSON.parse(JSON.stringify(this.originalFunction)); this.localFunction = JSON.parse(JSON.stringify(this.originalFunction));
this.sqlProxy = this.localFunction.sql; this.sqlProxy = this.localFunction.sql;
} }

View File

@ -27,7 +27,7 @@
<button <button
class="btn btn-dark btn-sm disabled" class="btn btn-dark btn-sm disabled"
:disabled="isChanged" :disabled="isChanged"
@click="false" @click="runRoutine"
> >
<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" />
@ -75,6 +75,7 @@
<script> <script>
import { mapGetters, mapActions } from 'vuex'; import { mapGetters, mapActions } from 'vuex';
import { uidGen } from 'common/libs/uidGen';
import QueryEditor from '@/components/QueryEditor'; 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';
@ -165,7 +166,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 getRoutineData () { async getRoutineData () {
if (!this.routine) return; if (!this.routine) return;
@ -182,6 +184,12 @@ export default {
const { status, response } = await Routines.getRoutineInformations(params); const { status, response } = await Routines.getRoutineInformations(params);
if (status === 'success') { if (status === 'success') {
this.originalRoutine = response; this.originalRoutine = response;
this.originalRoutine.parameters = [...this.originalRoutine.parameters.map(param => {
param._id = uidGen();
return param;
})];
this.localRoutine = JSON.parse(JSON.stringify(this.originalRoutine)); this.localRoutine = JSON.parse(JSON.stringify(this.originalRoutine));
this.sqlProxy = this.localRoutine.sql; this.sqlProxy = this.localRoutine.sql;
} }
@ -249,6 +257,23 @@ export default {
parametersUpdate (parameters) { parametersUpdate (parameters) {
this.localRoutine = { ...this.localRoutine, parameters }; this.localRoutine = { ...this.localRoutine, parameters };
}, },
runRoutine () { // TODO: create ask for params modal
let sql;
switch (this.connection.client) { // TODO: move in a better place
case 'maria':
case 'mysql':
case 'pg':
sql = `CALL \`${this.originalRoutine.name}\` ()`;
break;
case 'mssql':
sql = `EXEC ${this.originalRoutine.name}`;
break;
default:
sql = `CALL \`${this.originalRoutine.name}\` ()`;
}
this.newTab({ uid: this.connection.uid, content: sql, autorun: !this.originalRoutine.parameters.length });
},
showOptionsModal () { showOptionsModal () {
this.isOptionsModal = true; this.isOptionsModal = true;
}, },

View File

@ -48,7 +48,7 @@
v-show="!isQuering" v-show="!isQuering"
ref="queryTable" ref="queryTable"
:results="results" :results="results"
:tab-uid="tabUid" :tab-uid="tab.uid"
:conn-uid="connection.uid" :conn-uid="connection.uid"
mode="query" mode="query"
@update-field="updateField" @update-field="updateField"
@ -74,7 +74,7 @@ export default {
mixins: [tableTabs], mixins: [tableTabs],
props: { props: {
connection: Object, connection: Object,
tabUid: String, tab: Object,
isSelected: Boolean isSelected: Boolean
}, },
data () { data () {
@ -101,6 +101,8 @@ export default {
} }
}, },
created () { created () {
this.query = this.tab.content;
window.addEventListener('keydown', this.onKey); window.addEventListener('keydown', this.onKey);
}, },
mounted () { mounted () {
@ -112,6 +114,9 @@ export default {
window.addEventListener('mousemove', this.resize); window.addEventListener('mousemove', this.resize);
window.addEventListener('mouseup', this.stopResize); window.addEventListener('mouseup', this.stopResize);
}); });
if (this.tab.autorun)
this.runQuery(this.query);
}, },
beforeDestroy () { beforeDestroy () {
window.removeEventListener('keydown', this.onKey); window.removeEventListener('keydown', this.onKey);

View File

@ -152,7 +152,7 @@ export default {
} }
: workspace); : workspace);
}, },
NEW_TAB (state, { uid, tab }) { NEW_TAB (state, { uid, tab, content, autorun }) {
tabIndex[uid] = tabIndex[uid] ? ++tabIndex[uid] : 1; tabIndex[uid] = tabIndex[uid] ? ++tabIndex[uid] : 1;
const newTab = { const newTab = {
uid: tab, uid: tab,
@ -160,7 +160,9 @@ export default {
selected: false, selected: false,
type: 'query', type: 'query',
fields: [], fields: [],
keyUsage: [] keyUsage: [],
content: content || '',
autorun: !!autorun
}; };
state.workspaces = state.workspaces.map(workspace => { state.workspaces = state.workspaces.map(workspace => {
if (workspace.uid === uid) { if (workspace.uid === uid) {
@ -392,7 +394,7 @@ export default {
commit('ADD_WORKSPACE', workspace); commit('ADD_WORKSPACE', workspace);
if (getters.getWorkspace(uid).tabs.length < 3) if (getters.getWorkspace(uid).tabs.length < 3)
dispatch('newTab', uid); dispatch('newTab', { uid });
dispatch('setUnsavedChanges', false); dispatch('setUnsavedChanges', false);
}, },
@ -430,10 +432,10 @@ export default {
setSearchTerm ({ commit, getters }, term) { setSearchTerm ({ commit, getters }, term) {
commit('SET_SEARCH_TERM', { uid: getters.getSelected, term }); commit('SET_SEARCH_TERM', { uid: getters.getSelected, term });
}, },
newTab ({ commit }, uid) { newTab ({ commit }, { uid, content, autorun }) {
const tab = uidGen('T'); const tab = uidGen('T');
commit('NEW_TAB', { uid, tab }); commit('NEW_TAB', { uid, tab, content, autorun });
commit('SELECT_TAB', { uid, tab }); commit('SELECT_TAB', { uid, tab });
}, },
removeTab ({ commit }, payload) { removeTab ({ commit }, payload) {