745 lines
25 KiB
JavaScript
745 lines
25 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.
|
|
// We should wait for some time to preserve the correct order of execution of functions:
|
|
// page options dropdown items must be copied from template and rendered, before the template get deleted
|
|
// from the page. See initMixForm function in index.cshtml and initSwitchers in _mixCalendar.cshtml
|
|
$timeout(function () {
|
|
if (initMixForm && typeof initMixForm === 'function')
|
|
initMixForm();
|
|
}, 400);
|
|
});
|
|
}
|
|
};
|
|
}])
|
|
.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) {
|
|
$scope.data = {
|
|
Id: null,
|
|
AvailableTeamsAndViews: [],
|
|
AvailableCostCenters: [],
|
|
AvailableProjectRoles: [],
|
|
VisibleProjectRoles: [],
|
|
SelectedTeamsAndViews: [],
|
|
SelectedCostCenters: [],
|
|
SelectedProjectRoles: [],
|
|
DisableScreen: false,
|
|
DisableDelete: false,
|
|
ShowOpen: false,
|
|
SaveMixHasBeenRequested: false,
|
|
ActivateMixHasBeenRequested: false,
|
|
ShowSaveForm: false,
|
|
IsAvgMode: false, // Show totals summs as average values
|
|
DataLoaded: false,
|
|
DataChanged: false,
|
|
CanDoResourceRace: false,
|
|
CanDoTeamRace:false,
|
|
canDoRace: false,
|
|
RaceScore: 0
|
|
};
|
|
$scope.$on('resourceCountChanged', function (event, CanRunResourceRace, canDoRace) {
|
|
|
|
$scope.data.CanDoResourceRace = CanRunResourceRace;
|
|
$scope.data.canDoRace = canDoRace;
|
|
});
|
|
$scope.$on('SuperECCountChanged', function (event, CanDoTeamRace, canDoRace) {
|
|
|
|
$scope.data.CanDoTeamRace = CanDoTeamRace;
|
|
$scope.data.canDoRace = canDoRace;
|
|
});
|
|
|
|
$scope.$on('raceFinished', function (event, RaceScore) {
|
|
|
|
$scope.data.RaceScore = RaceScore;
|
|
var canvasUniquePostfix = Math.uuid();
|
|
var gradient = 'linear-gradient(-135deg, #7030A0 20%, #475FBE 30%, #04ABED 40%, #3CBDAF 70%, #8ED054 80%)';
|
|
if ($('#raceScoreMagnify').find('div.magnifyContainer'))
|
|
$('#raceScoreMagnify').find('div.magnifyContainer').remove();
|
|
$('#raceScoreMagnify').smallerbar(RaceScore || 0, 'race-canvas-' + canvasUniquePostfix, true, gradient,RaceScore);
|
|
$('#raceScoreMagnify').css({ 'display': '-webkit-box' });
|
|
});
|
|
$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) {
|
|
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;
|
|
|
|
if (initData) {
|
|
if (initData.mixId && (initData.mixId.length > 0)) {
|
|
$scope.data.Id = initData.mixId;
|
|
}
|
|
if (initData.showAvgTotals) {
|
|
$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;
|
|
}
|
|
|
|
$scope.$on('dataChanged', function (event, value) {
|
|
setDataChanged(value);
|
|
});
|
|
// Leave teamsAndViewsToSelect = undefined to preserve current filter
|
|
$scope.$on('changeDisplayView', function (event, newStartDateMs, newEndDateMs, teamsAndViewsToSelect, callbackFn) {
|
|
if (!$scope.canApplyFilter())
|
|
return;
|
|
|
|
// Incoming dates are as Text
|
|
setFilterDates(newStartDateMs, newEndDateMs);
|
|
if (teamsAndViewsToSelect && Array.isArray(teamsAndViewsToSelect) && (teamsAndViewsToSelect.length > 0)) {
|
|
setFilterSelectedTeamsAndViews(teamsAndViewsToSelect);
|
|
}
|
|
|
|
$timeout(function () {
|
|
$scope.applyFilter(callbackFn);
|
|
});
|
|
});
|
|
|
|
$scope.filterCostCentersChanged = function () {
|
|
setProjectRolesVisibility();
|
|
|
|
var mixFilter = getMixFilter();
|
|
$rootScope.$broadcast("clientFilterChanged", mixFilter);
|
|
};
|
|
$scope.filterProjectRolesChanged = function () {
|
|
var mixFilter = getMixFilter();
|
|
$rootScope.$broadcast("clientFilterChanged", mixFilter);
|
|
};
|
|
|
|
$scope.saveMixSuccess = function (data) {
|
|
if (data && data.Id) {
|
|
setDataChanged(false);
|
|
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 () {
|
|
$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 () {
|
|
$scope.lockScreen();
|
|
|
|
if (canSaveMix && typeof canSaveMix === 'function' && !canSaveMix()) {
|
|
$scope.unlockScreen();
|
|
return;
|
|
}
|
|
|
|
var filterData = getFilter4Saving();
|
|
$rootScope.$broadcast("saveChanges", filterData, activateMix, undefined, true);
|
|
};
|
|
$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();
|
|
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();
|
|
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,
|
|
CostCenters: mixFilter.CostCenters,
|
|
ProjectRoles: mixFilter.ProjectRoles,
|
|
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);
|
|
};
|
|
$scope.canDoRaceRes = function () {
|
|
if ($scope.canApplyFilter() && $scope.data.IsEditable && $scope.data.DataLoaded && $scope.data.CanDoResourceRace && !$scope.data.DataChanged && $scope.data.canDoRace && $scope.data.SelectedTeamsAndViews.length == 1) {
|
|
return true;
|
|
}
|
|
return false;
|
|
};
|
|
$scope.canDoRaceTeam = function () {
|
|
return $scope.canApplyFilter() && $scope.data.IsEditable && $scope.data.DataLoaded && !$scope.data.DataChanged && $scope.data.CanDoTeamRace && $scope.data.canDoRace && $scope.data.SelectedTeamsAndViews.length == 1;
|
|
};
|
|
$scope.canSaveMix = function () {
|
|
return $scope.canApplyFilter() && $scope.data.IsEditable && $scope.data.DataLoaded;
|
|
};
|
|
$scope.canActivateMix = function () {
|
|
return $scope.canSaveMix();
|
|
};
|
|
$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;
|
|
setDataChanged(false);
|
|
blockUI();
|
|
|
|
var internalCallBackFn = function (data, newChangeFlagValue) {
|
|
if (callbackFn && (typeof callbackFn === 'function')) {
|
|
callbackFn(data, newChangeFlagValue);
|
|
}
|
|
else {
|
|
setMixFilter(data, newChangeFlagValue);
|
|
}
|
|
$scope.data.DataLoaded = true;
|
|
};
|
|
|
|
if (!callbackFn || (! typeof callbackFn !== 'function')) {
|
|
callbackFn = setMixFilter;
|
|
}
|
|
|
|
var mixFilter = getMixFilter();
|
|
$rootScope.$broadcast("filterChanged", mixFilter, $scope.data.AvailableTeamsAndViews, internalCallBackFn);
|
|
|
|
setDataChanged(true);
|
|
};
|
|
|
|
$scope.applyRaceRes = function (callbackFn, teamlevel) {
|
|
if ($.isFunction(isValidHeader) && !isValidHeader())
|
|
return;
|
|
setDataChanged(false);
|
|
blockUI();
|
|
|
|
var mixFilter = getMixFilter();
|
|
var teamLevel = false;
|
|
$rootScope.$broadcast("raceChanged", mixFilter, $scope.data.AvailableTeamsAndViews, teamLevel);
|
|
$scope.data.DataLoaded = true;
|
|
|
|
setDataChanged(true);
|
|
};
|
|
$scope.applyRaceTeam = function (callbackFn, teamlevel) {
|
|
if ($.isFunction(isValidHeader) && !isValidHeader())
|
|
return;
|
|
setDataChanged(false);
|
|
blockUI();
|
|
|
|
var mixFilter = getMixFilter();
|
|
var teamLevel = true;
|
|
$rootScope.$broadcast("raceChanged", mixFilter, $scope.data.AvailableTeamsAndViews, teamLevel);
|
|
$scope.data.DataLoaded = true;
|
|
|
|
setDataChanged(true);
|
|
};
|
|
$scope.applyRace2Team = function (callbackFn) {
|
|
if ($.isFunction(isValidHeader) && !isValidHeader())
|
|
return;
|
|
setDataChanged(false);
|
|
blockUI();
|
|
|
|
var mixFilter = getMixFilter();
|
|
var teamLevel = true;
|
|
$rootScope.$broadcast("race2Changed", mixFilter, $scope.data.AvailableTeamsAndViews, teamLevel);
|
|
$scope.data.DataLoaded = true;
|
|
|
|
setDataChanged(true);
|
|
};
|
|
$scope.applyRace2Res = function (callbackFn) {
|
|
if ($.isFunction(isValidHeader) && !isValidHeader())
|
|
return;
|
|
setDataChanged(false);
|
|
blockUI();
|
|
|
|
var mixFilter = getMixFilter();
|
|
var teamLevel = false;
|
|
$rootScope.$broadcast("race2Changed", mixFilter, $scope.data.AvailableTeamsAndViews, teamLevel);
|
|
$scope.data.DataLoaded = true;
|
|
|
|
setDataChanged(true);
|
|
};
|
|
|
|
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, false);
|
|
unblockUI();
|
|
} catch (e) {
|
|
unblockUI();
|
|
showErrorModal();
|
|
} finally {
|
|
$scope.$broadcast('dataloaded');
|
|
}
|
|
})
|
|
.error(function (data, status, headers, config) {
|
|
unblockUI();
|
|
showErrorModal();
|
|
});
|
|
} catch (e) {
|
|
unblockUI();
|
|
showErrorModal();
|
|
}
|
|
}
|
|
|
|
function loadMixData() {
|
|
$rootScope.$broadcast('loadMix', $scope.data.Id, setMixFilter);
|
|
}
|
|
|
|
$scope.convertTeam = function () {
|
|
$scope.$apply(function () {
|
|
var data = $("#team-container").data("capacityPlanner").getData();
|
|
for (var j = 0; j < data.length; j++) {
|
|
var proj = data[j];
|
|
for (var k = 0; k < proj.Positions.length; k++) {
|
|
proj.Positions[k].StartDate = DateTimeConverter.jsonDateToMs(proj.Positions[k].StartDate);
|
|
proj.Positions[k].EndDate = DateTimeConverter.jsonDateToMs(proj.Positions[k].EndDate);
|
|
}
|
|
data[j] = proj;
|
|
}
|
|
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: data,
|
|
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 startDateMs = DateTimeConverter.stringToMs($scope.data.StartDate);
|
|
var endDateMs = DateTimeConverter.stringToMs($scope.data.EndDate);
|
|
var filter = {
|
|
StartDate: startDateMs,
|
|
EndDate: endDateMs,
|
|
TeamsViews: $scope.data.SelectedTeamsAndViews,
|
|
CostCenters: $scope.data.SelectedCostCenters,
|
|
ProjectRoles: $scope.data.SelectedProjectRoles
|
|
};
|
|
|
|
return filter;
|
|
}
|
|
function setMixFilter(data, setMixChangeFlag) {
|
|
// 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 ? DateTimeConverter.msFormatAsUtcString(data.StartDate) : null;
|
|
$scope.data.EndDate = data.EndDate > 0 ? DateTimeConverter.msFormatAsUtcString(data.EndDate) : 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;
|
|
|
|
// Client-side filters
|
|
$scope.data.AvailableCostCenters = data.Filter.Variants.AvailableCostCenters;
|
|
$scope.data.AvailableProjectRoles = data.Filter.Variants.AvailableProjectRoles;
|
|
}
|
|
|
|
if (data.Filter.Selection) {
|
|
$scope.data.SelectedTeamsAndViews = selectedTeams;
|
|
|
|
// Restore selection for client-side filters
|
|
setFilterCostCenters(data.Filter.Selection.CostCenters);
|
|
setFilterProjectRoles(data.Filter.Selection.ProjectRoles);
|
|
}
|
|
}
|
|
|
|
if (isMixSelected()) {
|
|
$scope.data.DataLoaded = true;
|
|
}
|
|
|
|
$timeout(function () {
|
|
// Reset changes flag. Code must be executed last after loading mix data.
|
|
// Queue its' execution after all watchers
|
|
setDataChanged(setMixChangeFlag);
|
|
});
|
|
}
|
|
function isMixSelected() {
|
|
return !!$scope.data.Id && $scope.data.Id != C_EMPTY_GUID;
|
|
}
|
|
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();
|
|
}
|
|
})
|
|
.error(function (data, status, headers, config) {
|
|
$scope.unlockScreen();
|
|
showErrorModal();
|
|
});
|
|
} catch (e) {
|
|
$scope.unlockScreen();
|
|
showErrorModal();
|
|
}
|
|
}
|
|
function setDataChanged(value) {
|
|
$scope.data.DataChanged = (value === true);
|
|
|
|
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;
|
|
}
|
|
|
|
function setFilterDates(startDateMs, endDateMs) {
|
|
// Dates are as Text
|
|
if (angular.isNumber(startDateMs) && (Number(startDateMs) > 0)) {
|
|
$scope.data.StartDate = DateTimeConverter.msFormatAsUtcString(startDateMs);
|
|
var startDateObj = DateTimeConverter.msToUtcDate(startDateMs);
|
|
$element.find("#MixStartDate").data('datepicker').setDate(startDateObj);
|
|
}
|
|
|
|
if (angular.isNumber(endDateMs) && (Number(endDateMs) > 0)) {
|
|
$scope.data.EndDate = DateTimeConverter.msFormatAsUtcString(endDateMs);
|
|
var endDateObj = DateTimeConverter.msToUtcDate(endDateMs);
|
|
$element.find("#MixEndDate").data('datepicker').setDate(endDateObj);
|
|
}
|
|
}
|
|
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);
|
|
}
|
|
function setFilterCostCenters(costCentersToSelect) {
|
|
$scope.data.SelectedCostCenters = [];
|
|
|
|
if (!$scope.data.AvailableCostCenters || !angular.isArray($scope.data.AvailableCostCenters))
|
|
return;
|
|
|
|
var availableCostCenters = {};
|
|
for (var index = 0; index < $scope.data.AvailableCostCenters.length; index++) {
|
|
availableCostCenters[$scope.data.AvailableCostCenters[index].Value] = true;
|
|
}
|
|
|
|
if (costCentersToSelect && angular.isArray(costCentersToSelect)) {
|
|
for (var index = 0; index < costCentersToSelect.length; index++) {
|
|
var costCenterId = costCentersToSelect[index];
|
|
if (costCenterId in availableCostCenters) {
|
|
$scope.data.SelectedCostCenters.push(costCenterId);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
function setFilterProjectRoles(projectRolesToSelect) {
|
|
$scope.data.SelectedProjectRoles = projectRolesToSelect;
|
|
setProjectRolesVisibility();
|
|
};
|
|
function getSelect2NewSelection(controlSelection, controlOptions, valuePropertyName) {
|
|
var result = null;
|
|
|
|
if (controlSelection && angular.isArray(controlSelection)) {
|
|
var newSelection = [];
|
|
|
|
if (controlOptions && angular.isArray(controlOptions)) {
|
|
var selectedItemsCount = controlSelection.length;
|
|
var optionsCount = controlOptions.length;
|
|
|
|
for (var sIndex = 0; sIndex < selectedItemsCount; sIndex++) {
|
|
var itemToCheck = controlSelection[sIndex];
|
|
var found = false;
|
|
|
|
for (var pIndex = 0; pIndex < optionsCount; pIndex++) {
|
|
if (controlOptions[pIndex][valuePropertyName] == itemToCheck) {
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (found) {
|
|
newSelection.push(itemToCheck);
|
|
}
|
|
}
|
|
}
|
|
|
|
result = newSelection;
|
|
}
|
|
|
|
return result;
|
|
};
|
|
function setProjectRolesVisibility() {
|
|
if (!$scope.data.AvailableProjectRoles || !angular.isArray($scope.data.AvailableProjectRoles))
|
|
// No project roles available for selection
|
|
return;
|
|
|
|
// Fill control with related to selected cost centers options
|
|
var expCatsCount = $scope.data.AvailableProjectRoles.length;
|
|
var anyCostCenterSelected = $scope.data.SelectedCostCenters && angular.isArray($scope.data.SelectedCostCenters) && ($scope.data.SelectedCostCenters.length > 0);
|
|
$scope.data.VisibleProjectRoles = [];
|
|
|
|
for (var eIndex = 0; eIndex < expCatsCount; eIndex++) {
|
|
var expCat = $scope.data.AvailableProjectRoles[eIndex];
|
|
|
|
if (expCat && expCat.Value && expCat.CostCenterId) {
|
|
if (!anyCostCenterSelected || ($scope.data.SelectedCostCenters.indexOf(expCat.CostCenterId) >= 0)) {
|
|
$scope.data.VisibleProjectRoles.push(expCat);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Fix current control selection
|
|
var newSelectedExpCats = getSelect2NewSelection($scope.data.SelectedProjectRoles, $scope.data.VisibleProjectRoles, 'Value');
|
|
$scope.data.SelectedProjectRoles = newSelectedExpCats;
|
|
}
|
|
}]); |