Refactored ServerAccordion

This commit is contained in:
Rsl1122 2018-02-23 11:36:06 +02:00
parent aaf1d8a28c
commit 2cd3851979
6 changed files with 329 additions and 129 deletions

View File

@ -28,7 +28,7 @@ import com.djrapitops.plan.utilities.html.HtmlUtils;
import com.djrapitops.plan.utilities.html.graphs.PunchCardGraph;
import com.djrapitops.plan.utilities.html.graphs.pie.ServerPreferencePie;
import com.djrapitops.plan.utilities.html.graphs.pie.WorldPie;
import com.djrapitops.plan.utilities.html.structure.ServerAccordionCreator;
import com.djrapitops.plan.utilities.html.structure.ServerAccordion;
import com.djrapitops.plan.utilities.html.tables.ActionsTable;
import com.djrapitops.plan.utilities.html.tables.GeoInfoTable;
import com.djrapitops.plan.utilities.html.tables.NicknameTable;
@ -123,10 +123,12 @@ public class InspectPage extends Page {
.collect(Collectors.toList());
String[] sessionsAccordion = HtmlStructure.createSessionsTabContentInspectPage(sessionsByServerName, allSessions, uuid);
String[] serverAccordion = ServerAccordionCreator.createAccordion(profile, serverNames);
ServerAccordion serverAccordion = new ServerAccordion(profile, serverNames);
addValue("accordionSessions", sessionsAccordion[0]);
addValue("accordionServers", serverAccordion[0]);
addValue("sessionTabGraphViewFunctions", sessionsAccordion[1] + serverAccordion[1]);
addValue("accordionServers", serverAccordion.toHtml());
addValue("sessionTabGraphViewFunctions", sessionsAccordion[1] + serverAccordion.toViewScript());
long dayAgo = now - TimeAmount.DAY.ms();
long weekAgo = now - TimeAmount.WEEK.ms();

View File

@ -0,0 +1,56 @@
/*
* Licence is provided in the jar as license.yml also here:
* https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/license.yml
*/
package com.djrapitops.plan.utilities.html.structure;
import com.djrapitops.plugin.utilities.Format;
import java.util.ArrayList;
import java.util.List;
/**
* Utility for creating html accordions.
*
* @author Rsl1122
*/
public class AbstractAccordion {
private final String id;
private final List<AccordionElement> elements;
private String emptyText = "No Data";
public AbstractAccordion(String id) {
this.id = new Format(id)
.removeSymbols()
.removeWhitespace()
.toString();
elements = new ArrayList<>();
}
public String toHtml() {
StringBuilder html = new StringBuilder();
html.append("<div class=\"panel-group scrollbar\" id=\"").append(id).append("\" role=\"tablist\" aria-multiselectable=\"true\">");
if (elements.isEmpty()) {
return "<div class=\"body\"><p>" + emptyText + "</p></div>";
} else {
for (AccordionElement element : elements) {
html.append(element.toHtml());
}
}
return html.append("</div>").toString(); // Close panel-group scrollbar
}
public void addElement(AccordionElement element) {
element.setParentId(id);
elements.add(element);
}
protected void setEmptyText(String text) {
emptyText = text;
}
}

View File

@ -0,0 +1,103 @@
/*
* Licence is provided in the jar as license.yml also here:
* https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/license.yml
*/
package com.djrapitops.plan.utilities.html.structure;
import com.djrapitops.plugin.utilities.Format;
import com.djrapitops.plugin.utilities.Verify;
/**
* Utility for creating html accordion elements.
*
* @author Rsl1122
*/
public class AccordionElement {
private final String id;
private final String title;
private String color;
private String parentId;
private String leftSide;
private String rightSide;
public AccordionElement(String id, String title) {
this.id = new Format(id)
.removeSymbols()
.removeWhitespace()
.toString();
this.title = title;
}
public void setParentId(String parentId) {
this.parentId = parentId;
}
public AccordionElement setColor(String color) {
this.color = color;
return this;
}
public AccordionElement setLeftSide(String leftSide) {
this.leftSide = leftSide;
return this;
}
public AccordionElement setRightSide(String rightSide) {
this.rightSide = rightSide;
return this;
}
public String toHtml() {
Verify.nullCheck(parentId, () -> new IllegalStateException("Parent ID not specified"));
StringBuilder html = new StringBuilder();
appendPanelHeading(html);
appendLeftContent(html);
appendRightContent(html);
// Finalize content
html.append("</div>") // Closes row clearfix
.append("</div>") // Closes panel-body
.append("</div>") // Closes panel-collapse
.append("</div>"); // Closes panel
return html.toString();
}
private void appendRightContent(StringBuilder html) {
if (rightSide != null) {
html.append("<div class=\"col-xs-12 col-sm-6 col-md-6 col-lg-6\">") // Right col-6
.append(rightSide)
.append("</div>"); // Right col-6
}
}
private void appendLeftContent(StringBuilder html) {
Verify.nullCheck(leftSide, () -> new IllegalStateException("No Content specified"));
html.append("<div id=\"").append(id).append("\" class=\"panel-collapse collapse\" role=\"tabpanel\"")
.append(" aria-labelledby=\"heading_").append(id).append("\">")
.append("<div class=\"panel-body\"><div class=\"row clearfix\">")
.append("<div class=\"col-xs-12 col-sm-6 col-md-6 col-lg-6\">") // Left col-6
.append(leftSide)
.append("</div>"); // Closes Left col-6
}
private void appendPanelHeading(StringBuilder html) {
html.append("<div class=\"panel");
if (color != null) {
html.append(" panel-col-").append(color);
}
html.append("\">")
.append("<div class=\"panel-heading\" role=\"tab\" id=\"heading_").append(id).append("\">")
.append("<h4 class=\"panel-title\">")
.append("<a class=\"collapsed\" role=\"button\" data-toggle=\"collapse\" data-parent=\"#")
.append(parentId).append("\" ")
.append("href=\"#").append(id).append("\" aria-expanded=\"false\" ")
.append("aria-controls=\"").append(id).append("\">")
.append(title) // Title (header)
.append("</a></h4>") // Closes collapsed & panel title
.append("</div>"); // Closes panel heading
}
}

View File

@ -0,0 +1,52 @@
/*
* Licence is provided in the jar as license.yml also here:
* https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/license.yml
*/
package com.djrapitops.plan.utilities.html.structure;
import java.io.Serializable;
/**
* Utility for filling AccordionElements.
*
* @author Rsl1122
* @see AccordionElement
*/
public class AccordionElementContentBuilder {
private StringBuilder html;
public AccordionElementContentBuilder() {
this.html = new StringBuilder();
}
public AccordionElementContentBuilder addRowBold(String color, String icon, String text, Serializable value) {
html.append("<p><i class=\"col-")
.append(color).append(" fa fa-").append(icon)
.append("\"></i> ").append(text);
html.append("<span class=\"pull-right\"><b>").append(value).append("</b></span></p>");
return this;
}
public AccordionElementContentBuilder addRow(String color, String icon, String text, Serializable value) {
html.append("<p><i class=\"col-")
.append(color).append(" fa fa-").append(icon)
.append("\"></i> ").append(text);
html.append("<span class=\"pull-right\">").append(value).append("</span></p>");
return this;
}
public AccordionElementContentBuilder addHtml(String html) {
this.html.append(html);
return this;
}
public String toHtml() {
return html.toString();
}
public AccordionElementContentBuilder addBreak() {
html.append("<br>");
return this;
}
}

View File

@ -0,0 +1,112 @@
/*
* Licence is provided in the jar as license.yml also here:
* https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/license.yml
*/
package com.djrapitops.plan.utilities.html.structure;
import com.djrapitops.plan.data.PlayerProfile;
import com.djrapitops.plan.data.container.Session;
import com.djrapitops.plan.data.time.WorldTimes;
import com.djrapitops.plan.system.settings.theme.Theme;
import com.djrapitops.plan.system.settings.theme.ThemeVal;
import com.djrapitops.plan.utilities.FormatUtils;
import com.djrapitops.plan.utilities.analysis.MathUtils;
import com.djrapitops.plan.utilities.html.graphs.pie.WorldPie;
import com.djrapitops.plugin.utilities.Format;
import java.util.List;
import java.util.Map;
import java.util.UUID;
/**
* HTML utility class for creating a Server Accordion.
*
* @author Rsl1122
*/
public class ServerAccordion extends AbstractAccordion {
private final StringBuilder viewScript;
public ServerAccordion(PlayerProfile profile, Map<UUID, String> serverNames) {
super("server_accordion");
viewScript = new StringBuilder();
Map<UUID, WorldTimes> worldTimesPerServer = profile.getWorldTimesPerServer();
if (worldTimesPerServer.isEmpty()) {
return;
}
addElements(profile, serverNames, worldTimesPerServer);
}
public String toViewScript() {
return viewScript.toString();
}
private void addElements(PlayerProfile profile, Map<UUID, String> serverNames, Map<UUID, WorldTimes> worldTimesPerServer) {
int i = 0;
for (Map.Entry<UUID, WorldTimes> entry : worldTimesPerServer.entrySet()) {
UUID serverUUID = entry.getKey();
String serverName = serverNames.getOrDefault(serverUUID, "Unknown");
WorldTimes worldTimes = entry.getValue();
List<Session> sessions = profile.getSessions(serverUUID);
long playtime = PlayerProfile.getPlaytime(sessions.stream());
int sessionCount = sessions.size();
long avgSession = MathUtils.averageLong(playtime, sessionCount);
long sessionMedian = PlayerProfile.getSessionMedian(sessions.stream());
long longestSession = PlayerProfile.getLongestSession(sessions.stream());
long mobKills = PlayerProfile.getMobKillCount(sessions.stream());
long playerKills = PlayerProfile.getPlayerKills(sessions.stream()).count();
long deaths = PlayerProfile.getDeathCount(sessions.stream());
String play = FormatUtils.formatTimeAmount(playtime);
String avg = sessionCount != 0 ? FormatUtils.formatTimeAmount(avgSession) : "-";
String median = sessionCount != 0 ? FormatUtils.formatTimeAmount(sessionMedian) : "-";
String longest = sessionCount != 0 ? FormatUtils.formatTimeAmount(longestSession) : "-";
String sanitizedServerName = new Format(serverName)
.removeSymbols()
.removeWhitespace().toString() + i;
String htmlID = "server_" + sanitizedServerName;
String worldId = "worldPieServer" + sanitizedServerName;
WorldPie worldPie = new WorldPie(worldTimes);
String title = serverName + "<span class=\"pull-right\">" + play + "</span>";
String leftSide = new AccordionElementContentBuilder()
.addRowBold("teal", "calendar-check-o", "Sessions", sessionCount)
.addRowBold("green", "clock-o", "Server Playtime", play)
.addRowBold("teal", "clock-o", "Longest Session", longest)
.addRowBold("teal", "clock-o", "Session Median", median)
.addBreak()
.addRowBold("red", "crosshairs", "Player Kills", playerKills)
.addRowBold("green", "crosshairs", "Mob Kills", mobKills)
.addRowBold("red", "frown-o", "Deaths", deaths)
.toHtml();
String rightSide = "<div id=\"" + worldId + "\" class=\"dashboard-donut-chart\"></div>" +
"<script>" +
"var " + worldId + "series = {name:'World Playtime',colorByPoint:true,data:" + worldPie.toHighChartsSeries() + "};" +
"var " + worldId + "gmseries = " + worldPie.toHighChartsDrilldown() + ";" +
"</script>";
addElement(new AccordionElement(htmlID, title)
.setColor(Theme.getValue(ThemeVal.PARSED_SERVER_ACCORDION))
.setLeftSide(leftSide)
.setRightSide(rightSide));
viewScript.append("worldPie(")
.append(worldId).append(", ")
.append(worldId).append("series, ")
.append(worldId).append("gmseries")
.append(");");
i++;
}
}
}

View File

@ -1,125 +0,0 @@
/*
* Licence is provided in the jar as license.yml also here:
* https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/license.yml
*/
package com.djrapitops.plan.utilities.html.structure;
import com.djrapitops.plan.data.PlayerProfile;
import com.djrapitops.plan.data.container.Session;
import com.djrapitops.plan.data.time.WorldTimes;
import com.djrapitops.plan.system.settings.theme.Theme;
import com.djrapitops.plan.system.settings.theme.ThemeVal;
import com.djrapitops.plan.utilities.FormatUtils;
import com.djrapitops.plan.utilities.analysis.MathUtils;
import com.djrapitops.plan.utilities.html.graphs.pie.WorldPie;
import com.djrapitops.plugin.utilities.Format;
import java.util.List;
import java.util.Map;
import java.util.UUID;
/**
* HTML utility class for creating a Server Accordion.
*
* @author Rsl1122
*/
public class ServerAccordionCreator {
public static String[] createAccordion(PlayerProfile profile, Map<UUID, String> serverNames) {
StringBuilder html = new StringBuilder("<div class=\"panel-group scrollbar\" id=\"session_accordion\" role=\"tablist\" aria-multiselectable=\"true\">");
StringBuilder viewScript = new StringBuilder();
Map<UUID, WorldTimes> worldTimesPerServer = profile.getWorldTimesPerServer();
if (worldTimesPerServer.isEmpty()) {
return new String[]{"<div class=\"body\">" +
"<p>No Sessions</p>" +
"</div>", ""};
}
int i = 0;
for (Map.Entry<UUID, WorldTimes> entry : worldTimesPerServer.entrySet()) {
UUID serverUUID = entry.getKey();
String serverName = serverNames.getOrDefault(serverUUID, "Unknown");
WorldTimes worldTimes = entry.getValue();
List<Session> sessions = profile.getSessions(serverUUID);
long playtime = PlayerProfile.getPlaytime(sessions.stream());
int sessionCount = sessions.size();
long avgSession = MathUtils.averageLong(playtime, sessionCount);
long sessionMedian = PlayerProfile.getSessionMedian(sessions.stream());
long longestSession = PlayerProfile.getLongestSession(sessions.stream());
long mobKills = PlayerProfile.getMobKillCount(sessions.stream());
long playerKills = PlayerProfile.getPlayerKills(sessions.stream()).count();
long deaths = PlayerProfile.getDeathCount(sessions.stream());
String play = FormatUtils.formatTimeAmount(playtime);
String avg = sessionCount != 0 ? FormatUtils.formatTimeAmount(avgSession) : "-";
String median = sessionCount != 0 ? FormatUtils.formatTimeAmount(sessionMedian) : "-";
String longest = sessionCount != 0 ? FormatUtils.formatTimeAmount(longestSession) : "-";
String sanitizedServerName = new Format(serverName)
.removeSymbols()
.removeWhitespace().toString() + i;
String htmlID = "server_" + sanitizedServerName;
String worldId = "worldPieServer" + sanitizedServerName;
WorldPie worldPie = new WorldPie(worldTimes);
// Accordion panel header
html.append("<div class=\"panel panel-col-").append(Theme.getValue(ThemeVal.PARSED_SERVER_ACCORDION)).append("\">")
.append("<div class=\"panel-heading\" role=\"tab\" id=\"heading_").append(htmlID).append("\">")
.append("<h4 class=\"panel-title\">")
.append("<a class=\"collapsed\" role=\"button\" data-toggle=\"collapse\" data-parent=\"#session_accordion\" ")
.append("href=\"#session_").append(htmlID).append("\" aria-expanded=\"false\" ")
.append("aria-controls=\"session_").append(htmlID).append("\">")
.append(serverName).append("<span class=\"pull-right\">").append(play).append("</span>") // Title (header)
.append("</a></h4>") // Closes collapsed, panel title
.append("</div>"); // Closes panel heading
// Content
html.append("<div id=\"session_").append(htmlID).append("\" class=\"panel-collapse collapse\" role=\"tabpanel\"")
.append(" aria-labelledby=\"heading_").append(htmlID).append("\">")
.append("<div class=\"panel-body\"><div class=\"row clearfix\">")
.append("<div class=\"col-xs-12 col-sm-6 col-md-6 col-lg-6\">") // Left col-6
// Sessions
.append("<p><i class=\"col-teal fa fa-calendar-check-o\"></i> Sessions <span class=\"pull-right\"><b>").append(sessionCount).append("</b></span></p>")
// Playtime
.append("<p><i class=\"col-green fa fa-clock-o\"></i> Server Playtime<span class=\"pull-right\"><b>").append(play).append("</b></span></p>")
.append("<p><i class=\"col-teal fa fa-clock-o\"></i> Longest Session<span class=\"pull-right\"><b>").append(longest).append("</b></span></p>")
.append("<p><i class=\"col-teal fa fa-clock-o\"></i> Session Median<span class=\"pull-right\"><b>").append(median).append("</b></span></p>")
.append("<br>")
// Player Kills
.append("<p><i class=\"col-red fa fa-crosshairs\"></i> Player Kills<span class=\"pull-right\"><b>").append(playerKills).append("</b></span></p>")
// Mob Kills
.append("<p><i class=\"col-green fa fa-crosshairs\"></i> Mob Kills<span class=\"pull-right\"><b>").append(mobKills).append("</b></span></p>")
// Deaths
.append("<p><i class=\"col-red fa fa-frown-o\"></i> Deaths<span class=\"pull-right\"><b>").append(deaths).append("</b></span></p>")
.append("</div>") // Closes Left col-6
.append("<div class=\"col-xs-12 col-sm-6 col-md-6 col-lg-6\">") // Right col-6
.append("<div id=\"").append(worldId).append("\" class=\"dashboard-donut-chart\"></div>")
// World Pie data script
.append("<script>")
.append("var ").append(worldId).append("series = {name:'World Playtime',colorByPoint:true,data:").append(worldPie.toHighChartsSeries()).append("};")
.append("var ").append(worldId).append("gmseries = ").append(worldPie.toHighChartsDrilldown()).append(";")
.append("</script>")
.append("</div>") // Right col-6
.append("</div>") // Closes row clearfix
.append("</div>") // Closes panel-body
.append("</div>") // Closes panel-collapse
.append("</div>"); // Closes panel
viewScript.append("worldPie(")
.append(worldId).append(", ")
.append(worldId).append("series, ")
.append(worldId).append("gmseries")
.append(");");
i++;
}
return new String[]{html.append("</div>").toString(), viewScript.toString()};
}
}