EnVisageOnline/Main/Source/EnVisage/Views/Team/Board.cshtml

1187 lines
58 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

@model EnVisage.Models.TeamboardModel
@using EnVisage.Code;
@{
ViewBag.Title = Model.SelectedTeamName;
var model = new
{
DisplayMode = new
{
MenuId = "visibilitydropdown_calendar",
DataSection = "capacityManagementView",
PageKey = "/Team/Board",
BackUrlTitle = "dashboard",
GroupByItems = new object[]
{
new { value = "2", text = "Project" },
new { value = "3", text = "Resource" },
new { value = "4", text = "Business Unit" },
new { value = "5", text = "Client" },
new { value = "6", text = "Cost Center" },
}
},
Filter = new
{
EntityType = EnVisage.Models.CapacityPageInitOption.CalendarEntityType.Team,
EntityId = Model.Id,
ShowFilters = false
},
TargetPage = "TeamBoard"
};
}
@section stylesheets
{
@Styles.Render(String.Format("{0}/{1}", Constants.C_BUNDLE_STYLES_BASE_PATH, "prevu-acstyles"))
@Styles.Render(String.Format("{0}/{1}", Constants.C_BUNDLE_STYLES_KENDO_PATH, "kendo-commonstyles"))
<style type="text/css">
#teamResourcesNewBtn:after {
content: "" !important;
}
#capacity-table .headcol {
left: -3px;
}
</style>
}
@section scripts
{
@Scripts.Render(String.Format("{0}/{1}", Constants.C_BUNDLE_SCRIPTS_BASE_PATH, "kendo-grid"))
@Scripts.Render(String.Format("{0}/{1}", Constants.C_BUNDLE_SCRIPTS_BASE_PATH, "flot-scripts"))
@Scripts.Render(String.Format("{0}/{1}", Constants.C_BUNDLE_SCRIPTS_BASE_PATH, "prevu-angularservices"))
@Scripts.Render(String.Format("{0}/{1}", Constants.C_BUNDLE_SCRIPTS_BASE_PATH, "prevu-activitycalendar"))
@Scripts.Render(String.Format("{0}/{1}", Constants.C_BUNDLE_SCRIPTS_BASE_PATH, "prevu-scenariodetails"))
@Scripts.Render(String.Format("{0}/{1}", Constants.C_BUNDLE_SCRIPTS_BASE_PATH, "prevu-tvboardpage"))
<script type="text/javascript">
var C_CREATE_RESOURCE_URL = '@Html.Raw(Url.Action("Edit", "PeopleResource", new { resourceId = Guid.Empty, teamId = "_rpcmnt0_", categoryId = "_rpcmnt1_", noAdjust = "true", start = "_rpcmnt2_", end = "_rpcmnt3_" }))';
var teamId = '@(!Guid.Empty.Equals(Model.Id) ? Model.Id.ToString() : "")';
var _teamPageState = null;
var forecastGraphDataSection = "ForecastGraphWidget";
var teamResourcesDataSection = "TeamResourcesWidget";
var capacityPlanningDataSection = "CapacityPlanningWidget";
var forecastGraphPrefKey = "ForecastGraphCollapsed";
var teamResourcesPrefKey = "TeamResourcesCollapsed";
var capacityPlanningPrefKey = "CapacityPlanningCollapsed";
var getTeamResourcesPath = '@Url.Action("GetTeamResources", "Team")';
function getSelectedTeamId() {
return teamId;
}
function noTeamSelected() {
return (!teamId || (teamId.length < 1));
}
function initPanels() {
var tasks = [];
tasks.push(loadUserPagePreferencesAsync(null, '@(model.DisplayMode.PageKey)'));
return $.when.apply($, tasks)
.then(function () {
var pageSections = arguments[0];
initTeamForecastWidgets(pageSections[forecastGraphDataSection], pageSections[capacityPlanningDataSection]);
initTeamResourcesWidget(pageSections[teamResourcesDataSection]);
initCapacityPlanner(pageSections[capacityPlanningDataSection]);
})
.then(null, function (response) {
console.error('An error occurred while loading page preferences');
showErrorModal();
});
}
function initTeamResourcesWidget(prefs) {
var chevron = $("#teamResources").find(".panel.collapsible-horizontal").find("a");
$(chevron).on('click', function () {
toggleHorizontalResourcesPanelCollapse(this, false);
});
if (prefs && (prefs.length > 0)) {
for(var index = 0; index < prefs.length; index++) {
if (prefs[index].Key === teamResourcesPrefKey) {
var prefValue = prefs[index].Value;
if (prefValue !== undefined) {
var isCollapsed = isHorizontalPanelCollapsed(chevron);
if (prefValue !== isCollapsed) {
toggleHorizontalResourcesPanelCollapse(chevron, true);
}
}
break;
}
}
}
var teamId = getSelectedTeamId();
$("#TeamInfo").teamResourcesBrowser({
teamId: teamId,
createItemButtonPlaceholder: 'teamResourcesNewBtn',
allowCreateItem: @(SecurityManager.CheckSecurityObjectPermission(Areas.Resources, AccessLevel.Write) ? "true" : "false"),
allowEditItem: @(SecurityManager.CheckSecurityObjectPermission(Areas.RD_ResourceInformation, AccessLevel.Write) ? "true" : "false"),
allowDeleteItem: @(SecurityManager.CheckSecurityObjectPermission(Areas.RD_ResourceInformation, AccessLevel.Write) ? "true" : "false"),
allowChangeExpCat: @(SecurityManager.CheckSecurityObjectPermission(Areas.RD_ResourceInformation, AccessLevel.Write) ? "true" : "false"),
createItemUrl: '@Url.Action("Edit", "PeopleResource")',
viewItemUrl: '@Url.Action("Details", "PeopleResource")',
editItemUrl: '@Url.Action("Edit", "PeopleResource")',
deleteItemUrl: '@Url.Action("Delete", "PeopleResource")',
changeExpCatItemUrl: '@Url.Action("ChangeResourceExpenditure", "PeopleResource")',
editItemModalId: 'editPeopleResourceModal',
changeExpCatModalId: 'PeopleResourceChangeExpCatModal'
});
}
function initTeamForecastWidgets(prefs, cPprefs) {
var chevron = $("#teamForecastGraphPlaceholder").find(".panel.collapsible-vertical").find("a");
$(chevron).on('click', function () {
toggleVerticalPanelCollapse(this, false);
});
var cPCollapsed= false;
if (cPprefs && (cPprefs.length > 0)) {
for(var index = 0; index < cPprefs.length; index++) {
if (cPprefs[index].Key === capacityPlanningPrefKey) {
cPCollapsed = cPprefs[index].Value;
break;
}
}
}
if (prefs && (prefs.length > 0)) {
for(var index = 0; index < prefs.length; index++) {
if (prefs[index].Key === forecastGraphPrefKey) {
var prefValue = prefs[index].Value;
if (prefValue !== undefined) {
var chevron = $("#teamForecastGraphPlaceholder").find(".panel.collapsible-vertical").find("a");
var isCollapsed = isHorizontalPanelCollapsed(chevron);
if (prefValue !== isCollapsed) {
$(chevron).toggleClass("collapsed");
if (cPCollapsed){
// $('#capacityPlanner').find('.panel-body').slideUp();
isZone2Row1Collapsed=true;
}
$(chevron).parents('.panel').find(".row.padding-sm").slideUp();
isZone1Row1Collapsed=true;
}
}
break;
}
}
}
reAlignDivs();
}
function initCapacityPlanner(prefs) {
var chevron = $("#capacityPlanner").find(".otherside").find("a");
$(chevron).on('click', function () {
toggleHorizontalCapacityPanelCollapse(this, false);
});
if (prefs && (prefs.length > 0)) {
for(var index = 0; index < prefs.length; index++) {
if (prefs[index].Key === capacityPlanningPrefKey) {
var prefValue = prefs[index].Value;
if (prefValue !== undefined) {
var isCollapsed = isHorizontalPanelCollapsed(chevron);
if (prefValue !== isCollapsed) {
toggleHorizontalCapacityPanelCollapse(chevron, true);
}
}
break;
}
}
}
initCapacityPlannerButtons();
};
function initCapacityPlannerButtons() {
// Init widget top buttons
var topBtnLockerOpts = {
timeout: 0
};
var opts;
var widgetTopButtons = $('div#arrowHolder');
if (widgetTopButtons) {
opts = $.extend(topBtnLockerOpts, { click: increaseCapacity });
widgetTopButtons.find('a[data-type=increaseCapacity]').buttonLocker(opts);
opts = $.extend(topBtnLockerOpts, { click: decreaseCapacity });
widgetTopButtons.find('a[data-type=decreaseCapacity]').buttonLocker(opts);;
opts = $.extend(topBtnLockerOpts, { click: resetCapacity });
widgetTopButtons.find('a[data-type=resetCapacity]').buttonLocker(opts);;
opts = $.extend(topBtnLockerOpts, { click: resetEntireCapacity });
widgetTopButtons.find('a[data-type=resetEntireCapacity]').buttonLocker(opts);;
}
}
function isHorizontalPanelCollapsed(activeA) {
return $(activeA).hasClass("collapsed");
}
function toggleHorizontalCapacityPanelCollapse (activeA, noDelay) {
$(activeA).toggleClass("collapsed");
var isCollapsed = $(activeA).hasClass("collapsed");
var graphChevron = $("#teamForecastGraphPlaceholder").find(".panel.collapsible-vertical").find("a");
var graphCollapsed = $(graphChevron).hasClass("collapsed");
if (isCollapsed) {
var panelBody = $(activeA).closest(".panel-compact").find(".panel-body");
var panelBodyHeight = panelBody.height();
$('#capacityPlanner').removeClass("col-lg-5").addClass("col-lg-1");
$('#teamForecastGraphPlaceholder').removeClass("col-lg-7").addClass("col-lg-11");
$(activeA).closest(".panel-compact").find(".row.padding-sm").fadeOut(noDelay ? 0 : 600, function () {
panelBody.height(panelBodyHeight);
$(activeA).find("span, i").fadeOut(noDelay ? 0 : 300, function () {
$(activeA).closest(".panel-heading").css("padding-bottom", "28px");
$(activeA).closest(".panel-compact").find(".vertical-text").closest("div")
.width(panelBodyHeight - 20 - 20).show();
$('#jq-flot-graph-FD').width($('#teamForecastGraphPlaceholder').width() -20);
updateCapacityWidgetHeight();
if(graphCollapsed){
// $('#capacityPlanner').find('.panel-body').slideUp();
isZone2Row1Collapsed=true;
}
});
});
}
else
{
// Panel should be expanded
$(activeA).closest(".panel-compact").find(".vertical-text").closest("div").fadeOut(noDelay ? 0 : 200, function() {
$('#teamForecastGraphPlaceholder').removeClass("col-lg-11").addClass("col-lg-7");
$('#capacityPlanner').removeClass("col-lg-1").addClass("col-lg-5");
setTimeout(function () {
$(activeA).closest(".panel-compact").find(".row.padding-sm").show(function () {
$('#capacityPlanner').find('.panel-body').slideDown();
isZone2Row1Collapsed=false;
$(activeA).closest(".panel-heading").css("padding-bottom", "");
$(activeA).find("i, span").fadeIn(noDelay ? 0 : 400);
$('#jq-flot-graph-FD').width($('#teamForecastGraphPlaceholder').width() -20);
$('#arrowHolder').find('i').show();
setTimeout(function () {
if($('#simpleModeForm').height() == 0)
$("#capacity-container").height(275);
else
updateCapacityWidgetHeight();
}, 600);
});
}, noDelay ? 0 : 400);
});
}
if (typeof redrawFreezeColumn === "function") {
// Redraw freeze column for forecast table (see _forecastDashboard)
redrawFreezeColumn();
}
// Saving preferences
var prefs = [];
prefs.push({
Key: capacityPlanningPrefKey,
Value: isCollapsed
});
saveUserPagePreferences(prefs, capacityPlanningDataSection); //reactivate this
}
function toggleHorizontalResourcesPanelCollapse (activeA, noDelay) {
$(activeA).toggleClass("collapsed");
var isCollapsed = $(activeA).hasClass("collapsed");
if (isCollapsed) {
var panelBody = $(activeA).closest(".panel-compact").find(".panel-body");
var panelBodyHeight = panelBody.height();
$(activeA).closest(".panel-compact").find(".row").fadeOut(noDelay ? 0 : 600, function () {
panelBody.height(panelBodyHeight);
$(activeA).find("span, i").fadeOut(noDelay ? 0 : 300, function () {
$('#teamResourcesNewBtn').hide();
$('#teamNonProjectTimeBtn').hide();
$('#TeamInfo').hide();
$(activeA).closest(".panel-heading").css("padding-bottom", "28px");
$('#teamResources').removeClass("col-lg-4").addClass("col-lg-1");
$('#teamCalendar').removeClass("col-lg-8").addClass("col-lg-11");
$(activeA).closest(".panel-compact").find(".vertical-text").closest("div")
.width(panelBodyHeight - 20 - 20).show();
$("#teamResources-container").height(190);
});
});
}
else
{
// Panel should be expanded
$(activeA).closest(".panel-compact").find(".vertical-text").closest("div").fadeOut(noDelay ? 0 : 200, function() {
$('#teamCalendar').removeClass("col-lg-11").addClass("col-lg-8");
$('#teamResources').removeClass("col-lg-1").addClass("col-lg-4");
setTimeout(function () {
$(activeA).closest(".panel-compact").find(".row").show(function () {
$(activeA).closest(".panel-heading").css("padding-bottom", "");
$(activeA).find("i, span").fadeIn(noDelay ? 0 : 400);
$(activeA).closest(".panel-compact").find(".row").css('padding-top', '0!important');
});
}, noDelay ? 0 : 400);
$('#teamResourcesNewBtn').show();
var isHidden = $('#teamNonProjectTimeBtn').data('isHidden');
if(!isHidden){
$('#teamNonProjectTimeBtn').show();
}
$('#TeamInfo').show();
setTimeout(function () {
$("#teamResources-container").height($('#TeamInfo').height());
}, 800);
});
}
// Saving preferences
var prefs = [];
prefs.push({
Key: teamResourcesPrefKey,
Value: isCollapsed
});
saveUserPagePreferences(prefs, teamResourcesDataSection);
}
var isZone1Row1Collapsed = false;
var isZone2Row1Collapsed = false;
var isZone2Row2Collapsed = false;
var Zone1Row1= $(".zone1row1");
var Zone1Row1Control= $(".zone1row1control");
var Zone2Row1=$(".zone2row1");
var Zone2Row1Control=$(".zone2row1control");
var Zone1Row2=$(".zone1row2");
var Zone1Row2Control=$(".zone1row2control");
var Zone2Row2=$('.zone2row2');
var Zone2Row2Control=$('.zone2row2control');
var Zone1Row3=$('.zone1row3');
var Zone1Row3Control=$('.zone1row3control');
function setDivHomes(){
Zone1Row1Control.appendTo(Zone1Row1);
Zone2Row1Control.appendTo(Zone2Row1);
Zone1Row2Control.appendTo(Zone1Row2);
Zone2Row2Control.appendTo(Zone2Row2);
Zone1Row3Control.appendTo(Zone1Row3);
}
function reAlignDivs(){
setDivHomes();
// move all zone1 controls up 1
if (isZone1Row1Collapsed )
{
Zone1Row2Control.appendTo(Zone1Row1);
Zone1Row3Control.appendTo(Zone1Row2);
} else {
if (Zone1Row2Control.length === 0)
{
Zone1Row3Control.appendTo(Zone1Row2);
}
}
}
function toggleVerticalPanelCollapse (activeA, noDelay) {
var isCollapsed = !$(activeA).hasClass("collapsed");
$(activeA).toggleClass("collapsed");
if (isCollapsed) {
$(activeA).parents('.panel').find(".row.padding-sm").slideUp();
// $('#capacityPlanner').find('.panel-body').slideUp();
isZone1Row1Collapsed=true;
}
else
{
// Panel should be expanded
$(activeA).parents('.panel').find(".row.padding-sm").slideDown();
$('#capacityPlanner').find('.panel-body').slideDown();
isZone2Row1Collapsed=false;
isZone1Row1Collapsed=false;
}
// Saving preferences
var prefs = [];
prefs.push({
Key: forecastGraphPrefKey,
Value: isCollapsed
});
saveUserPagePreferences(prefs, forecastGraphDataSection);
reAlignDivs(activeA,isCollapsed);
}
function loadData() {
loadTeamResourcesData();
loadCapacityPlanner();
loadForecastPanel();
}
function loadActivityCalendar(eventName, eventData) {
triggerBroadcastFromRootScope(eventName, eventData);
}
function loadTeamResourcesData() {
$('#teamResourcesLoader').show();
$("#TeamInfo").html('');
if (noTeamSelected()) {
// No team id specified
$("#TeamInfo").teamResourcesBrowser('setData', null);
$('#teamResourcesLoader').hide();
return;
}
var teamResourcesLoadUrl = getTeamResourcesPath;
$.post(teamResourcesLoadUrl, { teamId: teamId }, function (data) {
if (data) {
var dataPackage = {};
dataPackage.resources = data;
$("#TeamInfo").teamResourcesBrowser('setData', dataPackage);
$('#teamResourcesLoader').hide();
}
});
}
init.push(function () {
saveLastPageVisited(window.location.pathname + window.location.search);
// Capacity planner controls
var options = {
format: 'm/d/yyyy',
startDate: '@Constants.MIN_SELECTABLE_DATE',
endDate: '@Constants.MAX_SELECTABLE_DATE'
};
$('#bs-datepicker-rangePlanSimple').datepicker(options);
$('#capacityExpCat').select2();
// load widgets
initPanels().then(function () {
loadData();
})
.then(null, function (response) {
console.error('An error occurred while loading data for team board.');
showErrorModal();
});
});
function formatPCDate(jsonDate) {
if (jsonDate == null || jsonDate === "")
return "";
var dt = new Date(parseInt(jsonDate.replace("/Date(", "").replace(")/", ""), 10));
return (dt.getMonth() + 1) + "/" + dt.getDate() + "/" + dt.getFullYear();
}
function loadCapacityPlanner() {
if (!teamId || (teamId.length < 1))
return;
$('#capacityPlannerLoader').show();
$('#capacityPlannerContent').hide();
var id = teamId;
var expCatDropDown = $('#capacityExpCat');
var tbl = $("#simpleModeGrid");
var noPositions = true;
$.ajax({
url: '/Team/GetPlanCapacitySimpleMode',
type: 'post',
data: { teamId: id },
success: function (data) {
expCatDropDown.empty();
tbl.empty();
tbl.append($("<thead><tr><th class=\"autowidth\">Expenditure Category</th><th class=\"autowidth\">Start Date</th><th class=\"autowidth\">End Date</th><th class=\"smallCol\"></th></tr></thead>"));
var selInPlanHtml = $('<optgroup />').prop('label', "Categories in Plan").appendTo(expCatDropDown);
var selAddHtml = $('<optgroup />').prop('label', "Add Category").appendTo(expCatDropDown);
$.each(data["data"], function () {
$("<option />").val(this.Id).text(this.Name).appendTo(this.InPlan === true ? selInPlanHtml : selAddHtml);
if (this.Positions != null) {
for (var ctr = 0; ctr < this.Positions.length; ctr++) {
var categoryId = this.Id;
var pos = this.Positions[ctr];
var row = $('<tr></tr>');
row.append($("<td></td>").text(this.Name));
row.append($("<td></td>").text(formatPCDate(pos.StartDate)));
row.append($("<td></td>").text(formatPCDate(pos.EndDate)));
var rowButtons = $("<td></td>");
row.append(rowButtons);
var currentBtn = null;
var lockerOpts = null;
if (pos.Need > 0) {
@if (SecurityManager.CheckSecurityObjectPermission(Areas.RD_ResourceInformation, AccessLevel.Write))
{
<text>
lockerOpts = {
click: addPeopleResource,
params: {
teamId: id,
expCatId: categoryId,
startDate: pos.StartDateMs,
endDate: pos.EndDateMs > 0 ? pos.EndDateMs : null
},
timeout: 0
}
currentBtn = $("<a class='btn btn-xs btn-success' title='Fill Position' href='javascript:void(0)' style='margin-right:4px;'><i class='fa fa-plus'></i></a>");
rowButtons.append(currentBtn);
currentBtn.buttonLocker(lockerOpts);
</text>
}
lockerOpts = {
click: removeCapacityPosition,
params: {
startDate: formatPCDate(pos.StartDate),
endDate: formatPCDate(pos.EndDate),
expCatId: categoryId,
value: -1,
isPermanent: (pos.EndDate == null)
},
timeout: 0
};
currentBtn = $("<a class='btn btn-xs btn-danger' title='Remove Position' href='javascript:void(0)'><i class='fa fa-times'></i></a>");
rowButtons.append(currentBtn);
currentBtn.buttonLocker(lockerOpts);
} else {
lockerOpts = {
click: showFillDecrease,
params: {
startDate: formatPCDate(pos.StartDate),
teamId: id,
expCatId: categoryId
},
timeout: 0
};
currentBtn = $("<a class='btn btn-xs btn-info' title='Fill Decrease' href='javascript:void(0)' style='margin-right:4px;'><i class='fa fa-minus'></i></a>");
rowButtons.append(currentBtn);
currentBtn.buttonLocker(lockerOpts);
lockerOpts = {
click: removeCapacityPosition,
params: {
startDate: formatPCDate(pos.StartDate),
endDate: formatPCDate(pos.EndDate),
expCatId: categoryId,
value: 1,
isPermanent: (pos.EndDate == null)
},
timeout: 0
};
currentBtn = $("<a class='btn btn-xs btn-danger' title='Remove Position' href='javascript:void(0)'><i class='fa fa-times'></i></a>");
rowButtons.append(currentBtn);
currentBtn.buttonLocker(lockerOpts);
}
tbl.append(row);
noPositions = false;
}
}
});
if (noPositions === true) {
tbl.append($("<tr><td colspan=\"4\">No open positions</td></tr>"));
}
$('#capacityExpCat').select2({
allowClear: true
});
$('#capacityPlannerLoader').hide();
$('#capacityPlannerContent').show();
updateCapacityWidgetHeight();
},
error: function (ret) {
$('#capacityPlannerLoader').hide();
$('#capacityPlannerContent').show();
showErrorModal("@Constants.ERROR_GENERAL_TITLE_TEMPLATE", ret.statusText);
}
});
}
// Updates height of the Capacity planner widget to fit it's content
function updateCapacityWidgetHeight() {
var plannerOwnHeight = $('#capacityPlannerContent').height() + 9;
var graphContainerHeight = $('#graph-container').height();
var newWidgetHeight = Math.max(plannerOwnHeight, graphContainerHeight);
$('#capacity-container').height(newWidgetHeight);
}
function addPeopleResource(elem, params) {
if (!elem)
return;
if (!params || !params.teamId || !params.expCatId) {
elem.buttonLocker('enable');
throw "addPeopleResource: required arguments are empty";
}
blockUI();
var url = C_CREATE_RESOURCE_URL
.replace(/_rpcmnt0_/g, params.teamId)
.replace(/_rpcmnt1_/g, params.expCatId)
.replace(/_rpcmnt2_/g, params.startDate)
.replace(/_rpcmnt3_/g, params.endDate);
$('#editPeopleResourceForm').load(url, function () {
var form = $("#editPeopleResourceForm form");
$.validator.unobtrusive.parse(form);
$('#editPeopleResourceModal').on('show.bs.modal', function (e) {
if ($(e.target).attr('id') === 'editPeopleResourceModal') {
initPeopleResourceEditForm();
form.find(".validation-summary-errors").hide();
}
});
$('#editPeopleResourceForm form').data("url", url);
unblockUI();
elem.buttonLocker('enable');
$('#editPeopleResourceModal').modal('show');
});
}
function showFillDecrease(elem, params) {
if (!elem)
return;
if (!params || !params.teamId || !params.expCatId) {
elem.buttonLocker('enable');
throw "showFillDecrease: required arguments are empty";
}
$("#fillCapacityDecreaseResourceId").empty();
$('#fillCapacityDecreaseModal').modal('show');
blockUI();
$.ajax({
url: "/Team/GetResourcesForFillDecrease" + '?teamId=' + params.teamId + '&categoryId=' + params.expCatId + '&dateToFire=' + params.startDate,
type: 'post',
data: {},
success: function (data) {
$("#fillCapacityDecreaseEndDate").text(params.startDate);
var resourcesExist = false;
$.each(data["data"], function () {
resourcesExist = true;
$("<option />").val(this.Id).text(this.Name + (this.EndDate == null ? " (permanent)" : " (contract till " + formatPCDate(this.EndDate) + ")")).appendTo($("#fillCapacityDecreaseResourceId"));
});
$('#fillCapacityDecreaseResourceId').select2({
allowClear: true
});
if (resourcesExist === true)
$("#dvNoResourcesWarning").hide();
else
$("#dvNoResourcesWarning").show();
unblockUI();
$(elem).buttonLocker('enable');
},
error: function (ret) {
console.log(ret);
unblockUI();
$(elem).buttonLocker('enable');
showErrorModal("@Constants.ERROR_GENERAL_TITLE_TEMPLATE", ret.statusText);
}
});
}
function fillDecreaseSubmit() {
if ($("#fillCapacityDecreaseForm").valid() === false)
return;
blockUI();
$.ajax({
url: "/Team/FillDecreaseSubmit" + '?resourceId=' + $("#fillCapacityDecreaseResourceId").val() + '&endDate=' + $("#fillCapacityDecreaseEndDate").text(),
type: 'post',
data: {},
success: function (data) {
$('#fillCapacityDecreaseModal').modal('hide');
loadTeamResourcesData();
loadForecastPanel();
loadCapacityPlanner();
unblockUI();
loadActivityCalendar('teamBoard.plannedCapacityChanged', {});
},
error: function (ret) {
console.log(ret);
unblockUI();
showErrorModal("@Constants.ERROR_GENERAL_TITLE_TEMPLATE", ret.statusText);
}
});
}
function increaseCapacity(elem, params) {
if (!elem)
return;
if ($("#simpleModeForm").valid() === false) {
$(elem).buttonLocker('enable');
return;
}
var callback = function () {
$(elem).buttonLocker('enable');
};
blockUI();
changeCapacity($('#capacityStartDate').val(), $('#capacityEndDate').val(), $('#capacityExpCat').val(), $('#capacityAmount').val(), $('#permanent').prop('checked'), callback);
}
function decreaseCapacity(elem, params) {
if (!elem)
return;
if ($("#simpleModeForm").valid() === false) {
$(elem).buttonLocker('enable');
return;
}
var callback = function () {
$(elem).buttonLocker('enable');
};
blockUI();
changeCapacity($('#capacityStartDate').val(), $('#capacityEndDate').val(), $('#capacityExpCat').val(), -$('#capacityAmount').val(), $('#permanent').prop('checked'), callback);
}
function removeCapacityPosition(elem, params) {
if (!elem)
return;
if (!params || !params.startDate || !params.expCatId || !params.value || (params.isPermanent === undefined)) {
elem.buttonLocker('enable');
throw "removeCapacityPosition: required arguments are empty";
}
var callback = function () {
$(elem).buttonLocker('enable');
};
changeCapacity(params.startDate, params.endDate, params.expCatId, params.value, params.isPermanent, callback);
}
function changeCapacity(startDate, endDate, expenditureCategory, value, permanent, callback) {
$.ajax({
url: "/Team/ChangeCapacity" + '?startDate=' + startDate + '&endDate=' + endDate + '&expenditureCategoryId=' + expenditureCategory + '&capacityValue=' + value + '&teamId=' + getSelectedTeamId() + '&permanent=' + permanent,
type: 'post',
data: {},
success: function (data) {
loadCapacityPlanner();
loadForecastPanel();
unblockUI();
if (callback && (typeof callback === 'function')) {
callback();
}
loadActivityCalendar('teamBoard.plannedCapacityChanged', {});
},
error: function (ret) {
console.log(ret);
unblockUI();
if (callback && (typeof callback === 'function')) {
callback();
}
showErrorModal("@Constants.ERROR_GENERAL_TITLE_TEMPLATE", ret.statusText);
}
});
}
function resetCapacity(elem, params) {
if (!elem)
return;
if ($("#simpleModeForm").valid() === false) {
$(elem).buttonLocker('enable');
return;
}
blockUI();
$.ajax({
url: "/Team/ResetCapacity" + '?startDate=' + $('#capacityStartDate').val() + '&endDate=' + $('#capacityEndDate').val() + '&expenditureCategoryId=' + $('#capacityExpCat').val() + '&teamId=' + getSelectedTeamId() + '&permanent=' + $('#permanent').prop('checked'),
type: 'post',
data: {},
success: function (ret) {
if (ret.Result !== true) {
$(elem).buttonLocker('enable');
unblockUI();
showErrorModal("@Constants.ERROR_GENERAL_TITLE_TEMPLATE", ret.data);
} else {
$(elem).buttonLocker('enable');
loadCapacityPlanner();
loadForecastPanel();
unblockUI();
loadActivityCalendar('teamBoard.plannedCapacityChanged', {});
}
},
error: function (ret) {
console.log(ret);
$(elem).buttonLocker('enable');
unblockUI();
showErrorModal("@Constants.ERROR_GENERAL_TITLE_TEMPLATE", ret.statusText);
}
});
}
function resetEntireCapacity(elem, params) {
if (!elem)
return;
if ($("#simpleModeForm").valid() === false) {
$(elem).buttonLocker('enable');
return;
}
try
{
bootbox.dialog({
title: "Reset Planned Capacity",
message: '<div class="row"> ' +
'<div class="col-md-12"> ' +
'<p> Are you sure you want to reset Planned Capacity and make it equal to Actual Capacity? </p> ' +
'</div>' +
'<div class="col-md-10 col-md-offset-1"> ' +
'<div class="radio"> <label for="resetAllDates-0"> <input type="radio" name="resetAllDates" id="resetAllDates-0" value="0" checked="checked"> Use currently selected date range </label> </div>' +
'<div class="radio"> <label for="resetAllDates-1"> <input type="radio" name="resetAllDates" id="resetAllDates-1" value="1"> Reset entire capacity </label> </div> ' +
'</div>' +
'</div>',
buttons: {
cancel: {
label: "Cancel",
className: "btn-default",
callback: function () {
}
},
main: {
label: "Reset",
className: "btn-primary",
callback: function () {
var answer = $("input[name='resetAllDates']:checked").val() === "1";
var stDate = answer === true ? "1/1/1753" : $('#capacityStartDate').val();
var enDate = answer === true ? "1/1/2100" : $('#capacityEndDate').val();
var prmt = answer === true ? "true" : $('#permanent').prop('checked');
blockUI();
$.ajax({
url: "/Team/ResetCapacity" + '?startDate=' + stDate + '&endDate=' + enDate + '&teamId=' + getSelectedTeamId() + '&permanent=' + prmt,
type: 'post',
data: {},
success: function (ret) {
if (ret.Result !== true) {
showErrorModal("@Constants.ERROR_GENERAL_TITLE_TEMPLATE", ret.data);
unblockUI();
} else {
loadCapacityPlanner();
loadForecastPanel();
unblockUI();
loadActivityCalendar('teamBoard.plannedCapacityChanged', {});
}
},
error: function (ret) {
console.log(ret);
unblockUI();
showErrorModal("@Constants.ERROR_GENERAL_TITLE_TEMPLATE", ret.statusText);
}
});
}
}
}
});
}
finally {
$(elem).buttonLocker('enable');
}
}
function switchPermanent(id) {
if ($('#permanent').prop('checked')) {
$('#simpleModeForm .enddate').css('visibility', 'hidden');
$('#simpleModeForm .enddatespan').hide();
} else {
$('#simpleModeForm .enddate').css('visibility', 'visible');
$('#simpleModeForm .enddatespan').show();
}
}
function loadForecastPanel() {
if (!teamId || (teamId.length < 1))
return;
$('#forecastTableLoader').show();
$("#forecastBlock").html('');
//reset forecast block menu
var paramsObj = {
teamId: teamId,
mode: 'team'
};
var id = teamId;
var pageModel = '@Model.GetType().Name';
var loadUrl = '@Url.Action("Index", "ForecastDashboard")?menuId=visibilitydropdown&pageModel=' + pageModel + '&additionalFilters=' + JSON.stringify(paramsObj);
$("#forecastBlock")
.load(loadUrl, function (response, status, xhr) {
if (status === "error") {
$('#forecastTableLoader').hide();
showErrorModal('Loading error', 'We are sorry but there was an error, please try again later.');
} else {
$(".fcboard-criteria-select2").select2();
$('#forecastTableLoader').hide();
initForecastDashboard();
}
});
}
function OpenInNewWindow() {
var url = '@Url.Action("Index", "CapacityManagement")' + '?id=' + getSelectedTeamId();
window.open(url);
}
function viewNonProjectTime() {
var url = '@Url.Action("NonProjectTime", "PeopleResource")' + '?teamId=' + getSelectedTeamId();
window.location.href = url;
}
</script>
}
<div class="container-fluid" id="team-container">
<div class="row animated">
<div class="col-sm-12 col-lg-7 zone1row1" id="teamForecastGraphPlaceholder">
<div class="panel panel-white panel-compact otherside collapsible-vertical zone1row1control">
<div class="panel-heading">
<span class="panel-title ui-expander">
<a data-target="#graph-container">
<i class="panel-title-icon fa fa-bar-chart-o"></i><span>Projects by Status</span>
</a>
</span>
</div>
<div class="panel-body table-light" id="graph-container">
<div class="row padding-sm" style="padding-left: 20px!important; padding-right: 20px!important;">
@{Html.RenderPartial("_chart", Model);
}
</div>
</div>
</div>
</div>
<div class="col-sm-12 col-lg-5 zone2row1" id="capacityPlanner">
<div class='panel panel-white panel-compact collapsible-horizontal zone2row1control'>
<div class='panel-heading'>
<span class='panel-title ui-expander otherside'>
<a data-target="#capacity-container">
<i class="panel-title-icon fa fa-tasks"></i><span>Capacity Planning</span>
</a>
</span>
</div>
<div class='panel-body table-light' style="min-height:275px;" id="capacity-container">
<div class="vertical-text" style="display: none; margin-top: 20px; margin-left: 68%">
<i class="panel-title-icon fa fa-tasks"></i>
<span>Capacity Planning</span>
</div>
<div class="row padding-sm" style="padding-left: 20px!important; padding-right: 20px!important;">
<div id="capacityPlannerContent" style="display:none;min-height:275px;">
<form id="simpleModeForm" name="simpleModeForm">
<div class="row padding-sm">
<div class="col-xs-12 col-sm-12 col-md-5">
<div class="form-group no-margin-hr">
<label class="control-label">Expenditure Category</label>
<select id="capacityExpCat" class="form-control" name="capacityExpCat" data-key="expCategory" data-val="true" data-val-required="Required"></select>
</div>
</div>
<div class="col-xs-12 col-sm-12 col-md-7">
<div class="form-group no-margin-hr">
<label class="control-label">Start<span class="enddatespan">/End</span> Date</label>
<div class="input-daterange input-group" id="bs-datepicker-rangePlanSimple">
<input class="form-control" id="capacityStartDate" name="capacityStartDate" type="text" value="@(new DateTime(DateTime.Today.Year, DateTime.Today.AddMonths(1).Month, 1).ToShortDateString())" data-val="true" data-val-required="Required">
<span class="field-validation-valid" data-valmsg-for="capacityStartDate" data-valmsg-replace="true"></span>
<span class="input-group-addon enddate">to</span>
<input class="form-control enddate" id="capacityEndDate" name="capacityEndDate" type="text" value="@(new DateTime(DateTime.Today.Year + 1, DateTime.Today.AddMonths(1).Month, 1).AddDays(-1).ToShortDateString())" data-val="true" data-val-required="Required">
<span class="field-validation-valid" data-valmsg-for="capacityEndDate" data-valmsg-replace="true"></span>
</div>
<div class="no-margin-hr" style="margin-top:3px;">
<input type="checkbox" name="permanent" id="permanent" onclick="switchPermanent()" />&nbsp;<label for="permanent" class="nonStyled">Permanent</label>
</div>
</div>
</div>
<div class="col-xs-3 col-sm-3 col-md-2">
<div class="form-group no-margin-hr">
<label class="control-label" title="Number of Resources">Resources</label>
<input id="capacityAmount" name="capacityAmount" class="form-control" data-val="true" data-val-required="Required" data-val-number="Should be a number"
data-val-range="Should be between 1 and 100." data-val-range-max="100" data-val-range-min="1" data-val-integer="Should be an integer" value="1" />
<span class="field-validation-valid" data-valmsg-for="capacityAmount" data-valmsg-replace="true"></span>
</div>
</div>
<div class="col-xs-9 col-sm-9 col-md-10">
<div class="form-group no-margin-hr" id="arrowHolder">
<label class="control-label">&nbsp;</label><br />
<a class="btn btn-success" data-type="increaseCapacity" title="Increase Capacity"><i class="fa fa-arrow-up"></i></a>
<a class="btn btn-info" data-type="decreaseCapacity" title="Decrease Capacity"><i class="fa fa-arrow-down "></i></a>
<a class="btn btn-warning" data-type="resetCapacity" title="Reset Capacity"><i class="fa fa-undo"></i></a>
&nbsp;
<a class="btn btn-danger" data-type="resetEntireCapacity" title="Reset All Categories">Reset All</a>
</div>
</div>
</div>
</form>
<table id="simpleModeGrid" class="table table-striped dataTable-tight"></table>
<div id="fillCapacityDecreaseModal" class="modal fade" tabindex="-1" role="dialog" style="display: none;" data-backdrop="static">
<form id="fillCapacityDecreaseForm" name="fillCapacityDecreaseForm">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title">Fill Capacity Decrease</h4>
</div>
<div class="modal-body">
<p>
Please select the resource to fill decrease in Planned Capacity.
<br />
The resource will be set an End Date of <span id="fillCapacityDecreaseEndDate"></span>
</p>
<div class="alert" id="dvNoResourcesWarning">
There are no resources to fill decrease in Planned Capacity with given date - resources should be active and start at least one week before fill decrease date.
</div>
<select id="fillCapacityDecreaseResourceId" class="form-control" name="fillCapacityDecreaseResourceId" data-val="true" data-val-required="Please select a resource to fill capacity decrease"></select>
<span class="field-validation-valid" data-valmsg-for="fillCapacityDecreaseResourceId" data-valmsg-replace="true"></span>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" onclick="fillDecreaseSubmit();">Fill Decrease</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
<div id="capacityPlannerLoader" class="loadRotator" style="min-height:275px;">
<span>
<img class="valign-middle" src="@Url.Content("~/Content/images/loadFA.gif")" />&nbsp;&nbsp;loading...
</span>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-12 col-lg-8 zone1row2" id="teamCalendar">
@if (SecurityManager.CheckSecurityObjectPermission(Areas.ActivityCalendar, AccessLevel.Read))
{
<div class='panel panel-white panel-compact zone1row2control' data-section="capacityManagementView">
<div class='panel-heading'>
<span class='panel-title'><i class="panel-title-icon fa fa-calendar"></i>Team Calendar</span>
<div class="btn-group btn-group-xs pull-right" id="divCalendarMenu">
<button class="btn btn-info dropdown-toggle" type="button" data-toggle="dropdown"><i class="fa fa-bars"></i>&nbsp;<i class="fa fa-caret-down"></i></button>
<ul class="dropdown-menu-calendar dropdown-menu dropdown-menu-right calendar-options-menu" id="visibilitydropdown_calendar"></ul>
</div>
<div class="pull-right" style="padding-right: 20px;">
<a class="noshevron no-expand" href="javascript:OpenInNewWindow()">open in new window</a>
</div>
</div>
<div class='panel-body table-light' id="panelTeamCalendar" style="overflow-x: auto;padding: 5px 15px;">
@Html.Partial("~/Views/ActivityCalendar/_capacityManagement.cshtml", model)
</div>
</div>}
</div>
<div class="col-sm-12 col-lg-4 zone2row2" id="teamResources">
<div class="row zone2row2control">
<div class="col-sm-12">
<div class="panel panel-white panel-compact collapsible-horizontal">
<div class="panel-heading">
<span class='panel-title ui-expander'>
<a data-target="#teamResources-container">
<i class="panel-title-icon fa fa-users"></i><span>Team Resources</span>
</a>
</span>
</div>
<div>
<div id="teamResourcesNewBtn" style="margin-right:10px;"></div>
@if (SecurityManager.CheckSecurityObjectPermission(Areas.RD_ResourceNonProjectTime, AccessLevel.Read))
{
<a class="btn btn-warning" id="teamNonProjectTimeBtn" href="@(Url.Action("NonProjectTime", "PeopleResource") + "?teamId=" + Model.Id)" @*onclick= ="viewNonProjectTime()"*@ style="margin-top:5px;">
<i class="fa fa-plus"></i>
Add/View Non-Project Time
</a>}
</div>
<div class="panel-body table-light" id="teamResources-container">
<div class="vertical-text" style="display: none; margin-top: 20px; margin-left: 68%">
<i class="panel-title-icon fa fa-users"></i>
<span>Team Resources</span>
</div>
<div class="row" id="resContainer" style="padding-left: 11px!important; padding-right: 11px!important;padding-top: 0!important;">
<div id="teamResourcesLoader" class="loadRotator" style="min-height:275px;">
<span>
<img class="valign-middle" src="@Url.Content("~/Content/images/loadFA.gif")" />&nbsp;&nbsp;loading...
</span>
</div>
<div id="TeamInfo" style="min-height:180px;overflow-x:auto;"></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row animated">
<div class="col-sm-12 col-lg-12 zone1row3" id="teamForecastTablePlaceholder">
<div class="panel panel-white panel-compact zone1row3control" data-section="teamForecastView">
<div class='panel-heading'>
<span class='panel-title'><i class="panel-title-icon fa fa-bar-chart-o"></i>Team Forecast</span>
<div class="btn-group btn-group-xs pull-right" id="divForecastMenu">
<button class="btn btn-info dropdown-toggle" type="button" data-toggle="dropdown"><i class="fa fa-bars"></i>&nbsp;<i class="fa fa-caret-down"></i></button>
<ul class="dropdown-menu dropdown-menu-right" id="visibilitydropdown"></ul>
</div>
</div>
<div class='panel-body table-light' id="forecastBlock"></div>
<div id="forecastTableLoader" class="loadRotator">
<span>
<img class="valign-middle" src="@Url.Content("~/Content/images/loadFA.gif")" />&nbsp;&nbsp;loading...
</span>
</div>
</div>
</div>
</div>
</div>
<!-- Modal -->
<div id="createScenario" class="modal fade" tabindex="-1" role="dialog" data-backdrop="static">
<div class="modal-dialog modal-lg">
<div class="modal-content" id="reloadForm">
</div> <!-- / .modal-content -->
</div> <!-- / .modal-dialog -->
</div> <!-- /.modal -->
<!-- / Modal -->
<div id="editPeopleResourceModal" class="modal fade" tabindex="-1" data-width="680" role="dialog" data-backdrop="static">
<div class="modal-content" id="editPeopleResourceForm">
</div>
</div>
<div id="PeopleResourceChangeExpCatModal" class="modal fade" tabindex="-1" data-width="680" role="dialog" data-backdrop="static">
<div class="modal-content" id="peopleResourceChangeExpCatForm">
</div>
</div>