From ea16adb13ddea19d2de49f220b7e1c4565eb493d Mon Sep 17 00:00:00 2001 From: Aurora Lahtela <24460436+AuroraLS3@users.noreply.github.com> Date: Tue, 23 Aug 2022 22:01:22 +0300 Subject: [PATCH] Initial version of server extension cards TODO: Extension DataTables mapping --- .../resolver/json/ExtensionJSONResolver.java | 4 +- Plan/react/dashboard/src/App.js | 5 +- .../components/extensions/ExtensionCard.js | 36 +++++++---- .../dashboard/src/service/serverService.js | 6 ++ .../dashboard/src/views/layout/ServerPage.js | 49 ++++++++++++--- .../src/views/player/PlayerPluginData.js | 15 +++-- .../src/views/server/ServerPluginData.js | 61 +++++++++++++++++++ .../src/views/server/ServerWidePluginData.js | 49 +++++++++++++++ 8 files changed, 195 insertions(+), 30 deletions(-) create mode 100644 Plan/react/dashboard/src/views/server/ServerPluginData.js create mode 100644 Plan/react/dashboard/src/views/server/ServerWidePluginData.js diff --git a/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/resolver/json/ExtensionJSONResolver.java b/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/resolver/json/ExtensionJSONResolver.java index 3403dd98e..8d3cc601e 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/resolver/json/ExtensionJSONResolver.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/delivery/webserver/resolver/json/ExtensionJSONResolver.java @@ -23,6 +23,7 @@ import com.djrapitops.plan.delivery.web.resolver.Response; import com.djrapitops.plan.delivery.web.resolver.exception.BadRequestException; import com.djrapitops.plan.delivery.web.resolver.exception.NotFoundException; import com.djrapitops.plan.delivery.web.resolver.request.Request; +import com.djrapitops.plan.delivery.web.resolver.request.WebUser; import com.djrapitops.plan.delivery.webserver.cache.AsyncJSONResolverService; import com.djrapitops.plan.delivery.webserver.cache.DataID; import com.djrapitops.plan.delivery.webserver.cache.JSONStorage; @@ -66,7 +67,8 @@ public class ExtensionJSONResolver implements Resolver { @Override public boolean canAccess(Request request) { - return false; + WebUser permissions = request.getUser().orElse(new WebUser("")); + return permissions.hasPermission("page.server") || permissions.hasPermission("page.network"); } @GET diff --git a/Plan/react/dashboard/src/App.js b/Plan/react/dashboard/src/App.js index 15a70cc11..318edfc73 100644 --- a/Plan/react/dashboard/src/App.js +++ b/Plan/react/dashboard/src/App.js @@ -30,6 +30,8 @@ import AllPlayers from "./views/players/AllPlayers"; import ServerGeolocations from "./views/server/ServerGeolocations"; import LoginPage from "./views/layout/LoginPage"; import ServerPerformance from "./views/server/ServerPerformance"; +import ServerPluginData from "./views/server/ServerPluginData"; +import ServerWidePluginData from "./views/server/ServerWidePluginData"; const SwaggerView = React.lazy(() => import("./views/SwaggerView")); @@ -89,7 +91,8 @@ function App() { }/> }/> }/> - }/> + }/> + }/> { const [windowWidth, setWindowWidth] = useState(window.innerWidth); @@ -51,17 +52,29 @@ const ExtensionValue = ({data}) => { />); } -const ExtensionValues = ({tab}) => ( - - {tab.values.map((data, i) => { - return (); - } - )} - -) +const ExtensionValues = ({tab}) => { + return ( + <> + {Boolean(tab.values.length) && + {tab.values.map((data, i) => { + return (); + } + )} + } + + ) +} const ExtensionTable = ({table}) => { const {nightModeEnabled} = useTheme(); + const {t} = useTranslation(); + + const columns = table.table.rows.length ? table.table.rows.map((row, i) => {row.map((value, j) => {value})}) : + {table.table.columns.map((column, i) => + {i === 0 ? t('generic.noData') : '-'})} + + return ( @@ -72,11 +85,10 @@ const ExtensionTable = ({table}) => { - {table.table.rows.map((row, i) => {row.map((value, j) => )})} + {columns}
{value}
- ); + ) } const ExtensionTables = ({tab}) => { @@ -113,7 +125,7 @@ const ExtensionCard = ({extension}) => { {extension.onlyGenericTab ? '' : extension.tabs.map((tab, i) =>
  • ) diff --git a/Plan/react/dashboard/src/service/serverService.js b/Plan/react/dashboard/src/service/serverService.js index 33ae69b00..58175b7fe 100644 --- a/Plan/react/dashboard/src/service/serverService.js +++ b/Plan/react/dashboard/src/service/serverService.js @@ -42,6 +42,12 @@ export const fetchPerformanceOverview = async (identifier) => { return doGetRequest(url); } +export const fetchExtensionData = async (identifier) => { + const timestamp = Date.now(); + const url = `/v1/extensionData?server=${identifier}×tamp=${timestamp}`; + return doGetRequest(url); +} + export const fetchSessions = async (identifier) => { const timestamp = Date.now(); const url = `/v1/sessions?server=${identifier}×tamp=${timestamp}`; diff --git a/Plan/react/dashboard/src/views/layout/ServerPage.js b/Plan/react/dashboard/src/views/layout/ServerPage.js index 8b6474fc1..fccb8efb4 100644 --- a/Plan/react/dashboard/src/views/layout/ServerPage.js +++ b/Plan/react/dashboard/src/views/layout/ServerPage.js @@ -1,6 +1,6 @@ import React, {useEffect, useState} from "react"; import {useTranslation} from "react-i18next"; -import {Outlet, useParams} from "react-router-dom"; +import {Outlet, useOutletContext, useParams} from "react-router-dom"; import {useNavigation} from "../../hooks/navigationHook"; import { faCampground, @@ -25,14 +25,22 @@ import ErrorPage from "./ErrorPage"; import {SwitchTransition} from "react-transition-group"; import MainPageRedirect from "../../components/navigation/MainPageRedirect"; import {useDataRequest} from "../../hooks/dataFetchHook"; -import {fetchServerIdentity} from "../../service/serverService"; +import {fetchExtensionData, fetchServerIdentity} from "../../service/serverService"; +import ExtensionIcon from "../../components/extensions/ExtensionIcon"; const ServerPage = () => { const {t, i18n} = useTranslation(); const {identifier} = useParams(); const {isProxy, serverName} = useMetadata(); - const {data: serverIdentity, loadingError: identityLoadingError} = useDataRequest(fetchServerIdentity, [identifier]) + const { + data: serverIdentity, + loadingError: identityLoadingError + } = useDataRequest(fetchServerIdentity, [identifier]); + const { + data: extensionData, + loadingError: extensionDataLoadingError + } = useDataRequest(fetchExtensionData, [identifier]); const [error] = useState(undefined); const [sidebarItems, setSidebarItems] = useState([]); @@ -76,17 +84,30 @@ const ServerPage = () => { {name: 'html.label.performance', icon: faCogs, href: "performance"}, {}, {name: 'html.label.plugins'}, - {name: 'html.label.pluginsOverview', icon: faCubes, href: "plugins-overview"}, - {}, - {name: 'html.label.links'}, - {name: 'html.label.query', icon: faSearch, href: "/query"}, ] - // TODO Extensions + if (extensionData) { + items.push({name: 'html.label.pluginsOverview', icon: faCubes, href: "plugins-overview"}) + extensionData.extensions.filter(extension => extension.wide) + .map(extension => extension.extensionInformation) + .map(info => { + return { + name: info.pluginName, + icon: , + href: `plugins/${encodeURIComponent(info.pluginName)}` + } + }).forEach(item => items.push(item)) + } + + items.push( + {}, + {name: 'html.label.links'}, + {name: 'html.label.query', icon: faSearch, href: "/query"} + ); setSidebarItems(items); window.document.title = `Plan | Server Analysis`; - }, [t, i18n]) + }, [t, i18n, extensionData]) const {authRequired, loggedIn, user} = useAuth(); if (authRequired && !loggedIn) return @@ -113,6 +134,10 @@ const ServerPage = () => { error={{title: t('html.error.404NotFound'), message: t('html.error.serverNotSeen')}}/> return } + if (extensionDataLoadingError) { + return + } + if (!extensionData) return <> return ( <> @@ -123,7 +148,7 @@ const ServerPage = () => {
    - +