Handle Error Modal on upload
authorFulup Ar Foll <fulup@iot.bzh>
Wed, 27 Jan 2016 12:01:16 +0000 (13:01 +0100)
committerFulup Ar Foll <fulup@iot.bzh>
Wed, 27 Jan 2016 12:01:16 +0000 (13:01 +0100)
13 files changed:
afm-client/app/Frontend/app.js
afm-client/app/Frontend/etc/AppConfig.js
afm-client/app/Frontend/etc/routes.js
afm-client/app/Frontend/images/appli/isnotvalid.png
afm-client/app/Frontend/images/appli/istoobig.png
afm-client/app/Frontend/images/appli/w3c-widget.png
afm-client/app/Frontend/pages/Home/Dashboard.html [deleted file]
afm-client/app/Frontend/pages/Home/DashboardModule.js [deleted file]
afm-client/app/Frontend/pages/Home/DashboardModule.scss [deleted file]
afm-client/app/Frontend/pages/Sample/Sample.html [deleted file]
afm-client/app/Frontend/pages/Sample/SampleModule.js [deleted file]
afm-client/app/Frontend/pages/Sample/SampleModule.scss [deleted file]
afm-client/app/Frontend/widgets/FormInput/UploadAppli.js

index eac36e4..1d8fc2e 100644 (file)
@@ -17,7 +17,6 @@
     'AppConfig',
     'JQueryEmu',
     'DashboardModule',
-    'SampleModule',
     'UploadFiles',
     'LinkButton',
     'TokenRefresh',
index 16a2c87..16c05b5 100644 (file)
@@ -15,7 +15,8 @@
                         image : 'images/',
                         icons : 'images/icons/',
                         avatar: 'images/avatars/',
-                        audio : 'images/audio/'
+                        audio : 'images/audio/',
+                        appli : 'images/appli/'
                     },
                     
                     myapi: { // Warning paths should end with /
@@ -43,7 +44,7 @@
             .factory('AppCall', function ($http, AppConfig) {
                 var myCalls = {
                     get : function(plugin, action, query, callback) {
-                        query["token"] = AppConfig.session.token; // add token to provided query                        
+                        query.token = AppConfig.session.token; // add token to provided query                        
                         $http.get('/api/' + plugin + '/' + action , {params: query}).then (callback, callback);
                     }
 
index 18d281a..31b2d52 100644 (file)
@@ -1 +1 @@
-var foundationRoutes = [{"name":"mysample","url":"/sample","controller":"SampleController as ctrl","animationIn":"slideInRight","path":"pages/Sample/Sample.html"},{"name":"Dashboard","url":"/dashboard","controller":"DashboardController as ctrl","animationIn":"slideInRight","path":"pages/Dashboard/Dashboard.html"},{"name":"dashboard","url":"/dashboard","controller":"DashboardController as ctrl","animationIn":"slideInRight","path":"pages/Home/Dashboard.html"}]; 
+var foundationRoutes = [{"name":"Dashboard","url":"/dashboard","controller":"DashboardController as ctrl","animationIn":"slideInRight","path":"pages/Dashboard/Dashboard.html"}]; 
index 057c215..ae99e83 100644 (file)
Binary files a/afm-client/app/Frontend/images/appli/isnotvalid.png and b/afm-client/app/Frontend/images/appli/isnotvalid.png differ
index 5614073..4e73423 100644 (file)
Binary files a/afm-client/app/Frontend/images/appli/istoobig.png and b/afm-client/app/Frontend/images/appli/istoobig.png differ
index 74d3927..8a3beb9 100644 (file)
Binary files a/afm-client/app/Frontend/images/appli/w3c-widget.png and b/afm-client/app/Frontend/images/appli/w3c-widget.png differ
diff --git a/afm-client/app/Frontend/pages/Home/Dashboard.html b/afm-client/app/Frontend/pages/Home/Dashboard.html
deleted file mode 100644 (file)
index 036148a..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-<!-- Foundation Annotations generate tmp/route.js -->
----
-name: dashboard
-url:  /dashboard
-controller:   DashboardController as ctrl
-animationIn: slideInRight
----
-
-<h3> 
-<img class="logo" src="images/logo/triskel_iot_bzhx250.png" alt="IoT.bzh Logo" style="height:150px;">
-  Application Framework Manager Simple Client
-</h3>
-
-
-
-<div class="button-box box-content ">
-    <appli-button  ng-repeat="appliID in ctrl.appliIDs" store="ctrl.appliStore" handle={{appliID}} callback="ctrl.AppliCB"> </appli-button>
-    <upload-appli  class="ibz-right" label="Upload" icon="fi-upload" posturl="/api/post/upload-appli" callback="ctrl.FileUploaded" title="Upload AGL App"></upload-appli>
-</div>
-
-
-<div class="button-box box-content ">
-      
-    <submit-button class="session-button {{ctrl.APIcheck}}" icon="fi-play-circle" label="Start" clicked="ctrl.StartApp" ></submit-button>
-    <submit-button class="session-button {{ctrl.APIrefresh}}"  icon="fi-x-circle" label="Stop"   clicked="ctrl.StopApp" ></submit-button>
-    <submit-button class="session-button {{ctrl.APIreset}}" icon="fi-x" label="Remove" clicked="ctrl.RemoveApp" ></submit-button>
-    
-</div>
-<div class="message-box box-content vertical grid-frame">
-    <div class="response">
-        <span class="grid-content noscroll req {{ctrl.status}} ">req= {{ctrl.request}}</span>
-        <span class="grid-content noscroll res {{ctrl.status}} ">res= {{ctrl.response}}</span>
-        <span class="grid-content noscroll status {{ctrl.status}}">status= {{ctrl.errcode}}</span>
-    </div>
-</div>
-
-
-<link-button href="sample" icon="fi-home" label="sample"></link-button>
-<token-refresh autolog="true" callback="ctrl.AutoStart"></token-refresh>
-
diff --git a/afm-client/app/Frontend/pages/Home/DashboardModule.js b/afm-client/app/Frontend/pages/Home/DashboardModule.js
deleted file mode 100644 (file)
index f843df1..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-(function() {
-'use strict';
-
-// WARNING: make sure than app/frontend/services/AppConfig.js match your server
-
-// list all rependencies within the page + controler if needed
-angular.module('DashboardModule', ['SubmitButton', 'TokenRefresh', 'AppliButton'])
-
-  .controller('DashboardController', function ($http, AppConfig, Notification) {
-        var scope = this; // I hate JavaScript
-        scope.uuid   ="none";
-        scope.token  ="none";
-        scope.session="none";
-        scope.status ="err-no";
-        scope.appliIDs =[]; // array to hold applications ID
-        scope.appliStore={}; // array to hold applications json description
-
-        scope.ProcessResponse= function(data, errcode, headers, config) {
-            var apiname= 'API'+ data.request.api.replace('-','_');
-            scope.status = "err-ok";
-            scope.errcode= errcode;
-            scope.request  = data.request;
-            scope.response = data.response;
-            
-            // if token was refresh let's update AppConfig
-            if (data.request.token) AppConfig.session.token = data.request.token;
-            if (data.request.uuid)  AppConfig.session.uuid  = data.request.uuid;
-            if (data.request.timeout)  AppConfig.session.timeout  = data.request.timeout;
-
-            // Make sure we clean everything when Open/Close is called
-            if (apiname === "APIcreate" || apiname === "APIreset") {
-                scope.APIreset  ='';
-                scope.APIcreate ='';
-                scope.APIrefresh='';
-                scope.APIcheck  ='';
-            }
-            scope[apiname]="success";
-            
-            // If we have a new token let's update it
-            if (data.request.token) scope.token=data.request.token;
-            
-            console.log ("OK: "+ JSON.stringify(data));
-        };
-        
-        scope.ProcessError= function(data, errcode, headers, config) {
-            var apiname= 'API'+data.request.api.replace('-','_');
-            scope.status   = "err-fx";
-            scope.errcode  = errcode;
-            scope.request  = data.request;
-            scope.response = "";
-            scope[apiname]="fail";
-            
-            console.log ("FX: "+ JSON.stringify(data));
-        };
-
-        scope.OpenSession = function() {
-            console.log ("OpenSession"); 
-            var handler = $http.get(AppConfig.session.create + '?token='+AppConfig.session.initial);
-            
-            handler.success(scope.ProcessResponse);
-            handler.error(scope.ProcessError);
-        };        
-
-        scope.CheckSession = function() {
-            console.log ("CloseSession");
-            var handler = $http.get(AppConfig.session.check + '?token='+AppConfig.session.token);
-            
-            handler.success(scope.ProcessResponse);
-            handler.error(scope.ProcessError);
-        };
-        
-        scope.RefreshSession = function() {
-            console.log ("RefreshSession");
-            var handler = $http.get(AppConfig.session.refresh + '?token='+AppConfig.session.token);
-            
-            handler.success(scope.ProcessResponse);
-            handler.error(scope.ProcessError);
-        };
-        
-        scope.ResetSession = function() {
-            console.log ("ResetSession");
-            var handler = $http.get(AppConfig.session.reset + '?token='+AppConfig.session.token);
-            
-            handler.success(scope.ProcessResponse);
-            handler.error(scope.ProcessError);
-        };
-        
-        scope.AppliCB = function (appliID) {
-            console.log ("Application Clicked ID=[%s]", appliID);
-            
-        };
-        
-        scope.AutoStart = function () {
-            console.log ("AutoStart requesting Apps list");
-            var handler = $http.get('/api/afm-main/runnables' + '?token='+AppConfig.session.token);
-            handler.success(function(result) {
-                
-                // Check this is a valid response from Binder
-                if (result.request.jtype !== "AJB_reply" && result.request.api !== "runnables") {
-                  Notification.error ({message: "Invalid Respond to /opa/afm-main/runnable result="+result, delay: 5000}); 
-                  return;
-                }
-                
-                // loop on runnable application to prepare for display
-                var  appliIDs=[];
-                for (var idx=0; idx < result.response.length; idx ++) {
-                    appliIDs[idx] = result.response [idx].id;
-                    scope.appliStore [result.response [idx].id] =  result.response [idx];
-                }
-                scope.appliIDs = appliIDs; // avoid partial update to limit UI refresh
-                
-            });
-        };
-          
-   });
-
-console.log ("Dashboard Controller Loaded");
-})(); 
\ No newline at end of file
diff --git a/afm-client/app/Frontend/pages/Home/DashboardModule.scss b/afm-client/app/Frontend/pages/Home/DashboardModule.scss
deleted file mode 100644 (file)
index 8bf04a1..0000000
+++ /dev/null
@@ -1,71 +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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-@import "app/ibz-mixins";
-
-$COLOR_SUCCESS: green;
-$COLOR_FAIL: red;
-
-token-refresh {
-    display: block;
-    float: right;
-    margin: .5rem 1rem 0 0;
-}
-
-.button-box {
-    height  : 4.5rem;
-    
-    .session-button {
-      float: left;
-      width: 5rem;
-    };
-    
-    .response > span{
-        display: block;
-        margin: .3rem .5rem .3rem .5rem;        
-    }  
-    
-    .fail { 
-        color:$COLOR_FAIL;
-        border: 1px solid darken($COLOR_FAIL,10%);
-    }
-    .success { 
-        color:$COLOR_SUCCESS; 
-        border: 1px solid darken($COLOR_SUCCESS,10%);
-    }
-
-};
-
-.message-box {
-    height  : auto;
-    width: 100%;
-    font-size: .75rem;
-  
-    .response {
-        .err-no { color:grey; }
-        .res.err-ok { color: blue; }
-        .req.err-ok { color:blueviolet; }
-        .status.err-ok { color:green; }
-        .status.err-fx { color:red; }       
-    } 
-    
-
-};
-
-
-
diff --git a/afm-client/app/Frontend/pages/Sample/Sample.html b/afm-client/app/Frontend/pages/Sample/Sample.html
deleted file mode 100644 (file)
index 03a4558..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-<!-- Foundation Annotations generate tmp/route.js -->
----
-name: mysample
-url:  /sample
-controller:   SampleController as ctrl
-animationIn: slideInRight
----
-
-<h1><img class="logo" src="images/logo/triskel_iot_bzhx250.png" alt="IoT.bzh Logo" style="height:150px;">
-    Post File Upload
-</h1>
-
-<div class="sample-box box-content">
-    
-    <!-- Usage: upload-xxxxx
-         name     = [xxxxxx] is use a field label for xform input field. Should match with server side
-         category = [avatar] should match to a valid directory of thumbnail within AppConfig.path
-         thumbnail= [tux-bzh.png] a valid image within AppConfig.paths.[category]
-         istoobig = [istoobig.png] used image from AppConfig.paths.[category] when file is oversized
-         maxsize  = [xxx] maximum size in KB [default max depend on upload-type]
-         accept = [image] acceptable accept for upload
-    -->
-    <upload-image name="avatar" category="avatar" thumbnail="tux-visitor.png" maxsize="100" 
-        posturl="/api/post/upload-image" callback="ctrl.FileUploaded" accept="image" title="Change your Avatar">
-    </upload-image>
-    
-    <!-- Warning: name=xxx should match with what server expect [used as xform input name -->
-    <upload-audio  name="music" posturl="/api/post/upload-music" callback="ctrl.FileUploaded" title="Upload your Music"></upload-audio>
-
-    <!-- Warning: name=xxx should match with what server expect [used as xform input name -->
-    <upload-appli  name="appli" posturl="/api/post/upload-appli" callback="ctrl.FileUploaded" title="Upload AGL App"></upload-appli>
-
-</div>
-
-<link-button href="home" icon="fi-home" label="home"></link-button>
diff --git a/afm-client/app/Frontend/pages/Sample/SampleModule.js b/afm-client/app/Frontend/pages/Sample/SampleModule.js
deleted file mode 100644 (file)
index 8ae82ea..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-(function() {
-'use strict';
-
-// list all rependencies within the page + controler if needed
-angular.module('SampleModule', ['SubmitButton','UploadFiles'])
-
-  .controller('SampleController', function ($http) {
-        var scope = this; // I hate JavaScript
-
-        console.log ("sample Init");
-        
-        scope.FileUploaded = function (response) {
-           console.log ("FileUploaded response=%s", JSON.stringify(response));
-        };
-   });
-
-console.log ("SampleControler Loaded");
-})(); 
\ No newline at end of file
diff --git a/afm-client/app/Frontend/pages/Sample/SampleModule.scss b/afm-client/app/Frontend/pages/Sample/SampleModule.scss
deleted file mode 100644 (file)
index 7654424..0000000
+++ /dev/null
@@ -1,41 +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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-@import "app/ibz-mixins";
-
-
-.sample-box {
-    display: block;
-    height  : 4.5rem;
-    
-    .sample-button {
-      float: right;
-      width: 5rem;
-    };
-    
-    .muted-on-on,.muted-off-off{
-        background: blueviolet;
-    };
-        
-    .muted-error{
-        background: red;
-    };
-};
-
-
-
index c1b33ac..1ef7ce8 100644 (file)
@@ -39,9 +39,15 @@ var tmplAppli = '<input type="file" name="{{name}}-input" onchange="angular.elem
     
 var tmplModal = '<span class="modal-text">Upload Application <b>{{appname}}</b> ?</span>' +
             '<div>'+
-            '<img ng-src="{{appicon}}">' +
-            '<submit-button icon="fi-x" label="Cancel" clicked="refused"></submit-button>'+
-            '<submit-button icon="fi-like" label="Install" clicked="accepted"></submit-button> ' +
+            '<img ng-src="{{icon}}">' +
+            '<submit-button icon="fi-x" label="Cancel" clicked="abandon"></submit-button>'+
+            '<submit-button icon="fi-like" label="Install" clicked="success"></submit-button> ' +
+            '</div>';
+    
+var tmplError = '<span class="modal-text">Invalid Application <b>{{appname}}</b> ?</span>' +
+            '<div>'+
+            '<img ng-src="{{icon}}">' +
+            '<submit-button icon="fi-x" label="Close" clicked="abandon"></submit-button>'+
             '</div>';
     
 
@@ -90,36 +96,26 @@ function LoadFileSvc (scope, files, fileCB) {
 
     for (var i = 0; i < files.length; i++) {
         this.file = files[i];
-        console.log ("filetype=%s",this.file.type );
         // Unknow Type !!! if (!this.file.type.match(scope.mimetype)) continue;
 
         console.log ("Selected file=" + this.file.name + " size="+ this.file.size/1024 + " Type="+ this.file.type);
+        
+        this.basename= this.file.name.split('/').reverse()[0];
 
         // File to upload is too big
-        if (this.file.size > scope.maxsize*1024) {
-            scope.thumbnail = scope.istoobig; // warning if image path is wrong nothing happen
-            scope.$apply('thumbnail'); // we short-circuit Angular resync Image
-            return;
-        }
-
-        // This is not an uploadable file
-        if(isNaN(this.file.size)) {
-            scope.thumbnail = scope.isnotvalid; 
-            scope.$apply('thumbnail');
-            return;
-        }
-
-        this.basename= this.file.name.split('/').reverse()[0];
-        //scope.imgElem[0].file = this.file;
+        if (isNaN(this.file.size) || this.file.size > scope.maxsize*1024) {
+            setTimeout (fileCB,100);  // On error asynchronous callback without argument
+            
+        } else {
 
-        // If File is an image let display it now
-        if (fileCB) {
+            // If File is readable let's read it
             var reader = new FileReader();
             reader.readAsArrayBuffer(this.file);
             reader.onload = fileCB;
-        } 
-        // if everything is OK let's add file to xform
-        xform.append(scope.name, this.file, this.file.name);
+
+            // if everything is OK let's add file to xform
+            xform.append(scope.name, this.file, this.file.name);
+        }
     }
 }
 
@@ -146,9 +142,9 @@ angular.module('UploadFiles',['AppConfig', 'ModalNotification', 'RangeSlider'])
         scope.UpLoadFile=function (files) {
             var handle; 
             var appicon;
+            var template;
             
-            var accepted = function() {
-                console.log ("Modal Accepted");
+            var success = function() {
                 // This Looks OK let's Post Xform/File
                 handle.postfile(attrs.posturl + "?token=" + AppConfig.session.token);
 
@@ -156,44 +152,61 @@ angular.module('UploadFiles',['AppConfig', 'ModalNotification', 'RangeSlider'])
                 $timeout (function() {scope.modal.destroy();}, 1000);
             };
             
-            var refused = function() {
-                console.log ("Modal Refused");
+            var abandon = function() {
                 scope.modal.deactivate();
                 $timeout (function() {scope.modal.destroy();}, 1000);
             };
                        
             var readerCB = function (upload) {
-
-                var zipapp = new JSZip (upload.target.result);
-                var thumbnail = zipapp.file("icon_128.png");
-                
-                // Check is we have a thumbnail within loaded Zipfile
-                if (!thumbnail) {
-                    console.log ("This is not a valid Application Framework APP");
-                    scope.thumbnail=AppConfig.paths[scope.category] + 'isnotvalid.png';
-                    scope.$apply('thumbnail'); // we short-circuit Angular resync Image
-                } else {
-                    //scope.imgElem[0].src = window.URL.createObjectURL(new Blob([thumbnail.asArrayBuffer()], {type: "image"}));
-                    appicon = window.URL.createObjectURL(new Blob([thumbnail.asArrayBuffer()], {type: "image"}));
+               
+                // File upload fail handle error
+                if (! upload) {
+                    if (handle.file.size > scope.maxsize*1024) {
+                        appicon = scope.istoobig;
+                        template= tmplError;
+                    }
                     
-                    // reference http://foundation.zurb.com/apps/docs/#!/angular-modules
-                    var config = {
-                        animationIn: 'slideInFromTop',
-                        contentScope: {
-                            accepted: accepted,
-                            refused:  refused,
-                            appicon:  appicon,
-                            appname:  handle.basename
-                        }, template:  tmplModal
-                    }; 
-                    // Popup Modal to render application data
-                    scope.modal = new ModalFactory(config);
-                    scope.modal.activate ();
+                    if (isNaN(handle.file.size)) {
+                        appicon = scope.isnotvalid; 
+                        template= tmplError;
+                    }
+                                        
+                } else {
+
+                    var zipapp = new JSZip (upload.target.result);
+                    var thumbnail = zipapp.file("icon_128.png");
+
+                    // Check is we have a thumbnail within loaded Zipfile
+                    if (!thumbnail) {
+                        console.log ("This is not a valid Application Framework APP");
+                        appicon = scope.isnotvalid;
+                        template= tmplError;
+                        
+                    } else {
+                        //scope.imgElem[0].src = window.URL.createObjectURL(new Blob([thumbnail.asArrayBuffer()], {type: "image"}));
+                        appicon = window.URL.createObjectURL(new Blob([thumbnail.asArrayBuffer()], {type: "image"}));
+                        template = tmplModal;
+                    }
                 }
+                
+                // reference http://foundation.zurb.com/apps/docs/#!/angular-modules
+                var config = {
+                    animationIn: 'slideInFromTop',
+                    contentScope: {
+                        success : success,
+                        abandon : abandon,
+                        icon    : appicon,
+                        appname : handle.basename
+                    }, template : template
+                }; 
+                // Popup Modal to render application data
+                scope.modal = new ModalFactory(config);
+                scope.modal.activate ();
             };
             
             // Load file within browser and if OK call readerCB
             handle = new LoadFileSvc (scope, files, readerCB);
+            console.log (handle);
         };
 
         // Initiallize default values from attributes values
@@ -206,7 +219,7 @@ angular.module('UploadFiles',['AppConfig', 'ModalNotification', 'RangeSlider'])
         scope.label   = attrs.label || 'Upload';
         
         if (attrs.thumbnail) scope.isnotvalid= AppConfig.paths[scope.category] +  attrs.isnotvalid;
-        else  scope.isnotvalid=AppConfig.paths[scope.category] + 'isnotvalid.png';
+        else  scope.isnotvalid=AppConfig.paths[scope.category] + 'w3c-widget.png';
 
         if (attrs.istoobig) scope.istoobig= AppConfig.paths[scope.category] +  attrs.istoobig;
         else  scope.istoobig=AppConfig.paths[scope.category] + 'istoobig.png';