diff --git a/src/main/java/no/nibio/vips/logic/modules/barkbeetle/BarkbeetleBean.java b/src/main/java/no/nibio/vips/logic/modules/barkbeetle/BarkbeetleBean.java index bd19e9793299907f22c48429de9239c52df1dc9c..788dd0f774af97b0d305cbe7cc0f29be1e31a035 100644 --- a/src/main/java/no/nibio/vips/logic/modules/barkbeetle/BarkbeetleBean.java +++ b/src/main/java/no/nibio/vips/logic/modules/barkbeetle/BarkbeetleBean.java @@ -60,6 +60,17 @@ public class BarkbeetleBean { .getResultList(); } + /** + * Get the list of trapsites for the given season + * @param season + * @return + */ + public List<SeasonTrapsite> getSeasonTrapsiteCandidates(Integer season){ + return em.createNamedQuery("SeasonTrapsite.findUnactivatedBySeason") + .setParameter("season", season) + .getResultList(); + } + /** * Get a specific trapsite * @param seasonTrapsiteId @@ -247,4 +258,49 @@ public class BarkbeetleBean { public Integer getFirstAvailableSeason() { return (Integer) em.createNativeQuery("SELECT MIN(season) FROM barkbeetle.season_trapsite;").getSingleResult(); } + + /** + * This effectively makes a copy of all trap sites of one season to another. Registrations are not kept + * @param fromSeason + * @param toSeason + */ + public void copySeasonTrapsites(Integer fromSeason, Integer toSeason) + { + em.createNativeQuery("INSERT INTO barkbeetle.season_trapsite(" + + "season," + + "gis_geom," + + "trapsite_type," + + "county_no," + + "county_name," + + "municipality_no," + + "municipality_name," + + "county2012_no," + + "county2012_name," + + "municipality2012_no," + + "municipality2012_name," + + "user_id," + + "activated" + + ")\n" + + "SELECT " + + ":toSeason," + + "gis_geom," + + "trapsite_type," + + "county_no," + + "county_name," + + "municipality_no," + + "municipality_name," + + "county2012_no," + + "county2012_name," + + "municipality2012_no," + + "municipality2012_name," + + "user_id," + + "FALSE \n" + + "FROM barkbeetle.season_trapsite " + + "WHERE season=:fromSeason" + ) + .setParameter("fromSeason", fromSeason) + .setParameter("toSeason", toSeason) + .executeUpdate(); + + } } diff --git a/src/main/java/no/nibio/vips/logic/modules/barkbeetle/BarkbeetleController.java b/src/main/java/no/nibio/vips/logic/modules/barkbeetle/BarkbeetleController.java index 4e9ac249ad1c88240987e9cbd69c4751ac5790a8..9a1388c7a10e03c846ba6ec5e36b995b811e102a 100644 --- a/src/main/java/no/nibio/vips/logic/modules/barkbeetle/BarkbeetleController.java +++ b/src/main/java/no/nibio/vips/logic/modules/barkbeetle/BarkbeetleController.java @@ -83,7 +83,7 @@ public class BarkbeetleController extends HttpServlet { List<SeasonTrapsite> seasonTrapSites = BarkbeetleBean.getInstance().getSeasonTrapsites(season); Collections.sort(seasonTrapSites); Integer firstAvailableSeason = BarkbeetleBean.getInstance().getFirstAvailableSeason(); - Integer lastAvailableSeason = Calendar.getInstance().get(Calendar.YEAR); + Integer lastAvailableSeason = Calendar.getInstance().get(Calendar.YEAR) + 1; request.setAttribute("firstAvailableSeason", firstAvailableSeason); request.setAttribute("lastAvailableSeason", lastAvailableSeason); request.setAttribute("season", season); @@ -106,7 +106,7 @@ public class BarkbeetleController extends HttpServlet { request.setAttribute("trapsiteRegistrators", SessionControllerGetter.getUserBean().getUsersByVipsLogicRoles(new Integer[]{VipsLogicRole.BARKBEETLE_ADMIN, VipsLogicRole.BARKBEETLE_REGISTRATOR, VipsLogicRole.BARKBEETLE_COUNTY_ADMIN})); List<TrapsiteType> trapsiteTypes = BarkbeetleBean.getInstance().getTrapsiteTypes(); - request.setAttribute("season", season); + request.setAttribute("season", request.getParameter("seasonTrapsiteId") != null ? trapsite.getSeason() : season); request.setAttribute("seasonTrapsite", trapsite); request.setAttribute("seasonTrapsiteTypes", trapsiteTypes); request.setAttribute("messageKey", request.getParameter("messageKey")); @@ -147,6 +147,7 @@ public class BarkbeetleController extends HttpServlet { trapsite.setDateInstalled(formValidation.getFormField("dateInstalled").isEmpty() ? null : formValidation.getFormField("dateInstalled").getValueAsDate()); trapsite.setInstallationRemarks(formValidation.getFormField("installationRemarks").getWebValue()); trapsite.setUserId(SessionControllerGetter.getUserBean().getVipsLogicUser(formValidation.getFormField("userId").getValueAsInteger())); + trapsite.setLocationUpdated(formValidation.getFormField("locationUpdated").getWebValue().equals("true")); // Handling the GIS Point p2d = formValidation.getFormField("gisGeom").getValueAsPointWGS84(); @@ -320,13 +321,22 @@ public class BarkbeetleController extends HttpServlet { { if(SessionControllerGetter.getUserBean().authorizeUser(user, VipsLogicRole.BARKBEETLE_ADMIN, VipsLogicRole.SUPERUSER)) { + try { - if(BarkbeetleBean.getInstance().deleteSeasonTrapsite(Integer.valueOf(request.getParameter("seasonTrapsiteId")))) + SeasonTrapsite trapsite = request.getParameter("seasonTrapsiteId") != null ? + BarkbeetleBean.getInstance().getSeasonTrapsite(Integer.valueOf(request.getParameter("seasonTrapsiteId"))) + : null; + + if(trapsite != null && BarkbeetleBean.getInstance().deleteSeasonTrapsite(trapsite.getSeasonTrapsiteId())) { + Integer siteSeason = trapsite.getSeason(); + String redirectAction = request.getParameter("redirectAction") != null ? "&action=" + request.getParameter("redirectAction") : ""; response.sendRedirect(Globals.PROTOCOL + "://" + ServletUtil.getServerName(request) + "/barkbeetle?messageKey=deleteOK" + + "&season=" + siteSeason + + redirectAction ); } else @@ -344,6 +354,65 @@ public class BarkbeetleController extends HttpServlet { response.sendError(403,"Access not authorized"); // HTTP Forbidden } } + else if(action.equals("listSeasonTrapsiteCandidates")) + { + List<SeasonTrapsite> seasonTrapSiteCandidates = BarkbeetleBean.getInstance().getSeasonTrapsiteCandidates(season); + Collections.sort(seasonTrapSiteCandidates); + Integer firstAvailableSeason = BarkbeetleBean.getInstance().getFirstAvailableSeason(); + Integer lastAvailableSeason = Calendar.getInstance().get(Calendar.YEAR) + 1; + request.setAttribute("firstAvailableSeason", firstAvailableSeason); + request.setAttribute("lastAvailableSeason", lastAvailableSeason); + request.setAttribute("season", season); + request.setAttribute("seasonTrapsites", seasonTrapSiteCandidates); + request.setAttribute("messageKey", request.getParameter("messageKey")); + request.getRequestDispatcher("/modules/barkbeetle/barkbeetleSeasonTrapsiteCandidateList.ftl").forward(request, response); + } + else if(action.equals("activateSeasonTrapsite")) + { + if(!SessionControllerGetter.getUserBean().authorizeUser(user, VipsLogicRole.BARKBEETLE_ADMIN, VipsLogicRole.BARKBEETLE_COUNTY_ADMIN, VipsLogicRole.ORGANIZATION_ADMINISTRATOR, VipsLogicRole.SUPERUSER)) + { + response.sendError(403,"Access not authorized"); // HTTP Forbidden + } + + SeasonTrapsite trapsite = request.getParameter("seasonTrapsiteId") != null ? + BarkbeetleBean.getInstance().getSeasonTrapsite(Integer.valueOf(request.getParameter("seasonTrapsiteId"))) + : null; + + if(trapsite != null) + { + trapsite.setActivated(Boolean.TRUE); + BarkbeetleBean.getInstance().storeSeasonTrapsite(trapsite); + response.sendRedirect(Globals.PROTOCOL + "://" + + ServletUtil.getServerName(request) + + "/barkbeetle?action=listSeasonTrapsiteCandidates&messageKey=activateOK&season=" + trapsite.getSeason() + ); + } + else + { + response.sendError(404,"Den etterspurte fellelokaliteten finnes ikke i databasen"); // HTTP Forbidden + } + } + else if(action.equals("copySeasonTrapsites")) + { + if(!SessionControllerGetter.getUserBean().authorizeUser(user, VipsLogicRole.BARKBEETLE_ADMIN, VipsLogicRole.ORGANIZATION_ADMINISTRATOR, VipsLogicRole.SUPERUSER)) + { + response.sendError(403,"Access not authorized"); // HTTP Forbidden + } + try + { + Integer fromSeason = Integer.valueOf(request.getParameter("fromSeason")); + Integer toSeason = Integer.valueOf(request.getParameter("toSeason")); + BarkbeetleBean.getInstance().copySeasonTrapsites(fromSeason, toSeason); + response.sendRedirect(Globals.PROTOCOL + "://" + + ServletUtil.getServerName(request) + + "/barkbeetle?action=listSeasonTrapsiteCandidates&season=" + toSeason + ); + } + catch(NullPointerException | NumberFormatException ex) + { + response.sendError(500, ex.getMessage()); + } + } } else { diff --git a/src/main/java/no/nibio/vips/logic/modules/barkbeetle/SeasonTrapsite.java b/src/main/java/no/nibio/vips/logic/modules/barkbeetle/SeasonTrapsite.java index 60522a7185919dbff3050400bb1b84bb9552f191..0638449c5262fe47f858ad19587ba7629823d650 100644 --- a/src/main/java/no/nibio/vips/logic/modules/barkbeetle/SeasonTrapsite.java +++ b/src/main/java/no/nibio/vips/logic/modules/barkbeetle/SeasonTrapsite.java @@ -67,7 +67,8 @@ import org.locationtech.jts.geom.Point; @NamedQueries({ @NamedQuery(name = "SeasonTrapsite.findAll", query = "SELECT s FROM SeasonTrapsite s"), @NamedQuery(name = "SeasonTrapsite.findBySeasonTrapsiteId", query = "SELECT s FROM SeasonTrapsite s WHERE s.seasonTrapsiteId = :seasonTrapsiteId"), - @NamedQuery(name = "SeasonTrapsite.findBySeason", query = "SELECT s FROM SeasonTrapsite s WHERE s.season = :season"), + @NamedQuery(name = "SeasonTrapsite.findBySeason", query = "SELECT s FROM SeasonTrapsite s WHERE s.season = :season AND s.activated IS TRUE"), + @NamedQuery(name = "SeasonTrapsite.findUnactivatedBySeason", query = "SELECT s FROM SeasonTrapsite s WHERE s.season = :season AND s.activated IS FALSE"), @NamedQuery(name = "SeasonTrapsite.findByUserId", query = "SELECT s FROM SeasonTrapsite s WHERE s.userId = :userId"), @NamedQuery(name = "SeasonTrapsite.findByOwnerName", query = "SELECT s FROM SeasonTrapsite s WHERE s.ownerName = :ownerName"), @NamedQuery(name = "SeasonTrapsite.findByOwnerPhone", query = "SELECT s FROM SeasonTrapsite s WHERE s.ownerPhone = :ownerPhone"), @@ -133,6 +134,10 @@ public class SeasonTrapsite implements Serializable, Comparable { @JoinColumn(name = "trapsite_type", referencedColumnName = "trapsite_type_id") @ManyToOne private TrapsiteType trapsiteType; + @Column(name = "activated") + private Boolean activated; + @Column(name = "location_updated") + private Boolean locationUpdated; public SeasonTrapsite() { } @@ -538,5 +543,21 @@ public class SeasonTrapsite implements Serializable, Comparable { public void setMunicipality2012Name(String municipality2012Name) { this.municipality2012Name = municipality2012Name; } + + public Boolean getActivated() { + return activated; + } + + public void setActivated(Boolean activated) { + this.activated = activated; + } + + public Boolean getLocationUpdated() { + return locationUpdated; + } + + public void setLocationUpdated(Boolean locationUpdated) { + this.locationUpdated = locationUpdated; + } } diff --git a/src/main/webapp/formdefinitions/modules/barkbeetle/seasonTrapsiteForm.json b/src/main/webapp/formdefinitions/modules/barkbeetle/seasonTrapsiteForm.json index f108339f3e1a66b73c74e85fa22399957367dc74..768f3e639565b94d86219a15f693781fad25d10d 100644 --- a/src/main/webapp/formdefinitions/modules/barkbeetle/seasonTrapsiteForm.json +++ b/src/main/webapp/formdefinitions/modules/barkbeetle/seasonTrapsiteForm.json @@ -121,6 +121,11 @@ "name" : "propertySectionNo", "dataType" : "INTEGER", "required" : false + }, + { + "name" : "locationUpdated", + "dataType" : "STRING", + "required" : true } diff --git a/src/main/webapp/templates/modules/barkbeetle/barkbeetleSeasonTrapsiteCandidateList.ftl b/src/main/webapp/templates/modules/barkbeetle/barkbeetleSeasonTrapsiteCandidateList.ftl new file mode 100644 index 0000000000000000000000000000000000000000..baef453f8f1459296843f1de4dd1226847822142 --- /dev/null +++ b/src/main/webapp/templates/modules/barkbeetle/barkbeetleSeasonTrapsiteCandidateList.ftl @@ -0,0 +1,130 @@ +<#-- + 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/>. + +--><#include "../../master.ftl"> +<#macro page_head> + <title>Barkbilleregistrering: Fellelokalitet-kandidater for sesongen ${season}</title> +</#macro> +<#macro page_contents> +<#if messageKey?has_content && messageKey=="activateOK"> + <div class="alert alert-success">Fellelokaliteten ble aktivert ${.now}</div> +</#if> +<#if messageKey?has_content && messageKey=="deleteOK"> + <div class="alert alert-success">Fellelokaliteten ble slettet ${.now}</div> +</#if> +<p> + <a href="/barkbeetle?season=${season}" class="btn btn-default back" role="button">${i18nBundle.back}</a> +</p> +<h1>Fellelokalitet-kandidater for sesongen ${season}</h1> +<div class="form-inline"> + <div class="form-group"> + Velg sesong <select class="form-control" onchange="window.location.href='/barkbeetle?action=listSeasonTrapsiteCandidates&season=' + this.options[this.selectedIndex].value;"> + <#list firstAvailableSeason..lastAvailableSeason as availableSeason> + <option value="${availableSeason}" <#if availableSeason==season>selected</#if>>${availableSeason}</option> + </#list> + </select> + </div> +</div> +<div class="row"> + <div class="col-md-12"> + FORKLARING HER + </div> +</div> +<div class="singleBlockContainer"> + <div class="row"> + <#if seasonTrapsites?size == 0> + <div class="alert alert-warning"> + Det finnes for øyeblikket ingen fjorårskopier tilgjengelig. Dette kan enten skyldes at administrator + ikke har "snudd bunken", eller at alle kopiene er ferdig revidert. + </div> + <#if userIsAdmin> + <p> + <button type="button" onclick="if(confirm('Ønsker du virkelig å kopiere fellelokaliteter fra ${season-1} til ${season}?')){window.location.href='/barkbeetle?action=copySeasonTrapsites&fromSeason=${season-1}&toSeason=${season}';}" class="btn btn-primary" role="button">Snu bunken</button> + </p> + </#if> + </#if> + <table class="table table-striped"> + <thead> + <th>Fylke</th> + <th>Kommune</th> + <th>Eier</th> + <th>Lokalitet oppdatert</th> + <th>Registrant</th> + <th></th> + <th></th> + <th></th> + </thead> + <tbody> + <#list seasonTrapsites as site> + <tr> + <td>${site.countyName!""}</td> + <td>${site.municipalityName!""}</td> + <td><span class="alert-${site.ownerName?has_content?string("success","danger")}">${site.ownerName!"Ikke oppgitt"}</span></td> + <td><span class="alert-${site.locationUpdated?string("success","danger")}">${site.locationUpdated?string("Ja","Nei")}</span></td> + <td>${site.userId.firstName} ${site.userId.lastName}</td> + <#if userIsAdmin || userIsCountyAdmin || user.userId == site.userId.userId> + <td><a href="/barkbeetle?action=editSeasonTrapsite&season=${season}&seasonTrapsiteId=${site.seasonTrapsiteId}" class="btn btn-default" role="button">Endre lokalitetsinfo</a></td> + <td><#if site.ownerName?has_content && site.locationUpdated><a href="/barkbeetle?action=activateSeasonTrapsite&seasonTrapsiteId=${site.seasonTrapsiteId}" class="btn btn-default" role="button">Aktiver fellelokalitet</a></#if></td> + <#else> + <td colspan="2"></td> + </#if> + <td><button type="button" class="btn btn-danger" onclick="if(confirm('Ønsker du virkelig å slette?')){window.location.href='/barkbeetle?action=seasonTrapsiteDelete&redirectAction=listSeasonTrapsiteCandidates&seasonTrapsiteId=${site.seasonTrapsiteId}';}">Slett</button></td> + </tr> + </#list> + </tbody> + </table> + </div> +</div> +</#macro> +<#macro custom_js> + <script type="text/javascript" src="/js/constants.js"></script> +<script type="text/javascript"> +$(document).ready(function() { + // Check for Internet Explorer + var ua = window.navigator.userAgent; + //console.info(ua); + if(ua.indexOf("MSIE ") >= 0 || navigator.userAgent.match(/Trident.*rv\:11\./)) + { + alert("Hei! Det ser ut som du bruker Internet Explorer. Vi anbefaler Firefox, Edge eller Chrome når du er på denne nettsiden."); + return; + } +}); +</script> +</#macro> +<#macro custom_css> + <link rel="stylesheet" type="text/css" href="/css/3rdparty/ol.css"/ > + <style type="text/css"> + td.status_1 { + background-color: #ffe066 !important; + } + td.status_2 { + background-color: #1aff88 !important; + } + td.status_3 { + background-color: #ff6e66 !important; + } + + #seasonTrapsiteListMap { + height: 500px; + } + + div.popover { + min-width: 250px !important; + } + </style> +</#macro> +<@page_html/> \ No newline at end of file diff --git a/src/main/webapp/templates/modules/barkbeetle/barkbeetleSeasonTrapsiteForm.ftl b/src/main/webapp/templates/modules/barkbeetle/barkbeetleSeasonTrapsiteForm.ftl index f4ff0f831d465a5eaca0483dfc3e3ea8865247a8..e2c55b1c9745283d2b01aadbce3956b624973b9e 100644 --- a/src/main/webapp/templates/modules/barkbeetle/barkbeetleSeasonTrapsiteForm.ftl +++ b/src/main/webapp/templates/modules/barkbeetle/barkbeetleSeasonTrapsiteForm.ftl @@ -88,6 +88,7 @@ theForm["countyName"].value=municInfo[0]["fylkenavn"]; theForm["municipalityNo"].value=municInfo[0]["komnr"]; theForm["municipalityName"].value=municInfo[0]["komnavn"]; + theForm["locationUpdated"].value="true"; // This is for candidate trapsites copied from last year } } ) @@ -152,7 +153,7 @@ <div class="alert alert-success">Data ble lagret ${.now}</div> </#if> <p> - <a href="/barkbeetle?season=${season}" class="btn btn-default back" role="button">${i18nBundle.back}</a> + <a href="/barkbeetle?season=${season}<#if seasonTrapsite.seasonTrapsiteId?has_content && !seasonTrapsite.activated>&action=listSeasonTrapsiteCandidates</#if>" class="btn btn-default back" role="button">${i18nBundle.back}</a> </p> <h1><#if seasonTrapsite.seasonTrapsiteId?has_content>Rediger<#else>Ny</#if> fellelokalitet</h1> <div class="row"> @@ -189,6 +190,7 @@ <p>Felt merket med * må være utfylt</p> <form id="${formId}" role="form" action="/barkbeetle?action=seasonTrapsiteFormSubmit" method="POST" onsubmit="return validateForm(this);""> <input type="hidden" name="seasonTrapsiteId" value="${seasonTrapsite.seasonTrapsiteId!"-1"}"/> + <input type="hidden" name="locationUpdated" value="${seasonTrapsite.locationUpdated?string("true","false")}"/> <div class="form-group"> <label for="trapsiteType">Type fellelokalitet *</label> <select class="form-control" name="trapsiteTypeId" onblur="validateField(this);"> diff --git a/src/main/webapp/templates/modules/barkbeetle/barkbeetleSeasonTrapsiteList.ftl b/src/main/webapp/templates/modules/barkbeetle/barkbeetleSeasonTrapsiteList.ftl index eff08dec23f1116e0f81492729ef10aa1aae3d0d..73ab18484479b3e0d2ac42fcd7cc30209b3c6e56 100644 --- a/src/main/webapp/templates/modules/barkbeetle/barkbeetleSeasonTrapsiteList.ftl +++ b/src/main/webapp/templates/modules/barkbeetle/barkbeetleSeasonTrapsiteList.ftl @@ -92,6 +92,9 @@ <p> <a href="/barkbeetle?action=editSeasonTrapsite&season=${season}" class="btn btn-default" role="button">${i18nBundle.addNew}</a> </p> +<p> + <a href="/barkbeetle?action=listSeasonTrapsiteCandidates&season=${season}" class="btn btn-default" role="button">Hent en kopi fra fjoråret</a> +</p> </#if> <div class="singleBlockContainer"> <div class="row">