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 836dec4e5263e08412ccce70bdb80fd30c83f80d..2117a3f0852c531c38b620a6208ee3f59ec6f5b9 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,10 @@ 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.PointOfInterestType; +import no.nibio.vips.logic.entity.PointOfInterestTypeFarm; +import no.nibio.vips.logic.entity.PointOfInterestTypeField; +import no.nibio.vips.logic.entity.helpers.PointOfInterestFactory; import no.nibio.vips.logic.util.Globals; import no.nibio.vips.logic.util.SystemTime; import no.nibio.web.forms.FormField; @@ -530,7 +534,6 @@ public class PointOfInterestController extends HttpServlet { request.setAttribute("defaultMapZoom", user.getOrganizationId().getDefaultMapZoom()); request.getSession().setAttribute("availableTimeZones", SystemTime.getAvailableTimeZones()); request.getSession().setAttribute("defaultTimeZoneId", user.getOrganizationId().getDefaultTimeZone()); - request.getSession().setAttribute("weatherForecastProviders", em.createNamedQuery("WeatherForecastProvider.findAll").getResultList()); request.getSession().setAttribute("availableCountries", em.createNamedQuery("Country.findAll").getResultList()); request.getSession().setAttribute("defaultCountryCode", user.getOrganizationId().getCountryCode().getCountryCode()); request.getSession().setAttribute("groups", user.isSuperUser() || user.isOrganizationAdmin() ? SessionControllerGetter.getUserBean().getOrganizationGroups(user.getOrganizationId()) @@ -615,22 +618,22 @@ public class PointOfInterestController extends HttpServlet { { try { + FormValidation formValidation = FormValidator.validateForm("poiForm", request, getServletContext()); Integer pointOfInterestId = Integer.valueOf(request.getParameter("pointOfInterestId")); PointOfInterest poi = pointOfInterestId > 0 ? em.find(PointOfInterest.class, pointOfInterestId) - : new PointOfInterest(); + : PointOfInterestFactory.getPointOfInterest(formValidation.getFormField("pointOfInterestTypeId").getValueAsInteger()); if(SessionControllerGetter.getUserBean().authorizeUser(user, VipsLogicRole.ORGANIZATION_ADMINISTRATOR, VipsLogicRole.SUPERUSER) || poi.getPointOfInterestId() == null || Objects.equals(user.getUserId(), poi.getUserId().getUserId()) ) { - FormValidation formValidation = FormValidator.validateForm("poiForm", request, getServletContext()); Boolean poiNameAlreadyExists = SessionControllerGetter.getPointOfInterestBean().getPointOfInterest(formValidation.getFormField("name").getWebValue()) != null; // Only store if valid form data and NOT a new poi with an existing poiName if(formValidation.isValid() && !(poi.getPointOfInterestId() == null && poiNameAlreadyExists)) { // Set values - poi.setName(formValidation.getFormField("name").getWebValue()); + poi.setName(formValidation.getFormField("name").getWebValue()); // A POI is per default not a forecast location. Only superusers and orgadmins // may change the status if(SessionControllerGetter.getUserBean().authorizeUser(user, VipsLogicRole.ORGANIZATION_ADMINISTRATOR, VipsLogicRole.SUPERUSER)) @@ -763,12 +766,16 @@ public class PointOfInterestController extends HttpServlet { } else if(action.equals("deletePoiPreview")) { - if(SessionControllerGetter.getUserBean().authorizeUser(user, VipsLogicRole.ORGANIZATION_ADMINISTRATOR, VipsLogicRole.SUPERUSER)) + Integer pointOfInterestId = Integer.valueOf(request.getParameter("pointOfInterestId")); + PointOfInterest poi = em.find(PointOfInterest.class, pointOfInterestId); + if( + SessionControllerGetter.getUserBean().authorizeUser(user, VipsLogicRole.ORGANIZATION_ADMINISTRATOR, VipsLogicRole.SUPERUSER) + || user.getUserId().equals(poi.getUserId().getUserId()) + ) { try { - Integer pointOfInterestId = Integer.valueOf(request.getParameter("pointOfInterestId")); - PointOfInterest poi = em.find(PointOfInterest.class, pointOfInterestId); + // Are there forecasts attached to this location List<ForecastConfiguration> forecastConfigurations = SessionControllerGetter.getForecastBean().getForecastConfigurationsByLocation(poi); @@ -807,12 +814,15 @@ public class PointOfInterestController extends HttpServlet { } else if(action.equals("deletePoi")) { - if(SessionControllerGetter.getUserBean().authorizeUser(user, VipsLogicRole.ORGANIZATION_ADMINISTRATOR, VipsLogicRole.SUPERUSER)) + Integer pointOfInterestId = Integer.valueOf(request.getParameter("pointOfInterestId")); + PointOfInterest poi = em.find(PointOfInterest.class, pointOfInterestId); + if( + SessionControllerGetter.getUserBean().authorizeUser(user, VipsLogicRole.ORGANIZATION_ADMINISTRATOR, VipsLogicRole.SUPERUSER) + || user.getUserId().equals(poi.getUserId().getUserId()) + ) { try { - Integer pointOfInterestId = Integer.valueOf(request.getParameter("pointOfInterestId")); - //PointOfInterestWeatherStation weatherStation = em.find(PointOfInterestWeatherStation.class, pointOfInterestId); SessionControllerGetter.getPointOfInterestBean().deletePoi(pointOfInterestId); response.sendRedirect(new StringBuilder(Globals.PROTOCOL + "://") .append(ServletUtil.getServerName(request)) 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 60e491bd48cb2d06f30ba032525bc67043b38ef1..bfbc6407725ca57d603602708f090dc74e882f72 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 @@ -175,7 +175,7 @@ public class PointOfInterestBean { } else { - if(Objects.equals(pointOfInterestTypeId, PointOfInterestType.POINT_OF_INTEREST_TYPE_WEATHER_STATION)) + if(pointOfInterestTypeId != null && pointOfInterestTypeId == PointOfInterestType.POINT_OF_INTEREST_TYPE_WEATHER_STATION) { pois.addAll(this.getWeatherstationsForOrganization(em.find(Organization.class, organizationId),true)); } diff --git a/src/main/java/no/nibio/vips/logic/entity/PointOfInterestType.java b/src/main/java/no/nibio/vips/logic/entity/PointOfInterestType.java index 986e02a14b29b15c301e8f88c60622a1dff4f880..ee2a94eb7e1e161b21f607f2ae00262224637869 100755 --- a/src/main/java/no/nibio/vips/logic/entity/PointOfInterestType.java +++ b/src/main/java/no/nibio/vips/logic/entity/PointOfInterestType.java @@ -60,7 +60,10 @@ public class PointOfInterestType implements Serializable { private String defaultName; // Hard coded stuff - public final static Integer POINT_OF_INTEREST_TYPE_WEATHER_STATION = 1; + public static final int POINT_OF_INTEREST_TYPE_WEATHER_STATION = 1; + public static final int POINT_OF_INTEREST_TYPE_FARM = 2; + public static final int POINT_OF_INTEREST_TYPE_FIELD = 3; + public static final int POINT_OF_INTEREST_TYPE_REGION = 4; public PointOfInterestType() { } diff --git a/src/main/java/no/nibio/vips/logic/entity/PointOfInterestTypeFarm.java b/src/main/java/no/nibio/vips/logic/entity/PointOfInterestTypeFarm.java new file mode 100644 index 0000000000000000000000000000000000000000..2ba5ad333f48cd9664c4bde85e4bdd0425bddf6d --- /dev/null +++ b/src/main/java/no/nibio/vips/logic/entity/PointOfInterestTypeFarm.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 2020 <a href="http://www.nibio.no/">NIBIO</a> + * @author Tor-Einar Skog <tor-einar.skog@nibio.no> + */ +@Entity +@DiscriminatorValue("2") +@Table(name = "point_of_interest_farm") +public class PointOfInterestTypeFarm extends PointOfInterest implements Serializable { + +} diff --git a/src/main/java/no/nibio/vips/logic/entity/PointOfInterestTypeField.java b/src/main/java/no/nibio/vips/logic/entity/PointOfInterestTypeField.java new file mode 100644 index 0000000000000000000000000000000000000000..651a43246a6b66c233a624bef0640d62d7edcd49 --- /dev/null +++ b/src/main/java/no/nibio/vips/logic/entity/PointOfInterestTypeField.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 2020 <a href="http://www.nibio.no/">NIBIO</a> + * @author Tor-Einar Skog <tor-einar.skog@nibio.no> + */ +@Entity +@DiscriminatorValue("3") +@Table(name = "point_of_interest_field") +public class PointOfInterestTypeField extends PointOfInterest implements Serializable { + +} diff --git a/src/main/java/no/nibio/vips/logic/entity/helpers/PointOfInterestFactory.java b/src/main/java/no/nibio/vips/logic/entity/helpers/PointOfInterestFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..9cd70d815bef8d1624832a26b67a7c88f2c78290 --- /dev/null +++ b/src/main/java/no/nibio/vips/logic/entity/helpers/PointOfInterestFactory.java @@ -0,0 +1,49 @@ +/* + * 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.helpers; + +import no.nibio.vips.logic.entity.PointOfInterest; +import no.nibio.vips.logic.entity.PointOfInterestType; +import no.nibio.vips.logic.entity.PointOfInterestTypeFarm; +import no.nibio.vips.logic.entity.PointOfInterestTypeField; +import no.nibio.vips.logic.entity.PointOfInterestTypeRegion; +import no.nibio.vips.logic.entity.PointOfInterestWeatherStation; + +/** + * @copyright 2020 <a href="http://www.nibio.no/">NIBIO</a> + * @author Tor-Einar Skog <tor-einar.skog@nibio.no> + */ +public class PointOfInterestFactory { + public static PointOfInterest getPointOfInterest(Integer pointOfInterestTypeId) + { + switch(pointOfInterestTypeId){ + case PointOfInterestType.POINT_OF_INTEREST_TYPE_WEATHER_STATION: + return new PointOfInterestWeatherStation(); + case PointOfInterestType.POINT_OF_INTEREST_TYPE_FARM: + return new PointOfInterestTypeFarm(); + case PointOfInterestType.POINT_OF_INTEREST_TYPE_FIELD: + return new PointOfInterestTypeField(); + case PointOfInterestType.POINT_OF_INTEREST_TYPE_REGION: + return new PointOfInterestTypeRegion(); + default: + return new PointOfInterest(); + } + } +} diff --git a/src/main/java/no/nibio/vips/logic/scheduling/model/preprocessor/BremiaLactucaeModelPreprocessor.java b/src/main/java/no/nibio/vips/logic/scheduling/model/preprocessor/BremiaLactucaeModelPreprocessor.java index 067c032c6c1a625f5ea01a681951db5e2f4c1579..50092ba5691771c04600203fea5f1e3edc0f631e 100755 --- a/src/main/java/no/nibio/vips/logic/scheduling/model/preprocessor/BremiaLactucaeModelPreprocessor.java +++ b/src/main/java/no/nibio/vips/logic/scheduling/model/preprocessor/BremiaLactucaeModelPreprocessor.java @@ -51,7 +51,7 @@ public class BremiaLactucaeModelPreprocessor extends ModelRunPreprocessor { List<WeatherObservation> observations; - + try { observations = wdsUtil.getWeatherObservations( weatherStation, diff --git a/src/main/java/no/nibio/vips/logic/scheduling/model/preprocessor/DOWNCASTModelPreprocessor.java b/src/main/java/no/nibio/vips/logic/scheduling/model/preprocessor/DOWNCASTModelPreprocessor.java index e5d12c74f1ba7c07b4a861dcd82ccea81fe081cc..8589b8b8ec00ffaabac4a2100694c3a0771ff856 100755 --- a/src/main/java/no/nibio/vips/logic/scheduling/model/preprocessor/DOWNCASTModelPreprocessor.java +++ b/src/main/java/no/nibio/vips/logic/scheduling/model/preprocessor/DOWNCASTModelPreprocessor.java @@ -21,8 +21,10 @@ package no.nibio.vips.logic.scheduling.model.preprocessor; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashSet; import java.util.List; +import java.util.stream.Collectors; import no.nibio.vips.entity.ModelConfiguration; import no.nibio.vips.entity.WeatherObservation; import no.nibio.vips.logic.entity.ForecastConfiguration; @@ -64,7 +66,8 @@ public class DOWNCASTModelPreprocessor extends ModelRunPreprocessor{ }, configuration.getDateStartInTimeZone(), configuration.getDateEndInTimeZone()); - observations = wUtil.checkForAndFixHourlyTimeSeriesHoles(observations); + + observations = wUtil.checkForAndFixHourlyTimeSeriesHolesMultiParameter(observations); List<WeatherObservation> BTg = wUtil.filterWeatherObservationsByParameter(observations, new HashSet(Arrays.asList(WeatherElements.LEAF_WETNESS_DURATION_GROUND_LEVEL))); List<WeatherObservation> BT = wUtil.filterWeatherObservationsByParameter(observations, new HashSet(Arrays.asList(WeatherElements.LEAF_WETNESS_DURATION))); List<WeatherObservation> UM = wUtil.filterWeatherObservationsByParameter(observations, new HashSet(Arrays.asList(WeatherElements.RELATIVE_HUMIDITY_MEAN))); diff --git a/src/main/resources/db/migration/V6__POI_types_added.sql b/src/main/resources/db/migration/V6__POI_types_added.sql new file mode 100644 index 0000000000000000000000000000000000000000..359c4ec5f256285bcca3cbb9406735ebd6a17c6d --- /dev/null +++ b/src/main/resources/db/migration/V6__POI_types_added.sql @@ -0,0 +1,32 @@ +/* + * 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/>. + * + */ +/** + * Author: Tor-Einar Skog <tor-einar.skog@nibio.no> + * Created: Feb 28, 2020 + */ + +-- Create POI type farm as entity +CREATE TABLE public.point_of_interest_farm ( + 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) +); + +-- Create POI type field as entity +CREATE TABLE public.point_of_interest_field ( + 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) +); 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 2d48b985cbf55739a4817aec7e660702b809b1c7..a5a49fdfc7556c35d74c721469844f51b90c83df 100755 --- a/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts.properties +++ b/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts.properties @@ -395,7 +395,7 @@ editPoi=Edit Point Of Interest newPoi=New Point Of Interest pointOfInterestType=Point of Interest Type poiStored=Poi was stored -pointOfInterestType_0=General +pointOfInterestType_0=Unspecified noMapDataEntered=No map data entered DELIARFOBS=Delia radicum/floralis observation model DELIARFOBY=Delia radicum/floralis observation model for young crops 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 0561c01c42c1261f11905aeb12ab700d0068c0cd..c8cb25b416518741df79254f424779b7f5965411 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 @@ -395,7 +395,7 @@ editPoi=Edit Point Of Interest newPoi=New Point Of Interest pointOfInterestType=Point of Interest Type poiStored=Poi was stored -pointOfInterestType_0=General +pointOfInterestType_0=Unspecified noMapDataEntered=No map data entered DELIARFOBS=Delia radicum/floralis observation model DELIARFOBY=Delia radicum/floralis observation model for young crops 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 f65732a6e8f0ea86adbd29bee4d259a3a2e79009..74aeaeba73b58dc02b42a5209d11906c8d370532 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 @@ -394,7 +394,7 @@ editPoi=Edit Point Of Interest newPoi=New Point Of Interest pointOfInterestType=Point of Interest Type poiStored=Poi was stored -pointOfInterestType_0=General +pointOfInterestType_0=Unspecified noMapDataEntered=No map data entered DELIARFOBS=Delia radicum/floralis observation model DELIARFOBY=Delia radicum/floralis observation model for young crops 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 eb49190f24cc27a030be0db8b5373364a2a4527c..7ce392cd66f0fd1870f82cf39e95c0507269a0a8 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 @@ -395,7 +395,7 @@ editPoi=Rediger sted newPoi=Nytt sted pointOfInterestType=Stedstype poiStored=Stedet ble lagret -pointOfInterestType_0=Generelt +pointOfInterestType_0=Uspesifisert noMapDataEntered=Kartdata ikke registrert DELIARFOBS=Stor og liten k\u00e5lflue - observasjonsmodell DELIARFOBY=Stor og liten k\u00e5lflue - observasjonsmodell i nyplantede felt 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 a755739ad04bbed171da270c0554a374e3bb228b..6825f3fc5371cd006e62948073816237706412dc 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 @@ -395,7 +395,7 @@ editPoi=Edit Point Of Interest newPoi=New Point Of Interest pointOfInterestType=Point of Interest Type poiStored=Poi was stored -pointOfInterestType_0=General +pointOfInterestType_0=Unspecified noMapDataEntered=No map data entered DELIARFOBS=Delia radicum/floralis observation model DELIARFOBY=Delia radicum/floralis observation model for young crops diff --git a/src/main/webapp/templates/poiForm.ftl b/src/main/webapp/templates/poiForm.ftl index 0ed6cab663e7a1f7f1a4831c9f5b139a5fa62aa6..ca9d861cbbc6fc50ecc1c8ace26822f8b0a9278c 100755 --- a/src/main/webapp/templates/poiForm.ftl +++ b/src/main/webapp/templates/poiForm.ftl @@ -85,9 +85,11 @@ <label for="pointOfInterestTypeId">${i18nBundle.pointOfInterestType}</label> <select class="form-control" name="pointOfInterestTypeId" onblur="validateField(this);"> <#list 0..3 as pointOfInterestTypeId> + <#if pointOfInterestTypeId != 1> <option value="${pointOfInterestTypeId}"<#if poi.pointOfInterestTypeId?has_content && pointOfInterestTypeId == poi.pointOfInterestTypeId > selected="selected"</#if>>${i18nBundle["pointOfInterestType_" + pointOfInterestTypeId]}</option> + </#if> </#list> </select> <span class="help-block" id="${formId}_pointOfInterestTypeId_validation"></span> @@ -111,18 +113,6 @@ <label for="altitude">${i18nBundle.altitude} (${i18nBundle.meter})</label> <input type="number" class="form-control" name="altitude" placeholder="${i18nBundle.altitude}" value="${(poi.altitude?c)!""}" onblur="validateField(this);"/> <span class="help-block" id="${formId}_altitude_validation"></span> - </div> - <div class="form-group"> - <label for="weatherForecastProviderId">${i18nBundle.weatherForecastProvider}</label> - <select class="form-control" name="weatherForecastProviderId" onblur="validateField(this);"> - <option value="-1">${i18nBundle.none} ${i18nBundle.weatherForecastProvider?lower_case} - <#list weatherForecastProviders as weatherForecastProvider> - <option value="${weatherForecastProvider.weatherForecastProviderId}" - <#if poi.weatherForecastProviderId?has_content && poi.weatherForecastProviderId.weatherForecastProviderId == weatherForecastProvider.weatherForecastProviderId>selected="selected"</#if> - >${weatherForecastProvider.name}</option> - </#list> - </select> - <span class="help-block" id="${formId}_weatherForecastProviderId_validation"></span> </div> <div class="form-group"> <label for="timeZone">${i18nBundle.timeZone}</label>