CRM-14798 - crmApi - Allow batching
[civicrm-core.git] / js / angular-crmCaseType.js
CommitLineData
4c58e251
TO
1(function(angular, $, _) {
2
64790edd
TO
3 var partialUrl = function(relPath) {
4 return CRM.resourceUrls['civicrm'] + '/partials/crmCaseType/' + relPath;
8fc6fba7 5 };
64790edd 6
51d499e1 7 var crmCaseType = angular.module('crmCaseType', ['ngRoute', 'ui.utils', 'crmUi', 'unsavedChanges']);
4c58e251 8
506cd414 9 // Note: This template will be passed to cloneDeep(), so don't put any funny stuff in here!
9be5fc34
TO
10 var newCaseTypeTemplate = {
11 title: "",
12 name: "",
13 is_active: "1",
14 weight: "1",
15 definition: {
16 activityTypes: [
17 {name: 'Open Case', max_instances: 1 }
18 ],
19 activitySets: [
20 {
21 name: 'standard_timeline',
22 label: 'Standard Timeline',
23 timeline: '1', // Angular won't bind checkbox correctly with numeric 1
24 activityTypes: [
25 {name: 'Open Case', status: 'Completed' }
26 ]
27 }
28 ],
29 caseRoles: [
30 { name: 'Case Coordinator', creator: '1', manager: '1'}
31 ]
32 }
4d74de55
TO
33 };
34
4c58e251
TO
35 crmCaseType.config(['$routeProvider',
36 function($routeProvider) {
b75c2546
TO
37 $routeProvider.when('/caseType', {
38 templateUrl: partialUrl('list.html'),
39 controller: 'CaseTypeListCtrl',
40 resolve: {
41 caseTypes: function($route, crmApi) {
42 return crmApi('CaseType', 'get', {});
43 }
44 }
45 });
4c58e251 46 $routeProvider.when('/caseType/:id', {
64790edd 47 templateUrl: partialUrl('edit.html'),
4d74de55
TO
48 controller: 'CaseTypeCtrl',
49 resolve: {
50 selectedCaseType: function($route, crmApi) {
87dcd909 51 if ( $route.current.params.id !== 'new') {
52 return crmApi('CaseType', 'getsingle', {id: $route.current.params.id});
53 }
54 else {
9be5fc34 55 return _.cloneDeep(newCaseTypeTemplate);
87dcd909 56 }
4d74de55
TO
57 }
58 }
4c58e251
TO
59 });
60 }
61 ]);
62
95fd24c0
TO
63 // Add a new record by name.
64 // Ex: <crmAddName crm-options="['Alpha','Beta','Gamma']" crm-var="newItem" crm-on-add="callMyCreateFunction(newItem)" />
8fc6fba7 65 crmCaseType.directive('crmAddName', function() {
95fd24c0
TO
66 return {
67 restrict: 'AE',
bafce1db
TO
68 template: '<input class="add-activity" type="hidden" />',
69 link: function(scope, element, attrs) {
70 /// Format list of options for select2's "data"
71 var getFormattedOptions = function() {
72 return {
73 results: _.map(scope[attrs.crmOptions], function(option){
74 return {id: option, text: option};
75 })
76 };
77 };
78
79 var input = $('input', element);
80
81 scope._resetSelection = function() {
82 $(input).select2('close');
83 $(input).select2('val', '');
84 scope[attrs.crmVar] = '';
85 };
86
87 $(input).select2({
88 data: getFormattedOptions,
89 createSearchChoice: function(term) {
90 return {id: term, text: term};
91 }
92 });
93 $(input).on('select2-selecting', function(e) {
94 scope[attrs.crmVar] = e.val;
95 scope.$evalAsync(attrs.crmOnAdd);
96 scope.$evalAsync('_resetSelection()');
97 e.preventDefault();
98 });
60dd172b
TO
99
100 scope.$watch(attrs.crmOptions, function(value) {
101 $(input).select2('data', getFormattedOptions);
102 $(input).select2('val', '');
103 });
bafce1db 104 }
95fd24c0
TO
105 };
106 });
107
4d74de55 108 crmCaseType.controller('CaseTypeCtrl', function($scope, crmApi, selectedCaseType) {
64790edd 109 $scope.partialUrl = partialUrl;
76e4acb8 110
dc7a657e
TO
111 $scope.activityStatuses = CRM.crmCaseType.actStatuses;
112 $scope.activityTypes = CRM.crmCaseType.actTypes;
d7c25f6c 113 $scope.activityTypeNames = _.pluck(CRM.crmCaseType.actTypes, 'name');
8c7e0ae8 114 $scope.relationshipTypeNames = _.pluck(CRM.crmCaseType.relTypes, 'label_b_a'); // label_b_a is CRM_Case_XMLProcessor::REL_TYPE_CNAME
685acae4 115 $scope.locks = {caseTypeName: true};
dc7a657e 116
76e4acb8
TO
117 $scope.workflows = {
118 'timeline': 'Timeline',
b387506c 119 'sequence': 'Sequence'
76e4acb8
TO
120 };
121
4d74de55 122 $scope.caseType = selectedCaseType;
87dcd909 123 $scope.caseType.definition = $scope.caseType.definition || [];
4d74de55
TO
124 $scope.caseType.definition.activityTypes = $scope.caseType.definition.activityTypes || [];
125 $scope.caseType.definition.activitySets = $scope.caseType.definition.activitySets || [];
126 $scope.caseType.definition.caseRoles = $scope.caseType.definition.caseRoles || [];
dc7a657e 127 window.ct = $scope.caseType;
4c58e251 128
76e4acb8
TO
129 $scope.addActivitySet = function(workflow) {
130 var activitySet = {};
131 activitySet[workflow] = '1';
132 activitySet.activityTypes = [];
133
134 var offset = 1;
135 var names = _.pluck($scope.caseType.definition.activitySets, 'name');
136 while (_.contains(names, workflow + '_' + offset)) offset++;
137 activitySet.name = workflow + '_' + offset;
138 activitySet.label = (offset == 1 ) ? $scope.workflows[workflow] : ($scope.workflows[workflow] + ' #' + offset);
139
140 $scope.caseType.definition.activitySets.push(activitySet);
141 _.defer(function() {
142 $('.crmCaseType-acttab').tabs('refresh').tabs({active: -1});
143 });
144 };
145
d7c25f6c
TO
146 /// Add a new activity entry to an activity-set
147 $scope.addActivity = function(activitySet, activityType) {
148 activitySet.activityTypes.push({
183241d8 149 name: activityType,
150 status: 'Scheduled',
151 reference_activity: 'Open Case',
152 reference_offset: '1',
153 reference_select: 'newest'
d7c25f6c 154 });
60dd172b
TO
155 if (!_.contains($scope.activityTypeNames, activityType)) {
156 $scope.activityTypeNames.push(activityType);
157 }
d7c25f6c
TO
158 };
159
160 /// Add a new top-level activity-type entry
161 $scope.addActivityType = function(activityType) {
162 var names = _.pluck($scope.caseType.definition.activityTypes, 'name');
163 if (!_.contains(names, activityType)) {
164 $scope.caseType.definition.activityTypes.push({
165 name: activityType
166 });
60dd172b
TO
167
168 }
169 if (!_.contains($scope.activityTypeNames, activityType)) {
170 $scope.activityTypeNames.push(activityType);
d7c25f6c
TO
171 }
172 };
173
8c7e0ae8
TO
174 /// Add a new role
175 $scope.addRole = function(roles, roleName) {
bafce1db
TO
176 var names = _.pluck($scope.caseType.definition.caseRoles, 'name');
177 if (!_.contains(names, roleName)) {
178 roles.push({
179 name: roleName
180 });
181 }
60dd172b
TO
182 if (!_.contains($scope.relationshipTypeNames, roleName)) {
183 $scope.relationshipTypeNames.push(roleName);
184 }
8c7e0ae8
TO
185 };
186
4c58e251
TO
187 $scope.onManagerChange = function(managerRole) {
188 angular.forEach($scope.caseType.definition.caseRoles, function(caseRole) {
189 if (caseRole != managerRole) {
190 caseRole.manager = '0';
191 }
192 });
193 };
194
195 $scope.removeItem = function(array, item) {
196 var idx = _.indexOf(array, item);
197 if (idx != -1) {
198 array.splice(idx, 1);
199 }
200 };
201
5d973e24
TO
202 $scope.isNewActivitySetAllowed = function(workflow) {
203 switch (workflow) {
204 case 'timeline':
205 return true;
b387506c
TO
206 case 'sequence':
207 return 0 == _.where($scope.caseType.definition.activitySets, {sequence: '1'}).length;
5d973e24
TO
208 default:
209 if (console && console.log) console.log('Denied access to unrecognized workflow: (' + workflow + ')');
210 return false;
211 }
212 };
213
4c58e251 214 $scope.getWorkflowName = function(activitySet) {
76e4acb8
TO
215 var result = 'Unknown';
216 _.each($scope.workflows, function(value, key) {
217 if (activitySet[key]) result = value;
218 });
219 return result;
4c58e251
TO
220 };
221
222 /**
223 * Determine which HTML partial to use for a particular
224 *
225 * @return string URL of the HTML partial
226 */
227 $scope.activityTableTemplate = function(activitySet) {
228 if (activitySet.timeline) {
64790edd 229 return partialUrl('timelineTable.html');
b387506c
TO
230 } else if (activitySet.sequence) {
231 return partialUrl('sequenceTable.html');
4c58e251
TO
232 } else {
233 return '';
234 }
235 };
236
237 $scope.dump = function() {
238 console.log($scope.caseType);
76e4acb8
TO
239 };
240
aa1a7c2e 241 $scope.save = function() {
c7bccb5f 242 var result = crmApi('CaseType', 'create', $scope.caseType, true);
243 result.success(function(data) {
244 if (data.is_error == 0) {
245 $scope.caseType.id = data.id;
1ab5b88e 246 window.location.href = '#/caseType';
c7bccb5f 247 }
248 });
aa1a7c2e
TO
249 };
250
76e4acb8
TO
251 $scope.$watchCollection('caseType.definition.activitySets', function() {
252 _.defer(function() {
8fc6fba7 253 $('.crmCaseType-acttab').tabs('refresh');
76e4acb8
TO
254 });
255 });
685acae4 256
257 var updateCaseTypeName = function () {
258 if (!$scope.caseType.id && $scope.locks.caseTypeName) {
259 // Should we do some filtering? Lowercase? Strip whitespace?
a5ca1f48 260 var t = $scope.caseType.title ? $scope.caseType.title : '';
261 $scope.caseType.name = t.replace(/ /g, '_').replace(/[^a-zA-Z0-9_]/g, '').toLowerCase();
685acae4 262 }
263 };
264 $scope.$watch('locks.caseTypeName', updateCaseTypeName);
265 $scope.$watch('caseType.title', updateCaseTypeName);
4c58e251
TO
266 });
267
b75c2546
TO
268 crmCaseType.controller('CaseTypeListCtrl', function($scope, crmApi, caseTypes) {
269 $scope.caseTypes = caseTypes.values;
270 });
271
4c58e251 272})(angular, CRM.$, CRM._);