EnVisageOnline/Main-RMO/Source/EnVisage/Scripts/Angular/Controllers/MixControllers/mixHeaderController.js

551 lines
17 KiB
JavaScript

'use strict';
app
// form initialization needs to be called after data was loaded and angular updated all inputs with the new values
.directive('initForm', ['$timeout', function ($timeout) {
return {
link: function ($scope, elem, attrs, ctrl) {
$scope.$on('dataloaded', function () {
// need to queue form initialization after DOM rendering (even with timeout=0 action will be placed in the queue of browser actions)
$timeout(function () {
if (initMixForm && typeof initMixForm === 'function')
initMixForm();
});
});
}
};
}]).
directive('selectedDataChanged', ['$timeout', function ($timeout) {
return {
link: function ($scope, element, attrs) {
$scope.$on('selectedTeamsViewsChanged', function () {
$timeout(function () { // You might need this timeout to be sure its run after DOM render.
element.trigger("change");
}, 0, false);
})
}
};
}])
.controller('mixHeaderController', ['$scope', '$rootScope', '$http', '$filter', '$timeout', '$element', function ($scope, $rootScope, $http, $filter, $timeout, $element) {
var commonErrorMessage = 'An error occurred while processing your request. Please, try again later.',
emptyGuid = '00000000-0000-0000-0000-000000000000';
$scope.data = {
Id: null,
AvailableTeamsAndViews: [],
SelectedTeamsAndViews: [],
DisableScreen: false, // SA. ENV-1067
DisableDelete: false,
ShowOpen: false,
SaveMixHasBeenRequested: false,
ActivateMixHasBeenRequested: false,
ShowSaveForm: false,
IsAvgMode: false, // SA. ENV-1030. Show totals summs as average values
DataLoaded: false, // SA. ENV-1067
DataChanged: false // SA. ENV-1153
};
$scope.$watch('data.SelectedMix', function (newValue, oldValue) {
if (oldValue != newValue) {
$scope.data.ShowOpen = !!newValue && newValue != $scope.data.Id;
}
});
$scope.$watch('data.Users', function (newValue, oldValue) { // SA. ENV-1153
if ((oldValue != newValue) && ($scope.canClearMix())) {
setDataChanged(true);
}
});
$scope.groupTeamsFn = function (item) {
return item.Group.Name;
};
$scope.init = function (initData) {
$scope.data.Id = null;
$scope.data.DataChanged = false; // SA. ENV-1153
if (initData) {
if (initData.mixId && (initData.mixId.length > 0)) {
$scope.data.Id = initData.mixId;
}
if (initData.showAvgTotals) { // SA. ENV-1030. Totals summs as average
$scope.data.IsAvgMode = initData.showAvgTotals;
}
}
if (!isMixSelected()) {
initPageFilter();
}
else {
jQuery(document).ready(function () { loadMixData(); });
}
};
$scope.lockScreen = function () {
$scope.data.DisableScreen = true;
if (!isUIBlocked()) {
blockUI();
}
}
$scope.unlockScreen = function () {
unblockUI();
$scope.data.DisableScreen = false;
}
// SA. ENV-1153
$scope.$on('dataChanged', function (event, value) {
setDataChanged(value);
});
// SA. ENV-1159. Leave teamsAndViewsToSelect = undefined to preserver current filter
$scope.$on('changeDisplayView', function (event, newStartDate, newEndDate, teamsAndViewsToSelect, callbackFn) {
if (!$scope.canApplyFilter())
return;
// Incoming dates are as Text
setFilterDates(newStartDate, newEndDate);
// SA. ENV-1254
if (teamsAndViewsToSelect && Array.isArray(teamsAndViewsToSelect) && (teamsAndViewsToSelect.length > 0)) {
setFilterSelectedTeamsAndViews(teamsAndViewsToSelect);
}
$timeout(function () {
$scope.applyFilter(callbackFn);
});
});
$scope.saveMixSuccess = function (data) {
if (data && data.Id) {
setDataChanged(false); // SA. ENV-1153
goToMix(data.Id);
}
else {
// Some unknown problems with mix saving
showErrorModal('Oops!', 'Unexpected error happend during saving of the Mix. Contact your ' +
'system administrators for details');
$scope.unlockScreen();
}
}
$scope.saveMixFailed = function (errorMessage) {
showErrorModal('Oops!', errorMessage);
$scope.unlockScreen();
}
$scope.saveChanges = function () {
// SA. ENV-1067
$scope.lockScreen();
if (canSaveMix && typeof canSaveMix === 'function' && !canSaveMix()) {
$scope.unlockScreen();
return;
}
var filterData = getFilter4Saving();
$rootScope.$broadcast("saveChanges", filterData, $scope.saveMixSuccess, $scope.saveMixFailed);
};
$scope.activateMix = function () {
// SA. ENV-1067
$scope.lockScreen();
if (canSaveMix && typeof canSaveMix === 'function' && !canSaveMix()) {
$scope.unlockScreen();
return;
}
var filterData = getFilter4Saving();
$rootScope.$broadcast("saveChanges", filterData, activateMix);
};
// SA. ENV-1138
$scope.deleteUnopenedMix = function () {
if (!$scope.data.SelectedMix || ($scope.data.SelectedMix.length < 1))
return;
$scope.data.DisableDelete = true;
var mixId = $scope.data.SelectedMix;
try {
bootbox.confirm("Are you sure you want to delete this mix? This action cannot be undone.",
function (result) {
$scope.$apply(function () {
if (result) {
$rootScope.$broadcast("deleteMix", mixId, onUnopenedMixDeleted, onUnopenedMixDeleteFailed);
} else {
// bootbox is not angular directive so we have to tell angular that scope has been updated
$scope.data.DisableDelete = false;
}
});
});
} catch (e) {
$scope.data.DisableDelete = false;
showErrorModal('Oops!', commonErrorMessage);
unblockUI();
}
};
function onUnopenedMixDeleted() {
var mixId = $scope.data.SelectedMix;
// Remove mix from the AvailableMixes collection
for (var index = $scope.data.AvailableMixes.length - 1; index >= 0; index--) {
if ($scope.data.AvailableMixes[index].Value == mixId) {
$scope.data.AvailableMixes.splice(index, 1);
break;
}
}
$scope.data.DisableDelete = false;
$scope.data.SelectedMix = undefined;
// SA. We need to reset selected Mix. To reset select2 value we should find it in the DOM tree and set
// it's value using jQuery. Angular does all the work, but it can't reset displayed selection in select2,
// because select2 is a JS-control. So it can't be fully managed with the angular digest model
$element.find("*[ng-model='data.SelectedMix']").select2("val", "");
};
function onUnopenedMixDeleteFailed() {
$scope.data.DisableDelete = false;
};
$scope.deleteCurrentMix = function () {
$scope.data.DisableDelete = true;
try {
bootbox.confirm("Are you sure you want to delete this mix? This action cannot be undone.", function (result) {
$scope.$apply(function () {
if (result) {
setDataChanged(false);
$rootScope.$broadcast("deleteMix", $scope.data.Id, goToMix, onDeleteMixFailure);
} else {
// bootbox is not angular directive so we have to tell angular that scope has been updated
$scope.data.DisableDelete = false;
}
});
});
} catch (e) {
$scope.data.DisableDelete = false;
showErrorModal('Oops!', commonErrorMessage);
unblockUI();
}
};
function onDeleteMixFailure() {
$scope.data.DisableDelete = false;
}
function getFilter4Saving() {
var mixFilter = getMixFilter();
return {
Id: $scope.data.Id,
Name: $scope.data.Name,
StartDate: mixFilter.StartDate,
EndDate: mixFilter.EndDate,
Users: $scope.data.Users,
Filter: {
Selection: {
TeamsViews: mixFilter.TeamsViews,
AvailableTeams: mixFilter.AvailableTeams,
StartDate: mixFilter.StartDate,
EndDate: mixFilter.EndDate
},
Variants: {
AvailableTeamsAndViews: $scope.data.AvailableTeamsAndViews
}
}
};
};
$scope.navigateToMix = function () {
if (!$scope.data.SelectedMix)
return;
goToMix($scope.data.SelectedMix);
};
$scope.navigateToNewMix = function () {
goToMix();
};
$scope.canApplyFilter = function () {
return (($scope.data.SelectedTeamsAndViews || []).length > 0 &&
($scope.data.StartDate || null) != null &&
($scope.data.EndDate || null) != null);
};
// SA. ENV-1067
$scope.canSaveMix = function () {
return $scope.canApplyFilter() && $scope.data.IsEditable && $scope.data.DataLoaded;
};
// SA. ENV-1067
$scope.canActivateMix = function () {
return $scope.canSaveMix();
};
// SA. ENV-1143
$scope.canDeleteMix = function () {
return $scope.data.IsEditable && $scope.data.DataLoaded && isMixSelected();
};
$scope.canClearMix = function () {
return $scope.data.DataLoaded;
};
$scope.applyFilter = function (callbackFn) {
if ($.isFunction(isValidHeader) && !isValidHeader())
return;
blockUI();
var mixFilter = getMixFilter();
$rootScope.$broadcast("filterChanged", mixFilter, $scope.data.AvailableTeamsAndViews, callbackFn);
$scope.data.DataLoaded = true; // SA. ENV-1067
setDataChanged(true); // SA. ENV-1153
};
function goToMix(mixId) {
if (!mixId)
window.location.href = '/Mix';
else
window.location.href = '/Mix?id=' + mixId;
}
function initPageFilter() {
blockUI();
var request = getAntiXSRFRequest('/Mix/GetPageFilter', {});
try {
$http(request)
.success(function (data, status, headers, config) {
try {
if (!data) {
unblockUI();
return;
}
setMixFilter(data);
unblockUI();
} catch (e) {
unblockUI();
showErrorModal('Oops!', commonErrorMessage);
} finally {
$scope.$broadcast('dataloaded');
}
})
.error(function (data, status, headers, config) {
unblockUI();
showErrorModal('Oops!', commonErrorMessage);
});
} catch (e) {
unblockUI();
showErrorModal('Oops!', commonErrorMessage);
}
}
function loadMixData() {
$rootScope.$broadcast('loadMix', $scope.data.Id, setMixFilter);
}
$scope.convertTeam = function () {
$scope.$apply(function () {
var newTeam = {
Id: $('form#editTeamForm #Id').val(),
TVName: $('form#editTeamForm #Name').val(),
CompanyId: $('form#editTeamForm #CompanyId').val(),
CostCenterId: $('form#editTeamForm #CostCenterId').val(),
ReportToId: $('form#editTeamForm #ReportToId').val(),
UserId: $('form#editTeamForm #UserId').select2('val'),
CapacityTeamId: $('form#editTeamForm #CapacityTeamId').val(),
CopyPlanned: $('form#editTeamForm #CopyPlanned').val(),
IsNew: true,
Data: $("#team-container").data("capacityPlanner").getData(),
Group: {
Disabled: false,
Name: 'Teams'
}
};
for (var i = 0; i < $scope.data.AvailableTeamsAndViews.length; i++) {
if ($scope.data.AvailableTeamsAndViews[i].Id == newTeam.Id)
return;
}
$scope.data.AvailableTeamsAndViews.push(newTeam);
$scope.data.SelectedTeamsAndViews.push(newTeam);
if ($scope.canApplyFilter())
$scope.applyFilter();
});
$scope.$broadcast('selectedTeamsViewsChanged');
};
$scope.requestMixSaving = function () {
$scope.data.ShowSaveForm = true;
$scope.data.SaveMixHasBeenRequested = true;
$scope.data.ActivateMixHasBeenRequested = false;
};
$scope.requestMixActivation = function () {
$scope.data.ShowSaveForm = !isMixSelected();
$scope.data.SaveMixHasBeenRequested = false;
$scope.data.ActivateMixHasBeenRequested = true;
};
function getMixFilter() {
var startDate = new Date($scope.data.StartDate);
var endDate = new Date($scope.data.EndDate);
var filter = {
StartDate: Date.UTC(startDate.getFullYear(), startDate.getMonth(), startDate.getDate()),
EndDate: Date.UTC(endDate.getFullYear(), endDate.getMonth(), endDate.getDate()),
TeamsViews: []
};
filter.TeamsViews = $scope.data.SelectedTeamsAndViews;
return filter;
}
function setMixFilter(data) {
// prefill dropdown with team and view values
var selectedTeams = [];
$.each(data.Filter.Selection.TeamsViews || [], function (index, team) {
var teamId = team.Id;
var found = false;
for (var i = 0; i < data.Filter.Variants.AvailableTeamsAndViews.length; i++) {
if (data.Filter.Variants.AvailableTeamsAndViews[i].Id == teamId) {
selectedTeams.push(data.Filter.Variants.AvailableTeamsAndViews[i]);
found = true;
break;
}
}
if (!found && team.IsNew) {
data.Filter.Variants.AvailableTeamsAndViews.push(team);
selectedTeams.push(team);
}
});
$scope.data.Id = data.Id;
$scope.data.Name = data.Name;
$scope.data.StartDate = data.StartDate > 0 ? $filter('date')(data.StartDate, 'MM/dd/yyyy') : null;
$scope.data.EndDate = data.EndDate > 0 ? $filter('date')(data.EndDate, 'MM/dd/yyyy') : null;
$scope.data.Users = data.Users;
$scope.data.SelectedMix = data.Id;
if (data.Filter) {
if (data.Filter.Variants) {
$scope.data.AvailableTeamsAndViews = data.Filter.Variants.AvailableTeamsAndViews;
$scope.data.AvailableUsers = data.Filter.Variants.AvailableUsers;
$scope.data.AvailableMixes = data.Filter.Variants.AvailableMixes;
$scope.data.IsEditable = data.Filter.Variants.IsEditable;
}
if (data.Filter.Selection) {
$scope.data.SelectedTeamsAndViews = selectedTeams;
}
}
var mixSelected = isMixSelected();
$scope.data.DataLoaded = mixSelected; // SA. ENV-1067
$timeout(function () {
// SA. ENV-1153. Reset changes flag. Code must be executed last after loading mix data.
// Queue its' execution after all watchers
setDataChanged(false);
});
}
function isMixSelected() {
return !!$scope.data.Id && $scope.data.Id != emptyGuid;
}
function activateMix(data) {
$scope.lockScreen();
if (!data || !data.Id) {
$scope.unlockScreen();
return;
}
var mixId = data.Id;
var request = getAntiXSRFRequest('/Mix/ActivateMix', mixId);
try {
$http(request)
.success(function (data, status, headers, config) {
try {
$scope.unlockScreen();
bootbox.alert('Mix have been activated successfully', function () {
setDataChanged(false);
goToMix(mixId);
});
} catch (e) {
$scope.unlockScreen();
showErrorModal('Oops!', commonErrorMessage);
}
})
.error(function (data, status, headers, config) {
$scope.unlockScreen();
showErrorModal('Oops!', commonErrorMessage);
});
} catch (e) {
$scope.unlockScreen();
showErrorModal('Oops!', commonErrorMessage);
}
}
// SA. ENV-1153
function setDataChanged(value) {
$scope.data.DataChanged = value;
if (value) {
addPageLeaveHandler();
}
else {
removePageLeaveHandler();
}
}
function addPageLeaveHandler() {
window.onbeforeunload = function (e) {
var message = "Mix contains unsaved changes. Are you sure you want to leave the page?",
e = e || window.event;
// For IE and Firefox
if (e) {
e.returnValue = message;
}
// For Safari
return message;
};
}
function removePageLeaveHandler() {
window.onbeforeunload = null;
}
// SA. ENV-1159
function setFilterDates(startDate, endDate) {
// Dates are as Text
if (startDate && (startDate.length > 0)) {
$scope.data.StartDate = startDate;
var startDateObj = new Date(startDate);
$element.find("#MixStartDate").data('datepicker').setDate(startDateObj);
}
if (endDate && (endDate.length > 0)) {
$scope.data.EndDate = endDate;
var endDateObj = new Date(endDate);
$element.find("#MixEndDate").data('datepicker').setDate(endDateObj);
}
}
// SA. ENV-1254
function setFilterSelectedTeamsAndViews(teamsAndViews) {
if (!teamsAndViews || !Array.isArray(teamsAndViews) || (teamsAndViews.length < 1))
return;
var visualSelection = [];
var selectedTeams = $.grep($scope.data.AvailableTeamsAndViews, function (teamViewItem, index) {
var found = teamsAndViews.indexOf(teamViewItem.Id) >= 0;
if (found) {
var sortedIndex = $("select#selectedTeamViews").find("option:contains('" + teamViewItem.TVName + "')").val();
if (sortedIndex !== undefined)
visualSelection.push(sortedIndex);
}
return found;
});
$scope.data.SelectedTeamsAndViews = selectedTeams;
$('#selectedTeamViews').select2('val', visualSelection);
}
}]);