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.
457 lines
17 KiB
457 lines
17 KiB
4 years ago
|
<template>
|
||
3 years ago
|
<div style="height: 100%">
|
||
4 years ago
|
<v-tabs v-model="dbsTab" height="30" @change="loadCrons()">
|
||
4 years ago
|
<template v-for="db in dbAliasList">
|
||
4 years ago
|
<v-tab :key="db.meta.dbAlias" class="text-capitalize caption">
|
||
|
{{ db.connection.database }}
|
||
4 years ago
|
({{ db.meta.dbAlias }})
|
||
|
</v-tab>
|
||
3 years ago
|
<v-tab-item :key="db.meta.dbAlias" style="height: 100%">
|
||
4 years ago
|
<!-- <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>-->
|
||
3 years ago
|
<v-card style="height: calc(100% - 42px)">
|
||
4 years ago
|
<v-container style="height: 100%" fluid>
|
||
|
<!-- <div class="d-flex d-100 justify-center">-->
|
||
3 years ago
|
<v-row style="height: 100%">
|
||
4 years ago
|
<v-col cols="6">
|
||
|
<v-card class="pt-5 h-100">
|
||
3 years ago
|
<div style="position: relative" class="mb-4">
|
||
4 years ago
|
<h4
|
||
|
class="text-center"
|
||
|
:class="{
|
||
3 years ago
|
'grey--text text--darken-2': !$store.state.settings.darkTheme,
|
||
4 years ago
|
}"
|
||
|
>
|
||
|
Cron Job List
|
||
|
</h4>
|
||
4 years ago
|
|
||
3 years ago
|
<div style="position: absolute; right: 5px; bottom: 0">
|
||
4 years ago
|
<x-btn
|
||
|
outlined
|
||
3 years ago
|
:tooltip="$t('tooltip.reloadList')"
|
||
4 years ago
|
small
|
||
|
color="primary"
|
||
|
icon="refresh"
|
||
|
@click="loadCrons()"
|
||
|
>
|
||
3 years ago
|
<!-- Reload -->
|
||
|
{{ $t('general.reload') }}
|
||
4 years ago
|
</x-btn>
|
||
4 years ago
|
<x-btn
|
||
|
outlined
|
||
|
tooltip="Add new cron job"
|
||
|
small
|
||
|
color="primary"
|
||
|
icon="mdi-plus"
|
||
|
@click="addNewCron()"
|
||
|
>
|
||
3 years ago
|
New Cron
|
||
4 years ago
|
</x-btn>
|
||
|
</div>
|
||
|
</div>
|
||
|
|
||
4 years ago
|
<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"
|
||
3 years ago
|
style="max-width: 500px"
|
||
4 years ago
|
outlined
|
||
|
/>
|
||
4 years ago
|
|
||
4 years ago
|
<v-simple-table dense style="min-width: 400px">
|
||
4 years ago
|
<thead>
|
||
4 years ago
|
<tr>
|
||
3 years ago
|
<th class="text-center">#</th>
|
||
4 years ago
|
<th>Cron Title</th>
|
||
|
<th>Actions</th>
|
||
|
</tr>
|
||
4 years ago
|
</thead>
|
||
|
<tbody>
|
||
4 years ago
|
<tr v-if="crons && !crons.length">
|
||
3 years ago
|
<td class="caption text-center" colspan="3">No cron jobs are found</td>
|
||
4 years ago
|
</tr>
|
||
3 years ago
|
<template v-for="(cron, i) in crons">
|
||
4 years ago
|
<tr
|
||
3 years ago
|
v-if="
|
||
|
!filter || (cron.title && cron.title.toLowerCase().indexOf(filter.toLowerCase()) > -1)
|
||
|
"
|
||
4 years ago
|
:key="`${cron.title}-${cron.id}`"
|
||
|
class="pointer"
|
||
|
@click="editCronHandler(cron)"
|
||
|
>
|
||
|
<td>
|
||
|
<v-radio-group v-model="selectedItemIndex" dense hide-details class="mt-n2">
|
||
3 years ago
|
<v-radio :value="i" />
|
||
4 years ago
|
</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"
|
||
|
small
|
||
|
@click.stop="deleteCron(cron)"
|
||
|
>
|
||
|
mdi-delete
|
||
|
</x-icon>
|
||
|
</td>
|
||
|
</tr>
|
||
|
</template>
|
||
4 years ago
|
</tbody>
|
||
|
</v-simple-table>
|
||
|
</v-card>
|
||
|
</v-col>
|
||
3 years ago
|
<v-col v-if="selectedItem" cols="6" style="height: 100%; overflow: auto">
|
||
4 years ago
|
<v-card class="px-4 py-2" style="min-height: 100%">
|
||
|
<v-row class="mt-3">
|
||
|
<v-col cols="12" class="edit-header">
|
||
4 years ago
|
<h4
|
||
|
class="text-center text-capitalize mt-2 d-100"
|
||
|
:class="{
|
||
3 years ago
|
'grey--text text--darken-2': !$store.state.settings.darkTheme,
|
||
4 years ago
|
}"
|
||
|
>
|
||
|
{{ selectedItem.title }}
|
||
|
</h4>
|
||
4 years ago
|
<div class="save-btn">
|
||
4 years ago
|
<x-btn
|
||
|
outlined
|
||
|
:loading="updating"
|
||
|
:disabled="updating || !selectedItem"
|
||
3 years ago
|
:tooltip="$t('tooltip.saveChanges')"
|
||
4 years ago
|
small
|
||
|
color="primary"
|
||
|
icon="save"
|
||
|
@click="saveCron()"
|
||
|
>
|
||
3 years ago
|
<!-- Save -->
|
||
|
{{ $t('general.save') }}
|
||
4 years ago
|
</x-btn>
|
||
|
</div>
|
||
|
<v-switch
|
||
4 years ago
|
v-model="selectedItem.active"
|
||
4 years ago
|
class="enable-disable-switch"
|
||
|
inset
|
||
|
dense
|
||
|
hide-details
|
||
3 years ago
|
:label="selectedItem.active ? 'Enabled' : 'Disabled'"
|
||
4 years ago
|
/>
|
||
4 years ago
|
</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">
|
||
3 years ago
|
<v-text-field v-model="selectedItem.title" auto dense hide-details outlined label="Title" />
|
||
4 years ago
|
</v-col>
|
||
|
<v-col cols="6">
|
||
3 years ago
|
<v-text-field v-model="selectedItem.pattern" dense hide-details outlined label="Pattern" />
|
||
|
<span class="caption grey--text"
|
||
|
>Generate pattern from
|
||
|
<a target="_blank" href="http://corntab.com/" class="grey--text">http://corntab.com/</a></span
|
||
|
>
|
||
4 years ago
|
</v-col>
|
||
|
<v-col cols="6">
|
||
3 years ago
|
<v-text-field v-model="selectedItem.timezone" dense hide-details outlined label="Timezone" />
|
||
|
<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
|
||
|
>
|
||
4 years ago
|
</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>
|
||
3 years ago
|
<monaco-ts-editor v-model="selectedItem.cron_handler" style="height: 400px" />
|
||
4 years ago
|
</v-tab-item>
|
||
|
|
||
|
<v-tab><span class="caption text-capitalize">Webhook</span></v-tab>
|
||
|
|
||
|
<v-tab-item class="pt-3">
|
||
|
<v-overlay absolute>
|
||
3 years ago
|
<div class="text-center">Coming Soon...</div>
|
||
4 years ago
|
</v-overlay>
|
||
|
<v-text-field
|
||
4 years ago
|
v-model="selectedItem.webhook"
|
||
4 years ago
|
dense
|
||
|
outlined
|
||
|
label="Webhook url"
|
||
|
type="url"
|
||
4 years ago
|
/>
|
||
4 years ago
|
</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>
|
||
3 years ago
|
import { mapGetters } from 'vuex';
|
||
|
import MonacoTsEditor from '@/components/monaco/MonacoTsEditor';
|
||
4 years ago
|
|
||
|
export default {
|
||
4 years ago
|
name: 'CronJobs',
|
||
|
components: { MonacoTsEditor },
|
||
|
props: ['nodes'],
|
||
4 years ago
|
data: () => ({
|
||
|
edited: false,
|
||
|
crons: null,
|
||
|
updating: false,
|
||
|
dbsTab: 0,
|
||
|
filter: '',
|
||
3 years ago
|
selectedItem: null,
|
||
4 years ago
|
}),
|
||
4 years ago
|
async mounted() {
|
||
3 years ago
|
await this.loadCrons();
|
||
4 years ago
|
},
|
||
|
methods: {
|
||
4 years ago
|
async editCronHandler(cron) {
|
||
3 years ago
|
this.selectedItem = cron;
|
||
4 years ago
|
},
|
||
4 years ago
|
async deleteCron(cron) {
|
||
4 years ago
|
if (cron.id) {
|
||
3 years ago
|
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();
|
||
4 years ago
|
} else {
|
||
3 years ago
|
this.crons.splice(this.crons.indexOf(cron), 1);
|
||
4 years ago
|
}
|
||
|
if (cron === this.selectedItem) {
|
||
3 years ago
|
this.selectedItem = null;
|
||
4 years ago
|
}
|
||
|
},
|
||
4 years ago
|
async addNewCron() {
|
||
3 years ago
|
this.crons = this.crons || [];
|
||
|
this.crons.push(
|
||
|
(this.selectedItem = {
|
||
|
title: 'cron_job' + this.crons.length,
|
||
|
pattern: '* * * * * *',
|
||
|
timezone: 'America/Los_Angeles',
|
||
|
active: true,
|
||
|
cron_handler: '',
|
||
|
})
|
||
|
);
|
||
4 years ago
|
},
|
||
4 years ago
|
async loadCrons() {
|
||
3 years ago
|
this.crons = await this.$store.dispatch('sqlMgr/ActSqlOp', [
|
||
|
{
|
||
|
dbAlias: this.dbAliasList[this.dbsTab].meta.dbAlias,
|
||
|
env: this.$store.getters['project/GtrEnv'],
|
||
|
},
|
||
|
'xcCronList',
|
||
|
]);
|
||
4 years ago
|
if (this.selectedItem) {
|
||
3 years ago
|
this.selectedItem = this.crons.find(c => c.title === this.selectedItem.title);
|
||
4 years ago
|
}
|
||
3 years ago
|
this.edited = false;
|
||
4 years ago
|
},
|
||
4 years ago
|
async saveCron() {
|
||
3 years ago
|
this.updating = true;
|
||
|
const errorCrons = [];
|
||
4 years ago
|
try {
|
||
3 years ago
|
const saveList = this.crons.filter(cron => {
|
||
4 years ago
|
if (cron === this.selectedItem || !cron.id) {
|
||
|
if (cron.cron_handler.trim() && cron.webhook) {
|
||
3 years ago
|
errorCrons.push(`'${cron.title}'`);
|
||
4 years ago
|
}
|
||
3 years ago
|
return true;
|
||
4 years ago
|
}
|
||
3 years ago
|
return false;
|
||
|
});
|
||
4 years ago
|
|
||
|
if (!errorCrons.length) {
|
||
|
for (const cron of saveList) {
|
||
3 years ago
|
await this.$store.dispatch('sqlMgr/ActSqlOp', [
|
||
|
{
|
||
|
dbAlias: this.dbAliasList[this.dbsTab].meta.dbAlias,
|
||
|
env: this.$store.getters['project/GtrEnv'],
|
||
|
},
|
||
|
'xcCronSave',
|
||
|
cron,
|
||
|
]);
|
||
4 years ago
|
}
|
||
|
|
||
3 years ago
|
await this.loadCrons();
|
||
4 years ago
|
|
||
3 years ago
|
this.$toast.success('Cron job saved successfully').goAway(3000);
|
||
4 years ago
|
} else {
|
||
3 years ago
|
this.$toast
|
||
|
.error(`${errorCrons.join(', ')} cron jobs<br> have both webhook and handler, please remove one of them.`)
|
||
|
.goAway(10000);
|
||
4 years ago
|
}
|
||
|
} catch (e) {
|
||
3 years ago
|
this.$toast.error('Some error occurred').goAway(3000);
|
||
|
console.log(e, e.message);
|
||
4 years ago
|
}
|
||
3 years ago
|
this.updating = false;
|
||
|
this.edited = false;
|
||
|
},
|
||
4 years ago
|
},
|
||
|
computed: {
|
||
|
...mapGetters({
|
||
3 years ago
|
dbAliasList: 'project/GtrDbAliasList',
|
||
4 years ago
|
}),
|
||
4 years ago
|
enableCountText() {
|
||
3 years ago
|
return '';
|
||
4 years ago
|
},
|
||
|
selectedItemIndex: {
|
||
4 years ago
|
get() {
|
||
3 years ago
|
return this.crons ? this.crons.indexOf(this.selectedItem) : -1;
|
||
4 years ago
|
},
|
||
4 years ago
|
set(i) {
|
||
3 years ago
|
this.selectedItem = this.crons[i];
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
};
|
||
4 years ago
|
</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/>.
|
||
|
*
|
||
|
*/
|
||
|
-->
|