EnVisageOnline/Main-RMO/Source/EnVisage/Views/Project/Edit.cshtml

1065 lines
57 KiB
Plaintext
Raw Permalink 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.

@using EnVisage.Code
@using EnVisage.Code.HtmlHelpers
@model EnVisage.Models.ProjectModel
@{
ViewBag.Title = Model.Id != Guid.Empty ? "Edit " + Model.Name : "Add New Project";
}
@section stylesheets
{
<link href="~/Content/stylesheets/xeditable.css" rel="stylesheet" type="text/css">
<link href="~/Content/stylesheets/fileuploads.css" rel="stylesheet" type="text/css">
<link href="~/Content/stylesheets/bootstrap-modal-bs3patch.css" rel="stylesheet" />
<link href="~/Content/stylesheets/bootstrap-modal.css" rel="stylesheet" />
}
@section Scripts
{
<script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")"></script>
<script src="@Url.Content("~/Scripts/jquery.query-object.js")"></script>
<script src="@Url.Content("~/Scripts/CustomValidation.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/sliders.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/calendarMethods.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/Plugins/ScenarioDetailsGrid.js")" type="text/javascript"></script>
@Scripts.Render("~/bundles/angular-app-modules")
<script src="@Url.Content("~/Scripts/Angular/app.js")"></script>
<script src="@Url.Content("~/Scripts/Angular/Controllers/scenarioDetailController.js")"></script>
<script src="@Url.Content("~/Scripts/Angular/Controllers/costSavingController.js")"></script>
<script src="@Url.Content("~/Scripts/Angular/Controllers/slidersGroupController.js")"></script>
<script src="@Url.Content("~/Scripts/URIjs.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/FileUploads/jquery.ui.widget.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/FileUploads/jquery.iframe-transport.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/FileUploads/jquery.fileupload.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/Plugins/UploadFile.js")" type="text/javascript"></script>
<script src="~/Scripts/jquery.collapsiblepanel.js"></script>
<script src="~/Scripts/Angular/Controllers/masterScenarioCalendarController.js"></script>
<script src="@Url.Content("~/Scripts/bootstrap-modalmanager.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/bootstrap-modal.js")" type="text/javascript"></script>
<script type="text/javascript">
$.validator.setDefaults({
ignore: '.deleted .form-control, .deleted'
});
emulateNavUrl = "/Project";
var changesMade = false;
function onDataChanged() {
changesMade = true;
}
function onDataSaved() {
changesMade = false;
}
function setupUnload() {
$(window).on('beforeunload', function () {
if (changesMade) {
return 'Edit project contains unsaved changes. Are you sure you want to leave the page?';
}
});
}
init.push(function () {
@if (Model.Id != Guid.Empty)
{
<text>
setupUnload();
$(document).on('hide.bs.modal', "div[id^='modalAddNote_']", function (e) {
if ($(e.target).attr('id').indexOf("modalAddNote_") >= 0)
return true; // close modal form
if (typeof isNoteDataChanged === 'function')
if (isNoteDataChanged()) {
if (confirm("Note editing form contains unsaved changes, do you really want to close the form?")) {
if (typeof resetNoteDataChanged === 'function') {
resetNoteDataChanged();
$("div[id^='modalAddNote_']").modal("hide");
}
};
return false; // DO NOT close modal form
}
return true; // close modal form
});
</text>
}
var json = '@ViewBag.Statuses';
if (json.length > 0) {
json = json.replace(/&quot;/g, '"');
statuses = $.parseJSON(json);
}
initControls('body');
$('#input-color').minicolors({
control: 'hue',
position: 'bottom left',
theme: 'bootstrap'
});
$(document).on('hide.bs.modal', '#createScenario', function (e) {
// skip modal hide event from datepickers
if ($(e.target).attr('id') != 'createScenario')
return true; // close modal form
// 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();
}
return true; // close modal form
};
return false; // DO NOT close modal form
}
return true; // close modal form
});
$('#@Html.IdFor(t => t.HasChildren)').change(function () {
if ($(this).is(':checked')) {
$('#detailsLegend').html('Project Part Details');
$('#fsProjectDetails .pm-container:gt(0)').show();
$('#divCopyParts').show();
$('#fsProjectDetails .pm-container').addClass('panel');
$('#fsProjectDetails .pm-container .panel-heading').show();
$('#fsProjectDetails .pm-container .pm-partName').removeClass('deleted');
$('#fsProjectDetails .pm-container .pm-partName').show();
} else {
$('#detailsLegend').html('Project Details');
$('#fsProjectDetails .pm-container:gt(0)').hide();
$('#divCopyParts').hide();
$('#fsProjectDetails .pm-container').removeClass('panel');
$('#fsProjectDetails .pm-container .panel-heading').hide();
$('#fsProjectDetails .pm-container .pm-partName').addClass('deleted');
$('#fsProjectDetails .pm-container .pm-partName').hide();
}
});
$("#@Html.ClientIdFor(t => t.CompanyId)").change(loadInternalContacts);
loadInternalContacts();
$('.pm-container .pm-delete:eq(0)').hide();
var tab = $.QueryString["ptab"];
if (tab == "notes")
$('#tabsProject a[href="#tabNotes"]').tab('show');
else if (tab == "scenarios")
$('#tabsProject a[href="#tabScenarios"]').tab('show');
else if (tab == "newscenario") {
$('#tabsProject a[href="#tabScenarios"]').tab('show');
var scenarioToLoad = '@Model.PartForScenarioId';
if (!scenarioToLoad) scenarioToLoad = '@Model.Id';
loadScenario(scenarioToLoad);
} else if (tab == 'addpart') {
if (!$('#@Html.IdFor(t => t.HasChildren)').is(':checked')) {
$('#@Html.IdFor(t => t.HasChildren)').switcher('on');
}
addPart();
@if (Model.Id != Guid.Empty)
{
<text>
StartEdit('Project', '@Model.Id', "#btnDelete", "#btnsave", "erorMsgPlaceholder", '@Model.Timestamp');
</text>
}
} else {
@if (Model.Id != Guid.Empty)
{
<text>
StartEdit('Project', '@Model.Id', "#btnDelete", "#btnsave", "erorMsgPlaceholder", '@Model.Timestamp');
</text>
}
}
$('#@Html.IdFor(t => t.HasChildren)').change();
$('#fsProjectDetails .pm-container').each(function (i, obj) {
$(obj).data('index', i);
});
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
if (e.target.hash == "#tabGeneral") {
@if (Model.Id != Guid.Empty)
{
<text>
StartEdit('Project', '@Model.Id', "#btnDelete", "#btnsave", "erorMsgPlaceholder", '@Model.Timestamp');
</text>
}
} else {
StopEdit();
RemoveLock('Project', '@Model.Id');
}
@if (Model.HasChildren)
{
<text>
if (e.target.hash == "#tabScenarios") {
resizeFreez('master-scenario-table');
}
</text>
}
});
$('[id$=Teams].select2-container').each(function (index) {
assignedTeams[$(this).attr('id')] = $(this).select2('val');
});
$('[id$=Goals].select2-container').each(function (index) {
strategicGoals[$(this).attr('id')] = $(this).select2('val');
});
$('#tabGeneral').find('input[type=checkbox],input[type=text],select,textarea').not('.skip-change').on('change', function () {
onDataChanged();
});
});
var val;
var statuses;
var assignedTeams = [];
var strategicGoals = [];
function initControls(obj) {
$("#@Html.ClientIdFor(model => model.Number)").autocomplete({
source: '@Url.Action("ProjectNumberSearch", "Project")',
minLength: 1
});
$(obj).find('.attachments').uploadFile({
uploadUrl: '@Url.Action("Upload", "Attachments")',
deleteUrl: '@Url.Action("Delete", "Attachments")',
getContentUrl: '@Url.Action("Download", "Attachments")',
uploadCallback: function() {
onDataChanged();
},
removeCallback: function () {
onDataChanged();
}
});
$(obj).find(".datepicker").datepicker({
autoclose: true,
startDate: '@Constants.MIN_SELECTABLE_DATE', // SA. ENV-1235. Disable incorrect dates input
endDate: '@Constants.MAX_SELECTABLE_DATE' // SA. ENV-1235. Disable incorrect dates input
});
$(obj).find(".forselect2").select2({
allowClear: true
}).on('change', function (e) {
$(e.currentTarget).parents('form').validate().element($(e.currentTarget));
if ($(e.currentTarget).hasClass('type')) {
var green = $($(e.currentTarget)[0].options[$(e.currentTarget)[0].selectedIndex]).data('green');
var yellow = $($(e.currentTarget)[0].options[$(e.currentTarget)[0].selectedIndex]).data('yellow');
var red = $($(e.currentTarget)[0].options[$(e.currentTarget)[0].selectedIndex]).data('red');
var greenTxt = $(e.currentTarget).parents('.panel-body').find('.ind-green');
var yellowTxt = $(e.currentTarget).parents('.panel-body').find('.ind-yellow');
var redTxt = $(e.currentTarget).parents('.panel-body').find('.ind-red');
if (redTxt != null && redTxt.val() != '') {
redTxt.val(red);
}
if (greenTxt != null && greenTxt.val() != '') {
greenTxt.val(green);
}
if (yellowTxt != null && yellowTxt.val() == '') {
yellowTxt.val(yellow);
}
reinitThresholds($(e.currentTarget), yellow, red);
}
});
$(obj).find("select.pm-teams").select2({
placeholder: "Select teams",
});
//$(obj).find("select.pm-goals").select2({
// placeholder: "Select Strategic Goals",
//});
$(obj).find('.slider-container').each(function (o, e) {
var sl = $(this).slider({
'range': 'min',
'min': 0,
'max': 100,
'value': $(this).children('.sliderValue').val(),
change: onDependentChange,
slide: onDependentSlide
});
var txt = GetProbabText($(this).children('.sliderValue').val());
sl.children('.sliderTitle').html($(this).find('.sliderValue').val() + '%' + txt);
});
$(obj).find('select.pm-status').each(function () {
$(this).on('change', function () {
CheckProbability($(this));
});
CheckProbability($(this));
});
$(obj).find('.pm-revenue input.switcher').switcher({
on_state_content: 'Yes',
off_state_content: 'No'
}).parent().css("width", "80px");
$(obj).find('#@Html.IdFor(t=>t.HasChildren)').switcher({
on_state_content: 'Yes',
off_state_content: 'No'
}).parent().css("width", "80px");
if (!$(obj).is('body')) {
var arr = [];
var gls = [];
var eContacts = $(obj).find("select.ext-contacts");
var iContacts = $(obj).find("select.int-contacts");
var sGoals = $(obj).find("select.pm-goals");
if (eContacts.length > 0 && eContacts.val() != null && eContacts.val().length > 0)
arr = arr.concat(eContacts.val());
$(obj).parents('.pm-container').data('ecurrentContacts', arr);
if (iContacts.length > 0 && iContacts.val() != null && iContacts.val().length > 0)
arr = arr.concat(iContacts.val());
$(obj).parents('.pm-container').data('icurrentContacts', arr);
if (sGoals.length > 0 && sGoals.val() != null && sGoals.val().length > 0)
gls = gls.concat(sGoals.val());
$(obj).parents('.pm-container').data('icurrentGoals', gls);
} else {
$('.pm-container').each(function () {
var eContacts = $(this).find("select.ext-contacts");
var iContacts = $(this).find("select.int-contacts");
var sGoals = $(this).find("select.pm-goals");
var arr = [];
var gls = [];
if (eContacts.length > 0 && eContacts.val() != null && eContacts.val().length > 0)
arr = arr.concat(eContacts.val());
$(this).data('ecurrentContacts', arr);
if (iContacts.length > 0 && iContacts.val() != null && iContacts.val().length > 0)
arr = arr.concat(iContacts.val());
$(this).data('icurrentContacts', arr);
if (sGoals.length > 0 && sGoals.val() != null && sGoals.val().length > 0)
gls = gls.concat(sGoals.val());
$(this).data('icurrentGoals', gls);
});
}
$(obj).find("select.pm-clientId").each(function () {
$(this).change(loadExternalContacts);
loadExternalContacts($(this));
});
$(obj).find('.pm-threshold input.switcher').switcher({
on_state_content: 'Yes',
off_state_content: 'No'
}).parent().css("width", "80px");
// SA. ENV-789
$(obj).find("div.row.pm-partName").find("input").each(function () {
$(this).on("keyup", function () { partNameChanged(this); });
$(this).on("blur", function () { partNameChanged(this); });
partNameChanged(this);
});
loadInternalContacts();
// SA. ENV-790
var expandedProjectPartId = '@(Model.ExpandedPartId.HasValue && !Model.ExpandedPartId.Value.Equals(Guid.Empty) ?
Model.ExpandedPartId.Value.ToString("N") : String.Empty)';
if (expandedProjectPartId && (expandedProjectPartId.length > 0) && (obj == "body")) {
// expand the given project part
expandProjectPart(expandedProjectPartId);
}
// SA. ENV-959. Slider now is initalizing withing $(obj) container
$(obj).find(".threshold-container").each(function (i, o) {
var parent = $(o);
var valRed = parseFloat(parent.find("input[id*='@Html.ClientIdFor(model=>model.PerformanceRedThreshold)']").val());
var valYellow = parseFloat(parent.find("input[id*='@Html.ClientIdFor(model=>model.PerformanceYellowThreshold)']").val());
var classification = parent.parent().parent().parent().parent().parent().find("select.type").find(":selected");
if (isNaN(valRed) || isNaN(valYellow)) {
valYellow = (classification.attr('data-yellow') == null || classification.attr('data-yellow') == '') ? 25 : classification.attr('data-yellow');
valRed = (classification.attr('data-red') == null || classification.attr('data-red') == '') ? 50 : classification.attr('data-red');
updatePerformanceThreshold(parent, valYellow, valRed);
}
parent.find(".amount-yellow").text(valYellow + '%');
parent.find(".amount-red").text(valRed + '%');
parent.find(".slider-range").slider({
range: true,
min: 0,
max: 100,
values: [valYellow, valRed],
slide: function (event, ui) {
onDataChanged();
var yellowVal = parseFloat(ui.values[0]);
var redVal = parseFloat(ui.values[1]);
var parent = $(event.target).parent().parent();
parent.find(".amount-yellow").text(yellowVal + '%');
parent.find(".amount-red").text(redVal + '%');
console.log(ui.values[1] + '%');
parent.find('.slider-red-strip').css('width', 100 - redVal + '%'); // SA. ENV-959. Fixed bug
updatePerformanceThreshold(parent, yellowVal, redVal);
}
}).append('<div class="slider-red-strip" style="width: ' + (100 - valYellow) + '%"></div>');
});
$('.pm-threshold').change(function () {
var parent = $(this).parent().parent();
if ($(this).find("[id*='UseThreshold']").is(':checked')) {
parent.find(".threshold-container").show();
} else { parent.find(".threshold-container").hide(); }
});
}
function reinitThresholds(parent, yellowVal, redVal) {
if (redVal == 0 || yellowVal == 0) {
yellowVal = 25;
redVal = 50;
}
var threshold = parent.parent().parent().parent().parent().find(".slider-range");
threshold.slider({ values: [yellowVal, redVal], }).find(".slider-red-strip").css("width", (100 - redVal) + "%");
threshold.parent().find(".amount-yellow").text(yellowVal + '%');
threshold.parent().find(".amount-red").text(redVal + '%');
updatePerformanceThreshold(threshold.parent(), yellowVal, redVal);
}
function updatePerformanceThreshold(parent, yellowVal, redVal) {
parent.find("input[id*='@Html.ClientIdFor(model=>model.PerformanceYellowThreshold)']").val(yellowVal);
parent.find("input[id*='@Html.ClientIdFor(model=>model.PerformanceRedThreshold)']").val(redVal);
}
function CheckProbability(statusField) {
var value = $(statusField).val();
var probability = false;
for (var i = 0; i < statuses.length; i++) {
if (statuses[i].Id == value) {
probability = statuses[i].Probability100;
break;
}
}
var sldr = $(statusField).parents('.pm-container').find('.slider-container');
sldr.slider({ 'disabled': probability });
if (probability)
sldr.slider({ 'value': 100 });
}
function onProjectSave(moveNext) {
if (teamsUnassigned()) {
bootbox.confirm("All the resourced from removed teams will be unassigned, do you want to proceed?", function (result) {
if (result) {
if ($('#frmEditProject').valid())
blockUI();
$('#@Html.ClientIdFor(t => t.SaveAsCopy)').val(false);
$('#@Html.ClientIdFor(t => t.ContinueToScenarios)').val(moveNext == true);
onDataSaved();
$('#frmEditProject').submit();
}
});
return false;
}
else {
if ($('#frmEditProject').valid())
blockUI();
$('#@Html.ClientIdFor(t => t.SaveAsCopy)').val(false);
$('#@Html.ClientIdFor(t => t.ContinueToScenarios)').val(moveNext == true);
onDataSaved();
return true;
}
}
function teamsUnassigned() {
var result = false;
$('[id$=Teams].select2-container').each(function (index) {
var oldAssignments = assignedTeams[$(this).attr('id')];
if (oldAssignments) {
var newAssignments = $(this).select2('val');
oldAssignments.forEach(function (entry) {
if ($.inArray(entry, newAssignments) < 0) {
result = true;
return;
}
});
}
});
return result;
}
function createCopy() {
if ($('#frmEditProject').valid())
blockUI();
$('#@Html.ClientIdFor(t => t.SaveAsCopy)').val(true);
onDataSaved();
$('#frmEditProject').submit();
return true;
}
function onDependentSlide(event, ui) {
var value = parseInt(ui.value);
var txt = GetProbabText(value);
$(this).children(".sliderValue").val(value);
$(this).children(".sliderTitle").html(value + '%' + txt);
}
function onDependentChange(event, ui) {
var value = parseInt(ui.value);
var txt = GetProbabText(value);
$(this).children(".sliderValue").val(value);
$(this).children(".sliderTitle").html(value + '%' + txt);
}
function GetProbabText(value) {
var txt = '';
if (value > 0 && value <= 25)
txt = " (Low)";
if (value > 25 && value <= 75)
txt = " (Medium)";
if (value > 75 && value <= 99)
txt = " (High)";
if (value == 100)
txt = " (Expected)";
return txt;
}
function loadExternalContacts(obj) {
var selClient = obj.target == null ? $(obj) : $(obj.target);
var extContacts = selClient.parents('.pm-container').find('select.ext-contacts');
$.ajax({
url: "@Url.Action("LoadExternalContacts", "Project")",
data: { clientId: selClient.val(), selectControlId: selClient.prop("id") },
success: function (dt) {
var data = dt.contacts;
var markup = "<option value=''></option>";
for (var i = 0; i < data.length; i++) {
markup += "<option value=" + data[i].Id + ">" + data[i].FirstName + " " + data[i].LastName + "</option>";
}
extContacts.html(markup);
extContacts.select2("val", $("#" + dt.selectControlId).parents('.pm-container').data('ecurrentContacts'));
},
error: function (reponse) {
showErrorModal('Error.', reponse);
}
});
}
function loadInternalContacts() {
$.ajax({
url: "@Url.Action("LoadInternalContacts", "Project")",
data: { companyId: $("#@Html.ClientIdFor(t => t.CompanyId)").val(), selectControlId: $("#@Html.ClientIdFor(t => t.CompanyId)").prop("id") },
success: function (dt) {
var data = dt.contacts;
var markup = "<option value=''></option>";
for (var i = 0; i < data.length; i++) {
markup += "<option value=" + data[i].Id + ">" + data[i].FirstName + " " + data[i].LastName + "</option>";
}
$("select.int-contacts").each(function () {
$(this).html(markup);
$(this).select2("val", $(this).parents('.pm-container').data('icurrentContacts'));
});
},
error: function (reponse) {
showErrorModal('Error.', reponse);
}
});
$.ajax({
url: "@Url.Action("LoadCompanyGoals", "Project")",
data: { companyId: $("#@Html.ClientIdFor(t => t.CompanyId)").val(), selectControlId: $("#@Html.ClientIdFor(t => t.CompanyId)").prop("id") },
success: function (dt) {
var data = dt.goals;
var markup = "<option value=''></option>";
for (var i = 0; i < data.length; i++) {
markup += "<option value=" + data[i].Value + ">" + data[i].Text + "</option>";
}
$("select.pm-goals").each(function () {
$(this).html(markup);
$(this).select2("val", $(this).parents('.pm-container').data('icurrentGoals'));
});
},
error: function (reponse) {
showErrorModal('Error.', reponse);
}
});
}
$('#btnAddNote').click(function () {
$('.divForCreate_@Model.Id').load('@Url.Action("AddNote", "Project", new { Model.Id })', function () {
$('#btnSaveNote').click(function () {
if ($(this).parents('form').valid())
blockUI();
});
$(".innerForm input").removeData("validator");
$(".innerForm input").removeData("unobtrusiveValidation");
$.validator.unobtrusive.parseDynamicContent('.innerForm');
});
$('#modalAddNote_@Model.Id').modal("show");
});
function editNote(id) {
if (id == null || id == "")
return "";
var text = "@Url.Action("EditNote", "Project", new { Id = "JSVar" })";
text = text.replace("JSVar", id);
$('.divForCreate_@Model.Id').load(text, function () {
$('#btnSaveNote').click(function () {
if ($(this).parents('form').valid())
blockUI();
});
$(".innerForm input").removeData("validator");
$(".innerForm input").removeData("unobtrusiveValidation");
$.validator.unobtrusive.parseDynamicContent('.innerForm');
});
$('#modalAddNote_@Model.Id').modal("show");
}
function deleteNote(Id) {
if (Id == null || Id == "")
return "";
bootbox.confirm({
message: "Are you sure you want to delete this note?",
callback: function (result) {
if (result) {
var text = "@Url.Action("DeleteNote", "Project", new { Id = "JSVar" })"
text = text.replace("JSVar", Id);
blockUI();
$('.divForCreate_@Model.Id').load(text, function (response, status, xhr) {
unblockUI();
if (status == "error") {
showErrorModal('Loading error', 'We are sorry but there was an error, please try again later.');
} else {
if (window.URI) {
window.location = URI(window.location.href).setQuery("ptab", "notes");
} else
window.location.reload();
}
});
}
},
className: "bootbox-sm"
});
}
//fix modal force focus
$.fn.modal.Constructor.prototype.enforceFocus = function () {
var that = this;
$(document).on('focusin.modal', function (e) {
if ($(e.target).hasClass('select2-input')) {
return true;
}
if (that.$element[0] !== e.target && !that.$element.has(e.target).length) {
that.$element.focus();
}
});
};
function loadScenario(projectId) {
var url = "?Id=" + projectId;
$('#reloadForm').load('@Url.Action("LoadScenario", "Scenarios")' + url, function () {
initScenario();
$('#createScenario').modal('show');
});
}
function addPart() {
console.log("PPID:" + $('#@Html.IdFor(t => t.Id)').val());
onDataChanged();
var index = parseInt($('#@Html.IdFor(t => t.PartsCount)').val());
var postData = {
ParentProjectId: $('#@Html.IdFor(t => t.Id)').val(),
count: index
};
if ($('#chkCopyPartDetails').is(':checked')) {
var lastPanel = $('.pm-container:not(.deleted)').last();
postData = {
ParentProjectId: $('#@Html.IdFor(t => t.Id)').val(),
TypeId: lastPanel.find('.pm-type select').val(),
ClientId: lastPanel.find('select.pm-clientId').val(),
CompanyId: $("#@Html.ClientIdFor(t => t.CompanyId)").val(),
Deadline: lastPanel.find('.pm-deadline input').val(),
StatusId: lastPanel.find('select.pm-status').val(),
Probability: lastPanel.find('.pm-probability input').val(),
IsRevenueGenerating: lastPanel.find('.pm-revenue input').is(':checked'),
Priority: lastPanel.find('.pm-priority input').val(),
Details: lastPanel.find('.pm-details textarea').val(),
AssignedTeams: lastPanel.find('select.pm-teams').val(),
StrategicGoals: lastPanel.find('select.pm-goals').val(),
InternalContacts: lastPanel.find('select.int-contacts').val(),
ExternalContacts: lastPanel.find('select.ext-contacts').val(),
UseThreshold: lastPanel.find('input[id$=UseThreshold]').val(),
PerformanceRedThreshold: lastPanel.find('input[id$=PerformanceRedThreshold]').val(),
PerformanceYellowThreshold: lastPanel.find('input[id$=PerformanceYellowThreshold]').val(),
count: index
};
}
$('#fsProjectDetails .pm-container .panel-title a').addClass('collapsed');
$('#fsProjectDetails .pm-container .panel-collapse').removeClass('in');
$.post('@Url.Action("AddPart", "Project")', postData, function (html) {
var pattern = new RegExp(' id="', "gi");
html = html.replace(pattern, ' id="Parts_' + index + '__', 'gi');
pattern = new RegExp(' name="', "gi");
html = html.replace(pattern, ' name="Parts[' + index + '].', 'gi');
pattern = new RegExp(' data-toggle="collapse" data-target="#', "gi");
html = html.replace(pattern, ' data-toggle="collapse" data-target="#Parts_' + index + '__', 'gi');
pattern = new RegExp(' data-valmsg-for="', "gi");
html = html.replace(pattern, ' data-valmsg-for="Parts[' + index + '].', 'gi');
// SA. ENV-502. Attachments
pattern = new RegExp('data-uf-name-template="Attachments"', "gi");
html = html.replace(pattern, ' data-uf-name-template="Parts[' + index + '].Attachments"', 'gi');
$(html).appendTo($('#fsProjectDetails'));
$.validator.unobtrusive.parseDynamicContent($('#frmEditProject'));
$('#fsProjectDetails .pm-container:eq(' + index + ')').data('index', index);
$('#@Html.IdFor(t => t.PartsCount)').val(index + 1);
initControls($('#Parts_' + index + '__Id_projectPart'));
//hide "has parts" switcher
$('#@Html.IdFor(t => t.HasChildren)').parent().parent().parent().hide();
}).error(function (h, e) {
console.log("h = " + h);
console.log("e = " + e);
});
}
function removePart(obj) {
onDataChanged();
var container = $(obj).parents('.pm-container');
var index = container.data('index');
container.find('#Parts_' + index + '__DeletedPart').val('True');
container.addClass('deleted');
container.hide();
return false;
}
// SA. ENV-789
function partNameChanged(partNameInput) {
var labelText = "Part Details";
if (partNameInput.value && partNameInput.value.trim().length > 0)
labelText = partNameInput.value.trim() + " - Details";
var projectPartPanel = $(partNameInput).parents("div.panel.pm-container");
if (projectPartPanel) {
var partNameBlock = $(projectPartPanel).find("span.panel-title.ui-expander").children("a").children("span.partTitle");
$(partNameBlock).text(labelText);
}
}
// SA. ENV-790
function expandProjectPart(partId) {
// Collapse all exeisting project parts
$('#fsProjectDetails .pm-container .panel-title a').addClass('collapsed');
$('#fsProjectDetails .pm-container .panel-collapse').removeClass('in');
var partContainerId = "p_" + partId;
$('#fsProjectDetails .pm-container#' + partContainerId + ' .panel-title a').removeClass('collapsed');
$('#fsProjectDetails .pm-container#' + partContainerId + ' .panel-collapse').addClass('in');
}
function ToggleStatus(fieldId) {
var url = "/ForecastDashboard/CheckIfActive/";
var request = {
'scenarioId': fieldId
};
$.get(url, request, function (data) {
if (data == null || data == "") {
ToggleStatusConfirmed(fieldId);
return '';
} else {
bootbox.confirm({
message: "There is an active scenario for this project already. Are you sure you want to activate this scenario instead of active one?",
callback: function (result) {
if (result) {
ToggleStatusConfirmed(fieldId);
}
},
className: "bootbox-sm"
});
}
});
}
function ToggleStatusConfirmed(scenarioId) {
if (scenarioId == null || scenarioId == "")
return "";
var url = "/ForecastDashboard/ToggleStatus/";
var request = {
'scenarioId': scenarioId
};
$.get(url, request, function (data) {
location.href = location.origin + location.pathname + $.query.SET('ptab', 'scenarios');
});
return '';
}
</script>
}
<style type="text/css">
div.threshold-container .ui-slider {
background: green;
}
div.threshold-container .ui-slider-range {
background: #ffd800;
}
div.threshold-container .slider-red-strip {
float: right;
height: 100%;
background: red;
border-radius: 0 4px 4px 0;
}
</style>
<div id="erorMsgPlaceholder"></div>
<div class="panel-body">
<ul id="tabsProject" class="nav nav-tabs">
<li class="active">
<a href="#tabGeneral" data-toggle="tab">Project<span class="badge badge-primary"></span></a>
</li>
<li style="@(Model.Id != Guid.Empty ? "" : "display:none")">
<a href="#tabScenarios" data-toggle="tab">Scenarios<span class="badge badge-primary"></span></a>
</li>
<li style="@(Model.Id != Guid.Empty ? "" : "display:none")">
<a href="#tabNotes" data-toggle="tab">Notes<span class="badge badge-primary"></span></a>
</li>
</ul>
<div class="tab-content no-padding tab-content-bordered">
<div class="tab-pane fade in active" id="tabGeneral">
@using (Html.BeginForm("Edit", "Project", FormMethod.Post, new { @class = "form-horizontal", @id = "frmEditProject" }))
{
<div class="panel-body">
@Html.AntiForgeryToken()
@Html.HiddenFor(model => model.Id)
@Html.HiddenFor(model => model.PartForScenarioId)
@Html.HiddenFor(model => model.SaveAsCopy)
@Html.HiddenFor(model => model.ContinueToScenarios)
@Html.HiddenFor(model => model.PartsCount)
@Html.HiddenFor(model => model.InitialHasChildrenState)
<fieldset id="fsProjectGeneral" class="form-group-margin">
<legend class="text-bold small-bottom-margin">General Project Information</legend>
<div class="row">
<div class="col-sm-7 col-lg-5">
<div class="form-group no-margin-hr">
@Html.LabelFor(model => model.Name, new { @class = "control-label" })
@Html.TextBoxFor(model => model.Name, new { @class = "form-control", @id = "IDDDD" })
@Html.ValidationMessageFor(model => model.Name)
</div>
</div>
<div class="col-sm-5 col-lg-4">
<div class="form-group no-margin-hr">
@Html.LabelFor(model => model.Number, new { @class = "control-label" })
@Html.TextBoxFor(model => model.Number, new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.Number)
</div>
</div>
<div class="clearfix hidden-xs hidden-lg visible-sm-block visible-md-block"></div>
<div class="col-sm-5 col-lg-3">
<div class="form-group no-margin-hr">
@Html.LabelFor(model => model.Color, new { @class = "control-label" })
@Html.TextBoxFor(model => model.Color, new { @class = "form-control", @id = "input-color" })
@Html.ValidationMessageFor(model => model.Color)
</div>
</div>
<div class="clearfix hidden-xs hidden-sm hidden-md visible-lg-block"></div>
<div class="col-sm-7 col-lg-4">
<div class="form-group no-margin-hr">
@Html.LabelFor(model => model.CompanyId, new { @class = "control-label" })
@Html.DropDownListFor(model => model.CompanyId, Utils.GetCompanies(true), new { @class = "form-control forselect2" })
@Html.ValidationMessageFor(model => model.CompanyId)
</div>
</div>
<div class="clearfix hidden-xs hidden-lg visible-sm-block visible-md-block"></div>
<div class="col-sm-5 col-lg-3" @(Model.Id != Guid.Empty && Model.HasChildren ? "style=display:none;" : string.Empty)>
<div class="form-group no-margin-hr switcher-block">
@Html.LabelFor(model => model.HasChildren, new { @class = "control-label" })
@Html.CheckBoxFor(model => model.HasChildren, new { @class = "switcher form-control" })
@Html.ValidationMessageFor(model => model.HasChildren)
</div>
</div>
</div>
</fieldset>
<fieldset id="fsProjectDetails">
<legend class="text-bold small-bottom-margin" id="detailsLegend">Project Details</legend>
@Html.EditorFor(t => t.Parts)
</fieldset>
@Html.ValidationSummary(false, "The project could not be saved due to the following errors:")
@if (Model == null || Model.Id == Guid.Empty)
{
<div class="alert alert-info">
<button type="button" class="close" data-dismiss="alert">×</button>
<strong>Please note!</strong> System will automatically give you and all contributors of teams selected the Full Access permissions for this project. Other permissions need to be manually set up through Administration.
</div>
}
</div>
<div class="panel-footer">
<a class="btn btn-default" href='@Model.BackUrl'><i class="fa fa-backward"></i> Back to @Model.BackName</a>
<div id="divCopyParts" style="display: inline;">
<a id="btnAddPart" class="btn btn-success" href="javascript:addPart();"><i class="fa fa-plus"></i> Add Next Part</a>
<input type="checkbox" id="chkCopyPartDetails" name="chkCopyPartDetails" class="skip-change" />
<label for="chkCopyPartDetails">Copy Part Details</label>
</div>
<button type="submit" class="btn btn-warning lockable" id="btnsave" href="javascript:void(0)" onclick="return onProjectSave(false);"><i class="fa fa-save"></i> Save</button>
@if (Model != null && Model.Id != Guid.Empty)
{
<a id="btncreateCopy" class="btn btn-primary lockable" href="javascript:createCopy();"><i class="fa fa-list"></i> Copy</a>
<a id="btnDelete" class="btn btn-danger" href="@Url.Action("Delete", "Project", new { @id = Model.Id })"><i class="fa fa-trash-o"></i> Delete</a>
}
else
{
<button type="submit" class="btn btn-warning lockable" id="nextButton" href="javascript:void(0)" onclick="return onProjectSave(true);"><i class="fa fa-forward"></i> Save & Continue to Scenario(s)</button>
}
</div>
}
</div>
<div class="tab-pane fade" id="tabScenarios">
<div class="panel-body" data-section="masterScenarioGrid">
@if (SecurityManager.CheckSecurityObjectPermission(Areas.Scenarios, AccessLevel.Write))
{
if (!Model.HasChildren)
{
<a class="btn btn-primary lockable" href="javascript:;" onclick="loadScenario('@Model.Id');"><i class="fa fa-plus"></i> Add Scenario</a>
<h1></h1>
}
}
<div class="table-light table-responsive no-margin" id="scenarioslist_@Model.Id">
<table cellpadding="0" cellspacing="0" border="0" class="table table-striped table-bordered no-margin">
<thead>
<tr>
<th>Status</th>
<th>Scenario Type</th>
<th>Name</th>
<th>Projected Revenue</th>
<th>Expected Gross Margin</th>
<th>Calculated Gross Margin</th>
<th>Start Date</th>
<th>End Date</th>
<th></th>
</tr>
</thead>
<tbody>
@if (Model.HasChildren)
{
foreach (EnVisage.Models.ProjectPartModel pm in Model.Parts)
{
<text>
<tr>
<td colspan="9">
@if (SecurityManager.CheckSecurityObjectPermission(Areas.Scenarios, AccessLevel.Write))
{
<a class="btn btn-primary btn-xs lockable" href="javascript:;" onclick="loadScenario('@pm.Id');"><i class="fa fa-plus"></i> Add Scenario</a>@Html.Raw("&nbsp;&nbsp;");
}
<strong>@pm.Name</strong>
</td>
</tr>
</text>
List<EnVisage.Models.ScenarioTabModel> partScenarios = new List<EnVisage.Models.ScenarioTabModel>();
if (Model.Scenarios != null)
{
partScenarios = Model.Scenarios.Where(s => s.Type != ScenarioType.Actuals && s.ProjectId == pm.Id).OrderByDescending(s => s.Status).ThenBy(s => s.Name).ToList();
}
if (partScenarios.Count > 0)
{
foreach (var scenario in partScenarios)
{
<text>
<tr>
<td><span id="status_@scenario.Id">@scenario.Status</span></td>
<td>@scenario.Type</td>
<td><a id="aDet_@scenario.Id" class="popover-warning popover-dark" onclick="return CheckLock(this.id, 'Scenario', '@scenario.Id')" href="/Scenarios/Details/@scenario.Id?backUrl=@(Url.Encode(Url.Action("Edit", "Project", new{id=Model.Id})))&backName=project">@scenario.Name</a></td>
<td>@(scenario.ProjectedRevenue.HasValue ? scenario.ProjectedRevenue.Value.ToString("#") : string.Empty) </td>
<td>@(scenario.ExpectedGrossMargin.HasValue ? scenario.ExpectedGrossMargin.Value.ToString("p") : string.Empty) </td>
<td>@(scenario.CalculatedGrossMargin.HasValue ? scenario.CalculatedGrossMargin.Value.ToString("p") : string.Empty) </td>
<td>@(scenario.StartDate.HasValue ? scenario.StartDate.Value.ToShortDateString() : string.Empty)</td>
<td>@(scenario.EndDate.HasValue ? scenario.EndDate.Value.ToShortDateString() : string.Empty) </td>
<td style="white-space: nowrap;">
@if (scenario.Status.HasValue && scenario.Status.Value == ScenarioStatus.Active)
{
<a id='@scenario.Id' onclick="if(CheckLock(this.id, 'Scenario', '@scenario.Id')) {ToggleStatus('@scenario.Id', this);}" data-toggle="popover" data-placement="left" class="btn btn-xs btn-warning popover-warning popover-dark lockable" title="Deactivate"><i class="fa fa-times-circle-o"></i></a>
}
else if (scenario.Status.HasValue && scenario.Status.Value == ScenarioStatus.Inactive)
{
<a id='@scenario.Id' onclick="if(CheckLock(this.id, 'Scenario', '@scenario.Id')) {ToggleStatus('@scenario.Id', this);}" data-toggle="popover" data-placement="left" class="btn btn-xs btn-primary popover-warning popover-dark lockable" title="Activate"><i class="fa fa-check-circle-o"></i></a>
}
<a id="btnDelete_@scenario.Id" onclick="return CheckLock(this.id, 'Scenario', '@scenario.Id')" data-toggle="popover" data-placement="left" class="btn btn-sm btn-danger popover-warning popover-dark lockable" href="@Url.Action("Delete", "Scenarios", new { @id = scenario.Id, @backUrl = Url.Action("Edit", "Project", new { @id = Model.Id, @ptab = "scenarios" }) })"><i class="fa fa-trash-o"></i> Delete</a>
</td>
</tr>
</text>
}
}
}
}
else if (Model.Scenarios != null)
{
foreach (var scenario in Model.Scenarios.OrderByDescending(s => s.Status).ThenBy(s => s.Name))
{
if (scenario.Type != ScenarioType.Actuals)
{
<tr>
<td><span id="status_@scenario.Id">@scenario.Status</span></td>
<td>@scenario.Type</td>
<td><a id="aDet_@scenario.Id" class="popover-warning popover-dark" onclick="return CheckLock(this.id, 'Scenario', '@scenario.Id')" href="/Scenarios/Details/@scenario.Id?backUrl=@(Url.Encode(Url.Action("Edit", "Project", new{id=Model.Id})))&backName=project">@scenario.Name</a></td>
<td>@(scenario.ProjectedRevenue.HasValue ? scenario.ProjectedRevenue.Value.ToString("#") : string.Empty) </td>
<td>@(scenario.ExpectedGrossMargin.HasValue ? scenario.ExpectedGrossMargin.Value.ToString("p") : string.Empty) </td>
<td>@(scenario.CalculatedGrossMargin.HasValue ? scenario.CalculatedGrossMargin.Value.ToString("p") : string.Empty) </td>
<td>@(scenario.StartDate.HasValue ? scenario.StartDate.Value.ToShortDateString() : string.Empty)</td>
<td>@(scenario.EndDate.HasValue ? scenario.EndDate.Value.ToShortDateString() : string.Empty) </td>
<td style="white-space: nowrap;">
@if (scenario.Status.HasValue && scenario.Status.Value == ScenarioStatus.Active)
{
<a id='@scenario.Id' onclick="if(CheckLock(this.id, 'Scenario', '@scenario.Id')) {ToggleStatus('@scenario.Id', this);}" data-toggle="popover" data-placement="left" class="btn btn-xs btn-warning popover-warning popover-dark lockable" title="Deactivate"><i class="fa fa-times-circle-o"></i></a>
}
else if (scenario.Status.HasValue && scenario.Status.Value == ScenarioStatus.Inactive)
{
<a id='@scenario.Id' onclick="if(CheckLock(this.id, 'Scenario', '@scenario.Id')) {ToggleStatus('@scenario.Id', this);}" data-toggle="popover" data-placement="left" class="btn btn-xs btn-primary popover-warning popover-dark lockable" title="Activate"><i class="fa fa-check-circle-o"></i></a>
}
<a id="btnDelete_@scenario.Id" onclick="return CheckLock(this.id, 'Scenario', '@scenario.Id')" data-toggle="popover" data-placement="left" class="btn btn-sm btn-danger popover-warning popover-dark lockable" href="@Url.Action("Delete", "Scenarios", new { @id = scenario.Id, @backUrl = Url.Action("Edit", "Project", new { @id = Model.Id, @ptab = "scenarios" }) })"><i class="fa fa-trash-o"></i> Delete</a>
</td>
</tr>
}
}
}
</tbody>
</table>
</div>
@if (Model.HasChildren)
{
<br />
@Html.Partial("../Scenarios/_masterScenarioCalendar", Model.Id)
}
</div>
</div>
<div class="tab-pane fade" id="tabNotes">
<div class="panel-body">
<a class="btn btn-primary lockable" id="btnAddNote" href="javascript:;"><i class="fa fa-plus"></i> Add Note</a>
<h1></h1>
<div class="table-light table-responsive no-margin" id="noteslist_@Model.Id">
<table cellpadding="0" cellspacing="0" border="0" class="table table-striped table-bordered no-margin">
<thead>
<tr>
<th>Date</th>
<th>Author</th>
<th>Title</th>
<th>Details</th>
<th></th>
</tr>
</thead>
<tbody>
@if (Model.Notes.Count == 0)
{
<tr>
<td colspan="5">There are no notes for this project</td>
</tr>
}
else
{
foreach (var note in Model.Notes)
{
<tr>
<td>@((note.DateAdded == null) ? "N/A" : note.DateAdded.ToString("d"))</td>
<td>@note.Author.UserName</td>
<td>@note.Title</td>
<td>@(!string.IsNullOrEmpty(note.Details) ? (note.Details.Length < 200 ? note.Details : note.Details.Substring(0, 197) + "...") : "")</td>
<td>
<a href="javascript:void(0)" onclick="editNote('@note.Id');" class="btn btn-primary lockable"><i class="fa fa-edit"></i> Edit</a>
<a href="javascript:void(0)" onclick="deleteNote('@note.Id');" class="btn btn-danger lockable"><i class="fa fa-trash-o"></i> Delete</a>
</td>
</tr>
}
}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<div id="modalAddNote_@Model.Id" class="modal fade" tabindex="-1" role="dialog" style="display: none;" data-backdrop="static">
<div class="modal-dialog divForCreate_@Model.Id">
</div>
</div>
<div id="createScenario" class="modal fade" data-width="900" tabindex="-1" role="dialog" data-backdrop="static">
<div class="modal-content" id="reloadForm">
</div>
<!-- / .modal-content -->
</div>
<!-- / Modal -->