webclient: Allow cancel for running HIDScript jobs

This commit is contained in:
MaMe82 2018-10-29 17:46:15 +01:00
parent 6f3c83594f
commit c099277b27
6 changed files with 145 additions and 18 deletions

View File

@ -604,8 +604,9 @@ func (s *server) HIDCancelAllScriptJobs(ctx context.Context, rEmpty *pb.Empty) (
func (s *server) HIDCancelScriptJob(ctx context.Context, sJob *pb.HIDScriptJob) (empty *pb.Empty, err error) {
defer s.rootSvc.SubSysEvent.Emit(ConstructEventNotifyStateChange(common_web.STATE_CHANGE_EVT_TYPE_HID))
empty = &pb.Empty{}
job,err := s.rootSvc.SubSysUSB.HidScriptGetBackgroundJobByID(int(sJob.Id))
if err != nil { return nil, err }
if err != nil { return empty, err }
job.Cancel()
return

View File

@ -35,6 +35,11 @@ func InitCompHIDJobs() {
hvue.NewComponent(
"hid-job-overview-item",
hvue.Template(compHIDJobOverViewItemTemplate),
hvue.Method("cancel", func(vm *hvue.VM) {
job := &jsHidJobState{Object:vm.Get("job")}
println("Aborting job :", job.Id)
vm.Get("$store").Call("dispatch", VUEX_ACTION_CANCEL_HID_JOB, job.Id)
}),
hvue.Computed("jobstate",
func(vm *hvue.VM) interface{} {
//fetch job and cast back to jobstate
@ -120,21 +125,46 @@ ScriptSource string `js:"textSource"`
</q-popover>
</q-btn>
</q-item-side>
<q-item-side right v-if="!job.hasSucceeded && !job.hasFailed">
<q-btn flat round dense color="negative" icon="cancel" @click="cancel">
<q-popover>
cancel HIDScript job {{ job.id }}
</q-popover>
</q-btn>
</q-item-side>
</q-item>
`
//{ "evtype": 0, "vmId": 2, "jobId": 3, "hasError": false, "result": "null", "error": "", "message": "Script started", "time": "2018-07-30 04:56:42.297533 +0000 UTC m=+7625.097825001" }
compHIDJobOverviewTemplate = `
//{ "evtype": 0, "vmId": 2, "jobId": 3, "hasError": false, "result": "null", "error": "", "message": "Script started", "time": "2018-07-30 04:56:42.297533 +0000 UTC m=+7625.097825001" }
compHIDJobOverviewTemplate = `
<q-card class="full-height">
<q-list>
<q-list-header>Running</q-list-header>
<hid-job-overview-item v-for="job in $store.getters.hidjobsRunning" :job="job" :key="job.id"></hid-job-overview-item>
<q-list-header>Succeeded</q-list-header>
<hid-job-overview-item v-for="job in $store.getters.hidjobsSucceeded" :job="job" :key="job.id"></hid-job-overview-item>
<q-list-header>Failed</q-list-header>
<hid-job-overview-item v-for="job in $store.getters.hidjobsFailed" :job="job" :key="job.id"></hid-job-overview-item>
</q-list>
<q-list>
<q-collapsible opened icon-toggle>
<template slot="header">
<q-item-main label="Succeeded" :sublabel="'(' + $store.getters.hidjobsSucceeded.length + ' successful jobs)'"/>
<q-item-side v-if="$store.getters.hidjobsSucceeded.length > 0" right>
<q-btn icon="delete" color="red" @click="$store.dispatch('removeSucceededHidJobs')" round inverted flat />
</q-item-side>
</template>
<hid-job-overview-item v-for="job in $store.getters.hidjobsSucceeded" :job="job" :key="job.id"></hid-job-overview-item>
</q-collapsible>
</q-list>
<q-list>
<q-collapsible opened icon-toggle>
<template slot="header">
<q-item-main label="Failed" :sublabel="'(' + $store.getters.hidjobsFailed.length + ' failed jobs)'"/>
<q-item-side v-if="$store.getters.hidjobsFailed.length > 0" right>
<q-btn icon="delete" color="red" @click="$store.dispatch('removeFailedHidJobs')" round inverted flat />
</q-item-side>
</template>
<hid-job-overview-item v-for="job in $store.getters.hidjobsFailed" :job="job" :key="job.id"></hid-job-overview-item>
</q-collapsible>
</q-list>
</q-card>

View File

@ -171,6 +171,19 @@ const templateSelectStringModal = `
<q-btn icon="delete" color="negative" @click="onDeletePressed(name)" round flat />
</q-item-side>
</q-item>
<!--
<q-item tag="label">
<q-item-main>
<q-item-tile>
<q-btn color="primary" v-show="CurrentSelection != undefined" label="ok" @click="onLoadPressed(); visible=false"/>
<q-btn color="secondary" v-close-overlay label="close" />
</q-item-tile>
</q-item-main>
</q-item>
-->
</q-list>
<q-list slot="footer">
<q-item tag="label">
<q-item-main>
<q-item-tile>
@ -180,6 +193,7 @@ const templateSelectStringModal = `
</q-item-main>
</q-item>
</q-list>
</q-modal-layout>
</q-modal>
`

View File

@ -419,9 +419,16 @@ func (jl *jsHidJobStateList) UpdateEntry(id, vmId int64, hasFailed, hasSucceeded
hvue.Set(jl.Jobs, key, j)
}
func (jl *jsHidJobStateList) Clear() {
hvue.Set(jl,"jobs",O())
}
func (jl *jsHidJobStateList) DeleteEntry(id int64) {
jl.Jobs.Delete(strconv.Itoa(int(id))) //JS version
//delete(jl.Jobs, strconv.Itoa(int(id)))
key := strconv.Itoa(int(id))
hvue.Delete(jl.Jobs, key) // vue reactive version
//jl.Jobs.Delete(key) //JS version
//delete(jl.Jobs, key) // go version
}
/* WiFi settings */

View File

@ -45,12 +45,16 @@ const (
//HIDScripts and jobs
VUEX_ACTION_UPDATE_RUNNING_HID_JOBS = "updateRunningHidJobs"
VUEX_ACTION_REMOVE_SUCCEEDED_HID_JOBS = "removeSucceededHidJobs"
VUEX_ACTION_REMOVE_FAILED_HID_JOBS = "removeFailedHidJobs"
VUEX_ACTION_UPDATE_STORED_HID_SCRIPTS_LIST = "updateStoredHIDScriptsList"
VUEX_ACTION_UPDATE_CURRENT_HID_SCRIPT_SOURCE_FROM_REMOTE_FILE = "updateCurrentHidScriptSourceFromRemoteFile"
VUEX_ACTION_STORE_CURRENT_HID_SCRIPT_SOURCE_TO_REMOTE_FILE = "storeCurrentHidScriptSourceToRemoteFile"
VUEX_ACTION_CANCEL_HID_JOB = "cancelHIDJob"
VUEX_MUTATION_SET_CURRENT_HID_SCRIPT_SOURCE_TO = "setCurrentHIDScriptSource"
VUEX_MUTATION_SET_STORED_HID_SCRIPTS_LIST = "setStoredHIDScriptsList"
VUEX_MUTATION_DELETE_HID_JOB_ID = "deleteHIDJobID"
//USBGadget
VUEX_ACTION_DEPLOY_CURRENT_USB_SETTINGS = "deployCurrentUSBSettings"
@ -250,6 +254,52 @@ func actionUpdateAllStates(store *mvuex.Store, context *mvuex.ActionContext, sta
}
func actionCancelHidJob(store *mvuex.Store, context *mvuex.ActionContext, state *GlobalState, jobID *js.Object) {
go func() {
id := uint32(jobID.Int())
println("Cancel HIDScript job", id)
//fetch deployed gadget settings
err := RpcClient.CancelHIDScriptJob(defaultTimeout, id)
if err != nil {
println("Couldn't cancel HIDScript job", err)
return
}
// ToDo: update HIDScriptJob list (should be done event based)
}()
return
}
func actionRemoveSucceededHidJobs(store *mvuex.Store, context *mvuex.ActionContext, state *GlobalState) {
vJobs := state.HidJobList.Jobs //vue object, no real array --> values have to be extracted to filter
jobs := js.Global.Get("Object").Call("values", vJobs) //converted to native JS array (has filter method available
filtered := jobs.Call("filter", func(job *jsHidJobState) bool {
return job.HasSucceeded
})
for i:=0; i< filtered.Length(); i++ {
job := &jsHidJobState{Object: filtered.Index(i)}
store.Commit(VUEX_MUTATION_DELETE_HID_JOB_ID, job.Id)
}
return
}
func actionRemoveFailedHidJobs(store *mvuex.Store, context *mvuex.ActionContext, state *GlobalState) {
vJobs := state.HidJobList.Jobs //vue object, no real array --> values have to be extracted to filter
jobs := js.Global.Get("Object").Call("values", vJobs) //converted to native JS array (has filter method available
filtered := jobs.Call("filter", func(job *jsHidJobState) bool {
return job.HasFailed
})
for i:=0; i< filtered.Length(); i++ {
job := &jsHidJobState{Object: filtered.Index(i)}
store.Commit(VUEX_MUTATION_DELETE_HID_JOB_ID, job.Id)
}
return
}
func actionStartEventListen(store *mvuex.Store, context *mvuex.ActionContext, state *GlobalState) {
globalState.EventListenerShouldBeRunning = true
go func() {
@ -878,6 +928,8 @@ func actionUpdateRunningHidJobs(store *mvuex.Store, context *mvuex.ActionContext
return
}
state.HidJobList.Clear()
for _, jobstate := range jobstates {
println("updateing jobstate", jobstate)
state.HidJobList.UpdateEntry(jobstate.Id, jobstate.VmId, false, false, "initial job state", "", time.Now().String(), jobstate.Source)
@ -1149,6 +1201,13 @@ func initMVuex() *mvuex.Store {
mvuex.Mutation(VUEX_MUTATION_SET_EVENT_LISTENER_RUNNING, func(store *mvuex.Store, state *GlobalState, running *js.Object) {
state.EventListenerRunning = running.Bool()
}),
mvuex.Mutation(VUEX_MUTATION_DELETE_HID_JOB_ID, func(store *mvuex.Store, state *GlobalState, jobID *js.Object) {
id := jobID.Int()
state.HidJobList.DeleteEntry(int64(id))
}),
mvuex.Action(VUEX_ACTION_UPDATE_ALL_STATES, actionUpdateAllStates),
mvuex.Action(VUEX_ACTION_UPDATE_CURRENT_BLUETOOTH_CONTROLLER_INFORMATION, actionUpdateCurrentBluetoothControllerInformation),
@ -1208,6 +1267,11 @@ func initMVuex() *mvuex.Store {
mvuex.Action(VUEX_ACTION_START_EVENT_LISTEN, actionStartEventListen),
mvuex.Action(VUEX_ACTION_STOP_EVENT_LISTEN, actionStopEventListen),
mvuex.Action(VUEX_ACTION_REMOVE_SUCCEEDED_HID_JOBS, actionRemoveSucceededHidJobs),
mvuex.Action(VUEX_ACTION_REMOVE_FAILED_HID_JOBS, actionRemoveFailedHidJobs),
mvuex.Action(VUEX_ACTION_CANCEL_HID_JOB, actionCancelHidJob),
mvuex.Getter("triggerActions", func(state *GlobalState) interface{} {
return state.TriggerActionList.TriggerActions
}),
@ -1237,6 +1301,7 @@ func initMVuex() *mvuex.Store {
}),
mvuex.Getter("hidjobsSucceeded", func(state *GlobalState) interface{} {
println("Getter HID JOBS SUCCEEDED")
vJobs := state.HidJobList.Jobs //vue object, no real array --> values have to be extracted to filter
jobs := js.Global.Get("Object").Call("values", vJobs) //converted to native JS array (has filter method available
filtered := jobs.Call("filter", func(job *jsHidJobState) bool {
@ -1245,6 +1310,7 @@ func initMVuex() *mvuex.Store {
return filtered
}),
mvuex.Getter("storedWifiSettingsSelect", func(state *GlobalState) interface{} {
selectWS := js.Global.Get("Array").New()
for _, curS := range state.StoredWifiSettingsList {
@ -1270,18 +1336,9 @@ func initMVuex() *mvuex.Store {
// Update WiFi state
store.Dispatch(VUEX_ACTION_UPDATE_WIFI_STATE)
/*
// Update ethernet interface state (done by component)
store.Dispatch(VUEX_ACTION_UPDATE_ALL_ETHERNET_INTERFACE_SETTINGS)
*/
// propagate Vuex store to global scope to allow injecting it to Vue by setting the "store" option
js.Global.Set("store", store)
/*
// Start Event Listening
state.EventProcessor.StartListening()
*/
return store
}

View File

@ -29,6 +29,24 @@ func NewRpcClient(addr string) Rpc {
return rcl
}
func (rpc *Rpc) CancelHIDScriptJob(timeout time.Duration, jobID uint32) (err error) {
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
_,err = rpc.Client.HIDCancelScriptJob(ctx, &pb.HIDScriptJob{
Id:jobID,
})
return
}
func (rpc *Rpc) CancelAllHIDScriptJobs(timeout time.Duration) (err error) {
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
_,err = rpc.Client.HIDCancelAllScriptJobs(ctx, &pb.Empty{})
return
}
func (rpc *Rpc) GetStoredBluetoothSettingsList(timeout time.Duration) (ws []string, err error) {
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()