Skip to content

Commit

Permalink
Added funding table to UI #3369
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisala committed Dec 9, 2024
1 parent 3dac5be commit f617372
Show file tree
Hide file tree
Showing 8 changed files with 146 additions and 113 deletions.
109 changes: 109 additions & 0 deletions grails-app/assets/javascripts/budget.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
function BudgetViewModel(o, period) {
var self = this;
if (!o) o = {};

self.overallTotal = ko.observable(0.0);

var headerArr = [];
for (i = 0; i < period.length; i++) {
headerArr.push({"data": period[i]});
}
self.headers = ko.observableArray(headerArr);

var row = [];
o.rows ? row = o.rows : row.push(ko.mapping.toJS(new BudgetRowViewModel({}, period)));
self.rows = ko.observableArray($.map(row, function (obj, i) {
// Headers don't match with previously stored headers, adjust rows accordingly.
if (o.headers && period && o.headers.length != period.length) {
var updatedRow = [];
for (i = 0; i < period.length; i++) {
var index = -1;

for (j = 0; j < o.headers.length; j++) {
if (period[i] == o.headers[j].data) {
index = j;
break;
}
}
updatedRow.push(index != -1 ? obj.costs[index] : 0.0)
index = -1;
}
obj.costs = updatedRow;
}

return new BudgetRowViewModel(obj, period);
}));

self.overallTotal = ko.computed(function () {
var total = 0.0;
ko.utils.arrayForEach(this.rows(), function (row) {
if (row.rowTotal()) {
total += parseFloat(row.rowTotal());
}
});
return total;
}, this).extend({currency: {}});

var allBudgetTotal = [];
for (i = 0; i < period.length; i++) {
allBudgetTotal.push(new BudgetTotalViewModel(this.rows, i));
}
self.columnTotal = ko.observableArray(allBudgetTotal);

self.addRow = function () {
self.rows.push(new BudgetRowViewModel({}, period));
}
};

function BudgetTotalViewModel(rows, index) {
var self = this;
self.data = ko.computed(function () {
var total = 0.0;
ko.utils.arrayForEach(rows(), function (row) {
if (row.costs()[index]) {
total += parseFloat(row.costs()[index].dollar());
}
});
return total;
}, this).extend({currency: {}});
};


function BudgetRowViewModel(o, period) {
var self = this;
if (!o) o = {};
if (!o.activities || !_.isArray(o.activities)) o.activities = [];
self.shortLabel = ko.observable(o.shortLabel);
self.description = ko.observable(o.description);
self.activities = ko.observableArray(o.activities);

var arr = [];
// Have at least one period to record, which will essentially be a project total.
var minPeriods = _.max([1, period.length]);
for (var i = 0; i < minPeriods; i++) {
arr.push(ko.mapping.toJS(new FloatViewModel()));
}

if (o.costs && o.costs.length != arr.length) {
o.costs = arr;
}
o.costs ? arr = o.costs : arr;
self.costs = ko.observableArray($.map(arr, function (obj, i) {
return new FloatViewModel(obj);
}));

self.rowTotal = ko.computed(function () {
var total = 0.0;
ko.utils.arrayForEach(this.costs(), function (cost) {
if (cost.dollar())
total += parseFloat(cost.dollar());
});
return total;
}, this).extend({currency: {}});
};

function FloatViewModel(o) {
var self = this;
if (!o) o = {};
self.dollar = ko.observable(o.dollar ? o.dollar : 0.0).extend({numericString: 2}).extend({currency: {}});
};
110 changes: 0 additions & 110 deletions grails-app/assets/javascripts/meriplan.js
Original file line number Diff line number Diff line change
Expand Up @@ -1984,116 +1984,6 @@ function SingleAssetOutcomeViewModel(o, config) {
};
};

function BudgetViewModel(o, period) {
var self = this;
if (!o) o = {};

self.overallTotal = ko.observable(0.0);

var headerArr = [];
for (i = 0; i < period.length; i++) {
headerArr.push({"data": period[i]});
}
self.headers = ko.observableArray(headerArr);

var row = [];
o.rows ? row = o.rows : row.push(ko.mapping.toJS(new BudgetRowViewModel({}, period)));
self.rows = ko.observableArray($.map(row, function (obj, i) {
// Headers don't match with previously stored headers, adjust rows accordingly.
if (o.headers && period && o.headers.length != period.length) {
var updatedRow = [];
for (i = 0; i < period.length; i++) {
var index = -1;

for (j = 0; j < o.headers.length; j++) {
if (period[i] == o.headers[j].data) {
index = j;
break;
}
}
updatedRow.push(index != -1 ? obj.costs[index] : 0.0)
index = -1;
}
obj.costs = updatedRow;
}

return new BudgetRowViewModel(obj, period);
}));

self.overallTotal = ko.computed(function () {
var total = 0.0;
ko.utils.arrayForEach(this.rows(), function (row) {
if (row.rowTotal()) {
total += parseFloat(row.rowTotal());
}
});
return total;
}, this).extend({currency: {}});

var allBudgetTotal = [];
for (i = 0; i < period.length; i++) {
allBudgetTotal.push(new BudgetTotalViewModel(this.rows, i));
}
self.columnTotal = ko.observableArray(allBudgetTotal);

self.addRow = function () {
self.rows.push(new BudgetRowViewModel({}, period));
}
};

function BudgetTotalViewModel(rows, index) {
var self = this;
self.data = ko.computed(function () {
var total = 0.0;
ko.utils.arrayForEach(rows(), function (row) {
if (row.costs()[index]) {
total += parseFloat(row.costs()[index].dollar());
}
});
return total;
}, this).extend({currency: {}});
};


function BudgetRowViewModel(o, period) {
var self = this;
if (!o) o = {};
if (!o.activities || !_.isArray(o.activities)) o.activities = [];
self.shortLabel = ko.observable(o.shortLabel);
self.description = ko.observable(o.description);
self.activities = ko.observableArray(o.activities);

var arr = [];
// Have at least one period to record, which will essentially be a project total.
var minPeriods = _.max([1, period.length]);
for (var i = 0; i < minPeriods; i++) {
arr.push(ko.mapping.toJS(new FloatViewModel()));
}

if (o.costs && o.costs.length != arr.length) {
o.costs = arr;
}
o.costs ? arr = o.costs : arr;
self.costs = ko.observableArray($.map(arr, function (obj, i) {
return new FloatViewModel(obj);
}));

self.rowTotal = ko.computed(function () {
var total = 0.0;
ko.utils.arrayForEach(this.costs(), function (cost) {
if (cost.dollar())
total += parseFloat(cost.dollar());
});
return total;
}, this).extend({currency: {}});
};

function FloatViewModel(o) {
var self = this;
if (!o) o = {};
self.dollar = ko.observable(o.dollar ? o.dollar : 0.0).extend({numericString: 2}).extend({currency: {}});
};

function ActivitiesViewModel(activities, programActivities) {
var self = this;

Expand Down
5 changes: 3 additions & 2 deletions grails-app/assets/javascripts/organisation.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
//= require reportService
//= require components.js
//= require ecodata-components.js
//= require budget.js
/**
* Knockout view model for organisation pages.
* @param props JSON/javascript representation of the organisation.
Expand Down Expand Up @@ -658,7 +659,7 @@ OrganisationPageViewModel = function (props, options) {
self.selectedTargetMeasures = ko.observableArray();
var details = new OrganisationDetailsViewModel(propDetails, props, self.periods, self.allTargetMeasures, options);
updatedTargetMeasures(details);
self.reportingTargets = ko.observable(details);
self.reportingTargetsAndFunding = ko.observable(details);
self.isProjectDetailsLocked = ko.observable(false);

var setStartAndEndDateDefaults = function() {
Expand Down Expand Up @@ -762,7 +763,7 @@ OrganisationPageViewModel = function (props, options) {

self.saveCustomFields = function() {
if ($("#organisation-targets > table").validationEngine('validate')) {
var json = JSON.parse(self.reportingTargets().modelAsJSON());
var json = JSON.parse(self.reportingTargetsAndFunding().modelAsJSON());
return saveOrganisation(json);
}
};
Expand Down
1 change: 1 addition & 0 deletions grails-app/assets/javascripts/projects.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
//= require jquery-file-download/jquery.fileDownload.js
//= require document.js
//= require meriplan.js
//= require budget.js
//= require risks.js
//= require sites.js
//= require activity.js
Expand Down
1 change: 1 addition & 0 deletions grails-app/assets/javascripts/services.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ function OrganisationDetailsViewModel(o, organisation, budgetHeaders, allService
serviceIds = o.services && o.services.serviceIds || [],
targets = o.services && o.services.targets || [];
self.services = new OrganisationServicesViewModel(serviceIds, config.services, targets, budgetHeaders);
self.funding = new BudgetViewModel(o.funding, budgetHeaders);
function clearHiddenFields(jsData) {

};
Expand Down
2 changes: 2 additions & 0 deletions grails-app/views/organisation/_admin.gsp
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,8 @@
</g:else>
<g:if test="${showTargets}">
<div id="organisation-targets" class="tab-pane">
<h3>Total funding</h3>
<g:render template="/organisation/budget"/>
<h3>Service Targets</h3>
<g:render template="/organisation/serviceTargets" model="[services:organisation.services, periods:organisation.periods, showTargetDate:organisation.showTargetDate]"/>
</div>
Expand Down
29 changes: 29 additions & 0 deletions grails-app/views/organisation/_budget.gsp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<!-- ko with:reportingTargetsAndFunding().funding -->
<div class="funding">

<label><b>Funding</b><fc:iconHelp title="Project Budget">${budgetHelpText?:"Enter the budget as reviewed each year"}</fc:iconHelp></label>
<g:if test="${explanation}">
<p>${explanation}</p>
</g:if>
<table class="table">
<thead>
<tr>
<!-- ko foreach: headers -->
<th class="budget-amount"><div data-bind="text:data.label"></div>$</th>
<!-- /ko -->

</tr>
</thead>
<tbody data-bind="foreach : rows">
<tr>
<!-- ko foreach: costs -->
<td class="budget-amount">
<input type="number" class="form-control form-control-sm" data-bind="value: dollar, numeric: $root.number, disable: $root.isProjectDetailsLocked()" data-validation-engine="validate[custom[number]]"/>
</td>
<!-- /ko -->
</tr>
</tbody>
</table>

</div>
<!-- /ko -->
2 changes: 1 addition & 1 deletion grails-app/views/organisation/_serviceTargets.gsp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!-- ko with:reportingTargets() -->
<!-- ko with:reportingTargetsAndFunding() -->
<h4>${title ?: "Organisation services and minimum targets"}</h4>
<!-- ko with: services -->
<table class="table service-targets validationEngineContainer">
Expand Down

0 comments on commit f617372

Please sign in to comment.