From f44610a17c78a445e16fda47d62ca0cba531be6c Mon Sep 17 00:00:00 2001 From: Tim Otten Date: Tue, 9 Dec 2014 00:15:05 -0800 Subject: [PATCH] CRM-15578 - crmAttachment - Angular module for file attachments --- CRM/Core/Page/Angular.php | 2 + css/angular-crmAttachment.css | 21 ++++ js/angular-crmAttachment.js | 133 ++++++++++++++++++++++++ partials/crmAttachment/attachments.html | 43 ++++++++ 4 files changed, 199 insertions(+) create mode 100644 css/angular-crmAttachment.css create mode 100644 js/angular-crmAttachment.js create mode 100644 partials/crmAttachment/attachments.html diff --git a/CRM/Core/Page/Angular.php b/CRM/Core/Page/Angular.php index da6180e831..4626cb6073 100644 --- a/CRM/Core/Page/Angular.php +++ b/CRM/Core/Page/Angular.php @@ -68,7 +68,9 @@ class CRM_Core_Page_Angular extends CRM_Core_Page { $angularModules['ui.sortable'] = array('ext' => 'civicrm', 'js' => array('packages/bower_components/angular-ui-sortable/sortable.min.js')); $angularModules['unsavedChanges'] = array('ext' => 'civicrm', 'js' => array('packages/bower_components/angular-unsavedChanges/dist/unsavedChanges.min.js')); // https://github.com/jwstadler/angular-jquery-dialog-service + $angularModules['angularFileUpload'] = array('ext' => 'civicrm', 'js' => array('packages/bower_components/angular-file-upload/angular-file-upload.min.js')); $angularModules['dialogService'] = array('ext' => 'civicrm' , 'js' => array('packages/bower_components/angular-jquery-dialog-service/dialog-service.js')); + $angularModules['crmAttachment'] = array('ext' => 'civicrm', 'js' => array('js/angular-crmAttachment.js'), 'css' => array('css/angular-crmAttachment.css')); $angularModules['crmUi'] = array('ext' => 'civicrm', 'js' => array('js/angular-crm-ui.js')); $angularModules['crmUtil'] = array('ext' => 'civicrm', 'js' => array('js/angular-crm-util.js')); diff --git a/css/angular-crmAttachment.css b/css/angular-crmAttachment.css new file mode 100644 index 0000000000..31c6e2f5e3 --- /dev/null +++ b/css/angular-crmAttachment.css @@ -0,0 +1,21 @@ +.crm-attachments { + border: 1px solid transparent; +} + +.crm-attachments.nv-file-over { + border: 1px solid red; +} + +.crm-attachments td.filename { + font-size: 0.8em; + font-family: 'Courier New', monospace; + vertical-align: middle; +} + +.crm-attachments td.filename-new { + font-style: italic; +} + +.crm-attachments td .crm-form-text { + width: 30em; +} diff --git a/js/angular-crmAttachment.js b/js/angular-crmAttachment.js new file mode 100644 index 0000000000..57c2e690f4 --- /dev/null +++ b/js/angular-crmAttachment.js @@ -0,0 +1,133 @@ +/// crmFile: Manage file attachments +(function (angular, $, _) { + var partialUrl = function (relPath) { + return CRM.resourceUrls['civicrm'] + '/partials/crmAttachment/' + relPath; + }; + + angular.module('crmAttachment', ['angularFileUpload']); + + // crmAttachment manages the list of files which are attached to a given entity + angular.module('crmAttachment').factory('CrmAttachments', function (crmApi, crmStatus, FileUploader, $q) { + var _target; + + // @param target an Object(entity_table:'',entity_id:'') or function which generates an object + function CrmAttachments(target) { + _target = target; + var crmAttachments = this; + this.files = []; + this.uploader = new FileUploader({ + url: CRM.url('civicrm/ajax/attachment'), + onAfterAddingFile: function onAfterAddingFile(item) { + item.crmData = { + description: '' + }; + }, + onSuccessItem: function onSuccessItem(item, response, status, headers) { + crmAttachments.files.push(response.file.values[response.file.id]); + crmAttachments.uploader.removeFromQueue(item); + }, + onErrorItem: function onErrorItem(item, response, status, headers) { + var msg = (response && response.file && response.file.error_message) ? response.file.error_message : ts('Unknown error'); + CRM.alert(item.file.name + ' - ' + msg, ts('Attachment failed')); + crmAttachments.uploader.removeFromQueue(item); + } + }); + } + + angular.extend(CrmAttachments.prototype, { + // @return Object(entity_table:'',entity_id:'') + getTarget: function () { + return (angular.isFunction(_target) ? _target() : _target); + }, + // @return Promise + load: function load() { + var target = this.getTarget(); + var Attachment = this; + + if (target.entity_id) { + var params = { + entity_table: target.entity_table, + entity_id: target.entity_id + }; + return crmApi('Attachment', 'get', params).then(function (apiResult) { + Attachment.files = _.values(apiResult.values); + return Attachment; + }); + } + else { + var dfr = $q.defer(); + Attachment.files = []; + dfr.resolve(Attachment); + return dfr.promise; + } + }, + // @return Promise + save: function save() { + var crmAttachments = this; + var target = this.getTarget(); + if (!target.entity_table || !target.entity_id) { + throw "Cannot save attachments: unknown entity_table or entity_id"; + } + + var params = _.extend({}, target); + params.values = crmAttachments.files; + return crmApi('Attachment', 'replace', params) + .then(function () { + var dfr = $q.defer(); + + var newItems = crmAttachments.uploader.getNotUploadedItems(); + if (newItems.length > 0) { + _.each(newItems, function (item) { + item.formData = [_.extend({}, target, item.crmData)]; + }); + crmAttachments.uploader.onCompleteAll = function onCompleteAll() { + delete crmAttachments.uploader.onCompleteAll; + dfr.resolve(crmAttachments); + }; + crmAttachments.uploader.uploadAll(); + } + else { + dfr.resolve(crmAttachments); + } + + return dfr.promise; + }); + }, + // @param Object file APIv3 attachment record (e.g. id, entity_table, entity_id, description) + deleteFile: function deleteFile(file) { + var crmAttachments = this; + + var idx = _.indexOf(this.files, file); + if (idx != -1) { + this.files.splice(idx, 1); + } + + if (file.id) { + var p = crmApi('Attachment', 'delete', {id: file.id}).then( + function () { // success + }, + function (response) { // error; restore the file + var msg = angular.isObject(response) ? response.error_message : ''; + CRM.alert(msg, ts('Deletion failed')); + crmAttachments.files.push(file); + } + ); + return crmStatus({start: ts('Deleting...'), success: ts('Deleted')}, p); + } + } + }); + + return CrmAttachments; + }); + + // example: + // $scope.attachments = new CrmAttachments({entity_table: 'civicrm_mailing', entity_id: 123}); + //
+ angular.module('crmAttachment').controller('CrmAttachmentsCtrl', function ($scope, CrmAttachments) { + $scope.init = function init(att) { + $scope.att = att; + att.load(); + }; + }); + +})(angular, CRM.$, CRM._); diff --git a/partials/crmAttachment/attachments.html b/partials/crmAttachment/attachments.html new file mode 100644 index 0000000000..1a80f9495c --- /dev/null +++ b/partials/crmAttachment/attachments.html @@ -0,0 +1,43 @@ +
+ + + + + + + + + + + + + + + + +
+ {{file.name}} + + + + + + +
{{item.file.name}} + + + + +
+ + +
+ {{ts('Add file:')}}
+
+
+ {{ts('Alternatively, you may add new files using drag/drop.')}} +
+
-- 2.25.1