From 875f02046d25eb56dd9c92f3ed4aedf211fff094 Mon Sep 17 00:00:00 2001
From: Robert Goldmann <deadlocker@gmx.de>
Date: Sun, 4 Mar 2018 13:09:24 +0100
Subject: [PATCH] #269 - categories can now be added; added validation;

---
 .../budgetmaster/advices/ColorAdvice.java     |  17 +++
 .../controller/CategoryController.java        |  57 +++++++---
 .../budgetmaster/entities/Category.java       |   4 +
 .../budgetmaster/utils/Helpers.java           |  34 +++---
 .../budgetmaster/utils/Notification.java      |  49 +++++++++
 .../budgetmaster/utils/NotificationLevel.java |  28 +++++
 .../budgetmaster/utils/Strings.java           |   1 +
 .../validators/CategoryValidator.java         |  22 ++++
 src/main/resources/languages/_de.properties   |   1 +
 src/main/resources/languages/_en.properties   |   1 +
 src/main/resources/templates/newCategory.ftl  | 103 ++++++++++--------
 11 files changed, 242 insertions(+), 75 deletions(-)
 create mode 100644 src/main/java/de/deadlocker8/budgetmaster/advices/ColorAdvice.java
 create mode 100644 src/main/java/de/deadlocker8/budgetmaster/utils/Notification.java
 create mode 100644 src/main/java/de/deadlocker8/budgetmaster/utils/NotificationLevel.java
 create mode 100644 src/main/java/de/deadlocker8/budgetmaster/validators/CategoryValidator.java

diff --git a/src/main/java/de/deadlocker8/budgetmaster/advices/ColorAdvice.java b/src/main/java/de/deadlocker8/budgetmaster/advices/ColorAdvice.java
new file mode 100644
index 000000000..691982e92
--- /dev/null
+++ b/src/main/java/de/deadlocker8/budgetmaster/advices/ColorAdvice.java
@@ -0,0 +1,17 @@
+package de.deadlocker8.budgetmaster.advices;
+
+import de.deadlocker8.budgetmaster.utils.Helpers;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ModelAttribute;
+
+import java.util.ArrayList;
+
+@ControllerAdvice
+public class ColorAdvice
+{
+	@ModelAttribute("categoryColors")
+	public ArrayList<String> getCategoryColors()
+	{
+		return Helpers.getCategoryColorList();
+	}
+}
\ No newline at end of file
diff --git a/src/main/java/de/deadlocker8/budgetmaster/controller/CategoryController.java b/src/main/java/de/deadlocker8/budgetmaster/controller/CategoryController.java
index fa4ac89a1..f041d21ac 100644
--- a/src/main/java/de/deadlocker8/budgetmaster/controller/CategoryController.java
+++ b/src/main/java/de/deadlocker8/budgetmaster/controller/CategoryController.java
@@ -1,18 +1,26 @@
 package de.deadlocker8.budgetmaster.controller;
 
+import de.deadlocker8.budgetmaster.Validators.CategoryValidator;
 import de.deadlocker8.budgetmaster.entities.Category;
 import de.deadlocker8.budgetmaster.entities.CategoryType;
 import de.deadlocker8.budgetmaster.repositories.CategoryRepository;
 import de.deadlocker8.budgetmaster.utils.Colors;
 import de.deadlocker8.budgetmaster.utils.Helpers;
+import de.deadlocker8.budgetmaster.utils.Notification;
+import de.deadlocker8.budgetmaster.utils.NotificationLevel;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.stereotype.Controller;
 import org.springframework.ui.ModelMap;
+import org.springframework.validation.BindingResult;
+import org.springframework.validation.ObjectError;
+import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.ModelAttribute;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMethod;
 import tools.ConvertTo;
+import tools.Localization;
 
 import java.util.ArrayList;
 
@@ -23,6 +31,7 @@ public class CategoryController extends BaseController
 	@Autowired
 	private CategoryRepository categoryRepository;
 
+
 	@RequestMapping("/categories")
 	public String index(@ModelAttribute("model") ModelMap model)
 	{
@@ -39,7 +48,7 @@ public class CategoryController extends BaseController
 		}
 
 		model.addAttribute("confirm", true);
-		model.addAttribute("categories", categoryRepository.findAll());
+		model.addAttribute("categories", categoryRepository.findAllByOrderByNameAsc());
 		model.addAttribute("currentCategory", categoryRepository.getOne(ID));
 		return "categories";
 	}
@@ -65,27 +74,45 @@ public class CategoryController extends BaseController
 	public String newCategory(@ModelAttribute("model") ModelMap model)
 	{
 		//TODO: add color picker for custom colors
-		//TODO: validate wrong inputs --> empty name --> message on page --> validate before send?
 
-		ArrayList<String> categoryColors = Helpers.getCategoryColorList();
 		//add custom color (defaults to white here because we are adding a new category instead of editing an existing)
-		categoryColors.add("#FFFFFF");
-		model.addAttribute("categoryColors", categoryColors);
-
-		model.addAttribute("activeColor", ConvertTo.toRGBHexWithoutOpacity(Colors.CATEGORIES_LIGHT_GREY));
+		model.addAttribute("customColor", "#FFFFFF");
+		Category emptyCategory = new Category(null, ConvertTo.toRGBHexWithoutOpacity(Colors.CATEGORIES_LIGHT_GREY), CategoryType.CUSTOM);
+		model.addAttribute("category", emptyCategory);
 		return "newCategory";
 	}
 
-	@RequestMapping(value = "/categories/post/", method = RequestMethod.POST)
-	public String post(@ModelAttribute("NewCategory") Category category)
+	@RequestMapping(value = "/categories/newCategory", method = RequestMethod.POST)
+	public String post(@ModelAttribute("model") ModelMap model, @ModelAttribute("NewCategory") Category category, BindingResult bindingResult)
 	{
-		if(category == null
-				|| category.getName() == null
-				|| category.getName().isEmpty()
-				|| category.getColor() == null
-				|| category.getColor().isEmpty())
+		System.out.println(category);
+		CategoryValidator userValidator = new CategoryValidator();
+		userValidator.validate(category, bindingResult);
+
+		if(bindingResult.hasErrors())
 		{
-			System.out.println("Wrong input");
+			ArrayList<Notification> notifications = new ArrayList<>();
+			for(ObjectError error : bindingResult.getAllErrors())
+			{
+				notifications.add(new Notification(NotificationLevel.WARNING, null, Localization.getString(error.getCode())));
+			}
+
+			model.addAttribute("notifications", notifications);
+			if(Helpers.getCategoryColorList().contains(category.getColor()))
+			{
+				model.addAttribute("customColor", "#FFFFFF");
+			}
+			else
+			{
+				model.addAttribute("customColor", category.getColor());
+			}
+
+			if(category.getColor() == null)
+			{
+				category.setColor(ConvertTo.toRGBHexWithoutOpacity(Colors.CATEGORIES_LIGHT_GREY));
+			}
+			model.addAttribute("category", category);
+			return "newCategory";
 		}
 		else
 		{
diff --git a/src/main/java/de/deadlocker8/budgetmaster/entities/Category.java b/src/main/java/de/deadlocker8/budgetmaster/entities/Category.java
index ee68468af..2b8e98b94 100644
--- a/src/main/java/de/deadlocker8/budgetmaster/entities/Category.java
+++ b/src/main/java/de/deadlocker8/budgetmaster/entities/Category.java
@@ -7,6 +7,8 @@ import javax.persistence.Entity;
 import javax.persistence.GeneratedValue;
 import javax.persistence.GenerationType;
 import javax.persistence.Id;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
 
 @Entity
 public class Category
@@ -14,6 +16,8 @@ public class Category
 	@Id
 	@GeneratedValue(strategy = GenerationType.AUTO)
 	private Integer ID;
+	@NotNull
+	@Size(min = 1)
 	private String name;
 	private String color;
 	private CategoryType type;
diff --git a/src/main/java/de/deadlocker8/budgetmaster/utils/Helpers.java b/src/main/java/de/deadlocker8/budgetmaster/utils/Helpers.java
index 006895d8c..e5bea0fe2 100644
--- a/src/main/java/de/deadlocker8/budgetmaster/utils/Helpers.java
+++ b/src/main/java/de/deadlocker8/budgetmaster/utils/Helpers.java
@@ -91,23 +91,23 @@ public class Helpers
 	public static ArrayList<String> getCategoryColorList()
 	{
 		ArrayList<String> categoryColors = new ArrayList<>();
-		categoryColors.add(ConvertTo.toRGBHexWithoutOpacity(Colors.CATEGORIES_LIGHT_GREY));
-		categoryColors.add(ConvertTo.toRGBHexWithoutOpacity(Colors.CATEGORIES_GREY));
-		categoryColors.add(ConvertTo.toRGBHexWithoutOpacity(Colors.CATEGORIES_DARK_GREY));
-		categoryColors.add(ConvertTo.toRGBHexWithoutOpacity(Colors.CATEGORIES_LIGHT_YELLOW));
-		categoryColors.add(ConvertTo.toRGBHexWithoutOpacity(Colors.CATEGORIES_YELLOW));
-		categoryColors.add(ConvertTo.toRGBHexWithoutOpacity(Colors.CATEGORIES_ORANGE));
-		categoryColors.add(ConvertTo.toRGBHexWithoutOpacity(Colors.CATEGORIES_RED));
-		categoryColors.add(ConvertTo.toRGBHexWithoutOpacity(Colors.CATEGORIES_DARK_RED));
-		categoryColors.add(ConvertTo.toRGBHexWithoutOpacity(Colors.CATEGORIES_PINK));
-		categoryColors.add(ConvertTo.toRGBHexWithoutOpacity(Colors.CATEGORIES_PURPLE));
-		categoryColors.add(ConvertTo.toRGBHexWithoutOpacity(Colors.CATEGORIES_DARK_PURPLE));
-		categoryColors.add(ConvertTo.toRGBHexWithoutOpacity(Colors.CATEGORIES_BLUE));
-		categoryColors.add(ConvertTo.toRGBHexWithoutOpacity(Colors.CATEGORIES_SOFT_BLUE));
-		categoryColors.add(ConvertTo.toRGBHexWithoutOpacity(Colors.CATEGORIES_LIGHT_BLUE));
-		categoryColors.add(ConvertTo.toRGBHexWithoutOpacity(Colors.CATEGORIES_LIGHT_GREEN));
-		categoryColors.add(ConvertTo.toRGBHexWithoutOpacity(Colors.CATEGORIES_LIME_GREEN));
-		categoryColors.add(ConvertTo.toRGBHexWithoutOpacity(Colors.CATEGORIES_DARK_GREEN));
+		categoryColors.add(ConvertTo.toRGBHexWithoutOpacity(Colors.CATEGORIES_LIGHT_GREY).toLowerCase());
+		categoryColors.add(ConvertTo.toRGBHexWithoutOpacity(Colors.CATEGORIES_GREY).toLowerCase());
+		categoryColors.add(ConvertTo.toRGBHexWithoutOpacity(Colors.CATEGORIES_DARK_GREY).toLowerCase());
+		categoryColors.add(ConvertTo.toRGBHexWithoutOpacity(Colors.CATEGORIES_LIGHT_YELLOW).toLowerCase());
+		categoryColors.add(ConvertTo.toRGBHexWithoutOpacity(Colors.CATEGORIES_YELLOW).toLowerCase());
+		categoryColors.add(ConvertTo.toRGBHexWithoutOpacity(Colors.CATEGORIES_ORANGE).toLowerCase());
+		categoryColors.add(ConvertTo.toRGBHexWithoutOpacity(Colors.CATEGORIES_RED).toLowerCase());
+		categoryColors.add(ConvertTo.toRGBHexWithoutOpacity(Colors.CATEGORIES_DARK_RED).toLowerCase());
+		categoryColors.add(ConvertTo.toRGBHexWithoutOpacity(Colors.CATEGORIES_PINK).toLowerCase());
+		categoryColors.add(ConvertTo.toRGBHexWithoutOpacity(Colors.CATEGORIES_PURPLE).toLowerCase());
+		categoryColors.add(ConvertTo.toRGBHexWithoutOpacity(Colors.CATEGORIES_DARK_PURPLE).toLowerCase());
+		categoryColors.add(ConvertTo.toRGBHexWithoutOpacity(Colors.CATEGORIES_BLUE).toLowerCase());
+		categoryColors.add(ConvertTo.toRGBHexWithoutOpacity(Colors.CATEGORIES_SOFT_BLUE).toLowerCase());
+		categoryColors.add(ConvertTo.toRGBHexWithoutOpacity(Colors.CATEGORIES_LIGHT_BLUE).toLowerCase());
+		categoryColors.add(ConvertTo.toRGBHexWithoutOpacity(Colors.CATEGORIES_LIGHT_GREEN).toLowerCase());
+		categoryColors.add(ConvertTo.toRGBHexWithoutOpacity(Colors.CATEGORIES_LIME_GREEN).toLowerCase());
+		categoryColors.add(ConvertTo.toRGBHexWithoutOpacity(Colors.CATEGORIES_DARK_GREEN).toLowerCase());
 
 		return categoryColors;
 	}
diff --git a/src/main/java/de/deadlocker8/budgetmaster/utils/Notification.java b/src/main/java/de/deadlocker8/budgetmaster/utils/Notification.java
new file mode 100644
index 000000000..181295992
--- /dev/null
+++ b/src/main/java/de/deadlocker8/budgetmaster/utils/Notification.java
@@ -0,0 +1,49 @@
+package de.deadlocker8.budgetmaster.utils;
+
+import tools.Localization;
+
+public class Notification
+{
+	private NotificationLevel level;
+	private String messageTitle;
+	private String messageHeader;
+	private String messageBody;
+
+	public Notification(NotificationLevel level, String messageHeader, String messageBody)
+	{
+		this.level = level;
+		this.messageTitle = Localization.getString(level.getKey());
+		this.messageHeader = messageHeader;
+		this.messageBody = messageBody;
+	}
+
+	public NotificationLevel getLevel()
+	{
+		return level;
+	}
+
+	public String getMessageTitle()
+	{
+		return messageTitle;
+	}
+
+	public String getMessageHeader()
+	{
+		return messageHeader;
+	}
+
+	public String getMessageBody()
+	{
+		return messageBody;
+	}
+
+	@Override
+	public String toString()
+	{
+		return "Notification{" +
+				"level=" + level +
+				", messageHeader='" + messageHeader + '\'' +
+				", messageBody='" + messageBody + '\'' +
+				'}';
+	}
+}
\ No newline at end of file
diff --git a/src/main/java/de/deadlocker8/budgetmaster/utils/NotificationLevel.java b/src/main/java/de/deadlocker8/budgetmaster/utils/NotificationLevel.java
new file mode 100644
index 000000000..61bd8ee59
--- /dev/null
+++ b/src/main/java/de/deadlocker8/budgetmaster/utils/NotificationLevel.java
@@ -0,0 +1,28 @@
+package de.deadlocker8.budgetmaster.utils;
+
+public enum NotificationLevel
+{
+	INFO("title.info"),
+	WARNING("title.warning"),
+	ERROR("title.error");
+
+	private String key;
+
+	NotificationLevel(String key)
+	{
+		this.key = key;
+	}
+
+	public String getKey()
+	{
+		return key;
+	}
+
+	@Override
+	public String toString()
+	{
+		return "NotificationLevel{" +
+				"key='" + key + '\'' +
+				'}';
+	}
+}
diff --git a/src/main/java/de/deadlocker8/budgetmaster/utils/Strings.java b/src/main/java/de/deadlocker8/budgetmaster/utils/Strings.java
index 2c62a8e7d..bdad0b0a0 100644
--- a/src/main/java/de/deadlocker8/budgetmaster/utils/Strings.java
+++ b/src/main/java/de/deadlocker8/budgetmaster/utils/Strings.java
@@ -183,6 +183,7 @@ public class Strings
     public static final String WARNING_INTEGER_HEIGHT_IN_PIXELS = "warning.integer.height.in.pixels";
     public static final String WARNING_EMPTY_SAVEPATH_CHART = "warning.empty.savepath.chart";
     public static final String WARNING_EMPTY_CATEGORY_NAME = "warning.empty.category.name";
+    public static final String WARNING_EMPTY_CATEGORY_COLOR = "warning.empty.category.color";
     public static final String WARNING_EMPTY_PAYMENT_NAME = "warning.empty.payment.name";
     public static final String WARNING_NAME_CHARACTER_LIMIT_REACHED_45 = "warning.name.character.limit.reached.45";
     public static final String WARNING_NAME_CHARACTER_LIMIT_REACHED_150 = "warning.name.character.limit.reached.150";
diff --git a/src/main/java/de/deadlocker8/budgetmaster/validators/CategoryValidator.java b/src/main/java/de/deadlocker8/budgetmaster/validators/CategoryValidator.java
new file mode 100644
index 000000000..3a9c3db98
--- /dev/null
+++ b/src/main/java/de/deadlocker8/budgetmaster/validators/CategoryValidator.java
@@ -0,0 +1,22 @@
+package de.deadlocker8.budgetmaster.Validators;
+
+import de.deadlocker8.budgetmaster.entities.Category;
+import de.deadlocker8.budgetmaster.utils.Strings;
+import org.springframework.validation.Errors;
+import org.springframework.validation.ValidationUtils;
+import org.springframework.validation.Validator;
+
+
+public class CategoryValidator implements Validator
+{
+	public boolean supports(Class clazz)
+	{
+		return Category.class.equals(clazz);
+	}
+
+	public void validate(Object obj, Errors errors)
+	{
+		ValidationUtils.rejectIfEmptyOrWhitespace(errors, "name", Strings.WARNING_EMPTY_CATEGORY_NAME);
+		ValidationUtils.rejectIfEmptyOrWhitespace(errors, "color", Strings.WARNING_EMPTY_CATEGORY_COLOR);
+	}
+}
diff --git a/src/main/resources/languages/_de.properties b/src/main/resources/languages/_de.properties
index ec351e3a3..9a2526145 100644
--- a/src/main/resources/languages/_de.properties
+++ b/src/main/resources/languages/_de.properties
@@ -179,6 +179,7 @@ warning.empty.height.in.pixels=Bitte gib eine H
 warning.integer.height.in.pixels=Nur ganzahlige Werte sind f�r das Feld H�he erlaubt.
 warning.empty.savepath.chart=W�hle einen Speicherort f�r das Diagramm aus.
 warning.empty.category.name=Das Feld f�r den Namen darf nicht leer sein.
+warning.empty.category.color=Die Kategoriefarbe darf nicht leer sein.
 warning.empty.payment.name=Das Feld f�r den Namen darf nicht leer sein.
 warning.name.character.limit.reached.45=Der Name darf maximal 45 Zeichen lang sein.
 warning.name.character.limit.reached.150=Der Name darf maximal 150 Zeichen lang sein.
diff --git a/src/main/resources/languages/_en.properties b/src/main/resources/languages/_en.properties
index 4157b60f9..8788efcc8 100644
--- a/src/main/resources/languages/_en.properties
+++ b/src/main/resources/languages/_en.properties
@@ -179,6 +179,7 @@ warning.empty.height.in.pixels=Please enter a height in pixels.
 warning.integer.height.in.pixels=Only integer values are allowed for the height field.
 warning.empty.savepath.chart=Please select a location where you want to save the chart.
 warning.empty.category.name=The field for the name can not be empty.
+warning.empty.category.color=The category color should not be empty.
 warning.empty.payment.name=The field for the name can not be empty.
 warning.name.character.limit.reached.45=The name must not exceed 45 characters in length.
 warning.name.character.limit.reached.150=The name must not exceed 150 characters in length.
diff --git a/src/main/resources/templates/newCategory.ftl b/src/main/resources/templates/newCategory.ftl
index 0845c47e6..111cd1dbe 100644
--- a/src/main/resources/templates/newCategory.ftl
+++ b/src/main/resources/templates/newCategory.ftl
@@ -50,69 +50,86 @@
                     </div>
                 </div>
                 <div class="container">
-                <form name="NewCategory" action="/categories/post/" method="post">
-                    <div class="row">
-                        <div class="input-field col s12 m12 l8 offset-l2">
-                            <input id="category-name" type="text" name="name">
-                            <label for="category-name">Name</label>
+                    <form name="NewCategory" action="/categories/newCategory" method="post">
+                        <div class="row">
+                            <div class="input-field col s12 m12 l8 offset-l2">
+                                <input id="category-name" type="text" name="name" value="<#if !model["category"].getName??>${model["category"].getName()}</#if>">
+                                <label for="category-name">Name</label>
+                            </div>
                         </div>
-                    </div>
-                    <input type="hidden" name="color" id="categoryColor" value="">
-                    <#list model["categoryColors"] as color>
-                        <#if color?counter == 18>
-                        <#--add custom color picker-->
-                             <div class="col s2 m1 no-padding">
-                                 <div class="category-color" style="background-color: ${color}">
-                                     +
-                                 </div>
-                             </div>
-                        <#else>
+                        <input type="hidden" name="color" id="categoryColor" value="${model["category"].getColor()}">
+                        <#list categoryColors as color>
                             <#if color?counter == 1 || color?counter == 7 || color?counter == 13>
                                 <div class="row">
                                     <div class="col s2 m1 offset-m3 no-padding">
-                                        <div class="category-color <#if color == model["activeColor"]>category-color-active</#if>" style="background-color: ${color}"></div>
+                                        <div class="category-color <#if color == model["category"].getColor()>category-color-active</#if>" style="background-color: ${color}"></div>
                                     </div>
                             <#else>
                                 <div class="col s2 m1 no-padding">
-                                    <div class="category-color <#if color == model["activeColor"]>category-color-active</#if>" style="background-color: ${color}"></div>
+                                    <div class="category-color <#if color == model["category"].getColor()>category-color-active</#if>" style="background-color: ${color}"></div>
                                 </div>
                             </#if>
-                        </#if>
 
-                        <#if color?counter == 6 || color?counter == 12 || color?counter == 18>
+                            <#if color?counter == 6 || color?counter == 12>
+                                </div>
+                            </#if>
+                        </#list>
+                            <#--add custom color picker-->
+                            <div class="col s2 m1 no-padding">
+                                <div class="category-color <#if model["customColor"] == model["category"].getColor()>category-color-active</#if>" style="background-color: ${model["customColor"]}">
+                                    +
+                                </div>
                             </div>
-                        </#if>
-                    </#list>
-                    <br>
-                    <div class="row hide-on-small-only">
-                        <div class="col m6 l4 offset-l2 right-align">
-                            <a href="/categories" class="waves-effect waves-light btn budgetmaster-blue"><i class="material-icons left">clear</i>Abbrechen</a>
                         </div>
 
-                        <div class="col m6 l4 left-align">
-                            <button class="btn waves-effect waves-light budgetmaster-blue" type="submit" name="action">
-                                <i class="material-icons left">save</i>Speichern
-                            </button>
-                        </div>
-                    </div>
-                    <div class="hide-on-med-and-up">
-                        <div class="row center-align">
-                            <div class="col s12">
+                        <br>
+                        <div class="row hide-on-small-only">
+                            <div class="col m6 l4 offset-l2 right-align">
                                 <a href="/categories" class="waves-effect waves-light btn budgetmaster-blue"><i class="material-icons left">clear</i>Abbrechen</a>
                             </div>
-                        </div>
-                        <div class="row center-align">
-                            <div class="col s12">
-                                <button class="btn waves-effect waves-light budgetmaster-blue" type="submit" name="buttonSave">
+
+                            <div class="col m6 l4 left-align">
+                                <button class="btn waves-effect waves-light budgetmaster-blue" type="submit" name="action">
                                     <i class="material-icons left">save</i>Speichern
                                 </button>
                             </div>
                         </div>
-                    </div>
-                </form>
+                        <div class="hide-on-med-and-up">
+                            <div class="row center-align">
+                                <div class="col s12">
+                                    <a href="/categories" class="waves-effect waves-light btn budgetmaster-blue"><i class="material-icons left">clear</i>Abbrechen</a>
+                                </div>
+                            </div>
+                            <div class="row center-align">
+                                <div class="col s12">
+                                    <button class="btn waves-effect waves-light budgetmaster-blue" type="submit" name="buttonSave">
+                                        <i class="material-icons left">save</i>Speichern
+                                    </button>
+                                </div>
+                            </div>
+                        </div>
+                    </form>
+                </div>
             </div>
-        </div>
-    </main>
+        </main>
+
+        <!-- notificatiom modal -->
+        <#if model["notifications"]??>
+            <#if model["notifications"]?size == 1>
+                <div id="notificationModal" class="modal">
+                    <div class="modal-content">
+                        <h4>${model["notifications"][0].messageTitle}</h4>
+                        <#if model["notifications"][0].messageHeader??><h5>${model["notifications"][0].messageHeader}</h5></#if>
+                        <p>${model["notifications"][0].messageBody}</p>
+                    </div>
+                    <div class="modal-footer">
+                        <a class="modal-action modal-close waves-effect waves-green btn-flat">OK</a>
+                    </div>
+                </div>
+            <#else>
+
+            </#if>
+        </#if>
 
         <!--  Scripts-->
         <script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
-- 
GitLab