diff --git a/src/main/java/no/nibio/vips/logic/controller/servlet/WeatherStationDataSourceController.java b/src/main/java/no/nibio/vips/logic/controller/servlet/WeatherStationDataSourceController.java index 3efd496173cf61e8a0ffc2acd1546e45a7e84217..766d208f92d7924d4d5be151e124a313b34a2b05 100644 --- a/src/main/java/no/nibio/vips/logic/controller/servlet/WeatherStationDataSourceController.java +++ b/src/main/java/no/nibio/vips/logic/controller/servlet/WeatherStationDataSourceController.java @@ -27,9 +27,19 @@ import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import no.nibio.vips.gis.LonLatStringFormatException; import no.nibio.vips.logic.controller.session.PointOfInterestBean; import no.nibio.vips.logic.entity.VipsLogicUser; -import no.nibio.vips.logic.entity.WeatherStationDataSource;; +import no.nibio.vips.logic.entity.WeatherStationDataSource; +import no.nibio.vips.logic.util.Globals; +import no.nibio.vips.logic.util.SystemTime; +import no.nibio.vips.util.ServletUtil; +import no.nibio.web.forms.FormValidation; +import no.nibio.web.forms.FormValidationException; +import no.nibio.web.forms.FormValidator;; /** * Handles actions regarding listing and modifying weather station data sources @@ -39,6 +49,8 @@ import no.nibio.vips.logic.entity.WeatherStationDataSource;; */ public class WeatherStationDataSourceController extends HttpServlet{ + private static Logger LOGGER = LoggerFactory.getLogger(WeatherStationDataSourceController.class); + @EJB PointOfInterestBean poiBean; @@ -65,9 +77,120 @@ public class WeatherStationDataSourceController extends HttpServlet{ if(action == null) { List<WeatherStationDataSource> wsDataSources = poiBean.getWeatherStationDataSources(); + request.setAttribute("messageKey", request.getParameter("messageKey") != null ? request.getParameter("messageKey") : null); request.setAttribute("weatherStationDataSources", wsDataSources); request.getRequestDispatcher("/weatherStationDataSourceList.ftl").forward(request, response); } + else if(action.equals("editWeatherStationDataSource") || action.equals("newWeatherStationDataSource")) + { + WeatherStationDataSource weatherStationDataSource = null; + try + { + weatherStationDataSource = poiBean.getWeatherStationDataSource(Integer.valueOf(request.getParameter("weatherStationDataSourceId"))); + } + catch(NullPointerException | NumberFormatException ex){} + + if(weatherStationDataSource == null) + { + LOGGER.debug("Could not find weather data source with ID = " + request.getParameter("weatherStationDataSourceId")); + weatherStationDataSource = new WeatherStationDataSource(); + } + + request.setAttribute("messageKey", request.getParameter("messageKey") != null ? request.getParameter("messageKey") : null); + request.setAttribute("weatherStationDataSource", weatherStationDataSource); + request.getRequestDispatcher("/weatherStationDataSourceForm.ftl").forward(request, response); + } + else if(action.equals("weatherStationDataSourceFormSubmit")) + { + try + { + // Check that the provided id is either -1 or it already exists + Integer weatherStationDataSourceId = null; + WeatherStationDataSource weatherStationDataSource; + try + { + weatherStationDataSourceId = Integer.valueOf(request.getParameter("weatherStationDataSourceId")); + } + catch(NullPointerException | NumberFormatException ex) + { + response.sendError(400,"Wrong format of id for weather station data source"); + } + if(weatherStationDataSourceId < 0) + { + weatherStationDataSource = new WeatherStationDataSource(); + } + else + { + weatherStationDataSource = poiBean.getWeatherStationDataSource(weatherStationDataSourceId); + if(weatherStationDataSource == null) + { + response.sendError(404,"Could not find weather station data source with id=" + weatherStationDataSourceId); + } + } + FormValidation formValidation = FormValidator.validateForm("weatherStationDataSourceForm", request, getServletContext()); + if(formValidation.isValid()) + { + weatherStationDataSource.setName(formValidation.getFormField("name").getWebValue()); + weatherStationDataSource.setDefaultDescription(formValidation.getFormField("defaultDescription").getWebValue()); + weatherStationDataSource.setUri(formValidation.getFormField("uri").getWebValue()); + weatherStationDataSource.setDatafetchUriExpression(formValidation.getFormField("datafetchUriExpression").getWebValue()); + weatherStationDataSource.setInfoUriExpression(formValidation.getFormField("infoUriExpression").getWebValue()); + weatherStationDataSource.setIsGrid(formValidation.getFormField("isGrid").getWebValue() != null); + weatherStationDataSource = poiBean.storeWeatherStationDataSource(weatherStationDataSource); + + response.sendRedirect( + Globals.PROTOCOL + "://" + ServletUtil.getServerName(request) + + "/weatherstationdatasource?action=editWeatherStationDataSource&weatherStationDataSourceId=" + weatherStationDataSource.getWeatherStationDataSourceId() + + "&messageKey=weatherStationDataSourceStored" + ); + } + else + { + request.setAttribute("formValidation", formValidation); + request.setAttribute("weatherStationDataSource", weatherStationDataSource); + LOGGER.debug("Form NOT valid. Dispatching"); + request.getRequestDispatcher("/weatherStationDataSourceForm.ftl").forward(request, response); + } + } + catch(FormValidationException ex) + { + ex.printStackTrace(); + response.sendError(500, ex.getClass().toString() + ": " + ex.getMessage()); + } + } + else if(action.equals("deleteWeatherStationDataSource")) + { + + try + { + Integer weatherStationDataSourceId = Integer.valueOf(request.getParameter("weatherStationDataSourceId")); + WeatherStationDataSource weatherStationDataSource = poiBean.getWeatherStationDataSource(weatherStationDataSourceId); + if(weatherStationDataSource == null) + { + response.sendError(404,"Could not find weather station data source with id=" + weatherStationDataSourceId); + } + // Check: Can it be deleted? Not if organizations or weatherStations refer to it + if(poiBean.isweatherStationDataSourceDeleteable(weatherStationDataSource)) + { + poiBean.deleteWeatherStationDataSource(weatherStationDataSource); + // Redirect to list from which the deleted item has been removed + response.sendRedirect( + Globals.PROTOCOL + "://" + ServletUtil.getServerName(request) + + "/weatherstationdatasource?messageKey=weatherStationDataSourceDeleted" + ); + } + else + { + response.sendError(403,weatherStationDataSource.getName() + " is in use by one or more organizations, so it cannot be deleted. Hit the browser's back button return to your form."); + } + } + catch(NullPointerException | NumberFormatException ex) + { + response.sendError(400,"Wrong format of id for weather station data source"); + } + + + } } // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code."> 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 b7f95ffaafe991b9667267812604cc504818fb62..22229cf81bc468edeed0512b3f2a87923bec3c42 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 @@ -276,6 +276,41 @@ public class PointOfInterestBean { return em.createNamedQuery("WeatherStationDataSource.findGridSources").getResultList(); } + /** + * Checks if the weather station data source can be deleted from the system. Criteria: + * <ul> + * <li>Not referenced from public.point_of_interest_weather_station</li> + * <li>Not referenced from public.organization</li> + * </ul> + * @param weatherStationDataSource + * @return + */ + public Boolean isweatherStationDataSourceDeleteable(WeatherStationDataSource weatherStationDataSource) + { + Query poiRefQuery = em.createQuery("SELECT COUNT(*) FROM PointOfInterestWeatherStation poiws where poiws.weatherStationDataSourceId = :weatherStationDataSourceId"); + Long weatherStationReferences = (Long) poiRefQuery.setParameter("weatherStationDataSourceId", weatherStationDataSource).getSingleResult(); + if(weatherStationReferences > 0) + { + return false; + } + + Query orgRefQuery = em.createQuery("SELECT COUNT(*) FROM Organization o where o.defaultGridWeatherStationDataSource = :weatherStationDataSourceId"); + Long organizationReferences = (Long) orgRefQuery.setParameter("weatherStationDataSourceId", weatherStationDataSource).getSingleResult(); + return organizationReferences == 0; + } + + public void deleteWeatherStationDataSource(WeatherStationDataSource weatherStationDataSource) + { + WeatherStationDataSource sourceToDelete = em.find(WeatherStationDataSource.class, weatherStationDataSource.getWeatherStationDataSourceId()); + em.remove(sourceToDelete); + } + + public WeatherStationDataSource storeWeatherStationDataSource(WeatherStationDataSource weatherStationDataSource) + { + weatherStationDataSource = em.merge(weatherStationDataSource); + return weatherStationDataSource; + } + public PointOfInterestWeatherStation storeWeatherStation(PointOfInterestWeatherStation weatherStation) { weatherStation = em.merge(weatherStation); return weatherStation; diff --git a/src/main/java/no/nibio/vips/logic/entity/WeatherStationDataSource.java b/src/main/java/no/nibio/vips/logic/entity/WeatherStationDataSource.java index de26e9216e0115e8fda8a5d4f813ed367e203cc0..b31bd3aad0c4a63cf73652253fc942660688f974 100755 --- a/src/main/java/no/nibio/vips/logic/entity/WeatherStationDataSource.java +++ b/src/main/java/no/nibio/vips/logic/entity/WeatherStationDataSource.java @@ -72,6 +72,8 @@ public class WeatherStationDataSource implements Serializable { @Column(name = "is_grid") private Boolean isGrid; + + public Boolean getIsGrid() { return isGrid; } 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 3c388d81711ad192416bfbeb7917df9a24a44d70..8eaade79b48852e9e0367e23cd583290e9d81171 100755 --- a/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts.properties +++ b/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts.properties @@ -1057,3 +1057,9 @@ doNotUse=Do not use defaultGridWeatherStationDataSource=Gridded weather data source weatherStationDataSources=Weather station data sources newWeatherStationDataSource=New weather (station) data source +editWeatherStationDataSource=Edit weather (station) data source +datafetchUriExpression=URI template for requesting data +infoUriExpression=Template for request for station information +isGridWeatherDataSource=This is a grid based weather data source +weatherStationDataSourceStored=Weather (station) data source was successfully stored +weatherStationDataSourceDeleted=The weather (station) data source was successfully deleted 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 5911156f9a0a4d4b3d4f2f65ccbfaa6f3e504ea7..69fb5f1d3cda2371e2ac60f20c77b441c431eb66 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 @@ -1051,3 +1051,9 @@ doNotUse=Do not use defaultGridWeatherStationDataSource=Gridded weather data source weatherStationDataSources=Weather station data sources newWeatherStationDataSource=New weather (station) data source +editWeatherStationDataSource=Edit weather (station) data source +datafetchUriExpression=URI template for requesting data +infoUriExpression=Template for request for station information +isGridWeatherDataSource=This is a grid based weather data source +weatherStationDataSourceStored=Weather (station) data source was successfully stored +weatherStationDataSourceDeleted=The weather (station) data source was successfully deleted 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 00d9452c479f761d7c5e3c549a3e762ef9e03681..fcde6d89ad112ea828d6f8663fcb3e1def2c91a2 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 @@ -1049,3 +1049,9 @@ doNotUse=Do not use defaultGridWeatherStationDataSource=Gridded weather data source weatherStationDataSources=Weather station data sources newWeatherStationDataSource=New weather (station) data source +editWeatherStationDataSource=Edit weather (station) data source +datafetchUriExpression=URI template for requesting data +infoUriExpression=Template for request for station information +isGridWeatherDataSource=This is a grid based weather data source +weatherStationDataSourceStored=Weather (station) data source was successfully stored +weatherStationDataSourceDeleted=The weather (station) data source was successfully deleted 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 5a4728517f5baaf4adc625d517a253b583f1dfdd..c38d45b8e323f8dcbf34686cd19264bfa7b6383a 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 @@ -1057,3 +1057,9 @@ doNotUse=Ikke bruk defaultGridWeatherStationDataSource=GRID-basert v\u00e6rdatakilde weatherStationDataSources=V\u00e6r(stasjons)datakilder newWeatherStationDataSource=Ny v\u00e6r(stasjons)datakilde +editWeatherStationDataSource=Rediger v\u00e6r(stasjons)datakilde +datafetchUriExpression=URI-mal for v\u00e6rdataforesp\u00f8rsel +infoUriExpression=Mal for henvendelse om stasjonsinformasjon +isGridWeatherDataSource=Er en grid-basert v\u00e6rdatakilde +weatherStationDataSourceStored=V\u00e6r(stasjons)datakilden ble lagret +weatherStationDataSourceDeleted=V\u00e6r(stasjons)datakilden ble 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 c3a70f067b061e207fac2a8ac7964ea5038ff539..7eb7473abecd9c43cc4a7c7829f13ae9cb3c4052 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 @@ -1051,3 +1051,9 @@ doNotUse=Do not use defaultGridWeatherStationDataSource=Gridded weather data source weatherStationDataSources=Weather station data sources newWeatherStationDataSource=New weather (station) data source +editWeatherStationDataSource=Edit weather (station) data source +datafetchUriExpression=URI template for requesting data +infoUriExpression=Template for request for station information +isGridWeatherDataSource=This is a grid based weather data source +weatherStationDataSourceStored=Weather (station) data source was successfully stored +weatherStationDataSourceDeleted=The weather (station) data source was successfully deleted 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 47043bc4ada9ffbd0e48000e831d8cc7291e885e..8e0f57063b6cf713ffe34b4cfc16e42d4e119cfc 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 @@ -1045,3 +1045,9 @@ doNotUse=Do not use defaultGridWeatherStationDataSource=Gridded weather data source weatherStationDataSources=Weather station data sources newWeatherStationDataSource=New weather (station) data source +editWeatherStationDataSource=Edit weather (station) data source +datafetchUriExpression=URI template for requesting data +infoUriExpression=Template for request for station information +isGridWeatherDataSource=This is a grid based weather data source +weatherStationDataSourceStored=Weather (station) data source was successfully stored +weatherStationDataSourceDeleted=The weather (station) data source was successfully deleted diff --git a/src/main/webapp/formdefinitions/weatherStationDataSourceForm.json b/src/main/webapp/formdefinitions/weatherStationDataSourceForm.json new file mode 100644 index 0000000000000000000000000000000000000000..35cf480345f1f784dba1cd19c2b555b553245fbe --- /dev/null +++ b/src/main/webapp/formdefinitions/weatherStationDataSourceForm.json @@ -0,0 +1,59 @@ +{ + "_licenseNote": [ + "Copyright (c) 2024 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/>." + ], + "_comment" : "Structure of the organizationForm and how to validate it", + "fields": [ + { + "name" : "weatherStationDataSourceId", + "dataType" : "INTEGER", + "required" : true + }, + { + "name" : "name", + "dataType" : "STRING", + "required" : true + }, + { + "name" : "defaultDescription", + "dataType" : "STRING", + "required" : false + }, + { + "name" : "uri", + "dataType" : "STRING", + "required" : false + }, + { + "name" : "datafetchUriExpression", + "dataType" : "STRING", + "required" : true + }, + { + "name" : "infoUriExpression", + "dataType" : "STRING", + "required" : false + }, + { + "name" : "isGrid", + "dataType" : "STRING", + "required" : false + } + + ] +} diff --git a/src/main/webapp/templates/weatherStationDataSourceForm.ftl b/src/main/webapp/templates/weatherStationDataSourceForm.ftl new file mode 100644 index 0000000000000000000000000000000000000000..d386d502e3a02eaea22d83ad0139cc8254c53674 --- /dev/null +++ b/src/main/webapp/templates/weatherStationDataSourceForm.ftl @@ -0,0 +1,97 @@ +<#-- + Copyright (c) 2024 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/>. +--><#include "master.ftl"> +<#assign formId = "weatherStationDataSourceForm"> +<#macro page_head> + <title><#if weatherStationDataSource.weatherStationDataSourceId?has_content>${i18nBundle.editWeatherStationDataSource} ${weatherStationDataSource.name}<#else>${i18nBundle.newWeatherStationDataSource}</#if></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> + <script type="text/javascript"> + $(document).ready(function() { + // Load main form definition (for validation) + loadFormDefinition("${formId}"); + + }); + function handleWeatherStationDataSourceDelete(weatherStationDataSourceId){ + window.location.href="/weatherstationdatasource?action=deleteWeatherStationDataSource&weatherStationDataSourceId=" + weatherStationDataSourceId; + } + + </script> +</#macro> +<#macro page_contents> +<div class="singleBlockContainer"> + <p><a href="/weatherstationdatasource" class="btn btn-default back" role="button">${i18nBundle.back}</a></p> + <h1><#if weatherStationDataSource.weatherStationDataSourceId?has_content>${i18nBundle.editWeatherStationDataSource} ${weatherStationDataSource.name}<#else>${i18nBundle.newWeatherStationDataSource}</#if></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> + <div class="row"> + <div class="col-md-12"> + <form id="${formId}" role="form" action="/weatherstationdatasource?action=weatherStationDataSourceFormSubmit" method="POST" onsubmit="return validateForm(this);"> + <input type="hidden" name="weatherStationDataSourceId" value="${weatherStationDataSource.weatherStationDataSourceId!"-1"}"/> + <div class="form-group"> + <label for="name">${i18nBundle.name}</label> + <input type="text" class="form-control" name="name" placeholder="${i18nBundle.name}" value="${(weatherStationDataSource.name)!""}" onblur="validateField(this); "/> + <span class="help-block" id="${formId}_name_validation"></span> + </div> + <div class="form-group"> + <label for="defaultDescription">${i18nBundle.description}</label> + <input type="text" class="form-control" name="defaultDescription" placeholder="${i18nBundle.description}" value="${(weatherStationDataSource.defaultDescription)!""}" onblur="validateField(this); "/> + <span class="help-block" id="${formId}_defaultDescription_validation"></span> + </div> + <div class="form-group"> + <label for="uri">URI</label> + <input type="url" class="form-control" name="uri" placeholder="URI" value="${(weatherStationDataSource.uri)!""}" onblur="validateField(this); "/> + <span class="help-block" id="${formId}_uri_validation"></span> + </div> + <div class="form-group"> + <label for="datafetchUriExpression">${i18nBundle.datafetchUriExpression}</label> + <input type="url" class="form-control" name="datafetchUriExpression" placeholder="${i18nBundle.datafetchUriExpression}" value="${(weatherStationDataSource.datafetchUriExpression)!""}" onblur="validateField(this); "/> + <span class="help-block" id="${formId}_datafetchUriExpression_validation"></span> + </div> + <div class="form-group"> + <label for="infoUriExpression">${i18nBundle.infoUriExpression}</label> + <input type="url" class="form-control" name="infoUriExpression" placeholder="${i18nBundle.infoUriExpression}" value="${(weatherStationDataSource.infoUriExpression)!""}" onblur="validateField(this); "/> + <span class="help-block" id="${formId}_infoUriExpression_validation"></span> + </div> + <div class="form-group"> + <div class="checkbox"> + <label> + <input type="checkbox" id="isGrid" name="isGrid" value="true"<#if weatherStationDataSource.isGrid?has_content && weatherStationDataSource.isGrid == true> checked="checked"</#if>/> + </label> + ${i18nBundle.isGridWeatherDataSource} + <span class="help-block" id="${formId}_isGrid_validation"></span> + </div> + <button type="submit" class="btn btn-default">${i18nBundle.submit}</button> + <#if weatherStationDataSource.weatherStationDataSourceId?has_content> + <button type="button" class="btn btn-danger" onclick="if(confirm('${i18nBundle.confirmDelete}')){handleWeatherStationDataSourceDelete(${weatherStationDataSource.weatherStationDataSourceId});}">${i18nBundle.delete}</button> + </#if> + </form> + </div> + </div> +</div> +</#macro> +<@page_html/> \ No newline at end of file diff --git a/src/main/webapp/templates/weatherStationDataSourceList.ftl b/src/main/webapp/templates/weatherStationDataSourceList.ftl index 3645a22cd325764b0c280eb5d0b82b7f51eb38dd..82c6b0eb62b9c386636027ee68973a20de718fd0 100644 --- a/src/main/webapp/templates/weatherStationDataSourceList.ftl +++ b/src/main/webapp/templates/weatherStationDataSourceList.ftl @@ -24,16 +24,16 @@ </#macro> <#macro page_contents> <div class="singleBlockContainer"> -<h1>${i18nBundle.weatherStationDataSources}</h1> <#if messageKey?has_content> <div class="alert alert-success">${i18nBundle(messageKey)}</div> </#if> +<h1>${i18nBundle.weatherStationDataSources}</h1> <ul> <#list weatherStationDataSources as dSource> <li><a href="/weatherstationdatasource?action=editWeatherStationDataSource&weatherStationDataSourceId=${dSource.weatherStationDataSourceId}">${dSource.name}</a></li> </#list> </ul> -<p><a href="/weatherstationdatasource??action=newWeatherStationDataSource" class="btn btn-default back" role="button">${i18nBundle.newWeatherStationDataSource}</a></p> +<p><a href="/weatherstationdatasource?action=newWeatherStationDataSource" class="btn btn-default back" role="button">${i18nBundle.newWeatherStationDataSource}</a></p> </div> </#macro> <@page_html/>