From 166707ce578146b90ef722f8940706de21a34cfe Mon Sep 17 00:00:00 2001 From: Tor-Einar Skog <tor-einar.skog@nibio.no> Date: Fri, 17 Apr 2020 14:54:29 +0200 Subject: [PATCH] Allowing for deletion of POIs --- .../servlet/PointOfInterestController.java | 6 +- .../controller/session/ForecastBean.java | 19 +++- .../controller/session/ObservationBean.java | 21 ++++- .../session/PointOfInterestBean.java | 7 +- .../nibio/vips/logic/entity/Observation.java | 1 + .../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 + .../webapp/templates/poiDeletePreview.ftl | 92 +++++++++++++++++++ 12 files changed, 150 insertions(+), 8 deletions(-) create mode 100644 src/main/webapp/templates/poiDeletePreview.ftl diff --git a/src/main/java/no/nibio/vips/logic/controller/servlet/PointOfInterestController.java b/src/main/java/no/nibio/vips/logic/controller/servlet/PointOfInterestController.java index 2117a3f0..f829adbe 100755 --- a/src/main/java/no/nibio/vips/logic/controller/servlet/PointOfInterestController.java +++ b/src/main/java/no/nibio/vips/logic/controller/servlet/PointOfInterestController.java @@ -51,6 +51,7 @@ import no.nibio.vips.util.ServletUtil; import no.nibio.vips.logic.entity.WeatherForecastProvider; import no.nibio.vips.logic.i18n.SessionLocaleUtil; import no.nibio.vips.gis.GISUtil; +import no.nibio.vips.logic.entity.Observation; import no.nibio.vips.logic.entity.PointOfInterestType; import no.nibio.vips.logic.entity.PointOfInterestTypeFarm; import no.nibio.vips.logic.entity.PointOfInterestTypeField; @@ -780,10 +781,10 @@ public class PointOfInterestController extends HttpServlet { List<ForecastConfiguration> forecastConfigurations = SessionControllerGetter.getForecastBean().getForecastConfigurationsByLocation(poi); // TODO: Are there observations attached to this location? - + List<Observation> observations = SessionControllerGetter.getObservationBean().getObservationsByLocation(poi); // // If no strings attached, delete immediately - if(forecastConfigurations.isEmpty()) + if(forecastConfigurations.isEmpty() && observations.isEmpty()) { response.sendRedirect(new StringBuilder(Globals.PROTOCOL + "://") .append(ServletUtil.getServerName(request)) @@ -798,6 +799,7 @@ public class PointOfInterestController extends HttpServlet { request.setAttribute("poi", poi); request.setAttribute("forecastConfigurations", forecastConfigurations); // TODO Set observations + request.setAttribute("observations", observations); request.setAttribute("modelInformation", modelInformationMap); request.getRequestDispatcher("/poiDeletePreview.ftl").forward(request, response); } diff --git a/src/main/java/no/nibio/vips/logic/controller/session/ForecastBean.java b/src/main/java/no/nibio/vips/logic/controller/session/ForecastBean.java index 0d9baaa5..c7cb8912 100755 --- a/src/main/java/no/nibio/vips/logic/controller/session/ForecastBean.java +++ b/src/main/java/no/nibio/vips/logic/controller/session/ForecastBean.java @@ -415,7 +415,7 @@ public class ForecastBean { * Deletes all forecasts and results from the given weather station * @param weatherStation */ - public void deleteForecastConfigurations(PointOfInterestWeatherStation weatherStation) + public void deleteForecastConfigurationsForWeatherStation(PointOfInterestWeatherStation weatherStation) { List<ForecastConfiguration> forecastConfigurations = this.getForecastConfigurationsByWeatherStation(weatherStation); for(ForecastConfiguration forecastConfiguration:forecastConfigurations) @@ -427,6 +427,22 @@ public class ForecastBean { } } + /** + * Deletes all forecasts and results from the given location + * @param weatherStation + */ + public void deleteForecastConfigurationsForLocation(PointOfInterest location) + { + List<ForecastConfiguration> forecastConfigurations = this.getForecastConfigurationsByLocation(location); + for(ForecastConfiguration forecastConfiguration:forecastConfigurations) + { + em.createNativeQuery("DELETE FROM forecast_result WHERE forecast_configuration_id=:forecastConfigurationId") + .setParameter("forecastConfigurationId", forecastConfiguration.getForecastConfigurationId()) + .executeUpdate(); + em.remove(forecastConfiguration); + } + } + /** * Fetches one specific forecast configuration * @param forecastConfigurationId @@ -1230,4 +1246,5 @@ public class ForecastBean { .setParameter("year", year) .getResultList(); } + } diff --git a/src/main/java/no/nibio/vips/logic/controller/session/ObservationBean.java b/src/main/java/no/nibio/vips/logic/controller/session/ObservationBean.java index 253d85b3..0dd526fe 100755 --- a/src/main/java/no/nibio/vips/logic/controller/session/ObservationBean.java +++ b/src/main/java/no/nibio/vips/logic/controller/session/ObservationBean.java @@ -25,14 +25,12 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; -import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.TimeZone; import java.util.stream.Collectors; import javax.ejb.Stateless; import javax.persistence.EntityManager; @@ -60,7 +58,7 @@ import org.wololo.geojson.FeatureCollection; import org.wololo.geojson.GeoJSONFactory; /** - * @copyright 2014-2018 <a href="http://www.nibio.no/">NIBIO</a> + * @copyright 2014-2020 <a href="http://www.nibio.no/">NIBIO</a> * @author Tor-Einar Skog <tor-einar.skog@nibio.no> */ @Stateless @@ -749,4 +747,21 @@ public class ObservationBean { .getResultList(); } + public List<Observation> getObservationsByLocation(PointOfInterest poi) { + return em.createNativeQuery("SELECT * FROM Observation WHERE location_point_of_interest_id=:locationPointOfInterestId", Observation.class) + .setParameter("locationPointOfInterestId", poi.getPointOfInterestId()) + .getResultList(); + } + + /** + * Part of the cleaning up dependencies procedure for when deleting a POI + * @param poi + */ + public void deleteObservationsForLocation(PointOfInterest poi) { + em.createNamedQuery("Observation.findByLocationPointOfInterestId", Observation.class) + .setParameter("locationPointOfInterestId", poi.getPointOfInterestId()) + .getResultList().stream() + .forEach(obs -> em.remove(obs)); + } + } 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 bfbc6407..3d83a3b3 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 @@ -324,7 +324,7 @@ public class PointOfInterestBean { public void deleteWeatherStation(Integer pointOfInterestId) { PointOfInterestWeatherStation weatherStation = em.find(PointOfInterestWeatherStation.class, pointOfInterestId); - SessionControllerGetter.getForecastBean().deleteForecastConfigurations(weatherStation); + SessionControllerGetter.getForecastBean().deleteForecastConfigurationsForWeatherStation(weatherStation); em.remove(weatherStation); } @@ -359,7 +359,10 @@ public class PointOfInterestBean { } public void deletePoi(Integer pointOfInterestId) { - em.remove(em.find(PointOfInterest.class, pointOfInterestId)); + PointOfInterest poi = em.find(PointOfInterest.class, pointOfInterestId); + SessionControllerGetter.getForecastBean().deleteForecastConfigurationsForLocation(poi); + SessionControllerGetter.getObservationBean().deleteObservationsForLocation(poi); + em.remove(poi); } public List<PointOfInterest> getRelevantPointOfInterestsForUser(VipsLogicUser user) { diff --git a/src/main/java/no/nibio/vips/logic/entity/Observation.java b/src/main/java/no/nibio/vips/logic/entity/Observation.java index 321dfbc3..594d1975 100755 --- a/src/main/java/no/nibio/vips/logic/entity/Observation.java +++ b/src/main/java/no/nibio/vips/logic/entity/Observation.java @@ -67,6 +67,7 @@ import org.hibernate.annotations.TypeDefs; @NamedQuery(name = "Observation.findByObservationId", query = "SELECT o FROM Observation o WHERE o.observationId = :observationId"), @NamedQuery(name = "Observation.findByUserId", query = "SELECT o FROM Observation o WHERE o.userId IN(:userId)"), @NamedQuery(name = "Observation.findByLastEditedBy", query = "SELECT o FROM Observation o WHERE o.lastEditedBy IN(:lastEditedBy)"), + @NamedQuery(name = "Observation.findByLocationPointOfInterestId", query = "SELECT o FROM Observation o WHERE o.locationPointOfInterestId = :locationPointOfInterestId"), @NamedQuery(name = "Observation.findByStatusChangedByUserId", query = "SELECT o FROM Observation o WHERE o.statusChangedByUserId IN(:statusChangedByUserId)"), @NamedQuery(name = "Observation.findByUserIdAndPeriod", query = "SELECT o FROM Observation o WHERE o.timeOfObservation BETWEEN :start AND :end AND o.userId IN(:userId)"), @NamedQuery(name = "Observation.findByUserIdAndStatusTypeId", query = "SELECT o FROM Observation o WHERE o.userId IN(:userId) AND o.statusTypeId= :statusTypeId"), 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 a5a49fdf..37f6cb51 100755 --- a/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts.properties +++ b/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts.properties @@ -488,3 +488,5 @@ task_RunForecastConfigurationsByIdTask_description=Run all forecast configuratio forecastConfigurationIds=Forecast configuration ids locationIsPublic=Location is public maskObservationWith=Mask observation with +deletePoi=Delete point of interest +deletePoiPreviewExplanation=The point of interest that you want to delete has the resources below connected to it. When you delete the POI, you also delete these resources. 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 c8cb25b4..53cb3d7d 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 @@ -488,3 +488,5 @@ task_RunForecastConfigurationsByIdTask_description=Run all forecast configuratio forecastConfigurationIds=Forecast configuration ids locationIsPublic=Location is public maskObservationWith=Mask observation with +deletePoi=Delete point of interest +deletePoiPreviewExplanation= 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 74aeaeba..2ec31284 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 @@ -487,3 +487,5 @@ task_RunForecastConfigurationsByIdTask_description=Run all forecast configuratio forecastConfigurationIds=Forecast configuration ids locationIsPublic=Location is public maskObservationWith=Mask observation with +deletePoi=Delete point of interest +deletePoiPreviewExplanation= 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 7ce392cd..a287d25d 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 @@ -488,3 +488,5 @@ task_RunForecastConfigurationsByIdTask_description=Kj\u00f8r alle varlser som ko forecastConfigurationIds=Varseloppsett (id'er) locationIsPublic=Lokaliteten kan vises offentlig maskObservationWith=Masker observasjonen med +deletePoi=Slett sted +deletePoiPreviewExplanation=Stedet du \u00f8nsker \u00e5 slette har knyttet til seg de ressursene som er nevnt nedenfor. N\u00e5r du sletter stedet, vil ogs\u00e5 disse ressursene bli slettet. 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 6825f3fc..42d27b04 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 @@ -488,3 +488,5 @@ task_RunForecastConfigurationsByIdTask_description=Run all forecast configuratio forecastConfigurationIds=Forecast configuration ids locationIsPublic=Location is public maskObservationWith=Mask observation with +deletePoi=Delete point of interest +deletePoiPreviewExplanation= 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 e84487e0..66f1011f 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 @@ -485,3 +485,5 @@ task_RunForecastConfigurationsByIdTask_description=Run all forecast configuratio forecastConfigurationIds=Forecast configuration ids locationIsPublic=Location is public maskObservationWith=Mask observation with +deletePoi=Delete point of interest +deletePoiPreviewExplanation= diff --git a/src/main/webapp/templates/poiDeletePreview.ftl b/src/main/webapp/templates/poiDeletePreview.ftl new file mode 100644 index 00000000..bccee456 --- /dev/null +++ b/src/main/webapp/templates/poiDeletePreview.ftl @@ -0,0 +1,92 @@ +<#-- + Copyright (c) 2015 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/>. +--><#include "master.ftl"> +<#macro page_head> + <title>${i18nBundle.deletePoi}</title> +</#macro> +<#macro custom_css> + <link rel="stylesheet" type="text/css" href="/css/3rdparty/ol.css"/ > +</#macro> +<#macro custom_js> + <script type="text/javascript" src="/js/constants.js"></script> + <script type="text/javascript" src="/js/resourcebundle.js"></script> + <script type="text/javascript" src="/js/validateForm.js"></script> +</#macro> +<#macro page_contents> +<div class="singleBlockContainer"> + <p><a href="${returnURL}" class="btn btn-default cancel" role="button">${i18nBundle.cancel}</a></p> + <h1>${i18nBundle.deletePoi} ${poi.name}</h1> + <div id="errorMsgEl" class="alert alert-danger" <#if !formValidation?has_content> style="display:none;"</#if>> + <#if formValidation?has_content>${formValidation.validationMessages?replace("\n", "<br>")}</#if> + </div> + <#if messageKey?has_content> + <div class="alert alert-success">${i18nBundle(messageKey)}</div> + </#if> + <p>${i18nBundle.deletePoiPreviewExplanation}</p> + <h2>${i18nBundle.forecasts}</h2> + <table class="table table-striped"> + <thead> + <th>${i18nBundle.modelId}</th> + <th>${i18nBundle.dateStart}</th> + <th>${i18nBundle.dateEnd}</th> + <th></th> + </thead> + <tbody> + <#list forecastConfigurations as forecastConfiguration> + <tr> + <td> + <#if i18nBundle.containsKey(forecastConfiguration.modelId)> + ${i18nBundle[forecastConfiguration.modelId]} + <#else> + ${modelInformation[forecastConfiguration.modelId].defaultName} + </#if> + </td> + <td>${forecastConfiguration.dateStart}</td> + <td>${forecastConfiguration.dateEnd}</td> + <td><a href="/forecastConfiguration?action=viewForecastConfiguration&forecastConfigurationId=${forecastConfiguration.forecastConfigurationId}" target="new">${i18nBundle.edit}</a></td> + </tr> + </#list> + </tbody> + </table> + <h2>${i18nBundle.observations}</h2> + <table class="table table-striped"> + <thead> + <th>${i18nBundle.timeOfObservation}</th> + <th>${i18nBundle.cropOrganismId}</th> + <th>${i18nBundle.pestOrganismId}</th> + <th>${i18nBundle.observationHeading}</th> + <th></th> + </thead> + <tbody> + <#list observations as observation> + <tr> + <td>${observation.timeOfObservation}</td> + <td>${observation.cropOrganism.latinName}</td> + <td>${observation.organism.latinName}</td> + <td>${observation.observationHeading}</td> + <td><a href="/observation?action=editObservationForm&observationId=${observation.observationId}" target="new">${i18nBundle.edit}</a></td> + </tr> + </#list> + </tbody> + </table> + <p> + <a href="${returnURL}" class="btn btn-default cancel" role="button">${i18nBundle.cancel}</a> + <button type="button" class="btn btn-danger" onclick="if(confirm('${i18nBundle.confirmDelete}')){window.location.href='/poi?action=deletePoi&pointOfInterestId=${poi.pointOfInterestId}';}">${i18nBundle.deletePoi}</button> + </p> +</div> +</#macro> +<@page_html/> -- GitLab