DataExtension API player page plugin tab generation

This commit is contained in:
Rsl1122 2019-03-24 12:28:13 +02:00
parent aab5436b25
commit 099330ebd7
14 changed files with 296 additions and 33 deletions

View File

@ -68,6 +68,11 @@ public class Icon {
this.color = color;
}
@Override
public String toString() {
return "Icon{" + type.name() + ", '" + name + '\'' + ", " + color.name() + '}';
}
public static class Builder {
private final Icon icon;

View File

@ -25,7 +25,7 @@ import java.util.List;
*
* @author Rsl1122
*/
public class ExtensionPlayerData {
public class ExtensionPlayerData implements Comparable<ExtensionPlayerData> {
private final int pluginID;
@ -47,10 +47,19 @@ public class ExtensionPlayerData {
return extensionInformation;
}
public boolean hasOnlyGenericTab() {
return tabs.size() == 1 && tabs.get(0).getTabInformation().getTabName().isEmpty();
}
public List<ExtensionTabData> getTabs() {
return tabs;
}
@Override
public int compareTo(ExtensionPlayerData o) {
return String.CASE_INSENSITIVE_ORDER.compare(this.extensionInformation.getPluginName(), o.extensionInformation.getPluginName());
}
public static class Factory {
private final ExtensionPlayerData data;

View File

@ -50,6 +50,10 @@ public class ExtensionTabData implements Comparable<ExtensionTabData> {
stringData = new HashMap<>();
}
public TabInformation getTabInformation() {
return tabInformation;
}
public List<String> getValueOrder() {
return order;
}

View File

@ -105,9 +105,9 @@ public class ExtensionPlayerDataQuery implements Query<Map<UUID, List<ExtensionP
"t1." + ExtensionTabTable.TAB_NAME + " as tab_name," +
"t1." + ExtensionTabTable.TAB_PRIORITY + " as tab_priority," +
"t1." + ExtensionTabTable.ELEMENT_ORDER + " as element_order," +
"i1." + ExtensionIconTable.ICON_NAME + " as plugin_icon_name," +
"i1." + ExtensionIconTable.FAMILY + " as plugin_icon_family," +
"i1." + ExtensionIconTable.COLOR + " as plugin_icon_color," +
"i1." + ExtensionIconTable.ICON_NAME + " as provider_icon_name," +
"i1." + ExtensionIconTable.FAMILY + " as provider_icon_family," +
"i1." + ExtensionIconTable.COLOR + " as provider_icon_color," +
"i2." + ExtensionIconTable.ICON_NAME + " as tab_icon_name," +
"i2." + ExtensionIconTable.FAMILY + " as tab_icon_family," +
"i2." + ExtensionIconTable.COLOR + " as tab_icon_color" +
@ -204,9 +204,9 @@ public class ExtensionPlayerDataQuery implements Query<Map<UUID, List<ExtensionP
String description = set.getString(ExtensionProviderTable.DESCRIPTION);
int priority = set.getInt("provider_priority");
String iconName = set.getString("plugin_icon_name");
Family family = Family.getByName("plugin_icon_family").orElse(Family.SOLID);
Color color = Color.getByName("plugin_icon_color").orElse(Color.NONE);
String iconName = set.getString("provider_icon_name");
Family family = Family.getByName(set.getString("provider_icon_family")).orElse(Family.SOLID);
Color color = Color.getByName(set.getString("provider_icon_color")).orElse(Color.NONE);
Icon icon = new Icon(family, iconName, color);
return new ExtensionDescriptive(name, text, description, icon, priority);

View File

@ -74,7 +74,7 @@ public class CacheInspectPluginsTabRequest extends InfoRequestWithVariables impl
InspectPagePluginsContent pluginsTab = getPluginsTab(uuid);
pluginsTab.addTab(serverUUID, nav, Base64Util.decode(html));
pluginsTab.addTab(nav, Base64Util.decode(html));
return DefaultResponses.SUCCESS.get();
}
@ -84,6 +84,6 @@ public class CacheInspectPluginsTabRequest extends InfoRequestWithVariables impl
@Override
public void runLocally() {
getPluginsTab(player).addTab(serverInfo.getServerUUID(), variables.get("nav"), html);
getPluginsTab(player).addTab(variables.get("nav"), html);
}
}

View File

@ -55,6 +55,10 @@ public class Server implements Comparable<Server> {
return name;
}
public String getIdentifiableName() {
return !"Plan".equalsIgnoreCase(name) ? name : "Server " + id;
}
public void setName(String name) {
this.name = name;
}

View File

@ -21,10 +21,7 @@ import com.djrapitops.plan.system.webserver.cache.ResponseCache;
import com.djrapitops.plan.system.webserver.response.pages.parts.InspectPagePluginsContent;
import org.apache.commons.text.StringSubstitutor;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import java.util.*;
/**
* @author Rsl1122
@ -42,11 +39,12 @@ public class InspectPageResponse extends PageResponse {
@Override
public String getContent() {
Map<String, String> replaceMap = new HashMap<>();
InspectPagePluginsContent pluginsTab = (InspectPagePluginsContent)
ResponseCache.loadResponse(PageId.PLAYER_PLUGINS_TAB.of(uuid));
String[] inspectPagePluginsTab = pluginsTab != null ? pluginsTab.getContents() : getCalculating();
replaceMap.put("navPluginsTabs", inspectPagePluginsTab[0]);
replaceMap.put("pluginsTabs", inspectPagePluginsTab[1]);
// PluginData compatibility
Optional<String[]> pluginsTab = Optional.ofNullable((InspectPagePluginsContent) ResponseCache.loadResponse(PageId.PLAYER_PLUGINS_TAB.of(uuid)))
.map(InspectPagePluginsContent::getContents);
replaceMap.put("navPluginsTabs", pluginsTab.map(nav -> nav[0]).orElse(""));
replaceMap.put("pluginsTabs", pluginsTab.map(tab -> tab[1]).orElse(""));
return StringSubstitutor.replace(super.getContent(), replaceMap);
}

View File

@ -39,15 +39,15 @@ import java.util.*;
public class InspectPagePluginsContent extends PageResponse {
// ServerUUID, {nav, html}
private final Map<UUID, String[]> pluginsTab;
private final Map<String, String[]> pluginsTab;
public InspectPagePluginsContent() {
pluginsTab = new HashMap<>();
}
public InspectPagePluginsContent(UUID serverUUID, String nav, String html) {
public InspectPagePluginsContent(String nav, String html) {
pluginsTab = new HashMap<>();
addTab(serverUUID, nav, html);
addTab(nav, html);
}
public static InspectPagePluginsContent generateForThisServer(UUID playerUUID, ServerInfo serverInfo, HookHandler hookHandler) {
@ -56,16 +56,16 @@ public class InspectPagePluginsContent extends PageResponse {
Map<PluginData, InspectContainer> containers = hookHandler.getInspectContainersFor(playerUUID);
if (containers.isEmpty()) {
return new InspectPagePluginsContent(playerUUID, "<li><a>" + actualServerName + " (No Data)</a></li>",
return new InspectPagePluginsContent("<li><a>" + actualServerName + " (No Data)</a></li>",
"<div class=\"tab\"><div class=\"row clearfix\">" +
"<div class=\"col-md-12\">" + Html.CARD.parse("<p>No Data (" + actualServerName + ")</p>") +
"</div></div></div>");
}
String nav = "<li><a class=\"nav-button\" href=\"javascript:void(0)\">" + actualServerName + "</a></li>";
String nav = "<li><a class=\"nav-button\" href=\"javascript:void(0)\">" + actualServerName + " (Legacy)</a></li>";
String tab = createTab(containers);
return new InspectPagePluginsContent(serverInfo.getServerUUID(), nav, tab);
return new InspectPagePluginsContent(nav, tab);
}
private static String createTab(Map<PluginData, InspectContainer> containers) {
@ -84,8 +84,8 @@ public class InspectPagePluginsContent extends PageResponse {
return tab.toString();
}
public void addTab(UUID serverUUID, String nav, String html) {
pluginsTab.put(serverUUID, new String[]{nav, html});
public void addTab(String nav, String html) {
pluginsTab.put(nav, new String[]{nav, html});
}
public void addTab(InspectPagePluginsContent content) {

View File

@ -16,6 +16,8 @@
*/
package com.djrapitops.plan.utilities.html.icon;
import java.util.Optional;
public enum Color {
RED("col-red"),
PINK("col-pink"),
@ -55,6 +57,14 @@ public enum Color {
return Color.BLACK;
}
public static Optional<Color> getByName(String name) {
try {
return Optional.of(valueOf(name));
} catch (IllegalArgumentException e) {
return Optional.empty();
}
}
public String getHtmlClass() {
return htmlClass;
}

View File

@ -16,6 +16,8 @@
*/
package com.djrapitops.plan.utilities.html.icon;
import java.util.Optional;
public enum Family {
SOLID(" fa fa-", "\"></i>"),
REGULAR(" far fa-", "\"></i>"),
@ -33,4 +35,12 @@ public enum Family {
public String appendAround(String color, String name) {
return "<i class=\"" + color + middle + name + suffix;
}
public static Optional<Family> getByName(String name) {
try {
return Optional.of(valueOf(name));
} catch (IllegalArgumentException e) {
return Optional.empty();
}
}
}

View File

@ -29,6 +29,14 @@ public class Icon {
color = Color.NONE;
}
public static Icon fromExtensionIcon(com.djrapitops.plan.extension.icon.Icon icon) {
return new Icon(
Family.getByName(icon.getFamily().name()).orElse(Family.SOLID),
icon.getName(),
Color.getByName(icon.getColor().name()).orElse(Color.NONE)
);
}
public Icon(Family type, String name, Color color) {
this.type = type;
this.name = name;

View File

@ -33,6 +33,9 @@ import com.djrapitops.plan.system.settings.paths.TimeSettings;
import com.djrapitops.plan.system.settings.theme.Theme;
import com.djrapitops.plan.system.settings.theme.ThemeVal;
import com.djrapitops.plan.system.update.VersionCheckSystem;
import com.djrapitops.plan.system.webserver.cache.PageId;
import com.djrapitops.plan.system.webserver.cache.ResponseCache;
import com.djrapitops.plan.system.webserver.response.pages.parts.InspectPagePluginsContent;
import com.djrapitops.plan.utilities.comparators.SessionStartComparator;
import com.djrapitops.plan.utilities.formatting.Formatter;
import com.djrapitops.plan.utilities.formatting.Formatters;
@ -67,6 +70,7 @@ public class InspectPage implements Page {
private final PlanFiles files;
private final PlanConfig config;
private final PageFactory pageFactory;
private final Theme theme;
private final Graphs graphs;
private final HtmlTables tables;
@ -85,6 +89,7 @@ public class InspectPage implements Page {
VersionCheckSystem versionCheckSystem,
PlanFiles files,
PlanConfig config,
PageFactory pageFactory,
Theme theme,
Graphs graphs,
HtmlTables tables,
@ -98,6 +103,7 @@ public class InspectPage implements Page {
this.versionCheckSystem = versionCheckSystem;
this.files = files;
this.config = config;
this.pageFactory = pageFactory;
this.theme = theme;
this.graphs = graphs;
this.tables = tables;
@ -131,7 +137,7 @@ public class InspectPage implements Page {
public String parse(PlayerContainer player, UUID serverUUID, Map<UUID, String> serverNames) throws IOException {
long now = System.currentTimeMillis();
UUID uuid = player.getUnsafe(PlayerKeys.UUID);
UUID playerUUID = player.getUnsafe(PlayerKeys.UUID);
PlaceholderReplacer replacer = new PlaceholderReplacer();
@ -142,7 +148,7 @@ public class InspectPage implements Page {
replacer.put("timeZone", config.getTimeZoneOffsetHours());
boolean online = false;
Optional<Session> activeSession = SessionCache.getCachedSession(uuid);
Optional<Session> activeSession = SessionCache.getCachedSession(playerUUID);
if (activeSession.isPresent()) {
Session session = activeSession.get();
session.setSessionID(Integer.MAX_VALUE);
@ -259,6 +265,12 @@ public class InspectPage implements Page {
replacer.put("backButton", "<li><a title=\"to Server page\" href=\"/server\"><i class=\"material-icons\">arrow_back</i><i class=\"material-icons\">storage</i></a></li>");
}
InspectPluginTab pluginTabs = pageFactory.inspectPluginTabs(playerUUID);
// Legacy PluginData support until moved to database.
InspectPagePluginsContent pluginsTab = (InspectPagePluginsContent) ResponseCache.loadResponse(PageId.PLAYER_PLUGINS_TAB.of(playerUUID), InspectPagePluginsContent::new);
pluginsTab.addTab(new InspectPagePluginsContent(pluginTabs.getNav(), pluginTabs.getTab()));
return replacer.apply(files.readCustomizableResourceFlat("web/player.html"));
}

View File

@ -0,0 +1,168 @@
/*
* This file is part of Player Analytics (Plan).
*
* Plan is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License v3 as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Plan is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Plan. If not, see <https://www.gnu.org/licenses/>.
*/
package com.djrapitops.plan.utilities.html.pages;
import com.djrapitops.plan.extension.FormatType;
import com.djrapitops.plan.extension.implementation.TabInformation;
import com.djrapitops.plan.extension.implementation.results.player.ExtensionDescriptive;
import com.djrapitops.plan.extension.implementation.results.player.ExtensionInformation;
import com.djrapitops.plan.extension.implementation.results.player.ExtensionPlayerData;
import com.djrapitops.plan.extension.implementation.results.player.ExtensionTabData;
import com.djrapitops.plan.utilities.formatting.Formatter;
import com.djrapitops.plan.utilities.formatting.Formatters;
import com.djrapitops.plan.utilities.html.Html;
import com.djrapitops.plan.utilities.html.icon.Icon;
import com.djrapitops.plan.utilities.html.structure.TabsElement;
import java.util.*;
/**
* Responsible for generating /player page plugin tabs based on DataExtension API data.
*
* @author Rsl1122
*/
public class InspectPluginTab implements Comparable<InspectPluginTab> {
private String serverName;
private List<ExtensionPlayerData> data;
private Map<FormatType, Formatter<Long>> numberFormatters;
private Formatter<Double> decimalFormatter;
private Formatter<Double> percentageFormatter;
private String nav;
private String tab;
public InspectPluginTab(String nav, String tab) {
this.nav = nav;
this.tab = tab;
}
public InspectPluginTab(
String serverName,
List<ExtensionPlayerData> data,
Formatters formatters
) {
this.serverName = serverName;
this.data = data;
numberFormatters = new EnumMap<>(FormatType.class);
numberFormatters.put(FormatType.DATE_SECOND, formatters.secondLong());
numberFormatters.put(FormatType.DATE_YEAR, formatters.yearLong());
numberFormatters.put(FormatType.TIME_MILLISECONDS, formatters.timeAmount());
numberFormatters.put(FormatType.NONE, Object::toString);
this.decimalFormatter = formatters.decimals();
this.percentageFormatter = formatters.percentage();
generate();
}
public String getNav() {
return nav;
}
public String getTab() {
return tab;
}
private void generate() {
if (data.isEmpty()) {
nav = "<li><a class=\"nav-button\" href=\"javascript:void(0)\">" + serverName + " (No Data)</a></li>";
tab = "<div class=\"tab\"><div class=\"row clearfix\">" +
"<div class=\"col-md-12\">" + Html.CARD.parse("<p>No Data (" + serverName + ")</p>") +
"</div></div></div>";
} else {
nav = "<li><a class=\"nav-button\" href=\"javascript:void(0)\">" + serverName + "</a></li>";
tab = generatePageTab();
}
}
private String generatePageTab() {
Collections.sort(data);
StringBuilder tabBuilder = new StringBuilder();
for (ExtensionPlayerData datum : data) {
ExtensionInformation extensionInformation = datum.getExtensionInformation();
boolean onlyGeneric = datum.hasOnlyGenericTab();
String tabsElement;
if (onlyGeneric) {
ExtensionTabData genericTabData = datum.getTabs().get(0);
tabsElement = Html.BODY.parse(parseDataHtml(genericTabData));
} else {
tabsElement = new TabsElement(
datum.getTabs().stream().map(this::wrapToTabElementTab).toArray(TabsElement.Tab[]::new)
).toHtmlFull();
}
tabBuilder.append(wrapInContainer(extensionInformation, tabsElement));
}
return wrapInTab(tabBuilder.toString());
}
private String wrapInTab(String content) {
return "<div class=\"tab\"><div class=\"row clearfix\">" + content + "</div></div>";
}
private TabsElement.Tab wrapToTabElementTab(ExtensionTabData tabData) {
TabInformation tabInformation = tabData.getTabInformation();
return new TabsElement.Tab(tabInformation.getTabName(), parseDataHtml(tabData));
}
private String parseDataHtml(ExtensionTabData tabData) {
StringBuilder builder = new StringBuilder();
for (String key : tabData.getValueOrder()) {
tabData.getBoolean(key).ifPresent(data -> append(builder, data.getDescriptive(), data.getFormattedValue()));
tabData.getDouble(key).ifPresent(data -> append(builder, data.getDescriptive(), data.getFormattedValue(decimalFormatter)));
tabData.getPercentage(key).ifPresent(data -> append(builder, data.getDescriptive(), data.getFormattedValue(percentageFormatter)));
tabData.getNumber(key).ifPresent(data -> append(builder, data.getDescriptive(), data.getFormattedValue(numberFormatters.get(data.getFormatType()))));
tabData.getString(key).ifPresent(data -> append(builder, data.getDescriptive(), data.getFormattedValue()));
}
return builder.toString();
}
private void append(StringBuilder builder, ExtensionDescriptive descriptive, String formattedValue) {
Optional<String> description = descriptive.getDescription();
if (description.isPresent()) {
builder.append("<p title=\"").append(description.get()).append("\">");
} else {
builder.append("<p>");
}
builder.append(Icon.fromExtensionIcon(descriptive.getIcon()))
.append(' ').append(descriptive.getText()).append(": ").append(formattedValue).append("</p>");
}
private String wrapInContainer(ExtensionInformation information, String tabsElement) {
return "<div class=\"col-xs-12 col-sm-12 col-md-4 col-lg-4\"><div class=\"card\">" +
"<div class=\"header\">" +
"<h2>" + Icon.fromExtensionIcon(information.getIcon()) + ' ' + information.getPluginName() + "</h2>" +
"</div>" +
tabsElement +
"</div></div>";
}
@Override
public int compareTo(InspectPluginTab other) {
return String.CASE_INSENSITIVE_ORDER.compare(this.serverName, other.serverName);
}
}

View File

@ -23,9 +23,12 @@ import com.djrapitops.plan.data.store.containers.PlayerContainer;
import com.djrapitops.plan.db.Database;
import com.djrapitops.plan.db.access.queries.containers.ContainerFetchQueries;
import com.djrapitops.plan.db.access.queries.objects.ServerQueries;
import com.djrapitops.plan.extension.implementation.results.player.ExtensionPlayerData;
import com.djrapitops.plan.extension.implementation.storage.queries.ExtensionPlayerDataQuery;
import com.djrapitops.plan.system.database.DBSystem;
import com.djrapitops.plan.system.file.PlanFiles;
import com.djrapitops.plan.system.info.connection.ConnectionSystem;
import com.djrapitops.plan.system.info.server.Server;
import com.djrapitops.plan.system.info.server.ServerInfo;
import com.djrapitops.plan.system.settings.config.PlanConfig;
import com.djrapitops.plan.system.settings.theme.Theme;
@ -43,8 +46,7 @@ import dagger.Lazy;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.Map;
import java.util.UUID;
import java.util.*;
/**
* Factory for creating different {@link Page} objects.
@ -130,19 +132,52 @@ public class PageFactory {
return new AnalysisPage(analysisContainer, connectionSystem.get(), versionCheckSystem.get(), fileSystem.get(), formatters.get().decimals(), timings.get());
}
public InspectPage inspectPage(UUID uuid) {
public InspectPage inspectPage(UUID playerUUID) {
Database db = dbSystem.get().getDatabase();
PlayerContainer player = db.query(ContainerFetchQueries.fetchPlayerContainer(uuid));
PlayerContainer player = db.query(ContainerFetchQueries.fetchPlayerContainer(playerUUID));
Map<UUID, String> serverNames = db.query(ServerQueries.fetchServerNames());
return new InspectPage(
player, serverNames,
versionCheckSystem.get(),
fileSystem.get(), config.get(), theme.get(),
fileSystem.get(), config.get(), this, theme.get(),
graphs.get(), tables.get(), accordions.get(), formatters.get(),
serverInfo.get(), timings.get()
);
}
public InspectPluginTab inspectPluginTabs(UUID playerUUID) {
Database database = dbSystem.get().getDatabase();
Map<UUID, List<ExtensionPlayerData>> extensionPlayerData = database.query(new ExtensionPlayerDataQuery(playerUUID));
if (extensionPlayerData.isEmpty()) {
return new InspectPluginTab("No Extensions", Collections.emptyList(), formatters.get());
}
List<InspectPluginTab> inspectPluginTabs = new ArrayList<>();
for (Map.Entry<UUID, Server> entry : database.query(ServerQueries.fetchPlanServerInformation()).entrySet()) {
UUID serverUUID = entry.getKey();
String serverName = entry.getValue().getIdentifiableName();
List<ExtensionPlayerData> ofServer = extensionPlayerData.get(serverUUID);
if (ofServer == null) {
continue;
}
inspectPluginTabs.add(new InspectPluginTab(serverName, ofServer, formatters.get()));
}
StringBuilder navs = new StringBuilder();
StringBuilder tabs = new StringBuilder();
inspectPluginTabs.stream().sorted().forEach(tab -> {
navs.append(tab.getNav());
tabs.append(tab.getTab());
});
return new InspectPluginTab(navs.toString(), tabs.toString());
}
@Deprecated
public InspectPagePluginsContent inspectPagePluginsContent(UUID playerUUID) {
return InspectPagePluginsContent.generateForThisServer(playerUUID, serverInfo.get(), hookHandler.get());