Added HID jobe event handling to ViewModel of webclient

This commit is contained in:
MaMe82 2018-08-02 18:20:11 +02:00
parent 3b971750ae
commit eacd3eb11c
7 changed files with 128 additions and 49 deletions

83
dist/www/index.html vendored
View File

@ -17,6 +17,89 @@
<style type="text/css">
/* Job Entry */
.jobstate-entry {
margin: 3px;
list-style-type: none;
list-style-position: outside;
position: relative;
display: block;
width: 6.5em;
height: 1.7em;
background-color: gray;
background: linear-gradient(to top, #f4f4f4, #9e9e9e 80%);
border-radius: 99999px;
box-shadow: 1px 1px 1px 0 #3f3f3f, -1px -1px 1px 0 #ffffff;
vertical-align: middle;
cursor: pointer;
}
.jobstate-entry::before {
content:"";
list-style-type: none;
list-style-position: outside;
position: absolute;
display: inline-block;
left: 4%;
right: 4%;
top: 10%;
bottom: 10%;
width: 92%;
height: 80%;
background-color: gray;
background: linear-gradient(to bottom, #f4f4f4, #9e9e9e 80%);
border-radius: 99999px;
}
.jobstate-entry > span {
left: 10%;
top: 8%;
position: relative;
display: inline-block;
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.8);
font-size: 0.9em;
font-weight: 800;
}
.jobstate-entry > span::before {
content: "";
vertical-align: sub;
position: relative;
display:inline-block;
margin-right: 3px;
width: 1.1em;
height: 1.1em;
border-radius: 50%;
background: black;
left: 2%;
top: 5%;
bottom: 5%;
border-radius: 99999px;
background-color: #707070;
box-shadow: inset 0 0 10px 0 rgba(0, 0, 0, 0.7);
}
.jobstate-entry.SUCCEEDED > span::before {
background: rgb(150,255,0);
box-shadow: inset 0 0 4px 0 rgba(0, 0, 0, 0.5), 0 0 11px 1px rgb(150,255,0);
}
.jobstate-entry.FAILED > span::before {
background: rgb(255,160,130);
box-shadow: inset 0 0 7px 0 rgba(250, 50, 50, 1.0), 0 0 11px 2px rgb(255,160,130);
}
.jobstate-entry.RUNNING > span::before {
background: lightyellow;
box-shadow: inset 0 0 4px 0 rgba(0, 0, 0, 0.5), 0 0 11px 1px rgb(250,255,80);
}
/* CodeMirror */
.CodeMirror {
height: 60%;

View File

@ -44,12 +44,16 @@ LastMessage string `js:"lastMessage"`
TextResult string `js:"textResult"`
TextError string `js:"textError"`
LastUpdateTime string `js:"lastUpdateTime"` //JSON timestamp from server
ScriptSource string `js:"textError"`
ScriptSource string `js:"textSource"`
}
*/
compHIDJobTemplate = `
<li class="jobstate-entry" :class="jobstate">{{ job.id }}: {{ jobstate }}</li>
<div :style="{ 'display': 'flex' }">
<div class="jobstate-entry" :class="jobstate"><span>{{ job.vmId }}: {{ job.id }}</span></div>
<div v-if="job.hasSucceeded">{{ job.textResult }}</div>
<div v-if="job.hasFailed">{{ job.textError }}</div>
</div>
`
)

View File

@ -46,9 +46,9 @@ const (
//{ "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" }
compHIDJobsTemplate = `
<div>
<ul>
<hidjob v-for="job in jobs" :job="job"></hidjob>
</ul>
<div>
<hidjob v-for="job in jobs" :job="job" :key="job.id"></hidjob>
</div>
<table border="1">
<tr>
<th>Event Type</th>

View File

@ -66,6 +66,7 @@ const (
<span>P4wnP1 HID Script</span>
<button @click="SendAndRun()">as Job</button><br>
<code-editor v-model="scriptContent"></code-editor>
<hidjobs></hidjobs>
</div>
`
)

View File

@ -11,6 +11,7 @@ import (
"io"
"github.com/mame82/P4wnP1_go/common_web"
"strconv"
"github.com/mame82/hvue"
)
var eNoLogEvent = errors.New("No log event")
@ -238,7 +239,8 @@ func (jsEv *jsEvent) toHidEvent() (res *jsHidEvent, err error) {
if !ok { return nil,eNoHidEvent}
res.EvLogTime,ok = jsEv.Values[7].(string)
if !ok { return nil,eNoLogEvent}
if !ok { return nil,eNoHidEvent}
return res,nil
}
@ -255,7 +257,7 @@ type jsHidJobState struct {
TextResult string `js:"textResult"`
TextError string `js:"textError"`
LastUpdateTime string `js:"lastUpdateTime"` //JSON timestamp from server
ScriptSource string `js:"textError"`
ScriptSource string `js:"textSource"`
}
type jsHidJobStateList struct {
@ -267,18 +269,21 @@ func NewHIDJobStateList() *jsHidJobStateList {
jl := &jsHidJobStateList{Object:O()}
jl.Jobs = O()
//ToDo: Delete adding a test job
/*
//ToDo: Delete added a test jobs
jl.UpdateEntry(99,1,false,false, "This is the latest event message", "current result", "current error","16:00", "type('hello world')")
jl.UpdateEntry(100,1,false,true, "SUCCESS", "current result", "current error","16:00", "type('hello world')")
jl.UpdateEntry(101,1,true,false, "FAIL", "current result", "current error","16:00", "type('hello world')")
jl.UpdateEntry(102,1,true,true, "Error and Success at same time --> UNKNOWN", "current result", "current error","16:00", "type('hello world')")
jl.UpdateEntry(102,1,true,true, "Error and Success at same time --> UNKNOWN, repeated ID", "current result", "current error","16:00", "type('hello world')")
*/
return jl
}
func (jl *jsHidJobStateList) UpdateEntry(id, vmId int64, hasFailed, hasSucceeded bool, message, textResult, textError, lastUpdateTime, scriptSource string) {
//ToDo: Cehck if key exists and retrieve former job, to preserve fields which aren't changed (f.e. ScriptSource)
//Create job object
j := &jsHidJobState{Object:O()}
j.Id = id
@ -288,14 +293,14 @@ func (jl *jsHidJobStateList) UpdateEntry(id, vmId int64, hasFailed, hasSucceeded
j.LastMessage = message
j.TextResult = textResult
j.TextError = textError
j.LastUpdateTime = textError
j.LastUpdateTime = lastUpdateTime
if len(scriptSource) > 0 {j.ScriptSource = scriptSource}
jl.Jobs.Set(strconv.Itoa(int(j.Id)), j) //jobs["j.ID"]=j
//jl.Jobs.Set(strconv.Itoa(int(j.Id)), j) //jobs["j.ID"]=j <--Property addition/update can't be detected by Vue.js, see https://vuejs.org/v2/guide/list.html#Object-Change-Detection-Caveats
hvue.Set(jl.Jobs, strconv.Itoa(int(j.Id)), j)
}
func (jl *jsHidJobStateList) DeleteEntry(id int64) {
jl.Delete(strconv.Itoa(int(id))) //JS version
jl.Jobs.Delete(strconv.Itoa(int(id))) //JS version
//delete(jl.Jobs, strconv.Itoa(int(id)))
}
@ -307,9 +312,10 @@ type jsLoggerData struct {
cancel context.CancelFunc
*sync.Mutex
MaxEntries int `js:"maxEntries"`
JobList *jsHidJobStateList `js:"jobList"` //Needs to be exposed to JS in order to use JobList.UpdateEntry() from this JS object
}
func NewLogger(maxEntries int) *jsLoggerData {
func NewLogger(maxEntries int, jobList *jsHidJobStateList) *jsLoggerData {
loggerVmData := &jsLoggerData{
Object: js.Global.Get("Object").New(),
}
@ -318,10 +324,25 @@ func NewLogger(maxEntries int) *jsLoggerData {
loggerVmData.LogArray = js.Global.Get("Array").New()
loggerVmData.HidEventArray = js.Global.Get("Array").New()
loggerVmData.MaxEntries = maxEntries
loggerVmData.JobList = jobList
return loggerVmData
}
func (data *jsLoggerData) handleHidEvent(hEv *jsHidEvent ) {
if hEv.EvType == common_web.HidEventType_JOB_STARTED {
data.JobList.UpdateEntry(hEv.JobId, hEv.VMId, hEv.HasError, false, hEv.Message, hEv.Result, hEv.Error, hEv.EvLogTime,"")
}
if hEv.EvType == common_web.HidEventType_JOB_FAILED {
data.JobList.UpdateEntry(hEv.JobId, hEv.VMId, hEv.HasError, false, hEv.Message, hEv.Result, hEv.Error, hEv.EvLogTime,"")
}
if hEv.EvType == common_web.HidEventType_JOB_SUCCEEDED {
println("Updating job succeeded for", int(hEv.JobId))
data.JobList.UpdateEntry(hEv.JobId, hEv.VMId, hEv.HasError, true, hEv.Message, hEv.Result, hEv.Error, hEv.EvLogTime,"")
}
}
/* This method gets internalized and therefor the mutex won't be accessible*/
func (data *jsLoggerData) AddEntry(ev *pb.Event ) {
// println("ADD ENTRY", ev)
@ -345,6 +366,9 @@ func (data *jsLoggerData) AddEntry(ev *pb.Event ) {
case common_web.EVT_HID:
if hidEv,err := jsEv.toHidEvent(); err == nil {
data.HidEventArray.Call("push", hidEv)
//handle event
data.handleHidEvent(hidEv)
} else {
println("couldn't convert to HidEvent: ", jsEv)
}

View File

@ -34,40 +34,6 @@ type appController struct {
func main() {
println(GetBaseURL())
/*
println("Listening for RPC events ...")
err := Client.StartListenEvents(common.EVT_ANY)
if err != nil {println(err)}
time.Sleep(time.Second * 5)
Client.StopEventListening()
println("... done listening for RPC events")
time.Sleep(time.Second)
println("Listening for RPC events ...")
err := Client.StartListenEvents(common.EVT_LOG)
if err != nil {println(err)}
*/
/*
fmt.Printf("Address %v\n", strings.TrimSuffix(document.BaseURI(), "/"))
fmt.Printf("Client %v\n", Client)
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
gs, err := Client.GetDeployedGadgetSetting(ctx, &pb.Empty{})
if err == nil {
//export Gadget setting
js.Global.Set("gs", gs)
GS = gs
} else {
fmt.Printf("Error rpc call: %v\n", err)
}
*/
InitGlobalState() //sets Vuex store in JS window.store

View File

@ -62,8 +62,9 @@ func createGlobalStateStruct() GlobalState {
state.CurrentHIDScriptSource = initHIDScript
state.CurrentGadgetSettings = NewUSBGadgetSettings()
//UpdateGadgetSettingsFromDeployed(state.CurrentGadgetSettings)
state.EventLog = NewLogger(maxLogEntries)
state.HidJobList = NewHIDJobStateList()
state.EventLog = NewLogger(maxLogEntries, state.HidJobList)
state.IsModalEnabled = false
state.Counter = 1337