768 lines
43 KiB
Plaintext
768 lines
43 KiB
Plaintext
@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;
|
|
}
|
|
|
|
|
|
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");
|
|
|
|
$('#capacityView').switcher({
|
|
on_state_content: 'Actual',
|
|
off_state_content: 'Planned'
|
|
});
|
|
$('#capacityView').parent().css("width", "93px");
|
|
|
|
// SA. ENV-1298
|
|
container.find('#unassignedAllocations').switcher({
|
|
on_state_content: 'Auto',
|
|
off_state_content: 'Manual'
|
|
}).parent().css("width", "100px");
|
|
|
|
$('#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();
|
|
});
|
|
$(document).on('hide.bs.modal', '#copyScenario', function (e) {
|
|
if ($(e.target).attr('id') != 'copyScenario') {
|
|
$("#push_pull").focus();
|
|
return true; // close modal form
|
|
}
|
|
if (typeof isPPDataChanged === 'function')
|
|
if (isPPDataChanged()) {
|
|
if (confirm("Copy Scenario form contains unsaved changes, do you really want to close the form?")) {
|
|
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('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()) {
|
|
if (confirm("Add Team/Expenditure form contains unsaved changes, do you really want to close the form?")) {
|
|
if (typeof resetAddExpCatsDataChanged === 'function') {
|
|
resetAddExpCatsDataChanged();
|
|
$('#mix-edit-scenario-teams-dialog select').select2('val', '');
|
|
return true;
|
|
}
|
|
}
|
|
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', '#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
|
|
if (confirm("@EnVisage.Code.Constants.CONFIRM_CREATE_SCENARIO")) {
|
|
// reset change indicator
|
|
if (typeof resetScenarioDataChanged === 'function') {
|
|
resetScenarioDataChanged();
|
|
}
|
|
$('#create-scenario-dialog-content').html('');
|
|
return true; // close modal form
|
|
};
|
|
return false; // DO NOT close modal form
|
|
}
|
|
$('#create-scenario-dialog-content').html('');
|
|
return true; // close modal form
|
|
});
|
|
|
|
$(window).scroll(function () {
|
|
$('.menuGroup').removeClass('open');
|
|
hideRedundantPopovers($('#mix-table'), null);
|
|
});
|
|
|
|
$('.table-striped').scroll(function () {
|
|
$('.menuGroup').removeClass('open');
|
|
hideRedundantPopovers($('#mix-table'), null);
|
|
});
|
|
$(document).click(function (event) {
|
|
$('.menuGroup').removeClass('open');
|
|
if (!$(event.target).is('[data-toggled="popover"]'))
|
|
hideRedundantPopovers($('#mix-table'), null);
|
|
});
|
|
|
|
$(".dropdown-menu-scroll-auto").mousedown(function () {
|
|
dropDownInsideClick();
|
|
});
|
|
|
|
// SA. ENV-1254
|
|
$('#reassignExpenditureDialog').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) + '&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 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');
|
|
}
|
|
|
|
// SA. ENV-1254
|
|
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);
|
|
}
|
|
|
|
// SA. ENV-1254
|
|
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);
|
|
}
|
|
|
|
/* 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) {
|
|
console.log('fired');
|
|
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) {
|
|
|
|
setDropdownProps(button, dropdown, liHeight);
|
|
|
|
|
|
hideRedundantPopovers($('#mix-table'), null);
|
|
}
|
|
var liHeight = 30;
|
|
function hideRedundantPopovers(container, currentBtn) {
|
|
|
|
var id = null;
|
|
if (currentBtn) {
|
|
if (currentBtn.is('[data-toggle="popover"]'))
|
|
id = currentBtn.attr('id');
|
|
else
|
|
id = currentBtn.closest('[data-toggle="popover"]').attr('id');
|
|
}
|
|
container.find('[data-toggle="popover"]' + (id != null && id != undefined) ? '[id!="' + id + '"]' : '').popover('destroy');
|
|
}
|
|
</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:window.location.reload();">refresh</a> the Mix screen to check for updates.
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<!-- SA. ENV-1210. Page warning message -->
|
|
<div class="alert alert-warning" data-ng-show="PageWarningMessage && (PageWarningMessage.length > 0)" id="calendarWarnings"
|
|
data-ng-click="hidePageWarningMessage()">
|
|
<ul>
|
|
<li>{{ PageWarningMessage }}</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>
|
|
</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>
|
|
</ul>
|
|
</div>
|
|
<div class="table-light table-responsive very-big-table freezeTable mix-table" style="overflow-y: hidden;">
|
|
<table class="table table-striped table-bordered dataTable ng-hide" watch-resizing 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 ? '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"
|
|
dnd-draggable-opts="{helper: 'drag-project-helper', useAsPoint: true}"
|
|
dnd-droppable="!item.Pinned"
|
|
dnd-model="{Milliseconds: Calendar.Header.Weeks[$index].Milliseconds, Row: aIndex, Team: team, ProjectId: item.Id, CellIndex: $index}"
|
|
dnd-on-dragenter="dragEnter($dropmodel, $dragmodel, $event)"
|
|
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:45px;">
|
|
<div>
|
|
<i ng-style="{'float':'left', 'margin-right':'5px','margin-top':'5px','visibility': (!item.Pinned ? 'hidden' : 'visible')}" class="fa fa-pushpin"></i>
|
|
<div id="menu_dd_{{item.Id}}_{{team.Id}}" class="dropdown menuGroup " style="float:left;">
|
|
<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"));'><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"><a href="#" data-toggle="popover" ng-click="editPinProject(item, item.Id, team.Id, $event, 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"><a href="#" data-toggle="popover" ng-click="editPinProject(item, item.Id, team.Id, $event, 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 href="#" data-toggle="popover" ng-click="editScenarioDetails(item.Id, $event, 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><a href="#" 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 href="#" data-toggle="popover" ng-click="editScenarioTeams(item.Id, $event)"><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 href="#" data-toggle="popover"><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-warning popover-warning popover-dark" style="width:25px; text-align:center;"></i> Edit 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="{{Calendar.Projects[item.Id].Scenario.Name || 'Active Scenario'}}">{{Calendar.Projects[item.Id].Scenario.Name || 'Active Scenario'}}</span>
|
|
</div>
|
|
<div style="float: right;padding-right: 15px;">
|
|
<a data-toggle="popover" title="Copy" ng-click="copyScenario(item.Id, Calendar.Projects[item.Id].Scenario.Id)" class="btn btn-xs popover-warning popover-dark"><i class="fa fa-copy"></i></a>
|
|
</div>
|
|
</li>
|
|
<li ng-repeat="(id, scen) 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="{{scen.Name || 'Inactive Scenario'}}">{{scen.Name || 'Inactive Scenario'}}</span>
|
|
</div>
|
|
<div style="float: right;padding-right: 15px;">
|
|
<a data-toggle="popover" title="Activate in Mix" ng-click="activateScenario(scen.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" @*data-toggle="modal" data-target="#copyScenario"*@ ng-click="copyScenario(item.Id, scen.Id)" class="btn btn-xs popover-warning popover-dark"><i class="fa fa-copy"></i></a>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
@*<button type="button" class="close btn-lg row-remove" title="Remove project from team">x</button>*@
|
|
<i ng-class="{'fa-caret-right':item.OverEnd}" class="fa"></i>
|
|
</div>
|
|
@*<div style="width:20px;height:10px;float:right;"><i class="fa fa-caret-right"></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>
|
|
<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">
|
|
@* Vacations or Trainings row *@
|
|
<tr ng-repeat-start="key in DisplayDataOrder track by $index" ng-if="DisplayData[key].Type == 1 || DisplayData[key].Type == 2" class="total-row">
|
|
<td class="headcol resource-name left">
|
|
{{DisplayData[key].Name}}
|
|
</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>
|
|
@* Team row *@
|
|
<tr ng-if="DisplayData[key].Type == 3" class="total-row">
|
|
<td class="headcol left capacity-row-title">
|
|
<div class="row-title">{{DisplayData[key].Name}}</div>
|
|
</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">
|
|
<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 == 4">
|
|
<td class="headcol left capacity-row-title">
|
|
<a href="#" ng-click="toggleExpCategoryRow(key, $event)" 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-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">
|
|
<div class="top-side">{{ (cell.Value1 || 0 | number:2)}}</div>
|
|
<hr />
|
|
<div class="bottom-side">{{ (cell.Value2 || 0 | number:2)}}</div>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
@* Resources rows which related to current EC *@
|
|
<tr ng-if="DisplayData[key].Type == 4" ng-show="!DisplayData[key].IsCollapsed" 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">
|
|
<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">
|
|
<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.targetProjectId" class="form-control" ng-options="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.scenarioName" class="form-control" type="text" id="scenarioName" name="scenarioName" data-bind="value: scenarioName" required style="width:100%;" />
|
|
</div>
|
|
<div class="col-sm-6">
|
|
<span class="validation-error" ng-show="copier.scenarioName.$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" ng-click="cancelAddExpCatsAndTeams()">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> |