From 10f5a3b433111d1540bbc87b03c449a3544965a7 Mon Sep 17 00:00:00 2001
From: Tor-Einar Skog <tor-einar.skog@bioforsk.no>
Date: Thu, 25 Feb 2016 11:20:16 +0100
Subject: [PATCH] Added connections between crops and pests in observation form

---
 .../servlet/OrganismController.java           |  1 +
 .../controller/session/OrganismBean.java      | 32 +++++++++
 .../vips/logic/service/LogicService.java      | 17 +++++
 src/main/webapp/js/util.js                    | 13 ++++
 src/main/webapp/templates/cropPestForm.ftl    |  3 +
 src/main/webapp/templates/observationForm.ftl | 67 ++++++++++++++++++-
 6 files changed, 132 insertions(+), 1 deletion(-)

diff --git a/src/main/java/no/nibio/vips/logic/controller/servlet/OrganismController.java b/src/main/java/no/nibio/vips/logic/controller/servlet/OrganismController.java
index 0696e319..4473a1a8 100644
--- a/src/main/java/no/nibio/vips/logic/controller/servlet/OrganismController.java
+++ b/src/main/java/no/nibio/vips/logic/controller/servlet/OrganismController.java
@@ -311,6 +311,7 @@ public class OrganismController extends HttpServlet {
                 request.setAttribute("cropPest", cropPest);
             }
             request.setAttribute("hierarchyCategories", SessionControllerGetter.getOrganismBean().getHierarchyCategoryNames(SessionLocaleUtil.getCurrentLocale(request)));
+            request.setAttribute("messageKey", request.getParameter("messageKey"));
             request.getRequestDispatcher("/cropPestForm.ftl").forward(request, response);
         }
         else if(action.equals("submitCropPest"))
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 57b7b8fd..5adfe791 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
@@ -267,6 +267,38 @@ public class OrganismBean {
         }
     }
     
+    /**
+     * Searching recursively upwards in organism tree to find a cropPest.
+     * @param cropOrganismId id of the crop
+     * @param isPrimaryCrop false if this is the original crop, true if search upwards
+     * @return 
+     */
+    public CropPest getCropPestRecursive(Integer cropOrganismId, boolean isPrimaryCrop)
+    {
+        // Try to find a cropPest for this crop
+        CropPest cropPest = this.getCropPest(cropOrganismId);
+        // If found AND either it is the primary crop OR it's a parent set to include all child crops
+        // we return it
+        if(cropPest != null && (isPrimaryCrop || cropPest.getIncludeAllChildCrops()))
+        {
+            return cropPest;
+        }
+        // If not, check if parent crop exists and keep on searching
+        // (If no parent crop, we're done and return empty handed)
+        else
+        {
+            Organism o = em.find(Organism.class, cropOrganismId);
+            if(o.getParentOrganismId() != null)
+            {
+                return this.getCropPestRecursive(o.getParentOrganismId(), false);
+            }
+            else
+            {
+                return null;
+            }
+        }
+    }
+    
     public CropPest storeCropPest(CropPest cropPest)
     {
         return em.merge(cropPest);
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 fa00289e..07a4764d 100644
--- a/src/main/java/no/nibio/vips/logic/service/LogicService.java
+++ b/src/main/java/no/nibio/vips/logic/service/LogicService.java
@@ -48,6 +48,7 @@ import javax.ws.rs.core.Response;
 import no.nibio.vips.coremanager.service.ManagerResource;
 import no.nibio.vips.entity.WeatherObservation;
 import no.nibio.vips.logic.authenticate.PasswordValidationException;
+import no.nibio.vips.logic.entity.CropPest;
 import no.nibio.vips.logic.entity.ForecastResult;
 import no.nibio.vips.logic.i18n.SessionLocaleUtil;
 import no.nibio.vips.logic.entity.ForecastConfiguration;
@@ -592,6 +593,22 @@ public class LogicService {
         }
     }
     
+    @GET
+    @Path("organism/croppest/{cropOrganismId}")
+    @Produces("application/json;charset=UTF-8")
+    public Response getCropPest(@PathParam("cropOrganismId") Integer cropOrganismId)
+    {
+        CropPest retVal = SessionControllerGetter.getOrganismBean().getCropPestRecursive(cropOrganismId,true);
+        if(retVal != null)
+        {
+            return Response.ok().entity(retVal).build();
+        }
+        else
+        {
+            return Response.status(Response.Status.NO_CONTENT).build();
+        }
+    }
+    
     private ManagerResource getManagerResource()
     {
         Client client = ClientBuilder.newClient();
diff --git a/src/main/webapp/js/util.js b/src/main/webapp/js/util.js
index f86837a8..adebd204 100644
--- a/src/main/webapp/js/util.js
+++ b/src/main/webapp/js/util.js
@@ -21,3 +21,16 @@ function setFieldValue(theForm, fieldName, value)
 {
     theForm[fieldName] = value;
 }
+
+var compareSelectListOptions = function(a,b)
+{
+	if(a.text < b.text)
+	{
+		return -1;
+	}
+	if(a.text > b.text)
+	{
+		return 1;
+	}
+	return 0;
+}
diff --git a/src/main/webapp/templates/cropPestForm.ftl b/src/main/webapp/templates/cropPestForm.ftl
index e534dbae..e709ec31 100644
--- a/src/main/webapp/templates/cropPestForm.ftl
+++ b/src/main/webapp/templates/cropPestForm.ftl
@@ -40,6 +40,9 @@
 <#macro page_contents>
 <div class="singleBlockContainer">
 	<h1>${i18nBundle.editCropPests}</h1>
+	<#if messageKey?has_content>
+	<div class="alert alert-success">${i18nBundle(messageKey)}</div>
+	</#if>
 	<#assign formId = "cropPestForm">
 	<form id="${formId}" action="/organism?action=submitCropPest" method="POST" role="form" onsubmit="return validateForm(this);">
 	<div class="form-group">
diff --git a/src/main/webapp/templates/observationForm.ftl b/src/main/webapp/templates/observationForm.ftl
index 8b0617a8..8715c0e4 100755
--- a/src/main/webapp/templates/observationForm.ftl
+++ b/src/main/webapp/templates/observationForm.ftl
@@ -35,6 +35,7 @@
 	<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" src="/js/util.js"></script>
 	<script type="text/javascript" src="/js/objectGISInfoMap.js"></script>
 	<script type="text/javascript">
 		var organizationId = ${user.organizationId.organizationId};
@@ -131,6 +132,70 @@
 			mw.buildWidgets();
 		};
 		
+		var updateCropPests = function(){
+			var theForm = document.getElementById('observationForm');
+			var selectedCropId = theForm["cropOrganismId"].options[theForm["cropOrganismId"].options.selectedIndex].value;
+			// If this is not a new observation, or the selected crop is not in the database, we keep calm
+			if(theForm["observationId"].value !== "-1" ||  selectedCropId == "-10")
+			{
+				return;
+			}
+			$.getJSON( "/rest/organism/croppest/" + selectedCropId, function( json ) {
+				updateCropPestsCallback(json);
+			})
+			.fail(function() {
+			    alert( "Error getting pests for this crop. Please contact system administrator" );
+			  });
+		};
+		
+		var updateCropPestsCallback = function(cropPest) {
+			var pestList = document.getElementById('observationForm')["organismId"];
+			if(cropPest == null)
+			{
+				// Need to reorganize pests back to default
+				var allPests = [];
+				for(var i=2;i<pestList.options.length;i++)
+				{
+					allPests.push(pestList.options[i]);
+				}
+				allPests.sort(compareSelectListOptions);
+				pestList.options.length=2; // Keeping the top two
+				for(var i=0;i<allPests.length;i++)
+				{
+					pestList.options[pestList.options.length] = allPests[i];
+				}
+			}
+			else
+			{
+				var prioritatedPests = [];
+				var unprioritatedPests = []
+				for(var i=2;i<pestList.options.length;i++)
+				{
+					if(cropPest.pestOrganismIds.indexOf(parseInt(pestList.options[i].value)) >= 0)
+					{
+						//console.log(pestList.options[i].value + " is prioritated");
+						prioritatedPests.push(pestList.options[i]);
+					}
+					else if(pestList.options[i].value != "-1") // Avoiding the "---" option
+					{
+						//console.log(pestList.options[i].value + " is unprioritated");
+						unprioritatedPests.push(pestList.options[i]);
+					}
+					
+				}
+				pestList.options.length=2; // Keeping the top two
+				for(var i=0;i<prioritatedPests.length;i++)
+				{
+					pestList.options[pestList.options.length] = prioritatedPests[i];
+				}
+				pestList.options[pestList.options.length] = new Option("---","-1");
+				for(var i=0;i<unprioritatedPests.length;i++)
+				{
+					pestList.options[pestList.options.length] = unprioritatedPests[i];
+				}
+			}
+		};
+		
 	</script>
 </#macro>
 <#macro page_contents>
@@ -156,7 +221,7 @@
 			  
 			   <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>>
+			    <select class="form-control" name="cropOrganismId" <#if observation.organism?has_content>readonly="readonly"<#else>onblur="validateField(this);"</#if> onchange="updateCropPests();">
 				<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>
-- 
GitLab