Merge pull request #4757 from davecivicrm/CRM-15409
[civicrm-core.git] / js / angular-crmAttachment.js
1 /// crmFile: Manage file attachments
2 (function (angular, $, _) {
3 var partialUrl = function (relPath) {
4 return CRM.resourceUrls['civicrm'] + '/partials/crmAttachment/' + relPath;
5 };
6
7 angular.module('crmAttachment', ['angularFileUpload']);
8
9 // crmAttachment manages the list of files which are attached to a given entity
10 angular.module('crmAttachment').factory('CrmAttachments', function (crmApi, crmStatus, FileUploader, $q) {
11 // @param target an Object(entity_table:'',entity_id:'') or function which generates an object
12 function CrmAttachments(target) {
13 var crmAttachments = this;
14 this._target = target;
15 this.files = [];
16 this.uploader = new FileUploader({
17 url: CRM.url('civicrm/ajax/attachment'),
18 onAfterAddingFile: function onAfterAddingFile(item) {
19 item.crmData = {
20 description: ''
21 };
22 },
23 onSuccessItem: function onSuccessItem(item, response, status, headers) {
24 crmAttachments.files.push(response.file.values[response.file.id]);
25 crmAttachments.uploader.removeFromQueue(item);
26 },
27 onErrorItem: function onErrorItem(item, response, status, headers) {
28 var msg = (response && response.file && response.file.error_message) ? response.file.error_message : ts('Unknown error');
29 CRM.alert(item.file.name + ' - ' + msg, ts('Attachment failed'));
30 crmAttachments.uploader.removeFromQueue(item);
31 }
32 });
33 }
34
35 angular.extend(CrmAttachments.prototype, {
36 // @return Object(entity_table:'',entity_id:'')
37 getTarget: function () {
38 return (angular.isFunction(this._target) ? this._target() : this._target);
39 },
40 // @return Promise<Attachment>
41 load: function load() {
42 var target = this.getTarget();
43 var Attachment = this;
44
45 if (target.entity_id) {
46 var params = {
47 entity_table: target.entity_table,
48 entity_id: target.entity_id
49 };
50 return crmApi('Attachment', 'get', params).then(function (apiResult) {
51 Attachment.files = _.values(apiResult.values);
52 return Attachment;
53 });
54 }
55 else {
56 var dfr = $q.defer();
57 Attachment.files = [];
58 dfr.resolve(Attachment);
59 return dfr.promise;
60 }
61 },
62 // @return Promise
63 save: function save() {
64 var crmAttachments = this;
65 var target = this.getTarget();
66 if (!target.entity_table || !target.entity_id) {
67 throw "Cannot save attachments: unknown entity_table or entity_id";
68 }
69
70 var params = _.extend({}, target);
71 params.values = crmAttachments.files;
72 return crmApi('Attachment', 'replace', params)
73 .then(function () {
74 var dfr = $q.defer();
75
76 var newItems = crmAttachments.uploader.getNotUploadedItems();
77 if (newItems.length > 0) {
78 _.each(newItems, function (item) {
79 item.formData = [_.extend({}, target, item.crmData)];
80 });
81 crmAttachments.uploader.onCompleteAll = function onCompleteAll() {
82 delete crmAttachments.uploader.onCompleteAll;
83 dfr.resolve(crmAttachments);
84 };
85 crmAttachments.uploader.uploadAll();
86 }
87 else {
88 dfr.resolve(crmAttachments);
89 }
90
91 return dfr.promise;
92 });
93 },
94 // @param Object file APIv3 attachment record (e.g. id, entity_table, entity_id, description)
95 deleteFile: function deleteFile(file) {
96 var crmAttachments = this;
97
98 var idx = _.indexOf(this.files, file);
99 if (idx != -1) {
100 this.files.splice(idx, 1);
101 }
102
103 if (file.id) {
104 var p = crmApi('Attachment', 'delete', {id: file.id}).then(
105 function () { // success
106 },
107 function (response) { // error; restore the file
108 var msg = angular.isObject(response) ? response.error_message : '';
109 CRM.alert(msg, ts('Deletion failed'));
110 crmAttachments.files.push(file);
111 }
112 );
113 return crmStatus({start: ts('Deleting...'), success: ts('Deleted')}, p);
114 }
115 }
116 });
117
118 return CrmAttachments;
119 });
120
121 // example:
122 // $scope.myAttachments = new CrmAttachments({entity_table: 'civicrm_mailing', entity_id: 123});
123 // <div crm-attachments="myAttachments"/>
124 angular.module('crmAttachment').directive('crmAttachments', function ($parse, $timeout) {
125 return {
126 scope: {
127 crmAttachments: '@'
128 },
129 template: '<div ng-if="ready" ng-include="inclUrl"></div>',
130 link: function (scope, elm, attr) {
131 var model = $parse(attr.crmAttachments);
132 scope.att = model(scope.$parent);
133 scope.ts = CRM.ts(null);
134 scope.inclUrl = partialUrl('attachments.html');
135
136 // delay rendering of child tree until after model has been populated
137 scope.ready = true;
138 }
139 };
140 });
141
142 })(angular, CRM.$, CRM._);