Remove unneeded call to crmtooltip
[civicrm-core.git] / js / angular-crmMailing.js
CommitLineData
030dce01 1(function (angular, $, _) {
030dce01 2
88e9e883 3 angular.module('crmMailing', [
8443385d 4 'crmUtil', 'crmAttachment', 'crmAutosave', 'ngRoute', 'ui.utils', 'crmUi', 'dialogService'
f4f103fa 5 ]); // TODO ngSanitize, unsavedChanges
030dce01 6
7801d9b5
TO
7 // Time to wait before triggering AJAX update to recipients list
8 var RECIPIENTS_DEBOUNCE_MS = 100;
b73e0c53 9 var RECIPIENTS_PREVIEW_LIMIT = 10000;
7801d9b5 10
88e9e883 11 angular.module('crmMailing').config([
f4f103fa 12 '$routeProvider',
030dce01 13 function ($routeProvider) {
96ac27bd 14 $routeProvider.when('/mailing', {
030dce01
TO
15 template: '<div></div>',
16 controller: 'ListMailingsCtrl'
17 });
b7c3beb2
TO
18
19 var editorPaths = {
ef5d18a1
TO
20 '': '~/crmMailing/edit.html',
21 '/unified': '~/crmMailing/edit-unified.html',
22 '/unified2': '~/crmMailing/edit-unified2.html',
23 '/wizard': '~/crmMailing/edit-wizard.html'
b7c3beb2
TO
24 };
25 angular.forEach(editorPaths, function(editTemplate, pathSuffix) {
26 $routeProvider.when('/mailing/new' + pathSuffix, {
27 template: '<p>' + ts('Initializing...') + '</p>',
28 controller: 'CreateMailingCtrl',
29 resolve: {
30 selectedMail: function(crmMailingMgr) {
31 var m = crmMailingMgr.create();
32 return crmMailingMgr.save(m);
33 }
f4f103fa 34 }
b7c3beb2
TO
35 });
36 $routeProvider.when('/mailing/:id' + pathSuffix, {
37 templateUrl: editTemplate,
38 controller: 'EditMailingCtrl',
39 resolve: {
40 selectedMail: function($route, crmMailingMgr) {
41 return crmMailingMgr.get($route.current.params.id);
42 }
f4f103fa 43 }
b7c3beb2 44 });
030dce01
TO
45 });
46 }
47 ]);
48
416abe87 49 angular.module('crmMailing').controller('ListMailingsCtrl', ['crmLegacy', 'crmNavigator', function ListMailingsCtrl(crmLegacy, crmNavigator) {
030dce01
TO
50 // We haven't implemented this in Angular, but some users may get clever
51 // about typing URLs, so we'll provide a redirect.
416abe87
PH
52 var new_url = crmLegacy.url('civicrm/mailing/browse/unscheduled', {reset: 1, scheduled: 'false'});
53 crmNavigator.redirect(new_url);
54 }]);
030dce01 55
b7c3beb2
TO
56 angular.module('crmMailing').controller('CreateMailingCtrl', function EditMailingCtrl($scope, selectedMail, $location) {
57 // Transition URL "/mailing/new/foo" => "/mailing/123/foo"
58 var parts = $location.path().split('/'); // e.g. "/mailing/new" or "/mailing/123/wizard"
59 parts[2] = selectedMail.id;
60 $location.path(parts.join('/'));
61 $location.replace();
62 });
63
bdd3f781 64 angular.module('crmMailing').controller('EditMailingCtrl', function EditMailingCtrl($scope, selectedMail, $location, crmMailingMgr, crmStatus, CrmAttachments, crmMailingPreviewMgr, crmBlocker) {
27e690c2 65 $scope.mailing = selectedMail;
f4f103fa 66 $scope.attachments = new CrmAttachments(function () {
db083bf0
TO
67 return {entity_table: 'civicrm_mailing', entity_id: $scope.mailing.id};
68 });
ab0a4aec 69 $scope.attachments.load();
27e690c2
TO
70 $scope.crmMailingConst = CRM.crmMailing;
71
5d8901af 72 var ts = $scope.ts = CRM.ts(null);
bdd3f781 73 var block = $scope.block = crmBlocker();
27e690c2 74
86c3a327
TO
75 $scope.isSubmitted = function isSubmitted() {
76 return _.size($scope.mailing.jobs) > 0;
77 };
78
58dfba8d
TO
79 // @return Promise
80 $scope.previewMailing = function previewMailing(mailing, mode) {
81 return crmMailingPreviewMgr.preview(mailing, mode);
82 };
83
84 // @return Promise
85 $scope.sendTest = function sendTest(mailing, attachments, recipient) {
86 var savePromise = crmMailingMgr.save(mailing)
87 .then(function () {
88 return attachments.save();
b7c3beb2 89 });
bdd3f781 90 return block(crmStatus({start: ts('Saving...'), success: ''}, savePromise)
58dfba8d
TO
91 .then(function () {
92 crmMailingPreviewMgr.sendTest(mailing, recipient);
bdd3f781 93 }));
58dfba8d
TO
94 };
95
705c61e9
TO
96 // @return Promise
97 $scope.submit = function submit() {
c9ae63bb
TO
98 if (block.check() || $scope.crmMailing.$invalid) {
99 return;
100 }
101
db083bf0 102 var promise = crmMailingMgr.save($scope.mailing)
86c3a327
TO
103 .then(function () {
104 // pre-condition: the mailing exists *before* saving attachments to it
105 return $scope.attachments.save();
106 })
107 .then(function () {
108 return crmMailingMgr.submit($scope.mailing);
109 })
110 .then(function () {
b0797ac3 111 leave('scheduled');
86c3a327
TO
112 })
113 ;
bdd3f781 114 return block(crmStatus({start: ts('Submitting...'), success: ts('Submitted')}, promise));
2d36e6bc 115 };
58dfba8d 116
705c61e9
TO
117 // @return Promise
118 $scope.save = function save() {
bdd3f781 119 return block(crmStatus(null,
db083bf0
TO
120 crmMailingMgr
121 .save($scope.mailing)
122 .then(function () {
123 // pre-condition: the mailing exists *before* saving attachments to it
124 return $scope.attachments.save();
125 })
bdd3f781 126 ));
2d36e6bc 127 };
58dfba8d 128
705c61e9
TO
129 // @return Promise
130 $scope.delete = function cancel() {
bdd3f781 131 return block(crmStatus({start: ts('Deleting...'), success: ts('Deleted')},
f286acec 132 crmMailingMgr.delete($scope.mailing)
b0797ac3 133 .then(function () {
f2bad133 134 leave('unscheduled');
b0797ac3 135 })
bdd3f781 136 ));
2d36e6bc 137 };
58dfba8d 138
b0797ac3
TO
139 // @param string listingScreen 'archive', 'scheduled', 'unscheduled'
140 function leave(listingScreen) {
141 switch (listingScreen) {
142 case 'archive':
143 window.location = CRM.url('civicrm/mailing/browse/archived', {
144 reset: 1
145 });
146 break;
147 case 'scheduled':
148 window.location = CRM.url('civicrm/mailing/browse/scheduled', {
149 reset: 1,
150 scheduled: 'true'
151 });
152 break;
153 case 'unscheduled':
8acf0123 154 /* falls through */
b0797ac3
TO
155 default:
156 window.location = CRM.url('civicrm/mailing/browse/unscheduled', {
157 reset: 1,
158 scheduled: 'false'
159 });
160 }
f2bad133 161 }
030dce01
TO
162 });
163
7801d9b5
TO
164 // Controller for the edit-recipients fields (
165 // WISHLIST: Move most of this to a (cache-enabled) service
166 // Scope members:
167 // - [input] mailing: object
168 // - [output] recipients: array of recipient records
88e9e883 169 angular.module('crmMailing').controller('EditRecipCtrl', function EditRecipCtrl($scope, dialogService, crmApi, crmMailingMgr) {
5d8901af 170 var ts = $scope.ts = CRM.ts(null);
7801d9b5
TO
171 $scope.recipients = null;
172 $scope.getRecipientsEstimate = function () {
173 var ts = $scope.ts;
8acf0123 174 if ($scope.recipients === null) {
7801d9b5 175 return ts('(Estimating)');
f4f103fa 176 }
8acf0123 177 if ($scope.recipients.length === 0) {
7801d9b5 178 return ts('No recipients');
f4f103fa 179 }
8acf0123 180 if ($scope.recipients.length === 1) {
7801d9b5 181 return ts('~1 recipient');
f4f103fa
TO
182 }
183 if (RECIPIENTS_PREVIEW_LIMIT > 0 && $scope.recipients.length >= RECIPIENTS_PREVIEW_LIMIT) {
b73e0c53 184 return ts('>%1 recipients', {1: RECIPIENTS_PREVIEW_LIMIT});
f4f103fa 185 }
7801d9b5
TO
186 return ts('~%1 recipients', {1: $scope.recipients.length});
187 };
f4f103fa 188 $scope.getIncludesAsString = function () {
47bacc20
TO
189 var first = true;
190 var names = '';
f4f103fa
TO
191 _.each($scope.mailing.groups.include, function (id) {
192 if (!first) {
193 names = names + ', ';
194 }
195 var group = _.where(CRM.crmMailing.groupNames, {id: '' + id});
47bacc20
TO
196 names = names + group[0].title;
197 first = false;
198 });
f4f103fa
TO
199 _.each($scope.mailing.mailings.include, function (id) {
200 if (!first) {
201 names = names + ', ';
202 }
203 var oldMailing = _.where(CRM.crmMailing.civiMails, {id: '' + id});
47bacc20
TO
204 names = names + oldMailing[0].name;
205 first = false;
206 });
207 return names;
208 };
f4f103fa 209 $scope.getExcludesAsString = function () {
47bacc20
TO
210 var first = true;
211 var names = '';
f4f103fa
TO
212 _.each($scope.mailing.groups.exclude, function (id) {
213 if (!first) {
214 names = names + ', ';
215 }
216 var group = _.where(CRM.crmMailing.groupNames, {id: '' + id});
47bacc20
TO
217 names = names + group[0].title;
218 first = false;
219 });
f4f103fa
TO
220 _.each($scope.mailing.mailings.exclude, function (id) {
221 if (!first) {
222 names = names + ', ';
223 }
224 var oldMailing = _.where(CRM.crmMailing.civiMails, {id: '' + id});
47bacc20
TO
225 names = names + oldMailing[0].name;
226 first = false;
227 });
228 return names;
229 };
230
7801d9b5
TO
231 // We monitor four fields -- use debounce so that changes across the
232 // four fields can settle-down before AJAX.
233 var refreshRecipients = _.debounce(function () {
234 $scope.$apply(function () {
235 $scope.recipients = null;
8dfd5110
TO
236 crmMailingMgr.previewRecipients($scope.mailing, RECIPIENTS_PREVIEW_LIMIT).then(function (recipients) {
237 $scope.recipients = recipients;
b73e0c53 238 });
7801d9b5
TO
239 });
240 }, RECIPIENTS_DEBOUNCE_MS);
241 $scope.$watchCollection("mailing.groups.include", refreshRecipients);
242 $scope.$watchCollection("mailing.groups.exclude", refreshRecipients);
243 $scope.$watchCollection("mailing.mailings.include", refreshRecipients);
244 $scope.$watchCollection("mailing.mailings.exclude", refreshRecipients);
245
4dd19229 246 $scope.previewRecipients = function previewRecipients() {
7801d9b5
TO
247 var model = {
248 recipients: $scope.recipients
249 };
250 var options = {
251 autoOpen: false,
252 modal: true,
253 title: ts('Preview (%1)', {
254 1: $scope.getRecipientsEstimate()
52f515c6 255 })
7801d9b5 256 };
ef5d18a1 257 dialogService.open('recipDialog', '~/crmMailing/dialog/recipients.html', model, options);
7801d9b5
TO
258 };
259 });
260
261 // Controller for the "Preview Recipients" dialog
262 // Note: Expects $scope.model to be an object with properties:
263 // - recipients: array of contacts
88e9e883 264 angular.module('crmMailing').controller('PreviewRecipCtrl', function ($scope) {
5d8901af 265 $scope.ts = CRM.ts(null);
7801d9b5 266 });
493eb47a 267
493eb47a
TO
268 // Controller for the "Preview Mailing" dialog
269 // Note: Expects $scope.model to be an object with properties:
270 // - "subject"
271 // - "body_html"
272 // - "body_text"
870cbdbb 273 angular.module('crmMailing').controller('PreviewMailingDialogCtrl', function PreviewMailingDialogCtrl($scope) {
5d8901af 274 $scope.ts = CRM.ts(null);
493eb47a
TO
275 });
276
47bacc20
TO
277 // Controller for the "Preview Mailing Component" segment
278 // which displays header/footer/auto-responder
88e9e883 279 angular.module('crmMailing').controller('PreviewComponentCtrl', function PreviewMailingDialogCtrl($scope, dialogService) {
5d8901af 280 var ts = $scope.ts = CRM.ts(null);
52f515c6 281
47bacc20 282 $scope.previewComponent = function previewComponent(title, componentId) {
f4f103fa 283 var component = _.where(CRM.crmMailing.headerfooterList, {id: "" + componentId});
47bacc20
TO
284 if (!component || !component[0]) {
285 CRM.alert(ts('Invalid component ID (%1)', {
286 1: componentId
287 }));
288 return;
289 }
290 var options = {
291 autoOpen: false,
292 modal: true,
293 title: title // component[0].name
294 };
ef5d18a1 295 dialogService.open('previewComponentDialog', '~/crmMailing/dialog/previewComponent.html', component[0], options);
47bacc20
TO
296 };
297 });
298
299 // Controller for the "Preview Mailing" dialog
300 // Note: Expects $scope.model to be an object with properties:
301 // - "name"
302 // - "subject"
303 // - "body_html"
304 // - "body_text"
88e9e883 305 angular.module('crmMailing').controller('PreviewComponentDialogCtrl', function PreviewMailingDialogCtrl($scope) {
5d8901af 306 $scope.ts = CRM.ts(null);
47bacc20
TO
307 });
308
744bebee 309 // Controller for the in-place msg-template management
870cbdbb 310 angular.module('crmMailing').controller('MsgTemplateCtrl', function MsgTemplateCtrl($scope, crmMsgTemplates, dialogService) {
5d8901af 311 var ts = $scope.ts = CRM.ts(null);
744bebee
TO
312 $scope.crmMsgTemplates = crmMsgTemplates;
313
314 // @return Promise MessageTemplate (per APIv3)
74263d6b 315 $scope.saveTemplate = function saveTemplate(mailing) {
744bebee 316 var model = {
74263d6b 317 selected_id: mailing.msg_template_id,
744bebee
TO
318 tpl: {
319 msg_title: '',
74263d6b
TO
320 msg_subject: mailing.subject,
321 msg_text: mailing.body_text,
322 msg_html: mailing.body_html
744bebee
TO
323 }
324 };
325 var options = {
326 autoOpen: false,
327 modal: true,
328 title: ts('Save Template')
329 };
ef5d18a1 330 return dialogService.open('saveTemplateDialog', '~/crmMailing/dialog/saveTemplate.html', model, options)
f4f103fa 331 .then(function (item) {
74263d6b 332 mailing.msg_template_id = item.id;
744bebee
TO
333 return item;
334 });
335 };
336
337 // @param int id
338 // @return Promise
74263d6b 339 $scope.loadTemplate = function loadTemplate(mailing, id) {
744bebee 340 return crmMsgTemplates.get(id).then(function (tpl) {
74263d6b
TO
341 mailing.subject = tpl.msg_subject;
342 mailing.body_text = tpl.msg_text;
343 mailing.body_html = tpl.msg_html;
744bebee
TO
344 });
345 };
346 });
347
348 // Controller for the "Save Message Template" dialog
349 // Scope members:
350 // - [input] "model": Object
351 // - "selected_id": int
352 // - "tpl": Object
353 // - "msg_subject": string
354 // - "msg_text": string
355 // - "msg_html": string
88e9e883 356 angular.module('crmMailing').controller('SaveMsgTemplateDialogCtrl', function SaveMsgTemplateDialogCtrl($scope, crmMsgTemplates, dialogService) {
5d8901af 357 var ts = $scope.ts = CRM.ts(null);
744bebee
TO
358 $scope.saveOpt = {mode: '', newTitle: ''};
359 $scope.selected = null;
360
361 $scope.save = function save() {
362 var tpl = _.extend({}, $scope.model.tpl);
363 switch ($scope.saveOpt.mode) {
364 case 'add':
365 tpl.msg_title = $scope.saveOpt.newTitle;
366 break;
367 case 'update':
368 tpl.id = $scope.selected.id;
369 tpl.msg_title = $scope.selected.msg_title;
370 break;
371 default:
372 throw 'SaveMsgTemplateDialogCtrl: Unrecognized mode: ' + $scope.saveOpt.mode;
373 }
374 return crmMsgTemplates.save(tpl)
375 .then(function (item) {
376 CRM.status(ts('Saved'));
377 return item;
378 });
379 };
380
381 function scopeApply(f) {
382 return function () {
383 var args = arguments;
384 $scope.$apply(function () {
385 f.apply(args);
386 });
387 };
388 }
389
390 function init() {
391 crmMsgTemplates.get($scope.model.selected_id).then(
392 function (tpl) {
393 $scope.saveOpt.mode = 'update';
394 $scope.selected = tpl;
395 },
396 function () {
397 $scope.saveOpt.mode = 'add';
398 $scope.selected = null;
399 }
400 );
401 // When using dialogService with a button bar, the major button actions
402 // need to be registered with the dialog widget (and not embedded in
403 // the body of the dialog).
404 var buttons = {};
405 buttons[ts('Save')] = function () {
406 $scope.save().then(function (item) {
407 dialogService.close('saveTemplateDialog', item);
408 });
409 };
410 buttons[ts('Cancel')] = function () {
411 dialogService.cancel('saveTemplateDialog');
412 };
413 dialogService.setButtons('saveTemplateDialog', buttons);
414 }
f4f103fa 415
744bebee
TO
416 setTimeout(scopeApply(init), 0);
417 });
2d06b3b6 418
58dfba8d 419 angular.module('crmMailing').controller('EmailAddrCtrl', function EmailAddrCtrl($scope, crmFromAddresses) {
0a993c89
TO
420 $scope.crmFromAddresses = crmFromAddresses;
421 });
030dce01 422})(angular, CRM.$, CRM._);