"use strict"; /** * Created by andey on 14-12-2016. */ (function () { 'use strict'; angular.module('releaseModule') .directive('releasePlanItemList', ['$q', '$filter', 'relationModel', 'metadataModel', 'relationService', 'systemAlertService', 'events', '$timeout', function ($q, $filter, relationModel, metadataModel, relationService, systemAlertService, events, $timeout) { return { restrict: 'E', replace: true, templateUrl: 'views/release/release-plan-item-list.html', scope: { ticket: '=', isNew: '=?' }, link: function (scope) { scope.state = { dataIsLoading: false, movingToOtherList: false }; scope.releasePlanGroups = {}; scope.milestoneFilters = {}; scope.milestones = {}; //SW00523525 added check for target url for release profile page. scope.isNew === true ? scope.target = '_blank' : scope.target = '_self'; scope.parentSortableOptions = { placeholder: 'profile-relation__item-task-container', connectWith: '.profile-relation__release-plan-container', cancel: ':input,.locked', receive: function (event, ui) { var droptargetMilestone = ui.item.sortable.droptargetModel[0].realObject.releaseMilestone; if (droptargetMilestone !== ui.item.sortable.model.realObject.releaseMilestone) { scope.state.movingToOtherList = true; ui.item.sortable.model.realObject.releaseMilestone = droptargetMilestone; } }, stop: function (event, ui) { var sourceReleasePlanGroup = _.cloneDeep(ui.item.sortable.sourceModel); if (scope.state.movingToOtherList) { var targetReleasePlanGroup = _.cloneDeep(ui.item.sortable.droptargetModel); sortElements(targetReleasePlanGroup); scope.state.movingToOtherList = false; } if (sourceReleasePlanGroup.length) { sortElements(sourceReleasePlanGroup); } else { //Remove empty array from list var emptyArrayIndex = _.findIndex(scope.releasePlanGroups, function (group) { return group.length === 0; }); if (emptyArrayIndex !== -1) { scope.releasePlanGroups.splice(emptyArrayIndex, 1); } } function sortElements(releasePlanGroup) { var sequence = 1; _.forEach(releasePlanGroup, function (item, idx) { var sameOrderFlag = false, nextItem = null; if ((idx + 1) !== releasePlanGroup.length) { nextItem = releasePlanGroup[idx + 1]; } if (nextItem && item.realObject.sequence === nextItem.realObject.sequence && ui.item.sortable.model.id !== nextItem.id) { sameOrderFlag = true; } item.realObject.sequence = sequence; sequence = sameOrderFlag ? item.realObject.sequence : (item.realObject.sequence + 1); }); var releasePlanGroupIndex = _.findIndex(scope.releasePlanGroups, function (group) { if (group && group.length && releasePlanGroup[0].realObject.releaseMilestone === group[0].realObject.releaseMilestone) { return true; } }); scope.releasePlanGroups[releasePlanGroupIndex] = releasePlanGroup; } scope.dirty = true; } }; var allReleasePlanGroups = {}; scope.applyFilter = function (filterOption) { if (scope.dirty) { var modal = systemAlertService.modal({ type: 'info', title: $filter('i18n')('common.notification.dirty.title'), text: $filter('i18n')('common.notification.dirty.loseChanges'), buttons: [ { text: $filter('i18n')('common.button.yes'), data: true }, { text: $filter('i18n')('common.button.no'), data: false } ] }); modal.result.then(function (data) { if (data) { applyFilter(filterOption); } }); } else { applyFilter(filterOption); } }; scope.getSelectedFiltersList = function () { return _.filter(scope.milestoneFilters, { selected: true }); }; scope.selectAll = function (state) { _.forEach(scope.milestoneFilters, function (filter) { filter.selected = state; }); scope.releasePlanGroups = angular.copy(allReleasePlanGroups); }; scope.updateMilestone = function (selectedMilestone, releasePlanItem) { if (releasePlanItem.realObject.releaseMilestone === selectedMilestone.name) { return; } scope.$emit(events.RELEASE_PLAN_MILESTONE_CHANGE); //Remove item from old group var emptyArrayIndex = _.findIndex(scope.releasePlanGroups, function (group) { if (releasePlanItem.realObject.releaseMilestone === group[0].realObject.releaseMilestone) { _.remove(group, { id: releasePlanItem.id }); if (group.length === 0) { return true; } } }); //Remove empty array from list if (emptyArrayIndex !== -1) { scope.releasePlanGroups.splice(emptyArrayIndex, 1); } //Add item to new group var releasePlanGroupIndex = _.findIndex(scope.releasePlanGroups, function (group) { if (selectedMilestone.name === group[0].realObject.releaseMilestone) { return true; } }); if (releasePlanGroupIndex !== -1) { scope.releasePlanGroups[releasePlanGroupIndex].push(releasePlanItem); } else { scope.releasePlanGroups.push([releasePlanItem]); } releasePlanItem.realObject.releaseMilestone = selectedMilestone.name; scope.updateItemsSequence(releasePlanItem); }; scope.updateItemsSequence = function (releasePlanItem) { if (releasePlanItem.realObject.sequence <= 0 || isNaN(releasePlanItem.realObject.sequence) || _.isEmpty(releasePlanItem.realObject.sequence)) { releasePlanItem.realObject.sequence = 1; } else { releasePlanItem.realObject.sequence = parseInt(releasePlanItem.realObject.sequence); } var releasePlanGroupIndex = _.findIndex(scope.releasePlanGroups, function (group) { if (releasePlanItem.realObject.releaseMilestone === group[0].realObject.releaseMilestone) { return true; } }); var releasePlanGroup = angular.copy(scope.releasePlanGroups[releasePlanGroupIndex]), itemIndex = _.findIndex(releasePlanGroup, function (item) { return item.id == releasePlanItem.id; }); releasePlanGroup[itemIndex] = releasePlanItem; // Sort items releasePlanGroup.sort(function (item1, item2) { return (item1.length ? item1[0].realObject.sequence : item1.realObject.sequence) - (item2.length ? item2[0].realObject.sequence : item2.realObject.sequence); }); $timeout(function () { scope.releasePlanGroups[releasePlanGroupIndex] = releasePlanGroup; }, 2000); scope.dirty = true; }; scope.saveSequence = function () { var releasePlanItems = []; _.forEach(scope.releasePlanGroups, function (releaseGroup) { var originalReleaseGroup = _.find(allReleasePlanGroups, function (group) { if (group.length) { return group[0].realObject.releaseMilestone === releaseGroup[0].realObject.releaseMilestone; } else { return false; } }); //originalReleaseGroup not found indicates a new milestone group is created. if (!originalReleaseGroup) { originalReleaseGroup = []; } _.forEach(releaseGroup, function (releaseItem) { //originalItem not found indicates the milestone is updated. var originalItem = _.find(originalReleaseGroup, { id: releaseItem.id }); if (!originalItem || releaseItem.realObject.sequence !== originalItem.realObject.sequence || releaseItem.realObject.releaseMilestone !== originalItem.realObject.releaseMilestone) { var releasePlanItem = { parentId: scope.ticket.id, parentName: EntityVO.TYPE_RELEASE, parentDisplayId: scope.ticket.displayId, milestone: releaseItem.realObject.releaseMilestone, sequence: releaseItem.realObject.sequence, id: releaseItem.id, displayId: releaseItem.displayId, type: releaseItem.type }; releasePlanItems.push(releasePlanItem); } }); }); if (releasePlanItems.length) { relationService.updateReleasePlanItemsSequence(releasePlanItems).then(function () { refreshList(); scope.dirty = false; scope.$emit(events.RELEASE_PLAN_MILESTONE_NOT_DIRTY); }, function (response) { systemAlertService.error({ text: response.data.error, clear: false }); $modalInstance.dismiss(); }); } }; scope.onRevertClick = function () { applyFilter(); scope.dirty = false; }; scope.removeItem = function (planData) { var modalInstance = systemAlertService.modal({ title: $filter('i18n')('common.notification.delete.title'), text: $filter('i18n')('common.notification.delete.message'), buttons: [ { text: $filter('i18n')('common.notification.delete.button1'), data: true }, { text: $filter('i18n')('common.notification.delete.button2'), data: false } ] }); modalInstance.result.then(function (data) { if (data) { if (planData.item.type === EntityVO.TYPE_ACTIVITY) { relationModel.deleteActivity(planData.item).then(function () { removeReleaseItem(allReleasePlanGroups); removeReleaseItem(scope.releasePlanGroups); }, function (response) { systemAlertService.error({ text: response.data.error, clear: false }); $modalInstance.dismiss(); }); } else { var parent = { parentType: scope.ticket.type, parentId: scope.ticket.id }, relation = { id: planData.item.id, type: planData.item.type, relationshipType: planData.item.relationshipType, parentDisplayId: scope.ticket.displayId }; relationModel.removeRelation(parent, [relation]).then(function () { //TODO: Check if call returns success removeReleaseItem(allReleasePlanGroups); removeReleaseItem(scope.releasePlanGroups); }, function (response) { systemAlertService.error({ text: response.planData.error, clear: false }); $modalInstance.dismiss(); }); } } function removeReleaseItem(releasePlanGroups) { _.forEach(releasePlanGroups, function (releaseGroup) { if (planData.item.realObject.releaseMilestone === releaseGroup[0].realObject.releaseMilestone) { _.remove(releaseGroup, { id: planData.item.id }); if (releaseGroup.length) { scope.ticket.noOfRelatedItems[releaseGroup[0].realObject.releaseMilestone] = releaseGroup.length; } } }); //Remove empty array from list var emptyArrayIndex = _.findIndex(releasePlanGroups, function (group) { return group.length === 0; }); if (emptyArrayIndex !== -1) { releasePlanGroups.splice(emptyArrayIndex, 1); } } }); }; function resetFilter() { _.forEach(scope.milestoneFilters, function (item) { item.selected = false; }); } function applyFilter(filterOption) { if (filterOption) { filterOption.selected = !filterOption.selected; } scope.releasePlanGroups = angular.copy(allReleasePlanGroups); if (!_.some(scope.milestoneFilters, { selected: true })) { //No filter selected return; } else { _.remove(scope.releasePlanGroups, function (releasePlanGroup) { //Sometimes releaseMilestone may not be set, checking the same condition using ''. return !_.find(scope.milestoneFilters, { name: releasePlanGroup[0].realObject.releaseMilestone || '' }).selected; }); } scope.dirty = false; } function fetchReleasePlanList() { return relationModel.getRelationsByTag(scope.ticket.id, scope.ticket.type, 'releasePlan').then(function (response) { scope.releasePlanGroups = transformReleaseItems(response); allReleasePlanGroups = angular.copy(scope.releasePlanGroups); scope.ticket.noOfRelatedItems = {}; _.forEach(scope.releasePlanGroups, function (releaseGroup) { if (releaseGroup.length) { scope.ticket.noOfRelatedItems[releaseGroup[0].realObject.releaseMilestone] = releaseGroup.length; } }); }); } function transformReleaseItems(releaseItems) { var releasePlanGroups = _.chain(releaseItems) .groupBy('realObject.releaseMilestone') .map(function (item) { return item; }).value(); return releasePlanGroups; } function refreshList() { scope.state.dataIsLoading = true; fetchReleasePlanList().then(function () { resetFilter(); scope.state.dataIsLoading = false; }); } function init() { scope.state.dataIsLoading = true; var releasePlanPromise = fetchReleasePlanList(), activityMetadataPromise = metadataModel.getMetadataByType(EntityVO.TYPE_ACTIVITY), releaseMetadataPromise = metadataModel.getMetadataByType(EntityVO.TYPE_RELEASE); $q.all([releasePlanPromise, activityMetadataPromise, releaseMetadataPromise]).then(function (response) { var releaseMetadata = response[2]; scope.milestoneFilters = angular.copy(releaseMetadata.milestones); scope.milestoneFilters.unshift({ name: '', label: $filter('i18n')('common.labels.noneSet') }); scope.milestones = angular.copy(releaseMetadata.milestones); scope.state.dataIsLoading = false; }); } scope.$on(events.REFRESH_RELEASE_PLAN_LIST, function () { refreshList(); }); init(); } }; } ]); })();