From 13d8d6985a86790cc63cbffd2e2eb9d759871703 Mon Sep 17 00:00:00 2001
From: Tor-Einar Skog <tor-einar.skog@nibio.no>
Date: Tue, 29 May 2018 13:44:51 +0200
Subject: [PATCH] Bugfixes and improvements of Apple Fruit Moth Module

---
 .../vips/logic/entity/PreparationType.java    |  2 ++
 .../applefruitmoth/AppleFruitMothBean.java    | 19 +++++++++++++++++++
 .../AppleFruitMothController.java             | 11 +++++++----
 .../applefruitmoth/ObservationSite.java       | 17 +++++++++++++++++
 .../ObservationSitePointSeasonData.java       | 17 +++++++++++++++++
 .../ObservationSiteSeasonCommonData.java      |  3 +++
 .../vips/logic/i18n/vipslogictexts.properties |  1 +
 .../logic/i18n/vipslogictexts_bs.properties   |  1 +
 .../logic/i18n/vipslogictexts_hr.properties   |  1 +
 .../logic/i18n/vipslogictexts_nb.properties   |  1 +
 .../logic/i18n/vipslogictexts_sr.properties   |  1 +
 .../i18n/vipslogictexts_zh_CN.properties      |  1 +
 .../appleFruitMothStationForm.json            |  4 ++--
 .../js/appleFruitMothObservationSitesMap.js   |  2 +-
 .../templates/appleFruitMothClusterForm.ftl   |  4 +++-
 .../templates/appleFruitMothStationForm.ftl   | 16 +++++++++-------
 .../templates/appleFruitMothStationList.ftl   |  5 +++++
 17 files changed, 91 insertions(+), 15 deletions(-)

diff --git a/src/main/java/no/nibio/vips/logic/entity/PreparationType.java b/src/main/java/no/nibio/vips/logic/entity/PreparationType.java
index 12c2d1d4..623c0234 100755
--- a/src/main/java/no/nibio/vips/logic/entity/PreparationType.java
+++ b/src/main/java/no/nibio/vips/logic/entity/PreparationType.java
@@ -19,6 +19,7 @@
 
 package no.nibio.vips.logic.entity;
 
+import com.fasterxml.jackson.annotation.JsonIgnore;
 import java.io.Serializable;
 import java.util.Collection;
 import javax.persistence.Basic;
@@ -55,6 +56,7 @@ public class PreparationType implements Serializable {
     @Size(max = 255)
     @Column(name = "preparation_type_name")
     private String preparationTypeName;
+    @JsonIgnore
     @OneToMany(mappedBy = "preparationTypeId")
     private Collection<Preparation> preparationCollection;
 
diff --git a/src/main/java/no/nibio/vips/logic/modules/applefruitmoth/AppleFruitMothBean.java b/src/main/java/no/nibio/vips/logic/modules/applefruitmoth/AppleFruitMothBean.java
index 17760776..92c07b8a 100755
--- a/src/main/java/no/nibio/vips/logic/modules/applefruitmoth/AppleFruitMothBean.java
+++ b/src/main/java/no/nibio/vips/logic/modules/applefruitmoth/AppleFruitMothBean.java
@@ -31,11 +31,14 @@ import de.micromata.opengis.kml.v_2_2_0.Units;
 import de.micromata.opengis.kml.v_2_2_0.Vec2;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
+import java.util.Date;
 import java.util.List;
 import javax.ejb.LocalBean;
 import javax.ejb.Stateless;
 import javax.persistence.EntityManager;
+import javax.persistence.NoResultException;
 import javax.persistence.PersistenceContext;
+import javax.persistence.Query;
 import no.nibio.vips.logic.util.Globals;
 
 /**
@@ -54,6 +57,22 @@ public class AppleFruitMothBean {
         List<ObservationSite> sites = em.createNamedQuery("ObservationSite.findAll").getResultList();
         return sites;
     }
+    
+    public List<ObservationSite> getObservationSitesWithClusterCountLastUpdate(){
+        List<ObservationSite> sites = this.getObservationSites();
+        Query qu = em.createNativeQuery("SELECT max(last_updated) FROM applefruitmoth.observation_site_point_season_data osd WHERE osd.observation_site_point_id IN (SELECT observation_site_point_id FROM applefruitmoth.observation_site_point WHERE observation_site_id = :observationSiteId)");
+        sites.stream().forEach(site->{
+            qu.setParameter("observationSiteId", site.getObservationSiteId());
+            try
+            {
+                Date lastUpdated = (Date) qu.getSingleResult();
+                site.setLastUpdatedClusterCount(lastUpdated);
+            }
+            catch(NoResultException ex){}
+        });
+        
+        return sites;
+    }
 
     public ObservationSite getObservationSite(Integer observationSiteId) {
         return em.find(ObservationSite.class, observationSiteId);
diff --git a/src/main/java/no/nibio/vips/logic/modules/applefruitmoth/AppleFruitMothController.java b/src/main/java/no/nibio/vips/logic/modules/applefruitmoth/AppleFruitMothController.java
index c048e907..e4f3ca5d 100755
--- a/src/main/java/no/nibio/vips/logic/modules/applefruitmoth/AppleFruitMothController.java
+++ b/src/main/java/no/nibio/vips/logic/modules/applefruitmoth/AppleFruitMothController.java
@@ -70,7 +70,7 @@ public class AppleFruitMothController extends HttpServlet {
             if(action == null)
             {
                 // Show map and list of existing stations
-                List<ObservationSite> observationSites = SessionControllerGetter.getAppleFruitMothBean().getObservationSites();
+                List<ObservationSite> observationSites = SessionControllerGetter.getAppleFruitMothBean().getObservationSitesWithClusterCountLastUpdate();
                 request.setAttribute("observationSites", observationSites);
                 request.getRequestDispatcher("/appleFruitMothStationList.ftl").forward(request, response);
             }
@@ -284,9 +284,11 @@ public class AppleFruitMothController extends HttpServlet {
                     ObservationSite observationSite = SessionControllerGetter.getAppleFruitMothBean().getObservationSite(observationSiteId);
                     
                     ObservationSiteSeasonCommonData seasonCommonData = observationSite.getCommonDataForSeason(currentSeason);
-                    seasonCommonData.setRemarks(request.getParameter("remarks"));
-                    SessionControllerGetter.getAppleFruitMothBean().storeObservationSitePointSeasonCommonData(seasonCommonData);
-                    
+                    if(seasonCommonData != null)
+                    {
+                        seasonCommonData.setRemarks(request.getParameter("remarks") != null ? request.getParameter("remarks") : "");
+                        SessionControllerGetter.getAppleFruitMothBean().storeObservationSitePointSeasonCommonData(seasonCommonData);
+                    }
                     //System.out.println("sitePointSetLength=" + observationSite.getObservationSitePointSet().size());
                     treeNames.stream().forEach(treeName->{
                         try {
@@ -311,6 +313,7 @@ public class AppleFruitMothController extends HttpServlet {
                             newData.setAutumnDate(autumnDate);
                             newData.setSpringValue(springValue);
                             newData.setSpringDate(springDate);
+                            newData.setLastUpdated(new Date());
                             
                             SessionControllerGetter.getAppleFruitMothBean().storeObservationSitePointSeasonData(newData);
                             //dataSet.add(newData);
diff --git a/src/main/java/no/nibio/vips/logic/modules/applefruitmoth/ObservationSite.java b/src/main/java/no/nibio/vips/logic/modules/applefruitmoth/ObservationSite.java
index 716bd8a3..bf96fa03 100755
--- a/src/main/java/no/nibio/vips/logic/modules/applefruitmoth/ObservationSite.java
+++ b/src/main/java/no/nibio/vips/logic/modules/applefruitmoth/ObservationSite.java
@@ -21,6 +21,7 @@ package no.nibio.vips.logic.modules.applefruitmoth;
 
 import com.vividsolutions.jts.geom.Geometry;
 import java.io.Serializable;
+import java.util.Date;
 import java.util.HashSet;
 import java.util.Set;
 import javax.persistence.Basic;
@@ -78,6 +79,8 @@ public class ObservationSite implements Serializable, Comparable {
     @JoinColumn(name = "gis_id", referencedColumnName="gis_id")
     @OneToOne
     private Gis gisId;
+    @Transient
+    private Date lastUpdatedClusterCount;
 
 
     public ObservationSite() {
@@ -184,4 +187,18 @@ public class ObservationSite implements Serializable, Comparable {
     public void setGisId(Gis gisId) {
         this.gisId = gisId;
     }
+
+    /**
+     * @return the lastUpdatedClusterCount
+     */
+    public Date getLastUpdatedClusterCount() {
+        return lastUpdatedClusterCount;
+    }
+
+    /**
+     * @param lastUpdatedClusterCount the lastUpdatedClusterCount to set
+     */
+    public void setLastUpdatedClusterCount(Date lastUpdatedClusterCount) {
+        this.lastUpdatedClusterCount = lastUpdatedClusterCount;
+    }
 }
diff --git a/src/main/java/no/nibio/vips/logic/modules/applefruitmoth/ObservationSitePointSeasonData.java b/src/main/java/no/nibio/vips/logic/modules/applefruitmoth/ObservationSitePointSeasonData.java
index f45d325c..7dc10583 100755
--- a/src/main/java/no/nibio/vips/logic/modules/applefruitmoth/ObservationSitePointSeasonData.java
+++ b/src/main/java/no/nibio/vips/logic/modules/applefruitmoth/ObservationSitePointSeasonData.java
@@ -67,6 +67,9 @@ public class ObservationSitePointSeasonData implements Serializable {
     @JoinColumn(name = "observation_site_point_id", referencedColumnName = "observation_site_point_id", insertable = false, updatable = false)
     @ManyToOne(optional = false)
     private ObservationSitePoint observationSitePoint;
+    @Column(name = "last_updated")
+    @Temporal(TemporalType.DATE)
+    private Date lastUpdated;
 
     public ObservationSitePointSeasonData() {
     }
@@ -152,4 +155,18 @@ public class ObservationSitePointSeasonData implements Serializable {
         return "no.nibio.vips.logic.modules.applefruitmoth.ObservationSitePointSeasonData[ observationSitePointSeasonDataPK=" + observationSitePointSeasonDataPK + " ]";
     }
 
+    /**
+     * @return the lastUpdated
+     */
+    public Date getLastUpdated() {
+        return lastUpdated;
+    }
+
+    /**
+     * @param lastUpdated the lastUpdated to set
+     */
+    public void setLastUpdated(Date lastUpdated) {
+        this.lastUpdated = lastUpdated;
+    }
+
 }
diff --git a/src/main/java/no/nibio/vips/logic/modules/applefruitmoth/ObservationSiteSeasonCommonData.java b/src/main/java/no/nibio/vips/logic/modules/applefruitmoth/ObservationSiteSeasonCommonData.java
index 27842f45..fbe051b1 100755
--- a/src/main/java/no/nibio/vips/logic/modules/applefruitmoth/ObservationSiteSeasonCommonData.java
+++ b/src/main/java/no/nibio/vips/logic/modules/applefruitmoth/ObservationSiteSeasonCommonData.java
@@ -30,6 +30,8 @@ import javax.persistence.ManyToOne;
 import javax.persistence.NamedQueries;
 import javax.persistence.NamedQuery;
 import javax.persistence.Table;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
 import javax.xml.bind.annotation.XmlRootElement;
 
 /**
@@ -59,6 +61,7 @@ public class ObservationSiteSeasonCommonData implements Serializable {
     @Column(name = "remarks")
     private String remarks;
     @Column(name = "last_updated")
+    @Temporal(TemporalType.DATE)
     private Date lastUpdated;
     @JoinColumn(name = "observation_site_id", referencedColumnName = "observation_site_id", insertable = false, updatable = false)
     @ManyToOne(optional = false)
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 a7f13aad..cb32a49a 100755
--- a/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts.properties
+++ b/src/main/resources/no/nibio/vips/logic/i18n/vipslogictexts.properties
@@ -456,3 +456,4 @@ task_RunGridModelsTask_description=Run models that cover several locations
 currentDate=Current date
 days=Days
 older=Older
+lastUpdated=Last updated
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 dba53996..aa1bb34b 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
@@ -456,3 +456,4 @@ task_RunGridModelsTask_description=Test
 currentDate=Current date
 days=Days
 older=Older
+lastUpdated=Last updated
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 2a7c8e50..abd9465f 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
@@ -455,3 +455,4 @@ task_RunGridModelsTask_description=Test
 currentDate=Current date
 days=Days
 older=Older
+lastUpdated=Last updated
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 7cae4bcc..a74b126a 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
@@ -456,3 +456,4 @@ task_RunGridModelsTask_description=Kj\u00f8r modeller som spenner over flere lok
 currentDate=Gjeldende dato
 days=Dager
 older=Eldre
+lastUpdated=Sist oppdatert
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 704bfdc7..1565845e 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
@@ -456,3 +456,4 @@ task_RunGridModelsTask_description=Test
 currentDate=Current date
 days=Days
 older=Older
+lastUpdated=Last updated
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 f16f6fea..b275b893 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
@@ -453,3 +453,4 @@ task_RunGridModelsTask_description=Test
 currentDate=Current date
 days=Days
 older=Older
+lastUpdated=Last updated
diff --git a/src/main/webapp/formdefinitions/appleFruitMothStationForm.json b/src/main/webapp/formdefinitions/appleFruitMothStationForm.json
index 2954c06b..e5e22d46 100755
--- a/src/main/webapp/formdefinitions/appleFruitMothStationForm.json
+++ b/src/main/webapp/formdefinitions/appleFruitMothStationForm.json
@@ -1,6 +1,6 @@
 {
     "_licenseNote": [
-        "Copyright (c) 2014-2015 NIBIO <http://www.nibio.no/>. ",
+        "Copyright (c) 2014-2018 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 @@
         "You should have received a copy of the NIBIO Open Source License ",
         "along with VIPSLogic.  If not, see <http://www.nibio.no/licenses/>. "
     ],
-    "_comment" : "Structure of the weatherStationForm and how to validate it",
+    "_comment" : "Structure of the appleFruitMothStationForm and how to validate it",
     "fields": [
         {
             "name" : "observationSiteId",
diff --git a/src/main/webapp/js/appleFruitMothObservationSitesMap.js b/src/main/webapp/js/appleFruitMothObservationSitesMap.js
index ce67f149..dd2e3e5a 100755
--- a/src/main/webapp/js/appleFruitMothObservationSitesMap.js
+++ b/src/main/webapp/js/appleFruitMothObservationSitesMap.js
@@ -83,7 +83,7 @@ var initMap = function(container, mapAttribution)
 	          		trigger: 'manual',
 	          		html: true,
 	          		placement: "auto top",
-	          		title: "<a href='/applefruitmoth?action=viewObservationSite&observationSiteId=" + feature.getId() + "'>" + feature.get("name") + "</a>",
+	          		title: "<a href='/applefruitmoth?action=viewObservationSite&observationSiteId=" + feature.getId() + "'>" + feature.get("siteName") + "</a>",
 	          		content: generatePopupContents(feature.get("warningStatus"), feature.get("description"))
 	          	});
 	          	
diff --git a/src/main/webapp/templates/appleFruitMothClusterForm.ftl b/src/main/webapp/templates/appleFruitMothClusterForm.ftl
index a1042cc8..4e50de7f 100644
--- a/src/main/webapp/templates/appleFruitMothClusterForm.ftl
+++ b/src/main/webapp/templates/appleFruitMothClusterForm.ftl
@@ -24,12 +24,14 @@
    <#if messageKey?has_content>
             <div class="alert alert-success">${.now}: ${i18nBundle(messageKey)}</div>
     </#if>
+    <button type="button" class="btn btn-default" onclick="window.location='/applefruitmoth';"><i class="fa fa-arrow-left" aria-hidden="true"></i> Tilbake til stasjonsliste</button>
+    <#if user.isSuperUser() || user.isAppleFruitMothAdministrator() ><button class="btn btn-default" type="button" onclick="window.location='/applefruitmoth?action=viewObservationSite&observationSiteId=${observationSite.observationSiteId}';">Rediger ${observationSite.observationSiteName}</button></#if>
+                   
    <div class="singleBlockContainer">
 	
 	<div class="row">
             <form role="form" action="/applefruitmoth?action=clusterSubmit" method="POST" onsubmit="return validateForm(this)">
 		<div class="col-md-8">
-                    <button type="button" class="btn btn-default" onclick="window.location='/applefruitmoth';"><i class="fa fa-arrow-left" aria-hidden="true"></i> Tilbake</button>
                     <p>
                     Man trenger ikke registrere informasjon for alle trær (A-T) i 
                     lista. Et tre kan ha bare høsttallet registrert, men ikke bare vårtallet
diff --git a/src/main/webapp/templates/appleFruitMothStationForm.ftl b/src/main/webapp/templates/appleFruitMothStationForm.ftl
index 07e4436c..a8de8304 100755
--- a/src/main/webapp/templates/appleFruitMothStationForm.ftl
+++ b/src/main/webapp/templates/appleFruitMothStationForm.ftl
@@ -26,6 +26,7 @@
 	<script src="/js/resourcebundle.js"></script>
 	<script type="text/javascript" src="/js/3rdparty/ol.js"></script>
 	<script type="text/javascript" src="/js/constants.js"></script>
+        <script type="text/javascript" src="/js/validateForm.js"></script>
 	<script type="text/javascript" src="/js/appleFruitMothObservationSiteMap.js"></script>
 	<script type="text/javascript">
 		$(document).ready(function() {
@@ -35,16 +36,17 @@
 </#macro>
 <#macro page_contents>
 <h1>${observationSite.observationSiteName!i18nBundle.newObservationSite} ${currentSeason}</h1>
-<button type="button" class="btn btn-default" onclick="window.location='/applefruitmoth';"><i class="fa fa-arrow-left" aria-hidden="true"></i> ${i18nBundle.back}</button>
+<button type="button" class="btn btn-default" onclick="window.location='/applefruitmoth';"><i class="fa fa-arrow-left" aria-hidden="true"></i> Tilbake til stasjonsliste</button>
 <button type="button" class="btn btn-default" onclick="window.location='/applefruitmoth?action=registerCluster&observationSiteId=${observationSite.observationSiteId}&currentSeason=${currentSeason}';">Registrer klasetall</button>
 <div class="singleBlockContainer">
 	
 	<div class="row">
 		<div class="col-md-6">
-			<#assign formId = "observationSiteForm">
+			<#assign formId = "appleFruitMothStationForm">
 			<#if messageKey?has_content>
 				<div class="alert alert-success">${.now}: ${i18nBundle(messageKey)}</div>
 			</#if>
+                        <#if observationSiteSeasonCommonData??><div class="alert alert-info">${i18nBundle.lastUpdated}: ${observationSiteSeasonCommonData.lastUpdated}</div></#if>
 			<form id="${formId}" role="form" action="/applefruitmoth?action=observationSiteSubmit" method="POST">
 				<input type="hidden" name="observationSiteId" value="${observationSite.observationSiteId}"/>
 				<div class="form-group">
@@ -74,12 +76,12 @@
 				  </div>
 				<div class="form-group">
 				    <label for="degreeOfParasitation">${i18nBundle.degreeOfParasitation} (${i18nBundle.internal})</label>
-				    <input type="number" class="form-control" name="degreeOfParasitation" placeholder="${i18nBundle.degreeOfParasitation}" value="<#if observationSiteSeasonCommonData??>${observationSiteSeasonCommonData.degreeOfParasitation!""}</#if>" onblur="validateField(this);" />
+				    <input type="number" step="any" class="form-control" name="degreeOfParasitation" placeholder="${i18nBundle.degreeOfParasitation}" value="<#if observationSiteSeasonCommonData??>${observationSiteSeasonCommonData.degreeOfParasitation?c!""}</#if>" onblur="validateField(this);" />
 				    <span class="help-block" id="${formId}_degreeOfParasitation_validation"></span>
 				</div>
 				<div class="form-group">
 				    <label for="thousandBerrySample">${i18nBundle.thousandBerrySample} (${i18nBundle.internal})</label>
-				    <input type="number" class="form-control" name="thousandBerrySample" placeholder="${i18nBundle.thousandBerrySample}" value="<#if observationSiteSeasonCommonData??>${observationSiteSeasonCommonData.thousandBerrySample!""}</#if>" onblur="validateField(this);" />
+				    <input type="number" step="any" class="form-control" name="thousandBerrySample" placeholder="${i18nBundle.thousandBerrySample}" value="<#if observationSiteSeasonCommonData??>${observationSiteSeasonCommonData.thousandBerrySample?c!""}</#if>" onblur="validateField(this);" />
 				    <span class="help-block" id="${formId}_thousandBerrySample_validation"></span>
 				</div>
                                 <div class="form-group">
@@ -102,10 +104,10 @@
                             <tr><td>Antall trær med økning i klasetall over vinteren</td><td>${treesWithIncreasingValues}</td></tr>
                             <tr><td>Antall trær med nedgang i klasetall over vinteren</td><td>${treesWithDecreasingValues}</td></tr>
                             <tr><td>Antall trær med uendret klasetall over vinteren</td><td>${treesWithUnchangedValues}</td></tr>
-                            <tr><td>Angrepstall</td><td>${attackNumber!"[Data mangler]"}%</td></tr>
+                            <tr><td>Angrepstall</td><td><#if attackNumber??>${attackNumber?c}<#else>[Data mangler]</#if></td></tr>
                             <tr><td>Nødvendig antall klaser ${currentSeason}</td><td>${neededClusters!"[Data mangler]"}</td></tr>
-                            <tr><td>Prognosetall ${currentSeason}</td><td>${forecastNumber!"[Data mangler]"}</td></tr>
-                            <tr><td>Klasebrøk</td><td>${clusterFraction!"[Data mangler]"}</td></tr>
+                            <tr><td>Prognosetall ${currentSeason}</td><td><#if forecastNumber??>${forecastNumber}<#else>[Data mangler]</#if></td></tr>
+                            <tr><td>Klasebrøk</td><td><#if clusterFraction??>${clusterFraction?c}<#else>[Data mangler]</#if></td></tr>
                             
                         </tbody>
                         </table>
diff --git a/src/main/webapp/templates/appleFruitMothStationList.ftl b/src/main/webapp/templates/appleFruitMothStationList.ftl
index d725953b..e86ade49 100755
--- a/src/main/webapp/templates/appleFruitMothStationList.ftl
+++ b/src/main/webapp/templates/appleFruitMothStationList.ftl
@@ -39,11 +39,16 @@
 	<div class="row">
 		<div class="col-md-6">
 			<table class="table table-striped">
+                            <tr>
+                                <td colspan="3"></td>
+                                <th>Klasetall sist oppdatert</th>
+                            </tr>
                             <#list observationSites as observationSite>
                             <tr>
                                 <td>${observationSite.observationSiteName}</td>
                                 <td><#if user.isSuperUser() || user.isAppleFruitMothAdministrator() ><button class="btn btn-default" onclick="window.location='/applefruitmoth?action=viewObservationSite&observationSiteId=${observationSite.observationSiteId}';">Rediger</button></#if></td>
                                 <td><button class="btn btn-default" onclick="window.location='/applefruitmoth?action=registerCluster&observationSiteId=${observationSite.observationSiteId}';">Registrer klasetall</button></td>
+                                <td>${observationSite.lastUpdatedClusterCount!"Ukjent"}</td>
                             </tr>
                             </#list>
 			</table>
-- 
GitLab