diff options
Diffstat (limited to 'afb-client/app/Frontend/widgets')
-rw-r--r-- | afb-client/app/Frontend/widgets/ActionButtons/ActionButtons.scss (renamed from afb-client/app/Frontend/widgets/Buttons/SubmitButtons/SubmitButtons.scss) | 18 | ||||
-rw-r--r-- | afb-client/app/Frontend/widgets/ActionButtons/AppliButton.js | 205 | ||||
-rw-r--r-- | afb-client/app/Frontend/widgets/ActionButtons/SubmitButton.js (renamed from afb-client/app/Frontend/widgets/Buttons/SubmitButtons/SubmitButtons.js) | 2 | ||||
-rw-r--r-- | afb-client/app/Frontend/widgets/FormInput/InputPassword.js | 79 | ||||
-rw-r--r-- | afb-client/app/Frontend/widgets/FormInput/InputText.js | 179 | ||||
-rw-r--r-- | afb-client/app/Frontend/widgets/FormInput/UploadFiles.js | 2 | ||||
-rw-r--r-- | afb-client/app/Frontend/widgets/Notifications/TokenRefreshSvc.js | 4 |
7 files changed, 227 insertions, 262 deletions
diff --git a/afb-client/app/Frontend/widgets/Buttons/SubmitButtons/SubmitButtons.scss b/afb-client/app/Frontend/widgets/ActionButtons/ActionButtons.scss index 2150e4d..6cb8338 100644 --- a/afb-client/app/Frontend/widgets/Buttons/SubmitButtons/SubmitButtons.scss +++ b/afb-client/app/Frontend/widgets/ActionButtons/ActionButtons.scss @@ -19,4 +19,22 @@ @import "app/ibz-mixins"; // place here your submit buttons customization +appli-button { + @include ibz-button(grey,1rem) + img { + height: 3rem; + } + + + .disable>i { + text-decoration:none; // really not needed for the Top Bar, just for general technique + cursor: auto; + color: grey !important; + } +} +.appli-menu-start { + .start-start, .stop-stop { + i {color: grey;} + } +} diff --git a/afb-client/app/Frontend/widgets/ActionButtons/AppliButton.js b/afb-client/app/Frontend/widgets/ActionButtons/AppliButton.js new file mode 100644 index 0000000..269ee81 --- /dev/null +++ b/afb-client/app/Frontend/widgets/ActionButtons/AppliButton.js @@ -0,0 +1,205 @@ +/* + * Copyright (C) 2015 "IoT.bzh" + * Author "Fulup Ar Foll" + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Bugs: Input with Callback SHOULD BE get 'required' class + */ + +(function () { + 'use strict'; + + var tmplAppli = '<div ng-click="clicked()">' + + '<img ng-src="{{icon}}">' + + '<span>{{label}}</span>' + + '</div>'; + + var tmplModal = + '<b class="close-button" ng-click="close()">×</b>' + + '<img ng-src="{{icon}}">' + + '<span class="modal-text">Application <b>{{label}}</b></span>' + + '<ul class="vertical icon-left primary menu-bar appli-menu-start">' + + '<li class=start-{{runstatus}}><a ng-click=action("start")><i class="fi-check"> Start</i></a></li>' + + '<li class=stop-{{runstatus}}><a ng-click=action("stop")><i class="fi-x"> Stop</i></a></li>' + + '<li><a ng-click=action("info")><i class="fi-info"> Info</i></a></li>' + + '<li class=start-{{runstatus}}><a ng-click=action("uninstall")><i class="fi-x"> Uninstall</i></a></li>' + + '</ul>' + + ''; + + var tmplDetail = + '<b class="close-button" ng-click="close()">×</b>' + + '<img ng-src="{{icon}}">' + + '<span class="modal-text">Application <b>{{label}}</b></span>' + + '<ul class="vertical icon-left appli-menu-info">' + + '<li><i class="fi-paperclip"> Name : {{detail.name}} </i></li>' + + '<li><i class="fi-info"> Description {{detail.description}}</i></li>' + + '<li><i class="fi-torso"> Author : {{detail.author}}</i></li>' + + '</ul>' + + ''; + + angular.module('AppliButton', []) + .directive('appliButton', function (AppConfig, AppCall, ModalFactory, Notification, $timeout, $window, $location, urlquery) { + + function mymethods(scope, elem, attrs) { + scope.runstatus = "stop"; + scope.runmode = urlquery.runmode || "auto"; + scope.clicked = function () { + + var notifyError = function(action, response) { + Notification.error ({message: "Fail /api/afm-main" + action + "=" + scope.label + " RunID="+ scope.appID, delay: 5000}); + elem.addClass ("fail"); + elem.removeClass ("success"); + scope.callback (scope.appID, action, response); + }; + + var notifySuccess = function (action, response) { + elem.removeClass ("fail"); + scope.runID = response.data.response.runid; + scope.callback (scope.appID, action, response); + }; + + var closeModApp = function() { + scope.modApp.deactivate(); + $timeout (function() {scope.modApp.destroy();}, 1000); + }; + + var closeModInfo = function() { + scope.modInfo.deactivate(); + $timeout (function() {scope.modInfo.destroy();}, 1000); + }; + + var actionModal = function(action) { + console.log ("Modal Action=%s", action); + switch (action) { + + case "start": + if (scope.runstatus !== "stop") return; + AppCall.get ("afm-main", "start", {id: scope.appID, mode: scope.runmode}, function(response) { + if (response.status !== 200 || response.data.jtype !== "afb-reply") { + notifyError ("start", response); + return; + } + scope.runstatus="start"; + notifySuccess (action, response); + if(response.data.response.uri) + scope.winapp= $window.open(response.data.response.uri.replace("%h", $location.host())); + }); + break; + + case "stop": + if (scope.runstatus !== "start") return; + + AppCall.get ("afm-main", "terminate", {runid: scope.runID}, function(response) { + if (response.status !== 200 || response.data.jtype !== "afb-reply") { + notifyError ("stop", response); + return; + } + scope.runstatus="stop"; + + // if a remote window app was open let's close it + if (scope.winapp) { + console.log ("Closing Application Window label=%s id=%s", scope.label, scope.appID); + scope.winapp.close(); + scope.winapp=false; + } + notifySuccess (action, response); + }); + break; + + case "info": + AppCall.get ("afm-main", "detail", {id: scope.appID}, function(response) { + if (response.status !== 200 || response.data.jtype !== "afb-reply") { + notifyError ("detail", response); + return; + } + + // reference http://foundation.zurb.com/apps/docs/#!/angular-modules + var config = { + animationIn: 'slideInFromTop', + contentScope: { + close : closeModInfo, + icon : scope.icon, + label : scope.appID, + detail : response.data.response + }, template : tmplDetail + }; + // Popup Modal to render application data + scope.modInfo = new ModalFactory(config); + scope.modInfo.activate (); + + }); + break; + + case "uninstall": + if (scope.runstatus !== "stop") return; + AppCall.get ("afm-main", "uninstall", {id: scope.appID}, function(response) { + if (response.status !== 200 || response.data.jtype !== "afb-reply") { + notifyError ("uninstall", response); + return; + } + + notifySuccess (action, response); + }); + break; + + default: + console.log ("ActionModal unknown action=[%s]", action); + break; + } + + closeModApp(); + }; + + // reference http://foundation.zurb.com/apps/docs/#!/angular-modules + var config = { + animationIn: 'slideInFromTop', + contentScope: { + action : actionModal, + runstatus: scope.runstatus, + close : closeModApp, + icon : scope.icon, + label : scope.label + }, template : tmplModal + }; + // Popup Modal to render application data + scope.modApp = new ModalFactory(config); + scope.modApp.activate (); + }; + + // extract application information from AppID+Store + if (attrs.handle && scope.store [attrs.handle].name) { + scope.icon = AppConfig.paths.icons + attrs.handle; //scope.store [attrs.handle].name.toLowerCase() + '-ico.png'; + scope.label = scope.store [attrs.handle].name; + scope.appID= attrs.handle; + } else { + scope.icon = AppConfig.paths.icons + 'w3c-ico.png'; + scope.label = attrs.handle; + } + + // add label as class + elem.addClass (scope.label.toLowerCase()); + + // note: clicked in imported and when template is clicked + // it will call clicked method passed in param. + } + + return { + restrict: 'E', + template: tmplAppli, + link: mymethods, + scope: {callback: '=', store: '='} + }; + }); +})(); diff --git a/afb-client/app/Frontend/widgets/Buttons/SubmitButtons/SubmitButtons.js b/afb-client/app/Frontend/widgets/ActionButtons/SubmitButton.js index cba2aeb..323cd46 100644 --- a/afb-client/app/Frontend/widgets/Buttons/SubmitButtons/SubmitButtons.js +++ b/afb-client/app/Frontend/widgets/ActionButtons/SubmitButton.js @@ -21,7 +21,7 @@ (function () { 'use strict'; - var tmpl = '<div ng-click="clicked()"> <span>' + + var tmpl = '<div ng-click="clicked()">' + '<i class="{{icon}}"></i>' + '<span>{{label}}</span>' + '</div>'; diff --git a/afb-client/app/Frontend/widgets/FormInput/InputPassword.js b/afb-client/app/Frontend/widgets/FormInput/InputPassword.js deleted file mode 100644 index 157009c..0000000 --- a/afb-client/app/Frontend/widgets/FormInput/InputPassword.js +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (C) 2015 "IoT.bzh" - * Author "Fulup Ar Foll" - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU 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 General Public License for more details. - */ - -(function() { -'use strict'; - -var tmpl = '<input-text class="password" tip="{{tip1}}" placeholder="{{place1}}"' + - 'label="{{label1}}" callback="valid1" name="{{name}}-1" value="pass1" required minlen="{{minlen}}" type="password" >' + - '</input-text>' + - '<input-text class="password" tip="tip2" placeholder="{{place2}}"' + - 'label="{{label2}}" callback="valid2" name="{{name}}-2" value="pass2" required minlen="{{minlen}}" type="password" > '+ - '</input-text>'; - -angular.module('InputPassword',[]) - -.directive('inputPassword', function() { - function mymethods(scope, elem, attrs) { - - scope.valid1 = function (name, value) { - console.log ("Clicked InputPassword1 name=%s value=%s", name, value); - scope.firstpwd = value; - }; - - scope.valid2 = function (name, value, done) { - console.log ("Clicked InputPassword2 name=%s value=%s", name, value); - - // if both passwd equal then call form CB - if (scope.firstpwd !== value) { - done({valid: false, status: 'invalid', errmsg: "both password should match"}); - } else { - scope.callback (attrs.name, value); - } - - }; - - // this method can be called from controller to update widget status - scope.done=function (data) { - console.log ("Text-Input Callback ID="+ attrs.name + " data=", data); - for (var i in data) scope[i] = data[i]; - }; - - // Export some attributes within directive scope for template - scope.name = attrs.name; - scope.label1 = attrs.label || 'Password'; - scope.label2 = attrs.label || 'Password Verification'; - scope.place1 = attrs.placeholder1 || 'User Password'; - scope.tip1 = attrs.tip || 'Choose a Password'; - scope.place2 = attrs.placeholder1 || 'Password Verification'; - scope.tip2 = attrs.tip || 'Confirme your Password'; - scope.minlen = attrs.minlen || 10; - - if ("required" in attrs) scope.required = 'required'; - - } - - return { - restrict: 'E', - template: tmpl, - link: mymethods, - scope: { - callback : '=', - } - }; -}); - -console.log ("InputPassword Loaded"); -})(); diff --git a/afb-client/app/Frontend/widgets/FormInput/InputText.js b/afb-client/app/Frontend/widgets/FormInput/InputText.js deleted file mode 100644 index 2653175..0000000 --- a/afb-client/app/Frontend/widgets/FormInput/InputText.js +++ /dev/null @@ -1,179 +0,0 @@ - -/* - * Copyright (C) 2015 "IoT.bzh" - * Author "Fulup Ar Foll" - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU 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 General Public License for more details.. - */ - - - -(function() { -'use strict'; - -var tmpl = '<tip-modal tip="tip"></tip-modal>' + - '<label for="{{name}}-intext">{{label}} <i ng-show="required" ng-click="ToBeDefined" ' + - 'class="required {{status}} fi-checkbox" title="Free Value But Mandatory Argument" alt="?"> </i></label>'+ - '<input '+ - ' type="{{type}}" id="{{name}}-intext" placeholder="{{placeholder}}" class="status-{{status}}"'+ - ' ng-model="value" ng-blur="validate()" ng-focus="selected()" '+ - ' ng-model-options="{ updateOn: \'default blur\', debounce: {default: 500, blur: 0} }"' + - '><alert data-ng-show="!valid&&errmsg">{{errmsg}}</alert>'; - -var emailpatern = /^(([^<>()[\]\.,;:\s@\"]+(\.[^<>()[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i; - -angular.module('InputText',['JQueryEmu']) - -.directive('inputText', function(JQemu) { - function mymethods(scope, elem, attrs) { - - // default value at 1st rendering - scope.error = false; - scope.valid = false; - scope.status = 'untouch'; - - scope.input = elem.find ("input"); - scope.required = 0; - - // requirer is use to increment requested counter - if ("required" in attrs) { - scope.required = 1; - elem.addClass ("required"); - } - - // user enter input reset error status - scope.selected = function () { - scope.error=false; - scope.errmsg=false; - scope.status = 'touch'; - }; - - scope.validate = function () { - - // get value from input field bypassing Angular ng-model - console.log ("Clicked InputText name=%s value=%s valid=%s", scope.name, scope.value, scope.valid); - - // form is not untouched anymore - scope.parent.removeClass ("ng-pristine"); - - // if value not null clean up string - if (scope.value) { - scope.error=false; - // remove leading and trailling space - scope.value = scope.value.trim(); - - // remove any space is not allowed - if ('nospace' in attrs) { - scope.value=scope.value.replace(/\s/g, ''); - } - - if ('lowercase' in attrs) { - scope.value = scope.value.toLowerCase(); - } - - // check minimum lenght - if ("minlen" in attrs) { - if (scope.value.length < attrs.minlen) { - scope.status='invalid'; - scope.errmsg=scope.name + ': Mininum Lengh= ' + attrs.minlen + ' Characters'; - scope.error=true; - } - } - - if ('email' in attrs) { - if (!emailpatern.test (scope.value)) { - scope.status='invalid'; - scope.errmsg='invalid email address'; - scope.error=true; - } - } - - } else { - if (scope.required) { - scope.status='invalid'; - scope.errmsg=scope.name + ': Required Attribute'; - scope.error=true; - } - } - - // If local control fail let's refuse input - if (scope.error) { - if (scope.required && scope.valid) { - scope.valid = false; - if (scope.l4acounter.validated > 0) scope.l4acounter.validated --; - } - // use call to update form scope on form completeness - scope.callback (attrs.name, null, scope.done); - } else { - // localcheck is OK backup may nevertheless change status to false - if (scope.required && !scope.valid) scope.l4acounter.validated ++; - scope.status='valid'; - scope.valid=true; - scope.callback (attrs.name, scope.value, scope.done); - } - - }; - - // this method can be called from controller to update widget status - scope.done=function (data) { - console.log ("Text-Input Callback ID="+ attrs.name + " data=", data); - for (var i in data) scope[i] = data[i]; - }; - - // Export some attributes within directive scope for template - scope.label = attrs.label; - scope.name = attrs.name; - scope.placeholder = attrs.placeholder; - scope.type = attrs.type || "text"; - scope.tip = attrs.tip; - - // search for form within parent elemnts - scope.parent = JQemu.parent (elem, "FORM"); - - // email enforce lowercase and nospace - if ("email" in attrs) { - attrs.lowercase=true; - attrs.nospace=true; - attrs.minlen=6; - } - - if (scope.required) { - scope.l4acounter = scope.parent.data ("l4acounter"); - if (!scope.l4acounter) { - scope.l4acounter = {required:1, validated:0}; - console.log("Field "+scope.name+" is required (1st)"); - scope.parent.data ("l4acounter", scope.l4acounter); - } else { - console.log("Field "+scope.name+" is required"); - scope.l4acounter.required ++; - } - } - - // refresh validation each time controler update value - scope.$watch ('value', function(){ - if(scope.value) scope.validate(); } - ); - - } - - return { - restrict: 'E', - template: tmpl, - link: mymethods, - scope: { - callback : '=', - value: '=' - } - }; -}); - -console.log ("InputText Loaded"); -})(); diff --git a/afb-client/app/Frontend/widgets/FormInput/UploadFiles.js b/afb-client/app/Frontend/widgets/FormInput/UploadFiles.js index a23809f..90110c9 100644 --- a/afb-client/app/Frontend/widgets/FormInput/UploadFiles.js +++ b/afb-client/app/Frontend/widgets/FormInput/UploadFiles.js @@ -157,7 +157,7 @@ angular.module('UploadFiles',['AppConfig', 'ModalNotification', 'RangeSlider']) }; // Initiallize default values from attributes values - scope.name= attrs.name || 'avatar'; + scope.name= attrs.name || 'file'; scope.category= attrs.category || 'image'; scope.mimetype= (attrs.accept || 'image') + '/*'; scope.maxsize= attrs.maxsize || 100; // default max size 100KB diff --git a/afb-client/app/Frontend/widgets/Notifications/TokenRefreshSvc.js b/afb-client/app/Frontend/widgets/Notifications/TokenRefreshSvc.js index 3e5e8d6..4dee196 100644 --- a/afb-client/app/Frontend/widgets/Notifications/TokenRefreshSvc.js +++ b/afb-client/app/Frontend/widgets/Notifications/TokenRefreshSvc.js @@ -68,7 +68,7 @@ angular.module('TokenRefresh', ['AppConfig', 'ModalNotification']) scope.onsuccess = function(jresp, errcode) { if (errcode !== 200 || jresp.request.status !== "success") { - Notification.warning ({message: jresp.request.info, delay: 5000}); + Notification.warning ({message: "auto-connect :" + jresp.request.info, delay: 10000}); scope.offline(); return false; } @@ -111,7 +111,7 @@ angular.module('TokenRefresh', ['AppConfig', 'ModalNotification']) // Initial connection scope.loggin = function() { - AppCall.get (scope.plugin, "login", {token: AppConfig.session.initial}, function(jresp, errcode) { + AppCall.get (scope.plugin, "connect", {token: AppConfig.session.initial}, function(jresp, errcode) { if (!scope.onsuccess (jresp, errcode)) return; |