feat: scheduler edit

This commit is contained in:
Fabio Di Stasio 2021-01-15 19:18:16 +01:00
parent 1e7d4ca347
commit ceab4ef243
10 changed files with 255 additions and 46 deletions

View File

@ -676,7 +676,7 @@ export class MySQLClient extends AntaresCore {
return results.rows.map(row => {
const schedule = row['Create Event'].match(/(?<=ON SCHEDULE\n*?\s*?).*?(?=\n)/gs)[0];
const execution = schedule.includes('EVERY') ? 'EVERY' : 'ONCE';
const every = execution === 'EVERY' ? row['Create Event'].match(/(?<=EVERY )(\s*(\w+)){0,2}/gs)[0].split(' ') : [];
const every = execution === 'EVERY' ? row['Create Event'].match(/(?<=EVERY )(\s*([^\s]+)){0,2}/gs)[0].replaceAll('\'', '').split(' ') : [];
const starts = execution === 'EVERY' && schedule.includes('STARTS') ? schedule.match(/(?<=STARTS ').*?(?='\s)/gs)[0] : '';
const ends = execution === 'EVERY' && schedule.includes('ENDS') ? schedule.match(/(?<=ENDS ').*?(?='\s)/gs)[0] : '';
const at = execution === 'ONCE' && schedule.includes('AT') ? schedule.match(/(?<=AT ').*?(?='\s)/gs)[0] : '';
@ -716,18 +716,22 @@ export class MySQLClient extends AntaresCore {
*/
async alterEvent (params) {
const { scheduler } = params;
const tempProcedure = Object.assign({}, scheduler);
tempProcedure.name = `Antares_${tempProcedure.name}_tmp`;
try {
await this.createEvent(tempProcedure);
await this.dropEvent({ scheduler: tempProcedure.name });
await this.dropEvent({ scheduler: scheduler.oldName });
await this.createEvent(scheduler);
}
catch (err) {
return Promise.reject(err);
}
if (scheduler.execution === 'EVERY' && scheduler.every[0].includes('-'))
scheduler.every[0] = `'${scheduler.every[0]}'`;
const sql = `ALTER ${scheduler.definer ? ` DEFINER=${scheduler.definer}` : ''} EVENT \`${scheduler.oldName}\`
ON SCHEDULE
${scheduler.execution === 'EVERY'
? `EVERY ${scheduler.every.join(' ')}${scheduler.starts ? ` STARTS '${scheduler.starts}'` : ''}${scheduler.ends ? ` ENDS '${scheduler.ends}'` : ''}`
: `AT '${scheduler.at}'`}
ON COMPLETION${!scheduler.preserve ? ' NOT' : ''} PRESERVE
${scheduler.name !== scheduler.oldName ? `RENAME TO \`${scheduler.name}\`` : ''}
${scheduler.state}
COMMENT '${scheduler.comment}'
DO ${scheduler.sql}`;
return await this.raw(sql);
}
/**

View File

@ -15,7 +15,7 @@
<form class="form-horizontal">
<div class="form-group">
<div class="col-3">
<label class="form-label">{{ $t('word.user') }}:</label>
<label class="form-label">{{ $t('word.user') }}</label>
</div>
<div class="col-9">
<input
@ -28,7 +28,7 @@
</div>
<div class="form-group">
<div class="col-3">
<label class="form-label">{{ $t('word.password') }}:</label>
<label class="form-label">{{ $t('word.password') }}</label>
</div>
<div class="col-9">
<input

View File

@ -16,7 +16,7 @@
<fieldset class="m-0" :disabled="isTesting">
<div class="form-group">
<div class="col-4 col-sm-12">
<label class="form-label">{{ $t('word.connectionName') }}:</label>
<label class="form-label">{{ $t('word.connectionName') }}</label>
</div>
<div class="col-8 col-sm-12">
<input
@ -29,7 +29,7 @@
</div>
<div class="form-group">
<div class="col-4 col-sm-12">
<label class="form-label">{{ $t('word.client') }}:</label>
<label class="form-label">{{ $t('word.client') }}</label>
</div>
<div class="col-8 col-sm-12">
<select v-model="localConnection.client" class="form-select">
@ -53,7 +53,7 @@
</div>
<div class="form-group">
<div class="col-4 col-sm-12">
<label class="form-label">{{ $t('word.hostName') }}/IP:</label>
<label class="form-label">{{ $t('word.hostName') }}/IP</label>
</div>
<div class="col-8 col-sm-12">
<input
@ -65,7 +65,7 @@
</div>
<div class="form-group">
<div class="col-4 col-sm-12">
<label class="form-label">{{ $t('word.port') }}:</label>
<label class="form-label">{{ $t('word.port') }}</label>
</div>
<div class="col-8 col-sm-12">
<input
@ -79,7 +79,7 @@
</div>
<div class="form-group">
<div class="col-4 col-sm-12">
<label class="form-label">{{ $t('word.user') }}:</label>
<label class="form-label">{{ $t('word.user') }}</label>
</div>
<div class="col-8 col-sm-12">
<input
@ -92,7 +92,7 @@
</div>
<div class="form-group">
<div class="col-4 col-sm-12">
<label class="form-label">{{ $t('word.password') }}:</label>
<label class="form-label">{{ $t('word.password') }}</label>
</div>
<div class="col-8 col-sm-12">
<input

View File

@ -15,7 +15,7 @@
<form class="form-horizontal">
<div class="form-group">
<div class="col-3">
<label class="form-label">{{ $t('word.name') }}:</label>
<label class="form-label">{{ $t('word.name') }}</label>
</div>
<div class="col-9">
<input
@ -30,7 +30,7 @@
</div>
<div class="form-group">
<div class="col-3">
<label class="form-label">{{ $t('word.collation') }}:</label>
<label class="form-label">{{ $t('word.collation') }}</label>
</div>
<div class="col-9">
<select

View File

@ -16,7 +16,7 @@
<fieldset class="m-0" :disabled="isTesting">
<div class="form-group">
<div class="col-4 col-sm-12">
<label class="form-label">{{ $t('word.connectionName') }}:</label>
<label class="form-label">{{ $t('word.connectionName') }}</label>
</div>
<div class="col-8 col-sm-12">
<input
@ -29,7 +29,7 @@
</div>
<div class="form-group">
<div class="col-4 col-sm-12">
<label class="form-label">{{ $t('word.client') }}:</label>
<label class="form-label">{{ $t('word.client') }}</label>
</div>
<div class="col-8 col-sm-12">
<select
@ -57,7 +57,7 @@
</div>
<div class="form-group">
<div class="col-4 col-sm-12">
<label class="form-label">{{ $t('word.hostName') }}/IP:</label>
<label class="form-label">{{ $t('word.hostName') }}/IP</label>
</div>
<div class="col-8 col-sm-12">
<input
@ -69,7 +69,7 @@
</div>
<div class="form-group">
<div class="col-4 col-sm-12">
<label class="form-label">{{ $t('word.port') }}:</label>
<label class="form-label">{{ $t('word.port') }}</label>
</div>
<div class="col-8 col-sm-12">
<input
@ -83,7 +83,7 @@
</div>
<div class="form-group">
<div class="col-4 col-sm-12">
<label class="form-label">{{ $t('word.user') }}:</label>
<label class="form-label">{{ $t('word.user') }}</label>
</div>
<div class="col-8 col-sm-12">
<input
@ -96,7 +96,7 @@
</div>
<div class="form-group">
<div class="col-4 col-sm-12">
<label class="form-label">{{ $t('word.password') }}:</label>
<label class="form-label">{{ $t('word.password') }}</label>
</div>
<div class="col-8 col-sm-12">
<input

View File

@ -15,7 +15,7 @@
<form class="form-horizontal">
<div class="form-group">
<div class="col-3">
<label class="form-label">{{ $t('word.name') }}:</label>
<label class="form-label">{{ $t('word.name') }}</label>
</div>
<div class="col-9">
<input
@ -30,7 +30,7 @@
</div>
<div class="form-group">
<div class="col-3">
<label class="form-label">{{ $t('word.collation') }}:</label>
<label class="form-label">{{ $t('word.collation') }}</label>
</div>
<div class="col-9">
<select v-model="database.collation" class="form-select">

View File

@ -56,7 +56,7 @@
<div class="col-6 col-sm-12">
<label class="form-label">
<i class="mdi mdi-18px mdi-translate mr-1" />
{{ $t('word.language') }}:
{{ $t('word.language') }}
</label>
</div>
<div class="col-6 col-sm-12">
@ -78,7 +78,7 @@
<div class="form-group">
<div class="col-6 col-sm-12">
<label class="form-label">
{{ $t('message.notificationsTimeout') }}:
{{ $t('message.notificationsTimeout') }}
</label>
</div>
<div class="col-6 col-sm-12">
@ -103,7 +103,7 @@
<div class="form-group">
<div class="col-6 col-sm-12">
<label class="form-label">
{{ $t('word.autoCompletion') }}:
{{ $t('word.autoCompletion') }}
</label>
</div>
<div class="col-6 col-sm-12">
@ -118,7 +118,7 @@
<div class="form-group">
<div class="col-6 col-sm-12">
<label class="form-label">
{{ $t('message.wrapLongLines') }}:
{{ $t('message.wrapLongLines') }}
</label>
</div>
<div class="col-6 col-sm-12">
@ -205,9 +205,9 @@
<img :src="require('@/images/logo.svg').default" width="128">
<h4>{{ appName }}</h4>
<p>
{{ $t('word.version') }}: {{ appVersion }}<br>
{{ $t('word.version') }} {{ appVersion }}<br>
<a class="c-hand" @click="openOutside('https://github.com/Fabio286/antares')">GitHub</a> | <a class="c-hand" @click="openOutside('https://github.com/Fabio286/antares/blob/master/CHANGELOG.md')">CHANGELOG</a><br>
<small>{{ $t('word.author') }}: <a class="c-hand" @click="openOutside('https://github.com/Fabio286')">Fabio Di Stasio</a></small><br>
<small>{{ $t('word.author') }} <a class="c-hand" @click="openOutside('https://github.com/Fabio286')">Fabio Di Stasio</a></small><br>
<small>{{ $t('message.madeWithJS') }}</small>
</p>
</div>

View File

@ -0,0 +1,190 @@
<template>
<ConfirmModal
:confirm-text="$t('word.confirm')"
size="400"
@confirm="confirmOptionsChange"
@hide="$emit('hide')"
>
<template :slot="'header'">
<div class="d-flex">
<i class="mdi mdi-24px mdi-timer mr-1" /> {{ $t('word.timing') }} "{{ localOptions.name }}"
</div>
</template>
<div :slot="'body'">
<form class="form-horizontal">
<div class="form-group">
<label class="form-label col-4">
{{ $t('word.execution') }}
</label>
<div class="column">
<select
ref="firstInput"
v-model="optionsProxy.execution"
class="form-select"
>
<option>EVERY</option>
<option>ONCE</option>
</select>
</div>
</div>
<div v-if="optionsProxy.execution === 'EVERY'">
<div class="form-group">
<div class="col-4" />
<div class="column">
<div class="input-group">
<input
v-model="optionsProxy.every[0]"
class="form-input"
type="text"
@keypress="isNumberOrMinus($event)"
>
<select
v-model="optionsProxy.every[1]"
class="form-select text-uppercase"
style="width: 0;"
>
<option>YEAR</option>
<option>QUARTER</option>
<option>MONTH</option>
<option>WEEK</option>
<option>DAY</option>
<option>HOUR</option>
<option>MINUTE</option>
<option>SECOND</option>
<option>YEAR_MONTH</option>
<option>DAY_HOUR</option>
<option>DAY_MINUTE</option>
<option>DAY_SECOND</option>
<option>HOUR_MINUTE</option>
<option>HOUR_SECOND</option>
<option>MINUTE_SECOND</option>
</select>
</div>
</div>
</div>
<div class="form-group">
<label class="form-label col-4">
{{ $t('word.starts') }}
</label>
<div class="column">
<div class="input-group">
<label class="form-checkbox">
<input v-model="hasStart" type="checkbox"><i class="form-icon" />
</label>
<input
v-model="optionsProxy.starts"
v-mask="'####-##-## ##:##:##'"
type="text"
class="form-input"
>
<span class="input-group-addon p-vcentered">
<i class="form-icon mdi mdi-calendar" />
</span>
</div>
</div>
</div>
<div class="form-group">
<label class="form-label col-4">
{{ $t('word.ends') }}
</label>
<div class="column">
<div class="input-group">
<label class="form-checkbox">
<input v-model="hasEnd" type="checkbox"><i class="form-icon" />
</label>
<input
v-model="optionsProxy.ends"
v-mask="'####-##-## ##:##:##'"
type="text"
class="form-input"
>
<span class="input-group-addon p-vcentered">
<i class="form-icon mdi mdi-calendar" />
</span>
</div>
</div>
</div>
</div>
<div v-else>
<div class="form-group">
<div class="col-4" />
<div class="column">
<div class="input-group">
<input
v-model="optionsProxy.at"
v-mask="'####-##-## ##:##:##'"
type="text"
class="form-input"
>
<span class="input-group-addon p-vcentered">
<i class="form-icon mdi mdi-calendar" />
</span>
</div>
</div>
</div>
</div>
<div class="form-group">
<div class="col-4" />
<div class="column">
<label class="form-checkbox form-inline mt-2">
<input v-model="optionsProxy.preserve" type="checkbox"><i class="form-icon" /> {{ $t('message.preserveOnCompletion') }}
</label>
</div>
</div>
</form>
</div>
</ConfirmModal>
</template>
<script>
import ConfirmModal from '@/components/BaseConfirmModal';
import { mask } from 'vue-the-mask';
import moment from 'moment';
export default {
name: 'WorkspacePropsSchedulerTimingModal',
components: {
ConfirmModal
},
directives: {
mask
},
props: {
localOptions: Object,
workspace: Object
},
data () {
return {
optionsProxy: {},
isOptionsChanging: false,
hasStart: false,
hasEnd: false
};
},
created () {
this.optionsProxy = JSON.parse(JSON.stringify(this.localOptions));
this.hasStart = !!this.optionsProxy.starts;
this.hasEnd = !!this.optionsProxy.ends;
if (!this.optionsProxy.at) this.optionsProxy.at = moment().format('YYYY-MM-DD HH:mm:ss');
if (!this.optionsProxy.every.length) this.optionsProxy.every = ['1', 'DAY'];
setTimeout(() => {
this.$refs.firstInput.focus();
}, 20);
},
methods: {
confirmOptionsChange () {
if (!this.hasStart) this.optionsProxy.starts = '';
if (!this.hasEnd) this.optionsProxy.ends = '';
this.$emit('options-update', this.optionsProxy);
},
isNumberOrMinus (event) {
if (!/\d/.test(event.key) && event.key !== '-')
return event.preventDefault();
}
}
};
</script>

View File

@ -23,7 +23,7 @@
</button>
<div class="divider-vert py-3" />
<button class="btn btn-dark btn-sm" @click="false">
<button class="btn btn-dark btn-sm" @click="showTimingModal">
<span>{{ $t('word.timing') }}</span>
<i class="mdi mdi-24px mdi-timer ml-1" />
</button>
@ -82,13 +82,6 @@
</div>
</div>
</div>
<div class="columns">
<!-- <div class="column"> TODO: move in timing modal
<label class="form-checkbox form-inline">
<input v-model="localScheduler.preserve" type="checkbox"><i class="form-icon" /> {{ $t('message.preserveOnCompletion') }}
</label>
</div> -->
</div>
<div class="columns">
<div class="column">
<div class="form-group">
@ -132,18 +125,27 @@
:height="editorHeight"
/>
</div>
<WorkspacePropsSchedulerTimingModal
v-if="isTimingModal"
:local-options="localScheduler"
:workspace="workspace"
@hide="hideTimingModal"
@options-update="timingUpdate"
/>
</div>
</template>
<script>
import { mapGetters, mapActions } from 'vuex';
import QueryEditor from '@/components/QueryEditor';
import WorkspacePropsSchedulerTimingModal from '@/components/WorkspacePropsSchedulerTimingModal';
import Schedulers from '@/ipc-api/Schedulers';
export default {
name: 'WorkspacePropsTabScheduler',
components: {
QueryEditor
QueryEditor,
WorkspacePropsSchedulerTimingModal
},
props: {
connection: Object,
@ -154,6 +156,7 @@ export default {
tabUid: 'prop',
isQuering: false,
isSaving: false,
isTimingModal: false,
originalScheduler: null,
localScheduler: { sql: '' },
lastScheduler: null,
@ -295,6 +298,15 @@ export default {
this.editorHeight = size;
this.$refs.queryEditor.editor.resize();
}
},
showTimingModal () {
this.isTimingModal = true;
},
hideTimingModal () {
this.isTimingModal = false;
},
timingUpdate (options) {
this.localScheduler = options;
}
}
};

View File

@ -82,7 +82,10 @@ module.exports = {
export: 'Export',
returns: 'Returns',
timing: 'Timing',
state: 'State'
state: 'State',
execution: 'Execution',
starts: 'Starts',
ends: 'Ends'
},
message: {
appWelcome: 'Welcome to Antares SQL Client!',