Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/dev' into feature/issue3169
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisala committed Dec 19, 2024
2 parents a44cbd3 + 5f7c662 commit dad817b
Show file tree
Hide file tree
Showing 18 changed files with 6,674 additions and 157 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ dependencies {
providedCompile "io.methvin:directory-watcher:0.4.0"

if (!Boolean.valueOf(inplace)) {
implementation "org.grails.plugins:ecodata-client-plugin:7.0"
implementation "org.grails.plugins:ecodata-client-plugin:7.2-SNAPSHOT"
}
}

Expand Down
2,260 changes: 2,221 additions & 39 deletions forms/nht/grantsAndOthersProgressReport.json

Large diffs are not rendered by default.

2,137 changes: 2,127 additions & 10 deletions forms/nht/nhtOutputReport.json

Large diffs are not rendered by default.

2,236 changes: 2,150 additions & 86 deletions forms/nht/procurementsOutputReport.json

Large diffs are not rendered by default.

10 changes: 8 additions & 2 deletions grails-app/assets/javascripts/services.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@ function OrganisationServicesViewModel(serviceIds, allServices, outputTargets, p
target.serviceId = ko.observable(service ? service.id : null);
target.scoreId = ko.observable(score ? score.scoreId : null);

target.target = ko.observable();
var decimalPlaces = _.isNumber(score && score.decimalPlaces) ? score.decimalPlaces : 2;
target.target = ko.observable().extend({numericString: decimalPlaces});
target.targetDate = ko.observable().extend({simpleDate:false});

target.periodTargets = _.map(periods, function (period) {
Expand All @@ -96,7 +97,7 @@ function OrganisationServicesViewModel(serviceIds, allServices, outputTargets, p
var sum = 0;
var count = 0;
_.each(target.periodTargets, function (periodTarget) {
var target = parseInt(periodTarget.target());
var target = parseFloat(periodTarget.target());
if (!_.isNaN(target)) {
sum += target
count++;
Expand Down Expand Up @@ -209,6 +210,11 @@ function OrganisationServicesViewModel(serviceIds, allServices, outputTargets, p
});

target.scoreId.subscribe(function () {
var score = target.scoreId() ? target.score() : null;
if (score) {
var decimalPlaces = _.isNumber(score && score.decimalPlaces) ? score.decimalPlaces : 2;
target.target = ko.observable().extend({numericString: decimalPlaces});
}
target.updateTargets();
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -507,8 +507,10 @@ class ActivityController {

def outputName = params.type
def listName = params.listName
String activityForm = params.activityForm
Integer formVersion = params.getInt('formVersion', null)

def model = metadataService.annotatedOutputDataModel(outputName)
def model = metadataService.annotatedOutputDataModel(activityForm, outputName, formVersion)
if (listName) {
model = metadataService.findByName(listName, model)?.columns
}
Expand Down Expand Up @@ -617,14 +619,9 @@ class ActivityController {

String url = "${grailsApplication.config.getProperty('ecodata.baseUrl')}metadata/excelOutputTemplate"

if (params.data) {
webService.proxyPostRequest(response, url,
[listName:params.listName, type:params.type, data:params.data, editMode:params.editMode, allowExtraRows:params.allowExtraRows, autosizeColumns:false])
}
else {
url += "?type=${params.type?.encodeAsURL()}&listName=${params.listName?.encodeAsURL()}"
webService.proxyGetRequest(response, url, true, true)
}
Map postParams = [listName:params.listName, type:params.type, data:params.data, editMode:params.editMode, allowExtraRows:params.allowExtraRows, autosizeColumns:false, formVersion:params.getInt('formVersion'), activityForm:params.activityForm]

webService.proxyPostRequest(response, url, postParams)

return null
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,14 @@ class OrganisationController {
Map availableReportCategories = null
List services = null
List targetPeriods = null
List dashboardData = null
if (adminVisible) {
dashboardReports += [name:'announcements', label:'Announcements']
availableReportCategories = settingService.getJson(SettingPageType.ORGANISATION_REPORT_CONFIG)
services = organisationService.findApplicableServices(organisation, metadataService.getProjectServices())
targetPeriods = organisationService.generateTargetPeriods(organisation)
List scores = services.collect{it.scores}.flatten()
dashboardData = organisationService.scoresForOrganisation(organisation, scores?.collect{it.scoreId}, !hasEditorAccess)
}
boolean showTargets = userService.userIsSiteAdmin() && services && targetPeriods

Expand Down Expand Up @@ -110,7 +113,7 @@ class OrganisationController {
[about : [label: 'About', visible: true, stopBinding: false, type:'tab', default:!reportingVisible, displayedPrograms:projectGroups.displayedPrograms, servicesDashboard:[visible:true]],
projects : [label: 'Reporting', template:"/shared/projectListByProgram", visible: reportingVisible, stopBinding:true, default:reportingVisible, type: 'tab', reports:organisation.reports, adHocReportTypes:adHocReportTypes, reportOrder:reportOrder, hideDueDate:true, displayedPrograms:projectGroups.displayedPrograms, reportsFirst:true, declarationType:SettingPageType.RDP_REPORT_DECLARATION],
sites : [label: 'Sites', visible: reportingVisible, type: 'tab', stopBinding:true, projectCount:organisation.projects?.size()?:0, showShapefileDownload:adminVisible],
dashboard : [label: 'Dashboard', visible: reportingVisible, stopBinding:true, type: 'tab', template:'/shared/dashboard', reports:dashboardReports],
dashboard : [label: 'Dashboard', visible: reportingVisible, stopBinding:true, type: 'tab', template:'dashboard', reports:dashboardReports, dashboardData:dashboardData],
admin : [label: 'Admin', visible: adminVisible, type: 'tab', template:'admin', showEditAnnoucements:showEditAnnoucements, availableReportCategories:availableReportCategories, targetPeriods:targetPeriods, services: services, showTargets:showTargets]]

}
Expand Down Expand Up @@ -200,7 +203,7 @@ class OrganisationController {
}

List existingLinks = links?.findResults { it.documentId }
List toDeleteLinks = originalOrganisation?.links?.findAll { !existingLinks.contains(it.documentId) }
List toDeleteLinks = originalOrganisation?.links?.findAll { !existingLinks?.contains(it.documentId) }
// delete any links that were removed.
if (toDeleteLinks && !result.error) {
toDeleteLinks.each { link ->
Expand Down Expand Up @@ -452,7 +455,7 @@ class OrganisationController {
return
}
def outputModels = activityModel.outputs.collect {
[name:it, annotatedModel:metadataService.annotatedOutputDataModel(it), dataModel:metadataService.getDataModelFromOutputName(it)]
[name:it, annotatedModel:metadataService.annotatedOutputDataModel(activityType, it, null), dataModel:metadataService.getDataModelFromOutputName(it)]
}

def criteria = [type:activityType, projectId:organisation.projects.collect{it.projectId}, dateProperty:'plannedEndDate', startDate:params.plannedStartDate, endDate:params.plannedEndDate]
Expand Down
12 changes: 8 additions & 4 deletions grails-app/services/au/org/ala/merit/MetadataService.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,14 @@ class MetadataService {
})
}

def annotatedOutputDataModel(type) {
return cacheService.get('annotated-output-model'+type,{
Collections.unmodifiableList(webService.getJson(grailsApplication.config.getProperty('ecodata.baseUrl') +
'metadata/annotatedOutputDataModel?type='+type.encodeAsURL()))
def annotatedOutputDataModel(String activityForm, String formSection, Integer formVersion) {
return cacheService.get('annotated-output-model'+activityForm+'_'+formSection,{
String url = grailsApplication.config.getProperty('ecodata.baseUrl') +
'metadata/annotatedOutputDataModel?type='+formSection.encodeAsURL()+"&activityForm="+activityForm.encodeAsURL()
if (formVersion) {
url += "&formVersion="+formVersion
}
Collections.unmodifiableList(webService.getJson(url))
})
}

Expand Down
17 changes: 17 additions & 0 deletions grails-app/services/au/org/ala/merit/OrganisationService.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,23 @@ class OrganisationService {
scoreIds.collectEntries{ String scoreId ->[(scoreId):result.results?.find{it.scoreId == scoreId}?.result?.result ?: 0]}
}

List scoresForOrganisation(Map organisation, List<String> scoreIds, boolean approvedOnly = true) {

String url = grailsApplication.config.getProperty('ecodata.baseUrl')+"organisation/organisationMetrics/"+organisation.organisationId
Map params = [approvedOnly: approvedOnly, scoreIds: scoreIds]

Map result = webService.doPost(url, params)

List scores = result?.resp?.collect { Map score ->
Map target = organisation?.custom?.details?.services?.targets?.find { it.scoreId == score.scoreId }
score.target = target?.target
score
}

scores

}


/**
* Filter services to those supported by organisation.
Expand Down
2 changes: 1 addition & 1 deletion grails-app/services/au/org/ala/merit/ProjectService.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -1340,7 +1340,7 @@ class ProjectService {

stageReportActivityModel.outputs.each { outputType ->
def output = activity.outputs?.find { it.name == outputType }
def type = metadataService.annotatedOutputDataModel(outputType)
def type = metadataService.annotatedOutputDataModel(activity.type, outputType, activity.formVersion)

append(html,"<b> ${outputType}: </b> <br>");
type.each { field ->
Expand Down
4 changes: 3 additions & 1 deletion grails-app/taglib/au/org/ala/merit/DashboardTagLib.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -147,10 +147,12 @@ class DashboardTagLib {
percentComplete = Math.min(100, percentComplete)
percentComplete = Math.max(0, percentComplete)

int maxDecimalPlaces = score.decimalPlaces != null ? score.decimalPlaces : 2

out << """
<div class="progress progress-info active " style="position:relative">
<div class="${progressBarClass}" style="width: ${percentComplete}%;"></div>
<span class="pull-right progress-label ${percentComplete >= 99 ? 'progress-100':''}" style="position:absolute; top:0; right:0;"> ${g.formatNumber(type:'number',number:result, maxFractionDigits: 2, groupingUsed:true)}/${g.formatNumber(type:'number',number:target, maxFractionDigits: 2, groupingUsed:true)}</span>
<span class="pull-right progress-label ${percentComplete >= 99 ? 'progress-100':''}" style="position:absolute; top:0; right:0;"> ${g.formatNumber(type:'number',number:result, maxFractionDigits: maxDecimalPlaces, groupingUsed:true)}/${g.formatNumber(type:'number',number:target, maxFractionDigits: maxDecimalPlaces, groupingUsed:true)}</span>
</div>"""
}

Expand Down
12 changes: 12 additions & 0 deletions grails-app/views/organisation/_dashboard.gsp
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<g:if test="${dashboardData}">
<div class="dashboard-section" style="padding:10px; margin-top:10px;">
<g:each in="${dashboardData.groupBy{it.category}}" var="category">
<h3 class="serviceTitle">${category.key}</h3>
<g:each in="${category.value}" var="score">
<fc:renderScore score="${score}" includeInvoiced="false"></fc:renderScore>
</g:each>
</g:each>
</div>
</g:if>

<g:render template="/shared/dashboard"></g:render>
1 change: 1 addition & 0 deletions src/main/groovy/au/org/ala/merit/Score.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class Score {
BigDecimal target
Map result
List<Map> periodTargets
Integer decimalPlaces

double singleResult() {
this.result?.result ?: 0d
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,13 @@ var config =
"title": "Project review, improvement and evaluation methodology and approach (3000 character limit [approximately 500 words])"
}
},
{
"template": "nationalAndRegionalPlans",
"model": {
"includeUrl": true,
"headingTitle": "Conservation and management plans"
}
},
{
"template": "serviceOutcomeTargets",
"model": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,13 @@ var config =
"title": "Project review, improvement and evaluation methodology and approach (3000 character limit [approximately 500 words])"
}
},
{
"template": "nationalAndRegionalPlans",
"model": {
"includeUrl": true,
"headingTitle": "Conservation and management plans"
}
},
{
"template": "serviceOutcomeTargets",
"model": {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
load('../../../utils/audit.js');
var userId = "system";
db.project.find({"geographicInfo": {$exists: true},
"geographicInfo.isDefault": {$exists: false}}
).forEach(function(project) {
if (project.geographicInfo && project.geographicInfo.isDefault === undefined) {
project.geographicInfo.isDefault = false;
db.project.save(project);
audit(project, project.projectId, 'au.org.ala.ecodata.Project', userId, undefined, "Update");
print("Updated project: " + project.projectId);
}
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
load('../../../utils/uuid.js');
load('../../../utils/audit.js');
let adminUserId = '<tbd>'
const invoiceScoreId = '7u24188f-852h-3bex-c49g-60a2dsaa8723';
let scores = [

{
scoreId: invoiceScoreId,
entityTypes: undefined,
tags: [],
displayType: '',
entity: 'Activity',
outputType: 'Research and Development',
isOutputTarget: false,
category: 'Reporting',
status: 'active',
label: 'Invoiced number of hours conducting research and development',
description: '',
configuration: {
childAggregations: [
{
filter: {
property: 'name',
filterValue: 'NHT - Research and development',
type: 'filter'
},
childAggregations: [
{
property: 'data.noHoursConductingResearchAndDevelopmentInvoiced',
type: 'SUM'
}
]
}
]
}
}
,
{
_id: ObjectId('664c25abb61a6108c799bb66'),
scoreId: UUID.generate(),
label: 'Number of hours conducting research and development',
status: 'active',
isOutputTarget: true,
category: 'RLP and Bushfire Recovery',
outputType: 'Research and Development',
configuration: {
childAggregations: [
{
filter: {
property: 'name',
filterValue: 'NHT - Research and development',
type: 'filter'
},
childAggregations: [
{
property: 'data.noHoursConductingResearchAndDevelopment',
type: 'SUM'
}
]
}
]
},
dateCreated: ISODate('2024-12-17T04:40:11.160Z'),
lastUpdated: ISODate('2024-12-17T04:40:11.160Z'),
relatedScores: [
{
description: 'Invoiced by',
scoreId: invoiceScoreId
}
]
}];


for (let i=0; i<scores.length; i+=2) {
let invoiced = scores[i];
let delivered = scores[i+1];

audit(invoiced, invoiced.scoreId, 'au.org.ala.ecodata.Score', adminUserId, null, 'Insert');
db.score.insertOne(invoiced);

audit(delivered, delivered.scoreId, 'au.org.ala.ecodata.Score', adminUserId, null, 'Insert');
db.score.insertOne(delivered);

}
Original file line number Diff line number Diff line change
Expand Up @@ -539,6 +539,8 @@ class ActivityControllerSpec extends Specification implements ControllerUnitTest

params.type = 'RLP - Flora survey'
params.listName = 'floraSurveyDetails'
params.activityForm = 'Flora Survey'
params.formVersion = 2

JSON.createNamedConfig("clientSideFormattedDates", { cfg ->
DateTimeFormatter formatter = DateTimeFormat.forPattern("dd-MM-yyyy")
Expand All @@ -550,7 +552,7 @@ class ActivityControllerSpec extends Specification implements ControllerUnitTest
controller.ajaxUpload()

then:
1 * metadataService.annotatedOutputDataModel('RLP - Flora survey') >> getListModel()
1 * metadataService.annotatedOutputDataModel('Flora Survey', 'RLP - Flora survey', 2) >> getListModel()
1 * metadataService.findByName('floraSurveyDetails', getListModel()) >> getMapModel()
1 * speciesService.searchByScientificName(_) >> getScientificModel()

Expand Down

0 comments on commit dad817b

Please sign in to comment.