"use strict"; (function () { 'use strict'; angular.module('changeModule') .directive('datesV2', ['events', '$filter', 'editTicketDatesService', 'fieldValidationModel', '$modal', 'tabIds', 'metadataModel', 'collisionModel', 'systemAlertService', 'emailModel', 'ticketModel', 'searchModel', 'screenConfigurationModel', '$rootScope', 'configurationModel', 'expressionEventManager', '$timeout', function (events, $filter, editTicketDatesService, fieldValidationModel, $modal, tabIds, metadataModel, collisionModel, systemAlertService, emailModel, ticketModel, searchModel, screenConfigurationModel, $rootScope, configurationModel, expressionEventManager, $timeout) { return { restrict: 'E', replace: true, templateUrl: 'views/change/dates-v2.html', scope: { collisions: '=', context: '=', editMode: '=', isNew: '=', datesCustomFields: '=', screenLayout: '=', metadata: '=' }, link: function (scope, $element) { scope.$on(events.WIDGET_VALUE_CHANGE, function (event, data) { $rootScope.$broadcast(events.WIDGET_VALUE_CHANGE_FROM_WIZARD, data); }); scope.$on(events.FIELD_VALUE_CHANGE, function (event, data) { $rootScope.$broadcast(events.FIELD_VALUE_CHANGE_FROM_WIZARD, data); }); scope.showMeridian = window.showMeridian; var loadCollisions = !scope.editMode || scope.isNew; scope.collisionStates = { shouldRefreshCollisions: false, editCollisionStatus: false }; scope.state = { loadingCollisions: false }; scope.changeFlag = false; scope.asc = false; scope.validator = editTicketDatesService; scope.tabIds = tabIds; scope.disableCollisionManagement = searchModel.disableCollisionManagement; scope.collisionsSelected = 0; scope.currentDate = new Date(); scope.autoTriggerChangeCollisionForCIsUpto = configurationModel.autoTriggerChangeCollisionForCIsUpto; if (!scope.isNew) { metadataModel.getMetadataByType(EntityVO.TYPE_CHANGE).then(function (metadata) { scope.collisionStatuses = metadata.collisionStatuses; }); scope.collisionStates.editCollisionStatus = scope.context.accessMappings.collisionEditAllowed; } scope.datePickerOptions = { startingDay: configurationModel.getWeekStartingDay(), 'show-weeks': false, minDate: moment().year(1970).month(0).date(2), maxDate: moment().year(2038).month(0).date(18) }; scope.$watch('collisions', function () { scope.collisionsCopy = _.cloneDeep(scope.collisions); if (scope.collisions && scope.collisions.changeList) { scope.$emit(events.UPDATE_CHANGE_COLLISION_STATUS, scope.collisions); scope.$emit(events.CHANGE_COLLISION_STATUS_CHANGED, scope.collisions.changeList); } }); scope.$on(events.TOGGLE_CHANGE_CALENDAR, function (event, expanded) { scope.expanded = expanded; }); scope.openDatePicker = function (calendar, event) { calendar.open = true; if (scope.editMode) { event.stopPropagation(); } }; scope.updateDateTime = function (type) { editTicketDatesService.updateDateTime(scope[scope.tabIds.wizard.dates], scope.context, type); }; scope.editDatesView = function () { updateCollisions(); scope.collisionStates.shouldRefreshCollisions = false; }; scope.$watch('context.targetDate', function () { scope.updateTargetDateTime(); }); scope.$watch('context.scheduledStartDate', function (newDate, oldDate) { //Updating schedule start date model when selecting date from calendar scope.$broadcast(events.UPDATE_SCHEDULE_DATE, { name: 'scheduledStartDate', value: newDate }); newDate = newDate ? newDate.valueOf() : newDate; oldDate = oldDate ? oldDate.valueOf() : oldDate; refreshCollisions(newDate, oldDate); }); scope.$watch('context.scheduledEndDate', function (newDate, oldDate) { //Updating schedule end date model when selecting date from calendar scope.$broadcast(events.UPDATE_SCHEDULE_DATE, { name: 'scheduledEndDate', value: newDate }); newDate = newDate ? newDate.valueOf() : newDate; oldDate = oldDate ? oldDate.valueOf() : oldDate; refreshCollisions(newDate, oldDate); }); scope.$watch('context.linkedCIs', function () { if (!scope.editMode || scope.isNew) { if (scope.context.linkedCIs && scope.context.linkedCIs.length) { updateCollisions(); } else { scope.collisionsCopy = {}; } scope.collisionStates.shouldRefreshCollisions = false; } }); var cancelRootScopeListener1 = $rootScope.$on(events.AFFECTED_SERVICE_VALUE_CHANGED, function (event, selectedService) { if (!scope.editMode || scope.isNew) { scope.context.impactedService = selectedService; updateCollisions(); } }); var cancelRootScopeListener2 = $rootScope.$on(events.CHANGE_CLASS_VALUE_CHANGED, function (event, changeClass) { if (!scope.editMode || scope.isNew) { scope.context.timing = changeClass; scope.context.useTargetDate = false; scope.clearDates(); } }); scope.$watch(tabIds.wizard.dates + '.$dirty', function (dirty) { if (typeof dirty !== 'undefined') { scope.$emit(events.CHANGE_WIZARD_FORM_STATE, { name: scope.tabIds.wizard.dates, dirty: dirty }); } }); scope.$watch(tabIds.wizard.dates + '.$invalid', function (invalid) { if (typeof invalid !== 'undefined') { scope.$emit(events.CHANGE_WIZARD_FORM_STATE, { name: scope.tabIds.wizard.dates, invalid: invalid }); } }); scope.$on(events.CHANGE_COLLISION_SHOW_WEEKENDS, function (event, data) { scope.showWeekends = data.showWeekends; }); function refreshCollisions(newDate, oldDate) { var linkedCIs = []; if (scope.context.linkedCIs && scope.context.linkedCIs.length) { linkedCIs.push.apply(linkedCIs, scope.context.linkedCIs); } if (scope.context.impactedService && scope.context.impactedService.reconciliationId) { if (!_.find(linkedCIs, { id: scope.context.impactedService.reconciliationId })) { linkedCIs.push({ id: scope.context.impactedService.reconciliationId }); } } if (newDate && newDate !== oldDate) { if (!scope.editMode || scope.isNew) { if (loadCollisions) { updateCollisions(); } else if (scope.context.scheduledStartDate && scope.context.scheduledEndDate) { if (linkedCIs && linkedCIs.length && !isNaN(scope.autoTriggerChangeCollisionForCIsUpto) && !_.isUndefined(scope.autoTriggerChangeCollisionForCIsUpto) && linkedCIs.length > scope.autoTriggerChangeCollisionForCIsUpto) { scope.showRunCollisionDetectionMsg = true; scope.collisionsCopy = {}; } else { scope.collisionStates.shouldRefreshCollisions = true; } } } else if (scope.editMode) { scope.collisionStates.saveDatesAndUpdate = (scope.context.scheduledStartDate && scope.context.scheduledEndDate) && (scope.context.scheduledStartDate.getTime() <= scope.context.scheduledEndDate.getTime()) ? scope[scope.tabIds.wizard.dates].dateForm.$valid : false; scope.collisionStates.editCollisionStatus = false; checkAutoTriggerCollision(linkedCIs); } } else if (!scope.editMode || scope.isNew) { scope.collisionStates.shouldRefreshCollisions = false; scope.collisionsCopy = {}; } else if (scope.editMode) { checkAutoTriggerCollision(linkedCIs); } } function updateCollisions() { var linkedCIs = []; if (scope.context.impactedService) { linkedCIs.push({ id: scope.context.impactedService.reconciliationId }); } if (scope.context.linkedCIs && scope.context.linkedCIs.length) { linkedCIs.push.apply(linkedCIs, scope.context.linkedCIs); } if (scope.context.scheduledStartDate && scope.context.scheduledEndDate && linkedCIs && linkedCIs.length && (isNaN(scope.autoTriggerChangeCollisionForCIsUpto) || _.isUndefined(scope.autoTriggerChangeCollisionForCIsUpto) || linkedCIs.length <= scope.autoTriggerChangeCollisionForCIsUpto)) { scope.showRunCollisionDetectionMsg = false; scope.state.loadingCollisions = true; if (!scope.context.scheduledStartTime) { scope.context.scheduledStartTime = scope.context.scheduledStartDate; } if (!scope.context.scheduledEndTime) { scope.context.scheduledEndTime = scope.context.scheduledEndDate; } collisionModel.getListOfCollisionsAndCiByDate(scope.context.scheduledStartDate, scope.context.scheduledEndDate, linkedCIs) .then(function (data, error) { if (data) { scope.collisionsCopy = data; scope.collisionsCopy.changeList.filter(function (item) { if (item.id === scope.context.id) { scope.collisionsCopy.changeList.splice(scope.collisionsCopy.changeList.indexOf(item), 1); } }); scope.state.loadingCollisions = false; } if (error) { systemAlertService.error({ text: error, clear: true }); } }).finally(function () { loadCollisions = false; }); } else { scope.collisionsCopy = {}; scope.showRunCollisionDetectionMsg = scope.context.scheduledStartDate && scope.context.scheduledEndDate && linkedCIs && !isNaN(configurationModel.autoTriggerChangeCollisionForCIsUpto) && !_.isUndefined(configurationModel.autoTriggerChangeCollisionForCIsUpto) && linkedCIs.length && linkedCIs.length > scope.autoTriggerChangeCollisionForCIsUpto ? true : false; } } scope.updateTargetDateTime = function () { if (!scope[scope.tabIds.wizard.dates]) { return; } editTicketDatesService.updateTargetDateTime(scope[scope.tabIds.wizard.dates], scope.context); }; scope.toggleUseTargetDate = function () { scope.context.useTargetDate = !scope.context.useTargetDate; scope.showRunCollisionDetectionMsg = false; scope.clearDates(); }; scope.useTargetDateCheckboxVisible = function () { return !scope.editMode || (scope.isNew && scope.targetDateSection); }; scope.targetDateErrorMessageVisible = function () { return (scope.editMode || scope.context.useTargetDate) && scope.dates.targetDate.$invalid; }; scope.targetDateFieldVisible = function () { return (scope.isNew && scope.context.useTargetDate) || (!scope.isNew && scope.editMode); }; scope.clearDates = function () { if (scope.context.useTargetDate) { scope.context.scheduledStartDate = null; scope.context.scheduledEndDate = null; scope.context.actualStartDate = null; scope.context.actualEndDate = null; } else { scope.context.targetDate = null; } scope.$broadcast(events.CLEAR_CHANGE_DATES, scope.context.useTargetDate); }; scope.useTargetDateDisabled = function () { return scope.context.timing && scope.context.timing.name === 'Latent'; }; scope.isFieldRequired = function (field) { var fieldRequired = false; if (scope.context.timing) { fieldRequired = fieldValidationModel.isFieldRequired(EntityVO.TYPE_CHANGE, 'Draft', scope.context.timing.name, field); } return fieldRequired; }; scope.isFieldDisabled = function (field) { var fieldDisabled = false; if (scope.context.timing) { fieldDisabled = fieldValidationModel.isFieldDisabled(EntityVO.TYPE_CHANGE, 'Draft', scope.context.timing.name, field); } return fieldDisabled; }; scope.isFieldEditable = function (fieldName) { var accessMappings = scope.context.accessMappings, accessMapping = accessMappings && accessMappings.fieldMappings ? accessMappings.fieldMappings[fieldName] : null; if (accessMapping) { return (accessMapping === 'write'); } else { return accessMappings.datesEditAllowed; } }; scope.saveDates = function () { var dateChanges = { scheduledStartDate: getTimestamp(scope.context.scheduledStartDate), scheduledEndDate: getTimestamp(scope.context.scheduledEndDate), actualStartDate: getTimestamp(scope.context.actualStartDate), actualEndDate: getTimestamp(scope.context.actualEndDate), targetDate: getTimestamp(scope.context.targetDate) }; scope.state.loadingCollisions = true; var updateChangeDatesPromise = ticketModel.update(scope.context.id, scope.context.type, dateChanges); updateChangeDatesPromise.then(function (response, error) { if (response) { _.extend(scope.context, response); collisionModel.getListOfCollisionsById(scope.context, true) .then(function (collisionSummary) { if (collisionSummary.count > 0) { scope.collisions = collisionSummary; scope.collisionsCopy = _.cloneDeep(scope.collisions); } scope.state.loadingCollisions = false; }); } if (error) { systemAlertService.error({ text: error, clear: true }); } }).finally(function () { scope.collisionStates.editCollisionStatus = scope.context.accessMappings.collisionEditAllowed; scope.collisionStates.saveDatesAndUpdate = false; }); }; function getTimestamp(date, time) { time = time ? moment(time) : moment(date); return moment(date).set('hours', time.get('hours')).set('minutes', time.get('minutes')).format('X') * 1000; } function checkAutoTriggerCollision(linkedCIs) { scope.showRunCollisionDetectionMsg = scope.context.scheduledStartDate && scope.context.scheduledEndDate && linkedCIs && linkedCIs.length && !isNaN(scope.autoTriggerChangeCollisionForCIsUpto) && !_.isUndefined(scope.autoTriggerChangeCollisionForCIsUpto) && linkedCIs.length > scope.autoTriggerChangeCollisionForCIsUpto ? true : false; } scope.markStatus = function (status) { var count = 0, modalInstance = $modal.open({ templateUrl: 'views/change/rationale.html', windowClass: 'action-blade', controller: 'RationaleController', resolve: { isRationalRequired: function () { return !!(status.name === 'Resolved' || status.name === 'Ignored'); } } }); modalInstance.result.then(function (data) { scope.collisionsCopy.changeList.filter(function (change) { for (count = 0; count < change.configurationItems.length; count++) { if (change.configurationItems[count].selected && change.configurationItems[count].status && change.configurationItems[count].status.name !== status.name) { if (change.configurationItems[count].status.name === 'Resolved' || change.configurationItems[count].status.name === 'Ignored') { change.ciCount = change.ciCount + 1; } change.configurationItems[count].status = status; change.configurationItems[count].rationale = data; if (status.name === 'Resolved' || status.name === 'Ignored') { change.ciCount = change.ciCount - 1; } change.configurationItems[count].modified = true; } } }); scope.collisions.changeList = scope.collisionsCopy.changeList; scope.changeFlag = false; scope.selectAllToggle(false); scope.$emit(events.UPDATE_CHANGE_COLLISION_STATUS, scope.collisions); scope.$emit(events.CHANGE_COLLISION_STATUS_CHANGED, scope.collisions.changeList); }); }; /* * Show/Hide and Checked/Unchecked properties of collisions */ scope.selectAllToggle = function (select) { var cis = 0; if (!scope.collisionsCopy || !scope.collisionsCopy.changeList) { return; } for (var i = 0; i < scope.collisionsCopy.changeList.length; i++) { scope.collisionsCopy.changeList[i].selected = select; cis = cis + scope.collisionsCopy.changeList[i].configurationItems.length; for (var j = 0; j < scope.collisionsCopy.changeList[i].configurationItems.length; j++) { scope.collisionsCopy.changeList[i].configurationItems[j].selected = select; } } select ? scope.collisionsSelected = cis : scope.collisionsSelected = 0; }; scope.selectAllChanges = function (changeFlag) { scope.changeFlag = !changeFlag; scope.selectAllToggle(scope.changeFlag); }; scope.selectChange = function (changeItem) { changeItem.selected = !changeItem.selected; changeItem.show = changeItem.selected; if (!changeItem.selected) { scope.collisionsSelected = scope.collisionsSelected - changeItem.configurationItems.length; } for (var i = 0; i < changeItem.configurationItems.length; i++) { if (changeItem.selected && !changeItem.configurationItems[i].selected) { scope.collisionsSelected++; } changeItem.configurationItems[i].selected = changeItem.selected; } }; scope.selectCIs = function (ci, changeItem) { ci.selected = !ci.selected; ci.selected ? scope.collisionsSelected++ : scope.collisionsSelected--; if (!ci.selected) { changeItem.selected = ci.selected; } }; scope.showEmailForm = function () { var recipients = []; _.each(scope.collisionsCopy.changeList, function (change) { if (change.assignee.id) { change.assignee.loginId = change.assignee.id; change.assignee.type = $filter('i18n')('change.detail.emailRecipients.allCollisionManagers'); recipients.push(change.assignee); } }); recipients = _.uniqBy(recipients, 'id'); return emailModel.createEmail([scope.context], recipients); }; var screenPanels; if (!screenConfigurationModel.screensCacheByName[scope.screenLayout.name]) { screenConfigurationModel.loadScreenConfigurationByName(scope.screenLayout.name).then(function (screenLayout) { screenPanels = screenLayout.panels; scope.scheduledDatesSection = _.find(screenPanels, { name: 'scheduledDatesSection' }); scope.actualDatesSection = _.find(screenPanels, { name: 'actualDatesSection' }); scope.targetDateSection = _.find(screenPanels, { name: 'targetDateSection' }); }); } else { screenPanels = scope.screenLayout && screenConfigurationModel.screensCacheByName[scope.screenLayout.name] ? screenConfigurationModel.screensCacheByName[scope.screenLayout.name].panels : []; scope.scheduledDatesSection = _.find(screenPanels, { name: 'scheduledDatesSection' }); scope.actualDatesSection = _.find(screenPanels, { name: 'actualDatesSection' }); scope.targetDateSection = _.find(screenPanels, { name: 'targetDateSection' }); } scope.panelChildrenCount = function (screenPanelName) { if (screenPanelName) { var screenPanel = _.find(screenPanels, { name: screenPanelName }); var datesFieldName = screenPanelName.replace(/Section/g, ""); var datesFieldInDatesPanel = _.find(screenPanel.fields, { name: datesFieldName }); if (screenPanel && datesFieldInDatesPanel) { return 1; } else { //check if the dates widget is in any other panel _.find(screenPanels, function (panel) { if (panel.fields) { var datesFieldInOtherPanel = _.find(panel.fields, { name: datesFieldName }); var screenPaneltoUpdate; //get the fields and add it to the dates panel if (datesFieldInOtherPanel) { scope[screenPanelName].fields.push(datesFieldInOtherPanel); screenPaneltoUpdate = { screenPanelSection: scope[screenPanelName], datesField: datesFieldInOtherPanel }; //revert it from the dates panel on save scope.$emit(events.REMOVE_CHANGE_DATES_FROM_PANEL, screenPaneltoUpdate); return 1; } } }); } } return 0; }; if (scope.editMode) { scope.selectAllToggle(false); } scope.$on(events.UPDATE_DATE_LABEL_VISIBILITY, function (e, data) { switch (data.name) { case 'scheduledDates': if (scope.scheduledDatesSection && scope.scheduledDatesSection.fields && scope.scheduledDatesSection.fields[0] && scope.scheduledDatesSection.fields[0].hasOwnProperty('isHidden')) { scope.scheduledDatesSection.fields[0].isHidden = data.isHidden; } break; case 'actualDates': if (scope.actualDatesSection && scope.actualDatesSection.fields && scope.actualDatesSection.fields[0] && scope.actualDatesSection.fields[0].hasOwnProperty('isHidden')) { scope.actualDatesSection.fields[0].isHidden = data.isHidden; } break; case 'targetDate': if (scope.targetDateSection && scope.targetDateSection.fields && scope.targetDateSection.fields[0] && scope.targetDateSection.fields[0].hasOwnProperty('isHidden')) { scope.targetDateSection.fields[0].isHidden = data.isHidden; } break; } }); var noOfFieldAreasAttached = 0, totalFieldArea; scope.$on(events.FIELD_AREA_ATTACHED, function (e, screenName) { totalFieldArea = totalFieldArea || $element.find('.panel-field-area').length; noOfFieldAreasAttached++; if (totalFieldArea === noOfFieldAreasAttached) { console.log('All custom-area directives are loaded!'); screenConfigurationModel.allFieldsLoaded.datesTab = true; if (screenConfigurationModel.allFieldsLoaded.basicTab || scope.screenLayout.name === ScreenConfigurationVO.prototype.CHANGE_VIEW_SCREEN) { $timeout(function () { expressionEventManager.handleTicketLoad(); }); } } }); scope.$on('$destroy', function () { cancelRootScopeListener1(); cancelRootScopeListener2(); }); } }; } ]); })();