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