From 3ebdce373e134b70b129154d8033c1c628847a6c Mon Sep 17 00:00:00 2001 From: Fulup Ar Foll Date: Mon, 25 Jan 2016 14:37:32 +0100 Subject: First version --- .../app/Frontend/widgets/FormInput/UploadAppli.js | 230 +++++++++++++++++++++ 1 file changed, 230 insertions(+) create mode 100644 afm-client/app/Frontend/widgets/FormInput/UploadAppli.js (limited to 'afm-client/app/Frontend/widgets/FormInput/UploadAppli.js') diff --git a/afm-client/app/Frontend/widgets/FormInput/UploadAppli.js b/afm-client/app/Frontend/widgets/FormInput/UploadAppli.js new file mode 100644 index 0000000..d18f620 --- /dev/null +++ b/afm-client/app/Frontend/widgets/FormInput/UploadAppli.js @@ -0,0 +1,230 @@ + +/* + * 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.. + * + * Reference: + * https://developer.mozilla.org/en/docs/Web/API/FileReader + * https://developer.mozilla.org/en-US/docs/Using_files_from_web_applications#Using_hidden_file_input_elements_using_the_click%28%29_method + * https://uncorkedstudios.com/blog/multipartformdata-file-upload-with-angularjs + * https://www.terlici.com/2015/05/16/uploading-files-locally.html + * https://github.com/nervgh/angular-file-upload/blob/master/src/services/FileUploader.js + * https://stuk.github.io/jszip/documentation/howto/read_zip.html + * http://onehungrymind.com/zip-parsing-jszip-angular/ + * http://stackoverflow.com/questions/15341912/how-to-go-from-blob-to-arraybuffer + * + * Bugs: zip file sent even when flag as invalid + */ + + + +(function() { +'use strict'; + +var tmplAppli = ''+ + '
' + + ' {{label}}' + + '' + + '
'; + +var tmplModal = 'Upload Application {{appname}} ?' + + '
'+ + '' + + ''+ + ' ' + + '
'; + + +// Service Create xform insert files in and Post it to url +function LoadFileSvc (scope, files, fileCB) { + var xmlReq = new XMLHttpRequest(); + var xform = new FormData(); + + // Update slider during Upload + xmlReq.upload.onprogress = function (event) { + var progress = Math.round(event.lengthComputable ? event.loaded * 100 / event.total : 0); + if (scope.slider) scope.slider.setValue (progress); + }; + + // Upload is finish let's notify controler callback + xmlReq.onload = function () { + scope.divElem.addClass ("success"); + scope.divElem.removeClass ("error"); + var response ={ + status : xmlReq.status, + headers: xmlReq.getAllResponseHeaders() + }; + scope.callback (response); + }; + + xmlReq.onerror = function () { + scope.divElem.addClass ("error"); + scope.divElem.removeClass ("success"); + }; + + xmlReq.onabort = function () { + scope.divElem.addClass ("error"); + scope.divElem.removeClass ("success"); + var response ={ + status : xmlReq.status, + headers: xmlReq.getAllResponseHeaders() + }; + scope.callback (response); + }; + + this.postfile = function(posturl) { + // everything looks OK let's Post it + xmlReq.open("POST", posturl , true); + xmlReq.send(xform); + }; + + 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); + + // 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 File is an image let display it now + if (fileCB) { + 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); + } + +} + +angular.module('UploadFiles',['AppConfig', 'ModalNotification', 'RangeSlider']) + +.directive('uploadAppli', function(AppConfig, JQemu, Notification, ModalFactory, $timeout) { + function mymethods(scope, elem, attrs) { + + // get widget image handle from template + scope.inputElem = elem.find('input'); + scope.divElem = elem.find('div'); + + // Image was ckick let's simulate an input (file) click + scope.imgClicked = function () { + scope.inputElem[0].click(); // Warning Angular TriggerEvent does not work!!! + }; + + // Slider control handle registration after creation + scope.SliderInitCB=function (slider) { + scope.slider= slider; + }; + + // Upload is delegated to a shared function + scope.UpLoadFile=function (files) { + var handle; + var appicon; + + var accepted = function() { + console.log ("Modal Accepted"); + // This Looks OK let's Post Xform/File + handle.postfile(attrs.posturl + "?token=" + AppConfig.session.token); + + scope.modal.deactivate(); + $timeout (function() {scope.modal.destroy();}, 1000); + }; + + var refused = function() { + console.log ("Modal Refused"); + 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"})); + + // 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 (); + } + }; + + // Load file within browser and if OK call readerCB + handle = new LoadFileSvc (scope, files, readerCB); + }; + + // Initiallize default values from attributes values + scope.name= attrs.name || 'appli'; + scope.category= attrs.category || 'appli'; + scope.mimetype= (attrs.accept || '.wgt'); + scope.maxsize = attrs.maxsize || 100000; // default max size 100MB + scope.regexp = new RegExp (attrs.accept+ '.*','i'); + scope.icon = attrs.icon || 'fi-upload'; + 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'; + + if (attrs.istoobig) scope.istoobig= AppConfig.paths[scope.category] + attrs.istoobig; + else scope.istoobig=AppConfig.paths[scope.category] + 'istoobig.png'; + scope.noslider = attrs.noslider || false; + + if (!attrs.posturl) throw new TypeError('file-upload %s posturl=/api/xxxx/xxxx required', scope.attrs); + } + return { + restrict: 'E', + template: tmplAppli, + link: mymethods, + scope: { + callback : '=' + } + }; + +}); + +console.log ("UploadFile Loaded"); +})(); -- cgit 1.2.3-korg