diff --git a/grails-app/assets/javascripts/projects.js b/grails-app/assets/javascripts/projects.js index 0b49350a8..4dd0ba254 100644 --- a/grails-app/assets/javascripts/projects.js +++ b/grails-app/assets/javascripts/projects.js @@ -74,6 +74,7 @@ function isValid(p, a) { } function ProjectViewModel(project) { + project.geographicInfo = project.geographicInfo || {}; var self = this; // documents var docDefaults = newDocumentDefaults(project); @@ -175,6 +176,14 @@ function ProjectViewModel(project) { self.urlWeb = ko.observable(project.urlWeb).extend({url:true}); self.contractStartDate = ko.observable(project.contractStartDate).extend({simpleDate: false}); self.contractEndDate = ko.observable(project.contractEndDate).extend({simpleDate: false}); + self.geographicInfo = { + nationwide: ko.observable(project.geographicInfo.nationwide || false), + isDefault: ko.observable(project.geographicInfo.isDefault || false), + primaryState: ko.observable(project.geographicInfo.primaryState), + primaryElectorate: ko.observable(project.geographicInfo.primaryElectorate), + otherStates: ko.observableArray(project.geographicInfo.otherStates || []), + otherElectorates: ko.observableArray(project.geographicInfo.otherElectorates || []) + }; self.transients.programs = []; self.transients.subprograms = {}; self.transients.subprogramsToDisplay = ko.computed(function () { @@ -397,6 +406,62 @@ function ProjectViewModel(project) { self.associatedProgram(project.associatedProgram); // to trigger the computation of sub-programs }; + self.transients.states = ko.observableArray([]); + self.transients.states.filteredStates = ko.computed(function() { + var primaryState = self.geographicInfo.primaryState(), states = self.transients.states().concat([]); + if (primaryState) { + var index = states.indexOf(primaryState); + if (index > -1) { + states.splice(index, 1); + } + } + + return states; + }); + self.transients.electorates = ko.observableArray([]); + self.transients.electorates.filteredElectorates = ko.computed(function() { + var primaryElectorate = self.geographicInfo.primaryElectorate(), electorates = self.transients.electorates().concat([]); + if (primaryElectorate) { + var index = electorates.indexOf(primaryElectorate); + if (index > -1) { + electorates.splice(index, 1); + } + } + + return electorates; + }); + + self.loadStatesAndElectorates = function() { + var promise1 = $.getJSON(fcConfig.listOfStatesUrl, function(data) { + var states = []; + $.each(data, function(i, state) { + states.push(state.name); + }); + + self.transients.states(states); + }); + + var promse2 = $.getJSON(fcConfig.listOfElectoratesUrl, function(data) { + var electorates = []; + $.each(data, function(i, electorate) { + electorates.push(electorate.name); + }); + + self.transients.electorates(electorates); + }); + + $.when(promise1, promse2).done(self.loadGeographicInfo); + } + + self.loadGeographicInfo = function () { + self.geographicInfo.nationwide(project.geographicInfo.nationwide); + self.geographicInfo.isDefault(project.geographicInfo.isDefault); + self.geographicInfo.primaryState(project.geographicInfo.primaryState); + self.geographicInfo.primaryElectorate(project.geographicInfo.primaryElectorate); + self.geographicInfo.otherStates(project.geographicInfo.otherStates); + self.geographicInfo.otherElectorates(project.geographicInfo.otherElectorates); + } + self.toJS = function() { var toIgnore = self.ignore; // document properties to ignore. toIgnore.concat(['transients', 'daysStatus', 'projectDatesChanged', 'collectoryInstitutionId', 'ignore', 'projectStatus']); @@ -891,6 +956,7 @@ function ProjectPageViewModel(project, sites, activities, userRoles, config) { tags: self.tags(), promoteOnHomepage: self.promoteOnHomepage(), externalIds: ko.mapping.toJS(self.externalIds), + geographicInfo: ko.mapping.toJS(self.geographicInfo), options: { changeActivityDates: self.changeActivityDates(), includeSubmittedReports: self.includeSubmittedReports(), @@ -1362,4 +1428,4 @@ var RisksReportViewModel = function(project, options) { self.generateRisksReportPDF = function() { displayReport(options.riskChangesReportPdfUrl); }; -}; +}; \ No newline at end of file diff --git a/grails-app/conf/application.groovy b/grails-app/conf/application.groovy index b3e0d3bd9..1eea485be 100644 --- a/grails-app/conf/application.groovy +++ b/grails-app/conf/application.groovy @@ -282,6 +282,9 @@ sites.known_shapes = [ [id:'cl11194', name:'Australian Marine Parks (2024)'] ] +layers.elect = 'cl11163' +layers.states = 'cl927' + environments { development { grails.logging.jul.usebridge = true diff --git a/grails-app/controllers/au/org/ala/merit/ProjectController.groovy b/grails-app/controllers/au/org/ala/merit/ProjectController.groovy index 3aa643bcd..ac8696f8f 100644 --- a/grails-app/controllers/au/org/ala/merit/ProjectController.groovy +++ b/grails-app/controllers/au/org/ala/merit/ProjectController.groovy @@ -86,6 +86,10 @@ class ProjectController { user.hasViewAccess = projectService.canUserViewProject(user.userId, id) ?: false } def project = projectService.get(id, user,'all') + Map stateElectorate = projectService.findStateAndElectorateForProject(project.projectId) + if (stateElectorate) { + project << stateElectorate + } Map config = null if (project && !project.error) { config = projectService.getProgramConfiguration(project) @@ -1236,6 +1240,11 @@ class ProjectController { render reportData as JSON } + def spatialFeatures (String layerId) { + webService.proxyGetRequest(response, grailsApplication.config.getProperty('ecodata.baseUrl') + "spatial/features?layerId=${layerId}", false, true, 120000) + return null + } + private def error(String message, String projectId) { flash.message = message if (projectId) { diff --git a/grails-app/services/au/org/ala/merit/ProjectService.groovy b/grails-app/services/au/org/ala/merit/ProjectService.groovy index e99cc5874..761357552 100644 --- a/grails-app/services/au/org/ala/merit/ProjectService.groovy +++ b/grails-app/services/au/org/ala/merit/ProjectService.groovy @@ -66,6 +66,15 @@ class ProjectService { } + Map findStateAndElectorateForProject(String projectId) { + Map result = webService.getJson(grailsApplication.config.getProperty('ecodata.baseUrl') + 'project/findStateAndElectorateForProject?projectId=' + projectId) as Map + if (result.error) { + result = [:] + } + + result + } + void filterDataSetSummaries(List dataSetSummaries) { List forms = activityService.monitoringProtocolForms() diff --git a/grails-app/views/project/_editProject.gsp b/grails-app/views/project/_editProject.gsp index 5f8e4c071..80562028b 100644 --- a/grails-app/views/project/_editProject.gsp +++ b/grails-app/views/project/_editProject.gsp @@ -262,6 +262,73 @@ +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Geographic information
+ + + +
+ + + +
+ + + +
+ + + +
+ + +
+ + +
+
+ + +
+
+
+
+
+
diff --git a/grails-app/views/project/_geographicInfo.gsp b/grails-app/views/project/_geographicInfo.gsp new file mode 100644 index 000000000..c656def76 --- /dev/null +++ b/grails-app/views/project/_geographicInfo.gsp @@ -0,0 +1,33 @@ + + +

Geographic range

+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
Primary State${project.primarystate}
Other State(s)${project.otherstate}
Primary Electorate${project.primaryelect}
Other Electorate(s)${project.otherelect}
+
+
+
+
diff --git a/grails-app/views/project/_overview.gsp b/grails-app/views/project/_overview.gsp index 301be8c55..0b085a8ce 100644 --- a/grails-app/views/project/_overview.gsp +++ b/grails-app/views/project/_overview.gsp @@ -196,6 +196,7 @@
+
diff --git a/grails-app/views/project/index.gsp b/grails-app/views/project/index.gsp index 81e82440b..f42ce6697 100644 --- a/grails-app/views/project/index.gsp +++ b/grails-app/views/project/index.gsp @@ -1,4 +1,5 @@ <%@ page import="au.org.ala.merit.config.ProgramConfig; au.org.ala.merit.ProjectController" contentType="text/html;charset=UTF-8" expressionCodec="none"%> + @@ -82,6 +83,8 @@ projectScoresUrl: "${createLink(action:'serviceScores', id:project.projectId)}", healthCheckUrl: "${createLink(controller:'ajax', action:'keepSessionAlive')}", projectDatesValidationUrl: "${createLink(controller:'project', action:'ajaxValidateProjectDates', id:project.projectId)}", + listOfStatesUrl: "${createLink(controller:'project', action:'spatialFeatures', params: [layerId: "${grailsApplication.config.getProperty('layers.states')}"])}", + listOfElectoratesUrl: "${createLink(controller:'project', action:'spatialFeatures', params: [layerId: "${grailsApplication.config.getProperty('layers.elect')}"])}", spinnerUrl: "${asset.assetPath(src:'loading.gif')}", projectSitesUrl: "${createLink(action:'ajaxProjectSites', id:project.projectId)}", useGoogleBaseMap: ${grails.util.Environment.current == grails.util.Environment.PRODUCTION}, @@ -346,6 +349,7 @@ var config = { project.mapFeatures = $.parseJSON('${mapFeatures?.encodeAsJavaScript()}'); var viewModel = new ProjectPageViewModel(project, project.sites, project.activities || [], userRoles, config); viewModel.loadPrograms(programs); + viewModel.loadStatesAndElectorates(); ko.applyBindings(viewModel); window.validateProjectEndDate = viewModel.validateProjectEndDate; diff --git a/package-lock.json b/package-lock.json index 5febadea4..f59009faa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1254,9 +1254,9 @@ } }, "node_modules/cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", "dev": true, "engines": { "node": ">= 0.6" @@ -1546,9 +1546,9 @@ "dev": true }, "node_modules/elliptic": { - "version": "6.5.7", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.7.tgz", - "integrity": "sha512-ESVCtTwiA+XhY3wyh24QqRGBoP3rEdDUl3EDUUo9tft074fi19IrdpH7hLCMMP3CIj7jb3W96rn8lt/BqIlt5Q==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.0.tgz", + "integrity": "sha512-dpwoQcLc/2WLQvJvLRHKZ+f9FgOdjnq11rurqwekGQygGPsYSK29OMMD2WalatiqQ+XGFDglTNixpPfI+lpaAA==", "dependencies": { "bn.js": "^4.11.9", "brorand": "^1.1.0", @@ -1589,9 +1589,9 @@ } }, "node_modules/engine.io": { - "version": "6.5.5", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.5.tgz", - "integrity": "sha512-C5Pn8Wk+1vKBoHghJODM63yk8MvrO9EWZUfkAt5HAqIgPE4/8FF0PEGHXtEd40l223+cE5ABWuPzm38PHFXfMA==", + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.2.tgz", + "integrity": "sha512-gmNvsYi9C8iErnZdVcJnvCpSKbWTt1E8+JZo8b+daLninywUWi5NQ5STSHZ9rFjFO7imNcvb8Pc5pe/wMR5xEw==", "dev": true, "dependencies": { "@types/cookie": "^0.4.1", @@ -1599,7 +1599,7 @@ "@types/node": ">=10.0.0", "accepts": "~1.3.4", "base64id": "2.0.0", - "cookie": "~0.4.1", + "cookie": "~0.7.2", "cors": "~2.8.5", "debug": "~4.3.1", "engine.io-parser": "~5.2.1", @@ -1610,21 +1610,21 @@ } }, "node_modules/engine.io-parser": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.2.tgz", - "integrity": "sha512-RcyUFKA93/CXH20l4SoVvzZfrSDMOTUS3bWVpTt2FuFP+XYrL8i8oonHP7WInRyVHXh0n/ORtoeiE1os+8qkSw==", + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", + "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", "dev": true, "engines": { "node": ">=10.0.0" } }, "node_modules/engine.io/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "dev": true, "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -1636,9 +1636,9 @@ } }, "node_modules/engine.io/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, "node_modules/ent": { @@ -3796,16 +3796,16 @@ } }, "node_modules/socket.io": { - "version": "4.7.5", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.5.tgz", - "integrity": "sha512-DmeAkF6cwM9jSfmp6Dr/5/mfMwb5Z5qRrSXLpo3Fq5SqyU8CMF15jIN4ZhfSwu35ksM1qmHZDQ/DK5XTccSTvA==", + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.0.tgz", + "integrity": "sha512-8U6BEgGjQOfGz3HHTYaC/L1GaxDCJ/KM0XTkJly0EhZ5U/du9uNEZy4ZgYzEzIqlx2CMm25CrCqr1ck899eLNA==", "dev": true, "dependencies": { "accepts": "~1.3.4", "base64id": "~2.0.0", "cors": "~2.8.5", "debug": "~4.3.2", - "engine.io": "~6.5.2", + "engine.io": "~6.6.0", "socket.io-adapter": "~2.5.2", "socket.io-parser": "~4.2.4" }, @@ -5561,9 +5561,9 @@ } }, "cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", "dev": true }, "core-util-is": { @@ -5807,9 +5807,9 @@ "dev": true }, "elliptic": { - "version": "6.5.7", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.7.tgz", - "integrity": "sha512-ESVCtTwiA+XhY3wyh24QqRGBoP3rEdDUl3EDUUo9tft074fi19IrdpH7hLCMMP3CIj7jb3W96rn8lt/BqIlt5Q==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.0.tgz", + "integrity": "sha512-dpwoQcLc/2WLQvJvLRHKZ+f9FgOdjnq11rurqwekGQygGPsYSK29OMMD2WalatiqQ+XGFDglTNixpPfI+lpaAA==", "requires": { "bn.js": "^4.11.9", "brorand": "^1.1.0", @@ -5849,9 +5849,9 @@ } }, "engine.io": { - "version": "6.5.5", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.5.tgz", - "integrity": "sha512-C5Pn8Wk+1vKBoHghJODM63yk8MvrO9EWZUfkAt5HAqIgPE4/8FF0PEGHXtEd40l223+cE5ABWuPzm38PHFXfMA==", + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.2.tgz", + "integrity": "sha512-gmNvsYi9C8iErnZdVcJnvCpSKbWTt1E8+JZo8b+daLninywUWi5NQ5STSHZ9rFjFO7imNcvb8Pc5pe/wMR5xEw==", "dev": true, "requires": { "@types/cookie": "^0.4.1", @@ -5859,7 +5859,7 @@ "@types/node": ">=10.0.0", "accepts": "~1.3.4", "base64id": "2.0.0", - "cookie": "~0.4.1", + "cookie": "~0.7.2", "cors": "~2.8.5", "debug": "~4.3.1", "engine.io-parser": "~5.2.1", @@ -5867,26 +5867,26 @@ }, "dependencies": { "debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "dev": true, "requires": { - "ms": "2.1.2" + "ms": "^2.1.3" } }, "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true } } }, "engine.io-parser": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.2.tgz", - "integrity": "sha512-RcyUFKA93/CXH20l4SoVvzZfrSDMOTUS3bWVpTt2FuFP+XYrL8i8oonHP7WInRyVHXh0n/ORtoeiE1os+8qkSw==", + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", + "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", "dev": true }, "ent": { @@ -7539,16 +7539,16 @@ "dev": true }, "socket.io": { - "version": "4.7.5", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.5.tgz", - "integrity": "sha512-DmeAkF6cwM9jSfmp6Dr/5/mfMwb5Z5qRrSXLpo3Fq5SqyU8CMF15jIN4ZhfSwu35ksM1qmHZDQ/DK5XTccSTvA==", + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.0.tgz", + "integrity": "sha512-8U6BEgGjQOfGz3HHTYaC/L1GaxDCJ/KM0XTkJly0EhZ5U/du9uNEZy4ZgYzEzIqlx2CMm25CrCqr1ck899eLNA==", "dev": true, "requires": { "accepts": "~1.3.4", "base64id": "~2.0.0", "cors": "~2.8.5", "debug": "~4.3.2", - "engine.io": "~6.5.2", + "engine.io": "~6.6.0", "socket.io-adapter": "~2.5.2", "socket.io-parser": "~4.2.4" },