diff --git a/README.md b/README.md index dff7b07..c7d50dd 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,15 @@ ![BauDas Logo](https://services.joethei.xyz/images/bauDas.png) -#Kundenkarten Verwaltung +#Kundenkarten Analyse [![Build Status](https://teamcity.joethei.xyz/app/rest/builds/buildType:(id:Studium_Programmierung_Softwareprojektmanagement_SpmProd)/statusIcon)](https://tcstatus.joethei.space/dashboard/spm) [![Quality Gate](https://sonarqube.joethei.xyz/api/project_badges/measure?project=Studium_Programmierung_Softwareprojektmanagement&metric=alert_status) ![Code Coverage](https://sonarqube.joethei.xyz/api/project_badges/measure?project=Studium_Programmierung_Softwareprojektmanagement&metric=coverage)](https://sonarqube.joethei.xyz/dashboard?id=Studium_Programmierung_Softwareprojektmanagement) -## Requirements +## minimal Requirements - Java 8 - Maven 3 -- Tomcat 9 +- Tomcat 7 ## Development Setup @@ -20,7 +20,7 @@ - restart the server if needed -## TODO: better Name for this +## get the war - clone this repository - run maven goal ````package```` - war can be found in target folder diff --git a/pom.xml b/pom.xml index ffcc805..65068b4 100644 --- a/pom.xml +++ b/pom.xml @@ -16,10 +16,13 @@ 1.8 checkstyle.xml UTF-8 - ${project.build.directory}/jacoco.exec + src/main + src/test + jacoco + reuseReports + ${project.basedir}/target/jacoco.exec - Johannes Theiner @@ -33,7 +36,7 @@ Charlotte Friedemann charlotte.friedemann@informatik-emden.de - Developer + Project Management @@ -71,6 +74,11 @@ https://youtrack.joethei.xyz/issues/SPM + + TeamCity + https://teamcity.joethei.xyz + + @@ -220,6 +228,10 @@ org.jacoco jacoco-maven-plugin 0.8.4 + + + + default-prepare-agent @@ -244,6 +256,16 @@ + + + + + org.sonarsource.scanner.maven + sonar-maven-plugin + 3.6.0.1398 + + + diff --git a/src/main/java/de/hsel/spm/baudas/analysis/Cluster.java b/src/main/java/de/hsel/spm/baudas/analysis/Cluster.java index f98989c..d8cd1bd 100644 --- a/src/main/java/de/hsel/spm/baudas/analysis/Cluster.java +++ b/src/main/java/de/hsel/spm/baudas/analysis/Cluster.java @@ -15,6 +15,7 @@ import java.util.Map; * * @author Johannes Theiner * @version 0.1 + * @since 0.4 */ public class Cluster implements Analysis>> { @@ -26,7 +27,7 @@ public class Cluster implements Analysis>> { } /** - * get result of cluster analysis. + * get result of cluster analysis, cluster 0 is the average. * * @return Result */ diff --git a/src/main/java/de/hsel/spm/baudas/analysis/DayHour.java b/src/main/java/de/hsel/spm/baudas/analysis/DayHour.java deleted file mode 100644 index f2a223d..0000000 --- a/src/main/java/de/hsel/spm/baudas/analysis/DayHour.java +++ /dev/null @@ -1,22 +0,0 @@ -package de.hsel.spm.baudas.analysis; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.EqualsAndHashCode; - -/** - * object to better handle day, hour combinations. - * - * @author Johannes Theiner - * @version 0.1 - * @since 0.1 - **/ - -@Data -@EqualsAndHashCode -@AllArgsConstructor -public class DayHour { - - private String day; - private String hour; -} \ No newline at end of file diff --git a/src/main/java/de/hsel/spm/baudas/analysis/ShoppingCart.java b/src/main/java/de/hsel/spm/baudas/analysis/ShoppingCart.java index 6e5b443..edac14f 100644 --- a/src/main/java/de/hsel/spm/baudas/analysis/ShoppingCart.java +++ b/src/main/java/de/hsel/spm/baudas/analysis/ShoppingCart.java @@ -15,10 +15,10 @@ import java.util.List; import java.util.Map; /** - * The shopping-cart Analysis. + * The shopping-cart analysis. * * @author Julian Hinxlage - * @version 0.1 + * @version 0.4 */ public class ShoppingCart implements Analysis, List>> { @@ -37,7 +37,7 @@ public class ShoppingCart implements Analysis, List>> { instances.deleteAttributeAt(0); } - //alle artikel anzahlen auf 0 oder 1 setzen + //convert data to only contain bought/not bought NumericCleaner nc = new NumericCleaner(); nc.setMaxThreshold(1.0); nc.setMaxDefault(1.0); @@ -48,7 +48,7 @@ public class ShoppingCart implements Analysis, List>> { e.printStackTrace(); } - //zahl werte zu nomial werten umwandeln + NumericToNominal num2nom = new NumericToNominal(); num2nom.setAttributeIndices("first-last"); try { @@ -70,19 +70,18 @@ public class ShoppingCart implements Analysis, List>> { for (int i = 0; i < model.getAssociationRules().getRules().size(); i++) { AssociationRule rule = model.getAssociationRules().getRules().get(i); - List l1 = new ArrayList<>(); + List premises = new ArrayList<>(); for (Item item : rule.getPremise()) { - l1.add(item.getAttribute().name()); + premises.add(item.getAttribute().name()); } - List l2 = new ArrayList<>(); + List consequences = new ArrayList<>(); for (Item item : rule.getConsequence()) { - l2.add(item.getAttribute().name()); + consequences.add(item.getAttribute().name()); } - result.put(l1, l2); + result.put(premises, consequences); } - return result; } diff --git a/src/main/java/de/hsel/spm/baudas/analysis/ShoppingTimes.java b/src/main/java/de/hsel/spm/baudas/analysis/ShoppingTimes.java index ed99ee2..26810ba 100644 --- a/src/main/java/de/hsel/spm/baudas/analysis/ShoppingTimes.java +++ b/src/main/java/de/hsel/spm/baudas/analysis/ShoppingTimes.java @@ -4,20 +4,21 @@ import weka.core.Instance; import weka.core.Instances; import java.io.File; +import java.util.AbstractMap; import java.util.HashMap; import java.util.Map; /** - * Shopping Times Analysis. + * count customers at all times. * * @author Johannes Theiner * @version 0.1 * @since 0.1 **/ -public class ShoppingTimes implements Analysis> { +public class ShoppingTimes implements Analysis, Integer>> { private Instances instances; - private Map result; + private Map, Integer> result; public ShoppingTimes(File file) { instances = load(file); @@ -30,7 +31,7 @@ public class ShoppingTimes implements Analysis> { * @return Map of Day-Hour Combinations and the corresponding user count */ @Override - public Map getResult() { + public Map, Integer> getResult() { if (result != null) { return result; } @@ -38,7 +39,7 @@ public class ShoppingTimes implements Analysis> { result = new HashMap<>(); for (Instance instance : instances) { - DayHour dayHour = new DayHour(instance.stringValue(Attribute.SHOPPING_DAY), instance.stringValue(Attribute.SHOPPING_HOUR)); + Map.Entry dayHour = new AbstractMap.SimpleImmutableEntry<>(instance.stringValue(Attribute.SHOPPING_DAY), instance.stringValue(Attribute.SHOPPING_HOUR)); int tmp = 1; if (result.containsKey(dayHour)) tmp = result.get(dayHour) + 1; diff --git a/src/main/java/de/hsel/spm/baudas/analysis/TopFlopArticle.java b/src/main/java/de/hsel/spm/baudas/analysis/TopFlopArticle.java index 995379c..059532b 100644 --- a/src/main/java/de/hsel/spm/baudas/analysis/TopFlopArticle.java +++ b/src/main/java/de/hsel/spm/baudas/analysis/TopFlopArticle.java @@ -11,14 +11,12 @@ import java.util.stream.Collectors; import java.util.stream.Stream; /** - * get sum for every article and sort them ascending. + * get sum for every article bought and sort them in ascending order. * * @author Karsten Eden * @version 0.1 - * @since 0.1 + * @since 0.2 */ - - public class TopFlopArticle implements Analysis> { private Instances instances; diff --git a/src/main/java/de/hsel/spm/baudas/analysis/WeekOverview.java b/src/main/java/de/hsel/spm/baudas/analysis/WeekOverview.java index acb1f8d..c41d92a 100644 --- a/src/main/java/de/hsel/spm/baudas/analysis/WeekOverview.java +++ b/src/main/java/de/hsel/spm/baudas/analysis/WeekOverview.java @@ -9,7 +9,7 @@ import java.util.HashMap; import java.util.Map; /** - * Week WeekOverviewDiagram Analysis. + * generates a brief week overview. * * @author Julian Hinxlage * @version 0.1 @@ -28,7 +28,7 @@ public class WeekOverview implements Analysis> getResult() { @@ -45,13 +45,14 @@ public class WeekOverview implements Analysis(0.0, 0)); + } else { + result.put(day, + new AbstractMap.SimpleEntry<>( + result.get(day).getKey() + amount, + result.get(day).getValue() + 1 + ) + ); } - result.put(day, - new AbstractMap.SimpleEntry<>( - result.get(day).getKey() + amount, - result.get(day).getValue() + 1 - ) - ); } diff --git a/src/main/java/de/hsel/spm/baudas/web/ClusterDiagram.java b/src/main/java/de/hsel/spm/baudas/web/ClusterDiagram.java index 4da9a7f..a4ba39a 100644 --- a/src/main/java/de/hsel/spm/baudas/web/ClusterDiagram.java +++ b/src/main/java/de/hsel/spm/baudas/web/ClusterDiagram.java @@ -23,15 +23,23 @@ import java.util.*; **/ @WebServlet("/clusters") public class ClusterDiagram extends HttpServlet { + + private static Map> cache; + @Override protected void doGet(@NotNull HttpServletRequest req, @NotNull HttpServletResponse resp) throws IOException { req.setCharacterEncoding(StandardCharsets.UTF_8.name()); resp.setCharacterEncoding(StandardCharsets.UTF_8.name()); resp.setContentType("application/json"); PrintWriter out = resp.getWriter(); + Gson gson = new Gson(); + + if(cache != null) { + out.println(gson.toJson(cache)); + return; + } Map> result = new HashMap<>(); - Gson gson = new Gson(); if (req.getParameter("id") == null) { out.print(gson.toJson(result)); diff --git a/src/main/java/de/hsel/spm/baudas/web/Columns.java b/src/main/java/de/hsel/spm/baudas/web/Columns.java deleted file mode 100644 index 9b00650..0000000 --- a/src/main/java/de/hsel/spm/baudas/web/Columns.java +++ /dev/null @@ -1,11 +0,0 @@ -package de.hsel.spm.baudas.web; - -public class Columns { - private String col1; //NOPMD - private String col2; //NOPMD - - public Columns(String col1, String col2){ - this.col1 = col1; - this.col2 = col2; - } -} diff --git a/src/main/java/de/hsel/spm/baudas/web/ShoppingCartDiagram.java b/src/main/java/de/hsel/spm/baudas/web/ShoppingCartDiagram.java index 9e62281..c2413f6 100644 --- a/src/main/java/de/hsel/spm/baudas/web/ShoppingCartDiagram.java +++ b/src/main/java/de/hsel/spm/baudas/web/ShoppingCartDiagram.java @@ -26,17 +26,24 @@ public class ShoppingCartDiagram extends HttpServlet { private static final long serialVersionUID = 5026732432605473505L; + private static List> cache; + protected void doGet(@NotNull HttpServletRequest req, @NotNull HttpServletResponse resp) throws IOException { req.setCharacterEncoding(StandardCharsets.UTF_8.name()); resp.setCharacterEncoding(StandardCharsets.UTF_8.name()); resp.setContentType("application/json"); PrintWriter out = resp.getWriter(); - Gson gson = new Gson(); - List colList = new ArrayList<>(); + + if(cache != null) { + out.println(gson.toJson(cache)); + return; + } + + List> result = new ArrayList<>(); if (req.getParameter("id") == null) { - out.print(gson.toJson(colList)); + out.print(gson.toJson(result)); return; } @@ -44,21 +51,20 @@ public class ShoppingCartDiagram extends HttpServlet { File file = Data.get(uuid); ShoppingCart cart = new ShoppingCart(file); - Map, List> result = new HashMap<>(); - result = cart.getResult(); + Map, List> map = cart.getResult(); List col1 = new ArrayList<>(); List col2 = new ArrayList<>(); - for(Map.Entry, List> entry : result.entrySet()){ - col1.add(entry.getKey().toString()); - col2.add(entry.getValue().toString()); + for(Map.Entry, List> entry : map.entrySet()){ + col1.add(String.join(", ", entry.getKey())); + col2.add(String.join(", ", entry.getValue())); } for(int i = 0; i < col1.size(); i++ ){ - colList.add(new Columns(col1.get(i).replaceAll("\\[", "").replaceAll("\\]", ""), col2.get(i).replaceAll("\\[", "").replaceAll("\\]", ""))); + result.add(new AbstractMap.SimpleEntry<>(col1.get(i), col2.get(i))); } - out.print(gson.toJson(colList)); + out.print(gson.toJson(result)); } } diff --git a/src/main/java/de/hsel/spm/baudas/web/ShoppingTimesDiagram.java b/src/main/java/de/hsel/spm/baudas/web/ShoppingTimesDiagram.java index ed40db8..bbe011d 100644 --- a/src/main/java/de/hsel/spm/baudas/web/ShoppingTimesDiagram.java +++ b/src/main/java/de/hsel/spm/baudas/web/ShoppingTimesDiagram.java @@ -1,7 +1,6 @@ package de.hsel.spm.baudas.web; import com.google.gson.Gson; -import de.hsel.spm.baudas.analysis.DayHour; import de.hsel.spm.baudas.analysis.ShoppingTimes; import org.jetbrains.annotations.NotNull; @@ -13,16 +12,7 @@ import java.io.File; import java.io.IOException; import java.io.PrintWriter; import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Comparator; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeSet; -import java.util.UUID; +import java.util.*; import java.util.regex.Pattern; /** @@ -62,7 +52,7 @@ public class ShoppingTimesDiagram extends HttpServlet { UUID uuid = UUID.fromString(id); - if(cache.containsKey(uuid)) { + if (cache.containsKey(uuid)) { out.print(gson.toJson(cache.get(uuid))); return; } @@ -71,13 +61,13 @@ public class ShoppingTimesDiagram extends HttpServlet { File file = Data.get(uuid); ShoppingTimes shoppingTimes = new ShoppingTimes(file); - Map map = shoppingTimes.getResult(); + Map, Integer> map = shoppingTimes.getResult(); Set days = new TreeSet<>(); Set hours = new TreeSet<>(comparator); - for (DayHour dayHour : map.keySet()) { - days.add(dayHour.getDay()); - hours.add(dayHour.getHour()); + for (Map.Entry dayHour : map.keySet()) { + days.add(dayHour.getKey()); + hours.add(dayHour.getValue()); } result.put("labels", hours); @@ -86,8 +76,8 @@ public class ShoppingTimesDiagram extends HttpServlet { if (!result.containsKey(day)) result.put(day, new ArrayList<>()); for (String hour : hours) { - if (map.containsKey(new DayHour(day, hour))) { - result.get(day).add(map.get(new DayHour(day, hour)).toString()); + if (map.containsKey(new AbstractMap.SimpleEntry<>(day, hour))) { + result.get(day).add(map.get(new AbstractMap.SimpleEntry<>(day, hour)).toString()); } else result.get(day).add("0"); } } diff --git a/src/main/java/de/hsel/spm/baudas/web/TopFlopArticleDiagram.java b/src/main/java/de/hsel/spm/baudas/web/TopFlopArticleDiagram.java index 77d9a17..85a36f3 100644 --- a/src/main/java/de/hsel/spm/baudas/web/TopFlopArticleDiagram.java +++ b/src/main/java/de/hsel/spm/baudas/web/TopFlopArticleDiagram.java @@ -17,7 +17,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; -import java.util.*; import java.util.regex.Pattern; /** @@ -46,13 +45,13 @@ public class TopFlopArticleDiagram extends HttpServlet { String id = req.getParameter("id"); boolean match = Pattern.matches("[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}", id); - if(id == null || !match) { + if (id == null || !match) { return; } UUID uuid = UUID.fromString(id); - if(cache.containsKey(uuid)) { + if (cache.containsKey(uuid)) { out.println(gson.toJson(cache.get(uuid))); return; } diff --git a/src/main/webapp/head.jsp b/src/main/webapp/head.jsp index fab1aeb..3d556dd 100644 --- a/src/main/webapp/head.jsp +++ b/src/main/webapp/head.jsp @@ -18,4 +18,5 @@ - \ No newline at end of file + + \ No newline at end of file diff --git a/src/main/webapp/index.jsp b/src/main/webapp/index.jsp index 25064ff..739394e 100644 --- a/src/main/webapp/index.jsp +++ b/src/main/webapp/index.jsp @@ -23,7 +23,7 @@ -
+
@@ -75,122 +75,124 @@
+
+
- -
-
+ +
+
+
+ Warenkorbanalyse +
+
+ +
+
+
+
+
+ +
+
+
+
+
- Warenkorbanalyse + Werbung
-
- -
+
+

+ Werbung dient dazu, auf bestimmte Produkte, Angebote oder den Markt im + Allgemeinen aufmerksam zu machen. Sie kann über verschiedene Wege verbreitet + werden, etwa das Internet, Zeitungsannoncen oder auch per TV/Radio. + Im Gegensatz zu Rabatten (die zeitabhängig am besten funktionieren) ist Werbung + stark von der Zielgruppe abhängig. Insbesondere in der Kombination mit anderen + Marketingmaßnahmen kann sie so ihre volle Wirkung entfalten. +
+
+ Analysen, die für Werbung nützlich sein könnten: + Clusteranalyse, Wochenübersicht, Verkaufszahlen +

- - -
-
-
-
-
-
- Werbung -
-
-

- Werbung dient dazu, auf bestimmte Produkte, Angebote oder den Markt im - Allgemeinen aufmerksam zu machen. Sie kann über verschiedene Wege verbreitet - werden, etwa das Internet, Zeitungsannoncen oder auch per TV/Radio. - Im Gegensatz zu Rabatten (die zeitabhängig am besten funktionieren) ist Werbung - stark von der Zielgruppe abhängig. Insbesondere in der Kombination mit anderen - Marketingmaßnahmen kann sie so ihre volle Wirkung entfalten. -
-
- Analysen, die für Werbung nützlich sein könnten: - Clusteranalyse, Wochenübersicht, Verkaufszahlen -

-
-
-
+
+
+
+
+
+ Sortimentsveränderung
-
-
-
-
- Sortimentsveränderung -
-
-

- Gibt es eine Produktgruppe, die sich besonders gut verkauft, so sollte unter - Umständen über die Erweiterung des Sortiments innerhalb dieser Gruppe - nachgedacht werden. - Im Umkehrschluss dazu bietet sich an, schlecht verkaufte Produkte, welche keinen - hohen Gewinn abwerfen aus dem täglichen Verkaufsgeschäft wieder zu entfernen. - Dies verringert die Bildung von „Ladenhütern“ und schafft Platz für neue, sich - besser verkaufende Produkte. -
-
- Analysen, die bei der Sortimentswahl nützlich sein könnten: - Verkaufszahlen, Clusterübersicht -

-
-
-
-
-
-
-
-
-
-
- Rabatt -
-
-

- Rabatte können z.B. an Tagen angeboten werden, an denen nur wenige Kunden - erscheinen. Dadurch wird einerseits an dieses Tagen oder Uhrzeiten das - Kaufverhalten angeregt, als auch der Andrang an anderen reduziert. Dies dient - insbesondere der Entzerrung des zeitabhängigen Kaufverhaltens. - Des Weiteren können durch Rabatte weniger gut laufende Produkte in den - Vordergrund gerückt du vergünstigt angeboten werden. - Zusätzlich dazu können sich gut verkaufende Produkte mit einem (vermeintlich) - verringerten Preis versehen werden. Dies kann beim Kunden den „inneren - Schnäppchenjäger“ wecken und dafür sorgen, dass er sich dieses gute Angebot - nicht entgehen lassen kann. -
-
- Analysen, die zur Platzierung von Rabatten nützlich sein können: - Wochenübersicht, Einkaufszeiten, Verkaufszahlen -

-
-
-
-
-
-
-
-
- Produktplatzierung -
-
-

- Es gibt bestimmte Produkte, die werden häufig zusammen erworben. Sind diese - Produkte quer durch den Laden verstreut, so müssen die Kunden zusätzlich zu - ihren Wunschprodukten auch an anderen Auslagen vorbei und die Anzahl an - Spontankäufen eben jener weiteren Produkte steigt. -
-
- Analysen, die bei der Produktplatzierung hilfreich sein könnten: - Warenkorbsanalyse, Verkaufszahlen -

-
-
-
+
+

+ Gibt es eine Produktgruppe, die sich besonders gut verkauft, so sollte unter + Umständen über die Erweiterung des Sortiments innerhalb dieser Gruppe + nachgedacht werden. + Im Umkehrschluss dazu bietet sich an, schlecht verkaufte Produkte, welche keinen + hohen Gewinn abwerfen aus dem täglichen Verkaufsgeschäft wieder zu entfernen. + Dies verringert die Bildung von „Ladenhütern“ und schafft Platz für neue, sich + besser verkaufende Produkte. +
+
+ Analysen, die bei der Sortimentswahl nützlich sein könnten: + Verkaufszahlen, Clusterübersicht +

+
+
+
+
+
+
+
+ Rabatt +
+
+

+ Rabatte können z.B. an Tagen angeboten werden, an denen nur wenige Kunden + erscheinen. Dadurch wird einerseits an dieses Tagen oder Uhrzeiten das + Kaufverhalten angeregt, als auch der Andrang an anderen reduziert. Dies dient + insbesondere der Entzerrung des zeitabhängigen Kaufverhaltens. + Des Weiteren können durch Rabatte weniger gut laufende Produkte in den + Vordergrund gerückt du vergünstigt angeboten werden. + Zusätzlich dazu können sich gut verkaufende Produkte mit einem (vermeintlich) + verringerten Preis versehen werden. Dies kann beim Kunden den „inneren + Schnäppchenjäger“ wecken und dafür sorgen, dass er sich dieses gute Angebot + nicht entgehen lassen kann. +
+
+ Analysen, die zur Platzierung von Rabatten nützlich sein können: + Wochenübersicht, Einkaufszeiten, Verkaufszahlen +

+
+
+
+
+
+
+
+
+ Produktplatzierung +
+
+

+ Es gibt bestimmte Produkte, die werden häufig zusammen erworben. Sind diese + Produkte quer durch den Laden verstreut, so müssen die Kunden zusätzlich zu + ihren Wunschprodukten auch an anderen Auslagen vorbei und die Anzahl an + Spontankäufen eben jener weiteren Produkte steigt. +
+
+ Analysen, die bei der Produktplatzierung hilfreich sein könnten: + Warenkorbsanalyse, Verkaufszahlen +

+
+
+
+
+
+
<%@include file="footer.jsp" %> \ No newline at end of file diff --git a/src/main/webapp/js/clusters.js b/src/main/webapp/js/clusters.js index f0dfd22..a255cc6 100644 --- a/src/main/webapp/js/clusters.js +++ b/src/main/webapp/js/clusters.js @@ -23,7 +23,7 @@ function drawClusterTable(){ row.append(""); for (x in cluster_result){ if(x == 0){ - row.append("" + "ø" + ""); + row.append("" + "Durchschnitt" + ""); }else{ row.append("" + x + ""); } diff --git a/src/main/webapp/js/shopping_cart.js b/src/main/webapp/js/shopping_cart.js index 8edb9c5..70b7bb5 100644 --- a/src/main/webapp/js/shopping_cart.js +++ b/src/main/webapp/js/shopping_cart.js @@ -27,8 +27,8 @@ function drawShoppingCartTable(){ row.append(""); for (x in shopping_cart_result){ row.append(""); - row.append("" + shopping_cart_result[x].col1 + ""); - row.append("" + shopping_cart_result[x].col2 + ""); + row.append("" + shopping_cart_result[x].key + ""); + row.append("" + shopping_cart_result[x].value + ""); row.append(""); } row.append(""); diff --git a/src/main/webapp/menu.jsp b/src/main/webapp/menu.jsp index 33b82d3..0d814c0 100644 --- a/src/main/webapp/menu.jsp +++ b/src/main/webapp/menu.jsp @@ -17,7 +17,7 @@