mirror of https://github.com/nocodb/nocodb
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
421 lines
16 KiB
421 lines
16 KiB
4 years ago
|
<template>
|
||
|
<div style="height:100%">
|
||
|
<v-tabs @change="this.loadCrons()" height="30" v-model="dbsTab">
|
||
|
<template v-for="db in dbAliasList">
|
||
|
<v-tab :key="db.meta.dbAlias" class="text-capitalize caption">{{ db.connection.database }}
|
||
|
({{ db.meta.dbAlias }})
|
||
|
</v-tab>
|
||
|
<v-tab-item :key="db.meta.dbAlias" style="height:100%">
|
||
|
<!-- <v-toolbar flat height="42" class="toolbar-border-bottom">
|
||
|
<v-toolbar-title>
|
||
|
<v-breadcrumbs :items="[ ]" divider=">" dark large light class="title">
|
||
|
<template v-slot:divider>
|
||
|
<v-icon small color="grey lighten-2">forward</v-icon>
|
||
|
</template>
|
||
|
</v-breadcrumbs>
|
||
|
</v-toolbar-title>
|
||
|
<v-spacer></v-spacer>
|
||
|
<x-btn outlined tooltip="Reload list" small @click="loadCrons()" color="primary" icon="refresh">Reload
|
||
|
</x-btn>
|
||
|
<x-btn outlined tooltip="Add new cron job" small @click="addNewCron()" color="primary" icon="mdi-plus">New
|
||
|
Cron
|
||
|
</x-btn>
|
||
|
<x-btn outlined :loading="updating" :disabled="updating || !selectedItem" tooltip="Save Changes" small
|
||
|
@click="saveCron()"
|
||
|
color="primary" icon="save">Save
|
||
|
</x-btn>
|
||
|
|
||
|
</v-toolbar>-->
|
||
|
<v-card style="height:calc(100% - 42px)">
|
||
|
<v-container style="height: 100%" fluid>
|
||
|
<!-- <div class="d-flex d-100 justify-center">-->
|
||
|
<v-row style="height:100%">
|
||
|
<v-col cols="6">
|
||
|
<v-card class="pt-5 h-100">
|
||
|
|
||
|
<div style="position: relative; " class="mb-4">
|
||
|
<h4 class="text-center" :class="{
|
||
|
'grey--text text--darken-2' : !$store.state.windows.darkTheme
|
||
|
}">Cron Job List</h4>
|
||
|
|
||
|
<div style="position: absolute; right:5px;bottom:0">
|
||
|
<x-btn outlined tooltip="Reload list" small @click="loadCrons()" color="primary" icon="refresh">
|
||
|
Reload
|
||
|
</x-btn>
|
||
|
<x-btn outlined tooltip="Add new cron job" small @click="addNewCron()" color="primary"
|
||
|
icon="mdi-plus">New
|
||
|
Cron
|
||
|
</x-btn>
|
||
|
</div>
|
||
|
</div>
|
||
|
|
||
|
<v-text-field v-if="dbAliasList && dbAliasList[dbsTab]" v-model="filter" dense hide-details
|
||
|
class="my-2 mx-auto"
|
||
|
:placeholder="`Filter '${dbAliasList[dbsTab].connection.database}' scheduled cron jobs`"
|
||
|
prepend-inner-icon="search"
|
||
|
style="max-width:500px"
|
||
|
outlined></v-text-field>
|
||
|
|
||
|
<v-simple-table dense v-slot:default style="min-width: 400px">
|
||
|
<thead>
|
||
|
<tr>
|
||
|
<th class="text-center">#</th>
|
||
|
<th>Cron Title</th>
|
||
|
<th>Actions</th>
|
||
|
</tr>
|
||
|
</thead>
|
||
|
<tbody>
|
||
|
<tr v-if="crons && !crons.length">
|
||
|
<td class="caption text-center" colspan="3">
|
||
|
No cron jobs are found
|
||
|
</td>
|
||
|
</tr>
|
||
|
|
||
|
<tr v-for="(cron,i) in crons" :key="`${cron.title}-${cron.id}`"
|
||
|
v-if="!filter || (cron.title && cron.title.toLowerCase().indexOf(filter.toLowerCase()) > -1)"
|
||
|
@click="editCronHandler(cron)"
|
||
|
class="pointer"
|
||
|
>
|
||
|
<td>
|
||
|
<v-radio-group dense hide-details v-model="selectedItemIndex" class="mt-n2">
|
||
|
<v-radio :value="i"
|
||
|
></v-radio>
|
||
|
</v-radio-group>
|
||
|
</td>
|
||
|
<td>{{ cron.title }}</td>
|
||
|
<td>
|
||
|
<!-- <v-icon small @click="editCronHandler(cron)">mdi-pencil</v-icon>-->
|
||
|
<x-icon tooltip="Delete cron job" class="ml-2" color="error" @click.stop="deleteCron(cron)"
|
||
|
small>mdi-delete
|
||
|
</x-icon>
|
||
|
</td>
|
||
|
</tr>
|
||
|
</tbody>
|
||
|
</v-simple-table>
|
||
|
</v-card>
|
||
|
</v-col>
|
||
|
<v-col cols="6" v-if="selectedItem" style="height:100%; overflow: auto">
|
||
|
<v-card class="px-4 py-2" style="min-height: 100%">
|
||
|
<v-row class="mt-3">
|
||
|
<v-col cols="12" class="edit-header">
|
||
|
<h4 class="text-center text-capitalize mt-2 d-100" :class="{
|
||
|
'grey--text text--darken-2' : !$store.state.windows.darkTheme
|
||
|
}">{{ selectedItem.title }}</h4>
|
||
|
<div class="save-btn">
|
||
|
<x-btn outlined :loading="updating" :disabled="updating || !selectedItem"
|
||
|
tooltip="Save Changes" small
|
||
|
@click="saveCron()"
|
||
|
color="primary" icon="save">Save
|
||
|
</x-btn>
|
||
|
</div>
|
||
|
<v-switch
|
||
|
class="enable-disable-switch"
|
||
|
inset
|
||
|
dense
|
||
|
hide-details
|
||
|
v-model="selectedItem.active"
|
||
|
:label="selectedItem.active ? 'Enabled' : 'Disabled' "
|
||
|
></v-switch>
|
||
|
</v-col>
|
||
|
<!-- <v-col cols="12">-->
|
||
|
<!-- <v-switch-->
|
||
|
<!-- inset-->
|
||
|
<!-- dense-->
|
||
|
<!-- hide-details-->
|
||
|
<!-- v-model="selectedItem.active"-->
|
||
|
<!-- :label="selectedItem.active ? 'Enabled' : 'Disabled' "-->
|
||
|
<!-- ></v-switch>-->
|
||
|
<!-- </v-col>-->
|
||
|
<v-col cols="12">
|
||
|
<v-text-field auto
|
||
|
dense
|
||
|
hide-details
|
||
|
v-model="selectedItem.title"
|
||
|
outlined label="Title"></v-text-field>
|
||
|
</v-col>
|
||
|
<v-col cols="6">
|
||
|
<v-text-field
|
||
|
dense
|
||
|
hide-details
|
||
|
v-model="selectedItem.pattern"
|
||
|
outlined label="Pattern"></v-text-field>
|
||
|
<span class="caption grey--text">Generate pattern from <a target="_blank"
|
||
|
href="http://corntab.com/"
|
||
|
class="grey--text">http://corntab.com/</a></span>
|
||
|
</v-col>
|
||
|
<v-col cols="6">
|
||
|
<v-text-field
|
||
|
dense
|
||
|
hide-details
|
||
|
v-model="selectedItem.timezone"
|
||
|
outlined label="Timezone"></v-text-field>
|
||
|
<span class="caption grey--text" target="_blank">All timezones available at <a
|
||
|
href="https://momentjs.com/timezone/" class="grey--text">Moment Timezone Website</a>.</span>
|
||
|
|
||
|
</v-col>
|
||
|
|
||
|
<v-col cols="12">
|
||
|
<v-tabs height="30">
|
||
|
<v-tab><span class="caption text-capitalize">Handler</span></v-tab>
|
||
|
<v-tab-item class="pt-2">
|
||
|
<label class="caption grey--text">Cron handler</label>
|
||
|
<monaco-ts-editor v-model="selectedItem.cron_handler"
|
||
|
style="height : 400px"></monaco-ts-editor>
|
||
|
</v-tab-item>
|
||
|
|
||
|
<v-tab><span class="caption text-capitalize">Webhook</span></v-tab>
|
||
|
|
||
|
<v-tab-item class="pt-3">
|
||
|
<v-overlay absolute>
|
||
|
<div class="text-center">Coming Soon...</div>
|
||
|
</v-overlay>
|
||
|
<v-text-field
|
||
|
dense
|
||
|
outlined
|
||
|
label="Webhook url"
|
||
|
type="url"
|
||
|
v-model="selectedItem.webhook"
|
||
|
></v-text-field>
|
||
|
</v-tab-item>
|
||
|
</v-tabs>
|
||
|
</v-col>
|
||
|
<!-- <v-col cols="12">-->
|
||
|
<!-- <v-textarea-->
|
||
|
<!-- dense-->
|
||
|
<!-- hide-details-->
|
||
|
<!-- v-model="selectedItem.description"-->
|
||
|
<!-- dense outlined label="Description"></v-textarea>-->
|
||
|
<!-- </v-col>-->
|
||
|
<!--
|
||
|
<v-col cols="6">
|
||
|
<v-text-field auto
|
||
|
dense
|
||
|
hide-details
|
||
|
v-model="selectedItem.env"
|
||
|
dense outlined label="Environment"></v-text-field>
|
||
|
</v-col>
|
||
|
|
||
|
|
||
|
<v-col cols="6">
|
||
|
<v-text-field auto
|
||
|
dense
|
||
|
hide-details
|
||
|
v-model="selectedItem"
|
||
|
dense outlined label="Timeout(in milliseconds)" type="number"
|
||
|
step="1000"></v-text-field>
|
||
|
</v-col>
|
||
|
<v-col cols="6">
|
||
|
<v-text-field auto dense outlined label="Retry" type="number"
|
||
|
step="1"></v-text-field>
|
||
|
</v-col>
|
||
|
<v-col cols="6">
|
||
|
<v-text-field auto dense outlined label="Retry interval(in milliseconds)" type="number"
|
||
|
step="1000"></v-text-field>
|
||
|
</v-col>-->
|
||
|
</v-row>
|
||
|
</v-card>
|
||
|
</v-col>
|
||
|
</v-row>
|
||
|
|
||
|
</v-container>
|
||
|
</v-card>
|
||
|
<!-- </div>-->
|
||
|
</v-tab-item>
|
||
|
</template>
|
||
|
</v-tabs>
|
||
|
</div>
|
||
|
</template>
|
||
|
|
||
|
<script>
|
||
|
import {mapGetters} from "vuex";
|
||
|
import MonacoJsonEditor from "@/components/monaco/MonacoJsonEditor";
|
||
|
import MonacoTsEditor from "@/components/monaco/MonacoTsEditor";
|
||
|
|
||
|
export default {
|
||
|
name: "cron-jobs",
|
||
|
components: {MonacoTsEditor, MonacoJsonEditor},
|
||
|
data: () => ({
|
||
|
edited: false,
|
||
|
crons: null,
|
||
|
updating: false,
|
||
|
dbsTab: 0,
|
||
|
filter: '',
|
||
|
selectedItem: null
|
||
|
}),
|
||
|
props: ['nodes'],
|
||
|
async mounted() {
|
||
|
await this.loadCrons()
|
||
|
},
|
||
|
methods: {
|
||
|
async editCronHandler(cron) {
|
||
|
this.selectedItem = cron;
|
||
|
},
|
||
|
async deleteCron(cron) {
|
||
|
if (cron.id) {
|
||
|
await this.$store.dispatch('sqlMgr/ActSqlOp', [{
|
||
|
dbAlias: this.dbAliasList[this.dbsTab].meta.dbAlias,
|
||
|
env: this.$store.getters['project/GtrEnv']
|
||
|
}, 'cronDelete', {
|
||
|
id: cron.id
|
||
|
}]);
|
||
|
await this.loadCrons();
|
||
|
} else {
|
||
|
this.crons.splice(this.crons.indexOf(cron), 1)
|
||
|
}
|
||
|
if (cron === this.selectedItem) {
|
||
|
this.selectedItem = null;
|
||
|
}
|
||
|
},
|
||
|
async addNewCron() {
|
||
|
this.crons = this.crons || [];
|
||
|
this.crons.push(this.selectedItem = {
|
||
|
title: 'cron_job' + this.crons.length,
|
||
|
pattern: '* * * * * *',
|
||
|
timezone: 'America/Los_Angeles',
|
||
|
active: true,
|
||
|
cron_handler: ''
|
||
|
})
|
||
|
},
|
||
|
async loadCrons() {
|
||
|
this.crons = await this.$store.dispatch('sqlMgr/ActSqlOp', [{
|
||
|
dbAlias: this.dbAliasList[this.dbsTab].meta.dbAlias,
|
||
|
env: this.$store.getters['project/GtrEnv']
|
||
|
}, 'xcCronList']);
|
||
|
if (this.selectedItem) {
|
||
|
this.selectedItem = this.crons.find(c => c.title === this.selectedItem.title);
|
||
|
}
|
||
|
this.edited = false;
|
||
|
}
|
||
|
, async saveCron() {
|
||
|
this.updating = true;
|
||
|
let errorCrons = [];
|
||
|
try {
|
||
|
|
||
|
const saveList = this.crons.filter(cron => {
|
||
|
if (cron === this.selectedItem || !cron.id) {
|
||
|
if (cron.cron_handler.trim() && cron.webhook) {
|
||
|
errorCrons.push(`'${cron.title}'`)
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
})
|
||
|
|
||
|
|
||
|
// await this.$store.dispatch('sqlMgr/ActSqlOp', [{
|
||
|
// dbAlias: this.dbAliasList[this.dbsTab].meta.dbAlias,
|
||
|
// env: this.$store.getters['project/GtrEnv']
|
||
|
// }, 'xcCronSave', this.selectedItem]);
|
||
|
if (!errorCrons.length) {
|
||
|
for (const cron of saveList) {
|
||
|
// if (cron !== this.selectedItem && !cron.id) {
|
||
|
await this.$store.dispatch('sqlMgr/ActSqlOp', [{
|
||
|
dbAlias: this.dbAliasList[this.dbsTab].meta.dbAlias,
|
||
|
env: this.$store.getters['project/GtrEnv']
|
||
|
}, 'xcCronSave', cron]);
|
||
|
// }
|
||
|
}
|
||
|
|
||
|
await this.loadCrons();
|
||
|
|
||
|
this.$toast.success('Cron job saved successfully').goAway(3000);
|
||
|
} else {
|
||
|
this.$toast.error(`${errorCrons.join(', ')} cron jobs<br> have both webhook and handler, please remove one of them.`).goAway(10000)
|
||
|
}
|
||
|
} catch (e) {
|
||
|
this.$toast.error('Some error occurred').goAway(3000);
|
||
|
console.log(e, e.message);
|
||
|
}
|
||
|
this.updating = false;
|
||
|
this.edited = false;
|
||
|
}
|
||
|
},
|
||
|
computed: {
|
||
|
...mapGetters({
|
||
|
dbAliasList: 'project/GtrDbAliasList'
|
||
|
}),
|
||
|
enableCountText() {
|
||
|
return ''
|
||
|
},
|
||
|
selectedItemIndex: {
|
||
|
get() {
|
||
|
return this.crons ? this.crons.indexOf(this.selectedItem) : -1;
|
||
|
}, set(i) {
|
||
|
this.selectedItem = this.crons[i];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
</script>
|
||
|
|
||
|
<style scoped lang="scss">
|
||
|
::v-deep {
|
||
|
.v-tabs-bar {
|
||
|
border-bottom: solid 1px var(--v-primary-lighten2);
|
||
|
}
|
||
|
|
||
|
.v-tab {
|
||
|
border-right: 1px solid var(--v-primary-lighten2);
|
||
|
}
|
||
|
|
||
|
.v-input .v-input__slot fieldset legend {
|
||
|
margin-left: 8px;
|
||
|
}
|
||
|
|
||
|
.v-tabs {
|
||
|
height: 100%;
|
||
|
|
||
|
.v-tabs-items {
|
||
|
height: calc(100% - 30px);
|
||
|
|
||
|
.v-window__container {
|
||
|
height: 100%;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
.edit-header {
|
||
|
position: relative;
|
||
|
width: 100%;
|
||
|
|
||
|
.enable-disable-switch {
|
||
|
position: absolute;
|
||
|
left: 12px;
|
||
|
top: 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
.save-btn {
|
||
|
position: absolute !important;
|
||
|
right: 12px;
|
||
|
bottom: 10px;
|
||
|
}
|
||
|
</style>
|
||
|
<!--
|
||
|
/**
|
||
|
* @copyright Copyright (c) 2021, Xgene Cloud Ltd
|
||
|
*
|
||
|
* @author Naveen MR <oof1lab@gmail.com>
|
||
|
* @author Pranav C Balan <pranavxc@gmail.com>
|
||
|
*
|
||
|
* @license GNU AGPL version 3 or any later version
|
||
|
*
|
||
|
* This program is free software: you can redistribute it and/or modify
|
||
|
* it under the terms of the GNU Affero General Public License as
|
||
|
* published by the Free Software Foundation, either version 3 of the
|
||
|
* License, or (at your option) any later version.
|
||
|
*
|
||
|
* This program is distributed in the hope that it will be useful,
|
||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
* GNU Affero General Public License for more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU Affero General Public License
|
||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
*
|
||
|
*/
|
||
|
-->
|