mirror of https://github.com/shunfei/cronsun
Batch start/pause operation.
parent
4e6e5a191e
commit
a99eccb26b
63
web/job.go
63
web/job.go
|
@ -2,6 +2,7 @@ package web
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"sort"
|
||||
"strings"
|
||||
|
@ -56,26 +57,76 @@ func (j *Job) ChangeJobStatus(ctx *Context) {
|
|||
ctx.R.Body.Close()
|
||||
|
||||
vars := mux.Vars(ctx.R)
|
||||
originJob, rev, err := cronsun.GetJobAndRev(vars["group"], vars["id"])
|
||||
job, err = j.updateJobStatus(vars["group"], vars["id"], job.Pause)
|
||||
if err != nil {
|
||||
outJSONWithCode(ctx.W, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
originJob.Pause = job.Pause
|
||||
outJSON(ctx.W, job)
|
||||
}
|
||||
|
||||
func (j *Job) updateJobStatus(group, id string, isPause bool) (*cronsun.Job, error) {
|
||||
originJob, rev, err := cronsun.GetJobAndRev(group, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if originJob.Pause == isPause {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
originJob.Pause = isPause
|
||||
b, err := json.Marshal(originJob)
|
||||
if err != nil {
|
||||
outJSONWithCode(ctx.W, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_, err = cronsun.DefalutClient.PutWithModRev(originJob.Key(), string(b), rev)
|
||||
if err != nil {
|
||||
outJSONWithCode(ctx.W, http.StatusInternalServerError, err.Error())
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return originJob, nil
|
||||
}
|
||||
|
||||
func (j *Job) BatchChangeJobStatus(ctx *Context) {
|
||||
var jobIds []string
|
||||
decoder := json.NewDecoder(ctx.R.Body)
|
||||
err := decoder.Decode(&jobIds)
|
||||
if err != nil {
|
||||
outJSONWithCode(ctx.W, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
ctx.R.Body.Close()
|
||||
|
||||
vars := mux.Vars(ctx.R)
|
||||
op := vars["op"]
|
||||
var isPause bool
|
||||
switch op {
|
||||
case "pause":
|
||||
isPause = true
|
||||
case "start":
|
||||
default:
|
||||
outJSONWithCode(ctx.W, http.StatusBadRequest, "Unknow batch operation.")
|
||||
return
|
||||
}
|
||||
|
||||
outJSON(ctx.W, originJob)
|
||||
var updated int
|
||||
for i := range jobIds {
|
||||
id := strings.Split(jobIds[i], "/") // [Group, ID]
|
||||
if len(id) != 2 || id[0] == "" || id[1] == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
_, err = j.updateJobStatus(id[0], id[1], isPause)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
updated++
|
||||
}
|
||||
|
||||
outJSON(ctx.W, fmt.Sprintf("%d of %d updated.", updated, len(jobIds)))
|
||||
}
|
||||
|
||||
func (j *Job) UpdateJob(ctx *Context) {
|
||||
|
|
|
@ -56,6 +56,9 @@ func initRouters() (s *http.Server, err error) {
|
|||
// pause/start
|
||||
h = NewAuthHandler(jobHandler.ChangeJobStatus)
|
||||
subrouter.Handle("/job/{group}-{id}", h).Methods("POST")
|
||||
// batch pause/start
|
||||
h = NewAuthHandler(jobHandler.BatchChangeJobStatus)
|
||||
subrouter.Handle("/jobs/{op}", h).Methods("POST")
|
||||
// get a job
|
||||
h = NewAuthHandler(jobHandler.GetJob)
|
||||
subrouter.Handle("/job/{group}-{id}", h).Methods("GET")
|
||||
|
|
|
@ -1,11 +1,21 @@
|
|||
<style scope>
|
||||
.clearfix:after {content:""; clear:both; display:table;}
|
||||
.ui.fitted.checkbox {min-height: 15px;}
|
||||
</style>
|
||||
<template>
|
||||
<div>
|
||||
<div class="clearfix" style="margin-bottom: 20px;">
|
||||
<router-link class="ui left floated button" to="/job/executing">{{$L('view executing jobs')}}</router-link>
|
||||
<button class="ui left floated icon button" v-on:click="refresh"><i class="refresh icon"></i></button>
|
||||
<div class="ui icon buttons">
|
||||
<button class="ui left floated icon button" v-on:click="batched=!batched">批量</button>
|
||||
<button class="ui button" :class="{disabled: batchIds.length == 0}" v-if="batched" v-on:click="batch('start')">
|
||||
<i class="play icon"></i>
|
||||
</button>
|
||||
<button class="ui button" :class="{disabled: batchIds.length == 0}" v-if="batched" v-on:click="batch('pause')">
|
||||
<i class="pause icon"></i>
|
||||
</button>
|
||||
</div>
|
||||
<router-link class="ui right floated primary button" to="/job/create"><i class="add to calendar icon"></i> {{$L('create job')}}</router-link>
|
||||
</div>
|
||||
<form class="ui form">
|
||||
|
@ -35,7 +45,7 @@
|
|||
<tbody>
|
||||
<tr v-for="(job, index) in jobs">
|
||||
<td class="center aligned">
|
||||
<div class="ui icon dropdown">
|
||||
<div class="ui icon dropdown" v-show="!batched">
|
||||
<i class="content icon"></i>
|
||||
<div class="menu">
|
||||
<div class="item" v-on:click="$router.push('/job/edit/'+job.group+'/'+job.id)">{{$L('edit')}}</div>
|
||||
|
@ -45,6 +55,9 @@
|
|||
<div class="item" style="color:red;" v-on:click="removeJob(job.group, job.id, index)">{{$L('delete')}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui fitted checkbox" v-show="batched">
|
||||
<input type="checkbox" :value="job.group+'/'+job.id" v-model="batchIds"><label></label>
|
||||
</div>
|
||||
</td>
|
||||
<td class="center aligned"><i class="icon" v-bind:class="{pause: job.pause, play: !job.pause, green: !job.pause}"></i></td>
|
||||
<td>{{job.group}}</td>
|
||||
|
@ -76,6 +89,8 @@ export default {
|
|||
name: 'job',
|
||||
data: function(){
|
||||
return {
|
||||
batched: false,
|
||||
batchIds: [],
|
||||
groups: [],
|
||||
group: '',
|
||||
nodes: [],
|
||||
|
@ -101,6 +116,8 @@ export default {
|
|||
vm.nodes.push(resp[i].id);
|
||||
}
|
||||
}).do();
|
||||
|
||||
$('.ui.checkbox').checkbox();
|
||||
},
|
||||
|
||||
watch: {
|
||||
|
@ -174,6 +191,20 @@ export default {
|
|||
|
||||
showExecuteJobModal: function(jobName, jobGroup, jobId){
|
||||
this.$refs.executeJobModal.show(jobName, jobGroup, jobId);
|
||||
},
|
||||
|
||||
batch: function(op){
|
||||
switch(op) {
|
||||
case 'start': break;
|
||||
case 'pause': break;
|
||||
default: return;
|
||||
}
|
||||
|
||||
var vm = this;
|
||||
this.$rest.POST('jobs/'+op, this.batchIds).onsucceed(200, (resp)=>{
|
||||
vm.refresh();
|
||||
vm.$bus.$emit('warning', resp);
|
||||
}).do();
|
||||
}
|
||||
},
|
||||
|
||||
|
|
Loading…
Reference in New Issue