diff --git a/src/main/java/no/nibio/vips/logic/entity/PreparationType.java b/src/main/java/no/nibio/vips/logic/entity/PreparationType.java index 12c2d1d413ed41604b38caa6a52eee8ac34ada49..623c0234587d2dca2e6cafe8716137b77fc37a5f 100755 --- a/src/main/java/no/nibio/vips/logic/entity/PreparationType.java +++ b/src/main/java/no/nibio/vips/logic/entity/PreparationType.java @@ -19,6 +19,7 @@ package no.nibio.vips.logic.entity; +import com.fasterxml.jackson.annotation.JsonIgnore; import java.io.Serializable; import java.util.Collection; import javax.persistence.Basic; @@ -55,6 +56,7 @@ public class PreparationType implements Serializable { @Size(max = 255) @Column(name = "preparation_type_name") private String preparationTypeName; + @JsonIgnore @OneToMany(mappedBy = "preparationTypeId") private Collection<Preparation> preparationCollection; diff --git a/src/main/java/no/nibio/vips/logic/modules/applefruitmoth/AppleFruitMothBean.java b/src/main/java/no/nibio/vips/logic/modules/applefruitmoth/AppleFruitMothBean.java index 1776077651f8bbd4d1adf75dd781106c966a5564..92c07b8aae75114b2892e04652b4d70278160e34 100755 --- a/src/main/java/no/nibio/vips/logic/modules/applefruitmoth/AppleFruitMothBean.java +++ b/src/main/java/no/nibio/vips/logic/modules/applefruitmoth/AppleFruitMothBean.java @@ -31,11 +31,14 @@ import de.micromata.opengis.kml.v_2_2_0.Units; import de.micromata.opengis.kml.v_2_2_0.Vec2; import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Date; import java.util.List; import javax.ejb.LocalBean; import javax.ejb.Stateless; import javax.persistence.EntityManager; +import javax.persistence.NoResultException; import javax.persistence.PersistenceContext; +import javax.persistence.Query; import no.nibio.vips.logic.util.Globals; /** @@ -54,6 +57,22 @@ public class AppleFruitMothBean { List<ObservationSite> sites = em.createNamedQuery("ObservationSite.findAll").getResultList(); return sites; } + + public List<ObservationSite> getObservationSitesWithClusterCountLastUpdate(){ + List<ObservationSite> sites = this.getObservationSites(); + Query qu = em.createNativeQuery("SELECT max(last_updated) FROM applefruitmoth.observation_site_point_season_data osd WHERE osd.observation_site_point_id IN (SELECT observation_site_point_id FROM applefruitmoth.observation_site_point WHERE observation_site_id = :observationSiteId)"); + sites.stream().forEach(site->{ + qu.setParameter("observationSiteId", site.getObservationSiteId()); + try + { + Date lastUpdated = (Date) qu.getSingleResult(); + site.setLastUpdatedClusterCount(lastUpdated); + } + catch(NoResultException ex){} + }); + + return sites; + } public ObservationSite getObservationSite(Integer observationSiteId) { return em.find(ObservationSite.class, observationSiteId); diff --git a/src/main/java/no/nibio/vips/logic/modules/applefruitmoth/AppleFruitMothController.java b/src/main/java/no/nibio/vips/logic/modules/applefruitmoth/AppleFruitMothController.java index c048e907b747dfe2c4904983027447bccdfa9efa..e4f3ca5df594f6b3d04c8c7f6137eef0e083a1b0 100755 --- a/src/main/java/no/nibio/vips/logic/modules/applefruitmoth/AppleFruitMothController.java +++ b/src/main/java/no/nibio/vips/logic/modules/applefruitmoth/AppleFruitMothController.java @@ -70,7 +70,7 @@ public class AppleFruitMothController extends HttpServlet { if(action == null) { // Show map and list of existing stations - List<ObservationSite> observationSites = SessionControllerGetter.getAppleFruitMothBean().getObservationSites(); + List<ObservationSite> observationSites = SessionControllerGetter.getAppleFruitMothBean().getObservationSitesWithClusterCountLastUpdate(); request.setAttribute("observationSites", observationSites); request.getRequestDispatcher("/appleFruitMothStationList.ftl").forward(request, response); } @@ -284,9 +284,11 @@ public class AppleFruitMothController extends HttpServlet { ObservationSite observationSite = SessionControllerGetter.getAppleFruitMothBean().getObservationSite(observationSiteId); ObservationSiteSeasonCommonData seasonCommonData = observationSite.getCommonDataForSeason(currentSeason); - seasonCommonData.setRemarks(request.getParameter("remarks")); - SessionControllerGetter.getAppleFruitMothBean().storeObservationSitePointSeasonCommonData(seasonCommonData); - + if(seasonCommonData != null) + { + seasonCommonData.setRemarks(request.getParameter("remarks") != null ? request.getParameter("remarks") : ""); + SessionControllerGetter.getAppleFruitMothBean().storeObservationSitePointSeasonCommonData(seasonCommonData); + } //System.out.println("sitePointSetLength=" + observationSite.getObservationSitePointSet().size()); treeNames.stream().forEach(treeName->{ try { @@ -311,6 +313,7 @@ public class AppleFruitMothController extends HttpServlet { newData.setAutumnDate(autumnDate); newData.setSpringValue(springValue); newData.setSpringDate(springDate); + newData.setLastUpdated(new Date()); SessionControllerGetter.getAppleFruitMothBean().storeObservationSitePointSeasonData(newData); //dataSet.add(newData); diff --git a/src/main/java/no/nibio/vips/logic/modules/applefruitmoth/ObservationSite.java b/src/main/java/no/nibio/vips/logic/modules/applefruitmoth/ObservationSite.java index 716bd8a3e8ad935fab205a6e72c86f355b10b8e5..bf96fa03642907de80bd4e7c0b8caef084f8b059 100755 --- a/src/main/java/no/nibio/vips/logic/modules/applefruitmoth/ObservationSite.java +++ b/src/main/java/no/nibio/vips/logic/modules/applefruitmoth/ObservationSite.java @@ -21,6 +21,7 @@ package no.nibio.vips.logic.modules.applefruitmoth; import com.vividsolutions.jts.geom.Geometry; import java.io.Serializable; +import java.util.Date; import java.util.HashSet; import java.util.Set; import javax.persistence.Basic; @@ -78,6 +79,8 @@ public class ObservationSite implements Serializable, Comparable { @JoinColumn(name = "gis_id", referencedColumnName="gis_id") @OneToOne private Gis gisId; + @Transient + private Date lastUpdatedClusterCount; public ObservationSite() { @@ -184,4 +187,18 @@ public class ObservationSite implements Serializable, Comparable { public void setGisId(Gis gisId) { this.gisId = gisId; } + + /** + * @return the lastUpdatedClusterCount + */ + public Date getLastUpdatedClusterCount() { + return lastUpdatedClusterCount; + } + + /** + * @param lastUpdatedClusterCount the lastUpdatedClusterCount to set + */ + public void setLastUpdatedClusterCount(Date lastUpdatedClusterCount) { + this.lastUpdatedClusterCount = lastUpdatedClusterCount; + } } diff --git a/src/main/java/no/nibio/vips/logic/modules/applefruitmoth/ObservationSitePointSeasonData.java b/src/main/java/no/nibio/vips/logic/modules/applefruitmoth/ObservationSitePointSeasonData.java index f45d325c969924f9220ef071324ffa32e27297a0..7dc105836277ec94e71dd6801e0d76cf3249e011 100755 --- a/src/main/java/no/nibio/vips/logic/modules/applefruitmoth/ObservationSitePointSeasonData.java +++ b/src/main/java/no/nibio/vips/logic/modules/applefruitmoth/ObservationSitePointSeasonData.java @@ -67,6 +67,9 @@ public class ObservationSitePointSeasonData implements Serializable { @JoinColumn(name = "observation_site_point_id", referencedColumnName = "observation_site_point_id", insertable = false, updatable = false) @ManyToOne(optional = false) private ObservationSitePoint observationSitePoint; + @Column(name = "last_updated") + @Temporal(TemporalType.DATE) + private Date lastUpdated; public ObservationSitePointSeasonData() { } @@ -152,4 +155,18 @@ public class ObservationSitePointSeasonData implements Serializable { return "no.nibio.vips.logic.modules.applefruitmoth.ObservationSitePointSeasonData[ observationSitePointSeasonDataPK=" + observationSitePointSeasonDataPK + " ]"; } + /** + * @return the lastUpdated + */ + public Date getLastUpdated() { + return lastUpdated; + } + + /** + * @param lastUpdated the lastUpdated to set + */ + public void setLastUpdated(Date lastUpdated) { + this.lastUpdated = lastUpdated; + } + } diff --git a/src/main/java/no/nibio/vips/logic/modules/applefruitmoth/ObservationSiteSeasonCommonData.java b/src/main/java/no/nibio/vips/logic/modules/applefruitmoth/ObservationSiteSeasonCommonData.java index 27842f454f9411a4a4d509667ab30aa9cdc10fdd..fbe051b142a539472f03319bd1f3c6529ff5cca0 100755 --- a/src/main/java/no/nibio/vips/logic/modules/applefruitmoth/ObservationSiteSeasonCommonData.java +++ b/src/main/java/no/nibio/vips/logic/modules/applefruitmoth/ObservationSiteSeasonCommonData.java @@ -30,6 +30,8 @@ import javax.persistence.ManyToOne; import javax.persistence.NamedQueries; import javax.persistence.NamedQuery; import javax.persistence.Table; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; import javax.xml.bind.annotation.XmlRootElement; /** @@ -59,6 +61,7 @@ public class ObservationSiteSeasonCommonData implements Serializable { @Column(name = "remarks") private String remarks; @Column(name = "last_updated") + @Temporal(TemporalType.DATE) private Date lastUpdated; @JoinColumn(name = "observation_site_id", referencedColumnName = "observation_site_id", insertable = false, updatable = false) @ManyToOne(optional = false) 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 a7f13aad8be7ce0008dd1e82c717abc286f2f318..cb32a49a824de62c28fa4a1f29bbd6818d5f90e9 100755 --- a/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts.properties +++ b/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts.properties @@ -456,3 +456,4 @@ task_RunGridModelsTask_description=Run models that cover several locations currentDate=Current date days=Days older=Older +lastUpdated=Last updated 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 dba53996fd623cecc03e5580cd2dab891171f861..aa1bb34b1129629b176339e1cfa2e986517f49b2 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 @@ -456,3 +456,4 @@ task_RunGridModelsTask_description=Test currentDate=Current date days=Days older=Older +lastUpdated=Last updated 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 2a7c8e50ce7e88257533e086f03a612886a6920e..abd9465f410c934e078d8958bc4851f3021a5aad 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 @@ -455,3 +455,4 @@ task_RunGridModelsTask_description=Test currentDate=Current date days=Days older=Older +lastUpdated=Last updated 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 7cae4bccbceb3aa5a98050cd26406750a12821d1..a74b126a962e160a85b3f8feb1cc648f9462cb1e 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 @@ -456,3 +456,4 @@ task_RunGridModelsTask_description=Kj\u00f8r modeller som spenner over flere lok currentDate=Gjeldende dato days=Dager older=Eldre +lastUpdated=Sist oppdatert 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 704bfdc7224c1dc4a4189646f0d62e80ef2db989..1565845e361f6a34262336a3aa6452659fe69c9b 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 @@ -456,3 +456,4 @@ task_RunGridModelsTask_description=Test currentDate=Current date days=Days older=Older +lastUpdated=Last updated 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 f16f6fea4826008c66142487a6c8c049485db1dd..b275b893ee4e90de28867535ca644cba7afdbfc7 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 @@ -453,3 +453,4 @@ task_RunGridModelsTask_description=Test currentDate=Current date days=Days older=Older +lastUpdated=Last updated diff --git a/src/main/webapp/formdefinitions/appleFruitMothStationForm.json b/src/main/webapp/formdefinitions/appleFruitMothStationForm.json index 2954c06b241566e7a6310b864a1780916b8c9226..e5e22d4611d28cf3d0df5684ebab85444a6618b5 100755 --- a/src/main/webapp/formdefinitions/appleFruitMothStationForm.json +++ b/src/main/webapp/formdefinitions/appleFruitMothStationForm.json @@ -1,6 +1,6 @@ { "_licenseNote": [ - "Copyright (c) 2014-2015 NIBIO <http://www.nibio.no/>. ", + "Copyright (c) 2014-2018 NIBIO <http://www.nibio.no/>. ", "", "This file is part of VIPSLogic. ", "VIPSLogic is free software: you can redistribute it and/or modify ", @@ -16,7 +16,7 @@ "You should have received a copy of the NIBIO Open Source License ", "along with VIPSLogic. If not, see <http://www.nibio.no/licenses/>. " ], - "_comment" : "Structure of the weatherStationForm and how to validate it", + "_comment" : "Structure of the appleFruitMothStationForm and how to validate it", "fields": [ { "name" : "observationSiteId", diff --git a/src/main/webapp/js/appleFruitMothObservationSitesMap.js b/src/main/webapp/js/appleFruitMothObservationSitesMap.js index ce67f1497ba504fbfb4e6d385c8d2b1997c92460..dd2e3e5a139ba6b22bf04fa33d405b3905594850 100755 --- a/src/main/webapp/js/appleFruitMothObservationSitesMap.js +++ b/src/main/webapp/js/appleFruitMothObservationSitesMap.js @@ -83,7 +83,7 @@ var initMap = function(container, mapAttribution) trigger: 'manual', html: true, placement: "auto top", - title: "<a href='/applefruitmoth?action=viewObservationSite&observationSiteId=" + feature.getId() + "'>" + feature.get("name") + "</a>", + title: "<a href='/applefruitmoth?action=viewObservationSite&observationSiteId=" + feature.getId() + "'>" + feature.get("siteName") + "</a>", content: generatePopupContents(feature.get("warningStatus"), feature.get("description")) }); diff --git a/src/main/webapp/templates/appleFruitMothClusterForm.ftl b/src/main/webapp/templates/appleFruitMothClusterForm.ftl index a1042cc8a4388122573e59732e2c97857281157d..4e50de7fa029e049a34873971691b4b45d817799 100644 --- a/src/main/webapp/templates/appleFruitMothClusterForm.ftl +++ b/src/main/webapp/templates/appleFruitMothClusterForm.ftl @@ -24,12 +24,14 @@ <#if messageKey?has_content> <div class="alert alert-success">${.now}: ${i18nBundle(messageKey)}</div> </#if> + <button type="button" class="btn btn-default" onclick="window.location='/applefruitmoth';"><i class="fa fa-arrow-left" aria-hidden="true"></i> Tilbake til stasjonsliste</button> + <#if user.isSuperUser() || user.isAppleFruitMothAdministrator() ><button class="btn btn-default" type="button" onclick="window.location='/applefruitmoth?action=viewObservationSite&observationSiteId=${observationSite.observationSiteId}';">Rediger ${observationSite.observationSiteName}</button></#if> + <div class="singleBlockContainer"> <div class="row"> <form role="form" action="/applefruitmoth?action=clusterSubmit" method="POST" onsubmit="return validateForm(this)"> <div class="col-md-8"> - <button type="button" class="btn btn-default" onclick="window.location='/applefruitmoth';"><i class="fa fa-arrow-left" aria-hidden="true"></i> Tilbake</button> <p> Man trenger ikke registrere informasjon for alle trær (A-T) i lista. Et tre kan ha bare høsttallet registrert, men ikke bare vårtallet diff --git a/src/main/webapp/templates/appleFruitMothStationForm.ftl b/src/main/webapp/templates/appleFruitMothStationForm.ftl index 07e4436c892907f5d6539dcf116496d4709f3236..a8de8304e7b13ba5e9f760492e165b97e42a7b65 100755 --- a/src/main/webapp/templates/appleFruitMothStationForm.ftl +++ b/src/main/webapp/templates/appleFruitMothStationForm.ftl @@ -26,6 +26,7 @@ <script src="/js/resourcebundle.js"></script> <script type="text/javascript" src="/js/3rdparty/ol.js"></script> <script type="text/javascript" src="/js/constants.js"></script> + <script type="text/javascript" src="/js/validateForm.js"></script> <script type="text/javascript" src="/js/appleFruitMothObservationSiteMap.js"></script> <script type="text/javascript"> $(document).ready(function() { @@ -35,16 +36,17 @@ </#macro> <#macro page_contents> <h1>${observationSite.observationSiteName!i18nBundle.newObservationSite} ${currentSeason}</h1> -<button type="button" class="btn btn-default" onclick="window.location='/applefruitmoth';"><i class="fa fa-arrow-left" aria-hidden="true"></i> ${i18nBundle.back}</button> +<button type="button" class="btn btn-default" onclick="window.location='/applefruitmoth';"><i class="fa fa-arrow-left" aria-hidden="true"></i> Tilbake til stasjonsliste</button> <button type="button" class="btn btn-default" onclick="window.location='/applefruitmoth?action=registerCluster&observationSiteId=${observationSite.observationSiteId}¤tSeason=${currentSeason}';">Registrer klasetall</button> <div class="singleBlockContainer"> <div class="row"> <div class="col-md-6"> - <#assign formId = "observationSiteForm"> + <#assign formId = "appleFruitMothStationForm"> <#if messageKey?has_content> <div class="alert alert-success">${.now}: ${i18nBundle(messageKey)}</div> </#if> + <#if observationSiteSeasonCommonData??><div class="alert alert-info">${i18nBundle.lastUpdated}: ${observationSiteSeasonCommonData.lastUpdated}</div></#if> <form id="${formId}" role="form" action="/applefruitmoth?action=observationSiteSubmit" method="POST"> <input type="hidden" name="observationSiteId" value="${observationSite.observationSiteId}"/> <div class="form-group"> @@ -74,12 +76,12 @@ </div> <div class="form-group"> <label for="degreeOfParasitation">${i18nBundle.degreeOfParasitation} (${i18nBundle.internal})</label> - <input type="number" class="form-control" name="degreeOfParasitation" placeholder="${i18nBundle.degreeOfParasitation}" value="<#if observationSiteSeasonCommonData??>${observationSiteSeasonCommonData.degreeOfParasitation!""}</#if>" onblur="validateField(this);" /> + <input type="number" step="any" class="form-control" name="degreeOfParasitation" placeholder="${i18nBundle.degreeOfParasitation}" value="<#if observationSiteSeasonCommonData??>${observationSiteSeasonCommonData.degreeOfParasitation?c!""}</#if>" onblur="validateField(this);" /> <span class="help-block" id="${formId}_degreeOfParasitation_validation"></span> </div> <div class="form-group"> <label for="thousandBerrySample">${i18nBundle.thousandBerrySample} (${i18nBundle.internal})</label> - <input type="number" class="form-control" name="thousandBerrySample" placeholder="${i18nBundle.thousandBerrySample}" value="<#if observationSiteSeasonCommonData??>${observationSiteSeasonCommonData.thousandBerrySample!""}</#if>" onblur="validateField(this);" /> + <input type="number" step="any" class="form-control" name="thousandBerrySample" placeholder="${i18nBundle.thousandBerrySample}" value="<#if observationSiteSeasonCommonData??>${observationSiteSeasonCommonData.thousandBerrySample?c!""}</#if>" onblur="validateField(this);" /> <span class="help-block" id="${formId}_thousandBerrySample_validation"></span> </div> <div class="form-group"> @@ -102,10 +104,10 @@ <tr><td>Antall trær med økning i klasetall over vinteren</td><td>${treesWithIncreasingValues}</td></tr> <tr><td>Antall trær med nedgang i klasetall over vinteren</td><td>${treesWithDecreasingValues}</td></tr> <tr><td>Antall trær med uendret klasetall over vinteren</td><td>${treesWithUnchangedValues}</td></tr> - <tr><td>Angrepstall</td><td>${attackNumber!"[Data mangler]"}%</td></tr> + <tr><td>Angrepstall</td><td><#if attackNumber??>${attackNumber?c}<#else>[Data mangler]</#if></td></tr> <tr><td>Nødvendig antall klaser ${currentSeason}</td><td>${neededClusters!"[Data mangler]"}</td></tr> - <tr><td>Prognosetall ${currentSeason}</td><td>${forecastNumber!"[Data mangler]"}</td></tr> - <tr><td>Klasebrøk</td><td>${clusterFraction!"[Data mangler]"}</td></tr> + <tr><td>Prognosetall ${currentSeason}</td><td><#if forecastNumber??>${forecastNumber}<#else>[Data mangler]</#if></td></tr> + <tr><td>Klasebrøk</td><td><#if clusterFraction??>${clusterFraction?c}<#else>[Data mangler]</#if></td></tr> </tbody> </table> diff --git a/src/main/webapp/templates/appleFruitMothStationList.ftl b/src/main/webapp/templates/appleFruitMothStationList.ftl index d725953bf69a56c06f9d115c0416eb0f99478e90..e86ade492a79a7366d676b3a6d7a80aae52ccb8f 100755 --- a/src/main/webapp/templates/appleFruitMothStationList.ftl +++ b/src/main/webapp/templates/appleFruitMothStationList.ftl @@ -39,11 +39,16 @@ <div class="row"> <div class="col-md-6"> <table class="table table-striped"> + <tr> + <td colspan="3"></td> + <th>Klasetall sist oppdatert</th> + </tr> <#list observationSites as observationSite> <tr> <td>${observationSite.observationSiteName}</td> <td><#if user.isSuperUser() || user.isAppleFruitMothAdministrator() ><button class="btn btn-default" onclick="window.location='/applefruitmoth?action=viewObservationSite&observationSiteId=${observationSite.observationSiteId}';">Rediger</button></#if></td> <td><button class="btn btn-default" onclick="window.location='/applefruitmoth?action=registerCluster&observationSiteId=${observationSite.observationSiteId}';">Registrer klasetall</button></td> + <td>${observationSite.lastUpdatedClusterCount!"Ukjent"}</td> </tr> </#list> </table>