UNPKG

pip-webui

Version:

HTML5 UI for LOB applications

410 lines (341 loc) 14.5 kB
/** * @file Document list edit control * @copyright Digital Living Software Corp. 2014-2016 * @todo * - Improve samples in sampler app * - Add add/remove/hover animations */ (function (angular, _) { 'use strict'; var thisModule = angular.module('pipDocumentListEdit', ['ui.event', 'angularFileUpload', 'pipCore', 'pipFocused', 'pipRest', 'pipDocuments.Templates']); thisModule.config(function (pipTranslateProvider) { pipTranslateProvider.translations('en', { DOCUMENT_LIST_EDIT_TEXT: 'Click here to add a document', ERROR_TRANSACTION_IN_PROGRESS: 'Transaction is in progress. Please, wait until it\'s finished or abort' }); pipTranslateProvider.translations('ru', { DOCUMENT_LIST_EDIT_TEXT: 'Нажмите сюда, чтобы добавить документ', ERROR_TRANSACTION_IN_PROGRESS: 'Транзакция еще не завершена. Подождите окончания или прервите её' }); }); thisModule.directive('pipDocumentListEdit', function () { return { restrict: 'EA', scope: { pipDocuments: '=', pipAddedDocument: '=', ngDisabled: '&', pipCreated: '&', pipChanged: '&' }, templateUrl: 'document_list_edit/document_list_edit.html', controller: 'pipDocumentListEditController' }; } ); thisModule.controller('pipDocumentListEditController', function ($scope, $rootScope, $element, $attrs, $parse, $http, $upload, $timeout, pipRest, pipUtils) { var $control = $element.children('.pip-picture-drop'), itemPin = 0; $scope.documentList = {}; $scope.documentList.text = $attrs.pipDefaultText || 'DOCUMENT_LIST_EDIT_TEXT'; $scope.documentList.icon = $attrs.pipDefaultIcon || 'document'; $scope.documentList.iconError = 'warn-circle'; $scope.documentStartState = pipUtils.toBoolean($scope.pipAddedDocument) ? 'copied' : 'original'; $scope.cancelDrag = pipUtils.toBoolean($attrs.pipCanselDrag) === true; $scope.control = { uploading: 0, items: getItems(), reset: resetDocument, save: saveDocument, abort: onAbort }; $scope.filterItem = filterItem; $scope.onDelete = onDelete; $scope.onKeyDown = onKeyDown; $scope.onChange = onChange; $scope.onSelect = onSelect; // Add class $element.addClass('pip-document-list-edit'); // Initialize control $scope.control.reset(); executeCallback(); // Watch for changes $scope.$watchCollection( function () { // Todo: Optimize change tracking return $scope.pipDocuments; }, function (newValue) { if (!_.isEqual(newValue, $scope.pipDocuments)) { $scope.control.reset(); } } ); function getItems() { var documents = $scope.pipDocuments, items = [], i; if (documents === null || documents.length === 0) { return items; } for (i = 0; i < documents.length; i++) { items.push({ pin: itemPin++, id: documents[i].file_id, name: documents[i].file_name, uploading: false, uploaded: false, progress: 0, file: null, state: $scope.documentStartState // 'original' }); } return items; } function setItems() { var item, i; // Clean the array if ($scope.pipDocuments && $scope.pipDocuments.length > 0) { $scope.pipDocuments.splice(0, $scope.pipDocuments.length); } for (i = 0; i < $scope.control.items.length; i++) { item = $scope.control.items[i]; if (item.id) { $scope.pipDocuments.push({ file_id: item.id, file_name: item.name }); } } } function resetDocument() { $scope.control.uploading = 0; $scope.control.items = getItems(); } function getItemIdUrl(item) { var serverUrl = pipRest.serverUrl(), partyId = $rootScope.$party ? $rootScope.$party.id : pipRest.userId(); return serverUrl + '/api/parties/' + partyId + '/files/' + item.id; } function addItemUrl(item) { var serverUrl = pipRest.serverUrl(), partyId = $rootScope.$party ? $rootScope.$party.id : pipRest.userId(); return serverUrl + '/api/parties/' + partyId + '/files?name=' + item.file.name; } function addItem(item, callback) { var file = item.file, fileReader = new FileReader(); // Avoid double transactions if (item.uploading || item.file === null || item.state !== 'added') { return; } fileReader.onload = function (e) { if (item.uploading) { return; } item.uploading = true; item.upload = $upload.http({ url: addItemUrl(item), headers: { 'Content-Type': file.type }, data: e.target.result }) .then( function (response) { item.id = response.data.id; item.name = response.data.filename || item.name; item.uploaded = true; item.uploading = false; item.progress = 0; item.upload = null; item.file = null; item.state = 'original'; callback(); }, function () { item.uploaded = false; item.uploading = false; item.progress = 0; item.upload = null; item.state = 'error'; callback(); }, function (e) { // Math.min is to fix IE which reports 200% sometimes item.progress = Math.min(100, parseInt(100.0 * e.loaded / e.total)); } ); }; fileReader.readAsArrayBuffer(file); } function deleteItem(item, callback) { var control = $scope.control; // Avoid double transactions if (item.upload) { item.upload.abort(); item.upload = null; } if (item.state !== 'deleted') { return; } $http['delete'](getItemIdUrl(item)) .success(function () { _.remove(control.items, {pin: item.pin}); callback(); }) .error(function (data) { // Todo: perform a better processing if (data == null) { _.remove(control.items, {pin: item.pin}); } else { item.uploaded = false; item.uploading = false; item.progress = 0; item.upload = null; } callback(data); }); } function saveDocument(successCallback, errorCallback) { var control = $scope.control, onItemCallback, item, i; if (control.uploading) { if (errorCallback) { errorCallback('ERROR_TRANSACTION_IN_PROGRESS'); } return; } control.error = null; control.uploading = 0; onItemCallback = function (error) { // Storing only the first error if (error && !control.error) { control.error = error; } control.uploading--; // Finished uploading if (control.uploading == 0) { if (control.error) { if (errorCallback) { errorCallback(control.error); } else { console.error(control.error); // eslint-disable-line no-console } } else { setItems(); if (successCallback) { successCallback(); } } } }; for (i = 0; i < control.items.length; i++) { item = control.items[i]; if (item.state === 'added') { control.uploading++; addItem(item, onItemCallback); } else if (item.state === 'deleted') { control.uploading++; deleteItem(item, onItemCallback); } } // Nothing was uploaded if (control.uploading == 0) { if (successCallback) { successCallback(); } } } function onAbort() { var control = $scope.control, item, i; for (i = 0; i < control.items.length; i++) { item = control.items[i]; if (item.uploading) { if (item.upload) { item.upload.abort(); } item.uploaded = false; item.uploading = false; item.progress = 0; item.upload = null; } } // Abort transaction control.uploading = 0; } // Visualization functions function filterItem(item) { return item.state !== 'deleted'; } // Process user actions function onSelect($files) { var file, i; $control.focus(); if ($files == null || $files.length === 0) { return; } for (i = 0; i < $files.length; i++) { file = $files[i]; $scope.control.items.push({ pin: itemPin++, id: null, name: file.name, uploading: false, uploaded: false, progress: 0, file: file, state: 'added' }); } $scope.onChange(); } function onDelete(item) { if (item.state === 'added' || item.state === 'copied') { _.remove($scope.control.items, {pin: item.pin}); } else { item.state = 'deleted'; } $scope.onChange(); } function onKeyDown($event, item) { if (item) { if ($event.keyCode === 46 || $event.keyCode === 8) { if (item.state === 'added') { _.remove($scope.control.items, { pin: item.pin }); } else { item.state = 'deleted'; } $scope.onChange(); } } else if ($event.keyCode === 13 || $event.keyCode === 32) { // !! Avoid clash with $apply() setTimeout(function () { $control.trigger('click'); }, 0); } } // On change event function onChange() { if ($scope.pipChanged) { $scope.pipChanged({ $event: { sender: $scope.control }, $control: $scope.control }); } } function executeCallback() { // Execute callback if ($scope.pipCreated) { $scope.pipCreated({ $event: { sender: $scope.control }, $control: $scope.control }); } } } ); })(window.angular, window._);