Playerbase overview page layout

- Moved some files
This commit is contained in:
Aurora Lahtela 2022-05-23 18:58:06 +03:00
parent b942078485
commit 7e1bd7f4a6
32 changed files with 428 additions and 319 deletions

View File

@ -4,12 +4,12 @@ import './style/style.css';
import {BrowserRouter, Navigate, Route, Routes} from "react-router-dom"; import {BrowserRouter, Navigate, Route, Routes} from "react-router-dom";
import React from "react"; import React from "react";
import PlayerPage from "./views/PlayerPage"; import PlayerPage from "./views/layout/PlayerPage";
import PlayerOverview from "./views/PlayerOverview"; import PlayerOverview from "./views/player/PlayerOverview";
import PlayerSessions from "./views/PlayerSessions"; import PlayerSessions from "./views/player/PlayerSessions";
import PlayerPvpPve from "./views/PlayerPvpPve"; import PlayerPvpPve from "./views/player/PlayerPvpPve";
import PlayerServers from "./views/PlayerServers"; import PlayerServers from "./views/player/PlayerServers";
import PlayerPluginData from "./views/PlayerPluginData"; import PlayerPluginData from "./views/player/PlayerPluginData";
import {ThemeContextProvider} from "./hooks/themeHook"; import {ThemeContextProvider} from "./hooks/themeHook";
import axios from "axios"; import axios from "axios";
import ErrorView from "./views/ErrorView"; import ErrorView from "./views/ErrorView";
@ -17,13 +17,13 @@ import {faMapSigns} from "@fortawesome/free-solid-svg-icons";
import {MetadataContextProvider} from "./hooks/metadataHook"; import {MetadataContextProvider} from "./hooks/metadataHook";
import {AuthenticationContextProvider} from "./hooks/authenticationHook"; import {AuthenticationContextProvider} from "./hooks/authenticationHook";
import {NavigationContextProvider} from "./hooks/navigationHook"; import {NavigationContextProvider} from "./hooks/navigationHook";
import ServerPage from "./views/ServerPage"; import ServerPage from "./views/layout/ServerPage";
import ServerOverview from "./views/ServerOverview"; import ServerOverview from "./views/server/ServerOverview";
import MainPageRedirect from "./components/navigation/MainPageRedirect"; import MainPageRedirect from "./components/navigation/MainPageRedirect";
import ServerOnlineActivity from "./views/ServerOnlineActivity"; import OnlineActivity from "./views/server/OnlineActivity";
import ServerSessions from "./views/ServerSessions"; import ServerSessions from "./views/server/ServerSessions";
import ServerPvpPve from "./views/ServerPvpPve"; import ServerPvpPve from "./views/server/ServerPvpPve";
import ServerPlayerbaseOverview from "./views/ServerPlayerbaseOverview"; import PlayerbaseOverview from "./views/server/PlayerbaseOverview";
const OverviewRedirect = () => { const OverviewRedirect = () => {
return (<Navigate to={"overview"} replace={true}/>) return (<Navigate to={"overview"} replace={true}/>)
@ -67,10 +67,10 @@ function App() {
<Route path="/server/:identifier" element={<ServerPage/>}> <Route path="/server/:identifier" element={<ServerPage/>}>
<Route path="" element={<OverviewRedirect/>}/> <Route path="" element={<OverviewRedirect/>}/>
<Route path="overview" element={<ServerOverview/>}/> <Route path="overview" element={<ServerOverview/>}/>
<Route path="online-activity" element={<ServerOnlineActivity/>}/> <Route path="online-activity" element={<OnlineActivity/>}/>
<Route path="sessions" element={<ServerSessions/>}/> <Route path="sessions" element={<ServerSessions/>}/>
<Route path="pvppve" element={<ServerPvpPve/>}/> <Route path="pvppve" element={<ServerPvpPve/>}/>
<Route path="playerbase" element={<ServerPlayerbaseOverview/>}/> <Route path="playerbase" element={<PlayerbaseOverview/>}/>
<Route path="retention" element={<></>}/> <Route path="retention" element={<></>}/>
<Route path="players" element={<></>}/> <Route path="players" element={<></>}/>
<Route path="geolocations" element={<></>}/> <Route path="geolocations" element={<></>}/>

View File

@ -5,14 +5,14 @@ const End = ({children}) => (
<span className="float-end">{children}</span> <span className="float-end">{children}</span>
) )
const Datapoint = ({icon, color, name, value, valueLabel, bold, boldTitle, title}) => { const Datapoint = ({icon, color, name, value, valueLabel, bold, boldTitle, title, trend}) => {
const displayedValue = bold ? <b>{value}</b> : value; const displayedValue = bold ? <b>{value}</b> : value;
const extraLabel = valueLabel ? ` (${valueLabel})` : ''; const extraLabel = valueLabel instanceof String ? ` (${valueLabel})` : '';
const colorClass = color && color.startsWith("col-") ? color : "col-" + color; const colorClass = color && color.startsWith("col-") ? color : "col-" + color;
return ( return (
<p title={title ? title : name + " is " + value}> <p title={title ? title : name + " is " + value}>
<Fa icon={icon} className={colorClass}/> {boldTitle ? <b>{name}</b> : name} {icon && <Fa icon={icon} className={colorClass}/>} {boldTitle ? <b>{name}</b> : name}
{value !== undefined ? <End>{displayedValue} {extraLabel}</End> : ''} {value !== undefined ? <End>{displayedValue} {extraLabel}{trend}</End> : ''}
</p> </p>
); );
} }

View File

@ -1,8 +1,8 @@
import React from "react"; import React from "react";
import {useParams} from "react-router-dom"; import {useParams} from "react-router-dom";
import {useDataRequest} from "../../../hooks/dataFetchHook"; import {useDataRequest} from "../../../../hooks/dataFetchHook";
import {fetchPlayerbaseDevelopmentGraph} from "../../../service/serverService"; import {fetchPlayerbaseDevelopmentGraph} from "../../../../service/serverService";
import {ErrorViewBody} from "../../../views/ErrorView"; import {ErrorViewBody} from "../../../../views/ErrorView";
import {useTranslation} from "react-i18next"; import {useTranslation} from "react-i18next";
import {Card} from "react-bootstrap-v5"; import {Card} from "react-bootstrap-v5";
import {FontAwesomeIcon as Fa} from "@fortawesome/react-fontawesome"; import {FontAwesomeIcon as Fa} from "@fortawesome/react-fontawesome";

View File

@ -1,12 +1,12 @@
import {useTranslation} from "react-i18next"; import {useTranslation} from "react-i18next";
import {useParams} from "react-router-dom"; import {useParams} from "react-router-dom";
import {useDataRequest} from "../../../hooks/dataFetchHook"; import {useDataRequest} from "../../../../hooks/dataFetchHook";
import {fetchPlayersOnlineGraph} from "../../../service/serverService"; import {fetchPlayersOnlineGraph} from "../../../../service/serverService";
import {ErrorViewCard} from "../../../views/ErrorView"; import {ErrorViewCard} from "../../../../views/ErrorView";
import {Card} from "react-bootstrap-v5"; import {Card} from "react-bootstrap-v5";
import {FontAwesomeIcon as Fa} from "@fortawesome/react-fontawesome"; import {FontAwesomeIcon as Fa} from "@fortawesome/react-fontawesome";
import {faChartArea} from "@fortawesome/free-solid-svg-icons"; import {faChartArea} from "@fortawesome/free-solid-svg-icons";
import PlayersOnlineGraph from "../../graphs/PlayersOnlineGraph"; import PlayersOnlineGraph from "../../../graphs/PlayersOnlineGraph";
import React from "react"; import React from "react";
const OnlineActivityCard = () => { const OnlineActivityCard = () => {

View File

@ -1,21 +1,21 @@
import {useParams} from "react-router-dom"; import {useParams} from "react-router-dom";
import {useDataRequest} from "../../../hooks/dataFetchHook"; import {useDataRequest} from "../../../../hooks/dataFetchHook";
import { import {
fetchDayByDayGraph, fetchDayByDayGraph,
fetchHourByHourGraph, fetchHourByHourGraph,
fetchPunchCardGraph, fetchPunchCardGraph,
fetchServerCalendarGraph fetchServerCalendarGraph
} from "../../../service/serverService"; } from "../../../../service/serverService";
import {ErrorViewBody} from "../../../views/ErrorView"; import {ErrorViewBody} from "../../../../views/ErrorView";
import PunchCard from "../../graphs/PunchCard"; import PunchCard from "../../../graphs/PunchCard";
import {useTranslation} from "react-i18next"; import {useTranslation} from "react-i18next";
import {Card} from "react-bootstrap-v5"; import {Card} from "react-bootstrap-v5";
import CardTabs from "../../CardTabs"; import CardTabs from "../../../CardTabs";
import {faBraille, faChartArea} from "@fortawesome/free-solid-svg-icons"; import {faBraille, faChartArea} from "@fortawesome/free-solid-svg-icons";
import {faCalendar} from "@fortawesome/free-regular-svg-icons"; import {faCalendar} from "@fortawesome/free-regular-svg-icons";
import React from "react"; import React from "react";
import TimeByTimeGraph from "../../graphs/TimeByTimeGraph"; import TimeByTimeGraph from "../../../graphs/TimeByTimeGraph";
import ServerCalendar from "../../calendar/ServerCalendar"; import ServerCalendar from "../../../calendar/ServerCalendar";
const DayByDayTab = () => { const DayByDayTab = () => {
const {identifier} = useParams(); const {identifier} = useParams();

View File

@ -1,12 +1,12 @@
import {useTranslation} from "react-i18next"; import {useTranslation} from "react-i18next";
import {useParams} from "react-router-dom"; import {useParams} from "react-router-dom";
import {useDataRequest} from "../../../hooks/dataFetchHook"; import {useDataRequest} from "../../../../hooks/dataFetchHook";
import {fetchPlayerbaseDevelopmentGraph} from "../../../service/serverService"; import {fetchPlayerbaseDevelopmentGraph} from "../../../../service/serverService";
import {ErrorViewCard} from "../../../views/ErrorView"; import {ErrorViewCard} from "../../../../views/ErrorView";
import {Card} from "react-bootstrap-v5"; import {Card} from "react-bootstrap-v5";
import {FontAwesomeIcon as Fa} from "@fortawesome/react-fontawesome"; import {FontAwesomeIcon as Fa} from "@fortawesome/react-fontawesome";
import {faChartLine} from "@fortawesome/free-solid-svg-icons"; import {faChartLine} from "@fortawesome/free-solid-svg-icons";
import PlayersOnlineGraph from "../../graphs/PlayersOnlineGraph"; import PlayersOnlineGraph from "../../../graphs/PlayersOnlineGraph";
import React from "react"; import React from "react";
const PlayerbaseDevelopmentCard = () => { const PlayerbaseDevelopmentCard = () => {

View File

@ -1,9 +1,9 @@
import React from "react"; import React from "react";
import WorldPieCard from "../common/WorldPieCard"; import WorldPieCard from "../../common/WorldPieCard";
import {useParams} from "react-router-dom"; import {useParams} from "react-router-dom";
import {useDataRequest} from "../../../hooks/dataFetchHook"; import {useDataRequest} from "../../../../hooks/dataFetchHook";
import {fetchWorldPie} from "../../../service/serverService"; import {fetchWorldPie} from "../../../../service/serverService";
import {ErrorViewBody} from "../../../views/ErrorView"; import {ErrorViewBody} from "../../../../views/ErrorView";
const ServerWorldPieCard = () => { const ServerWorldPieCard = () => {
const {identifier} = useParams(); const {identifier} = useParams();

View File

@ -1,5 +1,5 @@
import React from "react"; import React from "react";
import InsightsFor30DaysCard from "../common/InsightsFor30DaysCard"; import InsightsFor30DaysCard from "../../common/InsightsFor30DaysCard";
const OnlineActivityInsightsCard = () => { const OnlineActivityInsightsCard = () => {
return ( return (

View File

@ -0,0 +1,42 @@
import React from "react";
import InsightsFor30DaysCard from "../../common/InsightsFor30DaysCard";
import {useTranslation} from "react-i18next";
import {FontAwesomeIcon as Fa} from "@fortawesome/react-fontawesome";
import Datapoint from "../../../Datapoint";
import {faLongArrowAltRight, faUser} from "@fortawesome/free-solid-svg-icons";
import SmallTrend from "../../../trend/SmallTrend";
const TwoPlayerChange = ({colorBefore, labelBefore, colorAfter, labelAfter}) => {
return (
<>
<Fa icon={faUser} className={`col-${colorBefore}`}/>{' '}{labelBefore}
{' '}<Fa icon={faLongArrowAltRight}/>{' '}
<Fa icon={faUser} className={`col-${colorAfter}`}/>{' '}{labelAfter}
</>
)
}
const PlayerbaseInsightsCard = ({data}) => {
const {t} = useTranslation();
if (!data) return <></>;
return (
<InsightsFor30DaysCard>
<Datapoint name={<TwoPlayerChange colorBefore={'light-green'}
labelBefore={t('html.label.new')}
colorAfter={'lime'}
labelAfter={t('html.label.regular')}/>}
value={data.new_to_regular}
trend={<SmallTrend trend={data.new_to_regular_trend}/>}
/>
<Datapoint name={<TwoPlayerChange colorBefore={'lime'}
labelBefore={t('html.label.regular')}
colorAfter={'bluegray'}
labelAfter={t('html.label.inactive')}/>}
value={data.regular_to_inactive}
trend={<SmallTrend trend={data.regular_to_inactive_trend}/>}
/>
</InsightsFor30DaysCard>
)
}
export default PlayerbaseInsightsCard;

View File

@ -1,5 +1,5 @@
import React from "react"; import React from "react";
import InsightsFor30DaysCard from "../common/InsightsFor30DaysCard"; import InsightsFor30DaysCard from "../../common/InsightsFor30DaysCard";
const PvpPveInsightsCard = () => { const PvpPveInsightsCard = () => {
return ( return (

View File

@ -1,5 +1,5 @@
import React from "react"; import React from "react";
import InsightsFor30DaysCard from "../common/InsightsFor30DaysCard"; import InsightsFor30DaysCard from "../../common/InsightsFor30DaysCard";
const SessionInsightsCard = () => { const SessionInsightsCard = () => {
return ( return (

View File

@ -3,7 +3,7 @@ import {Card} from "react-bootstrap-v5";
import {FontAwesomeIcon as Fa} from "@fortawesome/react-fontawesome"; import {FontAwesomeIcon as Fa} from "@fortawesome/react-fontawesome";
import {faBookOpen} from "@fortawesome/free-solid-svg-icons"; import {faBookOpen} from "@fortawesome/free-solid-svg-icons";
import React from "react"; import React from "react";
import OnlineActivityAsNumbersTable from "../../table/OnlineActivityAsNumbersTable"; import OnlineActivityAsNumbersTable from "../../../table/OnlineActivityAsNumbersTable";
const OnlineActivityAsNumbersCard = () => { const OnlineActivityAsNumbersCard = () => {
const {t} = useTranslation(); const {t} = useTranslation();

View File

@ -0,0 +1,52 @@
import {useTranslation} from "react-i18next";
import {Card} from "react-bootstrap-v5";
import {FontAwesomeIcon as Fa} from "@fortawesome/react-fontawesome";
import {faExchangeAlt, faUsers} from "@fortawesome/free-solid-svg-icons";
import ComparisonTable from "../../../table/ComparisonTable";
import {TableRow} from "../../../table/AsNumbersTable";
import BigTrend from "../../../trend/BigTrend";
import React from "react";
import {faClock} from "@fortawesome/free-regular-svg-icons";
const PlayerbaseTrendsCard = ({data}) => {
const {t} = useTranslation();
if (!data) return <></>;
return (
<Card>
<Card.Header>
<h6 className="col-black">
<Fa icon={faExchangeAlt} className="col-amber"/> {t('html.label.trends30days')}
</h6>
</Card.Header>
<ComparisonTable comparisonHeader={t('html.text.comparing30daysAgo')}
headers={[t('html.label.thirtyDaysAgo'), t('html.label.now'), t('html.label.trend')]}>
<TableRow icon={faUsers} color="black" text={t('html.label.totalPlayers')}
values={[data.total_players_now, data.total_players_then,
<BigTrend trend={data.total_players_trend}/>]}/>
<TableRow icon={faUsers} color="lime" text={t('html.label.regularPlayers')}
values={[data.regular_players_now, data.regular_players_then,
<BigTrend trend={data.regular_players_trend}/>]}/>
<TableRow icon={faClock} color="green"
text={t('html.label.averagePlaytime') + ' ' + t('html.label.perPlayer')}
values={[data.playtime_avg_now, data.playtime_avg_then,
<BigTrend trend={data.playtime_avg_trend}/>]}/>
<TableRow icon={faClock} color="gray" text={t('html.label.afk') + ' ' + t('html.label.perPlayer')}
values={[data.afk_now, data.afk_then, <BigTrend trend={data.afk_trend}/>]}/>
<TableRow icon={faClock} color="green"
text={t('html.label.averagePlaytime') + ' ' + t('html.label.perRegularPlayer')}
values={[data.regular_playtime_avg_now, data.regular_playtime_avg_then,
<BigTrend trend={data.regular_playtime_avg_trend}/>]}/>
<TableRow icon={faClock} color="teal"
text={t('html.label.averageSessionLength') + ' ' + t('html.label.perRegularPlayer')}
values={[data.regular_session_avg_now, data.regular_session_avg_then,
<BigTrend trend={data.regular_session_avg_trend}/>]}/>
<TableRow icon={faClock} color="gray"
text={t('html.label.afk') + ' ' + t('html.label.perRegularPlayer')}
values={[data.regular_afk_avg_now, data.regular_afk_avg_then,
<BigTrend trend={data.regular_afk_avg_trend}/>]}/>
</ComparisonTable>
</Card>
)
}
export default PlayerbaseTrendsCard

View File

@ -3,7 +3,7 @@ import {Card} from "react-bootstrap-v5";
import {FontAwesomeIcon as Fa} from "@fortawesome/react-fontawesome"; import {FontAwesomeIcon as Fa} from "@fortawesome/react-fontawesome";
import {faCampground} from "@fortawesome/free-solid-svg-icons"; import {faCampground} from "@fortawesome/free-solid-svg-icons";
import React from "react"; import React from "react";
import ServerPvpPveAsNumbersTable from "../../table/ServerPvpPveAsNumbersTable"; import ServerPvpPveAsNumbersTable from "../../../table/ServerPvpPveAsNumbersTable";
const PvpPveAsNumbersCard = ({kill_data}) => { const PvpPveAsNumbersCard = ({kill_data}) => {
const {t} = useTranslation(); const {t} = useTranslation();

View File

@ -1,9 +1,9 @@
import React from "react"; import React from "react";
import {useParams} from "react-router-dom"; 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 {ErrorViewBody} from "../../../views/ErrorView"; import {ErrorViewBody} from "../../../../views/ErrorView";
import RecentSessionsCard from "../common/RecentSessionsCard"; import RecentSessionsCard from "../../common/RecentSessionsCard";
const ServerRecentSessionsCard = () => { const ServerRecentSessionsCard = () => {

View File

@ -0,0 +1,49 @@
import {useTranslation} from "react-i18next";
import {Card} from "react-bootstrap-v5";
import {FontAwesomeIcon as Fa} from "@fortawesome/react-fontawesome";
import {faCrosshairs, faExchangeAlt, faSkull, faUsers} from "@fortawesome/free-solid-svg-icons";
import ComparisonTable from "../../../table/ComparisonTable";
import {TableRow} from "../../../table/AsNumbersTable";
import BigTrend from "../../../trend/BigTrend";
import {faCalendarCheck, faClock} from "@fortawesome/free-regular-svg-icons";
import React from "react";
const ServerWeekComparisonCard = ({data}) => {
const {t} = useTranslation();
if (!data) return <></>;
return (
<Card>
<Card.Header>
<h6 className="col-black">
<Fa icon={faExchangeAlt}/> {t('html.label.weekComparison')}
</h6>
</Card.Header>
<ComparisonTable comparisonHeader={t('html.label.comparing7days')}
headers={[data.start + ' - ' + data.midpoint, data.midpoint + ' - ' + data.end, t('html.label.trend')]}>
<TableRow icon={faUsers} color="blue" text={t('html.label.uniquePlayers')}
values={[data.unique_before, data.unique_after, <BigTrend trend={data.unique_trend}/>]}/>
<TableRow icon={faUsers} color="light-green" text={t('html.label.newPlayers')}
values={[data.new_before, data.new_after, <BigTrend trend={data.new_trend}/>]}/>
<TableRow icon={faUsers} color="lime" text={t('html.label.regularPlayers')}
values={[data.regular_before, data.regular_after, <BigTrend trend={data.regular_trend}/>]}/>
<TableRow icon={faClock} color="green"
text={t('html.label.averagePlaytime') + ' ' + t('html.label.perPlayer')}
values={[data.average_playtime_before, data.average_playtime_after,
<BigTrend trend={data.average_playtime_trend}/>]}/>
<TableRow icon={faCalendarCheck} color="teal" text={t('html.label.sessions')}
values={[data.sessions_before, data.sessions_after,
<BigTrend trend={data.sessions_trend}/>]}/>
<TableRow icon={faCrosshairs} color="red" text={t('html.label.playerKills')}
values={[data.player_kills_before, data.player_kills_after,
<BigTrend trend={data.player_kills_trend}/>]}/>
<TableRow icon={faCrosshairs} color="green" text={t('html.label.mobKills')}
values={[data.mob_kills_before, data.mob_kills_after,
<BigTrend trend={data.mob_kills_trend}/>]}/>
<TableRow icon={faSkull} color="black" text={t('html.label.deaths')}
values={[data.deaths_before, data.deaths_after, <BigTrend trend={data.deaths_trend}/>]}/>
</ComparisonTable>
</Card>
)
}
export default ServerWeekComparisonCard

View File

@ -0,0 +1,75 @@
import {useTranslation} from "react-i18next";
import {Card} from "react-bootstrap-v5";
import {FontAwesomeIcon as Fa} from "@fortawesome/react-fontawesome";
import {
faBookOpen,
faChartLine,
faCrosshairs,
faPowerOff,
faSkull,
faUser,
faUsers
} from "@fortawesome/free-solid-svg-icons";
import Datapoint from "../../../Datapoint";
import {faCalendarCheck, faClock} from "@fortawesome/free-regular-svg-icons";
import React from "react";
const ServerAsNumbersCard = ({data}) => {
const {t} = useTranslation();
if (!data) return <></>;
return (
<Card>
<Card.Header>
<h6 className="col-black">
<Fa icon={faBookOpen}/> {t('html.label.serverAsNumberse')}
</h6>
</Card.Header>
<Card.Body>
<Datapoint name={t('html.label.currentUptime')}
color={'light-green'} icon={faPowerOff}
value={data.current_uptime}/>
<hr/>
<Datapoint name={t('html.label.totalPlayers')}
color={'black'} icon={faUsers}
value={data.total_players} bold/>
<Datapoint name={t('html.label.regularPlayers')}
color={'lime'} icon={faUsers}
value={data.regular_players} bold/>
<Datapoint name={t('html.label.playersOnline')}
color={'blue'} icon={faUser}
value={data.online_players} bold/>
<hr/>
<Datapoint name={t('html.label.lastPeak') + ' (' + data.last_peak_date + ')'}
color={'blue'} icon={faChartLine}
value={data.last_peak_players} valueLabel={t('html.unit.players')} bold/>
<Datapoint name={t('html.label.bestPeak') + ' (' + data.best_peak_date + ')'}
color={'light-green'} icon={faChartLine}
value={data.best_peak_players} valueLabel={t('html.unit.players')} bold/>
<hr/>
<Datapoint name={t('html.label.totalPlaytime')}
color={'green'} icon={faClock}
value={data.playtime}/>
<Datapoint name={t('html.label.averagePlaytime') + ' ' + t('html.label.perPlayer')}
color={'green'} icon={faClock}
value={data.player_playtime}/>
<Datapoint name={t('html.label.sessions')}
color={'teal'} icon={faCalendarCheck}
value={data.sessions} bold/>
<hr/>
<Datapoint name={t('html.label.playerKills')}
color={'red'} icon={faCrosshairs}
value={data.player_kills} bold/>
<Datapoint name={t('html.label.mobKills')}
color={'green'} icon={faCrosshairs}
value={data.mob_kills} bold/>
<Datapoint name={t('html.label.deaths')}
color={'black'} icon={faSkull}
value={data.deaths} bold/>
</Card.Body>
</Card>
)
}
export default ServerAsNumbersCard;

View File

@ -11,7 +11,7 @@ const LineGraph = ({id, series}) => {
useEffect(() => { useEffect(() => {
NoDataDisplay(Highcharts); NoDataDisplay(Highcharts);
Highcharts.setOptions({lang: {noData: t('html.labels.noDataToDisplay')}}) Highcharts.setOptions({lang: {noData: t('html.label.noDataToDisplay')}})
Highcharts.setOptions(graphTheming); Highcharts.setOptions(graphTheming);
Highcharts.stockChart(id, { Highcharts.stockChart(id, {
rangeSelector: { rangeSelector: {

View File

@ -2,11 +2,11 @@ import React from "react";
import {FontAwesomeIcon as Fa} from "@fortawesome/react-fontawesome"; import {FontAwesomeIcon as Fa} from "@fortawesome/react-fontawesome";
import {faCaretDown, faCaretRight, faCaretUp} from "@fortawesome/free-solid-svg-icons"; import {faCaretDown, faCaretRight, faCaretUp} from "@fortawesome/free-solid-svg-icons";
const TrendUpGood = ({value}) => <Fa icon={faCaretUp} className="badge bg-success" title={value}/>; const TrendUpGood = ({value}) => <Fa icon={faCaretUp} className="text-success" title={value}/>;
const TrendUpBad = ({value}) => <Fa icon={faCaretUp} className="badge bg-danger" title={value}/>; const TrendUpBad = ({value}) => <Fa icon={faCaretUp} className="text-danger" title={value}/>;
const TrendDownBad = ({value}) => <Fa icon={faCaretDown} className="badge bg-danger" title={value}/>; const TrendDownBad = ({value}) => <Fa icon={faCaretDown} className="text-danger" title={value}/>;
const TrendDownGood = ({value}) => <Fa icon={faCaretDown} className="badge bg-success" title={value}/>; const TrendDownGood = ({value}) => <Fa icon={faCaretDown} className="text-success" title={value}/>;
const TrendSame = ({value}) => <Fa icon={faCaretRight} className="badge bg-warning" title={value}/>; const TrendSame = ({value}) => <Fa icon={faCaretRight} className="text-warning" title={value}/>;
const SmallTrend = ({trend}) => { const SmallTrend = ({trend}) => {

View File

@ -1,200 +0,0 @@
import React from "react";
import {Card, Col, Row} from "react-bootstrap-v5";
import {FontAwesomeIcon as Fa} from "@fortawesome/react-fontawesome";
import {
faBookOpen,
faChartLine,
faCrosshairs,
faExchangeAlt,
faExclamationCircle,
faPowerOff,
faSkull,
faTachometerAlt,
faUser,
faUsers
} from "@fortawesome/free-solid-svg-icons";
import Datapoint from "../components/Datapoint";
import {useTranslation} from "react-i18next";
import {useParams} from "react-router-dom";
import {fetchServerOverview} from "../service/serverService";
import {faCalendarCheck, faClock} from "@fortawesome/free-regular-svg-icons";
import {TableRow} from "../components/table/AsNumbersTable";
import ComparisonTable from "../components/table/ComparisonTable";
import BigTrend from "../components/trend/BigTrend";
import ErrorView from "./ErrorView";
import {useDataRequest} from "../hooks/dataFetchHook";
import OnlineActivityCard from "../components/cards/server/OnlineActivityCard";
const Last7DaysCard = ({data}) => {
const {t} = useTranslation();
if (!data) return <></>;
return (
<Card>
<Card.Header>
<h6 className="col-black">
{t('html.label.last7days')}
</h6>
</Card.Header>
<Card.Body>
<Datapoint name={t('html.label.uniquePlayers')}
color={'blue'} icon={faUsers}
value={data.unique_players} bold/>
<Datapoint name={t('html.label.uniquePlayers') + ' ' + t('html.label.perDay')}
color={'blue'} icon={faUser}
value={data.unique_players_day} bold/>
<Datapoint name={t('html.label.newPlayers')}
color={'light-green'} icon={faUsers}
value={data.new_players} bold/>
<Datapoint name={t('html.label.newPlayers')}
color={'light-green'} icon={faUsers}
value={data.new_players_retention_perc}
valueLabel={data.new_players_retention + '/' + data.new_players} bold/>
<hr/>
<Datapoint name={t('html.label.averageTps')}
color={'orange'} icon={faTachometerAlt}
value={data.average_tps} bold/>
<Datapoint name={t('html.label.lowTpsSpikes')}
color={'red'} icon={faExclamationCircle}
value={data.low_tps_spikes} bold/>
<Datapoint name={t('html.label.downtime')}
color={'red'} icon={faPowerOff}
value={data.downtime}/>
</Card.Body>
</Card>
)
}
const ServerAsNumbersCard = ({data}) => {
const {t} = useTranslation();
if (!data) return <></>;
return (
<Card>
<Card.Header>
<h6 className="col-black">
<Fa icon={faBookOpen}/> {t('html.label.serverAsNumberse')}
</h6>
</Card.Header>
<Card.Body>
<Datapoint name={t('html.label.currentUptime')}
color={'light-green'} icon={faPowerOff}
value={data.current_uptime}/>
<hr/>
<Datapoint name={t('html.label.totalPlayers')}
color={'black'} icon={faUsers}
value={data.total_players} bold/>
<Datapoint name={t('html.label.regularPlayers')}
color={'lime'} icon={faUsers}
value={data.regular_players} bold/>
<Datapoint name={t('html.label.playersOnline')}
color={'blue'} icon={faUser}
value={data.online_players} bold/>
<hr/>
<Datapoint name={t('html.label.lastPeak') + ' (' + data.last_peak_date + ')'}
color={'blue'} icon={faChartLine}
value={data.last_peak_players} valueLabel={t('html.unit.players')} bold/>
<Datapoint name={t('html.label.bestPeak') + ' (' + data.best_peak_date + ')'}
color={'light-green'} icon={faChartLine}
value={data.best_peak_players} valueLabel={t('html.unit.players')} bold/>
<hr/>
<Datapoint name={t('html.label.totalPlaytime')}
color={'green'} icon={faClock}
value={data.playtime}/>
<Datapoint name={t('html.label.averagePlaytime') + ' ' + t('html.label.perPlayer')}
color={'green'} icon={faClock}
value={data.player_playtime}/>
<Datapoint name={t('html.label.sessions')}
color={'teal'} icon={faCalendarCheck}
value={data.sessions} bold/>
<hr/>
<Datapoint name={t('html.label.playerKills')}
color={'red'} icon={faCrosshairs}
value={data.player_kills} bold/>
<Datapoint name={t('html.label.mobKills')}
color={'green'} icon={faCrosshairs}
value={data.mob_kills} bold/>
<Datapoint name={t('html.label.deaths')}
color={'black'} icon={faSkull}
value={data.deaths} bold/>
</Card.Body>
</Card>
)
}
const WeekComparisonCard = ({data}) => {
const {t} = useTranslation();
if (!data) return <></>;
return (
<Card>
<Card.Header>
<h6 className="col-black">
<Fa icon={faExchangeAlt}/> {t('html.label.weekComparison')}
</h6>
</Card.Header>
<ComparisonTable comparisonHeader={t('html.label.comparing7days')}
headers={[data.start + ' - ' + data.midpoint, data.midpoint + ' - ' + data.end, t('html.label.trend')]}>
<TableRow icon={faUsers} color="blue" text={t('html.label.uniquePlayers')}
values={[data.unique_before, data.unique_after, <BigTrend trend={data.unique_trend}/>]}/>
<TableRow icon={faUsers} color="light-green" text={t('html.label.newPlayers')}
values={[data.new_before, data.new_after, <BigTrend trend={data.new_trend}/>]}/>
<TableRow icon={faUsers} color="lime" text={t('html.label.regularPlayers')}
values={[data.regular_before, data.regular_after, <BigTrend trend={data.regular_trend}/>]}/>
<TableRow icon={faClock} color="green"
text={t('html.label.averagePlaytime') + ' ' + t('html.label.perPlayer')}
values={[data.average_playtime_before, data.average_playtime_after,
<BigTrend trend={data.average_playtime_trend}/>]}/>
<TableRow icon={faCalendarCheck} color="teal" text={t('html.label.sessions')}
values={[data.sessions_before, data.sessions_after,
<BigTrend trend={data.sessions_trend}/>]}/>
<TableRow icon={faCrosshairs} color="red" text={t('html.label.playerKills')}
values={[data.player_kills_before, data.player_kills_after,
<BigTrend trend={data.player_kills_trend}/>]}/>
<TableRow icon={faCrosshairs} color="green" text={t('html.label.mobKills')}
values={[data.mob_kills_before, data.mob_kills_after,
<BigTrend trend={data.mob_kills_trend}/>]}/>
<TableRow icon={faSkull} color="black" text={t('html.label.deaths')}
values={[data.deaths_before, data.deaths_after, <BigTrend trend={data.deaths_trend}/>]}/>
</ComparisonTable>
</Card>
)
}
const ServerOverview = () => {
const {identifier} = useParams();
const {data, loadingError} = useDataRequest(
fetchServerOverview,
[identifier])
if (loadingError) {
return <ErrorView error={loadingError}/>
}
return (
<section className="server_overview">
<Row>
<Col lg={9}>
<OnlineActivityCard/>
</Col>
<Col lg={3}>
<Last7DaysCard data={data ? data.last_7_days : undefined}/>
</Col>
</Row>
<Row>
<Col lg={4}>
<ServerAsNumbersCard data={data ? data.numbers : undefined}/>
</Col>
<Col lg={8}>
<WeekComparisonCard data={data ? data.weeks : undefined}/>
</Col>
</Row>
</section>
)
}
export default ServerOverview;

View File

@ -1,17 +1,17 @@
import React, {useEffect, useState} from "react"; import React, {useEffect, useState} from "react";
import Sidebar from "../components/navigation/Sidebar"; import Sidebar from "../../components/navigation/Sidebar";
import {Outlet, useOutletContext, useParams} from "react-router-dom"; import {Outlet, useOutletContext, useParams} from "react-router-dom";
import ColorSelectorModal from "../components/modal/ColorSelectorModal"; import ColorSelectorModal from "../../components/modal/ColorSelectorModal";
import {NightModeCss} from "../hooks/themeHook"; import {NightModeCss} from "../../hooks/themeHook";
import {fetchPlayer} from "../service/playerService"; import {fetchPlayer} from "../../service/playerService";
import ErrorView from "./ErrorView"; import ErrorView from "../ErrorView";
import {faCampground, faCubes, faInfoCircle, faNetworkWired} from "@fortawesome/free-solid-svg-icons"; import {faCampground, faCubes, faInfoCircle, faNetworkWired} from "@fortawesome/free-solid-svg-icons";
import {useAuth} from "../hooks/authenticationHook"; import {useAuth} from "../../hooks/authenticationHook";
import Header from "../components/navigation/Header"; import Header from "../../components/navigation/Header";
import {useNavigation} from "../hooks/navigationHook"; import {useNavigation} from "../../hooks/navigationHook";
import {useTranslation} from "react-i18next"; import {useTranslation} from "react-i18next";
import {faCalendarCheck} from "@fortawesome/free-regular-svg-icons"; import {faCalendarCheck} from "@fortawesome/free-regular-svg-icons";
import {useDataRequest} from "../hooks/dataFetchHook"; import {useDataRequest} from "../../hooks/dataFetchHook";
const PlayerPage = () => { const PlayerPage = () => {

View File

@ -1,7 +1,7 @@
import React, {useEffect, useState} from "react"; import React, {useEffect, useState} from "react";
import {useTranslation} from "react-i18next"; import {useTranslation} from "react-i18next";
import {Outlet} from "react-router-dom"; import {Outlet} from "react-router-dom";
import {useNavigation} from "../hooks/navigationHook"; import {useNavigation} from "../../hooks/navigationHook";
import { import {
faCampground, faCampground,
faChartArea, faChartArea,
@ -15,13 +15,13 @@ import {
faUsers, faUsers,
faUsersViewfinder faUsersViewfinder
} from "@fortawesome/free-solid-svg-icons"; } from "@fortawesome/free-solid-svg-icons";
import {useAuth} from "../hooks/authenticationHook"; import {useAuth} from "../../hooks/authenticationHook";
import {NightModeCss} from "../hooks/themeHook"; import {NightModeCss} from "../../hooks/themeHook";
import Sidebar from "../components/navigation/Sidebar"; import Sidebar from "../../components/navigation/Sidebar";
import Header from "../components/navigation/Header"; import Header from "../../components/navigation/Header";
import ErrorView from "./ErrorView"; import ErrorView from "../ErrorView";
import ColorSelectorModal from "../components/modal/ColorSelectorModal"; import ColorSelectorModal from "../../components/modal/ColorSelectorModal";
import {useMetadata} from "../hooks/metadataHook"; import {useMetadata} from "../../hooks/metadataHook";
import {faCalendarCheck} from "@fortawesome/free-regular-svg-icons"; import {faCalendarCheck} from "@fortawesome/free-regular-svg-icons";
const ServerPage = () => { const ServerPage = () => {

View File

@ -18,15 +18,15 @@ import {
faWifi faWifi
} from "@fortawesome/free-solid-svg-icons"; } from "@fortawesome/free-solid-svg-icons";
import {faSuperpowers} from "@fortawesome/free-brands-svg-icons"; import {faSuperpowers} from "@fortawesome/free-brands-svg-icons";
import Scrollable from "../components/Scrollable"; import Scrollable from "../../components/Scrollable";
import PunchCard from "../components/graphs/PunchCard"; import PunchCard from "../../components/graphs/PunchCard";
import Datapoint from "../components/Datapoint"; import Datapoint from "../../components/Datapoint";
import AsNumbersTable, {TableRow} from "../components/table/AsNumbersTable"; import AsNumbersTable, {TableRow} from "../../components/table/AsNumbersTable";
import {useTheme} from "../hooks/themeHook"; import {useTheme} from "../../hooks/themeHook";
import {usePlayer} from "./PlayerPage"; import {usePlayer} from "../layout/PlayerPage";
import {useMetadata} from "../hooks/metadataHook"; import {useMetadata} from "../../hooks/metadataHook";
import {useTranslation} from "react-i18next"; import {useTranslation} from "react-i18next";
import NicknamesCard from "../components/cards/player/NicknamesCard"; import NicknamesCard from "../../components/cards/player/NicknamesCard";
const PlayerOverviewCard = ({player}) => { const PlayerOverviewCard = ({player}) => {
const {t} = useTranslation(); const {t} = useTranslation();

View File

@ -1,9 +1,9 @@
import React, {useEffect} from "react"; import React, {useEffect} from "react";
import ExtensionCard, {ExtensionCardWrapper} from "../components/extensions/ExtensionCard"; import ExtensionCard, {ExtensionCardWrapper} from "../../components/extensions/ExtensionCard";
import {Card, Row} from "react-bootstrap-v5"; import {Card, Row} from "react-bootstrap-v5";
import {useParams} from "react-router-dom"; import {useParams} from "react-router-dom";
import Masonry from "masonry-layout"; import Masonry from "masonry-layout";
import {usePlayer} from "./PlayerPage"; import {usePlayer} from "../layout/PlayerPage";
const PlayerPluginData = () => { const PlayerPluginData = () => {
const {player} = usePlayer(); const {player} = usePlayer();

View File

@ -3,12 +3,12 @@ import {Card, Col, Row} from "react-bootstrap-v5";
import {FontAwesomeIcon as Fa} from "@fortawesome/react-fontawesome"; import {FontAwesomeIcon as Fa} from "@fortawesome/react-fontawesome";
import {faLifeRing} from "@fortawesome/free-regular-svg-icons"; import {faLifeRing} from "@fortawesome/free-regular-svg-icons";
import {faKhanda, faSkull} from "@fortawesome/free-solid-svg-icons"; import {faKhanda, faSkull} from "@fortawesome/free-solid-svg-icons";
import Datapoint from "../components/Datapoint"; import Datapoint from "../../components/Datapoint";
import KillsTable from "../components/table/KillsTable"; import KillsTable from "../../components/table/KillsTable";
import {usePlayer} from "./PlayerPage"; import {usePlayer} from "../layout/PlayerPage";
import {useTranslation} from "react-i18next"; import {useTranslation} from "react-i18next";
import PvpPveAsNumbersCard from "../components/cards/player/PvpPveAsNumbersCard"; import PvpPveAsNumbersCard from "../../components/cards/player/PvpPveAsNumbersCard";
import PvpKillsTableCard from "../components/cards/common/PvpKillsTableCard"; import PvpKillsTableCard from "../../components/cards/common/PvpKillsTableCard";
const InsightsCard = ({player}) => { const InsightsCard = ({player}) => {
const {t} = useTranslation(); const {t} = useTranslation();

View File

@ -2,13 +2,13 @@ import React from "react";
import {Card, Col, Row} from "react-bootstrap-v5"; import {Card, Col, Row} from "react-bootstrap-v5";
import {FontAwesomeIcon as Fa} from "@fortawesome/react-fontawesome"; import {FontAwesomeIcon as Fa} from "@fortawesome/react-fontawesome";
import {faHandPointer} from "@fortawesome/free-regular-svg-icons"; import {faHandPointer} from "@fortawesome/free-regular-svg-icons";
import Scrollable from "../components/Scrollable"; import Scrollable from "../../components/Scrollable";
import {faNetworkWired, faSignal} from "@fortawesome/free-solid-svg-icons"; import {faNetworkWired, faSignal} from "@fortawesome/free-solid-svg-icons";
import ServerPie from "../components/graphs/ServerPie"; import ServerPie from "../../components/graphs/ServerPie";
import ServerAccordion from "../components/accordion/ServerAccordion"; import ServerAccordion from "../../components/accordion/ServerAccordion";
import {usePlayer} from "./PlayerPage"; import {usePlayer} from "../layout/PlayerPage";
import {useTranslation} from "react-i18next"; import {useTranslation} from "react-i18next";
import PingGraph from "../components/graphs/PingGraph"; import PingGraph from "../../components/graphs/PingGraph";
const PingGraphCard = ({player}) => { const PingGraphCard = ({player}) => {
const {t} = useTranslation(); const {t} = useTranslation();

View File

@ -2,11 +2,11 @@ import React from "react";
import {Card, Col, Row} from "react-bootstrap-v5"; import {Card, Col, Row} from "react-bootstrap-v5";
import {FontAwesomeIcon as Fa} from "@fortawesome/react-fontawesome"; import {FontAwesomeIcon as Fa} from "@fortawesome/react-fontawesome";
import {faCalendarAlt} from "@fortawesome/free-regular-svg-icons"; import {faCalendarAlt} from "@fortawesome/free-regular-svg-icons";
import PlayerSessionCalendar from "../components/calendar/PlayerSessionCalendar"; import PlayerSessionCalendar from "../../components/calendar/PlayerSessionCalendar";
import {usePlayer} from "./PlayerPage"; import {usePlayer} from "../layout/PlayerPage";
import {useTranslation} from "react-i18next"; import {useTranslation} from "react-i18next";
import PlayerWorldPieCard from "../components/cards/player/PlayerWorldPieCard"; import PlayerWorldPieCard from "../../components/cards/player/PlayerWorldPieCard";
import PlayerRecentSessionsCard from "../components/cards/player/PlayerRecentSessionsCard"; import PlayerRecentSessionsCard from "../../components/cards/player/PlayerRecentSessionsCard";
const SessionCalendarCard = ({player}) => { const SessionCalendarCard = ({player}) => {
const {t} = useTranslation(); const {t} = useTranslation();

View File

@ -1,14 +1,14 @@
import React from "react"; import React from "react";
import {Col, Row} from "react-bootstrap-v5"; import {Col, Row} from "react-bootstrap-v5";
import OnlineActivityGraphsCard from "../components/cards/server/OnlineActivityGraphsCard"; import OnlineActivityGraphsCard from "../../components/cards/server/graphs/OnlineActivityGraphsCard";
import OnlineActivityAsNumbersCard from "../components/cards/server/OnlineActivityAsNumbersCard"; import OnlineActivityAsNumbersCard from "../../components/cards/server/tables/OnlineActivityAsNumbersCard";
import {useParams} from "react-router-dom"; import {useParams} from "react-router-dom";
import {useDataRequest} from "../hooks/dataFetchHook"; import {useDataRequest} from "../../hooks/dataFetchHook";
import {fetchOnlineActivityOverview} from "../service/serverService"; import {fetchOnlineActivityOverview} from "../../service/serverService";
import {ErrorViewBody} from "./ErrorView"; import {ErrorViewBody} from "../ErrorView";
import OnlineActivityInsightsCard from "../components/cards/server/OnlineActivityInsightsCard"; import OnlineActivityInsightsCard from "../../components/cards/server/insights/OnlineActivityInsightsCard";
const ServerOnlineActivity = () => { const OnlineActivity = () => {
const {identifier} = useParams(); const {identifier} = useParams();
const {data, loadingError} = useDataRequest(fetchOnlineActivityOverview, [identifier]) const {data, loadingError} = useDataRequest(fetchOnlineActivityOverview, [identifier])
@ -35,4 +35,4 @@ const ServerOnlineActivity = () => {
) )
} }
export default ServerOnlineActivity export default OnlineActivity

View File

@ -1,13 +1,15 @@
import {Col, Row} from "react-bootstrap-v5"; import {Col, Row} from "react-bootstrap-v5";
import React from "react"; import React from "react";
import PlayerbaseDevelopmentCard from "../components/cards/server/PlayerbaseDevelopmentCard"; import PlayerbaseDevelopmentCard from "../../components/cards/server/graphs/PlayerbaseDevelopmentCard";
import CurrentPlayerbaseCard from "../components/cards/server/CurrentPlayerbaseCard"; import CurrentPlayerbaseCard from "../../components/cards/server/graphs/CurrentPlayerbaseCard";
import {useParams} from "react-router-dom"; import {useParams} from "react-router-dom";
import {useDataRequest} from "../hooks/dataFetchHook"; import {useDataRequest} from "../../hooks/dataFetchHook";
import {fetchPlayerbaseOverview} from "../service/serverService"; import {fetchPlayerbaseOverview} from "../../service/serverService";
import ErrorView from "./ErrorView"; import ErrorView from "../ErrorView";
import PlayerbaseTrendsCard from "../../components/cards/server/tables/PlayerbaseTrendsCard";
import PlayerbaseInsightsCard from "../../components/cards/server/insights/PlayerbaseInsightsCard";
const ServerPlayerbaseOverview = () => { const PlayerbaseOverview = () => {
const {identifier} = useParams(); const {identifier} = useParams();
const {data, loadingError} = useDataRequest(fetchPlayerbaseOverview, [identifier]); const {data, loadingError} = useDataRequest(fetchPlayerbaseOverview, [identifier]);
@ -27,10 +29,10 @@ const ServerPlayerbaseOverview = () => {
</Row> </Row>
<Row> <Row>
<Col lg={8}> <Col lg={8}>
<PlayerbaseTrendsCard data={data?.trends}/>
</Col> </Col>
<Col lg={4}> <Col lg={4}>
<PlayerbaseInsightsCard data={data?.insights}/>
</Col> </Col>
</Row> </Row>
</section> </section>
@ -38,4 +40,4 @@ const ServerPlayerbaseOverview = () => {
) )
} }
export default ServerPlayerbaseOverview; export default PlayerbaseOverview;

View File

@ -0,0 +1,89 @@
import React from "react";
import {Card, Col, Row} from "react-bootstrap-v5";
import {faExclamationCircle, faPowerOff, faTachometerAlt, faUser, faUsers} from "@fortawesome/free-solid-svg-icons";
import Datapoint from "../../components/Datapoint";
import {useTranslation} from "react-i18next";
import {useParams} from "react-router-dom";
import {fetchServerOverview} from "../../service/serverService";
import ErrorView from "../ErrorView";
import {useDataRequest} from "../../hooks/dataFetchHook";
import OnlineActivityCard from "../../components/cards/server/graphs/OnlineActivityCard";
import ServerAsNumbersCard from "../../components/cards/server/values/ServerAsNumbersCard";
import ServerWeekComparisonCard from "../../components/cards/server/tables/ServerWeekComparisonCard";
const Last7DaysCard = ({data}) => {
const {t} = useTranslation();
if (!data) return <></>;
return (
<Card>
<Card.Header>
<h6 className="col-black">
{t('html.label.last7days')}
</h6>
</Card.Header>
<Card.Body>
<Datapoint name={t('html.label.uniquePlayers')}
color={'blue'} icon={faUsers}
value={data.unique_players} bold/>
<Datapoint name={t('html.label.uniquePlayers') + ' ' + t('html.label.perDay')}
color={'blue'} icon={faUser}
value={data.unique_players_day} bold/>
<Datapoint name={t('html.label.newPlayers')}
color={'light-green'} icon={faUsers}
value={data.new_players} bold/>
<Datapoint name={t('html.label.newPlayers')}
color={'light-green'} icon={faUsers}
value={data.new_players_retention_perc}
valueLabel={data.new_players_retention + '/' + data.new_players} bold/>
<hr/>
<Datapoint name={t('html.label.averageTps')}
color={'orange'} icon={faTachometerAlt}
value={data.average_tps} bold/>
<Datapoint name={t('html.label.lowTpsSpikes')}
color={'red'} icon={faExclamationCircle}
value={data.low_tps_spikes} bold/>
<Datapoint name={t('html.label.downtime')}
color={'red'} icon={faPowerOff}
value={data.downtime}/>
</Card.Body>
</Card>
)
}
const ServerOverview = () => {
const {identifier} = useParams();
const {data, loadingError} = useDataRequest(
fetchServerOverview,
[identifier])
if (loadingError) {
return <ErrorView error={loadingError}/>
}
return (
<section className="server_overview">
<Row>
<Col lg={9}>
<OnlineActivityCard/>
</Col>
<Col lg={3}>
<Last7DaysCard data={data?.last_7_days}/>
</Col>
</Row>
<Row>
<Col lg={4}>
<ServerAsNumbersCard data={data?.numbers}/>
</Col>
<Col lg={8}>
<ServerWeekComparisonCard data={data?.weeks}/>
</Col>
</Row>
</section>
)
}
export default ServerOverview;

View File

@ -1,8 +1,8 @@
import React from "react"; import React from "react";
import PvpPveAsNumbersCard from "../components/cards/server/PvpPveAsNumbersCard"; import PvpPveAsNumbersCard from "../../components/cards/server/tables/PvpPveAsNumbersCard";
import {Col, Row} from "react-bootstrap-v5"; import {Col, Row} from "react-bootstrap-v5";
import PvpKillsTableCard from "../components/cards/common/PvpKillsTableCard"; import PvpKillsTableCard from "../../components/cards/common/PvpKillsTableCard";
import PvpPveInsightsCard from "../components/cards/server/PvpPveInsightsCard"; import PvpPveInsightsCard from "../../components/cards/server/insights/PvpPveInsightsCard";
const ServerPvpPve = () => { const ServerPvpPve = () => {
return ( return (

View File

@ -1,8 +1,8 @@
import {Col, Row} from "react-bootstrap-v5"; import {Col, Row} from "react-bootstrap-v5";
import React from "react"; import React from "react";
import ServerWorldPieCard from "../components/cards/server/ServerWorldPieCard"; import ServerWorldPieCard from "../../components/cards/server/graphs/ServerWorldPieCard";
import ServerRecentSessionsCard from "../components/cards/server/ServerRecentSessionsCard"; import ServerRecentSessionsCard from "../../components/cards/server/tables/ServerRecentSessionsCard";
import SessionInsightsCard from "../components/cards/server/SessionInsightsCard"; import SessionInsightsCard from "../../components/cards/server/insights/SessionInsightsCard";
const ServerSessions = () => { const ServerSessions = () => {
return ( return (