mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2025-01-18 22:21:38 +01:00
Format Server/Network Overview values in the frontend
This commit is contained in:
parent
f9d2b0767f
commit
8e94d26ff3
@ -16,7 +16,6 @@
|
|||||||
*/
|
*/
|
||||||
package com.djrapitops.plan.delivery.rendering.json;
|
package com.djrapitops.plan.delivery.rendering.json;
|
||||||
|
|
||||||
import com.djrapitops.plan.delivery.domain.DateHolder;
|
|
||||||
import com.djrapitops.plan.delivery.domain.DateObj;
|
import com.djrapitops.plan.delivery.domain.DateObj;
|
||||||
import com.djrapitops.plan.delivery.domain.mutators.TPSMutator;
|
import com.djrapitops.plan.delivery.domain.mutators.TPSMutator;
|
||||||
import com.djrapitops.plan.delivery.formatting.Formatter;
|
import com.djrapitops.plan.delivery.formatting.Formatter;
|
||||||
@ -55,17 +54,14 @@ import java.util.concurrent.TimeUnit;
|
|||||||
@Singleton
|
@Singleton
|
||||||
public class ServerOverviewJSONCreator implements ServerTabJSONCreator<Map<String, Object>> {
|
public class ServerOverviewJSONCreator implements ServerTabJSONCreator<Map<String, Object>> {
|
||||||
|
|
||||||
private final Formatter<Long> day;
|
|
||||||
private final PlanConfig config;
|
private final PlanConfig config;
|
||||||
private final DBSystem dbSystem;
|
private final DBSystem dbSystem;
|
||||||
private final ServerInfo serverInfo;
|
private final ServerInfo serverInfo;
|
||||||
private final ServerSensor<?> serverSensor;
|
private final ServerSensor<?> serverSensor;
|
||||||
|
|
||||||
private final Formatter<Long> timeAmount;
|
|
||||||
private final Formatter<Double> decimals;
|
private final Formatter<Double> decimals;
|
||||||
private final Formatter<Double> percentage;
|
private final Formatter<Double> percentage;
|
||||||
private final ServerUptimeCalculator serverUptimeCalculator;
|
private final ServerUptimeCalculator serverUptimeCalculator;
|
||||||
private final Formatter<DateHolder> year;
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public ServerOverviewJSONCreator(
|
public ServerOverviewJSONCreator(
|
||||||
@ -82,9 +78,6 @@ public class ServerOverviewJSONCreator implements ServerTabJSONCreator<Map<Strin
|
|||||||
this.serverSensor = serverSensor;
|
this.serverSensor = serverSensor;
|
||||||
this.serverUptimeCalculator = serverUptimeCalculator;
|
this.serverUptimeCalculator = serverUptimeCalculator;
|
||||||
|
|
||||||
year = formatters.year();
|
|
||||||
day = formatters.dayLong();
|
|
||||||
timeAmount = formatters.timeAmount();
|
|
||||||
decimals = formatters.decimals();
|
decimals = formatters.decimals();
|
||||||
percentage = formatters.percentage();
|
percentage = formatters.percentage();
|
||||||
}
|
}
|
||||||
@ -118,7 +111,7 @@ public class ServerOverviewJSONCreator implements ServerTabJSONCreator<Map<Strin
|
|||||||
double averageTPS = tpsMutator.averageTPS();
|
double averageTPS = tpsMutator.averageTPS();
|
||||||
sevenDays.put("average_tps", averageTPS != -1 ? decimals.apply(averageTPS) : GenericLang.UNAVAILABLE.getKey());
|
sevenDays.put("average_tps", averageTPS != -1 ? decimals.apply(averageTPS) : GenericLang.UNAVAILABLE.getKey());
|
||||||
sevenDays.put("low_tps_spikes", tpsMutator.lowTpsSpikeCount(config.get(DisplaySettings.GRAPH_TPS_THRESHOLD_MED)));
|
sevenDays.put("low_tps_spikes", tpsMutator.lowTpsSpikeCount(config.get(DisplaySettings.GRAPH_TPS_THRESHOLD_MED)));
|
||||||
sevenDays.put("downtime", timeAmount.apply(tpsMutator.serverDownTime()));
|
sevenDays.put("downtime", tpsMutator.serverDownTime());
|
||||||
|
|
||||||
return sevenDays;
|
return sevenDays;
|
||||||
}
|
}
|
||||||
@ -137,18 +130,19 @@ public class ServerOverviewJSONCreator implements ServerTabJSONCreator<Map<Strin
|
|||||||
numbers.put("online_players", getOnlinePlayers(serverUUID, db));
|
numbers.put("online_players", getOnlinePlayers(serverUUID, db));
|
||||||
Optional<DateObj<Integer>> lastPeak = db.query(TPSQueries.fetchPeakPlayerCount(serverUUID, twoDaysAgo));
|
Optional<DateObj<Integer>> lastPeak = db.query(TPSQueries.fetchPeakPlayerCount(serverUUID, twoDaysAgo));
|
||||||
Optional<DateObj<Integer>> allTimePeak = db.query(TPSQueries.fetchAllTimePeakPlayerCount(serverUUID));
|
Optional<DateObj<Integer>> allTimePeak = db.query(TPSQueries.fetchAllTimePeakPlayerCount(serverUUID));
|
||||||
numbers.put("last_peak_date", lastPeak.map(year).orElse("-"));
|
numbers.put("last_peak_date", lastPeak.map(DateObj::getDate).map(Object.class::cast).orElse("-"));
|
||||||
numbers.put("last_peak_players", lastPeak.map(dateObj -> dateObj.getValue().toString()).orElse("-"));
|
numbers.put("last_peak_players", lastPeak.map(dateObj -> dateObj.getValue().toString()).orElse("-"));
|
||||||
numbers.put("best_peak_date", allTimePeak.map(year).orElse("-"));
|
numbers.put("best_peak_date", allTimePeak.map(DateObj::getDate).map(Object.class::cast).orElse("-"));
|
||||||
numbers.put("best_peak_players", allTimePeak.map(dateObj -> dateObj.getValue().toString()).orElse("-"));
|
numbers.put("best_peak_players", allTimePeak.map(dateObj -> dateObj.getValue().toString()).orElse("-"));
|
||||||
Long totalPlaytime = db.query(SessionQueries.playtime(0L, now, serverUUID));
|
Long totalPlaytime = db.query(SessionQueries.playtime(0L, now, serverUUID));
|
||||||
numbers.put("playtime", timeAmount.apply(totalPlaytime));
|
numbers.put("playtime", totalPlaytime);
|
||||||
numbers.put("player_playtime", userCount != 0 ? timeAmount.apply(totalPlaytime / userCount) : "-");
|
numbers.put("player_playtime", userCount != 0 ? totalPlaytime / userCount : "-");
|
||||||
numbers.put("sessions", db.query(SessionQueries.sessionCount(0L, now, serverUUID)));
|
numbers.put("sessions", db.query(SessionQueries.sessionCount(0L, now, serverUUID)));
|
||||||
numbers.put("player_kills", db.query(KillQueries.playerKillCount(0L, now, serverUUID)));
|
numbers.put("player_kills", db.query(KillQueries.playerKillCount(0L, now, serverUUID)));
|
||||||
numbers.put("mob_kills", db.query(KillQueries.mobKillCount(0L, now, serverUUID)));
|
numbers.put("mob_kills", db.query(KillQueries.mobKillCount(0L, now, serverUUID)));
|
||||||
numbers.put("deaths", db.query(KillQueries.deathCount(0L, now, serverUUID)));
|
numbers.put("deaths", db.query(KillQueries.deathCount(0L, now, serverUUID)));
|
||||||
numbers.put("current_uptime", serverUptimeCalculator.getServerUptimeMillis(serverUUID).map(timeAmount)
|
numbers.put("current_uptime", serverUptimeCalculator.getServerUptimeMillis(serverUUID)
|
||||||
|
.map(Object.class::cast)
|
||||||
.orElse(GenericLang.UNAVAILABLE.getKey()));
|
.orElse(GenericLang.UNAVAILABLE.getKey()));
|
||||||
|
|
||||||
return numbers;
|
return numbers;
|
||||||
@ -171,9 +165,9 @@ public class ServerOverviewJSONCreator implements ServerTabJSONCreator<Map<Strin
|
|||||||
|
|
||||||
Map<String, Object> weeks = new HashMap<>();
|
Map<String, Object> weeks = new HashMap<>();
|
||||||
|
|
||||||
weeks.put("start", day.apply(twoWeeksAgo));
|
weeks.put("start", twoWeeksAgo);
|
||||||
weeks.put("midpoint", day.apply(oneWeekAgo));
|
weeks.put("midpoint", oneWeekAgo);
|
||||||
weeks.put("end", day.apply(now));
|
weeks.put("end", now);
|
||||||
|
|
||||||
Integer uniqueBefore = db.query(PlayerCountQueries.uniquePlayerCount(twoWeeksAgo, oneWeekAgo, serverUUID));
|
Integer uniqueBefore = db.query(PlayerCountQueries.uniquePlayerCount(twoWeeksAgo, oneWeekAgo, serverUUID));
|
||||||
Integer uniqueAfter = db.query(PlayerCountQueries.uniquePlayerCount(oneWeekAgo, now, serverUUID));
|
Integer uniqueAfter = db.query(PlayerCountQueries.uniquePlayerCount(oneWeekAgo, now, serverUUID));
|
||||||
@ -199,9 +193,9 @@ public class ServerOverviewJSONCreator implements ServerTabJSONCreator<Map<Strin
|
|||||||
Long playtimeAfter = db.query(SessionQueries.playtime(oneWeekAgo, now, serverUUID));
|
Long playtimeAfter = db.query(SessionQueries.playtime(oneWeekAgo, now, serverUUID));
|
||||||
long avgPlaytimeBefore = uniqueBefore != 0 ? playtimeBefore / uniqueBefore : 0L;
|
long avgPlaytimeBefore = uniqueBefore != 0 ? playtimeBefore / uniqueBefore : 0L;
|
||||||
long avgPlaytimeAfter = uniqueAfter != 0 ? playtimeAfter / uniqueAfter : 0L;
|
long avgPlaytimeAfter = uniqueAfter != 0 ? playtimeAfter / uniqueAfter : 0L;
|
||||||
Trend avgPlaytimeTrend = new Trend(avgPlaytimeBefore, avgPlaytimeAfter, false, timeAmount);
|
Trend avgPlaytimeTrend = new Trend(avgPlaytimeBefore, avgPlaytimeAfter, false);
|
||||||
weeks.put("average_playtime_before", timeAmount.apply(avgPlaytimeBefore));
|
weeks.put("average_playtime_before", avgPlaytimeBefore);
|
||||||
weeks.put("average_playtime_after", timeAmount.apply(avgPlaytimeAfter));
|
weeks.put("average_playtime_after", avgPlaytimeAfter);
|
||||||
weeks.put("average_playtime_trend", avgPlaytimeTrend);
|
weeks.put("average_playtime_trend", avgPlaytimeTrend);
|
||||||
|
|
||||||
Long sessionsBefore = db.query(SessionQueries.sessionCount(twoWeeksAgo, oneWeekAgo, serverUUID));
|
Long sessionsBefore = db.query(SessionQueries.sessionCount(twoWeeksAgo, oneWeekAgo, serverUUID));
|
||||||
|
@ -16,9 +16,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.djrapitops.plan.delivery.rendering.json.network;
|
package com.djrapitops.plan.delivery.rendering.json.network;
|
||||||
|
|
||||||
import com.djrapitops.plan.delivery.domain.DateHolder;
|
|
||||||
import com.djrapitops.plan.delivery.domain.DateObj;
|
import com.djrapitops.plan.delivery.domain.DateObj;
|
||||||
import com.djrapitops.plan.delivery.formatting.Formatter;
|
|
||||||
import com.djrapitops.plan.delivery.formatting.Formatters;
|
import com.djrapitops.plan.delivery.formatting.Formatters;
|
||||||
import com.djrapitops.plan.delivery.rendering.json.Trend;
|
import com.djrapitops.plan.delivery.rendering.json.Trend;
|
||||||
import com.djrapitops.plan.gathering.ServerSensor;
|
import com.djrapitops.plan.gathering.ServerSensor;
|
||||||
@ -50,14 +48,11 @@ import java.util.concurrent.TimeUnit;
|
|||||||
@Singleton
|
@Singleton
|
||||||
public class NetworkOverviewJSONCreator implements NetworkTabJSONCreator<Map<String, Object>> {
|
public class NetworkOverviewJSONCreator implements NetworkTabJSONCreator<Map<String, Object>> {
|
||||||
|
|
||||||
private final Formatter<Long> day;
|
|
||||||
private final PlanConfig config;
|
private final PlanConfig config;
|
||||||
private final DBSystem dbSystem;
|
private final DBSystem dbSystem;
|
||||||
private final ServerInfo serverInfo;
|
private final ServerInfo serverInfo;
|
||||||
private final ServerSensor<?> serverSensor;
|
private final ServerSensor<?> serverSensor;
|
||||||
private final Formatter<Long> timeAmount;
|
|
||||||
private final ServerUptimeCalculator serverUptimeCalculator;
|
private final ServerUptimeCalculator serverUptimeCalculator;
|
||||||
private final Formatter<DateHolder> year;
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public NetworkOverviewJSONCreator(
|
public NetworkOverviewJSONCreator(
|
||||||
@ -73,10 +68,6 @@ public class NetworkOverviewJSONCreator implements NetworkTabJSONCreator<Map<Str
|
|||||||
this.serverInfo = serverInfo;
|
this.serverInfo = serverInfo;
|
||||||
this.serverSensor = serverSensor;
|
this.serverSensor = serverSensor;
|
||||||
this.serverUptimeCalculator = serverUptimeCalculator;
|
this.serverUptimeCalculator = serverUptimeCalculator;
|
||||||
|
|
||||||
year = formatters.year();
|
|
||||||
day = formatters.dayLong();
|
|
||||||
timeAmount = formatters.timeAmount();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, Object> createJSONAsMap() {
|
public Map<String, Object> createJSONAsMap() {
|
||||||
@ -122,17 +113,18 @@ public class NetworkOverviewJSONCreator implements NetworkTabJSONCreator<Map<Str
|
|||||||
ServerUUID serverUUID = serverInfo.getServerUUID();
|
ServerUUID serverUUID = serverInfo.getServerUUID();
|
||||||
Optional<DateObj<Integer>> lastPeak = db.query(TPSQueries.fetchPeakPlayerCount(serverUUID, twoDaysAgo));
|
Optional<DateObj<Integer>> lastPeak = db.query(TPSQueries.fetchPeakPlayerCount(serverUUID, twoDaysAgo));
|
||||||
Optional<DateObj<Integer>> allTimePeak = db.query(TPSQueries.fetchAllTimePeakPlayerCount(serverUUID));
|
Optional<DateObj<Integer>> allTimePeak = db.query(TPSQueries.fetchAllTimePeakPlayerCount(serverUUID));
|
||||||
numbers.put("last_peak_date", lastPeak.map(year).orElse("-"));
|
numbers.put("last_peak_date", lastPeak.map(DateObj::getDate).map(Object.class::cast).orElse("-"));
|
||||||
numbers.put("last_peak_players", lastPeak.map(dateObj -> dateObj.getValue().toString()).orElse("-"));
|
numbers.put("last_peak_players", lastPeak.map(dateObj -> dateObj.getValue().toString()).orElse("-"));
|
||||||
numbers.put("best_peak_date", allTimePeak.map(year).orElse("-"));
|
numbers.put("best_peak_date", allTimePeak.map(DateObj::getDate).map(Object.class::cast).orElse("-"));
|
||||||
numbers.put("best_peak_players", allTimePeak.map(dateObj -> dateObj.getValue().toString()).orElse("-"));
|
numbers.put("best_peak_players", allTimePeak.map(dateObj -> dateObj.getValue().toString()).orElse("-"));
|
||||||
Long totalPlaytime = db.query(SessionQueries.playtime(0L, now));
|
Long totalPlaytime = db.query(SessionQueries.playtime(0L, now));
|
||||||
numbers.put("playtime", timeAmount.apply(totalPlaytime));
|
numbers.put("playtime", totalPlaytime);
|
||||||
numbers.put("player_playtime", userCount != 0 ? timeAmount.apply(totalPlaytime / userCount) : "-");
|
numbers.put("player_playtime", userCount != 0 ? totalPlaytime / userCount : "-");
|
||||||
Long sessionCount = db.query(SessionQueries.sessionCount(0L, now));
|
Long sessionCount = db.query(SessionQueries.sessionCount(0L, now));
|
||||||
numbers.put("sessions", sessionCount);
|
numbers.put("sessions", sessionCount);
|
||||||
numbers.put("session_length_avg", sessionCount != 0 ? timeAmount.apply(totalPlaytime / sessionCount) : "-");
|
numbers.put("session_length_avg", sessionCount != 0 ? totalPlaytime / sessionCount : "-");
|
||||||
numbers.put("current_uptime", serverUptimeCalculator.getServerUptimeMillis(serverUUID).map(timeAmount)
|
numbers.put("current_uptime", serverUptimeCalculator.getServerUptimeMillis(serverUUID)
|
||||||
|
.map(Object.class::cast)
|
||||||
.orElse(GenericLang.UNAVAILABLE.getKey()));
|
.orElse(GenericLang.UNAVAILABLE.getKey()));
|
||||||
|
|
||||||
return numbers;
|
return numbers;
|
||||||
@ -147,9 +139,9 @@ public class NetworkOverviewJSONCreator implements NetworkTabJSONCreator<Map<Str
|
|||||||
|
|
||||||
Map<String, Object> weeks = new HashMap<>();
|
Map<String, Object> weeks = new HashMap<>();
|
||||||
|
|
||||||
weeks.put("start", day.apply(twoWeeksAgo));
|
weeks.put("start", twoWeeksAgo);
|
||||||
weeks.put("midpoint", day.apply(oneWeekAgo));
|
weeks.put("midpoint", oneWeekAgo);
|
||||||
weeks.put("end", day.apply(now));
|
weeks.put("end", now);
|
||||||
|
|
||||||
Integer uniqueBefore = db.query(PlayerCountQueries.uniquePlayerCount(twoWeeksAgo, oneWeekAgo));
|
Integer uniqueBefore = db.query(PlayerCountQueries.uniquePlayerCount(twoWeeksAgo, oneWeekAgo));
|
||||||
Integer uniqueAfter = db.query(PlayerCountQueries.uniquePlayerCount(oneWeekAgo, now));
|
Integer uniqueAfter = db.query(PlayerCountQueries.uniquePlayerCount(oneWeekAgo, now));
|
||||||
@ -175,9 +167,9 @@ public class NetworkOverviewJSONCreator implements NetworkTabJSONCreator<Map<Str
|
|||||||
Long playtimeAfter = db.query(SessionQueries.playtime(oneWeekAgo, now));
|
Long playtimeAfter = db.query(SessionQueries.playtime(oneWeekAgo, now));
|
||||||
long avgPlaytimeBefore = uniqueBefore != 0 ? playtimeBefore / uniqueBefore : 0L;
|
long avgPlaytimeBefore = uniqueBefore != 0 ? playtimeBefore / uniqueBefore : 0L;
|
||||||
long avgPlaytimeAfter = uniqueAfter != 0 ? playtimeAfter / uniqueAfter : 0L;
|
long avgPlaytimeAfter = uniqueAfter != 0 ? playtimeAfter / uniqueAfter : 0L;
|
||||||
Trend avgPlaytimeTrend = new Trend(avgPlaytimeBefore, avgPlaytimeAfter, false, timeAmount);
|
Trend avgPlaytimeTrend = new Trend(avgPlaytimeBefore, avgPlaytimeAfter, false);
|
||||||
weeks.put("average_playtime_before", timeAmount.apply(avgPlaytimeBefore));
|
weeks.put("average_playtime_before", avgPlaytimeBefore);
|
||||||
weeks.put("average_playtime_after", timeAmount.apply(avgPlaytimeAfter));
|
weeks.put("average_playtime_after", avgPlaytimeAfter);
|
||||||
weeks.put("average_playtime_trend", avgPlaytimeTrend);
|
weeks.put("average_playtime_trend", avgPlaytimeTrend);
|
||||||
|
|
||||||
Long sessionsBefore = db.query(SessionQueries.sessionCount(twoWeeksAgo, oneWeekAgo));
|
Long sessionsBefore = db.query(SessionQueries.sessionCount(twoWeeksAgo, oneWeekAgo));
|
||||||
@ -189,9 +181,9 @@ public class NetworkOverviewJSONCreator implements NetworkTabJSONCreator<Map<Str
|
|||||||
|
|
||||||
long avgSessionLengthBefore = sessionsBefore != 0 ? playtimeBefore / sessionsBefore : 0;
|
long avgSessionLengthBefore = sessionsBefore != 0 ? playtimeBefore / sessionsBefore : 0;
|
||||||
long avgSessionLengthAfter = sessionsAfter != 0 ? playtimeAfter / sessionsAfter : 0;
|
long avgSessionLengthAfter = sessionsAfter != 0 ? playtimeAfter / sessionsAfter : 0;
|
||||||
Trend avgSessionLengthTrend = new Trend(avgSessionLengthBefore, avgSessionLengthAfter, false, timeAmount);
|
Trend avgSessionLengthTrend = new Trend(avgSessionLengthBefore, avgSessionLengthAfter, false);
|
||||||
weeks.put("session_length_average_before", timeAmount.apply(avgSessionLengthBefore));
|
weeks.put("session_length_average_before", avgSessionLengthBefore);
|
||||||
weeks.put("session_length_average_after", timeAmount.apply(avgSessionLengthAfter));
|
weeks.put("session_length_average_after", avgSessionLengthAfter);
|
||||||
weeks.put("session_length_average_trend", avgSessionLengthTrend);
|
weeks.put("session_length_average_trend", avgSessionLengthTrend);
|
||||||
|
|
||||||
return weeks;
|
return weeks;
|
||||||
|
@ -8,6 +8,8 @@ import {faCalendarCheck, faClock} from "@fortawesome/free-regular-svg-icons";
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import {TableRow} from "../../../table/TableRow";
|
import {TableRow} from "../../../table/TableRow";
|
||||||
import {CardLoader} from "../../../navigation/Loader";
|
import {CardLoader} from "../../../navigation/Loader";
|
||||||
|
import FormattedDay from "../../../text/FormattedDay.jsx";
|
||||||
|
import FormattedTime, {formatTimeFunction} from "../../../text/FormattedTime.jsx";
|
||||||
|
|
||||||
const ServerWeekComparisonCard = ({data}) => {
|
const ServerWeekComparisonCard = ({data}) => {
|
||||||
const {t} = useTranslation();
|
const {t} = useTranslation();
|
||||||
@ -20,11 +22,18 @@ const ServerWeekComparisonCard = ({data}) => {
|
|||||||
</h6>
|
</h6>
|
||||||
</Card.Header>
|
</Card.Header>
|
||||||
<ComparisonTable comparisonHeader={t('html.label.comparing7days')}
|
<ComparisonTable comparisonHeader={t('html.label.comparing7days')}
|
||||||
headers={[data.start + ' - ' + data.midpoint, data.midpoint + ' - ' + data.end, t('html.label.trend')]}>
|
headers={[
|
||||||
<TableRow icon={faUsers} color="blue" text={t('html.label.uniquePlayers')}
|
<><FormattedDay date={data.start}/> - <FormattedDay date={data.midpoint}/></>,
|
||||||
values={[data.unique_before, data.unique_after,
|
<><FormattedDay date={data.midpoint}/> - <FormattedDay date={data.end}/></>,
|
||||||
|
t('html.label.trend')]}>
|
||||||
|
<TableRow icon={faUsers} color="blue"
|
||||||
|
text={t('html.label.uniquePlayers')}
|
||||||
|
values={[
|
||||||
|
data.unique_before,
|
||||||
|
data.unique_after,
|
||||||
<BigTrend key={JSON.stringify(data.unique_trend)}
|
<BigTrend key={JSON.stringify(data.unique_trend)}
|
||||||
trend={data.unique_trend}/>]}/>
|
trend={data.unique_trend}/>
|
||||||
|
]}/>
|
||||||
<TableRow icon={faUsers} color="light-green" text={t('html.label.newPlayers')}
|
<TableRow icon={faUsers} color="light-green" text={t('html.label.newPlayers')}
|
||||||
values={[data.new_before, data.new_after,
|
values={[data.new_before, data.new_after,
|
||||||
<BigTrend key={JSON.stringify(data.new_trend)}
|
<BigTrend key={JSON.stringify(data.new_trend)}
|
||||||
@ -35,14 +44,20 @@ const ServerWeekComparisonCard = ({data}) => {
|
|||||||
trend={data.regular_trend}/>]}/>
|
trend={data.regular_trend}/>]}/>
|
||||||
<TableRow icon={faClock} color="green"
|
<TableRow icon={faClock} color="green"
|
||||||
text={t('html.label.averagePlaytime') + ' ' + t('html.label.perPlayer')}
|
text={t('html.label.averagePlaytime') + ' ' + t('html.label.perPlayer')}
|
||||||
values={[data.average_playtime_before, data.average_playtime_after,
|
values={[
|
||||||
|
<FormattedTime key={"before-ms"} timeMs={data.average_playtime_before}/>,
|
||||||
|
<FormattedTime key={"after-ms"} timeMs={data.average_playtime_after}/>,
|
||||||
<BigTrend key={JSON.stringify(data.average_playtime_trend)}
|
<BigTrend key={JSON.stringify(data.average_playtime_trend)}
|
||||||
trend={data.average_playtime_trend}/>]}/>
|
trend={data.average_playtime_trend}
|
||||||
<TableRow icon={faClock} color="teal"
|
format={formatTimeFunction}/>]}/>
|
||||||
|
{data.session_length_average_before !== undefined && <TableRow
|
||||||
|
icon={faClock} color="teal"
|
||||||
text={t('html.label.averageSessionLength')}
|
text={t('html.label.averageSessionLength')}
|
||||||
values={[data.session_length_average_before, data.session_length_average_after,
|
values={[<FormattedTime key={"before-ms"} timeMs={data.session_length_average_before}/>,
|
||||||
|
<FormattedTime key={"after-ms"} timeMs={data.session_length_average_after}/>,
|
||||||
<BigTrend key={JSON.stringify(data.session_length_average_trend)}
|
<BigTrend key={JSON.stringify(data.session_length_average_trend)}
|
||||||
trend={data.session_length_average_trend}/>]}/>
|
trend={data.session_length_average_trend}
|
||||||
|
format={formatTimeFunction}/>]}/>}
|
||||||
<TableRow icon={faCalendarCheck} color="teal" text={t('html.label.sessions')}
|
<TableRow icon={faCalendarCheck} color="teal" text={t('html.label.sessions')}
|
||||||
values={[data.sessions_before, data.sessions_after,
|
values={[data.sessions_before, data.sessions_after,
|
||||||
<BigTrend key={JSON.stringify(data.sessions_trend)}
|
<BigTrend key={JSON.stringify(data.sessions_trend)}
|
||||||
|
@ -9,6 +9,8 @@ import {CardLoader} from "../../../navigation/Loader";
|
|||||||
import ExtendableCardBody from "../../../layout/extension/ExtendableCardBody";
|
import ExtendableCardBody from "../../../layout/extension/ExtendableCardBody";
|
||||||
import {useMetadata} from "../../../../hooks/metadataHook";
|
import {useMetadata} from "../../../../hooks/metadataHook";
|
||||||
import CurrentUptime from "../../../datapoint/CurrentUptime";
|
import CurrentUptime from "../../../datapoint/CurrentUptime";
|
||||||
|
import FormattedTime from "../../../text/FormattedTime.jsx";
|
||||||
|
import FormattedDate from "../../../text/FormattedDate.jsx";
|
||||||
|
|
||||||
const ServerAsNumbersCard = ({data}) => {
|
const ServerAsNumbersCard = ({data}) => {
|
||||||
const {t} = useTranslation();
|
const {t} = useTranslation();
|
||||||
@ -40,23 +42,23 @@ const ServerAsNumbersCard = ({data}) => {
|
|||||||
value={data.online_players} bold/>
|
value={data.online_players} bold/>
|
||||||
{showPeaks && <>
|
{showPeaks && <>
|
||||||
<hr/>
|
<hr/>
|
||||||
<Datapoint name={t('html.label.lastPeak') + ' (' + data.last_peak_date + ')'}
|
<Datapoint name={<>{t('html.label.lastPeak')} (<FormattedDate date={data.last_peak_date}/>)</>}
|
||||||
color={'blue'} icon={faChartLine}
|
color={'blue'} icon={faChartLine}
|
||||||
value={data.last_peak_players} valueLabel={t('html.unit.players')} bold/>
|
value={data.last_peak_players} valueLabel={t('html.unit.players')} bold/>
|
||||||
<Datapoint name={t('html.label.bestPeak') + ' (' + data.best_peak_date + ')'}
|
<Datapoint name={<>{t('html.label.bestPeak')} (<FormattedDate date={data.best_peak_date}/>)</>}
|
||||||
color={'light-green'} icon={faChartLine}
|
color={'light-green'} icon={faChartLine}
|
||||||
value={data.best_peak_players} valueLabel={t('html.unit.players')} bold/>
|
value={data.best_peak_players} valueLabel={t('html.unit.players')} bold/>
|
||||||
</>}
|
</>}
|
||||||
<hr/>
|
<hr/>
|
||||||
<Datapoint name={t('html.label.totalPlaytime')}
|
<Datapoint name={t('html.label.totalPlaytime')}
|
||||||
color={'green'} icon={faClock}
|
color={'green'} icon={faClock}
|
||||||
value={data.playtime}/>
|
value={<FormattedTime timeMs={data.playtime}/>}/>
|
||||||
<Datapoint name={t('html.label.averagePlaytime') + ' ' + t('html.label.perPlayer')}
|
<Datapoint name={t('html.label.averagePlaytime') + ' ' + t('html.label.perPlayer')}
|
||||||
color={'green'} icon={faClock}
|
color={'green'} icon={faClock}
|
||||||
value={data.player_playtime}/>
|
value={<FormattedTime timeMs={data.player_playtime}/>}/>
|
||||||
<Datapoint name={t('html.label.averageSessionLength')}
|
<Datapoint name={t('html.label.averageSessionLength')}
|
||||||
color={'teal'} icon={faClock}
|
color={'teal'} icon={faClock}
|
||||||
value={data.session_length_avg}/>
|
value={<FormattedTime timeMs={data.session_length_avg}/>}/>
|
||||||
<Datapoint name={t('html.label.sessions')}
|
<Datapoint name={t('html.label.sessions')}
|
||||||
color={'teal'} icon={faCalendarCheck}
|
color={'teal'} icon={faCalendarCheck}
|
||||||
value={data.sessions} bold/>
|
value={data.sessions} bold/>
|
||||||
|
@ -4,6 +4,8 @@ import {faPowerOff} from "@fortawesome/free-solid-svg-icons";
|
|||||||
import {faQuestionCircle} from "@fortawesome/free-regular-svg-icons";
|
import {faQuestionCircle} from "@fortawesome/free-regular-svg-icons";
|
||||||
import Datapoint from "../Datapoint";
|
import Datapoint from "../Datapoint";
|
||||||
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
|
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
|
||||||
|
import FormattedTime from "../text/FormattedTime.jsx";
|
||||||
|
import {isNumber} from "../../util/isNumber.js";
|
||||||
|
|
||||||
const CurrentUptime = ({uptime}) => {
|
const CurrentUptime = ({uptime}) => {
|
||||||
const {t} = useTranslation();
|
const {t} = useTranslation();
|
||||||
@ -15,7 +17,7 @@ const CurrentUptime = ({uptime}) => {
|
|||||||
return (
|
return (
|
||||||
<Datapoint icon={faPowerOff} color={'light-green'}
|
<Datapoint icon={faPowerOff} color={'light-green'}
|
||||||
name={t('html.label.currentUptime')}
|
name={t('html.label.currentUptime')}
|
||||||
value={uptime} valueLabel={infoBubble}/>
|
value={isNumber(uptime) && <FormattedTime timeMs={uptime}/> || uptime} valueLabel={infoBubble}/>
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3,13 +3,16 @@ import {usePreferences} from "../../hooks/preferencesHook";
|
|||||||
import {SimpleDateFormat} from "../../util/format/SimpleDateFormat";
|
import {SimpleDateFormat} from "../../util/format/SimpleDateFormat";
|
||||||
import {useMetadata} from "../../hooks/metadataHook";
|
import {useMetadata} from "../../hooks/metadataHook";
|
||||||
import {useTranslation} from "react-i18next";
|
import {useTranslation} from "react-i18next";
|
||||||
|
import {isNumber} from "../../util/isNumber.js";
|
||||||
|
|
||||||
const FormattedDate = ({date}) => {
|
const FormattedDate = ({date}) => {
|
||||||
|
console.log(date);
|
||||||
const {t} = useTranslation();
|
const {t} = useTranslation();
|
||||||
const {timeZoneOffsetHours} = useMetadata();
|
const {timeZoneOffsetHours} = useMetadata();
|
||||||
const {preferencesLoaded, dateFormatNoSeconds, recentDaysInDateFormat} = usePreferences();
|
const {preferencesLoaded, dateFormatNoSeconds, recentDaysInDateFormat} = usePreferences();
|
||||||
|
|
||||||
if (!preferencesLoaded || date === undefined || date === null) return <></>
|
if (!preferencesLoaded || date === undefined || date === null) return <></>;
|
||||||
|
if (!isNumber(date)) return date;
|
||||||
|
|
||||||
const pattern = dateFormatNoSeconds;
|
const pattern = dateFormatNoSeconds;
|
||||||
const recentDays = recentDaysInDateFormat;
|
const recentDays = recentDaysInDateFormat;
|
||||||
|
24
Plan/react/dashboard/src/components/text/FormattedDay.jsx
Normal file
24
Plan/react/dashboard/src/components/text/FormattedDay.jsx
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import {SimpleDateFormat} from "../../util/format/SimpleDateFormat";
|
||||||
|
import {useMetadata} from "../../hooks/metadataHook";
|
||||||
|
import {isNumber} from "../../util/isNumber.js";
|
||||||
|
|
||||||
|
const FormattedDay = ({date}) => {
|
||||||
|
const {timeZoneOffsetHours} = useMetadata();
|
||||||
|
|
||||||
|
if (date === undefined || date === null) return <></>;
|
||||||
|
if (!isNumber(date)) return date;
|
||||||
|
|
||||||
|
const pattern = "MMMMM d";
|
||||||
|
|
||||||
|
const offset = timeZoneOffsetHours * 60 * 60 * 1000;
|
||||||
|
const timestamp = date - offset;
|
||||||
|
|
||||||
|
const formatted = date !== 0 ? new SimpleDateFormat(pattern).format(timestamp) : '-';
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>{formatted}</>
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
export default FormattedDay
|
@ -1,11 +1,13 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {usePreferences} from "../../hooks/preferencesHook";
|
import {usePreferences} from "../../hooks/preferencesHook";
|
||||||
import {formatTimeAmount} from "../../util/format/TimeAmountFormat";
|
import {formatTimeAmount} from "../../util/format/TimeAmountFormat";
|
||||||
|
import {isNumber} from "../../util/isNumber.js";
|
||||||
|
|
||||||
const FormattedTime = ({timeMs}) => {
|
const FormattedTime = ({timeMs}) => {
|
||||||
const {preferencesLoaded, timeFormat} = usePreferences();
|
const {preferencesLoaded, timeFormat} = usePreferences();
|
||||||
|
|
||||||
if (!preferencesLoaded) return <></>
|
if (!preferencesLoaded) return <></>;
|
||||||
|
if (!isNumber(timeMs)) return timeMs;
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
YEAR: timeFormat.year,
|
YEAR: timeFormat.year,
|
||||||
@ -26,4 +28,10 @@ const FormattedTime = ({timeMs}) => {
|
|||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const formatTimeFunction = time => {
|
||||||
|
return (
|
||||||
|
<FormattedTime timeMs={time}/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export default FormattedTime
|
export default FormattedTime
|
@ -9,17 +9,20 @@ const TrendDownGood = ({value}) => <span className="badge bg-success"><Fa icon={
|
|||||||
const TrendSame = ({value}) => <span className="badge bg-warning"><Fa icon={faCaretRight}/>{value}</span>;
|
const TrendSame = ({value}) => <span className="badge bg-warning"><Fa icon={faCaretRight}/>{value}</span>;
|
||||||
|
|
||||||
|
|
||||||
const BigTrend = ({trend}) => {
|
const BigTrend = ({trend, format}) => {
|
||||||
if (!trend) {
|
if (!trend) {
|
||||||
return <TrendSame value={'?'}/>;
|
return <TrendSame value={'?'}/>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const value = format ? format(trend.text) : trend.text;
|
||||||
|
|
||||||
switch (trend.direction) {
|
switch (trend.direction) {
|
||||||
case '+':
|
case '+':
|
||||||
return (trend.reversed ? <TrendUpBad value={trend.text}/> : <TrendUpGood value={trend.text}/>);
|
return (trend.reversed ? <TrendUpBad value={trend.text}/> : <TrendUpGood value={value}/>);
|
||||||
case '-':
|
case '-':
|
||||||
return (trend.reversed ? <TrendDownGood value={trend.text}/> : <TrendDownBad value={trend.text}/>);
|
return (trend.reversed ? <TrendDownGood value={trend.text}/> : <TrendDownBad value={value}/>);
|
||||||
default:
|
default:
|
||||||
return <TrendSame value={trend.text}/>;
|
return <TrendSame value={value}/>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1506,3 +1506,13 @@ ul.filters {
|
|||||||
.nav-item.disabled {
|
.nav-item.disabled {
|
||||||
opacity: 30%;
|
opacity: 30%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.link {
|
||||||
|
color: var(--bs-link-color);
|
||||||
|
opacity: var(--bs-link-opacity);
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link:hover {
|
||||||
|
color: var(--bs-link-hover-color)
|
||||||
|
}
|
||||||
|
4
Plan/react/dashboard/src/util/isNumber.js
Normal file
4
Plan/react/dashboard/src/util/isNumber.js
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
// https://stackoverflow.com/a/1421988/20825073
|
||||||
|
export function isNumber(n) {
|
||||||
|
return !isNaN(parseFloat(n)) && !isNaN(n - 0)
|
||||||
|
}
|
@ -23,6 +23,7 @@ import {CardLoader} from "../../components/navigation/Loader";
|
|||||||
import ExtendableRow from "../../components/layout/extension/ExtendableRow";
|
import ExtendableRow from "../../components/layout/extension/ExtendableRow";
|
||||||
import {useAuth} from "../../hooks/authenticationHook";
|
import {useAuth} from "../../hooks/authenticationHook";
|
||||||
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
|
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
|
||||||
|
import FormattedTime from "../../components/text/FormattedTime.jsx";
|
||||||
|
|
||||||
const Last7DaysCard = ({data}) => {
|
const Last7DaysCard = ({data}) => {
|
||||||
const {t} = useTranslation();
|
const {t} = useTranslation();
|
||||||
@ -64,7 +65,7 @@ const Last7DaysCard = ({data}) => {
|
|||||||
value={data.low_tps_spikes} bold/>
|
value={data.low_tps_spikes} bold/>
|
||||||
<Datapoint name={t('html.label.downtime')}
|
<Datapoint name={t('html.label.downtime')}
|
||||||
color={'red'} icon={faPowerOff}
|
color={'red'} icon={faPowerOff}
|
||||||
value={data.downtime}/>
|
value={<FormattedTime timeMs={data.downtime}/>}/>
|
||||||
</Card.Body>
|
</Card.Body>
|
||||||
</Card>
|
</Card>
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user