1137 lines
66 KiB
Plaintext
1137 lines
66 KiB
Plaintext
@using EnVisage.Code;
|
|
@model string
|
|
|
|
<style type="text/css">
|
|
.validation-error {
|
|
color: red;
|
|
}
|
|
|
|
#mix-table thead {
|
|
border-collapse: separate;
|
|
border-spacing: 0;
|
|
}
|
|
|
|
#mix-table thead tr th {
|
|
-moz-background-clip: padding-box;
|
|
-webkit-background-clip: padding-box;
|
|
background-clip: padding-box;
|
|
border-top: 1.1px solid;
|
|
border-right: 1.1px solid;
|
|
}
|
|
|
|
.not-active {
|
|
pointer-events: none;
|
|
cursor: default;
|
|
}
|
|
</style>
|
|
<script type="text/javascript">
|
|
|
|
var _csDataChanged = false;
|
|
function onCSDataChanged() {
|
|
_csDataChanged = true;
|
|
}
|
|
function resetCSDataChanged() {
|
|
_csDataChanged = false;
|
|
}
|
|
function isCSDataChanged() {
|
|
return _csDataChanged;
|
|
}
|
|
var _addExpCatsDataChanged = false;
|
|
function onAddExpCatsDataChanged() {
|
|
_addExpCatsDataChanged = true;
|
|
}
|
|
function resetAddExpCatsDataChanged() {
|
|
_addExpCatsDataChanged = false;
|
|
}
|
|
function isAddExpCatsDataChanged() {
|
|
return _addExpCatsDataChanged;
|
|
}
|
|
var _importScenarioDataChanged = false;
|
|
function onImportScenarioDataChanged() {
|
|
_importScenarioDataChanged = true;
|
|
}
|
|
function resetImportScenarioDataChanged() {
|
|
_importScenarioDataChanged = false;
|
|
}
|
|
function isImportScenarioDataChanged() {
|
|
return _importScenarioDataChanged;
|
|
}
|
|
var _finInfoDataChanged = false;
|
|
function onFinInfoDataChanged() {
|
|
_finInfoDataChanged = true;
|
|
}
|
|
function resetFinInfoDataChanged() {
|
|
_finInfoDataChanged = false;
|
|
}
|
|
function isFinInfoDataChanged() {
|
|
return _finInfoDataChanged;
|
|
}
|
|
|
|
|
|
function initSwitchers() {
|
|
var container = $('#mix-project-container');
|
|
container.find('#groupCapacityByTeam').switcher({
|
|
on_state_content: 'Team',
|
|
off_state_content: 'Total'
|
|
}).parent().css("width", "100px");
|
|
|
|
container.find('#monthWeekMode').switcher({
|
|
on_state_content: 'Month',
|
|
off_state_content: 'Week'
|
|
}).parent().css("width", "80px");
|
|
|
|
container.find('#uomMode').switcher({
|
|
on_state_content: '# Hours',
|
|
off_state_content: '# Resources'
|
|
}).parent().css("width", "100px");
|
|
|
|
container.find('#capacityView').switcher({
|
|
on_state_content: 'Actual',
|
|
off_state_content: 'Planned'
|
|
}).parent().css("width", "93px");
|
|
|
|
container.find('#unassignedAllocations').switcher({
|
|
on_state_content: 'Auto',
|
|
off_state_content: 'Manual'
|
|
}).parent().css("width", "100px");
|
|
|
|
container.find('#chShowResources').switcher({
|
|
on_state_content: 'On',
|
|
off_state_content: 'Off'
|
|
}).parent().css("width", "80px");
|
|
|
|
$('#importScenarioIsActive').switcher({
|
|
on_state_content: 'Yes',
|
|
off_state_content: 'No'
|
|
}).parent().css("width", "80px");
|
|
|
|
$('#copyScenario').find('input[type=number],select,input[type=radio]').on("change", function () {
|
|
if (typeof onCSDataChanged === 'function')
|
|
onCSDataChanged();
|
|
});
|
|
$('#mix-edit-scenario-teams-dialog').find('select').on("change", function () {
|
|
if (typeof onAddExpCatsDataChanged === 'function')
|
|
onAddExpCatsDataChanged();
|
|
});
|
|
$('#mix-import-scenario-to-project-dialog').find('input[type=text],input[type=checkbox]').on("change", function () {
|
|
if ($.isFunction(onImportScenarioDataChanged))
|
|
onImportScenarioDataChanged();
|
|
});
|
|
$(document).on('hide.bs.modal', '#copyScenario', function (e) {
|
|
if ($(e.target).attr('id') != 'copyScenario') {
|
|
$("#push_pull").focus();
|
|
return true; // close modal form
|
|
}
|
|
if (typeof isCSDataChanged === 'function')
|
|
if (isCSDataChanged()) {
|
|
var msg = "@Resources.Messages.Scenario_Copy_UnsavedChanges";
|
|
bootbox.confirm(msg, function (result) {
|
|
if (result) {
|
|
if (typeof resetCSDataChanged === 'function') {
|
|
resetCSDataChanged();
|
|
}
|
|
$('#copyScenario').modal('hide');
|
|
}
|
|
});
|
|
|
|
$("#copyScenario").focus();
|
|
return false; // DO NOT close modal form
|
|
}
|
|
$("#copyScenario").focus();
|
|
return true; // close modal form
|
|
}).on('shown.bs.modal', '#copyScenario', function (e) {
|
|
if ($(e.target).attr('id') == 'copyScenario') {
|
|
if (typeof resetCSDataChanged === 'function')
|
|
resetCSDataChanged();
|
|
}
|
|
});
|
|
}
|
|
|
|
function saveMixPreferences() {
|
|
|
|
var preferences = collectPreferences('mixCalendar');
|
|
var section = getDataSection($('#mix-project-container'));
|
|
var url = generalizeUrl('@(Url.Action("Index", "Mix"))');
|
|
|
|
saveUserPagePreferences(preferences, section, url);
|
|
}
|
|
|
|
init.push(function () {
|
|
initSwitchers();
|
|
$(document).on('rmo.open-scenario-details-window', function (e, data) {
|
|
openMixScenarioDetailsEditDialog(data);
|
|
});
|
|
$(document).on('rmo.close-scenario-details-window', function (e) {
|
|
closeMixScenarioDetailsEditDialog();
|
|
});
|
|
$(document).on('rmo.open-scenario-teams-window', function (e) {
|
|
$('#mix-edit-scenario-teams-dialog').modal('show');
|
|
});
|
|
$(document).on('rmo.close-scenario-teams-window', function (e) {
|
|
$('#mix-edit-scenario-teams-dialog').modal('hide');
|
|
});
|
|
$(document).on('rmo.open-import-scenario-window', function (e) {
|
|
// we should set class manual because angular model property always true when window is showing, but switcher may has off state
|
|
$('#importScenarioIsActive').parent('.switcher').addClass('checked');
|
|
|
|
// clear validation errors from the last call
|
|
|
|
// clear validation messages
|
|
$('span.field-validation-error').removeClass('field-validation-error')
|
|
.addClass('field-validation-valid')
|
|
.html('');
|
|
|
|
// clear no valid inputs
|
|
$('input.input-validation-error').removeClass('input-validation-error');
|
|
|
|
$('#mix-import-scenario-to-project-dialog').modal('show');
|
|
});
|
|
$(document).on('rmo.close-import-scenario-window', function (e) {
|
|
// we should reset changes because this event fires only after user clicked save button
|
|
if ($.isFunction(resetImportScenarioDataChanged))
|
|
resetImportScenarioDataChanged();
|
|
|
|
$('#mix-import-scenario-to-project-dialog').modal('hide');
|
|
});
|
|
$(document).on('rmo.open-scenario-fininfo-window', function (e, data) {
|
|
openMixScenarioFinInfoEditDialog(data);
|
|
});
|
|
$(document).on('rmo.close-scenario-fininfo-window', function (e) {
|
|
closeMixScenarioFinInfoEditDialog();
|
|
});
|
|
$(document).on('hide.bs.modal', '#mix-edit-scenario-details-dialog', function (e) {
|
|
// skip modal hide event from datepickers
|
|
if ($(e.target).attr('id') != 'mix-edit-scenario-details-dialog')
|
|
return true; // close modal form
|
|
|
|
$('#mix-edit-scenario-details-dialog-content').html('');
|
|
});
|
|
$(document).on('shown.bs.modal', '#mix-edit-scenario-details-dialog', function (e) {
|
|
if (typeof (initScenarioDetails) === 'function')
|
|
initScenarioDetails();
|
|
});
|
|
$(document).on('hide.bs.modal', '#mix-edit-scenario-teams-dialog', function (e) {
|
|
// skip modal hide event from datepickers
|
|
if ($(e.target).attr('id') != 'mix-edit-scenario-teams-dialog')
|
|
return true; // close modal form
|
|
if (typeof isAddExpCatsDataChanged === 'function')
|
|
if (isAddExpCatsDataChanged()) {
|
|
var msg = "Add Team/Expenditure form contains unsaved changes, do you really want to close the form?";
|
|
bootbox.confirm(msg, function (result) {
|
|
if (result) {
|
|
if (typeof resetAddExpCatsDataChanged === 'function') {
|
|
resetAddExpCatsDataChanged();
|
|
$('#mix-edit-scenario-teams-dialog select').select2('val', '');
|
|
}
|
|
$('#mix-edit-scenario-teams-dialog').modal('hide');
|
|
}
|
|
});
|
|
|
|
return false; // DO NOT close modal form
|
|
}
|
|
$('#mix-edit-scenario-teams-dialog select').select2('val', '');
|
|
return true;
|
|
}).on('show.bs.modal', '#mix-edit-scenario-teams-dialog', function (e) {
|
|
$('#mix-edit-scenario-teams-dialog select').select2('val', '');
|
|
if (typeof resetAddExpCatsDataChanged === 'function') {
|
|
resetAddExpCatsDataChanged();
|
|
}
|
|
});
|
|
$(document).on('hide.bs.modal', '#mix-import-scenario-to-project-dialog', function (e) {
|
|
// skip modal hide event from datepickers
|
|
if ($(e.target).attr('id') != 'mix-import-scenario-to-project-dialog')
|
|
return true; // close modal form
|
|
|
|
if ($.isFunction(isImportScenarioDataChanged))
|
|
if (isImportScenarioDataChanged()) {
|
|
bootbox.confirm("Import Scenario to Project form contains unsaved changes, do you really want to close the form?", function (result) {
|
|
if (result) {
|
|
if (typeof resetImportScenarioDataChanged === 'function') {
|
|
resetImportScenarioDataChanged();
|
|
}
|
|
$('#mix-import-scenario-to-project-dialog').modal('hide');
|
|
}
|
|
});
|
|
|
|
return false; // DO NOT close modal form
|
|
}
|
|
return true;
|
|
}).on('show.bs.modal', '#mix-import-scenario-to-project-dialog', function (e) {
|
|
if ($.isFunction(resetImportScenarioDataChanged)) {
|
|
resetImportScenarioDataChanged();
|
|
}
|
|
});
|
|
$(document).on('hide.bs.modal', '#mix-edit-scenario-fininfo-dialog', function (e) {
|
|
// skip modal hide event from datepickers
|
|
if ($(e.target).attr('id') != 'mix-edit-scenario-fininfo-dialog')
|
|
return true; // close modal form
|
|
|
|
if ($(e.target).data('action') === 'save') {
|
|
resetFinInfoDataChanged();
|
|
$('#mix-edit-scenario-fininfo-dialog').removeData('action');
|
|
$('#mix-edit-scenario-fininfo-dialog-content').html('');
|
|
return true;
|
|
}
|
|
|
|
if (isFinInfoDataChanged()) {
|
|
|
|
var msg = "Edit Financials form contains unsaved changes, do you really want to close the form?";
|
|
bootbox.confirm(msg, function (result) {
|
|
if (result) {
|
|
if (typeof resetFinInfoDataChanged === 'function') {
|
|
resetFinInfoDataChanged();
|
|
$('#mix-edit-scenario-fininfo-dialog-content').html('');
|
|
}
|
|
$('#mix-edit-scenario-fininfo-dialog').modal('hide');
|
|
}
|
|
});
|
|
|
|
return false; // DO NOT close modal form
|
|
}
|
|
$('#mix-edit-scenario-fininfo-dialog-content').html('');
|
|
return true;
|
|
}).on('show.bs.modal', '#mix-edit-scenario-fininfo-dialog', function (e) {
|
|
$('#mix-edit-scenario-fininfo-dialog').find('input[type=checkbox],input[type=text],select,textarea').on("change", function () {
|
|
onFinInfoDataChanged();
|
|
});
|
|
}).on('shown.bs.modal', '#mix-edit-scenario-fininfo-dialog', function (e) {
|
|
if ($.isFunction(initScenarioDetails))
|
|
initScenarioDetails();
|
|
|
|
if ($.isFunction(initScenarioFinInfoModel))
|
|
initScenarioFinInfoModel();
|
|
});
|
|
$(document).on('hide.bs.modal', '#create-scenario-dialog', function (e) {
|
|
// skip modal hide event from datepickers
|
|
if ($(e.target).attr('id') != 'create-scenario-dialog')
|
|
return true; // close modal form
|
|
|
|
if ($(e.target).data('action') === 'save') {
|
|
$('#create-scenario-dialog-content').html('');
|
|
return true;
|
|
}
|
|
|
|
// check that form has been changed
|
|
if (typeof isScenarioDataChanged === 'function')
|
|
// if form has been changed
|
|
if (isScenarioDataChanged()) {
|
|
// ask user for confirmation of form close
|
|
bootbox.confirm("@Resources.Messages.Scenario_Create_Confirm", function (result) {
|
|
if (result) {
|
|
if (typeof resetScenarioDataChanged === 'function') {
|
|
resetScenarioDataChanged();
|
|
$('#create-scenario-dialog-content').html('');
|
|
}
|
|
$('#create-scenario-dialog').modal('hide');
|
|
}
|
|
});
|
|
|
|
|
|
return false; // DO NOT close modal form
|
|
}
|
|
$('#create-scenario-dialog-content').html('');
|
|
return true; // close modal form
|
|
});
|
|
|
|
$(window).scroll(function () {
|
|
$('#mix-table [dropdown-menu]').removeClass('open');
|
|
hideRedundantPopovers($('#mix-table'), null);
|
|
});
|
|
|
|
$('.table-striped').scroll(function () {
|
|
$('#mix-table [dropdown-menu]').removeClass('open');
|
|
hideRedundantPopovers($('#mix-table'), null);
|
|
});
|
|
$(document).click(function (event) {
|
|
$('#mix-table [dropdown-menu]').removeClass('open');
|
|
if (!$(event.target).is('[data-toggled="popover"]'))
|
|
hideRedundantPopovers($('#mix-table'), null);
|
|
});
|
|
|
|
$(".dropdown-menu-scroll-auto").mousedown(function () {
|
|
dropDownInsideClick();
|
|
});
|
|
|
|
$('#reassignExpenditureDialog').find('select').select2({
|
|
});
|
|
|
|
$(document).on('shown.bs.modal', '#projectsUpdateFromLiveDialog', function (e) {
|
|
$('#projectsUpdateFromLiveDialog').find('select').select2({
|
|
minimumResultsForSearch: -1
|
|
});
|
|
});
|
|
});
|
|
|
|
var _createScenarioModel = null;
|
|
function showCreateScenarioDialog(model) {
|
|
if (!model)
|
|
return;
|
|
|
|
_createScenarioModel = model;
|
|
$('#create-scenario-dialog-content').load('@Url.Action("LoadScenario", "Scenarios")?Id=' + _createScenarioModel.ProjectId + '&startDate=' + _createScenarioModel.StartDate + '&endDate=' + _createScenarioModel.EndDate + '&teamId=' + _createScenarioModel.TargetTeam.Id + '&teamName=' + escape(_createScenarioModel.TargetTeam.Name) + '&hideName=' + escape(_createScenarioModel.HideName) +
|
|
'&saveCallback=createScenario&canSaveDraft=false&statusIsEditable=false',
|
|
function (responseText, textStatus, xhr) {
|
|
if (xhr.status == 200) {
|
|
initScenario(createScenario);
|
|
$('#create-scenario-dialog').removeData('action');
|
|
$('#create-scenario-dialog').modal('show');
|
|
} else {
|
|
showErrorModal('Oops!', 'An error occurred while processing your request. Please, try again later.');
|
|
}
|
|
});
|
|
}
|
|
|
|
function openMixScenarioDetailsEditDialog(content) {
|
|
$('#mix-edit-scenario-details-dialog-content').html(content.html);
|
|
$('#mix-edit-scenario-details-dialog').modal('show');
|
|
}
|
|
|
|
function closeMixScenarioDetailsEditDialog() {
|
|
$('#mix-edit-scenario-details-dialog').modal('hide');
|
|
}
|
|
|
|
function openMixScenarioFinInfoEditDialog(content) {
|
|
$('#mix-edit-scenario-fininfo-dialog-content').html(content.html);
|
|
// it is workaround
|
|
registerDocumentEvents4InfoModel();
|
|
$('#mix-edit-scenario-fininfo-dialog').modal('show');
|
|
}
|
|
|
|
function closeMixScenarioFinInfoEditDialog() {
|
|
$('#mix-edit-scenario-fininfo-dialog').modal('hide');
|
|
}
|
|
|
|
function createScenario(scenario) {
|
|
if (!_createScenarioModel)
|
|
return;
|
|
|
|
$('#mix-project-container').scope().createScenario(scenario, _createScenarioModel);
|
|
$('#create-scenario-dialog').data('action', 'save');
|
|
$('#create-scenario-dialog').modal('hide');
|
|
}
|
|
|
|
// SA. ENV-1254
|
|
function showExpCatReassignDialog(initialRadioValue) {
|
|
$("#reassignExpenditureDialog").find("select").select2('val', '');
|
|
var initialRadioControl = $("#reassignExpenditureDialog").find("input[type='radio'][value='" + initialRadioValue + "']");
|
|
$(initialRadioControl).prop('checked', true);
|
|
reassignExpenditureRadioChanged(initialRadioControl);
|
|
$('#reassignExpenditureDialog').modal('show');
|
|
}
|
|
|
|
function reassignExpenditureRadioChanged(sender) {
|
|
reassignDisableSelects();
|
|
var foundselects = $(sender).parents("div.form-group").find("select");
|
|
|
|
if (foundselects.length > 0)
|
|
$.each(foundselects, function (index, item) {
|
|
$(item).data().select2._enabled = true;
|
|
});
|
|
|
|
$(sender).parents("div.form-group").find("input[type='checkbox']").prop('disabled', false);
|
|
}
|
|
|
|
function reassignDisableSelects() {
|
|
var selects = $("#reassignExpenditureDialog").find("select");
|
|
$.each(selects, function (index, item) {
|
|
$(item).data().select2._enabled = false;
|
|
});
|
|
|
|
$("#reassignExpenditureDialog").find("input[type='checkbox']").prop('disabled', true);
|
|
}
|
|
|
|
function scrollToProject(sender) {
|
|
if (!sender)
|
|
return;
|
|
|
|
var projectId = $(sender).attr('data-project-id');
|
|
if (!projectId || (projectId.length < 10))
|
|
return;
|
|
|
|
$('html, body').animate({
|
|
scrollTop: $("#prj_" + projectId.trim()).offset().top
|
|
}, 2000);
|
|
}
|
|
|
|
/* hack for Chrome begin */
|
|
/* Chrome frequently triggers mousemove event right after click event and sometimes mouseup event doesn't work and project doesn't expand in this case */
|
|
var _mouseDown = {};
|
|
function mousedown(event) {
|
|
_mouseDown = {
|
|
X: event.clientX,
|
|
Y: event.clientY
|
|
};
|
|
}
|
|
function mousemove(event) {
|
|
if (_mouseDown.X === event.clientX && _mouseDown.Y === event.clientY) {
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
}
|
|
}
|
|
/* hack for Chrome end */
|
|
|
|
function dropDownInsideClick(event) {
|
|
if (!event)
|
|
event = window.event;
|
|
|
|
var container = null, button = null;
|
|
if ($(event.target).hasClass('dropdown-menu'))
|
|
container = $(event.target);
|
|
else {
|
|
button = $(event.target);
|
|
container = button.closest('.dropdown-menu');
|
|
}
|
|
hideRedundantPopovers(container, button);
|
|
|
|
if (event.stopPropagation)
|
|
event.stopPropagation();
|
|
else
|
|
window.event.cancelBubble = true;
|
|
}
|
|
|
|
function dropDownFixPositionCalendar(button, dropdown, event) {
|
|
//if (!event)
|
|
// event = window.event;
|
|
setDropdownProps(button, dropdown, liHeight);
|
|
hideRedundantPopovers($('#mix-table'), null);
|
|
}
|
|
var liHeight = 30;
|
|
|
|
function isValidImportScenarioToProjectForm() {
|
|
$.validator.unobtrusive.parseDynamicContent('#mix-import-scenario-to-project-form');
|
|
return $('#mix-import-scenario-to-project-form').valid();
|
|
};
|
|
function refreshClick() {
|
|
$('#outdated').hide();
|
|
$('#btnApplyFilter').click();
|
|
}
|
|
</script>
|
|
<div ng-controller="mixProjectController" id="mix-project-container" ng-init="init(@Model)" ng-cloak>
|
|
|
|
<div class="alert alert-warning" style="display:none;" id="outdated">
|
|
<ul>
|
|
<li>
|
|
You opened project edit screen and information in the mix may be outdated. Please <a href="javascript:void(0);" onclick="refreshClick();">refresh</a> the Mix screen to check for updates.
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="alert alert-warning" data-ng-show="UnassignedExpendituresProjectsExist">
|
|
<ul>
|
|
<li>Destination team doesn't contain some necessary expenditure categories for the project. Please check allocations</li>
|
|
</ul>
|
|
</div>
|
|
<div class="alert alert-warning" data-ng-show="ShowDeletedObjectsWarning">
|
|
<i class="fa fa-times fa-warning-hide-button" title="Close this message" ng-click="hideDeletedProjectsWarning()"></i>
|
|
<ul>
|
|
<li ng-if="Calendar.ModifiedObjects && Calendar.ModifiedObjects.DeletedProjects">
|
|
The following projects were deleted from live database, and were automatically removed from the current Mix:<br />
|
|
<span class="warning-item-name" ng-repeat="projectName in Calendar.ModifiedObjects.DeletedProjects track by $index" ng-show="($index < 5) || deletedProjectsWarningTailVisible"><span ng-if="$index > 0">, </span>{{ projectName }}</span>
|
|
<span ng-if="Calendar.ModifiedObjects.DeletedProjects && (Calendar.ModifiedObjects.DeletedProjects.length > 5)" ng-show="!deletedProjectsWarningTailVisible">
|
|
<a href="javascript:void(0);" style="text-decoration:underline;" ng-click="showDeletedProjectsWarningTail()" title="Show complete list">...</a>
|
|
</span>
|
|
</li>
|
|
<li ng-if="Calendar.ModifiedObjects && Calendar.ModifiedObjects.DeletedResources">
|
|
The following resources were deleted from live database, and were automatically removed from the current Mix:<br />
|
|
<span class="warning-item-name" data-ng-repeat="resource in Calendar.ModifiedObjects.DeletedResources track by $index" ng-show="($index < 5) || liveDbDeletedResourcesWarningTailVisible"><span data-ng-if="$index > 0">, </span><span>{{ resource }}</span></span>
|
|
<span ng-if="Calendar.ModifiedObjects.DeletedResourcesCount > 5" ng-show="!liveDbDeletedResourcesWarningTailVisible">
|
|
<a href="javascript:void(0);" style="text-decoration:underline;" ng-click="showLiveDbDeletedResourcesWarningTail()" title="Show complete list">...</a>
|
|
</span>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="alert alert-warning" data-ng-show="ShowChangedObjectsWarning">
|
|
<i class="fa fa-times fa-warning-hide-button" title="Close this message" ng-click="hideLiveDbChangesWarning()"></i>
|
|
<ul>
|
|
<li>
|
|
Select <a href="javascript:void(0);" style="text-decoration:underline;" ng-click="updateMixFromLiveDatabase()">refresh</a> to update this Mix with the most recent data
|
|
</li>
|
|
<li ng-if="ChangedInLiveDbProjects && ChangedInLiveDbProjects.length > 0">
|
|
The following projects will be revised:
|
|
<span data-ng-repeat="project in ChangedInLiveDbProjects track by $index" ng-show="($index < 5) || liveDbChangedProjectsWarningTailVisible"><span data-ng-if="$index > 0">, </span><a onclick="scrollToProject(this)" data-project-id="{{ project.ProjectId }}" href="javascript:void(0);" title="Navigate to Project">{{ project.ProjectName }}</a></span>
|
|
<span ng-if="ChangedInLiveDbProjects && (ChangedInLiveDbProjects.length > 5)" ng-show="!liveDbChangedProjectsWarningTailVisible">
|
|
<a href="javascript:void(0);" style="text-decoration:underline;" ng-click="showLiveDbChangedProjectsWarningTail()" title="Show complete list">...</a>
|
|
</span>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="alert alert-warning" ng-show="showOutOfMixProjectsExistWarning">
|
|
<i class="fa fa-times fa-warning-hide-button" title="Close this message" ng-click="hideOutOfMixProjectsExistWarning()"></i>
|
|
<ul>
|
|
<li>
|
|
The following project(s) are no longer visible as scenario dates are outside current view:
|
|
<span style="color: #4083A9;">{{ OutOfMixProjects.join(', ') }}</span>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="btn-group pull-right" id="divMixMenuTemplate" style="display: none;">
|
|
<button class="btn btn-info dropdown-toggle lockable" type="button" data-toggle="dropdown"><i class="fa fa-bars"></i> <i class="fa fa-caret-down"></i></button>
|
|
<ul class="dropdown-menu dropdown-menu-right" style="width: 245px;" id="mixMenuTemplate">
|
|
<li class="padding-xs-hr">
|
|
<label>
|
|
<span class="switcherLbl">Default View</span>
|
|
<input type="checkbox" class="switcher px" id="monthWeekMode" data-key="monthWeekMode" ng-model="DisplayMode.IsViewModeMonth" onclick="saveMixPreferences()" />
|
|
</label>
|
|
</li>
|
|
<li class="padding-xs-hr">
|
|
<label>
|
|
<span class="switcherLbl">Quantity as</span>
|
|
<input type="checkbox" class="switcher px" id="uomMode" data-key="uomMode" ng-model="DisplayMode.IsUOMHours" onclick="saveMixPreferences()" />
|
|
</label>
|
|
</li>
|
|
<li class="padding-xs-hr">
|
|
<label>
|
|
<span class="switcherLbl">Resource Totals as </span>
|
|
<select id="selectOptions" data-key="showOption" class="form-control" style="padding: 3px" ng-model="DisplayMode.TotalsAs" onchange="saveMixPreferences()">
|
|
<option value="1">Allocated/Capacity</option>
|
|
<option value="2">Need/Capacity</option>
|
|
<option value="3">Allocated/Need</option>
|
|
<option value="4">Remaining/Capacity</option>
|
|
</select>
|
|
</label>
|
|
</li>
|
|
<li class="padding-xs-hr">
|
|
<label>
|
|
<span class="switcherLbl">Group Capacity by</span>
|
|
<input type="checkbox" class="switcher px" id="groupCapacityByTeam" data-key="groupCapacityByTeam" ng-model="DisplayMode.GroupCapacityByTeam" onclick="saveMixPreferences()" />
|
|
</label>
|
|
</li>
|
|
<li class="padding-xs-hr">
|
|
<label>
|
|
<span class="switcherLbl">Use Capacity</span>
|
|
<input type="checkbox" data-key="capacityView" id="capacityView" class="switcher px" ng-model="DisplayMode.CapacityView" onclick="saveMixPreferences()" />
|
|
</label>
|
|
</li>
|
|
<li class="padding-xs-hr">
|
|
<label>
|
|
<span class="switcherLbl">Assign Allocations</span>
|
|
<input type="checkbox" data-key="unassignedAllocations" id="unassignedAllocations" class="switcher px" ng-model="DisplayMode.UnassignedAllocations" onclick="saveMixPreferences()" />
|
|
</label>
|
|
</li>
|
|
<li class="padding-xs-hr">
|
|
<label>
|
|
<span class="switcherLbl">Show Resources</span>
|
|
<input type="checkbox" data-key="showResources" id="chShowResources" class="switcher px" ng-model="DisplayMode.ShowResources" onclick="saveMixPreferences()" />
|
|
</label>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="table-light table-responsive very-big-table freezeTable mix-table" style="overflow-y: hidden; padding-bottom:12px;">
|
|
<table class="table table-striped table-bordered dataTable ng-hide" id="mix-table" ng-show="Calendar != null && Calendar.Header != null">
|
|
<thead>
|
|
<tr>
|
|
<th class="headcol firstcol left">Teams</th>
|
|
<th ng-repeat="year in Calendar.Header.Years track by $index" colspan="{{year.Colspan}}" nowrap>
|
|
<i class="fa" style="margin-right: 5px;"></i>{{year.Title}}
|
|
</th>
|
|
</tr>
|
|
<tr>
|
|
<th class="headcol" style="visibility:hidden;"></th>
|
|
<th ng-repeat="month in Calendar.Header.Months track by $index" class="headcol-week" ng-click="toggleMonth($index)"
|
|
colspan="{{month.IsCollapsed ? 1 : month.Childs.length}}" nowrap>
|
|
<i class="fa" ng-class="month.CollapsedClass" style="margin-right: 5px;"></i>{{month.Title | limitTo : 3}}
|
|
</th>
|
|
</tr>
|
|
<tr>
|
|
<th class="headcol" style="visibility:hidden;"></th>
|
|
<th ng-repeat="week in Calendar.Header.Weeks track by $index" ng-if="week.Initialized" ng-show="week.Show" nowrap>
|
|
{{week.Title}}
|
|
</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody ng-repeat="team in Calendar.Teams | orderBy: 'Name' track by $index" ng-init="tIndex = $index">
|
|
@* Project row *@
|
|
<tr ng-repeat="project in team.Allocations track by $index" ng-init="aIndex = $index">
|
|
<td class="headcol left team-cell" data-ng-attr-style="{{team.AllocationCssStyles[$index]}}">{{team.Name}}</td>
|
|
<td project-cell="{{item.Value}}" ng-repeat="item in project.Cells track by $index"
|
|
ng-attr-colspan="{{item.colSpan}}"
|
|
ng-mousemove="team.Drop.Row == aIndex ? onMouseMove($event, team) : false"
|
|
ng-show="Calendar.Header.Weeks[$index].Show"
|
|
ng-if="Calendar.Header.Weeks[$index].Initialized && !item.IsSpanned"
|
|
class="proj-cell"
|
|
ng-style="{'cursor': (item.Pinned || item.DependencyPinned) ? 'default':'pointer'}"
|
|
ng-class="{
|
|
'droppable-active': (team.Drop.Row == aIndex) && (!team.Drop.Mod) && team.Drop.Cells[Calendar.Header.Weeks[$index].Milliseconds],
|
|
'droppable-before': (team.Drop.Row == aIndex) && (team.Drop.Mod == 'before') && team.Drop.Cells[Calendar.Header.Weeks[$index].Milliseconds],
|
|
'droppable-after': (team.Drop.Row == aIndex) && (team.Drop.Mod == 'after') && team.Drop.Cells[Calendar.Header.Weeks[$index].Milliseconds],
|
|
'dummy-team-row': item.IsDummyCell,
|
|
'default-background': item.Id}"
|
|
data-ng-attr-style="{{item.CssStyle}}"
|
|
title="{{item.Name}}"
|
|
dnd-draggable="!!item.Id && (!item.Pinned && !item.DependencyPinned)"
|
|
dnd-draggable-opts="{helper: 'drag-project-helper', useAsPoint: true}"
|
|
dnd-droppable="(!item.Pinned && !item.DependencyPinned)"
|
|
dnd-model="{Milliseconds: Calendar.Header.Weeks[$index].Milliseconds, Row: aIndex, Team: team, ProjectId: item.Id, CellIndex: $index}"
|
|
dnd-on-dragenter="dragEnter($dropmodel, $dragmodel)"
|
|
dnd-on-dragleave="dragLeave($dropmodel, $dragmodel)"
|
|
dnd-on-drop="drop($dropmodel, $dragmodel)"
|
|
ng-mousedown="setStartDnD($event)"
|
|
ng-attr-data-teamid="{{team.Id}}"
|
|
ng-attr-data-rowindex="{{aIndex}}"
|
|
onmousedown="mousedown(event)"
|
|
onmousemove="mousemove(event)">
|
|
<div ng-if="item.IsFirstCell" class="buttons-block" style="width:auto;">
|
|
<div>
|
|
<i class="fa fa-caret-right" ng-style="{'float':'right','margin-top':'5px','visibility':item.OverEnd ? 'visible' : 'hidden'}"></i>
|
|
<div id="menu_dd_{{item.Id}}_{{team.Id}}" class="dropdown" dropdown-menu style="float:right;" dnd-pointer-none>
|
|
<button type="button" title="Menu" style="margin-bottom:0px !important;" class="btn btn-xs dropdown-toggle" data-toggle="dropdown" onclick='dropDownFixPositionCalendar($(this), $(this).parent().find(".dropdown-menu"), event);'><i class="fa fa-caret-down"></i></button>
|
|
<ul id="ul_dd_{{item.Id}}_{{team.Id}}" class="dropdown-menu dropdown-menu-form dropdown-menu-right dropdown-menu-scroll-auto lioverflowh" style="text-align:left;padding:0px!important;width:220px;overflow-x: hidden;" onclick="dropDownInsideClick(event);">
|
|
<li ng-if="!item.Pinned && !item.DependencyPinned"><a data-toggle="popover" ng-click="editPinProject(item.Id, team.Id, true)"><i class="fa fa-pushpin btn-xs btn-info popover-warning popover-dark" style="width:25px; text-align:center;"></i> Pin Project</a></li>
|
|
<li ng-if="item.Pinned && !item.DependencyPinned"><a data-toggle="popover" ng-click="editPinProject(item.Id, team.Id, false)"><i class="fa fa-pushpin btn-xs btn-info popover-warning popover-dark" style="width:25px; text-align:center;"></i> Unpin Project</a></li>
|
|
<li><a data-toggle="popover" ng-click="editScenarioDetails(item.Id, item.Pinned)"><i class="fa fa-edit btn-xs btn-primary popover-warning popover-dark" style="width:25px; text-align:center;"></i> Edit Scenario Details</a></li>
|
|
<li ng-if="!item.Pinned && !item.DependencyPinned"><a data-toggle="popover" data-ng-click="removeTeamFromProject(item.Id, team.Id)"><i class="fa fa-times btn-xs btn-danger popover-warning popover-dark" style="width:25px; text-align:center;"></i> Remove from Team</a></li>
|
|
<li><a data-toggle="popover" ng-click="editScenarioTeams(item.Id)"><i class="fa fa-users btn-xs btn-pa-purple popover-warning popover-dark" style="width:25px; text-align:center;"></i> Add Team/Expenditure</a></li>
|
|
<li><a data-toggle="popover" ng-click="editScenarioFinInfo(item.Id)"><i class="fa fa-adjust btn-xs btn-success popover-warning popover-dark" style="width:25px; text-align:center;"></i> Edit Financials</a></li>
|
|
<li><a href="@Url.Action("Edit", "Project")?Id={{item.Id}}&mode=rmo" target="_blank" data-toggle="popover" onclick="$('#outdated').show();" class="projectEdit"><i class="fa fa-briefcase btn-xs btn-primary popover-warning popover-dark" style="width:25px; text-align:center;"></i> Edit Project</a></li>
|
|
<li><a data-toggle="popover" ng-click="importScenarioToProjectOpenWindow(item.Id)"><i class="fa fa-save btn-xs btn-warning popover-warning popover-dark" style="width:25px; text-align:center;"></i> Import to Project</a></li>
|
|
<li ng-show="item.ChangedInLiveDb"><a data-toggle="popover" ng-click="updateProjectFromDB(item.Id)"><i class="fa fa-refresh btn-xs btn-success popover-warning popover-dark" style="width:25px; text-align:center;"></i> Refresh Project</a></li>
|
|
<li class="divider"></li>
|
|
<li>
|
|
<div style="-ms-text-overflow: ellipsis; -o-text-overflow: ellipsis; text-overflow: ellipsis; overflow: hidden; max-width: 119px; float: left; padding-left: 15px;">
|
|
<span title="Active Scenario">Active Scenario</span>
|
|
</div>
|
|
<div style="float: right;padding-right: 15px;">
|
|
<a title="Copy" ng-click="copyScenario(Calendar.Projects[item.Id].Scenario)" class="btn btn-xs popover-warning popover-dark"><i class="fa fa-copy"></i></a>
|
|
</div>
|
|
</li>
|
|
<li ng-if="!item.Pinned && !item.DependencyPinned" ng-repeat="(id, inactiveScenario) in Calendar.Projects[item.Id].InactiveScenarios">
|
|
<div style="-ms-text-overflow: ellipsis; -o-text-overflow: ellipsis; text-overflow: ellipsis; overflow: hidden; max-width: 119px; float: left; padding-left: 15px;">
|
|
<span title="{{inactiveScenario.Name || 'Inactive Scenario'}}">{{inactiveScenario.Name || 'Inactive Scenario'}}</span>
|
|
</div>
|
|
<div style="float: right;padding-right: 15px;" ng-mouseover="showActivateScenarioTooltip($event,item.HasDependency)">
|
|
<a ng-disabled="item.HasDependency" data-toggle="popover" title="Activate in Mix" ng-click="activateScenario(inactiveScenario.Id, item.Id)" class="btn btn-xs btn-primary popover-warning popover-dark"><i class="fa fa-check-circle-o"></i></a>
|
|
<a data-toggle="popover" title="Copy" ng-click="copyScenario(inactiveScenario)" class="btn btn-xs popover-warning popover-dark"><i class="fa fa-copy"></i></a>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<i ng-show="item.HasLink" ng-style="{'float':'right', 'margin-right':'5px','margin-top':'5px'}" class="fa fa-link"></i>
|
|
<i ng-show="item.HasDependency" ng-style="{'float':'right', 'margin-right':'5px','margin-top':'5px'}" class="fa fa-level-down"></i>
|
|
<i ng-show="item.Pinned" ng-style="{'float':'right', 'margin-right':'5px','margin-top':'5px'}" class="fa fa-pushpin"></i>
|
|
<i ng-show="item.DependencyPinned" ng-mouseover="showProjectTooltip($event,item.DependencyToolTip)" ng-style="{'float':'right', 'margin-right':'5px','margin-top':'5px'}" class="fa fa-lock"></i>
|
|
<i ng-show="item.ChangedInLiveDb" ng-style="{'float':'right', 'margin-right':'5px','margin-top':'5px', 'color':'#ffd700', 'text-shadow':'0px 0px 3px black'}" class="fa fa-warning" title="Scenario was changed in LIVE database"></i>
|
|
</div>
|
|
</div>
|
|
<div ng-if="item.IsFirstCell" class="project-title">
|
|
<div style="float:left;margin-right:5px;"><i ng-class="{'fa-caret-left':item.OverStart}" class="fa"></i></div>
|
|
<div style="float:left" class="cell-text1" ng-style="{'width': (item.width)}">{{item.Name}}</div>
|
|
</div>
|
|
<a id="prj_{{ item.Id }}" ng-if="item.IsFirstCell" />
|
|
<script type="text/ng-template" id="drag-project-helper">
|
|
<div class='dnd-cell' data-ng-attr-style='{{item.CssStyle}}'> </div>
|
|
</script>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
<tbody ng-controller="teamInfoController">
|
|
@* Non-Project Time row *@
|
|
@if (SecurityManager.CheckSecurityObjectPermission(Areas.RD_ResourceNonProjectTime, AccessLevel.Read))
|
|
{
|
|
<tr ng-repeat-start="key in DisplayDataOrder track by $index" ng-if="DisplayData[key].Type == RowType.NonProjectTime" class="total-row">
|
|
<td class="headcol left np-time-name">
|
|
<a ng-click="toggleRow(key)" class="row-title">
|
|
<i class="noprint fa" ng-class="DisplayData[key].IsCollapsed ? 'fa-plus-square' : 'fa-minus-square'" style="margin-right: 5px;"
|
|
ng-attr-title="{{DisplayData[key].IsCollapsed ? 'Expand' : 'Collapse'}}">
|
|
</i>
|
|
{{ DisplayData[key].Name || '' }}
|
|
</a>
|
|
</td>
|
|
<td ng-repeat="cell in DisplayData[key].Cells track by $index" ng-show="Calendar.Header.Weeks[$index].Show" ng-if="Calendar.Header.Weeks[$index].Initialized">
|
|
<div class="cell-text">{{cell || 0 | number:2}}</div>
|
|
</td>
|
|
</tr>
|
|
<tr ng-if="DisplayData[key].Type == RowType.NonProjectTime" ng-show="!DisplayData[key].IsCollapsed" ng-repeat="(npTimeCategoryId, npTimeCategory) in DisplayData[key].Categories track by $index" class="total-row">
|
|
<td class="headcol left np-time-name">
|
|
<span>{{npTimeCategory.Name}}</span>
|
|
</td>
|
|
<td ng-repeat="cell in npTimeCategory.Cells track by $index" ng-show="Calendar.Header.Weeks[$index].Show" ng-if="Calendar.Header.Weeks[$index].Initialized">
|
|
<div class="cell-text">{{cell || 0 | number:2}}</div>
|
|
</td>
|
|
</tr>
|
|
}
|
|
@* Team, Company or Cost Center row *@
|
|
<tr ng-if="DisplayData[key].Type == RowType.Team || DisplayData[key].Type == RowType.Company || DisplayData[key].Type == RowType.CostCenter" class="total-row">
|
|
<td class="headcol left capacity-row-title">
|
|
<a ng-click="toggleParentRow(key)" class="row-title">
|
|
<i class="noprint fa" ng-class="DisplayData[key].IsCollapsed ? 'fa-plus-square' : 'fa-minus-square'" style="margin-right: 5px;"
|
|
ng-attr-title="{{DisplayData[key].IsCollapsed ? 'Expand' : 'Collapse'}}">
|
|
</i>
|
|
{{ DisplayData[key].Name || '' }}
|
|
</a>
|
|
</td>
|
|
<td ng-repeat="cell in DisplayData[key].Cells track by $index" ng-show="Calendar.Header.Weeks[$index].Show"
|
|
ng-if="Calendar.Header.Weeks[$index].Initialized" class="capacity-total" ng-class="DisplayData[key].CSSClass[$index]">
|
|
<div class="exp-cat-total tooltip-info" ng-click="showTooltip($event, cell, 'team')">
|
|
<div class="top-side">{{ (cell.Value1 || 0 | number:2)}}</div>
|
|
<hr />
|
|
<div class="bottom-side">{{ (cell.Value2 || 0 | number:2)}}</div>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
@* Expenditure category row *@
|
|
<tr ng-if="DisplayData[key].Type == RowType.ExpenditureCategory && DisplayData[key].Initialized" ng-show="DisplayData[key].Show">
|
|
<td ng-if="DisplayData[key].Resources.length > 0" class="headcol left capacity-row-title">
|
|
<a ng-click="toggleRow(key)" class="row-title">
|
|
<i class="noprint fa" ng-class="DisplayData[key].IsCollapsed ? 'fa-plus-square' : 'fa-minus-square'" style="margin-right: 5px;"
|
|
ng-attr-title="{{DisplayData[key].IsCollapsed ? 'Expand' : 'Collapse'}}">
|
|
</i>
|
|
{{ DisplayData[key].Name || 'empty' }}
|
|
</a>
|
|
</td>
|
|
<td ng-if="DisplayData[key].Resources.length == 0" class="headcol left capacity-row-title">
|
|
<span class="row-title">
|
|
{{ DisplayData[key].Name || 'empty' }}
|
|
</span>
|
|
</td>
|
|
<td ng-repeat="cell in DisplayData[key].Cells track by $index" ng-show="Calendar.Header.Weeks[$index].Show"
|
|
ng-if="Calendar.Header.Weeks[$index].Initialized" class="capacity-total" ng-class="DisplayData[key].CSSClass[$index]">
|
|
<div class="exp-cat-total tooltip-info" ng-click="showTooltip($event, cell, 'expenditure')">
|
|
<div class="top-side">
|
|
{{ (cell.Value1 || 0 | number:2) || cell.Value1 }}
|
|
</div>
|
|
<hr />
|
|
<div class="bottom-side">
|
|
{{ (cell.Value2 || 0 | number:2) || cell.Value2 }}
|
|
</div>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
@* Resources rows which related to current EC *@
|
|
<tr ng-if="DisplayData[key].Type == RowType.ExpenditureCategory && resource.Initialized" ng-show="!DisplayData[key].IsCollapsed && DisplayData[key].Show" ng-repeat="resource in DisplayData[key].Resources">
|
|
<td class="headcol left capacity-row-title">
|
|
<div class="resource-name row-title">{{resource.Name}}</div>
|
|
</td>
|
|
<td ng-repeat="cell in resource.Cells track by $index" ng-show="Calendar.Header.Weeks[$index].Show"
|
|
ng-if="Calendar.Header.Weeks[$index].Initialized" class="capacity-total" ng-class="resource.CSSClass[$index]">
|
|
<div class="exp-cat-total tooltip-info" ng-click="showTooltip($event, cell, 'resource')">
|
|
<div class="top-side">{{ (cell.Value1 || 0 | number:2)}}</div>
|
|
<hr />
|
|
<div class="bottom-side">{{ (cell.Value2 || 0 | number:2)}}</div>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
<tr ng-repeat-end ng-if="false"></tr>
|
|
</tbody>
|
|
</table>
|
|
|
|
</div>
|
|
<!-- Blocks "Projects with Unassigned Expenditures" and "Unassigned Projects" -->
|
|
<div class="row" data-ng-if="IsDataLoaded" data-ng-show="IsDataLoaded">
|
|
<div class="col-md-6">
|
|
<div class="rmo-projects-bucket">
|
|
<div class="rmo-projects-bucket-header">
|
|
<label class="control-label">Projects with Unassigned Expenditures</label>
|
|
</div>
|
|
<ul class="list-group" style="margin-bottom: 0px;">
|
|
<li class="list-group-item rmo-no-items" data-ng-show="!UnassignedExpendituresProjectsExist">
|
|
No items available
|
|
</li>
|
|
<li class="list-group-item" data-ng-repeat="item in Calendar.UnassignedExpendituresProjects track by $index"
|
|
data-ng-attr-style="{{item.CssStyle}}" style="vertical-align: middle;">
|
|
<div style="display: inline-block; float: right">
|
|
<a title="Edit" class="btn btn-xs popover-warning popover-dark" data-toggle="popover" data-ng-click="reassignExpCat(item, 'showExpCatReassignDialog')"><i class="fa fa-random icon black"></i></a>
|
|
</div>
|
|
<span>
|
|
{{item.Name}}
|
|
</span>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="rmo-projects-bucket">
|
|
<div class="rmo-projects-bucket-header">
|
|
<label class="control-label">Unscheduled Projects</label>
|
|
</div>
|
|
<ul class="list-group" style="margin-bottom: 0px;">
|
|
<li class="list-group-item rmo-no-items" data-ng-show="!UnscheduledProjectsExist">
|
|
No items available
|
|
</li>
|
|
<li class="list-group-item" data-ng-repeat="item in Calendar.UnscheduledProjects track by $index"
|
|
data-dnd-draggable="true"
|
|
data-dnd-draggable-opts="{ helper: 'drag-helper', useAsPoint: true}"
|
|
data-dnd-on-dragleave="dragleave($dropmodel, $dragmodel)"
|
|
data-dnd-on-dragenter="dragEnter($dropmodel, $dragmodel)"
|
|
data-dnd-model="{ProjectId: item.Id, IsUnscheduled: true}"
|
|
data-ng-attr-style="{{item.CssStyle}}">
|
|
{{item.Name}}
|
|
<script type="text/ng-template" id="drag-helper">
|
|
<div class='dnd-cell' data-ng-attr-style='{{item.CssStyle}}'> </div>
|
|
</script>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- Existing block "Projects Outside Current Range" -->
|
|
<div class="panel-body form-horizontal" id="dvBtns3">
|
|
<div class="row noprint" ng-show="Calendar.Queue4UnscheduledProjects.length > 0">
|
|
<label class="col-md-3 control-label" for="selProjects2Add">Projects Outside Current Range</label>
|
|
<div class="col-md-7 select2-primary">
|
|
<select ng-model="data.Projects2Add" id="selProjects2Add" name="selProjects2Add" class="form-control"
|
|
multiple="multiple" ng-options="project.Name for project in Calendar.Queue4UnscheduledProjects"></select>
|
|
</div>
|
|
<div class="col-md-2">
|
|
<button ng-click="addProjectsFromQueue()" class="btn btn-success" title="Add to Unscheduled Projects list"><i class="fa fa-plus"></i></button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="copyScenario" class="modal fade" tabindex="-1" role="dialog" style="display: none;" data-backdrop="static">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">x</button>
|
|
<h4 class="modal-title">Copy Scenario</h4>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="panel-body">
|
|
<div class="form-group">
|
|
<label class="col-sm-4 control-label" for="copierProjectId">Target Project</label>
|
|
<div class="col-sm-8 select2-primary">
|
|
<select id="copierProjectId" ng-model="copier.scenario.ParentId" class="form-control" ng-options="v.Id as v.Name for (k, v) in Calendar.Projects" required></select>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label class="col-sm-4 control-label" for="scenarioName">Scenario Name</label>
|
|
<div class="col-sm-8">
|
|
<input ng-model="copier.scenario.Name" class="form-control" type="text" id="scenarioName" name="scenarioName" required style="width:100%;" />
|
|
</div>
|
|
<div class="col-sm-6">
|
|
<span class="validation-error" ng-show="copier.scenario.Name.$error.required">Scenario Name is a required field</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div> <!-- / .modal-body -->
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-primary" data-dismiss="modal" ng-click="copyScenarioConfirmed()">OK</button>
|
|
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
|
|
</div>
|
|
</div> <!-- / .modal-content -->
|
|
</div> <!-- / .modal-dialog -->
|
|
</div> <!-- /.modal -->
|
|
<div id="mix-edit-scenario-details-dialog" class="modal fade" data-width="1000" tabindex="-1" role="dialog" style="display: none;" data-backdrop="static">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">x</button>
|
|
<h4 class="modal-title">Edit Scenario Details</h4>
|
|
</div>
|
|
<div class="modal-body" id="mix-edit-scenario-details-dialog-content">
|
|
</div> <!-- / .modal-body -->
|
|
</div> <!-- / .modal-content -->
|
|
</div> <!-- /.modal -->
|
|
<div id="mix-edit-scenario-teams-dialog" data-width="800" class="modal fade" tabindex="-1" role="dialog" style="display: none;" data-backdrop="static">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">x</button>
|
|
<h4 class="modal-title">Add Team/Expenditure</h4>
|
|
</div>
|
|
<div class="modal-body" id="mix-edit-scenario-teams-dialog-content">
|
|
<div class="panel-body form-horizontal">
|
|
<div class="form-group noprint">
|
|
<label class="col-md-3 control-label" for="selProjectExpCats2Add">Expenditure Category</label>
|
|
<div class="col-md-9 select2-primary">
|
|
<select ng-model="AddTeamForm.ProjectExpCats2Add" id="selProjectExpCats2Add" name="selProjectExpCats2Add" class="form-control"
|
|
multiple="multiple" ng-options="item.Name for item in AddTeamForm.AvailableProjectExpCats2Add"></select>
|
|
</div>
|
|
</div>
|
|
<div class="form-group noprint">
|
|
<label class="col-md-3 control-label" for="selProjectCurrTeams2Add">Team in Current View</label>
|
|
<div class="col-md-9 select2-primary">
|
|
<select ng-model="AddTeamForm.ProjectInTeams2Add" id="selProjectCurrTeams2Add" name="selProjectCurrTeams2Add" class="form-control"
|
|
multiple="multiple" ng-options="item.Name for item in AddTeamForm.AvailableInTeams"></select>
|
|
</div>
|
|
</div>
|
|
<div class="row noprint">
|
|
<label class="col-md-3 control-label" for="selProjectOutTeams2Add">Team out of Current View</label>
|
|
<div class="col-md-9 select2-primary">
|
|
<select ng-model="AddTeamForm.ProjectOutTeams2Add" id="selProjectOutTeams2Add" name="selProjectOutTeams2Add" class="form-control"
|
|
multiple="multiple" ng-options="item.Name for item in AddTeamForm.AvailableProjectOutTeams2Add"></select>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div> <!-- / .modal-body -->
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-primary" data-ng-click="addTeamsAndExpenditures2Project(true)">Open Scenario Details</button>
|
|
<button type="button" class="btn btn-primary" ng-click="addTeamsAndExpenditures2Project()">Save</button>
|
|
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
|
|
</div>
|
|
</div> <!-- / .modal-content -->
|
|
</div> <!-- /.modal -->
|
|
|
|
<div id="reassignExpenditureDialog" class="modal fade" tabindex="-1" role="dialog" style="display: none;" data-backdrop="static">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">x</button>
|
|
<h4 class="modal-title">Unassigned Expenditure Allocations</h4>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="panel-body">
|
|
<div class="form-group" data-ng-show="frmReassign_OtherEcActionEnabled">
|
|
<div class="col-sm-12">
|
|
<input type="radio" id="frmReassignOtherEC" data-ng-model="frmReassign_Action" value="otherEC" onchange="reassignExpenditureRadioChanged(this)" style="margin-right: 6px;" /><label for="frmReassignOtherEC">Replace {{ frmReassign_ExpCatName }} with another category</label>
|
|
<div class="row noprint" style="margin-left: 8px;">
|
|
<div class="col-sm-12">
|
|
<select data-ng-model="frmReassign_ToExpCatId" class="form-control" data-ng-options="s.Id as s.Name for s in frmReassign_ExpCatsInTeam"></select>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<div class="col-sm-12">
|
|
<input type="radio" id="frmReassignOtherTeam" data-ng-model="frmReassign_Action" value="otherTeam" onchange="reassignExpenditureRadioChanged(this)" style="margin-right: 6px;" /><label for="frmReassignOtherTeam">Assign {{ frmReassign_ExpCatName }} to another team</label>
|
|
<div class="row noprint" style="margin-left: 8px;">
|
|
<div class="col-sm-12">
|
|
<select data-ng-model="frmReassign_ToTeamId" class="form-control" data-ng-options="team.Id as team.Name group by team.Group.Name for team in frmReassign_MixTeams | orderBy:['Group.Ord','Name']"></select>
|
|
</div>
|
|
<div class="col-sm-12" style="font-style: italic;">
|
|
<span>* Team exists in Current Project</span>
|
|
</div>
|
|
<div class="col-sm-12" style="margin-top: 4px;">
|
|
<input type="checkbox" id="frmReassignAllExpCats" style="margin-right: 6px;" data-ng-model="frmReassign_TryAssignOtherECs" /><label for="frmReassignAllExpCats" style="font-weight: inherit;">Try to assign other project Expenditure categories to this Team</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<div class="col-sm-12">
|
|
<input type="radio" id="frmReassignRemove" data-ng-model="frmReassign_Action" value="remove" onchange="reassignExpenditureRadioChanged(this)" style="margin-right: 6px;" /><label for="frmReassignRemove">Remove {{ frmReassign_ExpCatName }} from the Project</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div> <!-- / .modal-body -->
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-primary" data-dismiss="modal" data-ng-click="reassignUnassignedAllocations(false)" data-ng-disabled="!IsReassignExpCatActionAvailable()">Execute</button>
|
|
<button type="button" class="btn btn-primary" data-dismiss="modal" data-ng-click="reassignUnassignedAllocations(true)" data-ng-disabled="!IsReassignExpCatActionAvailable()">Execute and open Scenario Details</button>
|
|
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
|
|
</div>
|
|
</div> <!-- / .modal-content -->
|
|
</div> <!-- / .modal-dialog -->
|
|
</div> <!-- /.modal -->
|
|
<div id="mix-import-scenario-to-project-dialog" data-width="600" class="modal fade" tabindex="-1" role="dialog" style="display: none;" data-backdrop="static">
|
|
<div class="modal-content">
|
|
<form id="mix-import-scenario-to-project-form">
|
|
<div class="modal-header">
|
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">x</button>
|
|
<h4 class="modal-title">Import Scenario to Project</h4>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="row">
|
|
<div class="col-sm-12">
|
|
<div class="form-group no-margin-hr">
|
|
<p class="text-center text-bold">Are you sure you want to import this scenario to the project?</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="row" ng-show="!!ImportScenarioForm.NewTeams && ImportScenarioForm.NewTeams.length > 0">
|
|
<div class="col-sm-12">
|
|
<div class="form-group no-margin-hr">
|
|
This scenario has the following teams that exist only in your Mix:
|
|
<ul>
|
|
<li ng-repeat="team in ImportScenarioForm.NewTeams track by $index">{{team.Name}}</li>
|
|
</ul>
|
|
These teams will also be imported into the system.
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col-md-9">
|
|
<div class="form-group no-margin-hr">
|
|
<label class="control-label" for="importScenerioName">Scenario Name</label>
|
|
<input type="text" id="importScenerioName" name="importScenerioName" class="form-control" data-val="true"
|
|
data-val-required="The Scenario Name field is required."
|
|
data-val-maxlength="Name should not exceed 200 characters" data-val-maxlength-max="200"
|
|
ng-model="ImportScenarioForm.Name" />
|
|
<span data-valmsg-for="importScenerioName" data-valmsg-replace="true"></span>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="form-group no-margin-hr switcher-block">
|
|
<label class="control-label" for="importScenarioIsActive">Create As Active</label>
|
|
<input type="checkbox" ng-model="ImportScenarioForm.IsActive" id="importScenarioIsActive" name="importScenarioIsActive" class="switcher form-control yes-no-switcher" />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col-sm-12">
|
|
<div class="form-group no-margin-hr">
|
|
<i>* Scenario will be imported in its current state, so if you have unsaved changes, unsaved version of scenario will be imported.</i>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div> <!-- / .modal-body -->
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-primary" ng-click="importScenarioToProjectConfirm()">OK</button>
|
|
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
|
|
</div>
|
|
</form>
|
|
</div> <!-- / .modal-content -->
|
|
</div> <!-- /.modal -->
|
|
<div id="mix-edit-scenario-fininfo-dialog" class="modal fade" data-width="1000" tabindex="-1" role="dialog" style="display: none;" data-backdrop="static">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">x</button>
|
|
<h4 class="modal-title">Edit Financials</h4>
|
|
</div>
|
|
<div class="modal-body" id="mix-edit-scenario-fininfo-dialog-content">
|
|
</div> <!-- / .modal-body -->
|
|
</div> <!-- / .modal-content -->
|
|
</div> <!-- /.modal -->
|
|
<div id="projectsUpdateFromLiveDialog" class="modal fade" data-width="800" tabindex="-1" role="dialog" style="display: none;" data-backdrop="static">
|
|
<div class="modal-dialog" style="width:100%">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">x</button>
|
|
<h4 class="modal-title">Update Projects from Live Database</h4>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="panel-body">
|
|
<div class="form-group" ng-show="frmLDBUpd_ProjectsToDelete && frmLDBUpd_ProjectsToDelete.length > 0">
|
|
<div class="row">
|
|
<div class="col-sm-12" style="font-weight:bold">
|
|
The following projects were deleted from LIVE database and will be deleted from current Mix:
|
|
</div>
|
|
<ul class="col-sm-12" style="margin-left: 20px;">
|
|
<li ng-repeat="item in frmLDBUpd_ProjectsToDelete track by $index">
|
|
{{ item.ProjectName }}
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="form-group" ng-show="frmLDBUpd_ProjectsToRemoveScenario && frmLDBUpd_ProjectsToRemoveScenario.length > 0">
|
|
<div class="row">
|
|
<div class="col-sm-12" style="font-weight:bold">
|
|
The following projects no longer have active scenarios in LIVE database,
|
|
and will be moved to Unscheduled Projects block:
|
|
</div>
|
|
<ul class="col-sm-12" style="margin-left: 20px;">
|
|
<li ng-repeat="item in frmLDBUpd_ProjectsToRemoveScenario track by $index">
|
|
{{ item.ProjectName }}
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="form-group" ng-show="frmLDBUpd_ProjectsToReplaceScenario && frmLDBUpd_ProjectsToReplaceScenario.length > 0">
|
|
<div class="row">
|
|
<div class="col-sm-12" style="font-weight:bold">
|
|
Active scenarios for the following projects were replaced in LIVE database.
|
|
Scenarios will be replaced for these projects in current Mix:
|
|
</div>
|
|
<ul class="col-sm-12" style="margin-left: 20px;">
|
|
<li ng-repeat="item in frmLDBUpd_ProjectsToReplaceScenario track by $index">
|
|
{{ item.ProjectName }}
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div> <!-- / .modal-body -->
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-primary" data-dismiss="modal" data-ng-click="updateProjectsFromLiveDbConfirmed(false)">Continue</button>
|
|
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
|
|
</div>
|
|
</div> <!-- / .modal-content -->
|
|
</div> <!-- / .modal-dialog -->
|
|
</div> <!-- /.modal -->
|
|
</div> |