diff --git a/Plan/common/src/main/java/com/djrapitops/plan/data/store/containers/AnalysisContainer.java b/Plan/common/src/main/java/com/djrapitops/plan/data/store/containers/AnalysisContainer.java index 4b748462a..8106966b7 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/data/store/containers/AnalysisContainer.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/data/store/containers/AnalysisContainer.java @@ -37,6 +37,7 @@ import com.djrapitops.plan.utilities.html.graphs.bar.BarGraph; import com.djrapitops.plan.utilities.html.graphs.line.PingGraph; import com.djrapitops.plan.utilities.html.graphs.pie.WorldPie; import com.djrapitops.plan.utilities.html.graphs.stack.StackGraph; +import com.djrapitops.plan.utilities.html.pages.AnalysisPluginTabs; import com.djrapitops.plan.utilities.html.structure.Accordions; import com.djrapitops.plan.utilities.html.structure.AnalysisPluginsTabContentCreator; import com.djrapitops.plan.utilities.html.structure.RecentLoginList; @@ -488,13 +489,14 @@ public class AnalysisContainer extends DynamicDataContainer { private void addPluginSuppliers() { // TODO Refactor into a system that supports running the analysis on Bungee - Key navAndTabs = new Key<>(new Type() { - }, "NAV_AND_TABS"); + Key navAndTabs = new Key<>(new Type() {}, "NAV_AND_TABS"); + Key pluginTabs = new Key<>(AnalysisPluginTabs.class, "PLUGIN_TABS"); putCachingSupplier(navAndTabs, () -> pluginsTabContentCreator.createContent( this, getValue(AnalysisKeys.PLAYERS_MUTATOR).orElse(new PlayersMutator(new ArrayList<>())) )); - putSupplier(AnalysisKeys.PLUGINS_TAB_NAV, () -> getUnsafe(navAndTabs)[0]); - putSupplier(AnalysisKeys.PLUGINS_TAB, () -> getUnsafe(navAndTabs)[1]); + putCachingSupplier(pluginTabs, () -> new AnalysisPluginTabs(serverContainer.getValue(ServerKeys.EXTENSION_DATA).orElse(new ArrayList<>()), formatters)); + putSupplier(AnalysisKeys.PLUGINS_TAB_NAV, () -> getUnsafe(pluginTabs).getNav() + getUnsafe(navAndTabs)[0]); + putSupplier(AnalysisKeys.PLUGINS_TAB, () -> getUnsafe(pluginTabs).getTabs() + getUnsafe(navAndTabs)[1]); } @Singleton diff --git a/Plan/common/src/main/java/com/djrapitops/plan/data/store/keys/ServerKeys.java b/Plan/common/src/main/java/com/djrapitops/plan/data/store/keys/ServerKeys.java index e252fab20..40009c56f 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/data/store/keys/ServerKeys.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/data/store/keys/ServerKeys.java @@ -25,6 +25,7 @@ import com.djrapitops.plan.data.store.Type; import com.djrapitops.plan.data.store.containers.PlayerContainer; import com.djrapitops.plan.data.store.objects.DateObj; import com.djrapitops.plan.data.time.WorldTimes; +import com.djrapitops.plan.extension.implementation.results.server.ExtensionServerData; import java.util.List; import java.util.Map; @@ -63,4 +64,5 @@ public class ServerKeys { public static final Key> ALL_TIME_PEAK_PLAYERS = new Key<>(new Type>() {}, "all_time_peak_players"); public static final Key> RECENT_PEAK_PLAYERS = new Key<>(new Type>() {}, "recent_peak_players"); public static final Key> COMMAND_USAGE = new Key<>(new Type>() {}, "command_usage"); + public static final Key> EXTENSION_DATA = new Key<>(new Type>() {}, "extension_data"); } \ No newline at end of file diff --git a/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/containers/ServerContainerQuery.java b/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/containers/ServerContainerQuery.java index ec377ab3f..af0620bb8 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/containers/ServerContainerQuery.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/db/access/queries/containers/ServerContainerQuery.java @@ -27,6 +27,7 @@ import com.djrapitops.plan.db.access.queries.ServerAggregateQueries; import com.djrapitops.plan.db.access.queries.objects.ServerQueries; import com.djrapitops.plan.db.access.queries.objects.TPSQueries; import com.djrapitops.plan.db.access.queries.objects.WorldTimesQueries; +import com.djrapitops.plan.extension.implementation.storage.queries.ExtensionServerDataQuery; import com.djrapitops.plan.system.cache.SessionCache; import com.djrapitops.plan.system.info.server.Server; @@ -94,6 +95,8 @@ public class ServerContainerQuery implements Query { container.putCachingSupplier(ServerKeys.MOB_KILL_COUNT, () -> SessionsMutator.forContainer(container).toMobKillCount()); container.putCachingSupplier(ServerKeys.DEATH_COUNT, () -> SessionsMutator.forContainer(container).toDeathCount()); + container.putCachingSupplier(ServerKeys.EXTENSION_DATA, () -> db.query(new ExtensionServerDataQuery(serverUUID))); + return container; } } \ No newline at end of file diff --git a/Plan/common/src/main/java/com/djrapitops/plan/utilities/html/pages/AnalysisPluginTabs.java b/Plan/common/src/main/java/com/djrapitops/plan/utilities/html/pages/AnalysisPluginTabs.java new file mode 100644 index 000000000..c58a02325 --- /dev/null +++ b/Plan/common/src/main/java/com/djrapitops/plan/utilities/html/pages/AnalysisPluginTabs.java @@ -0,0 +1,163 @@ +/* + * 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 . + */ +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.ExtensionDescriptive; +import com.djrapitops.plan.extension.implementation.results.ExtensionInformation; +import com.djrapitops.plan.extension.implementation.results.ExtensionTabData; +import com.djrapitops.plan.extension.implementation.results.server.ExtensionServerData; +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 /server page plugin tabs based on DataExtension API data. + *

+ * Currently very similar to {@link InspectPluginTab}. + * This will become more complex once tables are added, since some big tables will be moved to their own tabs. + * + * @author Rsl1122 + */ +public class AnalysisPluginTabs { + + private List serverData; + + private Map> numberFormatters; + + private Formatter decimalFormatter; + private Formatter percentageFormatter; + + private String nav; + private String tab; + + public AnalysisPluginTabs(String nav, String tab) { + this.nav = nav; + this.tab = tab; + } + + public AnalysisPluginTabs( + List serverData, + Formatters formatters + ) { + this.serverData = serverData; + + 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 getTabs() { + return tab; + } + + private void generate() { + if (serverData.isEmpty()) { + nav = "

  • Extensions (No Data)
  • "; + tab = "
    " + + "
    " + Html.CARD.parse("

    No Extension Data

    ") + + "
    "; + } else { + nav = "
  • General
  • "; + tab = generatePageTab(); + } + } + + private String generatePageTab() { + Collections.sort(serverData); + + StringBuilder tabBuilder = new StringBuilder(); + + for (ExtensionServerData datum : serverData) { + 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 "
    " + content + "
    "; + } + + 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 description = descriptive.getDescription(); + if (description.isPresent()) { + builder.append("

    "); + } else { + builder.append("

    "); + } + builder.append(Icon.fromExtensionIcon(descriptive.getIcon())) + .append(' ').append(descriptive.getText()).append(": ").append(formattedValue).append("

    "); + } + + private String wrapInContainer(ExtensionInformation information, String tabsElement) { + return "
    " + + "
    " + + "

    " + Icon.fromExtensionIcon(information.getIcon()) + ' ' + information.getPluginName() + "

    " + + "
    " + + tabsElement + + "
    "; + } +} \ No newline at end of file diff --git a/Plan/common/src/main/java/com/djrapitops/plan/utilities/html/structure/AnalysisPluginsTabContentCreator.java b/Plan/common/src/main/java/com/djrapitops/plan/utilities/html/structure/AnalysisPluginsTabContentCreator.java index 111d87ec9..842366f09 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/utilities/html/structure/AnalysisPluginsTabContentCreator.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/utilities/html/structure/AnalysisPluginsTabContentCreator.java @@ -68,7 +68,7 @@ public class AnalysisPluginsTabContentCreator { ) { if (mutator.all().isEmpty()) { - return new String[]{"
  • No Data
  • ", ""}; + return new String[]{"", ""}; } List uuids = mutator.uuids(); @@ -125,7 +125,7 @@ public class AnalysisPluginsTabContentCreator { ""; return new String[]{ - (displayGeneralTab ? "
  • General
  • " : "") + (displayGeneralTab ? "
  • General (Legacy)
  • " : "") + "
  • Player Data
  • " + nav.toString(), (displayGeneralTab ? generalTab.toString() : "") + playerListTab + otherTabs.toString() };