diff --git a/src/main/java/no/bioforsk/vips/logic/controller/servlet/ForecastConfigurationController.java b/src/main/java/no/bioforsk/vips/logic/controller/servlet/ForecastConfigurationController.java
new file mode 100644
index 0000000000000000000000000000000000000000..4e31f707c26a506580fbb47aaf7bf0f427d8c3f5
--- /dev/null
+++ b/src/main/java/no/bioforsk/vips/logic/controller/servlet/ForecastConfigurationController.java
@@ -0,0 +1,240 @@
+package no.bioforsk.vips.logic.controller.servlet;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import no.bioforsk.vips.logic.controller.session.ForecastBean;
+import no.bioforsk.vips.logic.controller.session.UserBean;
+import no.bioforsk.vips.logic.entity.PointOfInterest;
+import no.bioforsk.vips.logic.entity.PointOfInterestWeatherStation;
+import no.bioforsk.vips.logic.entity.VipsLogicRole;
+import no.bioforsk.vips.logic.entity.VipsLogicUser;
+import no.bioforsk.vips.logic.scheduling.model.ForecastConfiguration;
+import no.bioforsk.vips.logic.util.SessionControllerGetter;
+import no.bioforsk.vips.util.ServletUtil;
+import no.bioforsk.web.forms.FormField;
+import no.bioforsk.web.forms.FormValidation;
+import no.bioforsk.web.forms.FormValidator;
+
+/**
+ * Handles form configuration actions
+ * @copyright 2013 <a href="http://www.bioforsk.no/">Bioforsk</a>
+ * @author Tor-Einar Skog <tor-einar.skog@bioforsk.no>
+ */
+public class ForecastConfigurationController extends HttpServlet {
+    
+    @PersistenceContext(unitName="VIPSLogic-PU")
+    EntityManager em;
+
+    /**
+     * Processes requests for both HTTP <code>GET</code> and <code>POST</code>
+     * methods.
+     *
+     * @param request servlet request
+     * @param response servlet response
+     * @throws ServletException if a servlet-specific error occurs
+     * @throws IOException if an I/O error occurs
+     */
+    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
+            throws ServletException, IOException {
+        response.setContentType("text/html;charset=UTF-8");
+        
+        String action = request.getParameter("action");
+        VipsLogicUser user = (VipsLogicUser) request.getSession().getAttribute("user");
+        ForecastBean forecastBean = SessionControllerGetter.getForecastBean();
+        UserBean userBean = SessionControllerGetter.getUserBean();
+        
+        // Default: View list of users
+        // for SUPERUSERS and ORGANIZATION ADMINS
+        if(action == null)
+        {
+            if(userBean.authorizeUser(user, VipsLogicRole.ORGANIZATION_ADMINISTRATOR, VipsLogicRole.SUPERUSER))
+            {
+                List<ForecastConfiguration> forecasts;
+                if(user.isSuperUser())
+                {
+                    forecasts = forecastBean.getForecastConfigurations();
+                }
+                else
+                {
+                    forecasts = forecastBean.getForecastConfigurations(user.getOrganizationId());
+                }
+                request.setAttribute("forecastConfigurations", forecasts);
+                request.setAttribute("modelInformation", forecastBean.getIndexedModelInformation());
+                // If this is a redirect from a controller, with a message to be passed on
+                request.setAttribute("messageKey", request.getParameter("messageKey"));
+                request.getRequestDispatcher("/forecastConfigurationList.ftl").forward(request, response);
+            }
+            else
+            {
+                response.sendError(403,"Access not authorized"); // HTTP Forbidden
+            }
+      
+        }
+        
+        // View and edit a forecast configuration
+        // for SUPERUSERS and ORGANIZATION ADMINS
+        else if(action.equals("viewForecastConfiguration"))
+        {
+            if(userBean.authorizeUser(user, VipsLogicRole.ORGANIZATION_ADMINISTRATOR, VipsLogicRole.SUPERUSER))
+            {
+                try
+                {
+                    Long forecastConfigurationId = Long.valueOf(request.getParameter("forecastConfigurationId"));
+                    ForecastConfiguration forecastConfiguration = em.find(ForecastConfiguration.class, forecastConfigurationId);
+                    // No forecastconfiguration found, assuming user want to register new
+                    if(forecastConfiguration == null)
+                    {
+                        forecastConfiguration = new ForecastConfiguration();
+                    }
+                    // Only superusers can view and edit forecasts from other organizations
+                    if(! user.isSuperUser() && forecastConfiguration.getVipsLogicUserId() != null && !forecastConfiguration.getVipsLogicUserId().getOrganizationId().equals(user.getOrganizationId()))
+                    {
+                        response.sendError(403,"Access not authorized"); // HTTP Forbidden
+                    }
+                    else
+                    {
+                        // We must get date formats!
+                        Map<String, FormField> formFields = FormValidator.getFormFields("forecastConfigurationForm",getServletContext());
+                        // TODO: More intelligent selection of locations, weather stations and users
+                        request.setAttribute("locationPointOfInterests", em.createNamedQuery("PointOfInterest.findAll").getResultList());
+                        request.setAttribute("weatherStationPointOfInterests", em.createNamedQuery("PointOfInterestWeatherStation.findAll").getResultList());
+                        request.setAttribute("vipsLogicUsers", em.createNamedQuery("VipsLogicUser.findAll").getResultList());
+                        request.setAttribute("dateStart_dateFormat", formFields.get("dateStart").getDateFormat());
+                        request.setAttribute("dateEnd_dateFormat", formFields.get("dateEnd").getDateFormat());
+                        request.setAttribute("forecastConfiguration", forecastConfiguration);
+                        request.setAttribute("modelInformations", em.createNamedQuery("ModelInformation.findAll").getResultList());
+                        request.setAttribute("messageKey", request.getParameter("messageKey"));
+                        request.getRequestDispatcher("/forecastConfigurationForm.ftl").forward(request, response);
+                       
+                    }
+                }
+                catch(NullPointerException | NumberFormatException ex)
+                {
+                    response.sendError(500, "Invalid forecast configurationId " + request.getParameter("forecastConfigurationId"));
+                }
+                
+            }
+            else
+            {
+                response.sendError(403,"Access not authorized"); // HTTP Forbidden
+            }
+        }
+        
+        // Store forecast configuration
+        // Authorization: SUPERUSERS and ORGANIZATION ADMINS
+        else if(action.equals("forecastConfigurationFormSubmit"))
+        {
+            if(userBean.authorizeUser(user, VipsLogicRole.ORGANIZATION_ADMINISTRATOR, VipsLogicRole.SUPERUSER))
+            {
+                try
+                {
+                    Long forecastConfigurationId = Long.valueOf(request.getParameter("forecastConfigurationId"));
+                    ForecastConfiguration forecastConfiguration = em.find(ForecastConfiguration.class, forecastConfigurationId);
+                    // No forecastconfiguration found, assuming user want to register new
+                    if(forecastConfiguration == null)
+                    {
+                        forecastConfiguration = new ForecastConfiguration();
+                    }
+                    // Only superusers can view and edit forecasts from other organizations
+                    if(! user.isSuperUser() && forecastConfiguration.getVipsLogicUserId() != null && !forecastConfiguration.getVipsLogicUserId().getOrganizationId().equals(user.getOrganizationId()))
+                    {
+                        response.sendError(403,"Access not authorized"); // HTTP Forbidden
+                    }
+                    else
+                    {
+                        // Standard form validation
+                        FormValidation formValidation = FormValidator.validateForm("forecastConfigurationForm",request,getServletContext());
+                        if(formValidation.isValid())
+                        {
+                            // Store form config
+                            forecastConfiguration.setModelId(formValidation.getFormField("modelId").getWebValue());
+                            PointOfInterest locationPoi = em.find(PointOfInterest.class, formValidation.getFormField("locationPointOfInterestId").getValueAsInteger());
+                            forecastConfiguration.setLocationPointOfInterestId(locationPoi);
+                            PointOfInterest weatherStationPoi = em.find(PointOfInterestWeatherStation.class, formValidation.getFormField("weatherStationPointOfInterestId").getValueAsInteger());
+                            forecastConfiguration.setWeatherStationPointOfInterestId(weatherStationPoi);
+                            forecastConfiguration.setDateStart(formValidation.getFormField("dateStart").getValueAsDate());
+                            forecastConfiguration.setDateEnd(formValidation.getFormField("dateEnd").getValueAsDate());
+                            VipsLogicUser forecastConfigurationUser = em.find(VipsLogicUser.class, formValidation.getFormField("vipsLogicUserId").getValueAsInteger());
+                            forecastConfiguration.setVipsCoreUserId(forecastConfigurationUser);
+                            forecastBean.storeForecastConfiguration(forecastConfiguration);
+                            
+                            request.setAttribute("messageKey", request.getParameter("formConfigurationUpdated"));
+                            response.sendRedirect(new StringBuilder("http://").append(ServletUtil.getServerName(request)).append("/forecastConfiguration?action=viewForecastConfiguration&forecastConfigurationId=").append(forecastConfiguration.getForecastConfigurationId()).append("&messageKey=").append("forecastConfigurationUpdated").toString());
+                        }
+                        else
+                        {
+                            // Return to form with error messages
+                            request.setAttribute("formValidation", formValidation);
+                            // We must get date formats!
+                            Map<String, FormField> formFields = FormValidator.getFormFields("forecastConfigurationForm",getServletContext());
+                            // TODO: More intelligent selection of locations, weather stations and users
+                            request.setAttribute("locationPointOfInterests", em.createNamedQuery("PointOfInterest.findAll").getResultList());
+                            request.setAttribute("weatherStationPointOfInterests", em.createNamedQuery("PointOfInterestWeatherStation.findAll").getResultList());
+                            request.setAttribute("vipsLogicUsers", em.createNamedQuery("VipsLogicUser.findAll").getResultList());
+                            request.setAttribute("dateStart_dateFormat", formFields.get("dateStart").getDateFormat());
+                            request.setAttribute("dateEnd_dateFormat", formFields.get("dateEnd").getDateFormat());
+                            request.setAttribute("modelInformations", em.createNamedQuery("ModelInformation.findAll").getResultList());
+                            request.setAttribute("forecastConfiguration", forecastConfiguration);
+                            request.getRequestDispatcher("/forecastConfigurationForm.ftl").forward(request, response);
+                        }
+                    }
+                }
+                catch(NullPointerException | NumberFormatException ex)
+                {
+                    response.sendError(500, "Invalid forecast configurationId " + request.getParameter("forecastConfigurationId"));
+                }
+            }
+            else
+            {
+                response.sendError(403,"Access not authorized"); // HTTP Forbidden
+            }
+        }
+    }
+
+    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
+    /**
+     * Handles the HTTP <code>GET</code> method.
+     *
+     * @param request servlet request
+     * @param response servlet response
+     * @throws ServletException if a servlet-specific error occurs
+     * @throws IOException if an I/O error occurs
+     */
+    @Override
+    protected void doGet(HttpServletRequest request, HttpServletResponse response)
+            throws ServletException, IOException {
+        processRequest(request, response);
+    }
+
+    /**
+     * Handles the HTTP <code>POST</code> method.
+     *
+     * @param request servlet request
+     * @param response servlet response
+     * @throws ServletException if a servlet-specific error occurs
+     * @throws IOException if an I/O error occurs
+     */
+    @Override
+    protected void doPost(HttpServletRequest request, HttpServletResponse response)
+            throws ServletException, IOException {
+        processRequest(request, response);
+    }
+
+    /**
+     * Returns a short description of the servlet.
+     *
+     * @return a String containing servlet description
+     */
+    @Override
+    public String getServletInfo() {
+        return "Short description";
+    }// </editor-fold>
+
+}
diff --git a/src/main/java/no/bioforsk/vips/logic/controller/servlet/UserControllerServlet.java b/src/main/java/no/bioforsk/vips/logic/controller/servlet/UserController.java
similarity index 99%
rename from src/main/java/no/bioforsk/vips/logic/controller/servlet/UserControllerServlet.java
rename to src/main/java/no/bioforsk/vips/logic/controller/servlet/UserController.java
index 71240593b0af1c0c2b1f88aef4f774d1ca154e45..1041bfbfc431e58b2efa3c59c1e5c9bbeab103b0 100644
--- a/src/main/java/no/bioforsk/vips/logic/controller/servlet/UserControllerServlet.java
+++ b/src/main/java/no/bioforsk/vips/logic/controller/servlet/UserController.java
@@ -29,7 +29,7 @@ import no.bioforsk.web.forms.FormValidator;
  * @copyright 2013 <a href="http://www.bioforsk.no/">Bioforsk</a>
  * @author Tor-Einar Skog <tor-einar.skog@bioforsk.no>
  */
-public class UserControllerServlet extends HttpServlet {
+public class UserController extends HttpServlet {
 
     @PersistenceContext(unitName="VIPSLogic-PU")
     EntityManager em;
diff --git a/src/main/java/no/bioforsk/vips/logic/controller/session/ForecastBean.java b/src/main/java/no/bioforsk/vips/logic/controller/session/ForecastBean.java
index fc7bef3b3919b49ecfeaaa5a26f456f3713a8d75..0aa541fbb07827cb6274860e000cd04aea61e3fb 100644
--- a/src/main/java/no/bioforsk/vips/logic/controller/session/ForecastBean.java
+++ b/src/main/java/no/bioforsk/vips/logic/controller/session/ForecastBean.java
@@ -1,12 +1,25 @@
 package no.bioforsk.vips.logic.controller.session;
 
+import java.util.Date;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import javax.ejb.Stateless;
 import javax.persistence.EntityManager;
 import javax.persistence.PersistenceContext;
 import javax.persistence.Query;
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Response;
+import no.bioforsk.vips.coremanager.service.ManagerResource;
 import no.bioforsk.vips.logic.entity.ForecastResult;
+import no.bioforsk.vips.logic.entity.ModelInformation;
+import no.bioforsk.vips.logic.entity.Organization;
+import no.bioforsk.vips.logic.entity.VipsLogicUser;
 import no.bioforsk.vips.logic.scheduling.model.ForecastConfiguration;
+import org.codehaus.jackson.JsonNode;
+import org.jboss.resteasy.client.jaxrs.ResteasyWebTarget;
 
 /**
  * @copyright 2013 <a href="http://www.bioforsk.no/">Bioforsk</a>
@@ -51,6 +64,24 @@ public class ForecastBean {
         return q.getResultList();
     }
     
+    /**
+     * Returns _ALL_ forecasts. Not for the faint hearted
+     * @return 
+     */
+    public List<ForecastConfiguration> getForecastConfigurations()
+    {
+        return em.createNamedQuery("ForecastConfiguration.findAll").getResultList();
+    }
+    
+    public List<ForecastConfiguration> getForecastConfigurations(Organization organization)
+    {
+        List<VipsLogicUser> organizationUsers = em
+                                                .createNamedQuery("VipsLogicUser.findByOrganizationId")
+                                                .setParameter("organizationId", organization)
+                                                .getResultList();
+        return em.createNamedQuery("ForecastConfiguration.findByVipsLogicUserIds").setParameter("vipsLogicUserIds", organizationUsers).getResultList();
+    }
+    
     /**
      * Fetches one specific forecast configuration
      * @param forecastConfigurationId
@@ -60,4 +91,70 @@ public class ForecastBean {
     {
         return em.find(ForecastConfiguration.class, forecastConfigurationId);
     }
+    
+    /**
+     * Requests all info about models currently available in VIPSCoreManager
+     * Stores in local db for easy access. 
+     */
+    public void updateModelInformation()
+    {
+            // Get all model Ids from Core Manager
+            Response resp = this.getManagerResource().printModelListJSON();
+            for(JsonNode modelIdItem: resp.readEntity(JsonNode.class).findValues("modelId"))
+            {
+                String modelId = modelIdItem.getValueAsText();
+                
+                // We get the corresponding modelInformation entry 
+                ModelInformation modelInformation = em.find(ModelInformation.class, modelId);
+                if(modelInformation == null)
+                {
+                    modelInformation = new ModelInformation(modelId);
+                    em.persist(modelInformation);
+                    modelInformation.setDateFirstRegistered(new Date());
+                }
+                
+                // Retrieve and store information
+                modelInformation.setDefaultName(this.getManagerResource().printModelName(modelId).readEntity(String.class));
+                modelInformation.setDefaultDescription(this.getManagerResource().printModelDescription(modelId).readEntity(String.class));
+                modelInformation.setLicense(this.getManagerResource().printModelLicense(modelId).readEntity(String.class));
+                modelInformation.setCopyrightHolder(this.getManagerResource().printModelCopyright(modelId).readEntity(String.class));
+                modelInformation.setUsage(this.getManagerResource().printModelUsage(modelId).readEntity(String.class));
+                modelInformation.setSampleConfig(this.getManagerResource().printModelSampleConfig(modelId).readEntity(String.class));
+                modelInformation.setDateLastRegistered(new Date());
+            }
+            
+    }
+    
+    /**
+     * 
+     * @return All registered models accessible by ModelId as key
+     */
+    public Map<String,ModelInformation> getIndexedModelInformation()
+    {
+        Map<String, ModelInformation> retVal = new HashMap<>();
+        for(ModelInformation mi: (List<ModelInformation>) em.createNamedQuery("ModelInformation.findAll").getResultList())
+        {
+            retVal.put(mi.getModelId(), mi);
+        }
+        return retVal;
+    }
+    
+    public void storeForecastConfiguration(ForecastConfiguration forecastConfiguration)
+    {
+        em.merge(forecastConfiguration);
+    }
+    
+    
+    /**
+     * Get the interface for REST resources in VIPSCoreManager
+     * @return 
+     */
+    private ManagerResource getManagerResource()
+    {
+        Client client = ClientBuilder.newClient();
+        WebTarget target = client.target(System.getProperty("no.bioforsk.vips.coremanager.VIPSCOREMANAGER_URL"));
+        ResteasyWebTarget rTarget = (ResteasyWebTarget) target;
+        ManagerResource resource = rTarget.proxy(ManagerResource.class);
+        return resource;
+    }
 }
diff --git a/src/main/java/no/bioforsk/vips/logic/controller/session/UserBean.java b/src/main/java/no/bioforsk/vips/logic/controller/session/UserBean.java
index b3d97e2ba91c1895c1f303c5d3c3c93634e4bf5c..1c9c2d7fe2443a559becb7849a5de475f9f56653 100644
--- a/src/main/java/no/bioforsk/vips/logic/controller/session/UserBean.java
+++ b/src/main/java/no/bioforsk/vips/logic/controller/session/UserBean.java
@@ -123,15 +123,6 @@ public class UserBean {
     public void deleteUser(VipsLogicUser user)
     {
         user = em.find(VipsLogicUser.class, user.getUserId());
-        
-        // Remove dependent stuff
-        /* User authentication for this user
-        for(UserAuthentication auth: user.getUserAuthenticationSet())
-        {
-            System.out.println("Auth[DEBUG]=" + auth.getUsername());
-            em.remove(auth);
-        }
-        */
         em.remove(user);
     }
     
diff --git a/src/main/java/no/bioforsk/vips/logic/entity/ModelInformation.java b/src/main/java/no/bioforsk/vips/logic/entity/ModelInformation.java
new file mode 100644
index 0000000000000000000000000000000000000000..4ed6fd0c8321b08d4c9fc18c65827c38ce01004b
--- /dev/null
+++ b/src/main/java/no/bioforsk/vips/logic/entity/ModelInformation.java
@@ -0,0 +1,173 @@
+package no.bioforsk.vips.logic.entity;
+
+import java.io.Serializable;
+import java.util.Date;
+import javax.persistence.Basic;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.Table;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * @copyright 2013 <a href="http://www.bioforsk.no/">Bioforsk</a>
+ * @author Tor-Einar Skog <tor-einar.skog@bioforsk.no>
+ */
+@Entity
+@Table(name = "model_information")
+@XmlRootElement
+@NamedQueries({
+    @NamedQuery(name = "ModelInformation.findAll", query = "SELECT m FROM ModelInformation m"),
+    @NamedQuery(name = "ModelInformation.findByModelId", query = "SELECT m FROM ModelInformation m WHERE m.modelId = :modelId"),
+    @NamedQuery(name = "ModelInformation.findByDateFirstRegistered", query = "SELECT m FROM ModelInformation m WHERE m.dateFirstRegistered = :dateFirstRegistered"),
+    @NamedQuery(name = "ModelInformation.findByDateLastRegistered", query = "SELECT m FROM ModelInformation m WHERE m.dateLastRegistered = :dateLastRegistered"),
+    @NamedQuery(name = "ModelInformation.findByDefaultName", query = "SELECT m FROM ModelInformation m WHERE m.defaultName = :defaultName"),
+    @NamedQuery(name = "ModelInformation.findByCopyrightHolder", query = "SELECT m FROM ModelInformation m WHERE m.copyrightHolder = :copyrightHolder"),
+    @NamedQuery(name = "ModelInformation.findByLicense", query = "SELECT m FROM ModelInformation m WHERE m.license = :license"),
+    @NamedQuery(name = "ModelInformation.findByDefaultDescription", query = "SELECT m FROM ModelInformation m WHERE m.defaultDescription = :defaultDescription"),
+    @NamedQuery(name = "ModelInformation.findBySampleConfig", query = "SELECT m FROM ModelInformation m WHERE m.sampleConfig = :sampleConfig"),
+    @NamedQuery(name = "ModelInformation.findByUsage", query = "SELECT m FROM ModelInformation m WHERE m.usage = :usage")})
+public class ModelInformation implements Serializable {
+    private static final long serialVersionUID = 1L;
+    @Id
+    @Basic(optional = false)
+    @NotNull
+    @Size(min = 1, max = 10)
+    @Column(name = "model_id")
+    private String modelId;
+    @Column(name = "date_first_registered")
+    @Temporal(TemporalType.DATE)
+    private Date dateFirstRegistered;
+    @Column(name = "date_last_registered")
+    @Temporal(TemporalType.DATE)
+    private Date dateLastRegistered;
+    @Size(max = 63)
+    @Column(name = "default_name")
+    private String defaultName;
+    @Size(max = 255)
+    @Column(name = "copyright_holder")
+    private String copyrightHolder;
+    @Size(max = 2147483647)
+    @Column(name = "license")
+    private String license;
+    @Size(max = 2147483647)
+    @Column(name = "default_description")
+    private String defaultDescription;
+    @Size(max = 2147483647)
+    @Column(name = "sample_config")
+    private String sampleConfig;
+    @Size(max = 2147483647)
+    @Column(name = "usage")
+    private String usage;
+
+    public ModelInformation() {
+    }
+
+    public ModelInformation(String modelId) {
+        this.modelId = modelId;
+    }
+
+    public String getModelId() {
+        return modelId;
+    }
+
+    public void setModelId(String modelId) {
+        this.modelId = modelId;
+    }
+
+    public Date getDateFirstRegistered() {
+        return dateFirstRegistered;
+    }
+
+    public void setDateFirstRegistered(Date dateFirstRegistered) {
+        this.dateFirstRegistered = dateFirstRegistered;
+    }
+
+    public Date getDateLastRegistered() {
+        return dateLastRegistered;
+    }
+
+    public void setDateLastRegistered(Date dateLastRegistered) {
+        this.dateLastRegistered = dateLastRegistered;
+    }
+
+    public String getDefaultName() {
+        return defaultName;
+    }
+
+    public void setDefaultName(String defaultName) {
+        this.defaultName = defaultName;
+    }
+
+    public String getCopyrightHolder() {
+        return copyrightHolder;
+    }
+
+    public void setCopyrightHolder(String copyrightHolder) {
+        this.copyrightHolder = copyrightHolder;
+    }
+
+    public String getLicense() {
+        return license;
+    }
+
+    public void setLicense(String license) {
+        this.license = license;
+    }
+
+    public String getDefaultDescription() {
+        return defaultDescription;
+    }
+
+    public void setDefaultDescription(String defaultDescription) {
+        this.defaultDescription = defaultDescription;
+    }
+
+    public String getSampleConfig() {
+        return sampleConfig;
+    }
+
+    public void setSampleConfig(String sampleConfig) {
+        this.sampleConfig = sampleConfig;
+    }
+
+    public String getUsage() {
+        return usage;
+    }
+
+    public void setUsage(String usage) {
+        this.usage = usage;
+    }
+
+    @Override
+    public int hashCode() {
+        int hash = 0;
+        hash += (modelId != null ? modelId.hashCode() : 0);
+        return hash;
+    }
+
+    @Override
+    public boolean equals(Object object) {
+        // TODO: Warning - this method won't work in the case the id fields are not set
+        if (!(object instanceof ModelInformation)) {
+            return false;
+        }
+        ModelInformation other = (ModelInformation) object;
+        if ((this.modelId == null && other.modelId != null) || (this.modelId != null && !this.modelId.equals(other.modelId))) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return "no.bioforsk.vips.logic.entity.ModelInformation[ modelId=" + modelId + " ]";
+    }
+
+}
diff --git a/src/main/java/no/bioforsk/vips/logic/scheduling/model/ForecastConfiguration.java b/src/main/java/no/bioforsk/vips/logic/scheduling/model/ForecastConfiguration.java
index 26e612e81d9f8b9776d6cbdd7ae39565b11f59ee..fdb5ab3307dda9100ec8543a72da8f829c850d4a 100644
--- a/src/main/java/no/bioforsk/vips/logic/scheduling/model/ForecastConfiguration.java
+++ b/src/main/java/no/bioforsk/vips/logic/scheduling/model/ForecastConfiguration.java
@@ -22,6 +22,7 @@ import javax.validation.constraints.Size;
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.XmlTransient;
 import no.bioforsk.vips.logic.entity.PointOfInterest;
+import no.bioforsk.vips.logic.entity.VipsLogicUser;
 import org.codehaus.jackson.annotate.JsonIgnore;
 
 /**
@@ -37,7 +38,9 @@ import org.codehaus.jackson.annotate.JsonIgnore;
     @NamedQuery(name = "ForecastConfiguration.findByModelId", query = "SELECT f FROM ForecastConfiguration f WHERE f.modelId = :modelId"),
     @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.findByVipsCoreUserId", query = "SELECT f FROM ForecastConfiguration f WHERE f.vipsCoreUserId = :vipsCoreUserId")})
+    @NamedQuery(name = "ForecastConfiguration.findByVipsLogicUserId", query = "SELECT f FROM ForecastConfiguration f WHERE f.vipsLogicUserId = :vipsLogicUserId"),
+    @NamedQuery(name = "ForecastConfiguration.findByVipsLogicUserIds", query = "SELECT f FROM ForecastConfiguration f WHERE f.vipsLogicUserId IN (:vipsLogicUserIds)")
+})
 public class ForecastConfiguration implements Serializable {
     @OneToMany(cascade = CascadeType.ALL, mappedBy = "forecastConfiguration")
     private Set<ForecastModelConfiguration> forecastModelConfigurationSet;
@@ -56,8 +59,9 @@ public class ForecastConfiguration implements Serializable {
     @Column(name = "date_end")
     @Temporal(TemporalType.DATE)
     private Date dateEnd;
-    @Column(name = "vips_core_user_id")
-    private Integer vipsCoreUserId;
+    @JoinColumn(name = "vips_logic_user_id", referencedColumnName = "user_id")
+    @ManyToOne(optional = false)
+    private VipsLogicUser vipsLogicUserId;
     @JoinColumn(name = "location_point_of_interest_id", referencedColumnName = "point_of_interest_id")
     @ManyToOne
     private PointOfInterest locationPointOfInterestId;
@@ -104,12 +108,12 @@ public class ForecastConfiguration implements Serializable {
         this.dateEnd = dateEnd;
     }
 
-    public Integer getVipsCoreUserId() {
-        return vipsCoreUserId;
+    public VipsLogicUser getVipsLogicUserId() {
+        return vipsLogicUserId;
     }
 
-    public void setVipsCoreUserId(Integer vipsCoreUserId) {
-        this.vipsCoreUserId = vipsCoreUserId;
+    public void setVipsCoreUserId(VipsLogicUser vipsLogicUserId) {
+        this.vipsLogicUserId = vipsLogicUserId;
     }
 
     public PointOfInterest getLocationPointOfInterestId() {
diff --git a/src/main/java/no/bioforsk/web/forms/FormField.java b/src/main/java/no/bioforsk/web/forms/FormField.java
index a6106482f80a957f0a8de8b528d855d711d5d54a..8a09c075974276343abcc139066dde3893e7f18d 100644
--- a/src/main/java/no/bioforsk/web/forms/FormField.java
+++ b/src/main/java/no/bioforsk/web/forms/FormField.java
@@ -1,5 +1,8 @@
 package no.bioforsk.web.forms;
 
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
 import org.codehaus.jackson.annotate.JsonIgnore;
 
 /**
@@ -17,12 +20,14 @@ public class FormField {
     public static String FORM_FIELD_TYPE_STRING = "STRING";
     public static String FORM_FIELD_TYPE_INTEGER = "INTEGER";
     public static String FORM_FIELD_TYPE_DOUBLE = "DOUBLE";
+    public static String FORM_FIELD_TYPE_DATE = "DATE";
     public static String FORM_FIELD_TYPE_PASSWORD = "PASSWORD";
     public static String FORM_FIELD_TYPE_EMAIL = "EMAIL";
     public static String FORM_FIELD_TYPE_SELECT_SINGLE = "SELECT_SINGLE";
     public static String FORM_FIELD_TYPE_SELECT_MULTIPLE = "SELECT_MULTIPLE";
 
-    
+    // Standard format for dates is the ISO-8861-format
+    public static String DATE_DEFAULT_FORMAT = "yyyy-MM-dd";
     
     private String name;
     private String label;
@@ -36,6 +41,7 @@ public class FormField {
     private Integer minValue;
     private Integer maxValue;
     private String nullValue;
+    private String dateFormat;
     
     
     public Integer getValueAsInteger()
@@ -53,6 +59,17 @@ public class FormField {
         return Double.valueOf(this.webValue[0]);
     }
     
+    public Date getValueAsDate()
+    {
+        try
+        {
+            return new SimpleDateFormat(this.getDateFormat()).parse(this.getWebValue());
+        }
+        catch(ParseException ex)
+        {
+            return null;
+        }
+    }
     
     
     /**
@@ -253,5 +270,26 @@ public class FormField {
         this.nullValue = nullValue;
     }
 
+    /**
+     * @return the dateFormat (if not set, it returns FormField.DATE_DEFAULT_FORMAT
+     */
+    public String getDateFormat() {
+        if(this.dateFormat != null)
+        {
+            return dateFormat;
+        }
+        else
+        {
+            return DATE_DEFAULT_FORMAT;
+        }
+    }
+
+    /**
+     * @param dateFormat the dateFormat to set
+     */
+    public void setDateFormat(String dateFormat) {
+        this.dateFormat = dateFormat;
+    }
+
     
 }
diff --git a/src/main/java/no/bioforsk/web/forms/FormValidator.java b/src/main/java/no/bioforsk/web/forms/FormValidator.java
index 8fe7e1c7574079e921b474e00ed199a18cd29c24..278430f08322e2f07a60e50670588eb3267884dc 100644
--- a/src/main/java/no/bioforsk/web/forms/FormValidator.java
+++ b/src/main/java/no/bioforsk/web/forms/FormValidator.java
@@ -3,8 +3,13 @@ package no.bioforsk.web.forms;
 import java.io.IOException;
 import java.io.InputStream;
 import java.text.MessageFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
+import java.util.Map;
 import javax.servlet.ServletContext;
 import javax.servlet.http.HttpServletRequest;
 import no.bioforsk.vips.logic.authenticate.PasswordValidationException;
@@ -27,15 +32,14 @@ import org.codehaus.jackson.type.TypeReference;
  * @author Tor-Einar Skog <tor-einar.skog@bioforsk.no>
  */
 public class FormValidator {
+    
+    public static String RELATION_TYPE_EQUALS = "EQUALS";
+    public static String RELATION_TYPE_AFTER = "AFTER";
 
     public static FormValidation validateForm(String formName, HttpServletRequest request, ServletContext servletContext) throws IOException {
-        ObjectMapper mapper = new ObjectMapper();
-        JsonFactory factory = mapper.getJsonFactory();
-        InputStream in = servletContext.getResourceAsStream("/formdefinitions/" + formName + ".json");
-
-        JsonParser parser = factory.createJsonParser(in);
-        JsonNode formDefinition = mapper.readTree(parser);
-        List<FormField> fields = mapper.convertValue(formDefinition.findValue("fields"), new TypeReference<List<FormField>>(){});
+       
+        JsonNode formDefinition = getFormDefinition(formName, servletContext);
+        List<FormField> fields =  new ObjectMapper().convertValue(formDefinition.findValue("fields"), new TypeReference<List<FormField>>(){});
         FormValidation retVal = new FormValidation();
         
         for(FormField field: fields)
@@ -63,6 +67,23 @@ public class FormValidator {
                 }
             }
             
+            // Dates
+            // We try to conver to date using the given format
+            if(field.getType().equals(FormField.FORM_FIELD_TYPE_DATE))
+            {
+                SimpleDateFormat format = new SimpleDateFormat(field.getDateFormat());
+                try
+                {
+                    Date date = format.parse(field.getWebValue());
+                }
+                catch(ParseException ex)
+                {
+                    field.setValid(false);
+                    field.setValidationMessage(MessageFormat.format(SessionLocaleUtil.getI18nText(request, "doesNotMatchDateFormat"), field.getDateFormat()));
+                }
+                
+            }
+            
             if(field.getType().equals(FormField.FORM_FIELD_TYPE_PASSWORD))
             {
                 try
@@ -147,34 +168,93 @@ public class FormValidator {
         }
         
         // Check repeats
-        JsonNode repeatFields = formDefinition.findValue("repeatFields");
-        if(repeatFields != null)
+        JsonNode relations = formDefinition.findValue("relations");
+        if(relations != null)
         {
-            for(JsonNode item: repeatFields)
+            for(JsonNode item: relations)
             {
+                String relationType = item.findValue("relationType").getTextValue();
                 String primaryFieldName = item.findValue("primaryField").getTextValue();
-                String repeatFieldName = item.findValue("repeatField").getTextValue();
+                String secondaryFieldName = item.findValue("secondaryField").getTextValue();
                 FormField primaryField = retVal.getFormField(primaryFieldName);
-                FormField repeatField = retVal.getFormField(repeatFieldName);
-                if(primaryField == null || repeatField == null)
+                FormField secondaryField = retVal.getFormField(secondaryFieldName);
+                if(primaryField == null || secondaryField == null)
                 {
                     continue;
                 }
-
-                if(!primaryField.getWebValue().equals(repeatField.getWebValue()))
+                
+                // Repetition of strings
+                if(relationType.equals(RELATION_TYPE_EQUALS))
                 {
-                    repeatField.setValid(false);
-                    repeatField.setValidationMessage(
-                            MessageFormat.format(SessionLocaleUtil.getI18nText(request, "xIsNotEqualToY"),
-                                    SessionLocaleUtil.getI18nText(request, repeatFieldName),
-                                    SessionLocaleUtil.getI18nText(request, primaryFieldName)
-                                    )
-                    );
+                    if(!primaryField.getWebValue().equals(secondaryField.getWebValue()))
+                    {
+                        primaryField.setValid(false);
+                        primaryField.setValidationMessage(
+                                MessageFormat.format(SessionLocaleUtil.getI18nText(request, "xIsNotEqualToY"),
+                                        SessionLocaleUtil.getI18nText(request, primaryFieldName),
+                                        SessionLocaleUtil.getI18nText(request, secondaryFieldName)
+                                        )
+                        );
+                    }
+                }
+                // Ordering of dates
+                else if(relationType.equals(RELATION_TYPE_AFTER))
+                {
+                    if(primaryField.getValueAsDate().compareTo(secondaryField.getValueAsDate()) < 0)
+                    {
+                        primaryField.setValid(false);
+                        primaryField.setValidationMessage(
+                                MessageFormat.format(SessionLocaleUtil.getI18nText(request, "xIsNotAfterY"),
+                                        SessionLocaleUtil.getI18nText(request, primaryFieldName),
+                                        SessionLocaleUtil.getI18nText(request, secondaryFieldName)
+                                        )
+                        );
+                    }
                 }
             }
         }
         
         return retVal;
     }
+    
+    /**
+     * Fetches all fields and their constrants from form definition
+     * @param formName name of JSON file with form definition
+     * @param servletContext
+     * @return
+     * @throws IOException 
+     */
+    public static JsonNode getFormDefinition(String formName, ServletContext servletContext) throws IOException
+    {
+        ObjectMapper mapper = new ObjectMapper();
+        JsonFactory factory = mapper.getJsonFactory();
+        InputStream in = servletContext.getResourceAsStream("/formdefinitions/" + formName + ".json");
+
+        JsonParser parser = factory.createJsonParser(in);
+        JsonNode formDefinition = mapper.readTree(parser);
+        return formDefinition;
+    }
+    
+    /**
+     * 
+     * @param formName
+     * @param servletContext
+     * @return all form fields form the form definition, indexed by their name
+     * @throws IOException 
+     */
+    public static Map<String, FormField> getFormFields(String formName, ServletContext servletContext) throws IOException
+    {
+        JsonNode formDefinition = getFormDefinition(formName, servletContext);
+        ObjectMapper mapper = new ObjectMapper();
+        JsonNode fields = formDefinition.findValue("fields");
+        Map<String, FormField> retVal = new HashMap<>();
+        for(JsonNode fieldNode:fields)
+        {
+            FormField formField = mapper.convertValue(fieldNode, FormField.class);
+            retVal.put(formField.getName(), formField);
+        }
+        
+        return retVal;
+    }
 
 }
diff --git a/src/main/resources/no/bioforsk/vips/logic/i18n/vipslogictexts.properties b/src/main/resources/no/bioforsk/vips/logic/i18n/vipslogictexts.properties
index 56b1dc3277bb893d21ea5e4994b14889fe3ccc83..ba0447b82ea290f11359c333573798d7af25146b 100644
--- a/src/main/resources/no/bioforsk/vips/logic/i18n/vipslogictexts.properties
+++ b/src/main/resources/no/bioforsk/vips/logic/i18n/vipslogictexts.properties
@@ -73,3 +73,19 @@ userUpdated=User was updated
 delete=Delete
 confirmDelete=Do you really want to delete?
 userDeleted=User was deleted
+forecasts=Forecasts
+dateStart=Date start
+dateEnd=Date end
+poi=Point of interest
+viewForecastConfiguration=View forecast configuration
+forecastConfigurationUpdated=Forecast configuration was updated
+forecastConfigurationId=Forecast configuration
+vipsLogicUserId=User
+doesNotMatchDateFormat=Does not match format {0}
+modelId=Forecasting model
+APPLESCABM=Apple scab model
+NAERSTADMO=N\u00e6rstad's model
+locationPointOfInterestId=Location
+weatherStationPointOfInterestId=Weather station
+addNew=Add new
+xIsNotAfterY={0} is not after {1}
diff --git a/src/main/resources/no/bioforsk/vips/logic/i18n/vipslogictexts_no.properties b/src/main/resources/no/bioforsk/vips/logic/i18n/vipslogictexts_no.properties
index 1aebcd732bd035b7e54ad74cd47013dcd9d841f7..b6b50b109f54cc769b4bd2fd46054ec899ae97f3 100644
--- a/src/main/resources/no/bioforsk/vips/logic/i18n/vipslogictexts_no.properties
+++ b/src/main/resources/no/bioforsk/vips/logic/i18n/vipslogictexts_no.properties
@@ -73,3 +73,19 @@ userUpdated=Brukeren ble oppdatert
 delete=Slett
 confirmDelete=\u00d8nsker du virkelig \u00e5 slette?
 userDeleted=Brukeren ble slettet
+forecasts=Varsler
+dateStart=Startdato
+dateEnd=Sluttdato
+poi=Geografisk punkt
+viewForecastConfiguration=Se varseloppsett
+forecastConfigurationUpdated=Varseloppsettet ble oppdatert
+forecastConfigurationId=Varseloppsett
+vipsLogicUserId=Bruker
+doesNotMatchDateFormat=Stemmer ikke med formatet {0}
+modelId=Varslingsmodell
+APPLESCABM=Epleskurvmodell
+NAERSTADMO=N\u00e6rstads modell
+locationPointOfInterestId=Lokalitet
+weatherStationPointOfInterestId=M\u00e5lestasjon
+addNew=Legg til ny
+xIsNotAfterY={0} er ikke etter {1}
diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml
index 952cb690fac186ec930118e1b9383fc592fb6bff..b7f8ad6c2c644ed640248c172583afbd057add1b 100644
--- a/src/main/webapp/WEB-INF/web.xml
+++ b/src/main/webapp/WEB-INF/web.xml
@@ -18,7 +18,7 @@
     </servlet>
     <servlet>
         <servlet-name>UserControllerServlet</servlet-name>
-        <servlet-class>no.bioforsk.vips.logic.controller.servlet.UserControllerServlet</servlet-class>
+        <servlet-class>no.bioforsk.vips.logic.controller.servlet.UserController</servlet-class>
     </servlet>
     <servlet>
         <servlet-name>ResourceBundleJSServlet</servlet-name>
@@ -28,6 +28,10 @@
         <servlet-name>HttpErrorServlet</servlet-name>
         <servlet-class>no.bioforsk.vips.logic.controller.servlet.HttpErrorServlet</servlet-class>
     </servlet>
+    <servlet>
+        <servlet-name>ForecastController</servlet-name>
+        <servlet-class>no.bioforsk.vips.logic.controller.servlet.ForecastConfigurationController</servlet-class>
+    </servlet>
     <servlet-mapping>
         <servlet-name>PointOfInterestController</servlet-name>
         <url-pattern>/poi/*</url-pattern>
@@ -58,6 +62,10 @@
         <url-pattern>/error/404</url-pattern>
         <url-pattern>/error/403</url-pattern>
     </servlet-mapping>
+    <servlet-mapping>
+        <servlet-name>ForecastController</servlet-name>
+        <url-pattern>/forecastConfiguration</url-pattern>
+    </servlet-mapping>
     <welcome-file-list>
         <welcome-file>index.html</welcome-file>
     </welcome-file-list>
diff --git a/src/main/webapp/formdefinitions/forecastConfigurationForm.json b/src/main/webapp/formdefinitions/forecastConfigurationForm.json
new file mode 100644
index 0000000000000000000000000000000000000000..a5a08dbc69566202a6055f398c8a26cd0cf5d1fb
--- /dev/null
+++ b/src/main/webapp/formdefinitions/forecastConfigurationForm.json
@@ -0,0 +1,51 @@
+{
+    "_comment" : "Structure of the forecastConfigurationForm and how to validate it",
+    "fields": [
+        {
+            "name" : "forecastConfigurationId",
+            "type" : "INTEGER",
+            "required" : true
+        },
+        {
+            "name" : "vipsLogicUserId",
+            "type" : "INTEGER",
+            "type" : "SELECT_SINGLE",
+            "nullValue": "-1",
+            "required" : true
+        },
+        {
+            "name" : "modelId",
+            "type" : "SELECT_SINGLE",
+            "nullValue": "-1",
+            "required" : true
+        },
+        {
+            "name" : "locationPointOfInterestId",
+            "type" : "SELECT_SINGLE",
+            "nullValue": "-1",
+            "required" : true
+        },
+        {
+            "name" : "weatherStationPointOfInterestId",
+            "type" : "SELECT_SINGLE",
+            "nullValue": "-1",
+            "required" : true
+        },
+        {
+            "name" : "dateStart",
+            "type" : "DATE",
+            "dateFormat" : "yyyy-MM-dd",
+            "required" : true
+        },
+        {
+            "name" : "dateEnd",
+            "type" : "DATE",
+            "dateFormat" : "yyyy-MM-dd",
+            "required" : true
+        }
+        
+    ],
+    "relations":[
+        {"primaryField":"dateEnd","secondaryField":"dateStart", "relationType": "AFTER"}
+    ]
+}
diff --git a/src/main/webapp/formdefinitions/userRegistrationForm.json b/src/main/webapp/formdefinitions/userRegistrationForm.json
index 7fc292325e9946f493c17f5931cc28672f908202..08e602f803a86efff6585a80160f5b00be19adc6 100644
--- a/src/main/webapp/formdefinitions/userRegistrationForm.json
+++ b/src/main/webapp/formdefinitions/userRegistrationForm.json
@@ -49,7 +49,7 @@
         }
         
     ],
-    "repeatFields":[
-        {"primaryField":"password","repeatField":"password2"}
+    "relations":[
+        {"primaryField":"password2","secondaryField":"password", "relationType": "EQUALS"}
     ]
 }
diff --git a/src/main/webapp/js/moment.min.js b/src/main/webapp/js/moment.min.js
new file mode 100644
index 0000000000000000000000000000000000000000..568ad05cecad8a0cde991c6f744df72f9ac8ddea
--- /dev/null
+++ b/src/main/webapp/js/moment.min.js
@@ -0,0 +1,6 @@
+//! moment.js
+//! version : 2.4.0
+//! authors : Tim Wood, Iskren Chernev, Moment.js contributors
+//! license : MIT
+//! momentjs.com
+(function(a){function b(a,b){return function(c){return i(a.call(this,c),b)}}function c(a,b){return function(c){return this.lang().ordinal(a.call(this,c),b)}}function d(){}function e(a){u(a),g(this,a)}function f(a){var b=o(a),c=b.year||0,d=b.month||0,e=b.week||0,f=b.day||0,g=b.hour||0,h=b.minute||0,i=b.second||0,j=b.millisecond||0;this._input=a,this._milliseconds=+j+1e3*i+6e4*h+36e5*g,this._days=+f+7*e,this._months=+d+12*c,this._data={},this._bubble()}function g(a,b){for(var c in b)b.hasOwnProperty(c)&&(a[c]=b[c]);return b.hasOwnProperty("toString")&&(a.toString=b.toString),b.hasOwnProperty("valueOf")&&(a.valueOf=b.valueOf),a}function h(a){return 0>a?Math.ceil(a):Math.floor(a)}function i(a,b){for(var c=a+"";c.length<b;)c="0"+c;return c}function j(a,b,c,d){var e,f,g=b._milliseconds,h=b._days,i=b._months;g&&a._d.setTime(+a._d+g*c),(h||i)&&(e=a.minute(),f=a.hour()),h&&a.date(a.date()+h*c),i&&a.month(a.month()+i*c),g&&!d&&bb.updateOffset(a),(h||i)&&(a.minute(e),a.hour(f))}function k(a){return"[object Array]"===Object.prototype.toString.call(a)}function l(a){return"[object Date]"===Object.prototype.toString.call(a)||a instanceof Date}function m(a,b,c){var d,e=Math.min(a.length,b.length),f=Math.abs(a.length-b.length),g=0;for(d=0;e>d;d++)(c&&a[d]!==b[d]||!c&&q(a[d])!==q(b[d]))&&g++;return g+f}function n(a){if(a){var b=a.toLowerCase().replace(/(.)s$/,"$1");a=Kb[a]||Lb[b]||b}return a}function o(a){var b,c,d={};for(c in a)a.hasOwnProperty(c)&&(b=n(c),b&&(d[b]=a[c]));return d}function p(b){var c,d;if(0===b.indexOf("week"))c=7,d="day";else{if(0!==b.indexOf("month"))return;c=12,d="month"}bb[b]=function(e,f){var g,h,i=bb.fn._lang[b],j=[];if("number"==typeof e&&(f=e,e=a),h=function(a){var b=bb().utc().set(d,a);return i.call(bb.fn._lang,b,e||"")},null!=f)return h(f);for(g=0;c>g;g++)j.push(h(g));return j}}function q(a){var b=+a,c=0;return 0!==b&&isFinite(b)&&(c=b>=0?Math.floor(b):Math.ceil(b)),c}function r(a,b){return new Date(Date.UTC(a,b+1,0)).getUTCDate()}function s(a){return t(a)?366:365}function t(a){return 0===a%4&&0!==a%100||0===a%400}function u(a){var b;a._a&&-2===a._pf.overflow&&(b=a._a[gb]<0||a._a[gb]>11?gb:a._a[hb]<1||a._a[hb]>r(a._a[fb],a._a[gb])?hb:a._a[ib]<0||a._a[ib]>23?ib:a._a[jb]<0||a._a[jb]>59?jb:a._a[kb]<0||a._a[kb]>59?kb:a._a[lb]<0||a._a[lb]>999?lb:-1,a._pf._overflowDayOfYear&&(fb>b||b>hb)&&(b=hb),a._pf.overflow=b)}function v(a){a._pf={empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1}}function w(a){return null==a._isValid&&(a._isValid=!isNaN(a._d.getTime())&&a._pf.overflow<0&&!a._pf.empty&&!a._pf.invalidMonth&&!a._pf.nullInput&&!a._pf.invalidFormat&&!a._pf.userInvalidated,a._strict&&(a._isValid=a._isValid&&0===a._pf.charsLeftOver&&0===a._pf.unusedTokens.length)),a._isValid}function x(a){return a?a.toLowerCase().replace("_","-"):a}function y(a,b){return b.abbr=a,mb[a]||(mb[a]=new d),mb[a].set(b),mb[a]}function z(a){delete mb[a]}function A(a){var b,c,d,e,f=0,g=function(a){if(!mb[a]&&nb)try{require("./lang/"+a)}catch(b){}return mb[a]};if(!a)return bb.fn._lang;if(!k(a)){if(c=g(a))return c;a=[a]}for(;f<a.length;){for(e=x(a[f]).split("-"),b=e.length,d=x(a[f+1]),d=d?d.split("-"):null;b>0;){if(c=g(e.slice(0,b).join("-")))return c;if(d&&d.length>=b&&m(e,d,!0)>=b-1)break;b--}f++}return bb.fn._lang}function B(a){return a.match(/\[[\s\S]/)?a.replace(/^\[|\]$/g,""):a.replace(/\\/g,"")}function C(a){var b,c,d=a.match(rb);for(b=0,c=d.length;c>b;b++)d[b]=Pb[d[b]]?Pb[d[b]]:B(d[b]);return function(e){var f="";for(b=0;c>b;b++)f+=d[b]instanceof Function?d[b].call(e,a):d[b];return f}}function D(a,b){return a.isValid()?(b=E(b,a.lang()),Mb[b]||(Mb[b]=C(b)),Mb[b](a)):a.lang().invalidDate()}function E(a,b){function c(a){return b.longDateFormat(a)||a}var d=5;for(sb.lastIndex=0;d>=0&&sb.test(a);)a=a.replace(sb,c),sb.lastIndex=0,d-=1;return a}function F(a,b){var c;switch(a){case"DDDD":return vb;case"YYYY":case"GGGG":case"gggg":return wb;case"YYYYY":case"GGGGG":case"ggggg":return xb;case"S":case"SS":case"SSS":case"DDD":return ub;case"MMM":case"MMMM":case"dd":case"ddd":case"dddd":return zb;case"a":case"A":return A(b._l)._meridiemParse;case"X":return Cb;case"Z":case"ZZ":return Ab;case"T":return Bb;case"SSSS":return yb;case"MM":case"DD":case"YY":case"GG":case"gg":case"HH":case"hh":case"mm":case"ss":case"M":case"D":case"d":case"H":case"h":case"m":case"s":case"w":case"ww":case"W":case"WW":case"e":case"E":return tb;default:return c=new RegExp(N(M(a.replace("\\","")),"i"))}}function G(a){var b=(Ab.exec(a)||[])[0],c=(b+"").match(Hb)||["-",0,0],d=+(60*c[1])+q(c[2]);return"+"===c[0]?-d:d}function H(a,b,c){var d,e=c._a;switch(a){case"M":case"MM":null!=b&&(e[gb]=q(b)-1);break;case"MMM":case"MMMM":d=A(c._l).monthsParse(b),null!=d?e[gb]=d:c._pf.invalidMonth=b;break;case"D":case"DD":null!=b&&(e[hb]=q(b));break;case"DDD":case"DDDD":null!=b&&(c._dayOfYear=q(b));break;case"YY":e[fb]=q(b)+(q(b)>68?1900:2e3);break;case"YYYY":case"YYYYY":e[fb]=q(b);break;case"a":case"A":c._isPm=A(c._l).isPM(b);break;case"H":case"HH":case"h":case"hh":e[ib]=q(b);break;case"m":case"mm":e[jb]=q(b);break;case"s":case"ss":e[kb]=q(b);break;case"S":case"SS":case"SSS":case"SSSS":e[lb]=q(1e3*("0."+b));break;case"X":c._d=new Date(1e3*parseFloat(b));break;case"Z":case"ZZ":c._useUTC=!0,c._tzm=G(b);break;case"w":case"ww":case"W":case"WW":case"d":case"dd":case"ddd":case"dddd":case"e":case"E":a=a.substr(0,1);case"gg":case"gggg":case"GG":case"GGGG":case"GGGGG":a=a.substr(0,2),b&&(c._w=c._w||{},c._w[a]=b)}}function I(a){var b,c,d,e,f,g,h,i,j,k,l=[];if(!a._d){for(d=K(a),a._w&&null==a._a[hb]&&null==a._a[gb]&&(f=function(b){return b?b.length<3?parseInt(b,10)>68?"19"+b:"20"+b:b:null==a._a[fb]?bb().weekYear():a._a[fb]},g=a._w,null!=g.GG||null!=g.W||null!=g.E?h=X(f(g.GG),g.W||1,g.E,4,1):(i=A(a._l),j=null!=g.d?T(g.d,i):null!=g.e?parseInt(g.e,10)+i._week.dow:0,k=parseInt(g.w,10)||1,null!=g.d&&j<i._week.dow&&k++,h=X(f(g.gg),k,j,i._week.doy,i._week.dow)),a._a[fb]=h.year,a._dayOfYear=h.dayOfYear),a._dayOfYear&&(e=null==a._a[fb]?d[fb]:a._a[fb],a._dayOfYear>s(e)&&(a._pf._overflowDayOfYear=!0),c=S(e,0,a._dayOfYear),a._a[gb]=c.getUTCMonth(),a._a[hb]=c.getUTCDate()),b=0;3>b&&null==a._a[b];++b)a._a[b]=l[b]=d[b];for(;7>b;b++)a._a[b]=l[b]=null==a._a[b]?2===b?1:0:a._a[b];l[ib]+=q((a._tzm||0)/60),l[jb]+=q((a._tzm||0)%60),a._d=(a._useUTC?S:R).apply(null,l)}}function J(a){var b;a._d||(b=o(a._i),a._a=[b.year,b.month,b.day,b.hour,b.minute,b.second,b.millisecond],I(a))}function K(a){var b=new Date;return a._useUTC?[b.getUTCFullYear(),b.getUTCMonth(),b.getUTCDate()]:[b.getFullYear(),b.getMonth(),b.getDate()]}function L(a){a._a=[],a._pf.empty=!0;var b,c,d,e,f,g=A(a._l),h=""+a._i,i=h.length,j=0;for(d=E(a._f,g).match(rb)||[],b=0;b<d.length;b++)e=d[b],c=(F(e,a).exec(h)||[])[0],c&&(f=h.substr(0,h.indexOf(c)),f.length>0&&a._pf.unusedInput.push(f),h=h.slice(h.indexOf(c)+c.length),j+=c.length),Pb[e]?(c?a._pf.empty=!1:a._pf.unusedTokens.push(e),H(e,c,a)):a._strict&&!c&&a._pf.unusedTokens.push(e);a._pf.charsLeftOver=i-j,h.length>0&&a._pf.unusedInput.push(h),a._isPm&&a._a[ib]<12&&(a._a[ib]+=12),a._isPm===!1&&12===a._a[ib]&&(a._a[ib]=0),I(a),u(a)}function M(a){return a.replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(a,b,c,d,e){return b||c||d||e})}function N(a){return a.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function O(a){var b,c,d,e,f;if(0===a._f.length)return a._pf.invalidFormat=!0,a._d=new Date(0/0),void 0;for(e=0;e<a._f.length;e++)f=0,b=g({},a),v(b),b._f=a._f[e],L(b),w(b)&&(f+=b._pf.charsLeftOver,f+=10*b._pf.unusedTokens.length,b._pf.score=f,(null==d||d>f)&&(d=f,c=b));g(a,c||b)}function P(a){var b,c=a._i,d=Db.exec(c);if(d){for(a._pf.iso=!0,b=4;b>0;b--)if(d[b]){a._f=Fb[b-1]+(d[6]||" ");break}for(b=0;4>b;b++)if(Gb[b][1].exec(c)){a._f+=Gb[b][0];break}Ab.exec(c)&&(a._f+="Z"),L(a)}else a._d=new Date(c)}function Q(b){var c=b._i,d=ob.exec(c);c===a?b._d=new Date:d?b._d=new Date(+d[1]):"string"==typeof c?P(b):k(c)?(b._a=c.slice(0),I(b)):l(c)?b._d=new Date(+c):"object"==typeof c?J(b):b._d=new Date(c)}function R(a,b,c,d,e,f,g){var h=new Date(a,b,c,d,e,f,g);return 1970>a&&h.setFullYear(a),h}function S(a){var b=new Date(Date.UTC.apply(null,arguments));return 1970>a&&b.setUTCFullYear(a),b}function T(a,b){if("string"==typeof a)if(isNaN(a)){if(a=b.weekdaysParse(a),"number"!=typeof a)return null}else a=parseInt(a,10);return a}function U(a,b,c,d,e){return e.relativeTime(b||1,!!c,a,d)}function V(a,b,c){var d=eb(Math.abs(a)/1e3),e=eb(d/60),f=eb(e/60),g=eb(f/24),h=eb(g/365),i=45>d&&["s",d]||1===e&&["m"]||45>e&&["mm",e]||1===f&&["h"]||22>f&&["hh",f]||1===g&&["d"]||25>=g&&["dd",g]||45>=g&&["M"]||345>g&&["MM",eb(g/30)]||1===h&&["y"]||["yy",h];return i[2]=b,i[3]=a>0,i[4]=c,U.apply({},i)}function W(a,b,c){var d,e=c-b,f=c-a.day();return f>e&&(f-=7),e-7>f&&(f+=7),d=bb(a).add("d",f),{week:Math.ceil(d.dayOfYear()/7),year:d.year()}}function X(a,b,c,d,e){var f,g,h=new Date(Date.UTC(a,0)).getUTCDay();return c=null!=c?c:e,f=e-h+(h>d?7:0),g=7*(b-1)+(c-e)+f+1,{year:g>0?a:a-1,dayOfYear:g>0?g:s(a-1)+g}}function Y(a){var b=a._i,c=a._f;return"undefined"==typeof a._pf&&v(a),null===b?bb.invalid({nullInput:!0}):("string"==typeof b&&(a._i=b=A().preparse(b)),bb.isMoment(b)?(a=g({},b),a._d=new Date(+b._d)):c?k(c)?O(a):L(a):Q(a),new e(a))}function Z(a,b){bb.fn[a]=bb.fn[a+"s"]=function(a){var c=this._isUTC?"UTC":"";return null!=a?(this._d["set"+c+b](a),bb.updateOffset(this),this):this._d["get"+c+b]()}}function $(a){bb.duration.fn[a]=function(){return this._data[a]}}function _(a,b){bb.duration.fn["as"+a]=function(){return+this/b}}function ab(a){var b=!1,c=bb;"undefined"==typeof ender&&(this.moment=a?function(){return!b&&console&&console.warn&&(b=!0,console.warn("Accessing Moment through the global scope is deprecated, and will be removed in an upcoming release.")),c.apply(null,arguments)}:bb)}for(var bb,cb,db="2.4.0",eb=Math.round,fb=0,gb=1,hb=2,ib=3,jb=4,kb=5,lb=6,mb={},nb="undefined"!=typeof module&&module.exports,ob=/^\/?Date\((\-?\d+)/i,pb=/(\-)?(?:(\d*)\.)?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/,qb=/^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/,rb=/(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,4}|X|zz?|ZZ?|.)/g,sb=/(\[[^\[]*\])|(\\)?(LT|LL?L?L?|l{1,4})/g,tb=/\d\d?/,ub=/\d{1,3}/,vb=/\d{3}/,wb=/\d{1,4}/,xb=/[+\-]?\d{1,6}/,yb=/\d+/,zb=/[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i,Ab=/Z|[\+\-]\d\d:?\d\d/i,Bb=/T/i,Cb=/[\+\-]?\d+(\.\d{1,3})?/,Db=/^\s*\d{4}-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?([\+\-]\d\d:?\d\d|Z)?)?$/,Eb="YYYY-MM-DDTHH:mm:ssZ",Fb=["YYYY-MM-DD","GGGG-[W]WW","GGGG-[W]WW-E","YYYY-DDD"],Gb=[["HH:mm:ss.SSSS",/(T| )\d\d:\d\d:\d\d\.\d{1,3}/],["HH:mm:ss",/(T| )\d\d:\d\d:\d\d/],["HH:mm",/(T| )\d\d:\d\d/],["HH",/(T| )\d\d/]],Hb=/([\+\-]|\d\d)/gi,Ib="Date|Hours|Minutes|Seconds|Milliseconds".split("|"),Jb={Milliseconds:1,Seconds:1e3,Minutes:6e4,Hours:36e5,Days:864e5,Months:2592e6,Years:31536e6},Kb={ms:"millisecond",s:"second",m:"minute",h:"hour",d:"day",D:"date",w:"week",W:"isoWeek",M:"month",y:"year",DDD:"dayOfYear",e:"weekday",E:"isoWeekday",gg:"weekYear",GG:"isoWeekYear"},Lb={dayofyear:"dayOfYear",isoweekday:"isoWeekday",isoweek:"isoWeek",weekyear:"weekYear",isoweekyear:"isoWeekYear"},Mb={},Nb="DDD w W M D d".split(" "),Ob="M D H h m s w W".split(" "),Pb={M:function(){return this.month()+1},MMM:function(a){return this.lang().monthsShort(this,a)},MMMM:function(a){return this.lang().months(this,a)},D:function(){return this.date()},DDD:function(){return this.dayOfYear()},d:function(){return this.day()},dd:function(a){return this.lang().weekdaysMin(this,a)},ddd:function(a){return this.lang().weekdaysShort(this,a)},dddd:function(a){return this.lang().weekdays(this,a)},w:function(){return this.week()},W:function(){return this.isoWeek()},YY:function(){return i(this.year()%100,2)},YYYY:function(){return i(this.year(),4)},YYYYY:function(){return i(this.year(),5)},gg:function(){return i(this.weekYear()%100,2)},gggg:function(){return this.weekYear()},ggggg:function(){return i(this.weekYear(),5)},GG:function(){return i(this.isoWeekYear()%100,2)},GGGG:function(){return this.isoWeekYear()},GGGGG:function(){return i(this.isoWeekYear(),5)},e:function(){return this.weekday()},E:function(){return this.isoWeekday()},a:function(){return this.lang().meridiem(this.hours(),this.minutes(),!0)},A:function(){return this.lang().meridiem(this.hours(),this.minutes(),!1)},H:function(){return this.hours()},h:function(){return this.hours()%12||12},m:function(){return this.minutes()},s:function(){return this.seconds()},S:function(){return q(this.milliseconds()/100)},SS:function(){return i(q(this.milliseconds()/10),2)},SSS:function(){return i(this.milliseconds(),3)},SSSS:function(){return i(this.milliseconds(),3)},Z:function(){var a=-this.zone(),b="+";return 0>a&&(a=-a,b="-"),b+i(q(a/60),2)+":"+i(q(a)%60,2)},ZZ:function(){var a=-this.zone(),b="+";return 0>a&&(a=-a,b="-"),b+i(q(10*a/6),4)},z:function(){return this.zoneAbbr()},zz:function(){return this.zoneName()},X:function(){return this.unix()}},Qb=["months","monthsShort","weekdays","weekdaysShort","weekdaysMin"];Nb.length;)cb=Nb.pop(),Pb[cb+"o"]=c(Pb[cb],cb);for(;Ob.length;)cb=Ob.pop(),Pb[cb+cb]=b(Pb[cb],2);for(Pb.DDDD=b(Pb.DDD,3),g(d.prototype,{set:function(a){var b,c;for(c in a)b=a[c],"function"==typeof b?this[c]=b:this["_"+c]=b},_months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),months:function(a){return this._months[a.month()]},_monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),monthsShort:function(a){return this._monthsShort[a.month()]},monthsParse:function(a){var b,c,d;for(this._monthsParse||(this._monthsParse=[]),b=0;12>b;b++)if(this._monthsParse[b]||(c=bb.utc([2e3,b]),d="^"+this.months(c,"")+"|^"+this.monthsShort(c,""),this._monthsParse[b]=new RegExp(d.replace(".",""),"i")),this._monthsParse[b].test(a))return b},_weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdays:function(a){return this._weekdays[a.day()]},_weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysShort:function(a){return this._weekdaysShort[a.day()]},_weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),weekdaysMin:function(a){return this._weekdaysMin[a.day()]},weekdaysParse:function(a){var b,c,d;for(this._weekdaysParse||(this._weekdaysParse=[]),b=0;7>b;b++)if(this._weekdaysParse[b]||(c=bb([2e3,1]).day(b),d="^"+this.weekdays(c,"")+"|^"+this.weekdaysShort(c,"")+"|^"+this.weekdaysMin(c,""),this._weekdaysParse[b]=new RegExp(d.replace(".",""),"i")),this._weekdaysParse[b].test(a))return b},_longDateFormat:{LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D YYYY",LLL:"MMMM D YYYY LT",LLLL:"dddd, MMMM D YYYY LT"},longDateFormat:function(a){var b=this._longDateFormat[a];return!b&&this._longDateFormat[a.toUpperCase()]&&(b=this._longDateFormat[a.toUpperCase()].replace(/MMMM|MM|DD|dddd/g,function(a){return a.slice(1)}),this._longDateFormat[a]=b),b},isPM:function(a){return"p"===(a+"").toLowerCase().charAt(0)},_meridiemParse:/[ap]\.?m?\.?/i,meridiem:function(a,b,c){return a>11?c?"pm":"PM":c?"am":"AM"},_calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},calendar:function(a,b){var c=this._calendar[a];return"function"==typeof c?c.apply(b):c},_relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},relativeTime:function(a,b,c,d){var e=this._relativeTime[c];return"function"==typeof e?e(a,b,c,d):e.replace(/%d/i,a)},pastFuture:function(a,b){var c=this._relativeTime[a>0?"future":"past"];return"function"==typeof c?c(b):c.replace(/%s/i,b)},ordinal:function(a){return this._ordinal.replace("%d",a)},_ordinal:"%d",preparse:function(a){return a},postformat:function(a){return a},week:function(a){return W(a,this._week.dow,this._week.doy).week},_week:{dow:0,doy:6},_invalidDate:"Invalid date",invalidDate:function(){return this._invalidDate}}),bb=function(b,c,d,e){return"boolean"==typeof d&&(e=d,d=a),Y({_i:b,_f:c,_l:d,_strict:e,_isUTC:!1})},bb.utc=function(b,c,d,e){var f;return"boolean"==typeof d&&(e=d,d=a),f=Y({_useUTC:!0,_isUTC:!0,_l:d,_i:b,_f:c,_strict:e}).utc()},bb.unix=function(a){return bb(1e3*a)},bb.duration=function(a,b){var c,d,e,g=bb.isDuration(a),h="number"==typeof a,i=g?a._input:h?{}:a,j=null;return h?b?i[b]=a:i.milliseconds=a:(j=pb.exec(a))?(c="-"===j[1]?-1:1,i={y:0,d:q(j[hb])*c,h:q(j[ib])*c,m:q(j[jb])*c,s:q(j[kb])*c,ms:q(j[lb])*c}):(j=qb.exec(a))&&(c="-"===j[1]?-1:1,e=function(a){var b=a&&parseFloat(a.replace(",","."));return(isNaN(b)?0:b)*c},i={y:e(j[2]),M:e(j[3]),d:e(j[4]),h:e(j[5]),m:e(j[6]),s:e(j[7]),w:e(j[8])}),d=new f(i),g&&a.hasOwnProperty("_lang")&&(d._lang=a._lang),d},bb.version=db,bb.defaultFormat=Eb,bb.updateOffset=function(){},bb.lang=function(a,b){var c;return a?(b?y(x(a),b):null===b?(z(a),a="en"):mb[a]||A(a),c=bb.duration.fn._lang=bb.fn._lang=A(a),c._abbr):bb.fn._lang._abbr},bb.langData=function(a){return a&&a._lang&&a._lang._abbr&&(a=a._lang._abbr),A(a)},bb.isMoment=function(a){return a instanceof e},bb.isDuration=function(a){return a instanceof f},cb=Qb.length-1;cb>=0;--cb)p(Qb[cb]);for(bb.normalizeUnits=function(a){return n(a)},bb.invalid=function(a){var b=bb.utc(0/0);return null!=a?g(b._pf,a):b._pf.userInvalidated=!0,b},bb.parseZone=function(a){return bb(a).parseZone()},g(bb.fn=e.prototype,{clone:function(){return bb(this)},valueOf:function(){return+this._d+6e4*(this._offset||0)},unix:function(){return Math.floor(+this/1e3)},toString:function(){return this.clone().lang("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},toDate:function(){return this._offset?new Date(+this):this._d},toISOString:function(){return D(bb(this).utc(),"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]")},toArray:function(){var a=this;return[a.year(),a.month(),a.date(),a.hours(),a.minutes(),a.seconds(),a.milliseconds()]},isValid:function(){return w(this)},isDSTShifted:function(){return this._a?this.isValid()&&m(this._a,(this._isUTC?bb.utc(this._a):bb(this._a)).toArray())>0:!1},parsingFlags:function(){return g({},this._pf)},invalidAt:function(){return this._pf.overflow},utc:function(){return this.zone(0)},local:function(){return this.zone(0),this._isUTC=!1,this},format:function(a){var b=D(this,a||bb.defaultFormat);return this.lang().postformat(b)},add:function(a,b){var c;return c="string"==typeof a?bb.duration(+b,a):bb.duration(a,b),j(this,c,1),this},subtract:function(a,b){var c;return c="string"==typeof a?bb.duration(+b,a):bb.duration(a,b),j(this,c,-1),this},diff:function(a,b,c){var d,e,f=this._isUTC?bb(a).zone(this._offset||0):bb(a).local(),g=6e4*(this.zone()-f.zone());return b=n(b),"year"===b||"month"===b?(d=432e5*(this.daysInMonth()+f.daysInMonth()),e=12*(this.year()-f.year())+(this.month()-f.month()),e+=(this-bb(this).startOf("month")-(f-bb(f).startOf("month")))/d,e-=6e4*(this.zone()-bb(this).startOf("month").zone()-(f.zone()-bb(f).startOf("month").zone()))/d,"year"===b&&(e/=12)):(d=this-f,e="second"===b?d/1e3:"minute"===b?d/6e4:"hour"===b?d/36e5:"day"===b?(d-g)/864e5:"week"===b?(d-g)/6048e5:d),c?e:h(e)},from:function(a,b){return bb.duration(this.diff(a)).lang(this.lang()._abbr).humanize(!b)},fromNow:function(a){return this.from(bb(),a)},calendar:function(){var a=this.diff(bb().zone(this.zone()).startOf("day"),"days",!0),b=-6>a?"sameElse":-1>a?"lastWeek":0>a?"lastDay":1>a?"sameDay":2>a?"nextDay":7>a?"nextWeek":"sameElse";return this.format(this.lang().calendar(b,this))},isLeapYear:function(){return t(this.year())},isDST:function(){return this.zone()<this.clone().month(0).zone()||this.zone()<this.clone().month(5).zone()},day:function(a){var b=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=a?(a=T(a,this.lang()),this.add({d:a-b})):b},month:function(a){var b,c=this._isUTC?"UTC":"";return null!=a?"string"==typeof a&&(a=this.lang().monthsParse(a),"number"!=typeof a)?this:(b=this.date(),this.date(1),this._d["set"+c+"Month"](a),this.date(Math.min(b,this.daysInMonth())),bb.updateOffset(this),this):this._d["get"+c+"Month"]()},startOf:function(a){switch(a=n(a)){case"year":this.month(0);case"month":this.date(1);case"week":case"isoWeek":case"day":this.hours(0);case"hour":this.minutes(0);case"minute":this.seconds(0);case"second":this.milliseconds(0)}return"week"===a?this.weekday(0):"isoWeek"===a&&this.isoWeekday(1),this},endOf:function(a){return a=n(a),this.startOf(a).add("isoWeek"===a?"week":a,1).subtract("ms",1)},isAfter:function(a,b){return b="undefined"!=typeof b?b:"millisecond",+this.clone().startOf(b)>+bb(a).startOf(b)},isBefore:function(a,b){return b="undefined"!=typeof b?b:"millisecond",+this.clone().startOf(b)<+bb(a).startOf(b)},isSame:function(a,b){return b="undefined"!=typeof b?b:"millisecond",+this.clone().startOf(b)===+bb(a).startOf(b)},min:function(a){return a=bb.apply(null,arguments),this>a?this:a},max:function(a){return a=bb.apply(null,arguments),a>this?this:a},zone:function(a){var b=this._offset||0;return null==a?this._isUTC?b:this._d.getTimezoneOffset():("string"==typeof a&&(a=G(a)),Math.abs(a)<16&&(a=60*a),this._offset=a,this._isUTC=!0,b!==a&&j(this,bb.duration(b-a,"m"),1,!0),this)},zoneAbbr:function(){return this._isUTC?"UTC":""},zoneName:function(){return this._isUTC?"Coordinated Universal Time":""},parseZone:function(){return"string"==typeof this._i&&this.zone(this._i),this},hasAlignedHourOffset:function(a){return a=a?bb(a).zone():0,0===(this.zone()-a)%60},daysInMonth:function(){return r(this.year(),this.month())},dayOfYear:function(a){var b=eb((bb(this).startOf("day")-bb(this).startOf("year"))/864e5)+1;return null==a?b:this.add("d",a-b)},weekYear:function(a){var b=W(this,this.lang()._week.dow,this.lang()._week.doy).year;return null==a?b:this.add("y",a-b)},isoWeekYear:function(a){var b=W(this,1,4).year;return null==a?b:this.add("y",a-b)},week:function(a){var b=this.lang().week(this);return null==a?b:this.add("d",7*(a-b))},isoWeek:function(a){var b=W(this,1,4).week;return null==a?b:this.add("d",7*(a-b))},weekday:function(a){var b=(this.day()+7-this.lang()._week.dow)%7;return null==a?b:this.add("d",a-b)},isoWeekday:function(a){return null==a?this.day()||7:this.day(this.day()%7?a:a-7)},get:function(a){return a=n(a),this[a]()},set:function(a,b){return a=n(a),"function"==typeof this[a]&&this[a](b),this},lang:function(b){return b===a?this._lang:(this._lang=A(b),this)}}),cb=0;cb<Ib.length;cb++)Z(Ib[cb].toLowerCase().replace(/s$/,""),Ib[cb]);Z("year","FullYear"),bb.fn.days=bb.fn.day,bb.fn.months=bb.fn.month,bb.fn.weeks=bb.fn.week,bb.fn.isoWeeks=bb.fn.isoWeek,bb.fn.toJSON=bb.fn.toISOString,g(bb.duration.fn=f.prototype,{_bubble:function(){var a,b,c,d,e=this._milliseconds,f=this._days,g=this._months,i=this._data;i.milliseconds=e%1e3,a=h(e/1e3),i.seconds=a%60,b=h(a/60),i.minutes=b%60,c=h(b/60),i.hours=c%24,f+=h(c/24),i.days=f%30,g+=h(f/30),i.months=g%12,d=h(g/12),i.years=d},weeks:function(){return h(this.days()/7)},valueOf:function(){return this._milliseconds+864e5*this._days+2592e6*(this._months%12)+31536e6*q(this._months/12)},humanize:function(a){var b=+this,c=V(b,!a,this.lang());return a&&(c=this.lang().pastFuture(b,c)),this.lang().postformat(c)},add:function(a,b){var c=bb.duration(a,b);return this._milliseconds+=c._milliseconds,this._days+=c._days,this._months+=c._months,this._bubble(),this},subtract:function(a,b){var c=bb.duration(a,b);return this._milliseconds-=c._milliseconds,this._days-=c._days,this._months-=c._months,this._bubble(),this},get:function(a){return a=n(a),this[a.toLowerCase()+"s"]()},as:function(a){return a=n(a),this["as"+a.charAt(0).toUpperCase()+a.slice(1)+"s"]()},lang:bb.fn.lang,toIsoString:function(){var a=Math.abs(this.years()),b=Math.abs(this.months()),c=Math.abs(this.days()),d=Math.abs(this.hours()),e=Math.abs(this.minutes()),f=Math.abs(this.seconds()+this.milliseconds()/1e3);return this.asSeconds()?(this.asSeconds()<0?"-":"")+"P"+(a?a+"Y":"")+(b?b+"M":"")+(c?c+"D":"")+(d||e||f?"T":"")+(d?d+"H":"")+(e?e+"M":"")+(f?f+"S":""):"P0D"}});for(cb in Jb)Jb.hasOwnProperty(cb)&&(_(cb,Jb[cb]),$(cb.toLowerCase()));_("Weeks",6048e5),bb.duration.fn.asMonths=function(){return(+this-31536e6*this.years())/2592e6+12*this.years()},bb.lang("en",{ordinal:function(a){var b=a%10,c=1===q(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c}}),nb?(module.exports=bb,ab(!0)):"function"==typeof define&&define.amd?define("moment",function(b,c,d){return d.config().noGlobal!==!0&&ab(d.config().noGlobal===a),bb}):ab()}).call(this);
\ No newline at end of file
diff --git a/src/main/webapp/js/validateForm.js b/src/main/webapp/js/validateForm.js
index fd16c95c820452cc4bf63924623680592399ffa5..a8d4a64e70b860b71227272f92a5212d2b6766fe 100644
--- a/src/main/webapp/js/validateForm.js
+++ b/src/main/webapp/js/validateForm.js
@@ -9,10 +9,23 @@ var formFieldTypes = {
     TYPE_STRING: "STRING",
     TYPE_INTEGER: "INTEGER",
     TYPE_DOUBLE: "DOUBLE",
+    TYPE_DATE: "DATE",
     TYPE_PASSWORD: "PASSWORD",
     TYPE_EMAIL: "EMAIL",
     TYPE_SELECT_SINGLE: "SELECT_SINGLE",
     TYPE_SELECT_MULTIPLE: "SELECT_MULTIPLE"
+    
+};
+
+
+var defaultValues = {
+    DEFAULT_DATE_FORMAT: "yyyy-MM-dd"
+};
+
+// Primary field relates to secondary field as TYPE
+var relationTypes = {
+    RELATION_TYPE_EQUALS: "EQUALS",
+    RELATION_TYPE_AFTER: "AFTER"
 };
 
 // Storage for all form definitions for current page
@@ -35,6 +48,7 @@ var emailReg = /^([\w-\.]+@([\w-]+\.)+[\w-]{2,4})?$/;
  *  <li>The form must have an id that corresponds to a JSON file accessible in "/formdefinitions/[form_id].json"</li>
  *  <li>A DOM element with id "errorMsgEl" for where to put validation error messages</li>
  *  <li>jQuery for Ajax calls</li>
+ *  <li><a href="http://momentjs.com/">moment.js</a> for date validation</li>
  * </ul>
  * 
  * This function prepares for the validateFormActual function.
@@ -73,23 +87,41 @@ function validateFormActual(theForm)
         }
     }
     
-    // Check repeats
-    for(var i in formDefinition.repeatFields)
+    // Check relations
+    for(var i in formDefinition.relations)
     {
-        var item = formDefinition.repeatFields[i];
+        var item = formDefinition.relations[i];
         var primaryFieldWebValue = theForm[item.primaryField].value;
-        var repeatFieldWebValue = theForm[item.repeatField].value;
-        if(primaryFieldWebValue === null || repeatFieldWebValue === null)
+        var secondaryFieldWebValue = theForm[item.secondaryField].value;
+        if(primaryFieldWebValue === null || secondaryFieldWebValue === null)
         {
             continue;
         }
-        if(primaryFieldWebValue !== repeatFieldWebValue)
+        
+        // String equality NOW!
+        console.log("relationTYpe=" + item.relationType);
+        if(item.relationType === relationTypes.RELATION_TYPE_EQUALS)
         {
-            isValid = false;
-            invalidizeField(theForm[item.repeatField], theForm, getI18nMsg("xIsNotEqualToY",[
-                getI18nMsg(item.repeatField),
-                getI18nMsg(item.primaryField).toLowerCase()
-            ]));
+            if(primaryFieldWebValue !== secondaryFieldWebValue)
+            {
+                isValid = false;
+                invalidizeField(theForm[item.primaryField], theForm, getI18nMsg("xIsNotEqualToY",[
+                    getI18nMsg(item.primaryField),
+                    getI18nMsg(item.secondaryField).toLowerCase()
+                ]));
+            }
+        }
+        // Primary field is expected to be a date AFTER secondary key
+        else if(item.relationType === relationTypes.RELATION_TYPE_AFTER)
+        {
+            if(!moment(primaryFieldWebValue).isAfter(moment(secondaryFieldWebValue)))
+            {
+                isValid = false;
+                invalidizeField(theForm[item.primaryField], theForm, getI18nMsg("xIsNotAfterY",[
+                    getI18nMsg(item.primaryField),
+                    getI18nMsg(item.secondaryField).toLowerCase()
+                ]));
+            }
         }
         //console.log(item.primaryField);
     }
@@ -193,6 +225,22 @@ function validateFieldActual(fieldEl, theForm)
             return true;
         }
     }
+    
+    // Dates: check date format
+    if(fieldDefinition.type === formFieldTypes.TYPE_DATE)
+    {
+        var validFormat = (fieldDefinition.dateFormat !== null && fieldDefinition.dateFormat !== undefined) ? fieldDefinition.dateFormat : defaultValues.DEFAULT_DATE_FORMAT;
+        if(!moment(webValue, validFormat.toUpperCase(),true).isValid())
+        {
+            invalidizeField(fieldEl, theForm, getI18nMsg("doesNotMatchDateFormat",[validFormat]));
+            return false;
+        }
+        else
+        {
+            validizeField(fieldEl, theForm);
+            return true;
+        }
+    }
 
     // Check email format
     // We use a simple regExp for this
@@ -368,6 +416,11 @@ function evaluatePassword(passwordEl)
  */
 function invalidizeField(inputEl, theForm, message)
 {
+    // Make sure we don't try to manipulate hidden fields
+    if(inputEl.type === "hidden")
+    {
+        return;
+    }
     styleInvalid(theForm[inputEl.name]);
     getValidationOutputEl(inputEl, theForm).innerHTML = message;
 }
@@ -380,6 +433,11 @@ function invalidizeField(inputEl, theForm, message)
  */
 function validizeField(inputEl, theForm)
 {
+    // Make sure we don't try to manipulate hidden fields
+    if(inputEl.type === "hidden")
+    {
+        return;
+    }
     styleValid(theForm[inputEl.name]);
     getValidationOutputEl(inputEl, theForm).innerHTML = "";
 }
diff --git a/src/main/webapp/templates/forecastConfigurationForm.ftl b/src/main/webapp/templates/forecastConfigurationForm.ftl
new file mode 100644
index 0000000000000000000000000000000000000000..81c0d8ea63cb19d45a508d679b4c3bb8be2ac6a8
--- /dev/null
+++ b/src/main/webapp/templates/forecastConfigurationForm.ftl
@@ -0,0 +1,91 @@
+<#include "master.ftl">
+<#macro page_head>
+        <title></title>
+</#macro>
+<#macro custom_js>
+	<script src="/js/resourcebundle.js"></script>
+	<script src="/js/validateForm.js"></script>
+	<script src="http://code.jquery.com/ui/1.10.3/jquery-ui.min.js"></script>
+	<link href="http://code.jquery.com/ui/1.10.3/themes/redmond/jquery-ui.css" rel="stylesheet" />
+	<script type="text/javascript" src="/js/modernizr_custom.js"></script>
+	<script type="text/javascript" src="/js/moment.min.js"></script>
+	<script type="text/javascript">
+		// Make sure that there is a date picker present for HTML5 
+		// date input fields
+		if (!Modernizr.inputtypes.date) {
+		    $('input[type=date]').datepicker({ dateFormat: 'yy-mm-dd' });
+		}
+	</script>
+</#macro>
+<#macro page_contents>
+        <h1>${i18nBundle.viewForecastConfiguration}</h1>
+        <div id="errorMsgEl" class="alert alert-danger" <#if !formValidation?has_content> style="display:none;"</#if>>
+		<#if formValidation?has_content>${formValidation.validationMessages?replace("\n", "<br>")}</#if>
+	</div>
+	<#if messageKey?has_content>
+		<div class="alert alert-success">${i18nBundle(messageKey)}</div>
+	</#if>
+        <#assign formId = "forecastConfigurationForm">
+        <form id="${formId}" role="form" action="/forecastConfiguration?action=forecastConfigurationFormSubmit" method="POST" onsubmit="try{return validateForm(this);}catch(err){alert(err);return false;}">
+          <input type="hidden" name="forecastConfigurationId" value="${forecastConfiguration.forecastConfigurationId!"-1"}"/>
+          <div class="form-group">
+	    <label for="modelId">${i18nBundle.modelId}</label>
+	    <select class="form-control" name="modelId" onblur="validateField(this);">
+	    	<option value="-1">${i18nBundle.pleaseSelect} ${i18nBundle.modelId?lower_case}</option>
+	    	<#list modelInformations as modelInformation>
+	    	<option value="${modelInformation.modelId}"<#if forecastConfiguration.modelId?has_content && modelInformation.modelId == forecastConfiguration.modelId> selected="selected"</#if>>
+	    		<#if i18nBundle.containsKey(modelInformation.modelId)>
+				${i18nBundle[modelInformation.modelId]}
+			<#else>
+				${modelInformation.defaultName}
+			</#if>
+		</option>
+	    	</#list>
+	    </select>
+	    <span class="help-block" id="${formId}_modelId_validation"></span>
+	  </div>
+	  <div class="form-group">
+	    <label for="locationPointOfInterestId">${i18nBundle.locationPointOfInterestId}</label>
+	    <select class="form-control" name="locationPointOfInterestId" onblur="validateField(this);">
+	    	<option value="-1">${i18nBundle.pleaseSelect} ${i18nBundle.locationPointOfInterestId?lower_case}</option>
+	    	<#list locationPointOfInterests?sort_by("name") as poi>
+	    	<option value="${poi.pointOfInterestId}"<#if forecastConfiguration.locationPointOfInterestId?has_content && poi.pointOfInterestId == forecastConfiguration.locationPointOfInterestId.pointOfInterestId> selected="selected"</#if>>${poi.name}</option>
+	    	</#list>
+	    </select>
+	    <span class="help-block" id="${formId}_locationPointOfInterestId_validation"></span>
+	  </div>
+	  <div class="form-group">
+	    <label for="weatherStationPointOfInterestId">${i18nBundle.weatherStationPointOfInterestId}</label>
+	    <select class="form-control" name="weatherStationPointOfInterestId" onblur="validateField(this);">
+	    	<option value="-1">${i18nBundle.pleaseSelect} ${i18nBundle.weatherStationPointOfInterestId?lower_case}</option>
+	    	<#list weatherStationPointOfInterests?sort_by("name") as poi>
+	    	<option value="${poi.pointOfInterestId}"<#if forecastConfiguration.weatherStationPointOfInterestId?has_content && poi.pointOfInterestId == forecastConfiguration.weatherStationPointOfInterestId.pointOfInterestId> selected="selected"</#if>>${poi.name}</option>
+	    	</#list>
+	    </select>
+	    <span class="help-block" id="${formId}_weatherStationPointOfInterestId_validation"></span>
+	  </div>
+          <div class="form-group">
+	    <label for="dateStart">${i18nBundle.dateStart}</label>
+	    <input type="date" class="form-control" name="dateStart" placeholder="${i18nBundle.dateStart}" value="${(forecastConfiguration.dateStart?string(dateStart_dateFormat))!""}" onblur="validateField(this);" />
+	    <span class="help-block" id="${formId}_dateStart_validation"></span>
+	  </div>
+	  <div class="form-group">
+	    <label for="dateEnd">${i18nBundle.dateEnd}</label>
+	    <input type="date" class="form-control" name="dateEnd" placeholder="${i18nBundle.dateEnd}" value="${(forecastConfiguration.dateEnd?string(dateEnd_dateFormat))!""}" onblur="validateField(this);" />
+	    <span class="help-block" id="${formId}_dateEnd_validation"></span>
+	  </div>
+	  <div class="form-group">
+	    <label for="vipsLogicUserId">${i18nBundle.vipsLogicUserId}</label>
+	    <select class="form-control" name="vipsLogicUserId" onblur="validateField(this);">
+	    	<option value="-1">${i18nBundle.pleaseSelect} ${i18nBundle.vipsLogicUserId?lower_case}</option>
+	    	<#list vipsLogicUsers?sort_by("lastName") as user>
+	    	<option value="${user.userId}"<#if forecastConfiguration.vipsLogicUserId?has_content && user.userId == forecastConfiguration.vipsLogicUserId.userId> selected="selected"</#if>>${user.lastName}, ${user.firstName}</option>
+	    	</#list>
+	    </select>
+	    <span class="help-block" id="${formId}_vipsLogicUserId_validation"></span>
+	  </div>
+	  <button type="submit" class="btn btn-default">${i18nBundle.submit}</button>
+	  <button type="button" class="btn btn-danger" onclick="if(confirm('${i18nBundle.confirmDelete}')){alert('Not implemented');}">${i18nBundle.delete}</button>
+        </form>
+</#macro>
+<@page_html/>
diff --git a/src/main/webapp/templates/forecastConfigurationList.ftl b/src/main/webapp/templates/forecastConfigurationList.ftl
new file mode 100644
index 0000000000000000000000000000000000000000..09416bb8cd1a0f0ef1e647afe0ad487e0211f8a2
--- /dev/null
+++ b/src/main/webapp/templates/forecastConfigurationList.ftl
@@ -0,0 +1,38 @@
+<#include "master.ftl">
+<#macro page_head>
+        <title>${i18nBundle.forecasts}</title>
+</#macro>
+<#macro page_contents>
+        <h1>${i18nBundle.forecasts}</h1>
+        <#if messageKey?has_content>
+		<div class="alert alert-success">${i18nBundle(messageKey)}</div>
+	</#if>
+	<button type="button" class="btn btn-default" onclick="window.location.href='/forecastConfiguration?action=viewForecastConfiguration&forecastConfigurationId=-1'">${i18nBundle.addNew}</button>
+        <div class="table-responsive">
+	<table class="table table-striped">
+		<thead>
+			<th>${i18nBundle.modelId}</th>
+			<th>${i18nBundle.poi}</th>
+			<th>${i18nBundle.dateStart}</th>
+			<th>${i18nBundle.dateEnd}</th>
+		</thead>
+		<tbody>
+		<#list forecastConfigurations?sort_by("dateStart")?reverse 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.dateStart}</td>
+		    	<td>${forecastConfiguration.dateEnd}</td>
+		    </tr>
+		</#list>
+		</tbody>
+        </table>
+        </div>
+</#macro>
+<@page_html/>
diff --git a/src/main/webapp/templates/master.ftl b/src/main/webapp/templates/master.ftl
index f1b3c539ad41a6991803cf635b57b4979a3e6a57..349e8d8c38fcfc184ac3f3ce731d8f7165b24464 100644
--- a/src/main/webapp/templates/master.ftl
+++ b/src/main/webapp/templates/master.ftl
@@ -31,8 +31,8 @@
 	      <li class="dropdown">
 		<a href="#" class="dropdown-toggle" data-toggle="dropdown">Admin<b class="caret"></b></a>
 		<ul class="dropdown-menu">
-		  <li><a href="/user">Users</a></li>
-		  <li><a href="#">Another action</a></li>
+		  <li><a href="/user">${i18nBundle.users}</a></li>
+		  <li><a href="/forecastConfiguration">${i18nBundle.forecasts}</a></li>
 		  <li><a href="#">Something else here</a></li>
 		  <li><a href="#">Separated link</a></li>
 		  <li><a href="#">One more separated link</a></li>
diff --git a/src/main/webapp/templates/userForm.ftl b/src/main/webapp/templates/userForm.ftl
index 05894d41a07adc63e0298cd51c3a56bdbd22c1eb..c8705e91955b903a773fc7b9a8afc022cf8c005b 100644
--- a/src/main/webapp/templates/userForm.ftl
+++ b/src/main/webapp/templates/userForm.ftl
@@ -15,7 +15,7 @@
 		<div class="alert alert-success">${i18nBundle(messageKey)}</div>
 	</#if>
         <#assign formId = "userForm">
-        <form id="${formId}" role="form" action="/user?action=userFormSubmit" method="POST" onsubmit="return validateForm(this);" accept-charset="UTF-8">
+        <form id="${formId}" role="form" action="/user?action=userFormSubmit" method="POST" onsubmit="return validateForm(this);">
           <input type="hidden" name="userId" value="${viewUser.userId}"/>
 	  <!-- Authentication info should be dealt with outside this form -->
 	  <div class="form-group">
diff --git a/src/main/webapp/test/updatemodelinfo.jsp b/src/main/webapp/test/updatemodelinfo.jsp
new file mode 100644
index 0000000000000000000000000000000000000000..1835bd0e3ff65454f4026bbcbf62f63a1ba352c4
--- /dev/null
+++ b/src/main/webapp/test/updatemodelinfo.jsp
@@ -0,0 +1,23 @@
+<%-- 
+    Document   : updatemodelinfo
+    Created on : Dec 6, 2013, 5:11:53 PM
+    Author     : treinar
+--%>
+<%@page import="no.bioforsk.vips.logic.controller.session.ForecastBean"%>
+<%@page import="no.bioforsk.vips.logic.util.SessionControllerGetter"%>
+<%
+    ForecastBean fb = SessionControllerGetter.getForecastBean();
+    
+    fb.updateModelInformation();
+%>
+<%@page contentType="text/html" pageEncoding="UTF-8"%>
+<!DOCTYPE html>
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+        <title>Update model info</title>
+    </head>
+    <body>
+        <h1>This page calls the methods for updating model info. It also displays the updated model info(?)</h1>
+    </body>
+</html>