diff --git a/src/main/java/no/nibio/vips/logic/controller/servlet/ObservationController.java b/src/main/java/no/nibio/vips/logic/controller/servlet/ObservationController.java index 06fb3bad45342bfd6b1b420a348c50653be299d9..d60827abea796092d0f0dc52aaca5d0bfb8d3541 100644 --- a/src/main/java/no/nibio/vips/logic/controller/servlet/ObservationController.java +++ b/src/main/java/no/nibio/vips/logic/controller/servlet/ObservationController.java @@ -102,6 +102,8 @@ public class ObservationController extends HttpServlet { request.setAttribute("defaultMapZoom", user.getOrganizationId().getDefaultMapZoom()); List<Organism> allPests = em.createNamedQuery("Organism.findAllPests").getResultList(); request.setAttribute("allPests", allPests); + List<Organism> allCrops = em.createNamedQuery("Organism.findAllCrops").getResultList(); + request.setAttribute("allCrops", allCrops); // Hierarchy categories request.setAttribute("hierarchyCategories", SessionControllerGetter.getOrganismBean().getHierarchyCategoryNames(SessionLocaleUtil.getCurrentLocale(request))); request.setAttribute("observationMethods", em.createNamedQuery("ObservationMethod.findAll", ObservationMethod.class).getResultList()); @@ -138,6 +140,8 @@ public class ObservationController extends HttpServlet { request.setAttribute("defaultMapZoom", user.getOrganizationId().getDefaultMapZoom()); List<Organism> allPests = em.createNamedQuery("Organism.findAllPests").getResultList(); request.setAttribute("allPests", allPests); + List<Organism> allCrops = em.createNamedQuery("Organism.findAllCrops").getResultList(); + request.setAttribute("allCrops", allCrops); // Hierarchy categories request.setAttribute("hierarchyCategories", SessionControllerGetter.getOrganismBean().getHierarchyCategoryNames(SessionLocaleUtil.getCurrentLocale(request))); request.setAttribute("observationMethods", em.createNamedQuery("ObservationMethod.findAll", ObservationMethod.class).getResultList()); @@ -181,6 +185,7 @@ public class ObservationController extends HttpServlet { { observation.setOrganism(em.find(Organism.class, formValidation.getFormField("organismId").getValueAsInteger())); + observation.setCropOrganism(em.find(Organism.class, formValidation.getFormField("cropOrganismId").getValueAsInteger())); } //observation.setDenominator(formValidation.getFormField("denominator").getValueAsInteger()); //observation.setObservationMethodId(em.find(ObservationMethod.class, formValidation.getFormField("observationMethodId").getWebValue())); @@ -190,6 +195,8 @@ public class ObservationController extends HttpServlet { observation.setObservationHeading(formValidation.getFormField("observationHeading").getWebValue()); observation.setObservationText(formValidation.getFormField("observationText").getWebValue()); observation.setObservationData(formValidation.getFormField("observationData").getWebValue()); + observation.setIsQuantified(formValidation.getFormField("isQuantified").getWebValue() != null); + observation.setBroadcastMessage(formValidation.getFormField("broadcastMessage").getWebValue() != null); // Storing approval status if(SessionControllerGetter.getUserBean().authorizeUser(user, VipsLogicRole.OBSERVATION_AUTHORITY, VipsLogicRole.SUPERUSER)) diff --git a/src/main/java/no/nibio/vips/logic/controller/session/ObservationBean.java b/src/main/java/no/nibio/vips/logic/controller/session/ObservationBean.java index bcb1b8fe59a1ad6dc91fdfb061dd24b1f1fe20e5..d886ce1caf411583f5b0459ae989fd7c5a010088 100644 --- a/src/main/java/no/nibio/vips/logic/controller/session/ObservationBean.java +++ b/src/main/java/no/nibio/vips/logic/controller/session/ObservationBean.java @@ -161,4 +161,18 @@ public class ObservationBean { Observation observation = em.find(Observation.class, observationId); em.remove(observation); } + + public Object getBroadcastObservations(Integer organizationId) { + Organization organization= em.find(Organization.class, organizationId); + /*List<VipsLogicUser> users = em.createNamedQuery("VipsLogicUser.findByOrganizationId", VipsLogicUser.class) + .setParameter("organizationId", organization) + .getResultList();*/ + + List<Observation> retVal = this.getObservationsWithGeoInfo(em.createNamedQuery("Observation.findByOrganizationIdAndStatusTypeIdAndBroadcastMessage") + .setParameter("organizationId", organization) + .setParameter("statusTypeId", Observation.STATUS_TYPE_ID_APPROVED) + .getResultList()); + + return retVal; + } } diff --git a/src/main/java/no/nibio/vips/logic/controller/session/OrganismBean.java b/src/main/java/no/nibio/vips/logic/controller/session/OrganismBean.java index a200286897214a56d6328c2e4c71f66261e10587..1241c00bbd99485a16331334bbc8b0c93c17d216 100644 --- a/src/main/java/no/nibio/vips/logic/controller/session/OrganismBean.java +++ b/src/main/java/no/nibio/vips/logic/controller/session/OrganismBean.java @@ -96,7 +96,7 @@ public class OrganismBean { */ public List<Organism> getTopLevelOrganisms() { - List<Organism> retVal = em.createNativeQuery("SELECT * FROM Organism o WHERE o.parent_organism_id IS NULL", Organism.class).getResultList(); + List<Organism> retVal = em.createNativeQuery("SELECT * FROM Organism o WHERE o.parent_organism_id IS NULL AND o.organism_id > 0", Organism.class).getResultList(); for(Organism organism: retVal) { List<Organism> children = em.createNamedQuery("Organism.findByParentOrganismId").setParameter("parentOrganismId", organism.getOrganismId()).getResultList(); diff --git a/src/main/java/no/nibio/vips/logic/entity/Observation.java b/src/main/java/no/nibio/vips/logic/entity/Observation.java index 06601f8481d9dc994f44a6873d7a7fac665cfb31..01409a46bf9711eb1a146979672e652f1433f5de 100644 --- a/src/main/java/no/nibio/vips/logic/entity/Observation.java +++ b/src/main/java/no/nibio/vips/logic/entity/Observation.java @@ -58,6 +58,7 @@ import org.hibernate.annotations.TypeDefs; @NamedQuery(name = "Observation.findByObservationId", query = "SELECT o FROM Observation o WHERE o.observationId = :observationId"), @NamedQuery(name = "Observation.findByUserId", query = "SELECT o FROM Observation o WHERE o.userId IN(:userId)"), @NamedQuery(name = "Observation.findByOrganizationIdAndStatusTypeId", query = "SELECT o FROM Observation o WHERE o.userId IN(SELECT v.userId FROM VipsLogicUser v WHERE v.organizationId = :organizationId OR v.organizationId IN(SELECT o.organizationId FROM Organization o WHERE o.parentOrganizationId = :organizationId)) AND o.statusTypeId= :statusTypeId"), + @NamedQuery(name = "Observation.findByOrganizationIdAndStatusTypeIdAndBroadcastMessage", query = "SELECT o FROM Observation o WHERE o.userId IN(SELECT v.userId FROM VipsLogicUser v WHERE v.organizationId = :organizationId OR v.organizationId IN(SELECT o.organizationId FROM Organization o WHERE o.parentOrganizationId = :organizationId)) AND o.statusTypeId= :statusTypeId AND o.broadcastMessage IS TRUE"), @NamedQuery(name = "Observation.findByOrganism", query = "SELECT o FROM Observation o WHERE o.organism = :organism"), @NamedQuery(name = "Observation.findByTimeOfObservation", query = "SELECT o FROM Observation o WHERE o.timeOfObservation = :timeOfObservation") }) @@ -67,6 +68,7 @@ public class Observation implements Serializable, no.nibio.vips.observation.Obse private Integer observationId; private Date timeOfObservation; private Organism organism; + private Organism cropOrganism; private Integer userId; private List<Gis> geoinfo; //private Double observedValue; @@ -80,6 +82,7 @@ public class Observation implements Serializable, no.nibio.vips.observation.Obse private String statusRemarks; private String observationData; private Boolean isQuantified; + private Boolean broadcastMessage; private GISUtil GISUtil; @@ -249,7 +252,7 @@ public class Observation implements Serializable, no.nibio.vips.observation.Obse */ @JoinColumn(name = "organism_id", referencedColumnName = "organism_id") @ManyToOne - @JsonIgnore + //@JsonIgnore public Organism getOrganism() { return organism; } @@ -260,7 +263,7 @@ public class Observation implements Serializable, no.nibio.vips.observation.Obse public void setOrganism(Organism organism) { this.organism = organism; } - + /* @Override @Transient @@ -380,6 +383,7 @@ public class Observation implements Serializable, no.nibio.vips.observation.Obse */ @Type(type = "StringJsonObject") @Column(name = "observation_data") + @Override public String getObservationData() { return observationData; } @@ -406,4 +410,40 @@ public class Observation implements Serializable, no.nibio.vips.observation.Obse this.isQuantified = isQuantified; } + /** + * @return the cropOrganism + */ + @JoinColumn(name = "crop_organism_id", referencedColumnName = "organism_id") + @ManyToOne + public Organism getCropOrganism() { + return cropOrganism; + } + + /** + * @param cropOrganism the cropOrganism to set + */ + public void setCropOrganism(Organism cropOrganism) { + this.cropOrganism = cropOrganism; + } + + @Transient + public Integer getCropOrganismId() { + return this.getCropOrganism() != null ? this.getCropOrganism().getOrganismId() : null; + } + + /** + * @return the broadcastMessage + */ + @Column(name = "broadcast_message") + public Boolean getBroadcastMessage() { + return broadcastMessage; + } + + /** + * @param broadcastMessage the broadcastMessage to set + */ + public void setBroadcastMessage(Boolean broadcastMessage) { + this.broadcastMessage = broadcastMessage; + } + } 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 a8e5b3ca097812312e000386eae0f7c2627cec97..fa00289ed5354571648d74803ef30f431fe0b383 100644 --- a/src/main/java/no/nibio/vips/logic/service/LogicService.java +++ b/src/main/java/no/nibio/vips/logic/service/LogicService.java @@ -491,6 +491,37 @@ public class LogicService { return Response.ok().entity(observations).build(); } + @GET + @Path("observation/{observationId}") + @Produces("application/json;charset=UTF-8") + public Response getObservation(@PathParam("observationId") Integer observationId){ + return Response.ok().entity(SessionControllerGetter.getObservationBean().getObservation(observationId)).build(); + } + + /** + * Publicly available observations per organization + * @param organizationId + * @return APPROVED observations + */ + @GET + @Path("observation/list/{organizationId}") + @Produces("application/json;charset=UTF-8") + public Response getObservations(@PathParam("organizationId") Integer organizationId){ + return Response.ok().entity(SessionControllerGetter.getObservationBean().getObservations(organizationId, Observation.STATUS_TYPE_ID_APPROVED)).build(); + } + + /** + * Publicly available observations per organization + * @param organizationId + * @return APPROVED observations + */ + @GET + @Path("observation/broadcast/list/{organizationId}") + @Produces("application/json;charset=UTF-8") + public Response getBroadcastObservations(@PathParam("organizationId") Integer organizationId){ + return Response.ok().entity(SessionControllerGetter.getObservationBean().getBroadcastObservations(organizationId)).build(); + } + /** * Service available locally for cron jobs. Most useful on test servers * @return 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 1e939ee3dd8ee958b58a02b8a059f95c64b49ed1..2fec0015cdcfe64d4863c821914403d39b380095 100644 --- a/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts.properties +++ b/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts.properties @@ -327,3 +327,6 @@ allCategories=All categories pending=Pending approved=Approved rejected=Rejected +isQuantified=Is quantified +missingInDatabase=Missing in database +broadcastMessage=Broadcast the message 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 bee6d7baaaf6544955411e9b3649a7bd9b76a38a..3758cf8c032d410867fa7319d8c386be7ea7e8d9 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 @@ -327,3 +327,6 @@ allCategories=All categories pending=Pending approved=Approved rejected=Rejected +isQuantified=Is quantified +missingInDatabase=Missing in database +broadcastMessage=Broadcast the message 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 1a107c8a72cc822c138b8edf7a24abf8bbdbd301..c289788a79f5241ae9885703caa677e2aa4ed748 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 @@ -326,3 +326,6 @@ allCategories=All categories pending=Pending approved=Approved rejected=Rejected +isQuantified=Is quantified +missingInDatabase=Missing in database +broadcastMessage=Broadcast the message 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 ba275d0cd876549385432a8564f0e1b49b41d6a6..96c5dc398c008194ff593d40e6723f1f5fb39456 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 @@ -327,3 +327,6 @@ allCategories=Alle kategorier pending=Venter approved=Godkjent rejected=Avsl\u00e5tt +isQuantified=Er kvantifisert +missingInDatabase=Ikke funnet i databasen +broadcastMessage=Kringkast denne meldingen 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 9a75549594a2c43ae3bd56fbe0db973dbfd30f89..d0c87dade542a40fcfdfed0b821b390ebb0d79ee 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 @@ -327,3 +327,6 @@ allCategories=All categories pending=Pending approved=Approved rejected=Rejected +isQuantified=Is quantified +missingInDatabase=Missing in database +broadcastMessage=Broadcast the message diff --git a/src/main/webapp/formdefinitions/observationForm.json b/src/main/webapp/formdefinitions/observationForm.json index cb5a6a645245f8c01be894db96808023f72b5d68..665f0b450a38c51c0f8aa61d416ea6a3da3dd377 100644 --- a/src/main/webapp/formdefinitions/observationForm.json +++ b/src/main/webapp/formdefinitions/observationForm.json @@ -30,6 +30,13 @@ "required" : true, "nullValue" : "-1" }, + { + "name" : "cropOrganismId", + "dataType" : "INTEGER", + "fieldType" : "SELECT_SINGLE", + "required" : true, + "nullValue" : "-1" + }, { "name" : "timeOfObservation", "dataType" : "TIMESTAMP", @@ -44,6 +51,16 @@ "required" : true, "nullValue" : "{\"type\":\"FeatureCollection\",\"features\":[]}" }, + { + "name" : "isQuantified", + "dataType" : "STRING", + "required" : false + }, + { + "name" : "broadcastMessage", + "dataType" : "STRING", + "required" : false + }, { "name" : "observationData", "dataType" : "STRING", diff --git a/src/main/webapp/js/validateForm.js b/src/main/webapp/js/validateForm.js index d0bcdbd442a7f5aff9a57df27659d5eee2c1cf86..f54ea59e29238ea6b08b32dbdf3db629bb6bbe56 100644 --- a/src/main/webapp/js/validateForm.js +++ b/src/main/webapp/js/validateForm.js @@ -545,7 +545,14 @@ function validizeField(inputEl, theForm) return; } styleValid(theForm[inputEl.name]); - getValidationOutputEl(inputEl, theForm).innerHTML = ""; + try + { + getValidationOutputEl(inputEl, theForm).innerHTML = ""; + } + catch(e) + { + console.log(e.message); + } } /** diff --git a/src/main/webapp/templates/observationForm.ftl b/src/main/webapp/templates/observationForm.ftl index e2ea2a4cdd33c9f355a35cfc0baed21bdaead0d0..e5370b2b773fbc59dceb329954c69beb2a12217e 100755 --- a/src/main/webapp/templates/observationForm.ftl +++ b/src/main/webapp/templates/observationForm.ftl @@ -122,7 +122,7 @@ <div class="row"> <div class="col-md-6"> <#assign formId = "observationForm"> - <form id="${formId}" role="form" action="/observation?action=observationFormSubmit" method="POST" onsubmit="this['geoInfo'].value=getFeatures();try{mw.save();console.log(this['observationData']);this['observationData'].value=JSON.stringify(mw.toInspect);return validateForm(this);}catch(e){console.log(e.message);console.log(e);return false;}"> + <form id="${formId}" role="form" action="/observation?action=observationFormSubmit" method="POST" onsubmit="this['geoInfo'].value=getFeatures();try{mw.save();this['observationData'].value=JSON.stringify(mw.toInspect);return validateForm(this);}catch(e){console.log(e.message);console.log(e);return false;}"> <!--form id="${formId}" role="form" action="/observation?action=observationFormSubmit" method="POST" onsubmit="this['geoInfo'].value=getFeatures();mw.save();console.log(this['observationData']);this['observationData'].value=JSON.stringify(mw.toInspect);return validateForm(this);"--> <!--form id="${formId}" role="form" action="/observation?action=observationFormSubmit" method="POST" onsubmit="this['geoInfo'].value=getFeatures();mw.save();console.log(this['observationData']);this['observationData'].value=JSON.stringify(mw.toInspect);validateForm(this);return false;"--> <input type="hidden" name="geoInfo" value=""/> @@ -134,6 +134,7 @@ <select class="form-control" name="organismId" <#if observation.organism?has_content>readonly="readonly"<#else>onchange="initObservationData(this.options[this.options.selectedIndex].value,organizationId);" onblur="validateField(this);"</#if>> <option value="-1">${i18nBundle.pleaseSelect} ${i18nBundle.organism?lower_case}</option> + <option value="-10"<#if (observation.organism?has_content && observation.organism.organismId == -10)>selected="selected"</#if>>${i18nBundle.missingInDatabase}</option> <#list allPests?sort_by("latinName") as organism> <option value="${organism.organismId}" <#if (observation.organism?has_content && observation.organism.organismId == organism.organismId)>selected="selected"</#if> @@ -142,6 +143,21 @@ </select> <span class="help-block" id="${formId}_organismId_validation"></span> + </div> + <div class="form-group"> + <label for="cropOrganismId">${i18nBundle.cropOrganismId}</label> + <select class="form-control" name="cropOrganismId" <#if observation.organism?has_content>readonly="readonly"<#else>onblur="validateField(this);"</#if>> + <option value="-1">${i18nBundle.pleaseSelect} ${i18nBundle.cropOrganismId?lower_case}</option> + <option value="-10"<#if (observation.cropOrganism?has_content && observation.cropOrganism.organismId == -10)>selected="selected"</#if>>${i18nBundle.missingInDatabase}</option> + <#list allCrops?sort_by("latinName") as cropOrganism> + <option value="${cropOrganism.organismId}" + <#if (observation.cropOrganism?has_content && observation.cropOrganism.organismId == cropOrganism.organismId)>selected="selected"</#if> + >${cropOrganism.latinName!""}/${cropOrganism.getLocalName(currentLocale.language)!""} (${hierarchyCategories.getName(cropOrganism.hierarchyCategoryId)})</option> + </#list> + </select> + <span class="help-block" id="${formId}_cropOrganismId_validation"></span> + + </div> <!--div class="form-group"> <label for="location">${i18nBundle.location}</label> @@ -153,6 +169,14 @@ <input type="datetime" class="form-control" name="timeOfObservation" placeholder="${i18nBundle.timeOfObservation}" value="${(observation.timeOfObservation?string("yyyy-MM-dd HH:mmZ"))!.now?string("yyyy-MM-dd HH:mmZ")}" onblur="validateField(this);" /> <span class="help-block" id="${formId}_timeOfObservation_validation"></span> </div> + <div class="form-group"> + <div class="checkbox"> + <label> + <input type="checkbox" name="isQuantified"<#if observation.isQuantified?has_content && observation.isQuantified == false><#else>checked="checked"</#if>/> + </label> + ${i18nBundle.isQuantified} + </div> + </div> <div class="form-group"> <fieldset> <legend>Observation data</legend> @@ -180,6 +204,14 @@ </select> <span class="help-block" id="${formId}_observationMethodId_validation"></span> </div--> + <div class="form-group"> + <div class="checkbox"> + <label> + <input type="checkbox" name="broadcastMessage"<#if observation.broadcastMessage?has_content && observation.broadcastMessage == false><#else>checked="checked"</#if>/> + </label> + ${i18nBundle.broadcastMessage} + </div> + </div> <div class="form-group"> <label for="observationHeading">${i18nBundle.observationHeading}</label> <input type="text" class="form-control" name="observationHeading" placeholder="" value="${observation.observationHeading!""}" onblur="validateField(this);"/>