mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2025-01-21 15:41:24 +01:00
Implemented player ping graph on Frontend BETA player page
Affects issues: - Close #2258
This commit is contained in:
parent
52b8afe6cb
commit
f36f1202fc
@ -24,6 +24,7 @@ import com.djrapitops.plan.delivery.formatting.Formatter;
|
||||
import com.djrapitops.plan.delivery.formatting.Formatters;
|
||||
import com.djrapitops.plan.delivery.rendering.html.Html;
|
||||
import com.djrapitops.plan.delivery.rendering.json.graphs.Graphs;
|
||||
import com.djrapitops.plan.delivery.rendering.json.graphs.line.PingGraph;
|
||||
import com.djrapitops.plan.delivery.rendering.json.graphs.pie.WorldPie;
|
||||
import com.djrapitops.plan.extension.implementation.results.ExtensionData;
|
||||
import com.djrapitops.plan.extension.implementation.storage.queries.ExtensionPlayerDataQuery;
|
||||
@ -46,6 +47,7 @@ import com.djrapitops.plan.storage.database.queries.containers.PlayerContainerQu
|
||||
import com.djrapitops.plan.storage.database.queries.objects.ServerQueries;
|
||||
import com.djrapitops.plan.utilities.comparators.DateHolderRecentComparator;
|
||||
import com.djrapitops.plan.utilities.java.Lists;
|
||||
import com.djrapitops.plan.utilities.java.Maps;
|
||||
import org.apache.commons.text.StringEscapeUtils;
|
||||
|
||||
import javax.inject.Inject;
|
||||
@ -131,11 +133,26 @@ public class PlayerJSONCreator {
|
||||
data.put("calendar_series", graphs.calendar().playerCalendar(player).getEntries());
|
||||
data.put("server_pie_series", graphs.pie().serverPreferencePie(serverNames, worldTimesPerServer).getSlices());
|
||||
data.put("server_pie_colors", pieColors);
|
||||
data.put("ping_graph", createPingGraphJson(player));
|
||||
data.put("first_day", 1); // Monday
|
||||
data.put("extensions", playerExtensionData(playerUUID));
|
||||
return data;
|
||||
}
|
||||
|
||||
private Map<String, Object> createPingGraphJson(PlayerContainer player) {
|
||||
PingGraph pingGraph = graphs.line().pingGraph(player.getUnsafe(PlayerKeys.PING));
|
||||
return Maps.builder(String.class, Object.class)
|
||||
.put("min_ping_series", pingGraph.getMinGraph().getPoints())
|
||||
.put("avg_ping_series", pingGraph.getAvgGraph().getPoints())
|
||||
.put("max_ping_series", pingGraph.getMaxGraph().getPoints())
|
||||
.put("colors", Maps.builder(String.class, String.class)
|
||||
.put("min", theme.getValue(ThemeVal.GRAPH_MIN_PING))
|
||||
.put("avg", theme.getValue(ThemeVal.GRAPH_AVG_PING))
|
||||
.put("max", theme.getValue(ThemeVal.GRAPH_MAX_PING))
|
||||
.build())
|
||||
.build();
|
||||
}
|
||||
|
||||
private Map<String, Object> createOnlineActivityJSONMap(SessionsMutator sessionsMutator) {
|
||||
long now = System.currentTimeMillis();
|
||||
long monthAgo = now - TimeUnit.DAYS.toMillis(30L);
|
||||
|
55
Plan/react/dashboard/src/components/graphs/PingGraph.js
Normal file
55
Plan/react/dashboard/src/components/graphs/PingGraph.js
Normal file
@ -0,0 +1,55 @@
|
||||
import React, {useEffect} from "react";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import {useTheme} from "../../hooks/themeHook";
|
||||
import Highcharts from "highcharts/highstock";
|
||||
import {linegraphButtons, tooltip} from "../../util/graphs";
|
||||
|
||||
const PingGraph = ({data}) => {
|
||||
const {t} = useTranslation();
|
||||
const {graphTheming} = useTheme();
|
||||
|
||||
useEffect(() => {
|
||||
const avgPingSeries = {
|
||||
name: t('html.label.averagePing'),
|
||||
type: 'spline',
|
||||
tooltip: tooltip.twoDecimals,
|
||||
data: data.avg_ping_series,
|
||||
color: data.colors.avg
|
||||
}
|
||||
const maxPingSeries = {
|
||||
name: t('html.label.maxPing'),
|
||||
type: 'spline',
|
||||
tooltip: tooltip.twoDecimals,
|
||||
data: data.max_ping_series,
|
||||
color: data.colors.max
|
||||
}
|
||||
const minPingSeries = {
|
||||
name: t('html.label.minPing'),
|
||||
type: 'spline',
|
||||
tooltip: tooltip.twoDecimals,
|
||||
data: data.min_ping_series,
|
||||
color: data.colors.min
|
||||
}
|
||||
Highcharts.setOptions(graphTheming);
|
||||
Highcharts.stockChart("ping-graph", {
|
||||
rangeSelector: {
|
||||
selected: 2,
|
||||
buttons: linegraphButtons
|
||||
},
|
||||
yAxis: {
|
||||
softMax: 2,
|
||||
softMin: 0
|
||||
},
|
||||
title: {text: ''},
|
||||
series: [avgPingSeries, maxPingSeries, minPingSeries]
|
||||
})
|
||||
}, [data, graphTheming, t])
|
||||
|
||||
return (
|
||||
<div className="chart-area" id="ping-graph">
|
||||
<span className="loader"/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default PingGraph
|
@ -18,21 +18,30 @@ export const doSomeGetRequest = async (url, statusOptions) => {
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
for (const statusOption of statusOptions) {
|
||||
if (e.response.status === statusOption.status) {
|
||||
return {
|
||||
data: undefined,
|
||||
error: statusOption.get(response, e)
|
||||
};
|
||||
}
|
||||
}
|
||||
console.error(e);
|
||||
if (e.response !== undefined) {
|
||||
for (const statusOption of statusOptions) {
|
||||
if (e.response.status === statusOption.status) {
|
||||
return {
|
||||
data: undefined,
|
||||
error: statusOption.get(response, e)
|
||||
};
|
||||
}
|
||||
}
|
||||
return {
|
||||
data: undefined,
|
||||
error: {
|
||||
message: e.message,
|
||||
url,
|
||||
data: e.response.data
|
||||
}
|
||||
};
|
||||
}
|
||||
return {
|
||||
data: undefined,
|
||||
error: {
|
||||
message: e.message,
|
||||
url,
|
||||
data: e.response.data
|
||||
url
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -38,10 +38,15 @@ export const localeService = {
|
||||
init: async function () {
|
||||
try {
|
||||
const {data} = await fetchAvailableLocales();
|
||||
|
||||
this.defaultLanguage = data.defaultLanguage;
|
||||
this.availableLanguages = data.languages;
|
||||
this.languageVersions = data.languageVersions;
|
||||
if (data !== undefined) {
|
||||
this.defaultLanguage = data.defaultLanguage;
|
||||
this.availableLanguages = data.languages;
|
||||
this.languageVersions = data.languageVersions;
|
||||
} else {
|
||||
this.defaultLanguage = 'en'
|
||||
this.availableLanguages = [];
|
||||
this.languageVersions = [];
|
||||
}
|
||||
|
||||
this.clientLocale = window.localStorage.getItem("locale");
|
||||
if (!this.clientLocale) {
|
||||
|
@ -1,13 +1,32 @@
|
||||
import React from "react";
|
||||
import {Card, Col, Row} from "react-bootstrap-v5";
|
||||
import {FontAwesomeIcon as Fa} from "@fortawesome/react-fontawesome";
|
||||
import {faCalendar, faHandPointer} from "@fortawesome/free-regular-svg-icons";
|
||||
import {faHandPointer} from "@fortawesome/free-regular-svg-icons";
|
||||
import Scrollable from "../components/Scrollable";
|
||||
import {faNetworkWired} from "@fortawesome/free-solid-svg-icons";
|
||||
import {faNetworkWired, faSignal} from "@fortawesome/free-solid-svg-icons";
|
||||
import ServerPie from "../components/graphs/ServerPie";
|
||||
import ServerAccordion from "../components/accordion/ServerAccordion";
|
||||
import {usePlayer} from "./PlayerPage";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import PingGraph from "../components/graphs/PingGraph";
|
||||
|
||||
const PingGraphCard = ({player}) => {
|
||||
const {t} = useTranslation();
|
||||
|
||||
const hasPingData = Boolean(player.ping_graph.avg_ping_series.length);
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<Card.Header>
|
||||
<h6 className="col-black" style={{width: '100%'}}>
|
||||
<Fa icon={faSignal} className="col-amber"/> {t('html.label.ping')}
|
||||
</h6>
|
||||
</Card.Header>
|
||||
{hasPingData && <PingGraph data={player.ping_graph}/>}
|
||||
{!hasPingData && <Card.Body><p>{t('generic.noData')}</p></Card.Body>}
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
const ServersCard = ({player}) => {
|
||||
const {t} = useTranslation();
|
||||
@ -15,7 +34,7 @@ const ServersCard = ({player}) => {
|
||||
<Card>
|
||||
<Card.Header>
|
||||
<h6 className="col-black" style={{width: '100%'}}>
|
||||
<Fa icon={faCalendar} className="col-teal"/> {t('html.label.recentSessions')}
|
||||
<Fa icon={faNetworkWired} className="col-light-green"/> {t('html.label.servers')}
|
||||
<span className="float-end">
|
||||
<Fa icon={faHandPointer}/> <small>{t('html.text.clickToExpand')}</small>
|
||||
</span>
|
||||
@ -50,6 +69,11 @@ const PlayerServers = () => {
|
||||
const {player} = usePlayer();
|
||||
return (
|
||||
<section className="player_sessions">
|
||||
<Row>
|
||||
<Col lg={12}>
|
||||
<PingGraphCard player={player}/>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col lg={8}>
|
||||
<ServersCard player={player}/>
|
||||
|
Loading…
Reference in New Issue
Block a user