diff --git a/ToDo.txt b/ToDo.txt index 542335f..fd5fbd7 100644 --- a/ToDo.txt +++ b/ToDo.txt @@ -63,7 +63,7 @@ OTHER: - Load&Store runtime configuration from/to templates (accessible via web client) - Network events (interface down, DHCP lease/release) - add classes to all html elements of web client, to allow styling by sbd. who's able to do it better than me - +- add reboot/shutdown option accessible from webclient TO FIX: - remove dependencies of CLI client on service package diff --git a/dist/www/index.html b/dist/www/index.html index fca5fa8..c102f82 100644 --- a/dist/www/index.html +++ b/dist/www/index.html @@ -15,7 +15,6 @@ + + diff --git a/dist/www/lib/vue-codemirror.js b/dist/www/lib/vue-codemirror.js new file mode 100644 index 0000000..5749b50 --- /dev/null +++ b/dist/www/lib/vue-codemirror.js @@ -0,0 +1 @@ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("codemirror")):"function"==typeof define&&define.amd?define(["codemirror"],t):"object"==typeof exports?exports.VueCodemirror=t(require("codemirror")):e.VueCodemirror=t(e.codemirror)}(this,function(e){return function(e){function t(r){if(n[r])return n[r].exports;var o=n[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}var n={};return t.m=e,t.c=n,t.i=function(e){return e},t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="/",t(t.s=2)}([function(t,n){t.exports=e},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(3),o=n.n(r),i=n(5),s=n(4),c=s(o.a,i.a,!1,null,null,null);t.default=c.exports},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0}),t.install=t.codemirror=t.CodeMirror=void 0;var o=n(0),i=r(o),s=n(1),c=r(s),a=window.CodeMirror||i.default,u=function(e,t){t&&(t.options&&(c.default.props.globalOptions.default=function(){return t.options}),t.events&&(c.default.props.globalEvents.default=function(){return t.events})),e.component(c.default.name,c.default)},l={CodeMirror:a,codemirror:c.default,install:u};t.default=l,t.CodeMirror=a,t.codemirror=c.default,t.install=u},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(0),o=function(e){return e&&e.__esModule?e:{default:e}}(r),i=window.CodeMirror||o.default;"function"!=typeof Object.assign&&Object.defineProperty(Object,"assign",{value:function(e,t){if(null==e)throw new TypeError("Cannot convert undefined or null to object");for(var n=Object(e),r=1;r - - -` -) - - diff --git a/web_client/hvueCompHIDJobs.go b/web_client/hvueCompHIDJobs.go index 27403cb..deb563e 100644 --- a/web_client/hvueCompHIDJobs.go +++ b/web_client/hvueCompHIDJobs.go @@ -142,7 +142,7 @@ ScriptSource string `js:"textSource"` //{ "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 = ` - + HID Script jobs @@ -153,9 +153,6 @@ ScriptSource string `js:"textSource"` //{ "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" } compHIDJobEventOverviewTemplate = ` - - -
diff --git a/web_client/hvueCompHIDScript.go b/web_client/hvueCompHIDScript.go index f1468e8..0ba42a2 100644 --- a/web_client/hvueCompHIDScript.go +++ b/web_client/hvueCompHIDScript.go @@ -8,66 +8,79 @@ import ( "strconv" ) -type CompHIDScriptData struct { +type CompHIDScriptCodeEditorData struct { *js.Object - //ScriptContent string `js:"scriptContent"` + CodeMirrorOptions *CodeMirrorOptionsType `js:"codemirrorOptions"` } -func (data *CompHIDScriptData) SendAndRun(vm *hvue.VM) { +func (data *CompHIDScriptCodeEditorData) SendAndRun(vm *hvue.VM) { sourceCode := vm.Get("scriptContent").String() md5 := StringToMD5(sourceCode) //Calculate MD5 hexstring of current script content - //js.Global.Call("alert", md5) go func() { timeout := uint32(0) err := UploadHIDScript(md5, sourceCode) if err != nil { - notification := &QuasarNotification{Object: O()} - notification.Message = "Error uploading script" - notification.Detail = err.Error() - notification.Position = QUASAR_NOTIFICATION_POSITION_TOP - notification.Type = QUASAR_NOTIFICATION_TYPE_NEGATIVE - notification.Timeout = 5000 - QuasarNotify(notification) + QuasarNotifyError("Error uploading script", err.Error(), QUASAR_NOTIFICATION_POSITION_TOP) return } job,err := RunHIDScript(md5, timeout) if err != nil { - notification := &QuasarNotification{Object: O()} - notification.Message = "Error starting script as background job" - notification.Detail = err.Error() - notification.Position = QUASAR_NOTIFICATION_POSITION_TOP - notification.Type = QUASAR_NOTIFICATION_TYPE_NEGATIVE - notification.Timeout = 5000 - QuasarNotify(notification) + QuasarNotifyError("Error starting script as background job", err.Error(), QUASAR_NOTIFICATION_POSITION_TOP) return } - notification := &QuasarNotification{Object: O()} - notification.Message = "Script started successfully" - notification.Detail = "Job ID " + strconv.Itoa(int(job.Id)) - notification.Position = QUASAR_NOTIFICATION_POSITION_TOP - notification.Type = QUASAR_NOTIFICATION_TYPE_POSITIVE - notification.Timeout = 5000 - QuasarNotify(notification) + QuasarNotifySuccess("Script started successfully", "Job ID " + strconv.Itoa(int(job.Id)), QUASAR_NOTIFICATION_POSITION_TOP) }() } -func newCompHIDScriptData(vm *hvue.VM) interface{} { - newVM := &CompHIDScriptData{ - Object: js.Global.Get("Object").New(), - } - //newVM.ScriptContent = "layout('us');\ntype('hello');" - return newVM +type CodeMirrorMode struct { + *js.Object + Name string `js:"name"` + GlobalVars bool `js:"globalVars"` } -func InitCompHIDScript() { +type CodeMirrorExtraKeys struct { + *js.Object + CtrlSpace string `js:"Ctrl-Space"` +} + +type CodeMirrorOptionsType struct { + *js.Object + Mode *CodeMirrorMode `js:"mode"` + LineNumbers bool `js:"lineNumbers"` + LineWrapping bool `js:"lineWrapping"` + AutoCloseBrackets bool `js:"autoCloseBrackets"` + ExtraKeys *CodeMirrorExtraKeys `js:"extraKeys"` +} + +func newCompHIDScriptCodeEditorData(vm *hvue.VM) interface{} { + data := &CompHIDScriptCodeEditorData{ Object: O() } + + data.CodeMirrorOptions = &CodeMirrorOptionsType{Object: O()} + + data.CodeMirrorOptions.Mode = &CodeMirrorMode{ Object: O() } + data.CodeMirrorOptions.Mode.Name = "text/javascript" + data.CodeMirrorOptions.Mode.GlobalVars = true //expose globalVars of mode for auto-complete with addon/hint/show-hint.js, addon/hint/javascript-hint.js" + + data.CodeMirrorOptions.ExtraKeys = &CodeMirrorExtraKeys{ Object: O() } + data.CodeMirrorOptions.ExtraKeys.CtrlSpace = "autocomplete" + + data.CodeMirrorOptions.LineNumbers = true + //data.CodeMirrorOptions.LineWrapping = true + data.CodeMirrorOptions.AutoCloseBrackets = true + + return data +} + + +func InitComponentsHIDScript() { hvue.NewComponent( - "hid-script", - hvue.Template(compHIDScriptTemplate), - hvue.DataFunc(newCompHIDScriptData), - hvue.MethodsOf(&CompHIDScriptData{}), + "hid-script-code-editor", + hvue.Template(compHIDScriptCodeEditorTemplate), + hvue.DataFunc(newCompHIDScriptCodeEditorData), + hvue.MethodsOf(&CompHIDScriptCodeEditorData{}), hvue.ComputedWithGetSet( "scriptContent", func(vm *hvue.VM) interface{} { @@ -77,15 +90,34 @@ func InitCompHIDScript() { vm.Get("$store").Call("commit", VUEX_MUTATION_SET_CURRENT_HID_SCRIPT_SOURCE_TO, newScriptContent) }), ) + + hvue.NewComponent( + "hid-script", + hvue.Template(compHIDScriptTemplate), + ) } const ( compHIDScriptTemplate = ` - + +
+
+ +
+
+ +
+
+
+ +
- - + +
+` + compHIDScriptCodeEditorTemplate = ` + HIDScript editor @@ -99,15 +131,10 @@ const ( - + + - - - - - - ` ) diff --git a/web_client/hvueCompLogger.go b/web_client/hvueCompLogger.go index a22d5dd..e83b4a9 100644 --- a/web_client/hvueCompLogger.go +++ b/web_client/hvueCompLogger.go @@ -57,6 +57,7 @@ func InitCompLogger() { const ( compLoggerTemplate = ` +
@@ -73,7 +74,7 @@ const (
- +
` ) diff --git a/web_client/main.go b/web_client/main.go index d499485..38d769f 100644 --- a/web_client/main.go +++ b/web_client/main.go @@ -71,8 +71,7 @@ func main() { InitCompEthernetAddresses2() InitCompToggleSwitch() InitCompUSBSettings() - InitCompCodeEditor() - InitCompHIDScript() + InitComponentsHIDScript() InitCompLogger() InitCompState() InitComponentsNetwork() diff --git a/web_client/mvuexGlobalState.go b/web_client/mvuexGlobalState.go index b6abe0f..1b3d7da 100644 --- a/web_client/mvuexGlobalState.go +++ b/web_client/mvuexGlobalState.go @@ -13,17 +13,16 @@ var globalState *GlobalState const ( maxLogEntries = 500 - VUEX_ACTION_UPDATE_RUNNING_HID_JOBS = "updateRunningHidJobs" + VUEX_ACTION_UPDATE_RUNNING_HID_JOBS = "updateRunningHidJobs" VUEX_ACTION_DEPLOY_CURRENT_GADGET_SETTINGS = "deployCurrentGadgetSettings" VUEX_ACTION_UPDATE_GADGET_SETTINGS_FROM_DEPLOYED = "updateCurrentGadgetSettingsFromDeployed" - VUEX_ACTION_DEPLOY_ETHERNET_INTERFACE_SETTINGS = "deployEthernetInterfaceSettings" - VUEX_ACTION_UPDATE_WIFI_SETTINGS_FROM_DEPLOYED = "updateCurrentWifiSettingsFromDeployed" - VUEX_ACTION_DEPLOY_WIFI_SETTINGS = "deployWifiSettings" + VUEX_ACTION_DEPLOY_ETHERNET_INTERFACE_SETTINGS = "deployEthernetInterfaceSettings" + VUEX_ACTION_UPDATE_WIFI_SETTINGS_FROM_DEPLOYED = "updateCurrentWifiSettingsFromDeployed" + VUEX_ACTION_DEPLOY_WIFI_SETTINGS = "deployWifiSettings" - - VUEX_MUTATION_SET_CURRENT_GADGET_SETTINGS_TO = "setCurrentGadgetSettings" - VUEX_MUTATION_SET_CURRENT_WIFI_SETTINGS = "setCurrentWifiSettings" - VUEX_MUTATION_SET_CURRENT_HID_SCRIPT_SOURCE_TO = "setCurrentHIDScriptSource" + VUEX_MUTATION_SET_CURRENT_GADGET_SETTINGS_TO = "setCurrentGadgetSettings" + VUEX_MUTATION_SET_CURRENT_WIFI_SETTINGS = "setCurrentWifiSettings" + VUEX_MUTATION_SET_CURRENT_HID_SCRIPT_SOURCE_TO = "setCurrentHIDScriptSource" initHIDScript = `layout('us'); // US keyboard layout typingSpeed(100,150) // Wait 100ms between key strokes + an additional random value between 0ms and 150ms (natural) @@ -53,25 +52,24 @@ for (var i = 3; i < 10; i++) { type GlobalState struct { *js.Object - Title string `js:"title"` - CurrentHIDScriptSource string `js:"currentHIDScriptSource"` - CurrentGadgetSettings *jsGadgetSettings `js:"currentGadgetSettings"` - CurrentlyDeployingGadgetSettings bool `js:"deployingGadgetSettings"` - EventReceiver *jsEventReceiver `js:"eventReceiver"` - HidJobList *jsHidJobStateList `js:"hidJobList"` - IsModalEnabled bool `js:"isModalEnabled"` - IsConnected bool `js:"isConnected"` - FailedConnectionAttempts int `js:"failedConnectionAttempts"` - InterfaceSettings *jsEthernetSettingsList `js:"InterfaceSettings"` - WiFiSettings *jsWiFiSettings `js:"wifiSettings"` + Title string `js:"title"` + CurrentHIDScriptSource string `js:"currentHIDScriptSource"` + CurrentGadgetSettings *jsGadgetSettings `js:"currentGadgetSettings"` + CurrentlyDeployingGadgetSettings bool `js:"deployingGadgetSettings"` + EventReceiver *jsEventReceiver `js:"eventReceiver"` + HidJobList *jsHidJobStateList `js:"hidJobList"` + IsModalEnabled bool `js:"isModalEnabled"` + IsConnected bool `js:"isConnected"` + FailedConnectionAttempts int `js:"failedConnectionAttempts"` + InterfaceSettings *jsEthernetSettingsList `js:"InterfaceSettings"` + WiFiSettings *jsWiFiSettings `js:"wifiSettings"` - Counter int `js:"count"` - Text string `js:"text"` + Counter int `js:"count"` + Text string `js:"text"` } - func createGlobalStateStruct() GlobalState { - state := GlobalState{Object:O()} + state := GlobalState{Object: O()} state.Title = "P4wnP1 by MaMe82" state.CurrentHIDScriptSource = initHIDScript state.CurrentGadgetSettings = NewUSBGadgetSettings() @@ -84,11 +82,15 @@ func createGlobalStateStruct() GlobalState { state.FailedConnectionAttempts = 0 //Retrieve Interface settings // ToDo: Replace panics by default values - ifSettings,err := RpcClient.GetAllDeployedEthernetInterfaceSettings(time.Second*5) - if err != nil { panic("Couldn't retrieve interface settings") } + ifSettings, err := RpcClient.GetAllDeployedEthernetInterfaceSettings(time.Second * 5) + if err != nil { + panic("Couldn't retrieve interface settings") + } state.InterfaceSettings = ifSettings - wifiSettings,err := RpcClient.GetDeployedWiFiSettings(time.Second * 5) - if err != nil { panic("Couldn't retrieve WiFi settings") } + wifiSettings, err := RpcClient.GetDeployedWiFiSettings(time.Second * 5) + if err != nil { + panic("Couldn't retrieve WiFi settings") + } state.WiFiSettings = wifiSettings state.Counter = 1337 @@ -99,13 +101,13 @@ func createGlobalStateStruct() GlobalState { func actionUpdateGadgetSettingsFromDeployed(store *mvuex.Store, context *mvuex.ActionContext, state *GlobalState) { go func() { //fetch deployed gadget settings - dGS,err := RpcClient.RpcGetDeployedGadgetSettings(time.Second * 5) + dGS, err := RpcClient.RpcGetDeployedGadgetSettings(time.Second * 5) if err != nil { println("Couldn't retrieve deployed gadget settings") return } //convert to JS version - jsGS := &jsGadgetSettings{Object:O()} + jsGS := &jsGadgetSettings{Object: O()} jsGS.fromGS(dGS) //commit to current @@ -118,7 +120,7 @@ func actionUpdateGadgetSettingsFromDeployed(store *mvuex.Store, context *mvuex.A func actionUpdateWifiSettingsFromDeployed(store *mvuex.Store, context *mvuex.ActionContext, state *GlobalState) { go func() { //fetch deployed gadget settings - dWS,err := RpcClient.GetDeployedWiFiSettings(time.Second * 5) + dWS, err := RpcClient.GetDeployedWiFiSettings(time.Second * 5) if err != nil { println("Couldn't retrieve deployed WiFi settings") return @@ -131,7 +133,6 @@ func actionUpdateWifiSettingsFromDeployed(store *mvuex.Store, context *mvuex.Act return } - func actionDeployWifiSettings(store *mvuex.Store, context *mvuex.ActionContext, state *GlobalState, settings *jsWiFiSettings) { go func() { println("Vuex dispatch deploy WiFi settings") @@ -139,35 +140,36 @@ func actionDeployWifiSettings(store *mvuex.Store, context *mvuex.ActionContext, goSettings := settings.toGo() err := RpcClient.DeployeWifiSettings(time.Second*3, goSettings) - if err != nil {Alert(err)} + if err != nil { + Alert(err) + } }() } func actionUpdateRunningHidJobs(store *mvuex.Store, context *mvuex.ActionContext, state *GlobalState) { go func() { //fetch deployed gadget settings - jobstates,err := RpcClient.RpcGetRunningHidJobStates(time.Second * 10) + jobstates, err := RpcClient.RpcGetRunningHidJobStates(time.Second * 10) if err != nil { println("Couldn't retrieve stateof running HID jobs", err) return } - for _,jobstate := range jobstates { + 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) + state.HidJobList.UpdateEntry(jobstate.Id, jobstate.VmId, false, false, "initial job state", "", time.Now().String(), jobstate.Source) } }() return } - func actionDeployCurrentGadgetSettings(store *mvuex.Store, context *mvuex.ActionContext, state *GlobalState) { go func() { // ToDo: Indicate deployment process via global state state.CurrentlyDeployingGadgetSettings = true - defer func() {state.CurrentlyDeployingGadgetSettings = false}() + defer func() { state.CurrentlyDeployingGadgetSettings = false }() //get current GadgetSettings curGS := state.CurrentGadgetSettings.toGS() @@ -175,36 +177,17 @@ func actionDeployCurrentGadgetSettings(store *mvuex.Store, context *mvuex.Action //try to set them via gRPC (the server holds an internal state, setting != deploying) err := RpcClient.RpcSetRemoteGadgetSettings(curGS, time.Second) if err != nil { - - //ToDo: use global store to return something, or allow actions to return promises (latter is too much JavaScript) - //Alert(err.Error()) - notification := &QuasarNotification{Object: O()} - notification.Message = "Error in pre-check of new USB gadget settings" - notification.Detail = err.Error() - notification.Position = QUASAR_NOTIFICATION_POSITION_TOP - notification.Type = QUASAR_NOTIFICATION_TYPE_NEGATIVE - notification.Timeout = 5000 - QuasarNotify(notification) + QuasarNotifyError("Error in pre-check of new USB gadget settings", err.Error(), QUASAR_NOTIFICATION_POSITION_TOP) return } //try to deploy the, now set, remote GadgetSettings via gRPC - _,err = RpcClient.RpcDeployRemoteGadgetSettings(time.Second*10) + _, err = RpcClient.RpcDeployRemoteGadgetSettings(time.Second * 10) if err != nil { - //ToDo: use global store to return something, or allow actions to return promises (latter is too much JavaScript) - //Alert(err.Error()) - notification := &QuasarNotification{Object: O()} - notification.Message = "Error while deploying new USB gadget settings" - notification.Detail = err.Error() - notification.Position = QUASAR_NOTIFICATION_POSITION_TOP - notification.Type = QUASAR_NOTIFICATION_TYPE_NEGATIVE - notification.Timeout = 5000 - QuasarNotify(notification) + QuasarNotifyError("Error while deploying new USB gadget settings", err.Error(), QUASAR_NOTIFICATION_POSITION_TOP) return } - //ToDo: If we're here, we succeeded and should indicate this via global state - //Alert("GadgetSettings deployed successfully") notification := &QuasarNotification{Object: O()} notification.Message = "New Gadget Settings deployed successfully" notification.Position = QUASAR_NOTIFICATION_POSITION_TOP @@ -217,7 +200,6 @@ func actionDeployCurrentGadgetSettings(store *mvuex.Store, context *mvuex.Action return } - func actionDeployEthernetInterfaceSettings(store *mvuex.Store, context *mvuex.ActionContext, state *GlobalState, settings *jsEthernetInterfaceSettings) { go func() { println("Vuex dispatch deploy ethernet interface settings") @@ -225,7 +207,9 @@ func actionDeployEthernetInterfaceSettings(store *mvuex.Store, context *mvuex.Ac goSettings := settings.toGo() err := RpcClient.DeployedEthernetInterfaceSettings(time.Second*3, goSettings) - if err != nil {Alert(err)} + if err != nil { + Alert(err) + } }() } @@ -236,40 +220,40 @@ func initMVuex() *mvuex.Store { mvuex.State(state), mvuex.Action("actiontest", func(store *mvuex.Store, context *mvuex.ActionContext, state *GlobalState) { go func() { - for i:=0; i<10; i++ { + for i := 0; i < 10; i++ { println(state.Counter) - time.Sleep(1*time.Second) - context.Commit("increment",5) + time.Sleep(1 * time.Second) + context.Commit("increment", 5) } }() }), - mvuex.Mutation("setModalEnabled", func (store *mvuex.Store, state *GlobalState, enabled bool) { + mvuex.Mutation("setModalEnabled", func(store *mvuex.Store, state *GlobalState, enabled bool) { state.IsModalEnabled = enabled return }), - mvuex.Mutation("increment", func (store *mvuex.Store, state *GlobalState, add int) { + mvuex.Mutation("increment", func(store *mvuex.Store, state *GlobalState, add int) { state.Counter += add return }), - mvuex.Mutation("decrement", func (store *mvuex.Store, state *GlobalState) { + mvuex.Mutation("decrement", func(store *mvuex.Store, state *GlobalState) { state.Counter-- return }), - mvuex.Mutation("setText", func (store *mvuex.Store, state *GlobalState, newText string) { + mvuex.Mutation("setText", func(store *mvuex.Store, state *GlobalState, newText string) { state.Text = newText return }), - mvuex.Mutation(VUEX_MUTATION_SET_CURRENT_HID_SCRIPT_SOURCE_TO, func (store *mvuex.Store, state *GlobalState, newText string) { + mvuex.Mutation(VUEX_MUTATION_SET_CURRENT_HID_SCRIPT_SOURCE_TO, func(store *mvuex.Store, state *GlobalState, newText string) { state.CurrentHIDScriptSource = newText return }), - mvuex.Mutation(VUEX_MUTATION_SET_CURRENT_GADGET_SETTINGS_TO, func (store *mvuex.Store, state *GlobalState, settings *jsGadgetSettings) { + mvuex.Mutation(VUEX_MUTATION_SET_CURRENT_GADGET_SETTINGS_TO, func(store *mvuex.Store, state *GlobalState, settings *jsGadgetSettings) { state.CurrentGadgetSettings = settings return }), - mvuex.Mutation(VUEX_MUTATION_SET_CURRENT_WIFI_SETTINGS, func (store *mvuex.Store, state *GlobalState, settings *jsWiFiSettings) { + mvuex.Mutation(VUEX_MUTATION_SET_CURRENT_WIFI_SETTINGS, func(store *mvuex.Store, state *GlobalState, settings *jsWiFiSettings) { state.WiFiSettings = settings return }), @@ -289,6 +273,28 @@ func initMVuex() *mvuex.Store { mvuex.Action(VUEX_ACTION_DEPLOY_ETHERNET_INTERFACE_SETTINGS, actionDeployEthernetInterfaceSettings), mvuex.Action(VUEX_ACTION_UPDATE_WIFI_SETTINGS_FROM_DEPLOYED, actionUpdateWifiSettingsFromDeployed), mvuex.Action(VUEX_ACTION_DEPLOY_WIFI_SETTINGS, actionDeployWifiSettings), + + mvuex.Getter("testgetterProperty", func(state *GlobalState) interface{} { + //Note: GlobalState is a custom struct, used for the vuex store state + println("getter returning a property, for given state", state) + return state + }), + + mvuex.Getter("testgetterPropertyMulti", func(state *GlobalState) (string, int) { + println("getter returning a property with multiple results converted to an array, for given state", state) + return "two", 2 + }), + + mvuex.Getter("testgetterMethodWithArg", func(state interface{}) interface{} { + println("getter returning a function which takes an argument, input state isn't casted to known struct", state) + return func(i int) int { return i * 2 } // function returning given int multiplied by two + }), + mvuex.Getter("testgetterConsumeGetters", func(state *GlobalState, getters *js.Object) interface{} { + println("getter consuming state and getters as input", state) + println("getter3 getters", getters) + return getters + }), + ) // fetch deployed gadget settings @@ -310,4 +316,4 @@ func initMVuex() *mvuex.Store { func InitGlobalState() *mvuex.Store { return initMVuex() -} \ No newline at end of file +} diff --git a/web_client/quasarHelper.go b/web_client/quasarHelper.go index 91736a0..2bebce0 100644 --- a/web_client/quasarHelper.go +++ b/web_client/quasarHelper.go @@ -21,6 +21,8 @@ const ( QUASAR_NOTIFICATION_POSITION_BOTTOM = "bottom" QUASAR_NOTIFICATION_POSITION_BOTTOM_LEFT = "bottom-left" QUASAR_NOTIFICATION_POSITION_BOTTOM_RIGHT = "bottom-right" + + QUASAR_NOTIFICATION_TIMEOUT = 5000 ) type Quasar struct { @@ -59,3 +61,22 @@ func QuasarNotify(notification *QuasarNotification) { GlobalQuasar.Plugins["Notify"].Call("create", notification) } +func QuasarNotifyError(errorMessage string, messageDetails string, position string) { + notification := &QuasarNotification{Object: O()} + notification.Message = errorMessage + notification.Detail = messageDetails + notification.Position = position + notification.Type = QUASAR_NOTIFICATION_TYPE_NEGATIVE + notification.Timeout = QUASAR_NOTIFICATION_TIMEOUT + QuasarNotify(notification) +} + +func QuasarNotifySuccess(message string, detailMessage string, position string) { + notification := &QuasarNotification{Object: O()} + notification.Message = message + notification.Detail = detailMessage + notification.Position = position + notification.Type = QUASAR_NOTIFICATION_TYPE_POSITIVE + notification.Timeout = QUASAR_NOTIFICATION_TIMEOUT + QuasarNotify(notification) +} \ No newline at end of file