CRM-15578 - Mailing.create - Fix updates to "groups" and "mailings". Add test.
[civicrm-core.git] / js / angular-crmMailing2-directives.js
CommitLineData
5d72b4e2
TO
1(function (angular, $, _) {
2 var partialUrl = function (relPath) {
3 return CRM.resourceUrls['civicrm'] + '/partials/crmMailing2/' + relPath;
4 };
5
6 var crmMailing2 = angular.module('crmMailing2');
7
8 // example: <input name="subject" /> <input crm-mailing-token crm-for="subject"/>
9 // WISHLIST: Instead of global CRM.crmMailing.mailTokens, accept token list as an input
10 crmMailing2.directive('crmMailingToken', function () {
11 return {
12 scope: {
13 crmFor: '@'
14 },
15 template: '<input type="text" class="crmMailingToken" />',
16 link: function (scope, element, attrs) {
17 // 1. Find the corresponding input element (crmFor)
18
19 var form = $(element).closest('form');
20 var crmForEl = $('input[name="' + attrs.crmFor + '"],textarea[name="' + attrs.crmFor + '"]', form);
21 if (form.length != 1 || crmForEl.length != 1) {
22 if (console.log)
23 console.log('crmMailingToken cannot be matched to input element. Expected to find one form and one input.', form.length, crmForEl.length);
24 return;
25 }
26
27 // 2. Setup the token selector
28 $(element).select2({width: "10em",
29 dropdownAutoWidth: true,
30 data: CRM.crmMailing.mailTokens,
31 placeholder: ts('Insert')
32 });
33 $(element).on('select2-selecting', function (e) {
34 var origVal = crmForEl.val();
35 var origPos = crmForEl[0].selectionStart;
36 var newVal = origVal.substring(0, origPos) + e.val + origVal.substring(origPos, origVal.length);
37 crmForEl.val(newVal);
38 var newPos = (origPos + e.val.length);
39 crmForEl[0].selectionStart = newPos;
40 crmForEl[0].selectionEnd = newPos;
41
42 $(element).select2('close').select2('val', '');
43 crmForEl.triggerHandler('change');
44 crmForEl.focus();
45
46 e.preventDefault();
47 });
48 }
49 };
50 });
51
b0461279
TO
52 // example: <select multiple crm-mailing-recipients crm-mailing="mymailing" crm-avail-groups="myGroups" crm-avail-mailings="myMailings"></select>
53 crmMailing2.directive('crmMailingRecipients', function () {
54 return {
55 restrict: 'AE',
56 scope: {
57 crmAvailGroups: '@', // available groups
58 crmAvailMailings: '@', // available mailings
59 crmMailing: '@' // the mailing for which we are choosing recipients
60 },
61 templateUrl: partialUrl('directive/recipients.html'),
62 link: function (scope, element, attrs) {
63 scope.mailing = scope.$parent.$eval(attrs.crmMailing);
64 scope.groups = scope.$parent.$eval(attrs.crmAvailGroups);
65 scope.mailings = scope.$parent.$eval(attrs.crmAvailMailings);
66
67 scope.ts = CRM.ts('CiviMail');
68
69 /// Convert MySQL date ("yyyy-mm-dd hh:mm:ss") to JS date object
70 scope.parseDate = function (date) {
71 if (!angular.isString(date))
72 return date;
73 var p = date.split(/[\- :]/);
74 return new Date(p[0], p[1], p[2], p[3], p[4], p[5]);
75 };
76
77 /// Remove {value} from {array}
78 function arrayRemove(array, value) {
79 var idx = array.indexOf(value);
80 if (idx >= 0) {
81 array.splice(idx, 1);
82 }
83 }
84
85 // @param string id an encoded string like "4 civicrm_mailing include"
86 // @return Object keys: entity_id, entity_type, mode
87 function convertValueToObj(id) {
88 var a = id.split(" ");
89 return {entity_id: parseInt(a[0]), entity_type: a[1], mode: a[2]};
90 }
91
92 // @param Object mailing
93 // @return array list of values like "4 civicrm_mailing include"
94 function convertMailingToValues(mailing) {
95 var r = [];
96 angular.forEach(mailing.groups.include, function (v) {
97 r.push(v + " civicrm_group include");
98 });
99 angular.forEach(mailing.groups.exclude, function (v) {
100 r.push(v + " civicrm_group exclude");
101 });
102 angular.forEach(mailing.mailings.include, function (v) {
103 r.push(v + " civicrm_mailing include");
104 });
105 angular.forEach(mailing.mailings.exclude, function (v) {
106 r.push(v + " civicrm_mailing exclude");
107 });
108 return r;
109 }
110
111 // Update $(element) view based on latest data
112 function refreshUI() {
113 $(element).select2('val', convertMailingToValues(scope.mailing));
114 }
115
116 /// @return string HTML representingn an option
117 function formatItem(item) {
118 if (!item.id) {
119 // return `text` for optgroup
120 return item.text;
121 }
122 var option = convertValueToObj(item.id);
123 var icon = (option.entity_type === 'civicrm_mailing') ? 'EnvelopeIn.gif' : 'group.png';
124 var spanClass = (option.mode == 'exclude') ? 'crmMailing2-exclude' : 'crmMailing2-include';
125 return "<img src='../../sites/all/modules/civicrm/i/" + icon + "' height=12 width=12 /> <span class='" + spanClass + "'>" + item.text + "</span>";
126 }
127
128 $(element).select2({
129 dropdownAutoWidth: true,
130 placeholder: "Groups or Past Recipients",
131 formatResult: formatItem,
132 formatSelection: formatItem,
133 escapeMarkup: function (m) {
134 return m;
135 },
136 });
137
138 $(element).on('select2-selecting', function (e) {
139 var option = convertValueToObj(e.val);
140 var typeKey = option.entity_type == 'civicrm_mailing' ? 'mailings' : 'groups';
141 if (option.mode == 'exclude') {
142 scope.mailing[typeKey].exclude.push(option.entity_id);
143 arrayRemove(scope.mailing[typeKey].include, option.entity_id);
144 } else {
145 scope.mailing[typeKey].include.push(option.entity_id);
146 arrayRemove(scope.mailing[typeKey].exclude, option.entity_id);
147 }
148 scope.$apply();
149 $(element).select2('close');
150 e.preventDefault();
151 });
152
153 $(element).on("select2-removing", function (e) {
154 var option = convertValueToObj(e.val);
155 var typeKey = option.entity_type == 'civicrm_mailing' ? 'mailings' : 'groups';
156 arrayRemove(scope.mailing[typeKey][option.mode], option.entity_id);
157 scope.$apply();
158 e.preventDefault();
159 });
160
161 scope.$watchCollection(attrs.crmMailing + ".groups.include", refreshUI);
162 scope.$watchCollection(attrs.crmMailing + ".groups.exclude", refreshUI);
163 scope.$watchCollection(attrs.crmMailing + ".mailings.include", refreshUI);
164 scope.$watchCollection(attrs.crmMailing + ".mailings.exclude", refreshUI);
165 setTimeout(refreshUI, 50);
166 }
167 };
168 });
169
5d72b4e2 170})(angular, CRM.$, CRM._);