Merge pull request #15322 from alifrumin/removePrintIcon
[civicrm-core.git] / ang / crmCaseType.js
CommitLineData
4c58e251
TO
1(function(angular, $, _) {
2
0b199194 3 var crmCaseType = angular.module('crmCaseType', CRM.angRequires('crmCaseType'));
4c58e251 4
506cd414 5 // Note: This template will be passed to cloneDeep(), so don't put any funny stuff in here!
9be5fc34
TO
6 var newCaseTypeTemplate = {
7 title: "",
8 name: "",
9 is_active: "1",
10 weight: "1",
11 definition: {
12 activityTypes: [
4d8bbcf6
TO
13 {name: 'Open Case', max_instances: 1},
14 {name: 'Email'},
15 {name: 'Follow up'},
16 {name: 'Meeting'},
17 {name: 'Phone Call'}
9be5fc34
TO
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 37 $routeProvider.when('/caseType', {
ef5d18a1 38 templateUrl: '~/crmCaseType/list.html',
b75c2546
TO
39 controller: 'CaseTypeListCtrl',
40 resolve: {
41 caseTypes: function($route, crmApi) {
a214ce43 42 return crmApi('CaseType', 'get', {options: {limit: 0}});
b75c2546
TO
43 }
44 }
45 });
4c58e251 46 $routeProvider.when('/caseType/:id', {
ef5d18a1 47 templateUrl: '~/crmCaseType/edit.html',
4d74de55
TO
48 controller: 'CaseTypeCtrl',
49 resolve: {
9625aad1
TO
50 apiCalls: function($route, crmApi) {
51 var reqs = {};
52 reqs.actStatuses = ['OptionValue', 'get', {
7c2b40d1
CW
53 option_group_id: 'activity_status',
54 sequential: 1,
55 options: {limit: 0}
56 }];
57 reqs.caseStatuses = ['OptionValue', 'get', {
58 option_group_id: 'case_status',
59 sequential: 1,
6a55cb01 60 options: {
61 sort: 'weight',
62 limit: 0
63 }
9625aad1
TO
64 }];
65 reqs.actTypes = ['OptionValue', 'get', {
66 option_group_id: 'activity_type',
4324b8d7 67 sequential: 1,
9625aad1
TO
68 options: {
69 sort: 'name',
70 limit: 0
71 }
72 }];
ad8d1ce3
RO
73 reqs.defaultAssigneeTypes = ['OptionValue', 'get', {
74 option_group_id: 'activity_default_assignee',
75 sequential: 1,
76 options: {
77 limit: 0
78 }
79 }];
bb8b702c 80 reqs.relTypes = ['RelationshipType', 'get', {
4324b8d7 81 sequential: 1,
1e921db0 82 is_active: 1,
9625aad1 83 options: {
bb8b702c 84 sort: 'label_a_b',
9625aad1
TO
85 limit: 0
86 }
87 }];
88 if ($route.current.params.id !== 'new') {
89 reqs.caseType = ['CaseType', 'getsingle', {
90 id: $route.current.params.id
91 }];
87dcd909 92 }
9625aad1 93 return crmApi(reqs);
4d74de55
TO
94 }
95 }
4c58e251
TO
96 });
97 }
98 ]);
99
95fd24c0
TO
100 // Add a new record by name.
101 // Ex: <crmAddName crm-options="['Alpha','Beta','Gamma']" crm-var="newItem" crm-on-add="callMyCreateFunction(newItem)" />
8fc6fba7 102 crmCaseType.directive('crmAddName', function() {
95fd24c0
TO
103 return {
104 restrict: 'AE',
9597c394 105 template: '<input class="add-activity crm-action-menu fa-plus" type="hidden" />',
bafce1db 106 link: function(scope, element, attrs) {
bafce1db
TO
107
108 var input = $('input', element);
109
110 scope._resetSelection = function() {
111 $(input).select2('close');
112 $(input).select2('val', '');
113 scope[attrs.crmVar] = '';
114 };
115
4324b8d7 116 $(input).crmSelect2({
c0bb8bd4
DB
117 data: function () {
118 return { results: scope[attrs.crmOptions] };
119 },
bafce1db 120 createSearchChoice: function(term) {
4324b8d7 121 return {id: term, text: term + ' (' + ts('new') + ')'};
00eee619 122 },
4324b8d7 123 createSearchChoicePosition: 'bottom',
00eee619 124 placeholder: attrs.placeholder
bafce1db
TO
125 });
126 $(input).on('select2-selecting', function(e) {
127 scope[attrs.crmVar] = e.val;
128 scope.$evalAsync(attrs.crmOnAdd);
129 scope.$evalAsync('_resetSelection()');
130 e.preventDefault();
131 });
132 }
95fd24c0
TO
133 };
134 });
135
d7a470db
DB
136 crmCaseType.directive('crmEditableTabTitle', function($timeout) {
137 return {
138 restrict: 'AE',
139 link: function(scope, element, attrs) {
140 element.addClass('crm-editable crm-editable-enabled');
141 var titleLabel = $(element).find('span');
142 var penIcon = $('<i class="crm-i fa-pencil crm-editable-placeholder"></i>').prependTo(element);
143 var saveButton = $('<button type="button"><i class="crm-i fa-check"></i></button>').appendTo(element);
144 var cancelButton = $('<button type="cancel"><i class="crm-i fa-times"></i></button>').appendTo(element);
145 $('button', element).wrapAll('<div class="crm-editable-form" style="display:none" />');
146 var buttons = $('.crm-editable-form', element);
147 titleLabel.on('click', startEditMode);
148 penIcon.on('click', startEditMode);
149
150 function detectEscapeKeyPress (event) {
151 var isEscape = false;
152
153 if ("key" in event) {
154 isEscape = (event.key == "Escape" || event.key == "Esc");
155 } else {
156 isEscape = (event.keyCode == 27);
157 }
158
159 return isEscape;
160 }
161
162 function detectEnterKeyPress (event) {
163 var isEnter = false;
164
165 if ("key" in event) {
166 isEnter = (event.key == "Enter");
167 } else {
168 isEnter = (event.keyCode == 13);
169 }
170
171 return isEnter;
172 }
173
174 function startEditMode () {
175 if (titleLabel.is(":focus")) {
176 return;
177 }
178
179 penIcon.hide();
180 buttons.show();
181
182 saveButton.click(function () {
183 updateTextValue();
184 stopEditMode();
185 });
186
187 cancelButton.click(function () {
188 revertTextValue();
189 stopEditMode();
190 });
191
192 $(element).addClass('crm-editable-editing');
193
194 titleLabel
195 .attr("contenteditable", "true")
196 .focus()
197 .focusout(function (event) {
198 $timeout(function () {
199 revertTextValue();
200 stopEditMode();
201 }, 500);
202 })
203 .keydown(function(event) {
204 event.stopImmediatePropagation();
205
206 if(detectEscapeKeyPress(event)) {
207 revertTextValue();
208 stopEditMode();
209 } else if(detectEnterKeyPress(event)) {
210 event.preventDefault();
211 updateTextValue();
212 stopEditMode();
213 }
214 });
215 }
216
217 function stopEditMode () {
218 titleLabel.removeAttr("contenteditable").off("focusout");
219 titleLabel.off("keydown");
220 saveButton.off("click");
221 cancelButton.off("click");
222 $(element).removeClass('crm-editable-editing');
223
224 penIcon.show();
225 buttons.hide();
226 }
227
228 function revertTextValue () {
229 titleLabel.text(scope.activitySet.label);
230 }
231
232 function updateTextValue () {
233 var updatedTitle = titleLabel.text();
234
235 scope.$evalAsync(function () {
236 scope.activitySet.label = updatedTitle;
237 });
238 }
239 }
240 };
241 });
242
d9f57ab1 243 crmCaseType.controller('CaseTypeCtrl', function($scope, crmApi, apiCalls, crmUiHelp) {
41cf58d3 244 var defaultAssigneeDefaultValue, ts;
ad8d1ce3
RO
245
246 (function init () {
ad8d1ce3
RO
247
248 ts = $scope.ts = CRM.ts(null);
d9f57ab1 249 $scope.hs = crmUiHelp({file: 'CRM/Case/CaseType'});
ad8d1ce3
RO
250 $scope.locks = { caseTypeName: true, activitySetName: true };
251 $scope.workflows = { timeline: 'Timeline', sequence: 'Sequence' };
252 defaultAssigneeDefaultValue = _.find(apiCalls.defaultAssigneeTypes.values, { is_default: '1' }) || {};
253
254 storeApiCallsResults();
255 initCaseType();
256 initCaseTypeDefinition();
257 initSelectedStatuses();
258 })();
259
260 /// Stores the api calls results in the $scope object
261 function storeApiCallsResults() {
262 $scope.activityStatuses = apiCalls.actStatuses.values;
263 $scope.caseStatuses = _.indexBy(apiCalls.caseStatuses.values, 'name');
264 $scope.activityTypes = _.indexBy(apiCalls.actTypes.values, 'name');
265 $scope.activityTypeOptions = _.map(apiCalls.actTypes.values, formatActivityTypeOption);
266 $scope.defaultAssigneeTypes = apiCalls.defaultAssigneeTypes.values;
bb8b702c
AF
267 $scope.relationshipTypeOptions = getRelationshipTypeOptions(false);
268 $scope.defaultRelationshipTypeOptions = getRelationshipTypeOptions(true);
ad8d1ce3
RO
269 // stores the default assignee values indexed by their option name:
270 $scope.defaultAssigneeTypeValues = _.chain($scope.defaultAssigneeTypes)
271 .indexBy('name').mapValues('value').value();
272 }
273
bb8b702c
AF
274 // Returns the relationship type options. If the relationship is
275 // bidirectional (Ex: Spouse of) it adds a single option otherwise it adds
276 // two options representing the relationship type directions (Ex: Employee
277 // of, Employer of).
278 //
279 // The default relationship field needs values that are IDs with direction,
280 // while the role field needs values that are names (with implicit
281 // direction).
282 //
283 // At any rate, the labels should follow the convention in the UI of
284 // describing case roles from the perspective of the client, while the
285 // values must follow the convention in the XML of describing case roles
286 // from the perspective of the non-client.
287 function getRelationshipTypeOptions($isDefault) {
288 return _.transform(apiCalls.relTypes.values, function(result, relType) {
289 var isBidirectionalRelationship = relType.label_a_b === relType.label_b_a;
290 if ($isDefault) {
291 result.push({
292 label: relType.label_b_a,
293 value: relType.id + '_a_b'
294 });
295
296 if (!isBidirectionalRelationship) {
297 result.push({
298 label: relType.label_a_b,
299 value: relType.id + '_b_a'
300 });
301 }
302 }
cd2c9605
AF
303 // TODO The ids below really should use names not labels see
304 // https://lab.civicrm.org/dev/core/issues/774
bb8b702c
AF
305 else {
306 result.push({
307 text: relType.label_b_a,
cd2c9605 308 id: relType.label_a_b
bb8b702c
AF
309 });
310
311 if (!isBidirectionalRelationship) {
312 result.push({
313 text: relType.label_a_b,
cd2c9605 314 id: relType.label_b_a
bb8b702c
AF
315 });
316 }
317 }
318 }, []);
319 }
320
ad8d1ce3
RO
321 /// initializes the case type object
322 function initCaseType() {
323 var isNewCaseType = !apiCalls.caseType;
324
325 if (isNewCaseType) {
326 $scope.caseType = _.cloneDeep(newCaseTypeTemplate);
327 } else {
328 $scope.caseType = apiCalls.caseType;
329 }
330 }
76e4acb8 331
ad8d1ce3
RO
332 /// initializes the case type definition object
333 function initCaseTypeDefinition() {
334 $scope.caseType.definition = $scope.caseType.definition || [];
335 $scope.caseType.definition.activityTypes = $scope.caseType.definition.activityTypes || [];
336 $scope.caseType.definition.activitySets = $scope.caseType.definition.activitySets || [];
337 $scope.caseType.definition.caseRoles = $scope.caseType.definition.caseRoles || [];
338 $scope.caseType.definition.statuses = $scope.caseType.definition.statuses || [];
339 $scope.caseType.definition.timelineActivityTypes = $scope.caseType.definition.timelineActivityTypes || [];
06f21064
TO
340 $scope.caseType.definition.restrictActivityAsgmtToCmsUser = $scope.caseType.definition.restrictActivityAsgmtToCmsUser || 0;
341 $scope.caseType.definition.activityAsgmtGrps = $scope.caseType.definition.activityAsgmtGrps || [];
ad8d1ce3
RO
342
343 _.each($scope.caseType.definition.activitySets, function (set) {
344 _.each(set.activityTypes, function (type, name) {
345 var isDefaultAssigneeTypeUndefined = _.isUndefined(type.default_assignee_type);
1e921db0
RO
346 var typeDefinition = $scope.activityTypes[type.name];
347 type.label = (typeDefinition && typeDefinition.label) || type.name;
ad8d1ce3
RO
348
349 if (isDefaultAssigneeTypeUndefined) {
350 type.default_assignee_type = defaultAssigneeDefaultValue.value;
351 }
352 });
be5aae33 353 });
bb8b702c
AF
354
355 // go lookup and add client-perspective labels for $scope.caseType.definition.caseRoles
356 _.each($scope.caseType.definition.caseRoles, function (set) {
d02fe8e4
D
357 _.each($scope.relationshipTypeOptions, function (relationshipTypeOption) {
358 if (relationshipTypeOption.text == set.name) {
359 // relationshipTypeOption.id here corresponds to one of the civicrm_relationship_type.label database fields, not civicrm_relationship_type.id
360 set.displaylabel = relationshipTypeOption.id;
bb8b702c
AF
361 }
362 });
363 });
ad8d1ce3 364 }
7c2b40d1 365
ad8d1ce3
RO
366 /// initializes the selected statuses
367 function initSelectedStatuses() {
368 $scope.selectedStatuses = {};
093f1cfd 369
ad8d1ce3
RO
370 _.each(apiCalls.caseStatuses.values, function (status) {
371 $scope.selectedStatuses[status.name] = !$scope.caseType.definition.statuses.length || $scope.caseType.definition.statuses.indexOf(status.name) > -1;
372 });
373 }
4c58e251 374
76e4acb8
TO
375 $scope.addActivitySet = function(workflow) {
376 var activitySet = {};
377 activitySet[workflow] = '1';
378 activitySet.activityTypes = [];
379
380 var offset = 1;
381 var names = _.pluck($scope.caseType.definition.activitySets, 'name');
382 while (_.contains(names, workflow + '_' + offset)) offset++;
383 activitySet.name = workflow + '_' + offset;
384 activitySet.label = (offset == 1 ) ? $scope.workflows[workflow] : ($scope.workflows[workflow] + ' #' + offset);
385
386 $scope.caseType.definition.activitySets.push(activitySet);
387 _.defer(function() {
388 $('.crmCaseType-acttab').tabs('refresh').tabs({active: -1});
389 });
390 };
391
4324b8d7
CW
392 function formatActivityTypeOption(type) {
393 return {id: type.name, text: type.label, icon: type.icon};
394 }
395
396 function addActivityToSet(activitySet, activityTypeName) {
0f25eb9c
SA
397 activitySet.activityTypes = activitySet.activityTypes || [];
398 var activity = {
093f1cfd
AP
399 name: activityTypeName,
400 label: $scope.activityTypes[activityTypeName].label,
401 status: 'Scheduled',
402 reference_activity: 'Open Case',
403 reference_offset: '1',
ad8d1ce3
RO
404 reference_select: 'newest',
405 default_assignee_type: $scope.defaultAssigneeTypeValues.NONE
093f1cfd
AP
406 };
407 activitySet.activityTypes.push(activity);
408 if(typeof activitySet.timeline !== "undefined" && activitySet.timeline == "1") {
409 $scope.caseType.definition.timelineActivityTypes.push(activity);
410 }
411 }
412
413 function resetTimelineActivityTypes() {
414 $scope.caseType.definition.timelineActivityTypes = [];
415 angular.forEach($scope.caseType.definition.activitySets, function(activitySet) {
416 angular.forEach(activitySet.activityTypes, function(activityType) {
417 $scope.caseType.definition.timelineActivityTypes.push(activityType);
418 });
419 });
4324b8d7
CW
420 }
421
422 function createActivity(name, callback) {
423 CRM.loadForm(CRM.url('civicrm/admin/options/activity_type', {action: 'add', reset: 1, label: name, component_id: 7}))
424 .on('crmFormSuccess', function(e, data) {
425 $scope.activityTypes[data.optionValue.name] = data.optionValue;
426 $scope.activityTypeOptions.push(formatActivityTypeOption(data.optionValue));
427 callback(data.optionValue);
428 $scope.$digest();
429 });
430 }
431
432 // Add a new activity entry to an activity-set
433 $scope.addActivity = function(activitySet, activityType) {
434 if ($scope.activityTypes[activityType]) {
435 addActivityToSet(activitySet, activityType);
436 } else {
437 createActivity(activityType, function(newActivity) {
438 addActivityToSet(activitySet, newActivity.name);
439 });
60dd172b 440 }
d7c25f6c
TO
441 };
442
443 /// Add a new top-level activity-type entry
444 $scope.addActivityType = function(activityType) {
445 var names = _.pluck($scope.caseType.definition.activityTypes, 'name');
446 if (!_.contains(names, activityType)) {
4324b8d7
CW
447 // Add an activity type that exists
448 if ($scope.activityTypes[activityType]) {
449 $scope.caseType.definition.activityTypes.push({name: activityType});
450 } else {
451 createActivity(activityType, function(newActivity) {
452 $scope.caseType.definition.activityTypes.push({name: newActivity.name});
453 });
454 }
d7c25f6c
TO
455 }
456 };
457
ad8d1ce3
RO
458 /// Clears the activity's default assignee values for relationship and contact
459 $scope.clearActivityDefaultAssigneeValues = function(activity) {
460 activity.default_assignee_relationship = null;
461 activity.default_assignee_contact = null;
462 };
463
cd2c9605
AF
464 // TODO roleName passed to addRole is a misnomer, its passed as the
465 // label HOWEVER it should be saved to xml as the name see
466 // https://lab.civicrm.org/dev/core/issues/774
467
8c7e0ae8
TO
468 /// Add a new role
469 $scope.addRole = function(roles, roleName) {
bafce1db
TO
470 var names = _.pluck($scope.caseType.definition.caseRoles, 'name');
471 if (!_.contains(names, roleName)) {
bb8b702c
AF
472 var matchingRoles = _.filter($scope.relationshipTypeOptions, {id: roleName});
473 if (matchingRoles.length) {
474 var matchingRole = matchingRoles.shift();
475 roles.push({name: roleName, displaylabel: matchingRole.text});
4324b8d7 476 } else {
41cf58d3 477 CRM.loadForm(CRM.url('civicrm/admin/reltype', {action: 'add', reset: 1, label_a_b: roleName}))
4324b8d7 478 .on('crmFormSuccess', function(e, data) {
03f9a501 479 var newType = _.values(data.relationshipType)[0];
cdd01a31
D
480 $scope.$apply(function() {
481 $scope.addRoleOnTheFly(roles, newType);
482 });
4324b8d7
CW
483 });
484 }
60dd172b 485 }
8c7e0ae8
TO
486 };
487
cdd01a31
D
488 $scope.addRoleOnTheFly = function(roles, newType) {
489 roles.push({name: newType.label_b_a, displaylabel: newType.label_a_b});
490 // Assume that the case role should be A-B but add both directions as options.
38ddfacb 491 $scope.relationshipTypeOptions.push({id: newType.label_a_b, text: newType.label_b_a});
cdd01a31 492 if (newType.label_a_b != newType.label_b_a) {
38ddfacb 493 $scope.relationshipTypeOptions.push({id: newType.label_b_a, text: newType.label_a_b});
cdd01a31
D
494 }
495 };
496
4c58e251
TO
497 $scope.onManagerChange = function(managerRole) {
498 angular.forEach($scope.caseType.definition.caseRoles, function(caseRole) {
499 if (caseRole != managerRole) {
500 caseRole.manager = '0';
501 }
502 });
503 };
504
505 $scope.removeItem = function(array, item) {
506 var idx = _.indexOf(array, item);
507 if (idx != -1) {
508 array.splice(idx, 1);
093f1cfd 509 resetTimelineActivityTypes();
4c58e251
TO
510 }
511 };
512
b40b4114 513 $scope.isForkable = function() {
f2bad133 514 return !$scope.caseType.id || $scope.caseType.is_forkable;
b40b4114
TO
515 };
516
7c2b40d1
CW
517 $scope.newStatus = function() {
518 CRM.loadForm(CRM.url('civicrm/admin/options/case_status', {action: 'add', reset: 1}))
519 .on('crmFormSuccess', function(e, data) {
520 $scope.caseStatuses[data.optionValue.name] = data.optionValue;
521 $scope.selectedStatuses[data.optionValue.name] = true;
522 $scope.$digest();
523 });
524 };
525
5d973e24
TO
526 $scope.isNewActivitySetAllowed = function(workflow) {
527 switch (workflow) {
528 case 'timeline':
529 return true;
b387506c 530 case 'sequence':
b04e5ffb 531 return 0 === _.where($scope.caseType.definition.activitySets, {sequence: '1'}).length;
5d973e24 532 default:
bba9b4f0 533 CRM.console('warn', 'Denied access to unrecognized workflow: (' + workflow + ')');
5d973e24
TO
534 return false;
535 }
536 };
537
259a7652 538 $scope.isActivityRemovable = function(activitySet, activity) {
12b84ade 539 return true;
259a7652
TO
540 };
541
f42b448f
TO
542 $scope.isValidName = function(name) {
543 return !name || name.match(/^[a-zA-Z0-9_]+$/);
544 };
545
4c58e251 546 $scope.getWorkflowName = function(activitySet) {
76e4acb8
TO
547 var result = 'Unknown';
548 _.each($scope.workflows, function(value, key) {
549 if (activitySet[key]) result = value;
550 });
551 return result;
4c58e251
TO
552 };
553
554 /**
555 * Determine which HTML partial to use for a particular
556 *
557 * @return string URL of the HTML partial
558 */
559 $scope.activityTableTemplate = function(activitySet) {
560 if (activitySet.timeline) {
ef5d18a1 561 return '~/crmCaseType/timelineTable.html';
b387506c 562 } else if (activitySet.sequence) {
ef5d18a1 563 return '~/crmCaseType/sequenceTable.html';
4c58e251
TO
564 } else {
565 return '';
566 }
567 };
568
569 $scope.dump = function() {
570 console.log($scope.caseType);
76e4acb8
TO
571 };
572
aa1a7c2e 573 $scope.save = function() {
7c2b40d1
CW
574 // Add selected statuses
575 var selectedStatuses = [];
576 _.each($scope.selectedStatuses, function(v, k) {
577 if (v) selectedStatuses.push(k);
578 });
579 // Ignore if ALL or NONE selected
580 $scope.caseType.definition.statuses = selectedStatuses.length == _.size($scope.selectedStatuses) ? [] : selectedStatuses;
06f21064
TO
581
582 if ($scope.caseType.definition.activityAsgmtGrps) {
583 $scope.caseType.definition.activityAsgmtGrps = $scope.caseType.definition.activityAsgmtGrps.toString().split(",");
584 }
585
bb8b702c
AF
586 function dropDisplaylabel (v) {
587 delete v.displaylabel;
588 }
589
590 // strip out labels from $scope.caseType.definition.caseRoles
591 _.map($scope.caseType.definition.caseRoles, dropDisplaylabel);
592
c7bccb5f 593 var result = crmApi('CaseType', 'create', $scope.caseType, true);
3140a415 594 result.then(function(data) {
b04e5ffb 595 if (data.is_error === 0 || data.is_error == '0') {
c7bccb5f 596 $scope.caseType.id = data.id;
1ab5b88e 597 window.location.href = '#/caseType';
c7bccb5f 598 }
599 });
aa1a7c2e
TO
600 };
601
76e4acb8
TO
602 $scope.$watchCollection('caseType.definition.activitySets', function() {
603 _.defer(function() {
8fc6fba7 604 $('.crmCaseType-acttab').tabs('refresh');
76e4acb8
TO
605 });
606 });
685acae4 607
608 var updateCaseTypeName = function () {
609 if (!$scope.caseType.id && $scope.locks.caseTypeName) {
610 // Should we do some filtering? Lowercase? Strip whitespace?
a5ca1f48 611 var t = $scope.caseType.title ? $scope.caseType.title : '';
612 $scope.caseType.name = t.replace(/ /g, '_').replace(/[^a-zA-Z0-9_]/g, '').toLowerCase();
685acae4 613 }
614 };
615 $scope.$watch('locks.caseTypeName', updateCaseTypeName);
616 $scope.$watch('caseType.title', updateCaseTypeName);
b40b4114
TO
617
618 if (!$scope.isForkable()) {
619 CRM.alert(ts('The CiviCase XML file for this case-type prohibits editing the definition.'));
620 }
093f1cfd 621
4c58e251
TO
622 });
623
b75c2546 624 crmCaseType.controller('CaseTypeListCtrl', function($scope, crmApi, caseTypes) {
7abbf317
CW
625 var ts = $scope.ts = CRM.ts(null);
626
b75c2546 627 $scope.caseTypes = caseTypes.values;
4b8c8b42
TO
628 $scope.toggleCaseType = function (caseType) {
629 caseType.is_active = (caseType.is_active == '1') ? '0' : '1';
630 crmApi('CaseType', 'create', caseType, true)
c99f1a0a
TO
631 .catch(function (data) {
632 caseType.is_active = (caseType.is_active == '1') ? '0' : '1'; // revert
633 $scope.$digest();
4b8c8b42
TO
634 });
635 };
636 $scope.deleteCaseType = function (caseType) {
eb8e4c2d
TO
637 crmApi('CaseType', 'delete', {id: caseType.id}, {
638 error: function (data) {
7abbf317 639 CRM.alert(data.error_message, ts('Error'), 'error');
eb8e4c2d
TO
640 }
641 })
4b8c8b42 642 .then(function (data) {
c99f1a0a 643 delete caseTypes.values[caseType.id];
4b8c8b42
TO
644 });
645 };
470a458e
TO
646 $scope.revertCaseType = function (caseType) {
647 caseType.definition = 'null';
648 caseType.is_forked = '0';
649 crmApi('CaseType', 'create', caseType, true)
c99f1a0a
TO
650 .catch(function (data) {
651 caseType.is_forked = '1'; // restore
652 $scope.$digest();
470a458e
TO
653 });
654 };
b75c2546
TO
655 });
656
bba9b4f0 657})(angular, CRM.$, CRM._);