commit 8be7e897fbae6fa9f45f21413b16c7fda0414b36
Author: stepanekp <1stepanekpetr@gmail.com>
Date:   Tue Mar 29 22:56:52 2022 +0200

    #14 Configuration service and config dropdown added

diff --git a/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/controller/AppController.java b/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/controller/AppController.java
index 7df23a9..5c1ba3b 100644
--- a/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/controller/AppController.java
+++ b/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/controller/AppController.java
@@ -6,6 +6,7 @@ import cz.zcu.fav.kiv.antipatterndetectionapp.model.AntiPattern;
 import cz.zcu.fav.kiv.antipatterndetectionapp.model.Query;
 import cz.zcu.fav.kiv.antipatterndetectionapp.model.QueryResult;
 import cz.zcu.fav.kiv.antipatterndetectionapp.service.AntiPatternService;
+import cz.zcu.fav.kiv.antipatterndetectionapp.service.ConfigurationService;
 import cz.zcu.fav.kiv.antipatterndetectionapp.service.ProjectService;
 import cz.zcu.fav.kiv.antipatterndetectionapp.service.UserAccountService;
 import org.slf4j.Logger;
@@ -28,7 +29,10 @@ import java.io.FileWriter;
 import java.nio.file.Files;
 import java.time.LocalTime;
 import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 /**
  * This class contains all endpoints of the web application.
@@ -50,6 +54,9 @@ public class AppController {
     @Autowired
     private UserAccountService userAccountService;
 
+    @Autowired
+    private ConfigurationService configurationService;
+
     /**
      *  This method is called by the GET method and initializes
      *  the main page of the application (index). Loads all projects
@@ -390,5 +397,17 @@ public class AppController {
         return "redirect:/";
     }
 
+    @ModelAttribute("configList")
+    public List<String> configurationsGetList(HttpSession session){
+        List<String> configList;
+
+        if(session.getAttribute("user") != null)
+            configList = configurationService.getAllConfigurationNames();
+        else
+            configList = configurationService.getDefaultConfigurationNames();
+
+        return configList;
+    }
+
 
 }
diff --git a/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/service/ConfigurationService.java b/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/service/ConfigurationService.java
new file mode 100644
index 0000000..d048ae3
--- /dev/null
+++ b/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/service/ConfigurationService.java
@@ -0,0 +1,10 @@
+package cz.zcu.fav.kiv.antipatterndetectionapp.service;
+
+import java.util.List;
+
+public interface ConfigurationService {
+
+    List<String> getAllConfigurationNames();
+
+    List<String> getDefaultConfigurationNames();
+}
diff --git a/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/service/ConfigurationServiceImpl.java b/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/service/ConfigurationServiceImpl.java
new file mode 100644
index 0000000..18876b6
--- /dev/null
+++ b/src/main/java/cz/zcu/fav/kiv/antipatterndetectionapp/service/ConfigurationServiceImpl.java
@@ -0,0 +1,30 @@
+package cz.zcu.fav.kiv.antipatterndetectionapp.service;
+
+import org.springframework.core.io.FileSystemResource;
+import org.springframework.stereotype.Service;
+
+import java.io.File;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+
+@Service
+public class ConfigurationServiceImpl implements ConfigurationService {
+
+    @Override
+    public List<String> getAllConfigurationNames() {
+        List<String> configList = new ArrayList<String>();
+        File folder = new File(String.valueOf(Paths.get(new FileSystemResource("").getFile().getAbsolutePath() + "\\src\\main\\webapp\\configurations")));
+        for (final File fileEntry : folder.listFiles()) {
+            configList.add(fileEntry.getName().split("\\.")[0]);
+        }
+        return configList;
+    }
+
+    @Override
+    public List<String> getDefaultConfigurationNames() {
+        List<String> configList = new ArrayList<String>();
+        configList.add("Default");
+        return configList;
+    }
+}
diff --git a/src/main/webapp/WEB-INF/templates/fragments/navbar.html b/src/main/webapp/WEB-INF/templates/fragments/navbar.html
index 037835c..e8da9df 100644
--- a/src/main/webapp/WEB-INF/templates/fragments/navbar.html
+++ b/src/main/webapp/WEB-INF/templates/fragments/navbar.html
@@ -1,4 +1,4 @@
-<div th:fragment="navBar" xmlns:th="http://www.w3.org/1999/xhtml">
+<div th:fragment="navBar" xmlns:th="http://www.w3.org/1999/xhtml" xmlns:form="http://www.w3.org/1999/xhtml">
     <nav class="navbar fixed-top navbar-expand-lg navbar-light bg-light" id="main-navbar">
         <a class="navbar-brand">Anti Pattern Detector</a>
         <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
@@ -22,9 +22,7 @@
                 </li>
                 <li class="nav-item active" id="current-configuration-box">
                     <select class="form-control">
-                        <option value="1">Default</option>
-                        <option value="2">test-config-1</option>
-                        <option value="3">test-config-2</option>
+                        <option th:each="config : ${configList}" th:value = ${config} th:text = ${config}></option>
                     </select>
                 </li>
                 <li class="nav-item active">
diff --git a/src/main/webapp/configurations/Default.json b/src/main/webapp/configurations/Default.json
new file mode 100644
index 0000000..51b45a1
--- /dev/null
+++ b/src/main/webapp/configurations/Default.json
@@ -0,0 +1,90 @@
+{
+    "name" : "Default",
+    "default" : "1",
+    "TooLongSprint": [
+        {
+            "thresholdName": "maxIterationLength",
+            "value": "21"
+        },
+        {
+            "thresholdName": "maxNumberOfTooLongIterations",
+            "value": "0"
+        }
+    ],
+    "VaryingSprintLength": [
+        {
+            "thresholdName": "maxDaysDifference",
+            "value": "7"
+        },
+        {
+            "thresholdName": "maxIterationChanged",
+            "value": "1"
+        }
+    ],
+    "BusinessAsUsual": [
+        {
+            "thresholdName": "divisionOfIterationsWithRetrospective",
+            "value": "66.66f"
+        },
+        {
+           "thresholdName": "searchSubstringsWithRetrospective",
+            "value": "%retr%||%revi%||%week%scrum%"
+        }
+    ],
+    "SpecifyNothing": [
+        {
+            "thresholdName": "minNumberOfWikiPagesWithSpecification",
+            "value": "1"
+        },
+        {
+            "thresholdName": "minNumberOfActivitiesWithSpecification",
+            "value": "1"
+        },
+        {
+            "thresholdName": "minAvgLengthOfActivityDescription",
+            "value": "150"
+        },
+        {
+            "thresholdName": "searchSubstringsWithProjectSpecification",
+            "value": "%dsp%||%specifikace%||%specification%||%vize%proj%||%vize%produ%"
+        }
+    ],
+    "RoadToNowhere": [
+        {
+            "thresholdName": "minNumberOfWikiPagesWithProjectPlan",
+            "value": "1"
+        },
+        {
+            "thresholdName": "minNumberOfActivitiesWithProjectPlan",
+            "value": "1"
+        },
+        {
+            "thresholdName": "searchSubstringsWithProjectPlan",
+            "value": "%plán projektu%||%project plan%||%plan project%||%projektový plán%"
+        }
+    ],
+    "LongOrNonExistentFeedbackLoops": [
+        {
+            "thresholdName": "divisionOfIterationsWithFeedbackLoop",
+            "value": "50.00f"
+        },
+        {
+            "thresholdName": "maxGapBetweenFeedbackLoopRate",
+            "value": "2f"
+        },
+        {
+            "thresholdName": "searchSubstringsWithFeedbackLoop",
+            "value": "%schůz%zákazník%||%předvedení%zákazník%||%zákazn%demo%||%schůz%zadavat%||%inform%schůz%||%zákazn%||%zadavatel%"
+        }
+    ],
+    "NinetyNinetyRule": [
+        {
+            "thresholdName": "maxDivisionRange",
+            "value": "1.25f"
+        },
+        {
+            "thresholdName": "maxBadDivisionLimit",
+            "value": "2"
+        }
+    ]
+}
\ No newline at end of file
diff --git a/src/main/webapp/resources/js/editor.js b/src/main/webapp/resources/js/editor.js
index a2d55d2..0e70ebc 100644
--- a/src/main/webapp/resources/js/editor.js
+++ b/src/main/webapp/resources/js/editor.js
@@ -178,7 +178,7 @@ function codeFormat() {
     let S=window.getSelection().toString();
     if(S.length == 0)
         return;
-    if(window.getSelection().anchorNode.parentNode.nodeName.toLowerCase() ===  'code'){
+    if(window.getSelection().anchorNode.parentNode.nodeName.toLowerCase() ===  'pre'){
         document.execCommand('formatBlock', false, 'div');
         document.execCommand('insertHTML',false, S);
     }
