diff --git a/src/main/java/no/nibio/vips/logic/controller/servlet/ForecastConfigurationController.java b/src/main/java/no/nibio/vips/logic/controller/servlet/ForecastConfigurationController.java index daaeae40511a70eca9d9f2cb4197e0010dd92238..3275c260b6b2996f7556fddb6402e67b6ddcf01a 100644 --- a/src/main/java/no/nibio/vips/logic/controller/servlet/ForecastConfigurationController.java +++ b/src/main/java/no/nibio/vips/logic/controller/servlet/ForecastConfigurationController.java @@ -140,13 +140,29 @@ public class ForecastConfigurationController extends HttpServlet { request.setAttribute("organizations", organizations); request.setAttribute("selectedOrganizationIds", selectedOrganizationIds); + + request.setAttribute("allUsers", userBean.getAllUsers()); + // If super user requests private forecasts for a user + try + { + Integer otherUserId = Integer.valueOf(request.getParameter("otherUserId")); + List<ForecastConfiguration> privateForecastConfigurationsForOtherUser = forecastBean.getPrivateForecastConfigurationsForUser(otherUserId); + request.setAttribute("privateForecastConfigurationsForOtherUser", privateForecastConfigurationsForOtherUser); + request.setAttribute("otherUserId", otherUserId); + } + catch(NumberFormatException nfe) {} } else { forecasts = forecastBean.getForecastConfigurations(user.getOrganizationId(), selectedModelIds, from, to); } Collections.sort(forecasts); + request.setAttribute("forecastConfigurations", forecasts); + + List<ForecastConfiguration> privateForecasts; + privateForecasts = forecastBean.getPrivateForecastConfigurationsForUser(user.getUserId()); + request.setAttribute("privateForecastConfigurations", privateForecasts); request.setAttribute("modelInformation", modelInformationMap); request.setAttribute("selectedModelIds", selectedModelIds); request.setAttribute("from", from); @@ -185,6 +201,11 @@ public class ForecastConfigurationController extends HttpServlet { { response.sendError(403,"Access not authorized"); // HTTP Forbidden } + // Only superusers can view and edit private forecasts from other users + else if(forecastConfiguration.getIsPrivate() && ! user.isSuperUser() && forecastConfiguration.getVipsLogicUserId() != null && !forecastConfiguration.getVipsLogicUserId().getUserId().equals(user.getUserId())) + { + response.sendError(403,"Access not authorized"); // HTTP Forbidden + } else { // TODO: More intelligent selection of locations, weather stations and users 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 d4f7a713afaaa0525fae2252bf460f5c9646916d..da528cf17523bb4742763de5aca782246603c8b3 100644 --- a/src/main/java/no/nibio/vips/logic/controller/session/ForecastBean.java +++ b/src/main/java/no/nibio/vips/logic/controller/session/ForecastBean.java @@ -41,6 +41,7 @@ import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.UUID; import java.util.logging.Level; import java.util.logging.Logger; import javax.ejb.Stateless; @@ -104,7 +105,26 @@ public class ForecastBean { Query q = em.createNamedQuery("ForecastResult.findByForecastConfigurationId"); q.setParameter("forecastConfigurationId", forecastConfigurationId); return q.getResultList(); - + } + + public boolean isUserAuthorizedForForecastConfiguration(Long forecastConfigurationId, String userUUID) + { + // Authentication + ForecastConfiguration fc = em.find(ForecastConfiguration.class, forecastConfigurationId); + if(fc.getIsPrivate()) + { + if(userUUID == null) + { + return false; + } + UUID uUUID = UUID.fromString(userUUID); + VipsLogicUser user = SessionControllerGetter.getUserBean().findVipsLogicUser(uUUID); + if(user == null || user.getUserId().equals( fc.getVipsLogicUserId())) + { + return false; + } + } + return true; } public List<ForecastResult> getForecastResults(Long forecastConfigurationId, Integer latestDays) @@ -180,7 +200,7 @@ public class ForecastBean { /** - * Get all forecast configurations for one user. + * Get all PUBLIC forecast configurations for one user. * TODO: Should be season based, or possibly based on start/stop date * @param userId * @return @@ -193,6 +213,23 @@ public class ForecastBean { return q.getResultList(); } + /** + * Get all PRIVATE forecast configurations for one user. + * TODO: Should be season based, or possibly based on start/stop date + * @param userId + * @return + */ + public List<ForecastConfiguration> getPrivateForecastConfigurationsForUser(Integer userId) + { + VipsLogicUser user = em.find(VipsLogicUser.class, userId); + Query q = em.createNamedQuery("ForecastConfiguration.findPrivateByVipsLogicUserId"); + q.setParameter("vipsLogicUserId", user); + return q.getResultList(); + } + + + + public List<ForecastConfiguration> getForecastConfigurationsForUserAndDate(Integer userId, Date from, Date to) { VipsLogicUser user = em.find(VipsLogicUser.class, userId); @@ -404,6 +441,7 @@ public class ForecastBean { forecastConfiguration.setModelId(formFields.get("modelId").getWebValue()); forecastConfiguration.setCropOrganismId(em.find(Organism.class, formFields.get("cropOrganismId").getValueAsInteger())); forecastConfiguration.setPestOrganismId(em.find(Organism.class, formFields.get("pestOrganismId").getValueAsInteger())); + forecastConfiguration.setIsPrivate(formFields.get("isPrivate").getWebValue() != null); PointOfInterest locationPoi = em.find(PointOfInterest.class, formFields.get("locationPointOfInterestId").getValueAsInteger()); forecastConfiguration.setLocationPointOfInterestId(locationPoi); PointOfInterest weatherStationPoi = em.find(PointOfInterestWeatherStation.class, formFields.get("weatherStationPointOfInterestId").getValueAsInteger()); @@ -878,7 +916,8 @@ public class ForecastBean { "WHERE forecast_configuration_id IN( \n" + " SELECT forecast_configuration_id \n" + " FROM forecast_configuration \n" + - " WHERE location_point_of_interest_id=:locationPointOfInterestId \n" + + " WHERE is_private IS FALSE \n" + + " AND location_point_of_interest_id=:locationPointOfInterestId \n" + (cropOrganismIds != null && ! cropOrganismIds.isEmpty() ? " AND crop_organism_id IN (" + StringUtils.join(cropOrganismIds, ",") + ") " : "") + ")\n" + "AND to_char(result_valid_time, '" + dateFormat + "') = :dateStr"; @@ -912,6 +951,10 @@ public class ForecastBean { List<ForecastResult> results = new ArrayList<>(); for(ForecastConfiguration forecastConfiguration:forecastConfigurations) { + if(forecastConfiguration.getIsPrivate()) + { + continue; + } mappedForecastConfigurations.put(forecastConfiguration.getForecastConfigurationId(), forecastConfiguration); Query q = em.createNativeQuery( "SELECT * FROM forecast_result WHERE forecast_configuration_id = :forecastConfigurationId " @@ -968,5 +1011,25 @@ public class ForecastBean { return forecastConfiguration; } + + public List<ForecastConfiguration> getPrivateForecastConfigurationSummaries(VipsLogicUser user) { + List<ForecastConfiguration> forecastConfigurations = this.getPrivateForecastConfigurationsForUser(user.getUserId()); + // TODO: Filter forecastconfigurations based on criteria (activity, crops, geography etc) + List<ForecastConfiguration> filteredConfigs = new ArrayList<>(); + Query q = em.createNamedQuery("ForecastSummary.findByForecastConfigurationId"); + for(ForecastConfiguration config: forecastConfigurations) + { + config.setForecastSummaries( + + q.setParameter("forecastConfigurationId", config.getForecastConfigurationId()) + .getResultList() + ); + if(config.getForecastSummaries() != null && !config.getForecastSummaries().isEmpty()) + { + filteredConfigs.add(config); + } + } + return filteredConfigs; + } } diff --git a/src/main/java/no/nibio/vips/logic/entity/ForecastConfiguration.java b/src/main/java/no/nibio/vips/logic/entity/ForecastConfiguration.java index 679b66da5309808a7df8cdc060d7d1950332ac07..6fa0860969cfa571174869654cc4121f393dcd5e 100644 --- a/src/main/java/no/nibio/vips/logic/entity/ForecastConfiguration.java +++ b/src/main/java/no/nibio/vips/logic/entity/ForecastConfiguration.java @@ -47,31 +47,35 @@ import javax.persistence.Transient; import no.nibio.vips.util.WeatherUtil; /** - * @copyright 2014-2015 <a href="http://www.nibio.no/">NIBIO</a> + * @copyright 2014-2016 <a href="http://www.nibio.no/">NIBIO</a> * @author Tor-Einar Skog <tor-einar.skog@nibio.no> */ @Entity @Table(name = "forecast_configuration") @XmlRootElement @NamedQueries({ - @NamedQuery(name = "ForecastConfiguration.findAll", query = "SELECT f FROM ForecastConfiguration f"), + @NamedQuery(name = "ForecastConfiguration.findAll", query = "SELECT f FROM ForecastConfiguration f WHERE f.isPrivate = FALSE"), @NamedQuery(name = "ForecastConfiguration.findByForecastConfigurationId", query = "SELECT f FROM ForecastConfiguration f WHERE f.forecastConfigurationId = :forecastConfigurationId"), @NamedQuery(name = "ForecastConfiguration.findByForecastConfigurationIds", query = "SELECT f FROM ForecastConfiguration f WHERE f.forecastConfigurationId IN(:forecastConfigurationIds)"), - @NamedQuery(name = "ForecastConfiguration.findByModelId", query = "SELECT f FROM ForecastConfiguration f WHERE f.modelId = :modelId"), - @NamedQuery(name = "ForecastConfiguration.findByModelIds", query = "SELECT f FROM ForecastConfiguration f WHERE f.modelId IN (:modelIds)"), - @NamedQuery(name = "ForecastConfiguration.findByDateStart", query = "SELECT f FROM ForecastConfiguration f WHERE f.dateStart = :dateStart"), - @NamedQuery(name = "ForecastConfiguration.findByDateEnd", query = "SELECT f FROM ForecastConfiguration f WHERE f.dateEnd = :dateEnd"), - @NamedQuery(name = "ForecastConfiguration.findActiveAtDate", query = "SELECT f FROM ForecastConfiguration f WHERE f.dateStart <= :currentDate AND f.dateEnd >= :currentDate"), - @NamedQuery(name = "ForecastConfiguration.findByLocationPointOfInterestId", query = "SELECT f FROM ForecastConfiguration f WHERE f.locationPointOfInterestId = :locationPointOfInterestId"), - @NamedQuery(name = "ForecastConfiguration.findByWeatherStationPointOfInterestId", query = "SELECT f FROM ForecastConfiguration f WHERE f.weatherStationPointOfInterestId = :weatherStationPointOfInterestId"), - @NamedQuery(name = "ForecastConfiguration.findByWeatherStationPointOfInterestIdAndDate", query = "SELECT f FROM ForecastConfiguration f WHERE f.weatherStationPointOfInterestId = :weatherStationPointOfInterestId AND f.dateStart <= :to AND f.dateEnd >= :from"), - @NamedQuery(name = "ForecastConfiguration.findByVipsLogicUserId", query = "SELECT f FROM ForecastConfiguration f WHERE f.vipsLogicUserId = :vipsLogicUserId"), - @NamedQuery(name = "ForecastConfiguration.findByVipsLogicUserIdAndDate", query = "SELECT f FROM ForecastConfiguration f WHERE f.vipsLogicUserId = :vipsLogicUserId AND f.dateStart <= :to AND f.dateEnd >= :from" ), - @NamedQuery(name = "ForecastConfiguration.findByVipsLogicUserIdAndCropOrganismId", query = "SELECT f FROM ForecastConfiguration f WHERE f.vipsLogicUserId = :vipsLogicUserId AND f.cropOrganismId.organismId IN (:cropOrganismIds)"), - @NamedQuery(name = "ForecastConfiguration.findByVipsLogicUserIdAndCropOrganismIdsAndDate", query = "SELECT f FROM ForecastConfiguration f WHERE f.vipsLogicUserId = :vipsLogicUserId AND f.cropOrganismId.organismId IN (:cropOrganismIds) AND f.dateStart <= :to AND f.dateEnd >= :from"), - @NamedQuery(name = "ForecastConfiguration.findByVipsLogicUserIds", query = "SELECT f FROM ForecastConfiguration f WHERE f.vipsLogicUserId IN (:vipsLogicUserIds)"), - @NamedQuery(name = "ForecastConfiguration.findByVipsLogicUserIdsAndModelIds", query = "SELECT f FROM ForecastConfiguration f WHERE f.vipsLogicUserId IN (:vipsLogicUserIds) AND f.modelId IN (:modelIds)"), - @NamedQuery(name = "ForecastConfiguration.findByVipsLogicUserIdsAndModelIdsAndDate", query = "SELECT f FROM ForecastConfiguration f WHERE f.vipsLogicUserId IN (:vipsLogicUserIds) AND f.modelId IN (:modelIds) AND f.dateStart <= :to AND f.dateEnd >= :from")}) + @NamedQuery(name = "ForecastConfiguration.findByModelId", query = "SELECT f FROM ForecastConfiguration f WHERE f.modelId = :modelId AND f.isPrivate = FALSE"), + @NamedQuery(name = "ForecastConfiguration.findByModelIds", query = "SELECT f FROM ForecastConfiguration f WHERE f.modelId IN (:modelIds) AND f.isPrivate = FALSE"), + @NamedQuery(name = "ForecastConfiguration.findByDateStart", query = "SELECT f FROM ForecastConfiguration f WHERE f.dateStart = :dateStart AND f.isPrivate = FALSE"), + @NamedQuery(name = "ForecastConfiguration.findByDateEnd", query = "SELECT f FROM ForecastConfiguration f WHERE f.dateEnd = :dateEnd AND f.isPrivate = FALSE"), + @NamedQuery(name = "ForecastConfiguration.findActiveAtDate", query = "SELECT f FROM ForecastConfiguration f WHERE f.dateStart <= :currentDate AND f.dateEnd >= :currentDate AND f.isPrivate = FALSE"), + @NamedQuery(name = "ForecastConfiguration.findByLocationPointOfInterestId", query = "SELECT f FROM ForecastConfiguration f WHERE f.locationPointOfInterestId = :locationPointOfInterestId AND f.isPrivate = FALSE"), + @NamedQuery(name = "ForecastConfiguration.findByWeatherStationPointOfInterestId", query = "SELECT f FROM ForecastConfiguration f WHERE f.weatherStationPointOfInterestId = :weatherStationPointOfInterestId AND f.isPrivate = FALSE"), + @NamedQuery(name = "ForecastConfiguration.findByWeatherStationPointOfInterestIdAndDate", query = "SELECT f FROM ForecastConfiguration f WHERE f.weatherStationPointOfInterestId = :weatherStationPointOfInterestId AND f.dateStart <= :to AND f.dateEnd >= :from AND f.isPrivate = FALSE"), + @NamedQuery(name = "ForecastConfiguration.findByVipsLogicUserId", query = "SELECT f FROM ForecastConfiguration f WHERE f.vipsLogicUserId = :vipsLogicUserId AND f.isPrivate = FALSE"), + @NamedQuery(name = "ForecastConfiguration.findByVipsLogicUserIdAndDate", query = "SELECT f FROM ForecastConfiguration f WHERE f.vipsLogicUserId = :vipsLogicUserId AND f.dateStart <= :to AND f.dateEnd >= :from AND f.isPrivate = FALSE" ), + @NamedQuery(name = "ForecastConfiguration.findByVipsLogicUserIdAndCropOrganismId", query = "SELECT f FROM ForecastConfiguration f WHERE f.vipsLogicUserId = :vipsLogicUserId AND f.cropOrganismId.organismId IN (:cropOrganismIds) AND f.isPrivate = FALSE"), + @NamedQuery(name = "ForecastConfiguration.findByVipsLogicUserIdAndCropOrganismIdsAndDate", query = "SELECT f FROM ForecastConfiguration f WHERE f.vipsLogicUserId = :vipsLogicUserId AND f.cropOrganismId.organismId IN (:cropOrganismIds) AND f.dateStart <= :to AND f.dateEnd >= :from AND f.isPrivate = FALSE"), + @NamedQuery(name = "ForecastConfiguration.findPrivateByVipsLogicUserId", query = "SELECT f FROM ForecastConfiguration f WHERE f.vipsLogicUserId = :vipsLogicUserId AND f.isPrivate = TRUE"), + @NamedQuery(name = "ForecastConfiguration.findPrivateByVipsLogicUserIdAndDate", query = "SELECT f FROM ForecastConfiguration f WHERE f.vipsLogicUserId = :vipsLogicUserId AND f.dateStart <= :to AND f.dateEnd >= :from AND f.isPrivate = TRUE" ), + @NamedQuery(name = "ForecastConfiguration.findPrivateByVipsLogicUserIdAndCropOrganismId", query = "SELECT f FROM ForecastConfiguration f WHERE f.vipsLogicUserId = :vipsLogicUserId AND f.cropOrganismId.organismId IN (:cropOrganismIds) AND f.isPrivate = TRUE"), + @NamedQuery(name = "ForecastConfiguration.findPrivateByVipsLogicUserIdAndCropOrganismIdsAndDate", query = "SELECT f FROM ForecastConfiguration f WHERE f.vipsLogicUserId = :vipsLogicUserId AND f.cropOrganismId.organismId IN (:cropOrganismIds) AND f.dateStart <= :to AND f.dateEnd >= :from AND f.isPrivate = TRUE"), + @NamedQuery(name = "ForecastConfiguration.findByVipsLogicUserIds", query = "SELECT f FROM ForecastConfiguration f WHERE f.vipsLogicUserId IN (:vipsLogicUserIds) AND f.isPrivate = FALSE"), + @NamedQuery(name = "ForecastConfiguration.findByVipsLogicUserIdsAndModelIds", query = "SELECT f FROM ForecastConfiguration f WHERE f.vipsLogicUserId IN (:vipsLogicUserIds) AND f.modelId IN (:modelIds) AND f.isPrivate = FALSE"), + @NamedQuery(name = "ForecastConfiguration.findByVipsLogicUserIdsAndModelIdsAndDate", query = "SELECT f FROM ForecastConfiguration f WHERE f.vipsLogicUserId IN (:vipsLogicUserIds) AND f.modelId IN (:modelIds) AND f.dateStart <= :to AND f.dateEnd >= :from AND f.isPrivate = FALSE")}) public class ForecastConfiguration implements Serializable, Comparable { @OneToMany(cascade = CascadeType.ALL, mappedBy = "forecastConfiguration", fetch = FetchType.EAGER) private Set<ForecastModelConfiguration> forecastModelConfigurationSet; @@ -109,6 +113,8 @@ public class ForecastConfiguration implements Serializable, Comparable { @JoinColumn(name = "pest_organism_id", referencedColumnName = "organism_id") @ManyToOne private Organism pestOrganismId; + @Column(name = "is_private") + private Boolean isPrivate; @Transient private WeatherUtil weatherUtil; @@ -370,4 +376,18 @@ public class ForecastConfiguration implements Serializable, Comparable { format.setTimeZone(timeZone1); return format.format(this.getDateEnd()); }*/ + + /** + * @return the isPrivate + */ + public Boolean getIsPrivate() { + return isPrivate; + } + + /** + * @param isPrivate the isPrivate to set + */ + public void setIsPrivate(Boolean isPrivate) { + this.isPrivate = isPrivate; + } } diff --git a/src/main/java/no/nibio/vips/logic/service/LogicService.java b/src/main/java/no/nibio/vips/logic/service/LogicService.java index 07a4764d030c1cf8d65e7a8c01aa68219a8d8c0a..53a70b1a48adad398bbab9e92b78709f5fba877c 100644 --- a/src/main/java/no/nibio/vips/logic/service/LogicService.java +++ b/src/main/java/no/nibio/vips/logic/service/LogicService.java @@ -87,14 +87,24 @@ public class LogicService { @GET @Path("forecastresults/{forecastConfigurationId}") @Produces("application/json;charset=UTF-8") - public Response getForecastResults(@PathParam("forecastConfigurationId") Long forecastConfigurationId) + public Response getForecastResults( + @PathParam("forecastConfigurationId") Long forecastConfigurationId, + @QueryParam("userUUID") String userUUID + ) { - List<ForecastResult> results = SessionControllerGetter.getForecastBean().getForecastResults(forecastConfigurationId); - if(results == null) + if(SessionControllerGetter.getForecastBean().isUserAuthorizedForForecastConfiguration(forecastConfigurationId, userUUID)) + { + List<ForecastResult> results = SessionControllerGetter.getForecastBean().getForecastResults(forecastConfigurationId); + if(results == null) + { + results = new ArrayList<>(); + } + return Response.ok().entity(results).build(); + } + else { - results = new ArrayList<>(); + return Response.status(Response.Status.UNAUTHORIZED).build(); } - return Response.ok().entity(results).build(); } @GET @@ -102,15 +112,23 @@ public class LogicService { @Produces("application/json;charset=UTF-8") public Response getForecastResults( @PathParam("forecastConfigurationId") Long forecastConfigurationId, - @PathParam("latestDays") Integer latestDays + @PathParam("latestDays") Integer latestDays, + @QueryParam("userUUID") String userUUID ) { - List<ForecastResult> results = SessionControllerGetter.getForecastBean().getForecastResults(forecastConfigurationId, latestDays); - if(results == null) + if(SessionControllerGetter.getForecastBean().isUserAuthorizedForForecastConfiguration(forecastConfigurationId, userUUID)) { - results = new ArrayList<>(); + List<ForecastResult> results = SessionControllerGetter.getForecastBean().getForecastResults(forecastConfigurationId, latestDays); + if(results == null) + { + results = new ArrayList<>(); + } + return Response.ok().entity(results).build(); + } + else + { + return Response.status(Response.Status.UNAUTHORIZED).build(); } - return Response.ok().entity(results).build(); } @GET @@ -125,6 +143,27 @@ public class LogicService { return Response.ok().entity(summaries).build(); } + @GET + @Path("forecastconfigurationsummaries/private/{userUUID}") + @Produces("application/json;charset=UTF-8") + public Response getForecastSummaries( + @PathParam("userUUID") String userUUID + ) + { + UUID uUUID = UUID.fromString(userUUID); + VipsLogicUser user = SessionControllerGetter.getUserBean().findVipsLogicUser(uUUID); + if(user != null) + { + List<ForecastConfiguration> summaries = SessionControllerGetter.getForecastBean().getPrivateForecastConfigurationSummaries(user); + return Response.ok().entity(summaries).build(); + } + else + { + return Response.status(Response.Status.UNAUTHORIZED).build(); + } + + } + /** * Returns the requested forecast configuration * @param forecastConfigurationId @@ -133,15 +172,51 @@ public class LogicService { @GET @Path("forecastconfigurations/{forecastConfigurationId}") @Produces("application/json;charset=UTF-8") - public Response getForecastConfiguration(@PathParam("forecastConfigurationId") Long forecastConfigurationId) + public Response getForecastConfiguration(@PathParam("forecastConfigurationId") Long forecastConfigurationId,@QueryParam("userUUID") String userUUID) + { + if(SessionControllerGetter.getForecastBean().isUserAuthorizedForForecastConfiguration(forecastConfigurationId, userUUID)) + { + ForecastConfiguration forecastConfiguration = SessionControllerGetter.getForecastBean().getForecastConfiguration(forecastConfigurationId); + return Response.ok().entity(forecastConfiguration).build(); + } + else + { + return Response.status(Response.Status.UNAUTHORIZED).build(); + } + } + + @GET + @Path("forecastconfigurations/private/{userUUID}") + @Produces("application/json;charset=UTF-8") + public Response getPrivateForecastConfigurations(@PathParam("userUUID") String userUUID) { - ForecastConfiguration forecastConfiguration = SessionControllerGetter.getForecastBean().getForecastConfiguration(forecastConfigurationId); - return Response.ok().entity(forecastConfiguration).build(); + try + { + UUID uUUID = UUID.fromString(userUUID); + VipsLogicUser user = SessionControllerGetter.getUserBean().findVipsLogicUser(uUUID); + if(user != null) + { + List<ForecastConfiguration> retVal = SessionControllerGetter.getForecastBean().getPrivateForecastConfigurationsForUser(user.getUserId()); + return Response.ok().entity(retVal).build(); + } + else + { + return Response.status(Response.Status.UNAUTHORIZED).build(); + } + } + catch(NullPointerException npe) + { + return Response.noContent().build(); + } + } /** * Returns a list of forecasts for given organization * @param organizationId + * @param cropOrganismIds + * @param from + * @param to * @return */ @GET 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 fac5f04c38a74b63cffc3800f9762d0b8ae38cff..829aee3a352d8eb2e36b6b1dd833cff8a8413e37 100644 --- a/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts.properties +++ b/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts.properties @@ -338,3 +338,7 @@ includeAllChildCrops=Include all child crops pestOrganismIds=Pests cropPestUpdated=Crop pest was updated surveillanceMessageInformation=If you want to create a message about an observation, please use the observation registration form +isPrivate=Is private +privateForecasts=Private forecasts +privateForecastsForOtherUser=Private forecasts for other user +noPrivateForecastsFoundForUser=No private forecasts found for user 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 5a5afd5e0bc3568952dea52c70812e6f103f3f4b..b707f0fbd7186dbad2a8bbdc6731567068086a4e 100644 --- a/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_bs.properties +++ b/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_bs.properties @@ -338,3 +338,7 @@ includeAllChildCrops=Include all child crops pestOrganismIds=Pests cropPestUpdated=Crop pest was updated surveillanceMessageInformation=If you want to create a message about an observation, please use the observation registration form +isPrivate=Is private +privateForecasts=Private forecasts +privateForecastsForOtherUser=Private forecasts for other user +noPrivateForecastsFoundForUser=No private forecasts found for user 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 2f79968fd3eb9c4310e0390abcb2e69f3c1433c5..5beb86b7e9c233c42982d19dcf7a0c9ce10873be 100644 --- a/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_hr.properties +++ b/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_hr.properties @@ -337,3 +337,7 @@ includeAllChildCrops=Include all child crops pestOrganismIds=Pests cropPestUpdated=Crop pest was updated surveillanceMessageInformation=If you want to create a message about an observation, please use the observation registration form +isPrivate=Is private +privateForecasts=Private forecasts +privateForecastsForOtherUser=Private forecasts for other user +noPrivateForecastsFoundForUser=No private forecasts found for user 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 035fda637f46c1f676d9172bfd7e32e20c790a6f..a58b7a01d4a691f3524144c3e847120327e2da13 100644 --- a/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_nb.properties +++ b/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_nb.properties @@ -338,3 +338,7 @@ includeAllChildCrops=Inkluder alle underarter, sorter og varianter pestOrganismIds=Skadegj\u00f8rere cropPestUpdated=Skadegj\u00f8rere for kultur ble lagret surveillanceMessageInformation=Hvis du \u00f8nsker \u00e5 lage en melding om en observasjon/et f\u00f8rstefunn, vennligst bruk <a href="/observation?action=newObservationForm">observasjonsregistreringsskjemaet</a> +isPrivate=Er privat +privateForecasts=Private varsler +privateForecastsForOtherUser=Private varsler for annen bruker +noPrivateForecastsFoundForUser=Fant ingen private varsler for brukeren 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 fb2ab4d0bdecacd01ebc231561dcf424308694ca..0c0763768b7e97cea5ff5f03fe28c6ca7b45a4ce 100644 --- a/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_sr.properties +++ b/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts_sr.properties @@ -338,3 +338,7 @@ includeAllChildCrops=Include all child crops pestOrganismIds=Pests cropPestUpdated=Crop pest was updated surveillanceMessageInformation=If you want to create a message about an observation, please use the observation registration form +isPrivate=Is private +privateForecasts=Private forecasts +privateForecastsForOtherUser=Private forecasts for other user +noPrivateForecastsFoundForUser=No private forecasts found for user diff --git a/src/main/webapp/formdefinitions/forecastConfigurationForm.json b/src/main/webapp/formdefinitions/forecastConfigurationForm.json index b5b1d23cb75b32248dfdafb30797d0e016b47ed9..0273d045d5898e6c6ca56f872a46bd85f31e2dd6 100644 --- a/src/main/webapp/formdefinitions/forecastConfigurationForm.json +++ b/src/main/webapp/formdefinitions/forecastConfigurationForm.json @@ -51,6 +51,11 @@ "nullValue": "-1", "required" : true }, + { + "name" : "isPrivate", + "dataType" : "STRING", + "required" : false + }, { "name" : "locationPointOfInterestId", "dataType" : "INTEGER", diff --git a/src/main/webapp/templates/forecastConfigurationForm.ftl b/src/main/webapp/templates/forecastConfigurationForm.ftl index 376f35a73ad7d8b3fc5abd0c90756a76365897c5..6f3bdf60fa243f6c8b7109ee8ddf8dd27fba7125 100644 --- a/src/main/webapp/templates/forecastConfigurationForm.ftl +++ b/src/main/webapp/templates/forecastConfigurationForm.ftl @@ -1,5 +1,5 @@ <#-- - Copyright (c) 2014 NIBIO <http://www.nibio.no/>. + Copyright (c) 2016 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 @@ along with VIPSLogic. If not, see <http://www.nibio.no/licenses/>. --><#include "master.ftl"> <#macro page_head> - <title></title> + <title>${i18nBundle.viewForecastConfiguration}</title> </#macro> <#macro custom_js> <script src="/js/resourcebundle.js"></script> @@ -85,6 +85,14 @@ </select> <span class="help-block" id="${formId}_cropOrganismId_validation"></span> </div> + <div class="form-group"> + <div class="checkbox"> + <label> + <input type="checkbox" name="isPrivate"<#if forecastConfiguration.isPrivate?has_content && forecastConfiguration.isPrivate == true> checked="checked"</#if>/> + </label> + ${i18nBundle.isPrivate} + </div> + </div> <div class="form-group"> <label for="pestOrganismId">${i18nBundle.pestOrganismId}</label> <select class="form-control" id="pestOrganismId" name="pestOrganismId" onblur="validateField(this);" onchange="renderModelSpecificFields('${formId}');"> diff --git a/src/main/webapp/templates/forecastConfigurationList.ftl b/src/main/webapp/templates/forecastConfigurationList.ftl index 4ba2845c6c6d5c9b75175cb448678ffe4f0cf7c7..5349d69f1be7c2bcbed35d81c0b0c16c599a2e8a 100644 --- a/src/main/webapp/templates/forecastConfigurationList.ftl +++ b/src/main/webapp/templates/forecastConfigurationList.ftl @@ -95,6 +95,83 @@ </tbody> </table> </div> + <h2>${i18nBundle.privateForecasts}</h2> + <div class="table-responsive"> + <table class="table table-striped"> + <thead> + <th>${i18nBundle.modelId}</th> + <th>${i18nBundle.poi}</th> + <th>${i18nBundle.weatherStationPointOfInterestId}</th> + <th>${i18nBundle.dateStart}</th> + <th>${i18nBundle.dateEnd}</th> + </thead> + <tbody> + <#list privateForecastConfigurations as forecastConfiguration> + <tr style="cursor: pointer;" onclick="window.location.href='/forecastConfiguration?action=viewForecastConfiguration&forecastConfigurationId=${forecastConfiguration.forecastConfigurationId}';"> + <td> + <#if i18nBundle.containsKey(forecastConfiguration.modelId)> + ${i18nBundle[forecastConfiguration.modelId]} + <#else> + ${modelInformation[forecastConfiguration.modelId].defaultName} + </#if> + </td> + <td>${forecastConfiguration.locationPointOfInterestId.name}</td> + <td>${forecastConfiguration.weatherStationPointOfInterestId.name}</td> + <td>${forecastConfiguration.dateStart}</td> + <td>${forecastConfiguration.dateEnd}</td> + </tr> + </#list> + </tbody> + </table> + </div> + <#if user.isSuperUser() > + <h2>${i18nBundle.privateForecastsForOtherUser}</h2> + <div class="form-group"> + <label for="otherUserId">${i18nBundle.user}</label> + <select class="form-control" name="otherUserId" onchange="window.location.href='/forecastConfiguration?otherUserId=' + this.options[this.options.selectedIndex].value;"> + <option value="-1">${i18nBundle.pleaseSelect} ${i18nBundle.user?lower_case}</option> + <#list allUsers?sort_by("lastName") as otherUser> + <#if otherUser.userId != user.userId> + <option value="${otherUser.userId}" + <#if (otherUserId?has_content && otherUserId == otherUser.userId)>selected="selected"</#if> + >${otherUser.lastName}, ${otherUser.firstName}</option> + </#if> + </#list> + </select> + </div> + <#if privateForecastConfigurationsForOtherUser?has_content> + <div class="table-responsive"> + <table class="table table-striped"> + <thead> + <th>${i18nBundle.modelId}</th> + <th>${i18nBundle.poi}</th> + <th>${i18nBundle.weatherStationPointOfInterestId}</th> + <th>${i18nBundle.dateStart}</th> + <th>${i18nBundle.dateEnd}</th> + </thead> + <tbody> + <#list privateForecastConfigurations as forecastConfiguration> + <tr style="cursor: pointer;" onclick="window.location.href='/forecastConfiguration?action=viewForecastConfiguration&forecastConfigurationId=${forecastConfiguration.forecastConfigurationId}';"> + <td> + <#if i18nBundle.containsKey(forecastConfiguration.modelId)> + ${i18nBundle[forecastConfiguration.modelId]} + <#else> + ${modelInformation[forecastConfiguration.modelId].defaultName} + </#if> + </td> + <td>${forecastConfiguration.locationPointOfInterestId.name}</td> + <td>${forecastConfiguration.weatherStationPointOfInterestId.name}</td> + <td>${forecastConfiguration.dateStart}</td> + <td>${forecastConfiguration.dateEnd}</td> + </tr> + </#list> + </tbody> + </table> + </div> + <#elseif otherUserId?has_content> + <div class="alert alert-warning">${i18nBundle.noPrivateForecastsFoundForUser}</div> + </#if> + </#if> </div> </#macro> <@page_html/>