From 6ad1b015aa6fbc9ca51b5cc766dc44adc55a6867 Mon Sep 17 00:00:00 2001 From: Tor-Einar Skog <tor-einar.skog@nibio.no> Date: Wed, 20 Sep 2023 13:53:21 +0200 Subject: [PATCH] Feature: FireBlight map: First draft of nursery/apiary site layer --- pom.xml | 2 +- .../session/PointOfInterestBean.java | 1 + .../vips/logic/entity/PointOfInterest.java | 3 + .../entity/PointOfInterestTypeApiarySite.java | 36 + .../entity/PointOfInterestTypeNursery.java | 36 + .../nibio/vips/logic/service/POIService.java | 24 + .../db/migration/V14__POI_type_added.sql | 38 + .../vips/logic/i18n/vipslogictexts.properties | 2 + .../logic/i18n/vipslogictexts_bs.properties | 2 + .../logic/i18n/vipslogictexts_hr.properties | 2 + .../logic/i18n/vipslogictexts_nb.properties | 2 + .../logic/i18n/vipslogictexts_sr.properties | 2 + .../i18n/vipslogictexts_zh_CN.properties | 2 + .../map_applications/fireblight/js/map.js | 912 ++++++++++-------- src/main/webapp/templates/poiForm.ftl | 2 +- 15 files changed, 665 insertions(+), 401 deletions(-) create mode 100644 src/main/java/no/nibio/vips/logic/entity/PointOfInterestTypeApiarySite.java create mode 100644 src/main/java/no/nibio/vips/logic/entity/PointOfInterestTypeNursery.java create mode 100644 src/main/resources/db/migration/V14__POI_type_added.sql diff --git a/pom.xml b/pom.xml index f0953827..3b94a9fa 100755 --- a/pom.xml +++ b/pom.xml @@ -217,7 +217,7 @@ <dependency> <groupId>no.nibio.vips</groupId> <artifactId>VIPSCommon</artifactId> - <version>2022.1</version> + <version>2.0.8-SNAPSHOT</version> </dependency> <dependency> <groupId>javax</groupId> diff --git a/src/main/java/no/nibio/vips/logic/controller/session/PointOfInterestBean.java b/src/main/java/no/nibio/vips/logic/controller/session/PointOfInterestBean.java index 8516bd86..fbe1d3e7 100755 --- a/src/main/java/no/nibio/vips/logic/controller/session/PointOfInterestBean.java +++ b/src/main/java/no/nibio/vips/logic/controller/session/PointOfInterestBean.java @@ -395,6 +395,7 @@ public class PointOfInterestBean { { GISUtil gisUtil = new GISUtil(); poi.addProperty("pointOfInterestId", poi.getPointOfInterestId()); + poi.addProperty("pointOfInterestTypeId", poi.getPointOfInterestTypeId()); if(poi.getGisGeom() != null) { diff --git a/src/main/java/no/nibio/vips/logic/entity/PointOfInterest.java b/src/main/java/no/nibio/vips/logic/entity/PointOfInterest.java index 2c22c7db..796d7816 100755 --- a/src/main/java/no/nibio/vips/logic/entity/PointOfInterest.java +++ b/src/main/java/no/nibio/vips/logic/entity/PointOfInterest.java @@ -48,6 +48,7 @@ import javax.persistence.DiscriminatorValue; import javax.persistence.FetchType; import javax.persistence.OneToMany; import no.nibio.vips.gis.GISUtil; +import org.wololo.geojson.Feature; /** * @copyright 2017 <a href="http://www.nibio.no/">NIBIO</a> @@ -64,6 +65,7 @@ import no.nibio.vips.gis.GISUtil; @NamedQuery(name = "PointOfInterest.findByPointOfInterestId", query = "SELECT p FROM PointOfInterest p WHERE p.pointOfInterestId = :pointOfInterestId"), @NamedQuery(name = "PointOfInterest.findByPointOfInterestIds", query = "SELECT p FROM PointOfInterest p WHERE p.pointOfInterestId IN :pointOfInterestIds"), @NamedQuery(name = "PointOfInterest.findByOrganizationId", query = "SELECT p FROM PointOfInterest p WHERE p.user IN(SELECT u.userId FROM VipsLogicUser u WHERE u.organizationId=:organizationId OR u.organizationId IN (SELECT o.organizationId FROM Organization o WHERE o.parentOrganizationId = :organizationId)) ORDER BY p.name ASC"), + @NamedQuery(name = "PointOfInterest.findByOrganizationIdAndPoiTypes", query = "SELECT p FROM PointOfInterest p WHERE p.pointOfInterestTypeId in :pointOfInterestTypes AND p.user IN(SELECT u.userId FROM VipsLogicUser u WHERE u.organizationId=:organizationId OR u.organizationId IN (SELECT o.organizationId FROM Organization o WHERE o.parentOrganizationId = :organizationId)) ORDER BY p.name ASC"), @NamedQuery(name = "PointOfInterest.findForecastLocationsByOrganizationId", query = "SELECT p FROM PointOfInterest p WHERE p.isForecastLocation IS TRUE AND p.user IN(SELECT u.userId FROM VipsLogicUser u WHERE u.organizationId=:organizationId OR u.organizationId IN (SELECT o.organizationId FROM Organization o WHERE o.parentOrganizationId = :organizationId)) ORDER BY p.name ASC"), @NamedQuery(name = "PointOfInterest.findByName", query = "SELECT p FROM PointOfInterest p WHERE p.name = :name"), @NamedQuery(name = "PointOfInterest.findByNameCaseInsensitive", query = "SELECT p FROM PointOfInterest p WHERE lower(p.name) = lower(:name)"), @@ -357,6 +359,7 @@ public class PointOfInterest implements Serializable, Comparable { public String getGeoJSON() { this.addProperty("pointOfInterestId", this.getPointOfInterestId()); + this.addProperty("pointOfInterestTypeId", this.getPointOfInterestTypeId()); return this.gisUtil.getGeoJSONFromGeometry(this.getGisGeom(), this.getProperties()); } diff --git a/src/main/java/no/nibio/vips/logic/entity/PointOfInterestTypeApiarySite.java b/src/main/java/no/nibio/vips/logic/entity/PointOfInterestTypeApiarySite.java new file mode 100644 index 00000000..58e0e462 --- /dev/null +++ b/src/main/java/no/nibio/vips/logic/entity/PointOfInterestTypeApiarySite.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2020 NIBIO <http://www.nibio.no/>. + * + * This file is part of VIPSLogic. + * VIPSLogic is free software: you can redistribute it and/or modify + * it under the terms of the NIBIO Open Source License as published by + * NIBIO, either version 1 of the License, or (at your option) any + * later version. + * + * VIPSLogic is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * NIBIO Open Source License for more details. + * + * You should have received a copy of the NIBIO Open Source License + * along with VIPSLogic. If not, see <http://www.nibio.no/licenses/>. + * + */ + +package no.nibio.vips.logic.entity; + +import java.io.Serializable; +import javax.persistence.DiscriminatorValue; +import javax.persistence.Entity; +import javax.persistence.Table; + +/** + * @copyright 2023 <a href="http://www.nibio.no/">NIBIO</a> + * @author Tor-Einar Skog <tor-einar.skog@nibio.no> + */ +@Entity +@DiscriminatorValue("6") +@Table(name = "point_of_interest_apiary_site") +public class PointOfInterestTypeApiarySite extends PointOfInterest implements Serializable { + +} diff --git a/src/main/java/no/nibio/vips/logic/entity/PointOfInterestTypeNursery.java b/src/main/java/no/nibio/vips/logic/entity/PointOfInterestTypeNursery.java new file mode 100644 index 00000000..18565569 --- /dev/null +++ b/src/main/java/no/nibio/vips/logic/entity/PointOfInterestTypeNursery.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2020 NIBIO <http://www.nibio.no/>. + * + * This file is part of VIPSLogic. + * VIPSLogic is free software: you can redistribute it and/or modify + * it under the terms of the NIBIO Open Source License as published by + * NIBIO, either version 1 of the License, or (at your option) any + * later version. + * + * VIPSLogic is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * NIBIO Open Source License for more details. + * + * You should have received a copy of the NIBIO Open Source License + * along with VIPSLogic. If not, see <http://www.nibio.no/licenses/>. + * + */ + +package no.nibio.vips.logic.entity; + +import java.io.Serializable; +import javax.persistence.DiscriminatorValue; +import javax.persistence.Entity; +import javax.persistence.Table; + +/** + * @copyright 2023 <a href="http://www.nibio.no/">NIBIO</a> + * @author Tor-Einar Skog <tor-einar.skog@nibio.no> + */ +@Entity +@DiscriminatorValue("7") +@Table(name = "point_of_interest_nursery") +public class PointOfInterestTypeNursery extends PointOfInterest implements Serializable { + +} diff --git a/src/main/java/no/nibio/vips/logic/service/POIService.java b/src/main/java/no/nibio/vips/logic/service/POIService.java index 7ef5783d..32839ba2 100644 --- a/src/main/java/no/nibio/vips/logic/service/POIService.java +++ b/src/main/java/no/nibio/vips/logic/service/POIService.java @@ -46,6 +46,9 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import com.webcohesion.enunciate.metadata.Facet; import com.webcohesion.enunciate.metadata.rs.TypeHint; +import java.util.Arrays; +import java.util.stream.Collectors; +import javax.ws.rs.QueryParam; import no.nibio.vips.gis.GISUtil; import no.nibio.vips.logic.entity.Country; @@ -97,6 +100,27 @@ public class POIService { PointOfInterest retVal = SessionControllerGetter.getPointOfInterestBean().getPointOfInterest(pointOfInterestId); return Response.ok().entity(retVal).build(); } + + /** + * @param organizationId Id of the organization in question + * @param poiTypesStr Comma separated list of poiTypes + * @return GeoJson with pois filtered by organization and type + */ + @GET + @Path("organization/{organizationId}/type/geojson") + @Produces("application/json;charset=UTF-8") + @TypeHint(PointOfInterest.class) + public Response getPoisByPoiTypesAsGeoJson( + @PathParam("organizationId") Integer organizationId, + @QueryParam("poiTypes") String poiTypesStr + ) + { + List<Integer> poiTypes = Arrays.asList(poiTypesStr.split(",")).stream().map(str->Integer.valueOf(str)).collect(Collectors.toList()); + Organization organization = SessionControllerGetter.getUserBean().getOrganization(organizationId); + List<PointOfInterest> pois = SessionControllerGetter.getPointOfInterestBean().getPoisForOrganizationAndOfTypes(organization, poiTypes); + + return Response.ok().entity(SessionControllerGetter.getPointOfInterestBean().getPoisAsGeoJson(pois)).build(); + } /** * Find a POI (Point of interest) by name diff --git a/src/main/resources/db/migration/V14__POI_type_added.sql b/src/main/resources/db/migration/V14__POI_type_added.sql new file mode 100644 index 00000000..2fcdf8bb --- /dev/null +++ b/src/main/resources/db/migration/V14__POI_type_added.sql @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2020 NIBIO <http://www.nibio.no/>. + * + * This file is part of VIPSLogic. + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ +/** + * Author: Tor-Einar Skog <tor-einar.skog@nibio.no> + * Created: September 18th, 2023 + */ + +-- Create POI type apiary site (birøkterplass) as entity +CREATE TABLE public.point_of_interest_apiary_site ( + point_of_interest_id INTEGER REFERENCES public.point_of_interest(point_of_interest_id) PRIMARY KEY REFERENCES public.point_of_interest(point_of_interest_id) +); + +INSERT INTO public.point_of_interest_type (point_of_interest_type_id, default_name) +VALUES (6, 'Apiary site'); + +-- Create POI type nursery as entity +CREATE TABLE public.point_of_interest_nursery ( + point_of_interest_id INTEGER REFERENCES public.point_of_interest(point_of_interest_id) PRIMARY KEY REFERENCES public.point_of_interest(point_of_interest_id) +); + +INSERT INTO public.point_of_interest_type (point_of_interest_type_id, default_name) +VALUES (7, 'Nursery'); \ No newline at end of file diff --git a/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts.properties b/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts.properties index a2c3609a..947d27d1 100755 --- a/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts.properties +++ b/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts.properties @@ -1044,3 +1044,5 @@ LEAFBLOTCH=Leaf blotch model universalMessageSettingsLink_tpl=To edit your notification subscriptions, please use this link: {0} pointOfInterestType_5=Trap sowingDate=Sowing date +pointOfInterestType_6=Apiary site +pointOfInterestType_7=Nursery diff --git a/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_bs.properties b/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_bs.properties index 9789f83e..fe09b88c 100755 --- a/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_bs.properties +++ b/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_bs.properties @@ -1038,3 +1038,5 @@ LEAFBLOTCH=Leaf blotch model universalMessageSettingsLink_tpl=To edit your VIPS notification subscriptions, please use this link: {0} pointOfInterestType_5=Trap sowingDate=Sowing date +pointOfInterestType_6=Apiary site +pointOfInterestType_7=Nursery diff --git a/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_hr.properties b/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_hr.properties index 59e50597..ebcccfcd 100755 --- a/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_hr.properties +++ b/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_hr.properties @@ -1036,3 +1036,5 @@ LEAFBLOTCH=Leaf blotch model universalMessageSettingsLink_tpl=To edit your notification subscriptions, please use this link: {0} pointOfInterestType_5=Trap sowingDate=Sowing date +pointOfInterestType_6=Apiary site +pointOfInterestType_7=Nursery diff --git a/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_nb.properties b/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_nb.properties index 0eeeb052..2e80c64e 100755 --- a/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_nb.properties +++ b/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_nb.properties @@ -1044,3 +1044,5 @@ LEAFBLOTCH=Bladflekksjukdomsmodell universalMessageSettingsLink_tpl=For \u00e5 endre dine abonnement p\u00e5 push-varsler fra VIPS, bruk denne lenken: {0} pointOfInterestType_5=Felle sowingDate=S\u00e5dato +pointOfInterestType_6=Big\u00e5rdsplass +pointOfInterestType_7=Planteskole diff --git a/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_sr.properties b/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_sr.properties index d8b6a735..a431e5ec 100755 --- a/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_sr.properties +++ b/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_sr.properties @@ -1038,3 +1038,5 @@ LEAFBLOTCH=Leaf blotch model universalMessageSettingsLink_tpl=To edit your notification subscriptions, please use this link: {0} pointOfInterestType_5=Trap sowingDate=Sowing date +pointOfInterestType_6=Apiary site +pointOfInterestType_7=Nursery diff --git a/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_zh_CN.properties b/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_zh_CN.properties index 7f748c1d..27b71513 100755 --- a/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_zh_CN.properties +++ b/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_zh_CN.properties @@ -1032,3 +1032,5 @@ LEAFBLOTCH=Leaf blotch model universalMessageSettingsLink_tpl=To edit your notification subscriptions, please use this link: {0} pointOfInterestType_5=Trap sowingDate=Sowing date +pointOfInterestType_6=Apiary site +pointOfInterestType_7=Nursery diff --git a/src/main/webapp/map_applications/fireblight/js/map.js b/src/main/webapp/map_applications/fireblight/js/map.js index a6b0f098..b9671d45 100755 --- a/src/main/webapp/map_applications/fireblight/js/map.js +++ b/src/main/webapp/map_applications/fireblight/js/map.js @@ -1,5 +1,5 @@ -// The globally available map object -var map, featureOverlay, newFeatureOverlay; +// The globally available map objects +var map, featureOverlay, newFeatureOverlay, diseaseSpreadingPoisOverlay; // Override localization settings for this particular web page var hardcodedLanguage = "nb"; @@ -7,235 +7,354 @@ var hardcodedLanguage = "nb"; // If false, touching map will not create a new item var registration = false; var geolocation; -function initMap() +async function initMap() { - + var features = new ol.Collection(); -var iconRadius = 10; - -var styles = { - // Bulkemispel = rød - 'cotoneaster bullatus': [new ol.style.Style({ - image: new ol.style.Circle({ - fill: new ol.style.Fill({ color: [255,0,0,1] }), - stroke: new ol.style.Stroke({width: 1, color: [0,0,0,1] }), - radius: iconRadius - }) - })], - // Sprikemispel = dyp oransje - 'cotoneaster divaricata': [new ol.style.Style({ - image: new ol.style.Circle({ - fill: new ol.style.Fill({ color: [239,133,19,1] }), - stroke: new ol.style.Stroke({width: 1, color: [0,0,0,1] }), - radius: iconRadius - }) - })], - // Pilemispel = gul - 'cotoneaster salicifolia': [new ol.style.Style({ - image: new ol.style.Circle({ - fill: new ol.style.Fill({ color: [239,236,19,1] }), - stroke: new ol.style.Stroke({width: 1, color: [0,0,0,1] }), - radius: iconRadius - }) - })], - // Eple = grønn - 'malus domestica': [new ol.style.Style({ - image: new ol.style.Circle({ - fill: new ol.style.Fill({ color: [0,255,0,1] }), - stroke: new ol.style.Stroke({ width: 1, color: [0,0,0,1] }), - radius: iconRadius - }) - })], - // Pære = grågrønn - 'pyrus communis': [new ol.style.Style({ - image: new ol.style.Circle({ - fill: new ol.style.Fill({ color: [122,175,131,1] }), - stroke: new ol.style.Stroke({width: 1, color: [0,0,0,1] }), - radius: iconRadius - }) - })], - // Planteriket = blå - 'plantae': [new ol.style.Style({ - image: new ol.style.Circle({ - fill: new ol.style.Fill({ color: [0,0,255,1] }), - stroke: new ol.style.Stroke({ width: 1, color: [0,0,0,1] }), - radius: iconRadius - }) - }) - ] -}; - - featureOverlay = new ol.layer.Vector({ - source: new ol.source.Vector({ - features: features - }), - style: function(feature, resolution){ - // Site that has been cleared is all black - var observationData = JSON.parse(feature.get("observationData")); - if(observationData["tiltak"] == "Ryddet" && observationData["symptom"] == "Ikke symptom") - { - return [new ol.style.Style({ + var iconRadius = 10; + + var styles = { + // Bulkemispel = rød + 'cotoneaster bullatus': [new ol.style.Style({ image: new ol.style.Circle({ - fill: new ol.style.Fill({ color: [0,0,0,1] }), - stroke: new ol.style.Stroke({ color: [0,0,0,1] }), + fill: new ol.style.Fill({color: [255, 0, 0, 1]}), + stroke: new ol.style.Stroke({width: 1, color: [0, 0, 0, 1]}), radius: iconRadius }) - })]; - } - else if(observationData["tiltak"] == "Ryddet" && observationData["symptom"] == "Symptom") - { - return [new ol.style.Style({ + })], + // Sprikemispel = dyp oransje + 'cotoneaster divaricata': [new ol.style.Style({ image: new ol.style.Circle({ - fill: new ol.style.Fill({ color: [255,255,255,1] }), - stroke: new ol.style.Stroke({ width: 8, color: [0,0,0,1] }), + fill: new ol.style.Fill({color: [239, 133, 19, 1]}), + stroke: new ol.style.Stroke({width: 1, color: [0, 0, 0, 1]}), radius: iconRadius }) - })]; - } + })], + // Pilemispel = gul + 'cotoneaster salicifolia': [new ol.style.Style({ + image: new ol.style.Circle({ + fill: new ol.style.Fill({color: [239, 236, 19, 1]}), + stroke: new ol.style.Stroke({width: 1, color: [0, 0, 0, 1]}), + radius: iconRadius + }) + })], + // Eple = grønn + 'malus domestica': [new ol.style.Style({ + image: new ol.style.Circle({ + fill: new ol.style.Fill({color: [0, 255, 0, 1]}), + stroke: new ol.style.Stroke({width: 1, color: [0, 0, 0, 1]}), + radius: iconRadius + }) + })], + // Pære = grågrønn + 'pyrus communis': [new ol.style.Style({ + image: new ol.style.Circle({ + fill: new ol.style.Fill({color: [122, 175, 131, 1]}), + stroke: new ol.style.Stroke({width: 1, color: [0, 0, 0, 1]}), + radius: iconRadius + }) + })], + // Planteriket = blå + 'plantae': [new ol.style.Style({ + image: new ol.style.Circle({ + fill: new ol.style.Fill({color: [0, 0, 255, 1]}), + stroke: new ol.style.Stroke({width: 1, color: [0, 0, 0, 1]}), + radius: iconRadius + }) + }) + ] + }; + + featureOverlay = new ol.layer.Vector({ + source: new ol.source.Vector({ + features: features + }), + style: function (feature, resolution) { + // Site that has been cleared is all black + var observationData = JSON.parse(feature.get("observationData")); + if (observationData["tiltak"] == "Ryddet" && observationData["symptom"] == "Ikke symptom") + { + return [new ol.style.Style({ + image: new ol.style.Circle({ + fill: new ol.style.Fill({color: [0, 0, 0, 1]}), + stroke: new ol.style.Stroke({color: [0, 0, 0, 1]}), + radius: iconRadius + }) + })]; + } else if (observationData["tiltak"] == "Ryddet" && observationData["symptom"] == "Symptom") + { + return [new ol.style.Style({ + image: new ol.style.Circle({ + fill: new ol.style.Fill({color: [255, 255, 255, 1]}), + stroke: new ol.style.Stroke({width: 8, color: [0, 0, 0, 1]}), + radius: iconRadius + }) + })]; + } - var retVal = null; - if(feature.get("cropOrganism") != null && feature.get("cropOrganism")["latinName"] != null) - { - retVal = styles[feature.get("cropOrganism")["latinName"].toLowerCase()]; - } - else - { - retVal = styles["plantae"]; - } - //console.info(retVal[0].getImage().getStroke().getWidth()); - // If symptom has been registered, mark with inner black dot - if(observationData["symptom"] == "Symptom") - { + var retVal = null; + if (feature.get("cropOrganism") != null && feature.get("cropOrganism")["latinName"] != null) + { + retVal = styles[feature.get("cropOrganism")["latinName"].toLowerCase()]; + } else + { + retVal = styles["plantae"]; + } + //console.info(retVal[0].getImage().getStroke().getWidth()); + // If symptom has been registered, mark with inner black dot + if (observationData["symptom"] == "Symptom") + { retVal = [ - new ol.style.Style({ - image: new ol.style.Circle({ - fill: new ol.style.Fill({ color: [0,0,0,1] }), - stroke: new ol.style.Stroke({ width: 8, color: retVal[0].getImage().getFill().getColor() }), - radius: iconRadius - }) + new ol.style.Style({ + image: new ol.style.Circle({ + fill: new ol.style.Fill({color: [0, 0, 0, 1]}), + stroke: new ol.style.Stroke({width: 8, color: retVal[0].getImage().getFill().getColor()}), + radius: iconRadius }) + }) ]; + } + return retVal; } - return retVal; - } - - }); - - newFeatureOverlay = new ol.layer.Vector({ - source: new ol.source.Vector({ - features: new ol.Collection() - }), - style: [new ol.style.Style({ - image: new ol.style.Circle({ - fill: new ol.style.Fill({ color: [255,255,255,1] }), - stroke: new ol.style.Stroke({ color: [0,0,0,1], width: 3, lineDash: [2,2] }), - radius: 10 - }) - })] - - }); - - - var parser = new ol.format.WMTSCapabilities(); - fetch('https://opencache.statkart.no/gatekeeper/gk/gk.open_wmts?Version=1.0.0&service=wmts&request=getcapabilities').then(function(response) { + + }); + + newFeatureOverlay = new ol.layer.Vector({ + source: new ol.source.Vector({ + features: new ol.Collection() + }), + style: [new ol.style.Style({ + image: new ol.style.Circle({ + fill: new ol.style.Fill({color: [255, 255, 255, 1]}), + stroke: new ol.style.Stroke({color: [0, 0, 0, 1], width: 3, lineDash: [2, 2]}), + radius: 10 + }) + })] + + }); + + + + + /* + + new ol.style.Style({ + image: new ol.style.Circle({ + stroke: new Stroke({color: '#7c8692'}), + radius: 200 / (resolution / viewProjection.getMetersPerUnit() * Math.cos(latitude_rad)), + }), + }); + [new ol.style.Style({ + image: new ol.style.Circle({ + fill: new ol.style.Fill({color: [255, 87, 222, 1]}), + stroke: new ol.style.Stroke({color: [0, 0, 0, 1], width: 3, lineDash: [2, 2]}), + radius: 10 + }) + })] + */ + + + var parser = new ol.format.WMTSCapabilities(); + fetch('https://opencache.statkart.no/gatekeeper/gk/gk.open_wmts?Version=1.0.0&service=wmts&request=getcapabilities').then(function (response) { return response.text(); - }).then(function(text) { + }).then(function (text) { var result = parser.read(text); var options = ol.source.WMTS.optionsFromCapabilities(result, { - layer: 'topo4', - matrixSet: 'EPSG:3857' + layer: 'topo4', + matrixSet: 'EPSG:3857' + }); + var topo4 = + new ol.layer.Tile({ + opacity: 1, + source: new ol.source.WMTS(/** @type {!olx.source.WMTSOptions} */ (options)) + }); + + + diseaseSpreadingPoisOverlay = new ol.layer.Vector({ + source: new ol.source.Vector({ + features: new ol.Collection() + }), + style: diseaseSpreadingPoiStyle }); - var topo4 = - new ol.layer.Tile({ - opacity: 1, - source: new ol.source.WMTS(/** @type {!olx.source.WMTSOptions} */ (options)) - }); - - + map = new ol.Map({ - target: 'map', - layers: [ + target: 'map', + layers: [ //topo2graatone, topo4, //osm, + diseaseSpreadingPoisOverlay, featureOverlay, newFeatureOverlay - ], - view: new ol.View({ + ], + view: new ol.View({ center: ol.proj.fromLonLat([8.5, 60.8]), zoom: 6 - }) - }); + }) + }); + + + + //map.addOverlay(diseaseSpreadingPoisOverlay); + + // Configure geolocation tracker + geolocation = new ol.Geolocation({ + trackingOptions: { + enableHighAccuracy: true + }, + projection: map.getView().getProjection() + }); + var positionFeature = new ol.Feature(); + positionFeature.setStyle( + new ol.style.Style({ + image: new ol.style.Circle({ + radius: 6, + fill: new ol.style.Fill({ + color: '#3399CC', + }), + stroke: new ol.style.Stroke({ + color: '#fff', + width: 2, + }), + }), + }) + ); - // Configure geolocation tracker - geolocation = new ol.Geolocation({ - trackingOptions: { - enableHighAccuracy: true - }, - projection: map.getView().getProjection() - }); - var positionFeature = new ol.Feature(); - positionFeature.setStyle( - new ol.style.Style({ - image: new ol.style.Circle({ - radius: 6, - fill: new ol.style.Fill({ - color: '#3399CC', - }), - stroke: new ol.style.Stroke({ - color: '#fff', - width: 2, - }), - }), - }) - ); - - geolocation.on('change:position', function () { - var coordinates = geolocation.getPosition(); - positionFeature.setGeometry(coordinates ? new ol.geom.Point(coordinates) : null); - }); - - new ol.layer.Vector({ - map: map, - source: new ol.source.Vector({ - features: [positionFeature], - }), - }); + geolocation.on('change:position', function () { + var coordinates = geolocation.getPosition(); + positionFeature.setGeometry(coordinates ? new ol.geom.Point(coordinates) : null); + }); + new ol.layer.Vector({ + map: map, + source: new ol.source.Vector({ + features: [positionFeature] + }) + }); + // TODO feature properties must be synchronized var lastYear = new Date().getFullYear() - 1; // Population the season select list, setting last year as default selected initSeasonSelectList(lastYear); + getAndRenderDiseaseSpreadingPois(); getAndRenderObservations(lastYear); - map.on('click', function(evt){ - //features = [] - var feature = map.forEachFeatureAtPixel( - evt.pixel, function(ft, l) { return ft; } - ); + map.on('click', function (evt) { + //features = [] + var feature = map.forEachFeatureAtPixel( + evt.pixel, function (ft, l) { + return ft; + } + ); - var vectorSource = newFeatureOverlay.getSource(); - // Remove any new features already created - vectorSource.clear(); + var vectorSource = newFeatureOverlay.getSource(); + // Remove any new features already created + vectorSource.clear(); - if (feature && feature.getProperties()["observationId"] != undefined) { - // Create a fake icon for highlighting - var fakeFeature = createFeature(feature.getGeometry().getCoordinates()); - vectorSource.addFeature(fakeFeature); - displayFeature(feature); - } - else if(registration) - { - var newFeature = createFeature(map.getCoordinateFromPixel(evt.pixel)); - vectorSource.addFeature(newFeature); - editFeature(newFeature.getId()); - } + if (feature && feature.getProperties()["observationId"] != undefined) { + // Create a fake icon for highlighting + var fakeFeature = createFeature(feature.getGeometry().getCoordinates()); + vectorSource.addFeature(fakeFeature); + displayFeature(feature); + } else if (registration) + { + var newFeature = createFeature(map.getCoordinateFromPixel(evt.pixel)); + vectorSource.addFeature(newFeature); + editFeature(newFeature.getId()); + } }); - + }); // END FETCH + +} + +let openLayersDefaultStyle = undefined; + +function getOpenLayersDefaultStyle() +{ + if(openLayersDefaultStyle == undefined) + { + var fill = new ol.style.Fill({ + color: 'rgba(255,255,255,0.4)' + }); + var stroke = new ol.style.Stroke({ + color: '#3399CC', + width: 1.25 + }); + openLayersDefaultStyle = [ + new ol.style.Style({ + image: new ol.style.Circle({ + fill: fill, + stroke: stroke, + radius: 5 + }), + fill: fill, + stroke: stroke + }) + ]; + } + return openLayersDefaultStyle; +} + +/** + * Styling the different disease spreading pois + * @param {ol.Feature} feature + * @param {Number} resolution + * @returns {Array} + */ +function diseaseSpreadingPoiStyle(feature, resolution) +{ + if(feature.getGeometry().getType() == "Point") + { + const radiusInMeters = feature.getProperties()["pointOfInterestTypeId"] == "6" ? 5000 + : feature.getProperties()["pointOfInterestTypeId"] == "7" ? 10000 + : 500; + const fillColor = feature.getProperties()["pointOfInterestTypeId"] == "6" ? [255,0, 0, 0.5] + : feature.getProperties()["pointOfInterestTypeId"] == "7" ? [255, 127,127 , 0.5] + : [255, 255, 255, 0.0]; + const viewProjection = map.getView().getProjection(); + const coordsInViewProjection = feature.getGeometry().getCoordinates(); + const longLat = ol.proj.toLonLat(coordsInViewProjection, viewProjection); + const latitude_rad = longLat[1] * Math.PI / 180; + const circle = new ol.style.Style({ + image: new ol.style.Circle({ + fill: new ol.style.Fill({color: fillColor}), + stroke: new ol.style.Stroke({color: [0, 0, 0, 1], width: 5, lineDash: [5, 10], lineCap:"square"}), + radius: radiusInMeters / (resolution / viewProjection.getMetersPerUnit() * Math.cos(latitude_rad)) + }) + }); + + return [circle]; + } + + return getOpenLayersDefaultStyle(); +} + + +function getAndRenderDiseaseSpreadingPois() +{ + fetch("/rest/poi/organization/1/type/geojson?poiTypes=6,7") + .then(response => response.json()) + .then(data => { + let olFeatures = (new ol.format.GeoJSON()).readFeatures( + data, + { + dataProjection: "EPSG:4326", + featureProjection: map.getView().getProjection().getCode() + } + ); + + //sconsole.info(olFeatures); + //console.info(diseaseSpreadingPoisOverlay.getSource()); + diseaseSpreadingPoisOverlay.getSource().clear(); + diseaseSpreadingPoisOverlay.getSource().addFeatures(olFeatures); + + }); + + } /** @@ -246,14 +365,14 @@ var styles = { function getAndRenderObservations(fromSeason) { //console.info("getAndRenderObservations(" + season + ")"); - $.getJSON("/rest/observation/filter/1/geoJSON?from=" + fromSeason + "-01-01&pestId=" + paerebrann.organismId, function(geoData){ + $.getJSON("/rest/observation/filter/1/geoJSON?from=" + fromSeason + "-01-01&pestId=" + paerebrann.organismId, function (geoData) { //console.info(geoData) var format = new ol.format.GeoJSON(); var drawnfeatures = format.readFeatures(geoData, { - //dataProjection: "EPSG:32633", - dataProjection: "EPSG:4326", - featureProjection: map.getView().getProjection().getCode() + //dataProjection: "EPSG:32633", + dataProjection: "EPSG:4326", + featureProjection: map.getView().getProjection().getCode() }); featureOverlay.getSource().clear(); featureOverlay.getSource().addFeatures(drawnfeatures); @@ -264,73 +383,72 @@ function getAndRenderObservations(fromSeason) /** * * @param {type} fromSeason -* @param {type} countyNo + * @param {type} countyNo * @returns {undefined} */ function getAndRenderObservationsForReport(fromSeason, countyNo = "-1") { //console.info("getAndRenderObservations(" + season + ")"); - $.getJSON("/rest/observation/filter/1/geoJSON?from=" + fromSeason + "-01-01&pestId=" + paerebrann.organismId, function(geoData){ + $.getJSON("/rest/observation/filter/1/geoJSON?from=" + fromSeason + "-01-01&pestId=" + paerebrann.organismId, function (geoData) { //console.info(geoData) - // Filter by county - $.getJSON("/corsproxy/https://ws.geonorge.no/kommuneinfo/v1/fylker/" + countyNo + "/omrade") - .always(function(serviceResponse){ - //console.info(geoData); - //console.info(serviceResponse); - - if(parseInt(countyNo) > 0) - { - var filteredFeatures = []; - for(var i=0;i < geoData.features.length;i++) - { - var featureToBeFiltered = geoData.features[i]; - coordinate = proj4("EPSG:4326","EPSG:4258",[featureToBeFiltered.geometry.coordinates[0],featureToBeFiltered.geometry.coordinates[1]]); - // For some weird reason, d3 returns NOT contains in our case - if(!d3.geoContains(serviceResponse.omrade, coordinate)) - { - //console.info(featureToBeFiltered); - filteredFeatures.push(featureToBeFiltered); - } - //console.info(featureToBeFiltered); - } - //console.info(filteredFeatures); - geoData.features = filteredFeatures; - } - - var format = new ol.format.GeoJSON(); - - var drawnfeatures = format.readFeatures(geoData, { - //dataProjection: "EPSG:32633", - dataProjection: "EPSG:4326", - featureProjection: map.getView().getProjection().getCode() - }); - featureOverlay.getSource().clear(); - featureOverlay.getSource().addFeatures(drawnfeatures); - } - ); - }); + // Filter by county + $.getJSON("/corsproxy/https://ws.geonorge.no/kommuneinfo/v1/fylker/" + countyNo + "/omrade") + .always(function (serviceResponse) { + //console.info(geoData); + //console.info(serviceResponse); + + if (parseInt(countyNo) > 0) + { + var filteredFeatures = []; + for (var i = 0; i < geoData.features.length; i++) + { + var featureToBeFiltered = geoData.features[i]; + coordinate = proj4("EPSG:4326", "EPSG:4258", [featureToBeFiltered.geometry.coordinates[0], featureToBeFiltered.geometry.coordinates[1]]); + // For some weird reason, d3 returns NOT contains in our case + if (!d3.geoContains(serviceResponse.omrade, coordinate)) + { + //console.info(featureToBeFiltered); + filteredFeatures.push(featureToBeFiltered); + } + //console.info(featureToBeFiltered); + } + //console.info(filteredFeatures); + geoData.features = filteredFeatures; + } + + var format = new ol.format.GeoJSON(); + + var drawnfeatures = format.readFeatures(geoData, { + //dataProjection: "EPSG:32633", + dataProjection: "EPSG:4326", + featureProjection: map.getView().getProjection().getCode() + }); + featureOverlay.getSource().clear(); + featureOverlay.getSource().addFeatures(drawnfeatures); + } + ); + }); } function toggleRegistration(theButton) { - if(registration) + if (registration) { theButton.title = "Registrering er AV"; - theButton.style.color="white"; - } - else + theButton.style.color = "white"; + } else { theButton.title = "Registrering er PÅ"; - theButton.style.color="red"; + theButton.style.color = "red"; } - registration = ! registration; + registration = !registration; } function toggleTracking(theButton) { - geolocation.setTracking(!geolocation.getTracking()); - theButton.style.backgroundColor = geolocation.getTracking() ? "green" : "rgba(0,60,136,.5)"; - theButton.title = geolocation.getTracking() ? "Vis min posisjon er PÅ" : "Vis min posisjon er AV"; + geolocation.setTracking(!geolocation.getTracking()); + theButton.style.backgroundColor = geolocation.getTracking() ? "green" : "rgba(0,60,136,.5)"; + theButton.title = geolocation.getTracking() ? "Vis min posisjon er PÅ" : "Vis min posisjon er AV"; } /** @@ -338,11 +456,11 @@ function toggleTracking(theButton) * @param {type} coordinate * @returns {createFeature.newFeature|ol.Feature} */ -var createFeature = function(coordinate) +var createFeature = function (coordinate) { - if(coordinate.length == 2) + if (coordinate.length == 2) { - coordinate = [coordinate[0],coordinate[1],0]; + coordinate = [coordinate[0], coordinate[1], 0]; } var point = new ol.geom.Point(coordinate); var newFeature = new ol.Feature({ @@ -351,34 +469,34 @@ var createFeature = function(coordinate) }); newFeature.setId(-1); newFeature.setProperties({ - "observationId": -1, - "observationData": "{\"symptom\":\"\",\"tiltak\":\"\",\"forekomststorrelse\":\"\"}", - "cropOrganism": {}, - "observationText" : "", - "timeOfObservation": moment().valueOf() - }); - + "observationId": -1, + "observationData": "{\"symptom\":\"\",\"tiltak\":\"\",\"forekomststorrelse\":\"\"}", + "cropOrganism": {}, + "observationText": "", + "timeOfObservation": moment().valueOf() + }); + return newFeature; } -var displayFeature = function(feature) +var displayFeature = function (feature) { var featureForm = document.getElementById("featureForm"); - + var observationData = JSON.parse(feature.get("observationData")); var timeOfObservation = new moment(feature.get("timeOfObservation")); var html = [ '<button type="button" onclick="unFocusForm()">X</button>', - '<button type="button" onclick="editFeature(\'', feature.getId() ,'\');">Rediger</button>', + '<button type="button" onclick="editFeature(\'', feature.getId(), '\');">Rediger</button>', '<button type="button" onclick="deleteFeature(' + feature.getId() + ')">Slett</button>', '<h3>Registrering</h3>', '<table>', - '<tr><td>Type</td><td>',getLocalizedOrganismName(feature.get("cropOrganism"),hardcodedLanguage),'</td></tr>', - '<tr><td>Størrelse</td><td>',observationData["forekomststorrelse"],'</td></tr>', - '<tr><td>Symptom</td><td>',observationData["symptom"],'</td></tr>', - '<tr><td>Tiltak</td><td>',observationData["tiltak"],'</td></tr>', - '<tr><td>Beskrivelse</td><td>',feature.get("observationText"),'</td></tr>', - '<tr><td>Dato</td><td>',timeOfObservation.format("DD.MM.YYYY"),'</td></tr>', + '<tr><td>Type</td><td>', getLocalizedOrganismName(feature.get("cropOrganism"), hardcodedLanguage), '</td></tr>', + '<tr><td>Størrelse</td><td>', observationData["forekomststorrelse"], '</td></tr>', + '<tr><td>Symptom</td><td>', observationData["symptom"], '</td></tr>', + '<tr><td>Tiltak</td><td>', observationData["tiltak"], '</td></tr>', + '<tr><td>Beskrivelse</td><td>', feature.get("observationText"), '</td></tr>', + '<tr><td>Dato</td><td>', timeOfObservation.format("DD.MM.YYYY"), '</td></tr>', '</table>' ]; featureForm.innerHTML = html.join(""); @@ -399,26 +517,26 @@ var paerebrann = {}; function initForekomsttyper() { - $.getJSON("/rest/organism/search/latinnames?keywords=" + forekomsttypeLatinskeNavn.join(","), function(data){ - forekomsttyper = data; + $.getJSON("/rest/organism/search/latinnames?keywords=" + forekomsttypeLatinskeNavn.join(","), function (data) { + forekomsttyper = data; }); } -function initPaerebrann(){ - $.getJSON("/rest/organism/search/latinnames?keywords=Erwinia amylovora", function(data){ - if(data.length == 1) - { - paerebrann = data[0]; - initMap(); - } +function initPaerebrann() { + $.getJSON("/rest/organism/search/latinnames?keywords=Erwinia amylovora", function (data) { + if (data.length == 1) + { + paerebrann = data[0]; + initMap(); + } }); } -var getCropOrganism = function(organismId) +var getCropOrganism = function (organismId) { - for(var i=0;i<forekomsttyper.length;i++) + for (var i = 0; i < forekomsttyper.length; i++) { - if(forekomsttyper[i].organismId == organismId) + if (forekomsttyper[i].organismId == organismId) { return forekomsttyper[i]; } @@ -430,54 +548,54 @@ var symptoms = ["Ikke symptom", "Symptom"]; var tiltaks = ["Ikke ryddet", "Ryddet"]; -var editFeature = function(featureId) +var editFeature = function (featureId) { var feature = featureId > 0 ? featureOverlay.getSource().getFeatureById(featureId) - : newFeatureOverlay.getSource().getFeatureById(featureId); + : newFeatureOverlay.getSource().getFeatureById(featureId); var observationData = JSON.parse(feature.get("observationData")); var timeOfObservation = new moment(feature.get("timeOfObservation")); var featureForm = document.getElementById("featureForm"); - var html = - '<button type="button" onclick="unFocusForm()" title="Avbryt">X</button>' + - (featureId > 0 ? '<button type="button" onclick="deleteFeature(' + featureId + ')">Delete</button>' : '') + - '<h3>' + (featureId > 0 ? "R" : "Ny r") + 'egistrering</h3>' + - '<table>' + - '<tr><td>Type</td><td>' + - generateCropSelect("forekomsttype", forekomsttyper, feature.get("cropOrganism")["organismId"]) + - '</td></tr>' + - '<tr><td>Størrelse</td><td>' + - generateSelect("forekomststorrelse", forekomststorrelses, observationData["forekomststorrelse"]) + - '</td></tr>' + - '<tr><td>Symptom</td><td>' + - generateSelect("symptom", symptoms, observationData["symptom"]) + - '</td></tr>' + - '<tr><td>Tiltak</td><td>' + - generateSelect ("tiltak", tiltaks, observationData["tiltak"]) + - '</td></tr>' + - '<tr><td>Beskrivelse</td><td>' + - '<textarea id="beskrivelse" name="beskrivelse">' + (feature.get("observationText") != null ? feature.get("observationText") : "") + '</textarea>' + - '</td></tr>' + - '<tr><td>Dato</td><td>' + - '<input type="text" id="dato" name="dato" size="10" value="'+ timeOfObservation.format("DD.MM.YYYY") + '"/></td></tr>' + - '<tr><td></td><td>' + - '<input type="submit" value="Lagre" onclick="storeFeature(' + feature.getId() + ');"/></td></tr>' + - '</table>'; - - + var html = + '<button type="button" onclick="unFocusForm()" title="Avbryt">X</button>' + + (featureId > 0 ? '<button type="button" onclick="deleteFeature(' + featureId + ')">Delete</button>' : '') + + '<h3>' + (featureId > 0 ? "R" : "Ny r") + 'egistrering</h3>' + + '<table>' + + '<tr><td>Type</td><td>' + + generateCropSelect("forekomsttype", forekomsttyper, feature.get("cropOrganism")["organismId"]) + + '</td></tr>' + + '<tr><td>Størrelse</td><td>' + + generateSelect("forekomststorrelse", forekomststorrelses, observationData["forekomststorrelse"]) + + '</td></tr>' + + '<tr><td>Symptom</td><td>' + + generateSelect("symptom", symptoms, observationData["symptom"]) + + '</td></tr>' + + '<tr><td>Tiltak</td><td>' + + generateSelect("tiltak", tiltaks, observationData["tiltak"]) + + '</td></tr>' + + '<tr><td>Beskrivelse</td><td>' + + '<textarea id="beskrivelse" name="beskrivelse">' + (feature.get("observationText") != null ? feature.get("observationText") : "") + '</textarea>' + + '</td></tr>' + + '<tr><td>Dato</td><td>' + + '<input type="text" id="dato" name="dato" size="10" value="' + timeOfObservation.format("DD.MM.YYYY") + '"/></td></tr>' + + '<tr><td></td><td>' + + '<input type="submit" value="Lagre" onclick="storeFeature(' + feature.getId() + ');"/></td></tr>' + + '</table>'; + + featureForm.innerHTML = html; focusForm(); //console.info(feature); }; -var storeFeature = function(featureId) +var storeFeature = function (featureId) { var feature = featureId > 0 ? featureOverlay.getSource().getFeatureById(featureId) - : newFeatureOverlay.getSource().getFeatureById(featureId); - + : newFeatureOverlay.getSource().getFeatureById(featureId); + // Store, clear newFeature layer // Need to add feature as payload var format = new ol.format.GeoJSON(); - + // Add the form data var cropOrganism = getCropOrganism(document.getElementById("forekomsttype").options[document.getElementById("forekomsttype").options.selectedIndex].value); //console.info(cropOrganism); @@ -486,32 +604,32 @@ var storeFeature = function(featureId) var tiltak = document.getElementById("tiltak").options[document.getElementById("tiltak").options.selectedIndex].value; var observationText = document.getElementById("beskrivelse").value; var observationHeading = "Registrering av pærebrann"; - var timeOfObservation = moment(document.getElementById("dato").value + "+0200","DD.MM.YYYYZ"); - if(timeOfObservation.year() < 2000) + var timeOfObservation = moment(document.getElementById("dato").value + "+0200", "DD.MM.YYYYZ"); + if (timeOfObservation.year() < 2000) { alert("Feil dato (før år 2000). Datoformat er DD.MM.ÅÅÅÅ"); return; } - + feature.setProperties({ - timeOfObservation: timeOfObservation.valueOf(), - cropOrganism: cropOrganism, - organism: paerebrann, - observationHeading: observationHeading, - observationText: observationText, - observationData: "{\"symptom\":\"" + symptom + "\",\"tiltak\":\"" + tiltak + "\",\"forekomststorrelse\":\"" + forekomststorrelse + "\"}", - statusTypeId: 3, - statusRemarks: "Registrert via pærebrannovervåkningskartet", - isQuantified: true, - broadcastMessage: false + timeOfObservation: timeOfObservation.valueOf(), + cropOrganism: cropOrganism, + organism: paerebrann, + observationHeading: observationHeading, + observationText: observationText, + observationData: "{\"symptom\":\"" + symptom + "\",\"tiltak\":\"" + tiltak + "\",\"forekomststorrelse\":\"" + forekomststorrelse + "\"}", + statusTypeId: 3, + statusRemarks: "Registrert via pærebrannovervåkningskartet", + isQuantified: true, + broadcastMessage: false }); var result = format.writeFeatures([feature], { dataProjection: 'EPSG:4326', featureProjection: map.getView().getProjection().getCode() - }); - + }); + //console.log(feature); - + $.ajax({ type: "POST", url: "/rest/observation/gisobservation", @@ -519,41 +637,40 @@ var storeFeature = function(featureId) data: result, contentType: "application/json; charset=utf-8", dataType: "json", - success: function(geoData){ + success: function (geoData) { //console.info(geoData) var format = new ol.format.GeoJSON(); var drawnfeatures = format.readFeatures(geoData, { - dataProjection: "EPSG:4326", - featureProjection: map.getView().getProjection().getCode() + dataProjection: "EPSG:4326", + featureProjection: map.getView().getProjection().getCode() }); newFeatureOverlay.getSource().clear(true); // If storing an existing feature, remove the one // that was there before storing, since the returned // one has a new gisId (featureId) - if(featureId > 0) + if (featureId > 0) { featureOverlay.getSource().removeFeature(feature); } featureOverlay.getSource().addFeatures(drawnfeatures); unFocusForm(); }, - error: function( jqXHR, textStatus, errorThrown) { - if(jqXHR.status == 401) + error: function (jqXHR, textStatus, errorThrown) { + if (jqXHR.status == 401) { - if(confirm("Kan ikke lagre fordi du er logget ut av applikasjonen. Klikk OK for å logge inn.")) + if (confirm("Kan ikke lagre fordi du er logget ut av applikasjonen. Klikk OK for å logge inn.")) { window.location.reload(); } - } - else + } else { alert("Beklager, en feil oppsto. Status = " + jqXHR.status + ", eventuell feilmelding: " + textStatus); } } }); - - + + } /** @@ -561,38 +678,37 @@ var storeFeature = function(featureId) * @param {type} featureId * @returns {undefined} */ -var deleteFeature = function(featureId) +var deleteFeature = function (featureId) { - if(!confirm("Er du sikker på at du vil slette?")) + if (!confirm("Er du sikker på at du vil slette?")) { return; } - + var feature = featureOverlay.getSource().getFeatureById(featureId); - + $.ajax({ type: "DELETE", url: "/rest/observation/gisobservation/" + feature.getId(), - success: function(response){ - console.info(response); + success: function (response) { + //console.info(response); // If storing an existing feature, remove the one // that was there before storing, since the returned // one has a new gisId (featureId) - if(featureId > 0) + if (featureId > 0) { featureOverlay.getSource().removeFeature(feature); } unFocusForm(); }, - error: function( jqXHR, textStatus, errorThrown) { - if(jqXHR.status == 401) + error: function (jqXHR, textStatus, errorThrown) { + if (jqXHR.status == 401) { - if(confirm("Kan ikke slette fordi du er logget ut av applikasjonen. Klikk OK for å logge inn.")) + if (confirm("Kan ikke slette fordi du er logget ut av applikasjonen. Klikk OK for å logge inn.")) { window.location.reload(); } - } - else + } else { alert("Beklager, en feil oppsto. Status = " + jqXHR.status + ", eventuell feilmelding: " + textStatus); } @@ -600,29 +716,29 @@ var deleteFeature = function(featureId) }); } -var generateSelect = function(selectName, options, preselect) +var generateSelect = function (selectName, options, preselect) { var retVal = '<select id="' + selectName + '" name="' + selectName + '">'; - for(var i=0; i< options.length; i++) + for (var i = 0; i < options.length; i++) { - retVal += '<option value="' + options[i] + '"' + (options[i] == preselect ? " selected=\"selected\"" : "") + '">' + options[i] + '</option>'; + retVal += '<option value="' + options[i] + '"' + (options[i] == preselect ? " selected=\"selected\"" : "") + '">' + options[i] + '</option>'; } retVal += '</select>'; return retVal; } -var generateCropSelect = function(selectName, cropOrganisms, preselect) +var generateCropSelect = function (selectName, cropOrganisms, preselect) { var retVal = '<select id="' + selectName + '" name="' + selectName + '">'; - for(var c=0; c < forekomsttypeLatinskeNavn.length; c++) + for (var c = 0; c < forekomsttypeLatinskeNavn.length; c++) { currentLatinName = forekomsttypeLatinskeNavn[c]; - for(var i=0; i< cropOrganisms.length; i++) + for (var i = 0; i < cropOrganisms.length; i++) { - if(cropOrganisms[i].latinName == currentLatinName) + if (cropOrganisms[i].latinName == currentLatinName) { - retVal += '<option value="' + cropOrganisms[i].organismId + '"' + (cropOrganisms[i].organismId == preselect ? " selected=\"selected\"" : "") + '">' + - (currentLatinName == "Plantae" ? "Annet" : getLocalizedOrganismName(cropOrganisms[i], hardcodedLanguage)) + retVal += '<option value="' + cropOrganisms[i].organismId + '"' + (cropOrganisms[i].organismId == preselect ? " selected=\"selected\"" : "") + '">' + + (currentLatinName == "Plantae" ? "Annet" : getLocalizedOrganismName(cropOrganisms[i], hardcodedLanguage)) + '</option>'; } } @@ -631,13 +747,13 @@ var generateCropSelect = function(selectName, cropOrganisms, preselect) return retVal; } -var focusForm = function() +var focusForm = function () { var featureForm = document.getElementById("featureForm"); featureForm.style.display = "block"; } -var unFocusForm = function() +var unFocusForm = function () { var featureForm = document.getElementById("featureForm"); featureForm.style.display = "none"; @@ -645,63 +761,61 @@ var unFocusForm = function() newFeatureOverlay.getSource().clear(); } -var navigateTo = function(center) +var navigateTo = function (center) { var centerPosition = ol.proj.transform(center, 'EPSG:4326', 'EPSG:3857'); - view = new ol.View({ + view = new ol.View({ center: centerPosition, zoom: 18 - }); + }); + + map.setView(view); - map.setView(view); - var searchResultsEl = document.getElementById("searchResults"); searchResultsEl.innerHTML = ""; - searchResultsEl.style.display="none"; + searchResultsEl.style.display = "none"; }; /** * Uses the client's geolocation information - displays it on the map */ function showLocation() { - if (navigator.geolocation) { - if(window.location.protocol === "http:") + if (navigator.geolocation) { + if (window.location.protocol === "http:") { - navigator.geolocation.getCurrentPosition(function(geopositionObj){ + navigator.geolocation.getCurrentPosition(function (geopositionObj) { // TODO: position and display location icon - } + } ); - } - else + } else { - if(confirm("Lokalisering fungerer bare over https (sikker tilkobling mellom nettleser og tjener). Klikk OK for å gå til sikker tilkobling.")) + if (confirm("Lokalisering fungerer bare over https (sikker tilkobling mellom nettleser og tjener). Klikk OK for å gå til sikker tilkobling.")) { window.location = "https:" + window.location.href.substring(window.location.protocol.length); } } } else { - alert( "Lokaliseringsfunksjonen er ikke tilgjengelig i denne nettleseren."); + alert("Lokaliseringsfunksjonen er ikke tilgjengelig i denne nettleseren."); } } function navToLocation() { if (navigator.geolocation) { - if(window.location.protocol === "https:") + if (window.location.protocol === "https:") { - navigator.geolocation.getCurrentPosition(function(geopositionObj){ + navigator.geolocation.getCurrentPosition(function (geopositionObj) { navigateTo([geopositionObj.coords.longitude, geopositionObj.coords.latitude]); - } + } ); - } - else + } else { - if(confirm("Lokalisering fungerer bare over https (sikker tilkobling mellom nettleser og tjener). Klikk OK for å gå til sikker tilkobling.")) + if (confirm("Lokalisering fungerer bare over https (sikker tilkobling mellom nettleser og tjener). Klikk OK for å gå til sikker tilkobling.")) { window.location = "https:" + window.location.href.substring(window.location.protocol.length); } } } else { - alert( "Lokaliseringsfunksjonen er ikke tilgjengelig i denne nettleseren."); + alert("Lokaliseringsfunksjonen er ikke tilgjengelig i denne nettleseren."); } } @@ -717,26 +831,26 @@ function initSeasonSelectList(selectedSeason) // How many years do we go back? $.ajax({ url: "/rest/observation/first/" + paerebrann.organismId - }) - .done(function(data){ - var time = moment(data); - var firstYear = time.toDate().getFullYear(); - // Loop gjennom år, lag valgliste :-) - var startSeasonList = document.getElementById("startSeason"); - for(var i=firstYear;i<=thisYear;i++) - { - var yearOpt = new Option("",i); - yearOpt.innerHTML = i + " →" - if(i==selectedSeason) - { - yearOpt.selected=true; - } - startSeasonList.options[startSeasonList.options.length] = yearOpt; - } }) - .fail(function(jqXHR, textStatus, errorThrown){ - alert(textStatus); - }); - + .done(function (data) { + var time = moment(data); + var firstYear = time.toDate().getFullYear(); + // Loop gjennom år, lag valgliste :-) + var startSeasonList = document.getElementById("startSeason"); + for (var i = firstYear; i <= thisYear; i++) + { + var yearOpt = new Option("", i); + yearOpt.innerHTML = i + " →" + if (i == selectedSeason) + { + yearOpt.selected = true; + } + startSeasonList.options[startSeasonList.options.length] = yearOpt; + } + }) + .fail(function (jqXHR, textStatus, errorThrown) { + alert(textStatus); + }); + } - + diff --git a/src/main/webapp/templates/poiForm.ftl b/src/main/webapp/templates/poiForm.ftl index b2d0274b..64127dda 100755 --- a/src/main/webapp/templates/poiForm.ftl +++ b/src/main/webapp/templates/poiForm.ftl @@ -84,7 +84,7 @@ <div class="form-group"> <label for="pointOfInterestTypeId">${i18nBundle.pointOfInterestType}</label> <select class="form-control" name="pointOfInterestTypeId" onblur="validateField(this);"> - <#list [0,1,2,3,5] as pointOfInterestTypeId> + <#list [0,1,2,3,5,6,7] as pointOfInterestTypeId> <#if pointOfInterestTypeId != 1> <option value="${pointOfInterestTypeId}"<#if poi.pointOfInterestTypeId?has_content && pointOfInterestTypeId == poi.pointOfInterestTypeId -- GitLab