mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2024-07-01 00:54:55 +02:00
Network sessions tab implemented in React
This commit is contained in:
parent
b8258a38a6
commit
adc4162217
|
@ -108,7 +108,7 @@ public enum HtmlLang implements Lang {
|
||||||
LABEL_AVG_ENTITIES("html.label.averageEntities", "Average Entities"),
|
LABEL_AVG_ENTITIES("html.label.averageEntities", "Average Entities"),
|
||||||
LABEL_AVG_CHUNKS("html.label.averageChunks", "Average Chunks"),
|
LABEL_AVG_CHUNKS("html.label.averageChunks", "Average Chunks"),
|
||||||
LABEL_LOW_TPS("html.label.lowTpsSpikes", "Low TPS Spikes"),
|
LABEL_LOW_TPS("html.label.lowTpsSpikes", "Low TPS Spikes"),
|
||||||
LABEL_LOW_TPS_7_DAYS("html.label.lowTpsSpikes", "Low TPS Spikes (7 days)"),
|
LABEL_LOW_TPS_7_DAYS("html.label.lowTpsSpikes7days", "Low TPS Spikes (7 days)"),
|
||||||
LABEL_DOWNTIME("html.label.downtime", "Downtime"),
|
LABEL_DOWNTIME("html.label.downtime", "Downtime"),
|
||||||
// Sessions tab #tab-sessions-overview
|
// Sessions tab #tab-sessions-overview
|
||||||
TITLE_RECENT_SESSIONS("html.label.recentSessions", "Recent Sessions"),
|
TITLE_RECENT_SESSIONS("html.label.recentSessions", "Recent Sessions"),
|
||||||
|
|
|
@ -37,6 +37,7 @@ const ServerJoinAddresses = React.lazy(() => import("./views/server/ServerJoinAd
|
||||||
const NetworkPage = React.lazy(() => import("./views/layout/NetworkPage"));
|
const NetworkPage = React.lazy(() => import("./views/layout/NetworkPage"));
|
||||||
const NetworkOverview = React.lazy(() => import("./views/network/NetworkOverview"));
|
const NetworkOverview = React.lazy(() => import("./views/network/NetworkOverview"));
|
||||||
const NetworkServers = React.lazy(() => import("./views/network/NetworkServers"));
|
const NetworkServers = React.lazy(() => import("./views/network/NetworkServers"));
|
||||||
|
const NetworkSessions = React.lazy(() => import("./views/network/NetworkSessions"));
|
||||||
|
|
||||||
const PlayersPage = React.lazy(() => import("./views/layout/PlayersPage"));
|
const PlayersPage = React.lazy(() => import("./views/layout/PlayersPage"));
|
||||||
const AllPlayers = React.lazy(() => import("./views/players/AllPlayers"));
|
const AllPlayers = React.lazy(() => import("./views/players/AllPlayers"));
|
||||||
|
@ -119,6 +120,7 @@ function App() {
|
||||||
<Route path="" element={<Lazy><OverviewRedirect/></Lazy>}/>
|
<Route path="" element={<Lazy><OverviewRedirect/></Lazy>}/>
|
||||||
<Route path="overview" element={<Lazy><NetworkOverview/></Lazy>}/>
|
<Route path="overview" element={<Lazy><NetworkOverview/></Lazy>}/>
|
||||||
<Route path="serversOverview" element={<Lazy><NetworkServers/></Lazy>}/>
|
<Route path="serversOverview" element={<Lazy><NetworkServers/></Lazy>}/>
|
||||||
|
<Route path="sessions" element={<Lazy><NetworkSessions/></Lazy>}/>
|
||||||
<Route path="players" element={<Lazy><AllPlayers/></Lazy>}/>
|
<Route path="players" element={<Lazy><AllPlayers/></Lazy>}/>
|
||||||
<Route path="plugins-overview" element={<Lazy><ServerPluginData/></Lazy>}/>
|
<Route path="plugins-overview" element={<Lazy><ServerPluginData/></Lazy>}/>
|
||||||
<Route path="plugins/:plugin" element={<Lazy><ServerWidePluginData/></Lazy>}/>
|
<Route path="plugins/:plugin" element={<Lazy><ServerWidePluginData/></Lazy>}/>
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
import {Card} from "react-bootstrap-v5";
|
||||||
|
import React from "react";
|
||||||
|
import {CardLoader} from "../../navigation/Loader";
|
||||||
|
import ServerPie from "../../graphs/ServerPie";
|
||||||
|
import {faNetworkWired} from "@fortawesome/free-solid-svg-icons";
|
||||||
|
import CardHeader from "../CardHeader";
|
||||||
|
import {useDataRequest} from "../../../hooks/dataFetchHook";
|
||||||
|
import {fetchServerPie} from "../../../service/networkService";
|
||||||
|
import {ErrorViewCard} from "../../../views/ErrorView";
|
||||||
|
|
||||||
|
const ServerPieCard = () => {
|
||||||
|
const {data, loadingError} = useDataRequest(fetchServerPie, []);
|
||||||
|
|
||||||
|
if (!data) return <CardLoader/>;
|
||||||
|
if (loadingError) return <ErrorViewCard error={loadingError}/>;
|
||||||
|
|
||||||
|
const series = data.server_pie_series_30d;
|
||||||
|
const colors = data.server_pie_colors;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<CardHeader icon={faNetworkWired} color={'teal'} label={'html.label.serverPlaytime30days'}/>
|
||||||
|
<ServerPie series={series} colors={colors}/>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ServerPieCard;
|
|
@ -1,6 +1,5 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import InsightsFor30DaysCard from "../../common/InsightsFor30DaysCard";
|
import InsightsFor30DaysCard from "../../common/InsightsFor30DaysCard";
|
||||||
import {useParams} from "react-router-dom";
|
|
||||||
import {useDataRequest} from "../../../../hooks/dataFetchHook";
|
import {useDataRequest} from "../../../../hooks/dataFetchHook";
|
||||||
import {fetchSessionOverview} from "../../../../service/serverService";
|
import {fetchSessionOverview} from "../../../../service/serverService";
|
||||||
import {ErrorViewCard} from "../../../../views/ErrorView";
|
import {ErrorViewCard} from "../../../../views/ErrorView";
|
||||||
|
@ -8,29 +7,35 @@ import Datapoint from "../../../Datapoint";
|
||||||
import {useTranslation} from "react-i18next";
|
import {useTranslation} from "react-i18next";
|
||||||
import {faGamepad, faUsers} from "@fortawesome/free-solid-svg-icons";
|
import {faGamepad, faUsers} from "@fortawesome/free-solid-svg-icons";
|
||||||
import {faClock} from "@fortawesome/free-regular-svg-icons";
|
import {faClock} from "@fortawesome/free-regular-svg-icons";
|
||||||
|
import {fetchNetworkSessionsOverview} from "../../../../service/networkService";
|
||||||
|
|
||||||
const SessionInsightsCard = () => {
|
const SessionInsightsCard = ({identifier}) => {
|
||||||
const {t} = useTranslation();
|
const {t} = useTranslation();
|
||||||
const {identifier} = useParams();
|
|
||||||
|
|
||||||
const {data, loadingError} = useDataRequest(fetchSessionOverview, [identifier]);
|
const {
|
||||||
|
data,
|
||||||
|
loadingError
|
||||||
|
} = useDataRequest(identifier ? fetchSessionOverview : fetchNetworkSessionsOverview, [identifier]);
|
||||||
|
|
||||||
if (loadingError) return <ErrorViewCard error={loadingError}/>
|
if (loadingError) return <ErrorViewCard error={loadingError}/>
|
||||||
|
|
||||||
|
const insights = data?.insights;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<InsightsFor30DaysCard>
|
<InsightsFor30DaysCard>
|
||||||
<Datapoint name={t('html.label.mostActiveGamemode')} icon={faGamepad} color="teal" bold
|
<Datapoint name={t('html.label.mostActiveGamemode')} icon={faGamepad} color="teal" bold
|
||||||
value={data?.insights.most_active_gamemode}
|
value={insights?.most_active_gamemode}
|
||||||
valueLabel={data?.insights.most_active_gamemode_perc}
|
valueLabel={insights?.most_active_gamemode_perc}
|
||||||
/>
|
/>
|
||||||
<Datapoint name={t('html.label.serverOccupied')} icon={faUsers} color="teal"
|
<Datapoint name={t('html.label.serverOccupied')} icon={faUsers} color="teal"
|
||||||
value={'~' + data?.insights.server_occupied} valueLabel={data?.insights.server_occupied_perc}
|
value={insights?.server_occupied ? '~' + insights.server_occupied : undefined}
|
||||||
|
valueLabel={insights?.server_occupied_perc}
|
||||||
/>
|
/>
|
||||||
<Datapoint name={t('html.label.playtime')} icon={faClock} color="green"
|
<Datapoint name={t('html.label.playtime')} icon={faClock} color="green"
|
||||||
value={data?.insights.total_playtime}
|
value={insights?.total_playtime}
|
||||||
/>
|
/>
|
||||||
<Datapoint name={t('html.label.afkTime')} icon={faClock} color="grey"
|
<Datapoint name={t('html.label.afkTime')} icon={faClock} color="grey"
|
||||||
value={data?.insights.afk_time} valueLabel={data?.insights.afk_time_perc}
|
value={insights?.afk_time} valueLabel={insights?.afk_time_perc}
|
||||||
/>
|
/>
|
||||||
</InsightsFor30DaysCard>
|
</InsightsFor30DaysCard>
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,14 +1,10 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import {useParams} from "react-router-dom";
|
|
||||||
import {useDataRequest} from "../../../../hooks/dataFetchHook";
|
import {useDataRequest} from "../../../../hooks/dataFetchHook";
|
||||||
import {fetchSessions} from "../../../../service/serverService";
|
import {fetchSessions} from "../../../../service/serverService";
|
||||||
import {ErrorViewCard} from "../../../../views/ErrorView";
|
import {ErrorViewCard} from "../../../../views/ErrorView";
|
||||||
import RecentSessionsCard from "../../common/RecentSessionsCard";
|
import RecentSessionsCard from "../../common/RecentSessionsCard";
|
||||||
|
|
||||||
const ServerRecentSessionsCard = () => {
|
const ServerRecentSessionsCard = ({identifier}) => {
|
||||||
|
|
||||||
const {identifier} = useParams();
|
|
||||||
|
|
||||||
const {data, loadingError} = useDataRequest(fetchSessions, [identifier])
|
const {data, loadingError} = useDataRequest(fetchSessions, [identifier])
|
||||||
|
|
||||||
if (loadingError) return <ErrorViewCard error={loadingError}/>
|
if (loadingError) return <ErrorViewCard error={loadingError}/>
|
||||||
|
|
|
@ -5,6 +5,7 @@ import {withReducedSaturation} from "../../util/colors";
|
||||||
import Highcharts from 'highcharts/highmaps.js';
|
import Highcharts from 'highcharts/highmaps.js';
|
||||||
import map from '@highcharts/map-collection/custom/world.geo.json';
|
import map from '@highcharts/map-collection/custom/world.geo.json';
|
||||||
import Accessibility from "highcharts/modules/accessibility";
|
import Accessibility from "highcharts/modules/accessibility";
|
||||||
|
import NoDataDisplay from "highcharts/modules/no-data-to-display";
|
||||||
|
|
||||||
const GeolocationWorldMap = ({series, colors}) => {
|
const GeolocationWorldMap = ({series, colors}) => {
|
||||||
const {t} = useTranslation();
|
const {t} = useTranslation();
|
||||||
|
@ -19,8 +20,10 @@ const GeolocationWorldMap = ({series, colors}) => {
|
||||||
joinBy: ['iso-a3', 'code']
|
joinBy: ['iso-a3', 'code']
|
||||||
};
|
};
|
||||||
|
|
||||||
|
NoDataDisplay(Highcharts);
|
||||||
Accessibility(Highcharts);
|
Accessibility(Highcharts);
|
||||||
Highcharts.setOptions(graphTheming);
|
Highcharts.setOptions(graphTheming);
|
||||||
|
Highcharts.setOptions({lang: {noData: t('html.label.noDataToDisplay')}});
|
||||||
Highcharts.mapChart('countryWorldMap', {
|
Highcharts.mapChart('countryWorldMap', {
|
||||||
chart: {
|
chart: {
|
||||||
animation: true
|
animation: true
|
||||||
|
|
|
@ -5,6 +5,7 @@ import {formatTimeAmount} from '../../util/formatters'
|
||||||
import {useTheme} from "../../hooks/themeHook";
|
import {useTheme} from "../../hooks/themeHook";
|
||||||
import {withReducedSaturation} from "../../util/colors";
|
import {withReducedSaturation} from "../../util/colors";
|
||||||
import {useTranslation} from "react-i18next";
|
import {useTranslation} from "react-i18next";
|
||||||
|
import NoDataDisplay from "highcharts/modules/no-data-to-display";
|
||||||
import Accessibility from "highcharts/modules/accessibility";
|
import Accessibility from "highcharts/modules/accessibility";
|
||||||
|
|
||||||
const ServerPie = ({colors, series}) => {
|
const ServerPie = ({colors, series}) => {
|
||||||
|
@ -21,8 +22,10 @@ const ServerPie = ({colors, series}) => {
|
||||||
data: series
|
data: series
|
||||||
};
|
};
|
||||||
|
|
||||||
|
NoDataDisplay(Highcharts);
|
||||||
Accessibility(Highcharts);
|
Accessibility(Highcharts);
|
||||||
Highcharts.setOptions(graphTheming);
|
Highcharts.setOptions(graphTheming);
|
||||||
|
Highcharts.setOptions({lang: {noData: t('html.label.noDataToDisplay')}});
|
||||||
Highcharts.chart('server-pie', {
|
Highcharts.chart('server-pie', {
|
||||||
chart: {
|
chart: {
|
||||||
backgroundColor: 'transparent',
|
backgroundColor: 'transparent',
|
||||||
|
|
|
@ -51,7 +51,7 @@ export const useDataRequest = (fetchMethod, parameters) => {
|
||||||
console.warn(error);
|
console.warn(error);
|
||||||
datastore.finishUpdate(fetchMethod)
|
datastore.finishUpdate(fetchMethod)
|
||||||
setLoadingError(error);
|
setLoadingError(error);
|
||||||
finishUpdate(new Date().getTime(), "Error", datastore.isSomethingUpdating());
|
finishUpdate(new Date().getTime(), "Error: " + error, datastore.isSomethingUpdating());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -9,3 +9,13 @@ export const fetchServersOverview = async (updateRequested) => {
|
||||||
const url = `/v1/network/servers?timestamp=${updateRequested}`;
|
const url = `/v1/network/servers?timestamp=${updateRequested}`;
|
||||||
return doGetRequest(url);
|
return doGetRequest(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const fetchServerPie = async (timestamp) => {
|
||||||
|
const url = `/v1/graph?type=serverPie×tamp=${timestamp}`;
|
||||||
|
return doGetRequest(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const fetchNetworkSessionsOverview = async (timestamp) => {
|
||||||
|
const url = `/v1/network/sessionsOverview?timestamp=${timestamp}`;
|
||||||
|
return doGetRequest(url);
|
||||||
|
}
|
|
@ -42,7 +42,8 @@ export const fetchExtensionData = async (timestamp, identifier) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const fetchSessions = async (timestamp, identifier) => {
|
export const fetchSessions = async (timestamp, identifier) => {
|
||||||
const url = `/v1/sessions?server=${identifier}×tamp=${timestamp}`;
|
const url = identifier ? `/v1/sessions?server=${identifier}×tamp=${timestamp}` :
|
||||||
|
`/v1/sessions?timestamp=${timestamp}`;
|
||||||
return doGetRequest(url);
|
return doGetRequest(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
26
Plan/react/dashboard/src/views/network/NetworkSessions.js
Normal file
26
Plan/react/dashboard/src/views/network/NetworkSessions.js
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
import {Col, Row} from "react-bootstrap-v5";
|
||||||
|
import React from "react";
|
||||||
|
import ServerRecentSessionsCard from "../../components/cards/server/tables/ServerRecentSessionsCard";
|
||||||
|
import SessionInsightsCard from "../../components/cards/server/insights/SessionInsightsCard";
|
||||||
|
import LoadIn from "../../components/animation/LoadIn";
|
||||||
|
import ServerPieCard from "../../components/cards/common/ServerPieCard";
|
||||||
|
|
||||||
|
const NetworkSessions = () => {
|
||||||
|
return (
|
||||||
|
<LoadIn>
|
||||||
|
<section className="server_sessions">
|
||||||
|
<Row>
|
||||||
|
<Col lg={8}>
|
||||||
|
<ServerRecentSessionsCard identifier={undefined}/>
|
||||||
|
</Col>
|
||||||
|
<Col lg={4}>
|
||||||
|
<ServerPieCard/>
|
||||||
|
<SessionInsightsCard identifier={undefined}/>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</section>
|
||||||
|
</LoadIn>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default NetworkSessions;
|
|
@ -4,18 +4,20 @@ import ServerWorldPieCard from "../../components/cards/server/graphs/ServerWorld
|
||||||
import ServerRecentSessionsCard from "../../components/cards/server/tables/ServerRecentSessionsCard";
|
import ServerRecentSessionsCard from "../../components/cards/server/tables/ServerRecentSessionsCard";
|
||||||
import SessionInsightsCard from "../../components/cards/server/insights/SessionInsightsCard";
|
import SessionInsightsCard from "../../components/cards/server/insights/SessionInsightsCard";
|
||||||
import LoadIn from "../../components/animation/LoadIn";
|
import LoadIn from "../../components/animation/LoadIn";
|
||||||
|
import {useParams} from "react-router-dom";
|
||||||
|
|
||||||
const ServerSessions = () => {
|
const ServerSessions = () => {
|
||||||
|
const {identifier} = useParams();
|
||||||
return (
|
return (
|
||||||
<LoadIn>
|
<LoadIn>
|
||||||
<section className="server_sessions">
|
<section className="server_sessions">
|
||||||
<Row>
|
<Row>
|
||||||
<Col lg={8}>
|
<Col lg={8}>
|
||||||
<ServerRecentSessionsCard/>
|
<ServerRecentSessionsCard identifier={identifier}/>
|
||||||
</Col>
|
</Col>
|
||||||
<Col lg={4}>
|
<Col lg={4}>
|
||||||
<ServerWorldPieCard/>
|
<ServerWorldPieCard/>
|
||||||
<SessionInsightsCard/>
|
<SessionInsightsCard identifier={identifier}/>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
</section>
|
</section>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user