From 059d4553aa0ade69bda42b4d428a3f30bb416983 Mon Sep 17 00:00:00 2001 From: Aurora Lahtela <24460436+AuroraLS3@users.noreply.github.com> Date: Sun, 27 Nov 2022 09:48:55 +0200 Subject: [PATCH] Implemented react side of export for frontend BETA --- Plan/common/build.gradle | 7 +- .../plan/delivery/export/ExportScheduler.java | 13 ++ .../plan/delivery/export/ReactExporter.java | 50 +++++ .../delivery/export/ReactExporterTest.java | 16 +- Plan/react/dashboard/src/App.js | 23 +- .../src/components/navigation/Header.js | 6 +- .../src/components/navigation/Sidebar.js | 2 +- .../dashboard/src/hooks/dataFetchHook.js | 3 +- .../src/service/authenticationService.js | 5 +- .../src/service/backendConfiguration.js | 7 +- .../dashboard/src/service/localeService.js | 5 +- .../dashboard/src/service/metadataService.js | 16 +- .../dashboard/src/service/networkService.js | 22 +- .../dashboard/src/service/serverService.js | 208 +++++++++++++++--- .../dashboard/src/views/layout/ErrorPage.js | 2 +- .../dashboard/src/views/layout/NetworkPage.js | 3 +- 16 files changed, 309 insertions(+), 79 deletions(-) diff --git a/Plan/common/build.gradle b/Plan/common/build.gradle index 2ad19f3ed..39c226119 100644 --- a/Plan/common/build.gradle +++ b/Plan/common/build.gradle @@ -142,7 +142,7 @@ task determineAssetModifications { def modified = gitModifiedAsString.isEmpty() ? System.currentTimeMillis() : Long.parseLong(gitModifiedAsString) * 1000 def relativePath = tree.getDir().toPath().relativize(f.toPath()) // File path relative to the tree versionFile.text += String.format( - "%s: %s\n", relativePath.toString().replace('.', ','), modified + "%s: %s\n", relativePath.toString().replace('.', ',').replace('\\', '/'), modified ) } tree = fileTree(dir: 'src/main/resources/assets/plan/locale') @@ -157,16 +157,17 @@ task determineAssetModifications { def modified = gitModifiedAsString.isEmpty() ? System.currentTimeMillis() : Long.parseLong(gitModifiedAsString) * 1000 def relativePath = tree.getDir().toPath().relativize(f.toPath()) // File path relative to the tree versionFile.text += String.format( - "%s: %s\n", relativePath.toString().replace('.', ','), modified + "%s: %s\n", relativePath.toString().replace('.', ',').replace('\\', '/'), modified ) } tree = fileTree("$rootDir/react/dashboard/build") tree.forEach { File f -> + if (f.getName().endsWith(".map")) return def modified = System.currentTimeMillis() def relativePath = tree.getDir().toPath().relativize(f.toPath()) // File path relative to the tree versionFile.text += String.format( - "%s: %s\n", relativePath.toString().replace('.', ','), modified + "%s: %s\n", relativePath.toString().replace('.', ',').replace('\\', '/'), modified ) } } diff --git a/Plan/common/src/main/java/com/djrapitops/plan/delivery/export/ExportScheduler.java b/Plan/common/src/main/java/com/djrapitops/plan/delivery/export/ExportScheduler.java index 569b48b26..e476d8f33 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/delivery/export/ExportScheduler.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/delivery/export/ExportScheduler.java @@ -20,6 +20,7 @@ import com.djrapitops.plan.identification.Server; import com.djrapitops.plan.identification.ServerInfo; import com.djrapitops.plan.settings.config.PlanConfig; import com.djrapitops.plan.settings.config.paths.ExportSettings; +import com.djrapitops.plan.settings.config.paths.PluginSettings; import com.djrapitops.plan.storage.database.DBSystem; import com.djrapitops.plan.storage.database.Database; import com.djrapitops.plan.storage.database.queries.objects.ServerQueries; @@ -79,10 +80,22 @@ public class ExportScheduler extends PluginRunnable { return; } + scheduleReactExport(); scheduleServerPageExport(); schedulePlayersPageExport(); } + private void scheduleReactExport() { + if (config.isFalse(PluginSettings.FRONTEND_BETA) || + config.isFalse(ExportSettings.SERVER_PAGE) && + config.isFalse(ExportSettings.PLAYER_PAGES) && + config.isFalse(ExportSettings.PLAYERS_PAGE)) {return;} + + runnableFactory.create( + new ExportTask(exporter, Exporter::exportReact, errorLogger) + ).runTaskLaterAsynchronously(TimeAmount.toTicks(5, TimeUnit.SECONDS)); + } + private void schedulePlayersPageExport() { long period = TimeAmount.toTicks(config.get(ExportSettings.EXPORT_PERIOD), TimeUnit.MILLISECONDS) / 4; diff --git a/Plan/common/src/main/java/com/djrapitops/plan/delivery/export/ReactExporter.java b/Plan/common/src/main/java/com/djrapitops/plan/delivery/export/ReactExporter.java index 834eda354..ee55f1a52 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/delivery/export/ReactExporter.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/delivery/export/ReactExporter.java @@ -17,8 +17,13 @@ package com.djrapitops.plan.delivery.export; import com.djrapitops.plan.delivery.web.AssetVersions; +import com.djrapitops.plan.delivery.web.resolver.Response; +import com.djrapitops.plan.delivery.web.resolver.request.Request; +import com.djrapitops.plan.delivery.webserver.resolver.json.RootJSONResolver; +import com.djrapitops.plan.exceptions.connection.WebException; import com.djrapitops.plan.settings.config.PlanConfig; import com.djrapitops.plan.settings.config.paths.WebserverSettings; +import com.djrapitops.plan.settings.locale.LangCode; import com.djrapitops.plan.storage.file.PlanFiles; import com.djrapitops.plan.storage.file.Resource; import org.apache.commons.lang3.StringUtils; @@ -27,7 +32,9 @@ import javax.inject.Inject; import javax.inject.Singleton; import java.io.IOException; import java.nio.file.Path; +import java.util.Collections; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; /** @@ -40,16 +47,19 @@ public class ReactExporter extends FileExporter { private final PlanFiles files; private final PlanConfig config; + private final RootJSONResolver jsonHandler; private final AssetVersions assetVersions; @Inject public ReactExporter( PlanFiles files, PlanConfig config, + RootJSONResolver jsonHandler, AssetVersions assetVersions ) { this.files = files; this.config = config; + this.jsonHandler = jsonHandler; this.assetVersions = assetVersions; } @@ -62,6 +72,21 @@ public class ReactExporter extends FileExporter { exportAsset(toDirectory, "manifest.json"); exportAsset(toDirectory, "robots.txt"); exportStaticBundle(toDirectory); + exportLocaleJson(toDirectory.resolve("locale")); + exportMetadataJson(toDirectory.resolve("metadata")); + } + + private void exportMetadataJson(Path toDirectory) throws IOException { + exportJson(toDirectory, "metadata"); + exportJson(toDirectory, "version"); + exportJson(toDirectory, "networkMetadata"); + } + + private void exportLocaleJson(Path toDirectory) throws IOException { + exportJson(toDirectory, "locale"); // List of languages + for (LangCode langCode : LangCode.values()) { + exportJson(toDirectory, "locale/" + langCode.name(), langCode.name()); + } } private void exportStaticBundle(Path toDirectory) throws IOException { @@ -89,4 +114,29 @@ public class ReactExporter extends FileExporter { export(toDirectory.resolve(asset), files.getResourceFromJar("web/" + asset)); } + private void exportJson(Path toDirectory, String resource) throws IOException { + exportJson(toDirectory, resource, toJsonResourceName(resource)); + } + + private void exportJson(Path toDirectory, String resource, String fileName) throws IOException { + Path to = toDirectory.resolve(fileName + ".json"); + Optional jsonResponse = getJsonResponse(resource); + if (jsonResponse.isPresent()) { + export(to, jsonResponse.get().getBytes()); + } + } + + private String toJsonResourceName(String resource) { + return StringUtils.replaceEach(resource, new String[]{"?", "&",}, new String[]{"-", "_"}); + } + + private Optional getJsonResponse(String resource) { + try { + return jsonHandler.getResolver().resolve(new Request("GET", "/v1/" + resource, null, Collections.emptyMap())); + } catch (WebException e) { + // The rest of the exceptions should not be thrown + throw new IllegalStateException("Unexpected exception thrown: " + e, e); + } + } + } diff --git a/Plan/common/src/test/java/com/djrapitops/plan/delivery/export/ReactExporterTest.java b/Plan/common/src/test/java/com/djrapitops/plan/delivery/export/ReactExporterTest.java index bec1fe1a0..dd57ccf47 100644 --- a/Plan/common/src/test/java/com/djrapitops/plan/delivery/export/ReactExporterTest.java +++ b/Plan/common/src/test/java/com/djrapitops/plan/delivery/export/ReactExporterTest.java @@ -24,15 +24,16 @@ import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.api.function.Executable; import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.util.List; -import java.util.stream.Collectors; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertTrue; @ExtendWith(FullSystemExtension.class) class ReactExporterTest { @@ -56,11 +57,12 @@ class ReactExporterTest { .resolve("../react/dashboard/build"); List filesToExport = Files.list(reactBuildPath) + .filter(path -> !path.endsWith(".map")) .map(path -> path.relativize(reactBuildPath)) - .collect(Collectors.toList()); - List filesExported = Files.list(exportPath) - .map(path -> path.relativize(exportPath)) - .collect(Collectors.toList()); - assertEquals(filesToExport, filesExported); + .toList(); + List filesExported = Files.list(exportPath).map(path -> path.relativize(exportPath)).toList(); + assertAll(filesToExport.stream() + .map(path -> (Executable) () -> assertTrue(filesExported.contains(path))) + .toList()); } } \ No newline at end of file diff --git a/Plan/react/dashboard/src/App.js b/Plan/react/dashboard/src/App.js index fbe40cad1..a9c9fdcb2 100644 --- a/Plan/react/dashboard/src/App.js +++ b/Plan/react/dashboard/src/App.js @@ -12,6 +12,7 @@ import {MetadataContextProvider} from "./hooks/metadataHook"; import {AuthenticationContextProvider} from "./hooks/authenticationHook"; import {NavigationContextProvider} from "./hooks/navigationHook"; import MainPageRedirect from "./components/navigation/MainPageRedirect"; +import {staticSite} from "./service/backendConfiguration"; const PlayerPage = React.lazy(() => import("./views/layout/PlayerPage")); const PlayerOverview = React.lazy(() => import("./views/player/PlayerOverview")); @@ -51,6 +52,7 @@ const QueryResultView = React.lazy(() => import("./views/query/QueryResultView") const LoginPage = React.lazy(() => import("./views/layout/LoginPage")); const RegisterPage = React.lazy(() => import("./views/layout/RegisterPage")); +const ErrorPage = React.lazy(() => import("./views/layout/ErrorPage")); const ErrorsPage = React.lazy(() => import("./views/layout/ErrorsPage")); const SwaggerView = React.lazy(() => import("./views/SwaggerView")); @@ -90,8 +92,9 @@ function App() { }/> }/> - }/> - }/> + }/> + {!staticSite && }/>} + {!staticSite && }/>} }> }/> }/> @@ -134,7 +137,8 @@ function App() { }/> }/> }/> - }/> + {!staticSite && + }/>} }/> }/> }/> @@ -147,13 +151,18 @@ function App() { icon: faMapSigns }}/>}/> - }> + {!staticSite && }> }/> }/> }/> - - }/> - }/> + } + {!staticSite && }/>} + {!staticSite && }/>} + }/> diff --git a/Plan/react/dashboard/src/components/navigation/Header.js b/Plan/react/dashboard/src/components/navigation/Header.js index 28ca6dae7..cc875017b 100644 --- a/Plan/react/dashboard/src/components/navigation/Header.js +++ b/Plan/react/dashboard/src/components/navigation/Header.js @@ -10,7 +10,7 @@ import DropdownToggle from "react-bootstrap-v5/lib/esm/DropdownToggle"; import {localeService} from "../../service/localeService"; import {useTranslation} from "react-i18next"; import {useNavigation} from "../../hooks/navigationHook"; -import {baseAddress} from "../../service/backendConfiguration"; +import {baseAddress, staticSite} from "../../service/backendConfiguration"; const LanguageSelector = () => { const languages = localeService.getLanguages(); @@ -55,9 +55,9 @@ const Header = ({page, tab, hideUpdater}) => { {!hideUpdater && <>
- + } {' '} {lastUpdate.formatted}
diff --git a/Plan/react/dashboard/src/components/navigation/Sidebar.js b/Plan/react/dashboard/src/components/navigation/Sidebar.js index f06171be4..9d7341384 100644 --- a/Plan/react/dashboard/src/components/navigation/Sidebar.js +++ b/Plan/react/dashboard/src/components/navigation/Sidebar.js @@ -230,7 +230,7 @@ const Sidebar = ({items, showBackButton}) => { } - {items.length ? items.map((item, i) => renderItem(item, i, openCollapse, toggleCollapse, t)) : ''} + {items.length ? items.filter(item => item !== undefined).map((item, i) => renderItem(item, i, openCollapse, toggleCollapse, t)) : ''} } diff --git a/Plan/react/dashboard/src/hooks/dataFetchHook.js b/Plan/react/dashboard/src/hooks/dataFetchHook.js index b0211014b..f413d7084 100644 --- a/Plan/react/dashboard/src/hooks/dataFetchHook.js +++ b/Plan/react/dashboard/src/hooks/dataFetchHook.js @@ -2,6 +2,7 @@ import {useEffect, useState} from "react"; import {useNavigation} from "./navigationHook"; import {useDataStore} from "./datastoreHook"; import {useMetadata} from "./metadataHook"; +import {staticSite} from "../service/backendConfiguration"; export const useDataRequest = (fetchMethod, parameters) => { const [data, setData] = useState(undefined); @@ -16,7 +17,7 @@ export const useDataRequest = (fetchMethod, parameters) => { const handleResponse = (json, error, skipOldData, timeout) => { if (json) { const timestamp = json.timestamp; - if (timestamp) { + if (staticSite || timestamp) { // Data has timestamp, the data may come from cache const acceptedTimestamp = timestamp + (refreshBarrierMs ? refreshBarrierMs : 15000); if (acceptedTimestamp < updateRequested) { diff --git a/Plan/react/dashboard/src/service/authenticationService.js b/Plan/react/dashboard/src/service/authenticationService.js index cc275309b..dca9ef148 100644 --- a/Plan/react/dashboard/src/service/authenticationService.js +++ b/Plan/react/dashboard/src/service/authenticationService.js @@ -1,6 +1,9 @@ -import {doGetRequest, doSomePostRequest, standard200option} from "./backendConfiguration"; +import {doGetRequest, doSomePostRequest, standard200option, staticSite} from "./backendConfiguration"; export const fetchWhoAmI = async () => { + if (staticSite) { + return {authRequired: false, loggedIn: false} + } const url = '/v1/whoami'; return doGetRequest(url); } diff --git a/Plan/react/dashboard/src/service/backendConfiguration.js b/Plan/react/dashboard/src/service/backendConfiguration.js index a895d8742..f8a370fcf 100644 --- a/Plan/react/dashboard/src/service/backendConfiguration.js +++ b/Plan/react/dashboard/src/service/backendConfiguration.js @@ -11,11 +11,8 @@ const isCurrentAddress = (address) => { return is; } -// Concat to prevent double string replacement. -/*eslint-disable no-useless-concat */ -export const baseAddress = "PLAN_BASE" + "_ADDRESS" === javaReplaced.address || !isCurrentAddress(javaReplaced.address) ? "" : javaReplaced.address; -export const staticSite = "PLAN_EXPORTED" + "_VERSION" !== javaReplaced.isStatic; -/*eslint-enable no-useless-concat */ +export const baseAddress = javaReplaced.address.startsWith('PLAN_') || !isCurrentAddress(javaReplaced.address) ? "" : javaReplaced.address; +export const staticSite = javaReplaced.isStatic === 'true'; export const doSomeGetRequest = async (url, statusOptions) => { return doSomeRequest(url, statusOptions, async () => axios.get(url)); diff --git a/Plan/react/dashboard/src/service/localeService.js b/Plan/react/dashboard/src/service/localeService.js index 583384ffa..9b1930364 100644 --- a/Plan/react/dashboard/src/service/localeService.js +++ b/Plan/react/dashboard/src/service/localeService.js @@ -4,6 +4,7 @@ import I18NextLocalStorageBackend from "i18next-localstorage-backend"; import I18NextHttpBackend from 'i18next-http-backend'; import {initReactI18next} from 'react-i18next'; import {fetchAvailableLocales} from "./metadataService"; +import {baseAddress, staticSite} from "./backendConfiguration"; /** * A locale system for localizing the website. @@ -53,6 +54,8 @@ export const localeService = { this.clientLocale = this.defaultLanguage; } + let loadPath = baseAddress + '/v1/locale/{{lng}}'; + if (staticSite) loadPath = baseAddress + '/locale/{{lng}}.json' await i18next .use(I18NextChainedBackend) .use(initReactI18next) @@ -70,7 +73,7 @@ export const localeService = { expirationTime: 7 * 24 * 60 * 60 * 1000, // 7 days versions: this.languageVersions }, { - loadPath: '/v1/locale/{{lng}}' + loadPath: loadPath }] }, }, () => {/* No need to initialize anything */ diff --git a/Plan/react/dashboard/src/service/metadataService.js b/Plan/react/dashboard/src/service/metadataService.js index 6604a672b..84c01f410 100644 --- a/Plan/react/dashboard/src/service/metadataService.js +++ b/Plan/react/dashboard/src/service/metadataService.js @@ -1,26 +1,30 @@ -import {doGetRequest} from "./backendConfiguration"; +import {doGetRequest, staticSite} from "./backendConfiguration"; export const fetchPlanMetadata = async () => { - const url = '/v1/metadata'; + let url = '/v1/metadata'; + if (staticSite) url = '/metadata/metadata.json' return doGetRequest(url); } export const fetchPlanVersion = async () => { - const url = '/v1/version'; + let url = '/v1/version'; + if (staticSite) url = '/metadata/version.json' return doGetRequest(url); } export const fetchAvailableLocales = async () => { - const url = '/v1/locale'; + let url = '/v1/locale'; + if (staticSite) url = '/locale/locale.json' return doGetRequest(url); } export const fetchErrorLogs = async () => { - const url = '/v1/errors'; + let url = '/v1/errors'; return doGetRequest(url); } export const fetchNetworkMetadata = async () => { - const url = '/v1/networkMetadata'; + let url = '/v1/networkMetadata'; + if (staticSite) url = '/metadata/networkMetadata.json' return doGetRequest(url); } \ No newline at end of file diff --git a/Plan/react/dashboard/src/service/networkService.js b/Plan/react/dashboard/src/service/networkService.js index b37b546ec..94ceb4907 100644 --- a/Plan/react/dashboard/src/service/networkService.js +++ b/Plan/react/dashboard/src/service/networkService.js @@ -1,36 +1,42 @@ -import {doGetRequest} from "./backendConfiguration"; +import {doGetRequest, staticSite} from "./backendConfiguration"; export const fetchNetworkOverview = async (updateRequested) => { - const url = `/v1/network/overview?timestamp=${updateRequested}`; + let url = `/v1/network/overview?timestamp=${updateRequested}`; + if (staticSite) url = `/data/network-overview.json`; return doGetRequest(url); } export const fetchServersOverview = async (updateRequested) => { - const url = `/v1/network/servers?timestamp=${updateRequested}`; + let url = `/v1/network/servers?timestamp=${updateRequested}`; + if (staticSite) url = `/data/network-servers.json`; return doGetRequest(url); } export const fetchServerPie = async (timestamp) => { - const url = `/v1/graph?type=serverPie×tamp=${timestamp}`; + let url = `/v1/graph?type=serverPie×tamp=${timestamp}`; + if (staticSite) url = `/data/graph-serverPie.json`; return doGetRequest(url); } export const fetchNetworkSessionsOverview = async (timestamp) => { - const url = `/v1/network/sessionsOverview?timestamp=${timestamp}`; + let url = `/v1/network/sessionsOverview?timestamp=${timestamp}`; + if (staticSite) url = `/data/network-sessionsOverview.json`; return doGetRequest(url); } export const fetchNetworkPlayerbaseOverview = async (timestamp) => { - const url = `/v1/network/playerbaseOverview?timestamp=${timestamp}`; + let url = `/v1/network/playerbaseOverview?timestamp=${timestamp}`; + if (staticSite) url = `/data/network-playerbaseOverview.json`; return doGetRequest(url); } export const fetchNetworkPingTable = async (timestamp) => { - const url = `/v1/network/pingTable?timestamp=${timestamp}`; + let url = `/v1/network/pingTable?timestamp=${timestamp}`; + if (staticSite) url = `/data/network-pingTable.json`; return doGetRequest(url); } export const fetchNetworkPerformanceOverview = async (timestamp, serverUUIDs) => { - const url = `/v1/network/performanceOverview?servers=${encodeURIComponent(JSON.stringify(serverUUIDs))}×tamp=${timestamp}`; + let url = `/v1/network/performanceOverview?servers=${encodeURIComponent(JSON.stringify(serverUUIDs))}×tamp=${timestamp}`; return doGetRequest(url); } \ No newline at end of file diff --git a/Plan/react/dashboard/src/service/serverService.js b/Plan/react/dashboard/src/service/serverService.js index eeb4a6e39..95a841431 100644 --- a/Plan/react/dashboard/src/service/serverService.js +++ b/Plan/react/dashboard/src/service/serverService.js @@ -1,130 +1,270 @@ -import {doGetRequest} from "./backendConfiguration"; - +import {doGetRequest, staticSite} from "./backendConfiguration"; export const fetchServerIdentity = async (timestamp, identifier) => { - const url = `/v1/serverIdentity?server=${identifier}`; + let url = `/v1/serverIdentity?server=${identifier}`; + if (staticSite) url = `/data/serverIdentity-${identifier}.json`; return doGetRequest(url); } export const fetchServerOverview = async (timestamp, identifier) => { - const url = `/v1/serverOverview?server=${identifier}×tamp=${timestamp}`; + let url = `/v1/serverOverview?server=${identifier}×tamp=${timestamp}`; + if (staticSite) url = `/data/serverOverview-${identifier}.json`; return doGetRequest(url); } export const fetchOnlineActivityOverview = async (timestamp, identifier) => { - const url = `/v1/onlineOverview?server=${identifier}×tamp=${timestamp}`; + let url = `/v1/onlineOverview?server=${identifier}×tamp=${timestamp}`; + if (staticSite) url = `/data/onlineOverview-${identifier}.json`; return doGetRequest(url); } export const fetchPlayerbaseOverview = async (timestamp, identifier) => { - const url = `/v1/playerbaseOverview?server=${identifier}×tamp=${timestamp}`; + let url = `/v1/playerbaseOverview?server=${identifier}×tamp=${timestamp}`; + if (staticSite) url = `/data/playerbaseOverview-${identifier}.json`; return doGetRequest(url); } export const fetchSessionOverview = async (timestamp, identifier) => { - const url = `/v1/sessionsOverview?server=${identifier}×tamp=${timestamp}`; + let url = `/v1/sessionsOverview?server=${identifier}×tamp=${timestamp}`; + if (staticSite) url = `/data/sessionsOverview-${identifier}.json`; return doGetRequest(url); } export const fetchPvpPve = async (timestamp, identifier) => { - const url = `/v1/playerVersus?server=${identifier}×tamp=${timestamp}`; + let url = `/v1/playerVersus?server=${identifier}×tamp=${timestamp}`; + if (staticSite) url = `/data/playerVersus-${identifier}.json`; return doGetRequest(url); } export const fetchPerformanceOverview = async (timestamp, identifier) => { - const url = `/v1/performanceOverview?server=${identifier}×tamp=${timestamp}`; + let url = `/v1/performanceOverview?server=${identifier}×tamp=${timestamp}`; + if (staticSite) url = `/data/performanceOverview-${identifier}.json`; return doGetRequest(url); } export const fetchExtensionData = async (timestamp, identifier) => { - const url = `/v1/extensionData?server=${identifier}×tamp=${timestamp}`; + let url = `/v1/extensionData?server=${identifier}×tamp=${timestamp}`; + if (staticSite) url = `/data/extensionData-${identifier}.json`; return doGetRequest(url); } export const fetchSessions = async (timestamp, identifier) => { - const url = identifier ? `/v1/sessions?server=${identifier}×tamp=${timestamp}` : - `/v1/sessions?timestamp=${timestamp}`; + if (identifier) { + return await fetchSessionsServer(timestamp, identifier); + } else { + return await fetchSessionsNetwork(timestamp); + } +} + +const fetchSessionsServer = async (timestamp, identifier) => { + let url = `/v1/sessions?server=${identifier}×tamp=${timestamp}`; + if (staticSite) url = `/data/sessions-${identifier}.json`; + return doGetRequest(url); +} + +const fetchSessionsNetwork = async (timestamp) => { + let url = `/v1/sessions?timestamp=${timestamp}`; + if (staticSite) url = `/data/sessions.json`; return doGetRequest(url); } export const fetchKills = async (timestamp, identifier) => { - const url = `/v1/kills?server=${identifier}×tamp=${timestamp}`; + let url = `/v1/kills?server=${identifier}×tamp=${timestamp}`; + if (staticSite) url = `/data/kills-${identifier}.json`; return doGetRequest(url); } export const fetchPlayers = async (timestamp, identifier) => { - const url = identifier ? `/v1/players?server=${identifier}×tamp=${timestamp}` : `/v1/players?timestamp=${timestamp}`; + if (identifier) { + return await fetchPlayersServer(timestamp, identifier); + } else { + return await fetchPlayersNetwork(timestamp); + } +} +const fetchPlayersServer = async (timestamp, identifier) => { + let url = `/v1/players?server=${identifier}×tamp=${timestamp}`; + if (staticSite) url = `/data/players-${identifier}.json`; + return doGetRequest(url); +} + +const fetchPlayersNetwork = async (timestamp) => { + let url = `/v1/players?timestamp=${timestamp}`; + if (staticSite) url = `/data/players.json`; return doGetRequest(url); } export const fetchPingTable = async (timestamp, identifier) => { - const url = `/v1/pingTable?server=${identifier}×tamp=${timestamp}`; + let url = `/v1/pingTable?server=${identifier}×tamp=${timestamp}`; + if (staticSite) url = `/data/pingTable-${identifier}.json`; return doGetRequest(url); } export const fetchPlayersOnlineGraph = async (timestamp, identifier) => { - const url = identifier ? `/v1/graph?type=playersOnline&server=${identifier}×tamp=${timestamp}` : - `/v1/graph?type=playersOnline×tamp=${timestamp}`; + if (identifier) { + return await fetchPlayersOnlineGraphServer(timestamp, identifier); + } else { + return await fetchPlayersOnlineGraphNetwork(timestamp); + } +} + +const fetchPlayersOnlineGraphServer = async (timestamp, identifier) => { + let url = `/v1/graph?type=playersOnline&server=${identifier}×tamp=${timestamp}`; + if (staticSite) url = `/data/graph-playersOnline_${identifier}.json`; + return doGetRequest(url); +} + +const fetchPlayersOnlineGraphNetwork = async (timestamp) => { + let url = `/v1/graph?type=playersOnline×tamp=${timestamp}`; + if (staticSite) url = `/data/graph-playersOnline.json`; return doGetRequest(url); } export const fetchPlayerbaseDevelopmentGraph = async (timestamp, identifier) => { - const url = identifier ? `/v1/graph?type=activity&server=${identifier}×tamp=${timestamp}` : - `/v1/graph?type=activity×tamp=${timestamp}`; + if (identifier) { + return await fetchPlayerbaseDevelopmentGraphServer(timestamp, identifier); + } else { + return await fetchPlayerbaseDevelopmentGraphNetwork(timestamp); + } +} + +const fetchPlayerbaseDevelopmentGraphServer = async (timestamp, identifier) => { + let url = `/v1/graph?type=activity&server=${identifier}×tamp=${timestamp}`; + if (staticSite) url = `/data/graph-activity_${identifier}.json`; + return doGetRequest(url); +} + +const fetchPlayerbaseDevelopmentGraphNetwork = async (timestamp) => { + let url = `/v1/graph?type=activity×tamp=${timestamp}`; + if (staticSite) url = `/data/graph-activity.json`; return doGetRequest(url); } export const fetchDayByDayGraph = async (timestamp, identifier) => { - const url = identifier ? `/v1/graph?type=uniqueAndNew&server=${identifier}×tamp=${timestamp}` : - `/v1/graph?type=uniqueAndNew×tamp=${timestamp}`; + if (identifier) { + return await fetchDayByDayGraphServer(timestamp, identifier); + } else { + return await fetchDayByDayGraphNetwork(timestamp); + } +} + +const fetchDayByDayGraphServer = async (timestamp, identifier) => { + let url = `/v1/graph?type=uniqueAndNew&server=${identifier}×tamp=${timestamp}`; + if (staticSite) url = `/data/graph-uniqueAndNew_${identifier}.json`; + return doGetRequest(url); +} + +const fetchDayByDayGraphNetwork = async (timestamp) => { + let url = `/v1/graph?type=uniqueAndNew×tamp=${timestamp}`; + if (staticSite) url = `/data/graph-uniqueAndNew.json`; return doGetRequest(url); } export const fetchHourByHourGraph = async (timestamp, identifier) => { - const url = identifier ? `/v1/graph?type=hourlyUniqueAndNew&server=${identifier}×tamp=${timestamp}` : - `/v1/graph?type=hourlyUniqueAndNew×tamp=${timestamp}`; + if (identifier) { + return await fetchHourByHourGraphServer(timestamp, identifier); + } else { + return await fetchHourByHourGraphNetwork(timestamp); + } +} + +const fetchHourByHourGraphServer = async (timestamp, identifier) => { + let url = `/v1/graph?type=hourlyUniqueAndNew&server=${identifier}×tamp=${timestamp}`; + if (staticSite) url = `/data/graph-hourlyUniqueAndNew_${identifier}.json`; + return doGetRequest(url); +} + +const fetchHourByHourGraphNetwork = async (timestamp) => { + let url = `/v1/graph?type=hourlyUniqueAndNew×tamp=${timestamp}`; + if (staticSite) url = `/data/graph-hourlyUniqueAndNew.json`; return doGetRequest(url); } export const fetchServerCalendarGraph = async (timestamp, identifier) => { - const url = `/v1/graph?type=serverCalendar&server=${identifier}×tamp=${timestamp}`; + let url = `/v1/graph?type=serverCalendar&server=${identifier}×tamp=${timestamp}`; + if (staticSite) url = `/data/graph-serverCalendar_${identifier}.json`; return doGetRequest(url); } export const fetchPunchCardGraph = async (timestamp, identifier) => { - const url = `/v1/graph?type=punchCard&server=${identifier}×tamp=${timestamp}`; + let url = `/v1/graph?type=punchCard&server=${identifier}×tamp=${timestamp}`; + if (staticSite) url = `/data/graph-punchCard_${identifier}.json`; return doGetRequest(url); } export const fetchWorldPie = async (timestamp, identifier) => { - const url = `/v1/graph?type=worldPie&server=${identifier}×tamp=${timestamp}`; + let url = `/v1/graph?type=worldPie&server=${identifier}×tamp=${timestamp}`; + if (staticSite) url = `/data/graph-worldPie_${identifier}.json`; return doGetRequest(url); } export const fetchGeolocations = async (timestamp, identifier) => { - const url = identifier ? `/v1/graph?type=geolocation&server=${identifier}×tamp=${timestamp}` : - `/v1/graph?type=geolocation×tamp=${timestamp}`; + if (identifier) { + return await fetchGeolocationsServer(timestamp, identifier); + } else { + return await fetchGeolocationsNetwork(timestamp); + } +} + +const fetchGeolocationsServer = async (timestamp, identifier) => { + let url = `/v1/graph?type=geolocation&server=${identifier}×tamp=${timestamp}`; + if (staticSite) url = `/data/graph-geolocation_${identifier}.json`; + return doGetRequest(url); +} + +const fetchGeolocationsNetwork = async (timestamp) => { + let url = `/v1/graph?type=geolocation×tamp=${timestamp}`; + if (staticSite) url = `/data/graph-geolocation.json`; return doGetRequest(url); } export const fetchOptimizedPerformance = async (timestamp, identifier, after) => { - const url = `/v1/graph?type=optimizedPerformance&server=${identifier}×tamp=${timestamp}&after=${after}`; + let url = `/v1/graph?type=optimizedPerformance&server=${identifier}×tamp=${timestamp}&after=${after}`; + if (staticSite) url = `/data/graph-optimizedPerformance_${identifier}.json`; return doGetRequest(url); } export const fetchPingGraph = async (timestamp, identifier) => { - const url = `/v1/graph?type=aggregatedPing&server=${identifier}×tamp=${timestamp}`; + let url = `/v1/graph?type=aggregatedPing&server=${identifier}×tamp=${timestamp}`; + if (staticSite) url = `/data/graph-aggregatedPing_${identifier}.json`; return doGetRequest(url); } export const fetchJoinAddressPie = async (timestamp, identifier) => { - const url = identifier ? `/v1/graph?type=joinAddressPie&server=${identifier}×tamp=${timestamp}` : - `/v1/graph?type=joinAddressPie×tamp=${timestamp}`; + if (identifier) { + return await fetchJoinAddressPieServer(timestamp, identifier); + } else { + return await fetchJoinAddressPieNetwork(timestamp); + } +} + +const fetchJoinAddressPieServer = async (timestamp, identifier) => { + let url = `/v1/graph?type=joinAddressPie&server=${identifier}×tamp=${timestamp}`; + if (staticSite) url = `/data/graph-joinAddressPie_${identifier}.json`; + return doGetRequest(url); +} + +const fetchJoinAddressPieNetwork = async (timestamp) => { + let url = `/v1/graph?type=joinAddressPie×tamp=${timestamp}`; + if (staticSite) url = `/data/graph-joinAddressPie.json`; return doGetRequest(url); } export const fetchJoinAddressByDay = async (timestamp, identifier) => { - const url = identifier ? `/v1/graph?type=joinAddressByDay&server=${identifier}×tamp=${timestamp}` : - `/v1/graph?type=joinAddressByDay×tamp=${timestamp}`; + if (identifier) { + return await fetchJoinAddressByDayServer(timestamp, identifier); + } else { + return await fetchJoinAddressByDayNetwork(timestamp); + } +} + +const fetchJoinAddressByDayServer = async (timestamp, identifier) => { + let url = `/v1/graph?type=joinAddressByDay&server=${identifier}×tamp=${timestamp}`; + if (staticSite) url = `/data/graph-joinAddressByDay_${identifier}.json`; + return doGetRequest(url); +} + +const fetchJoinAddressByDayNetwork = async (timestamp) => { + let url = `/v1/graph?type=joinAddressByDay×tamp=${timestamp}`; + if (staticSite) url = `/data/graph-joinAddressByDay.json`; return doGetRequest(url); } diff --git a/Plan/react/dashboard/src/views/layout/ErrorPage.js b/Plan/react/dashboard/src/views/layout/ErrorPage.js index 7bb606c26..eb9c2f77a 100644 --- a/Plan/react/dashboard/src/views/layout/ErrorPage.js +++ b/Plan/react/dashboard/src/views/layout/ErrorPage.js @@ -12,7 +12,7 @@ const ErrorPage = ({error}) => {
-
+
diff --git a/Plan/react/dashboard/src/views/layout/NetworkPage.js b/Plan/react/dashboard/src/views/layout/NetworkPage.js index 8a7a85bb5..b6a10112a 100644 --- a/Plan/react/dashboard/src/views/layout/NetworkPage.js +++ b/Plan/react/dashboard/src/views/layout/NetworkPage.js @@ -26,6 +26,7 @@ import {SwitchTransition} from "react-transition-group"; import MainPageRedirect from "../../components/navigation/MainPageRedirect"; import {ServerExtensionContextProvider, useServerExtensionContext} from "../../hooks/serverExtensionDataContext"; import {iconTypeToFontAwesomeClass} from "../../util/icons"; +import {staticSite} from "../../service/backendConfiguration"; const NetworkSidebar = () => { const {t, i18n} = useTranslation(); @@ -49,7 +50,7 @@ const NetworkSidebar = () => { href: "serversOverview" }, {name: 'html.label.sessions', icon: faCalendarCheck, href: "sessions"}, - {name: 'html.label.performance', icon: faCogs, href: "performance"}, + staticSite ? undefined : {name: 'html.label.performance', icon: faCogs, href: "performance"}, {}, ...servers.map(server => { return {