mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2024-09-27 14:02:38 +02:00
Implemented some more structure for server page
This commit is contained in:
parent
e77a9ee8b5
commit
45baebfb01
@ -21,6 +21,7 @@ import ServerPage from "./views/ServerPage";
|
||||
import ServerOverview from "./views/ServerOverview";
|
||||
import MainPageRedirect from "./components/navigation/MainPageRedirect";
|
||||
import ServerOnlineActivity from "./views/ServerOnlineActivity";
|
||||
import ServerSessions from "./views/ServerSessions";
|
||||
|
||||
const OverviewRedirect = () => {
|
||||
return (<Navigate to={"overview"} replace={true}/>)
|
||||
@ -65,7 +66,7 @@ function App() {
|
||||
<Route path="" element={<OverviewRedirect/>}/>
|
||||
<Route path="overview" element={<ServerOverview/>}/>
|
||||
<Route path="online-activity" element={<ServerOnlineActivity/>}/>
|
||||
<Route path="sessions" element={<></>}/>
|
||||
<Route path="sessions" element={<ServerSessions/>}/>
|
||||
<Route path="pvppve" element={<></>}/>
|
||||
<Route path="playerbase" element={<></>}/>
|
||||
<Route path="players" element={<></>}/>
|
||||
|
@ -0,0 +1,23 @@
|
||||
import {useTranslation} from "react-i18next";
|
||||
import {Card} from "react-bootstrap-v5";
|
||||
import {FontAwesomeIcon as Fa} from "@fortawesome/react-fontawesome";
|
||||
import {faLifeRing} from "@fortawesome/free-solid-svg-icons";
|
||||
import React from "react";
|
||||
|
||||
const InsightsFor30DaysCard = ({children}) => {
|
||||
const {t} = useTranslation();
|
||||
return (
|
||||
<Card>
|
||||
<Card.Header>
|
||||
<h6 className="col-black">
|
||||
<Fa icon={faLifeRing} className="col-red"/> {t('html.label.insights30days')}
|
||||
</h6>
|
||||
</Card.Header>
|
||||
<Card.Body>
|
||||
{children}
|
||||
</Card.Body>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
export default InsightsFor30DaysCard;
|
@ -0,0 +1,28 @@
|
||||
import {useTranslation} from "react-i18next";
|
||||
import {Card} from "react-bootstrap-v5";
|
||||
import {FontAwesomeIcon as Fa} from "@fortawesome/react-fontawesome";
|
||||
import {faCalendar, faHandPointer} from "@fortawesome/free-regular-svg-icons";
|
||||
import Scrollable from "../../Scrollable";
|
||||
import SessionAccordion from "../../accordion/SessionAccordion";
|
||||
import React from "react";
|
||||
|
||||
const RecentSessionsCard = ({sessions}) => {
|
||||
const {t} = useTranslation();
|
||||
return (
|
||||
<Card>
|
||||
<Card.Header>
|
||||
<h6 className="col-black" style={{width: '100%'}}>
|
||||
<Fa icon={faCalendar} className="col-teal"/> {t('html.label.recentSessions')}
|
||||
<span className="float-end">
|
||||
<Fa icon={faHandPointer}/> <small>{t('html.text.clickToExpand')}</small>
|
||||
</span>
|
||||
</h6>
|
||||
</Card.Header>
|
||||
<Scrollable>
|
||||
<SessionAccordion sessions={sessions}/>
|
||||
</Scrollable>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
export default RecentSessionsCard;
|
@ -0,0 +1,26 @@
|
||||
import {useTranslation} from "react-i18next";
|
||||
import {Card} from "react-bootstrap-v5";
|
||||
import {FontAwesomeIcon as Fa} from "@fortawesome/react-fontawesome";
|
||||
import {faClock} from "@fortawesome/free-regular-svg-icons";
|
||||
import WorldPie from "../../graphs/WorldPie";
|
||||
import React from "react";
|
||||
|
||||
const WorldPieCard = ({worldSeries, gmSeries}) => {
|
||||
const {t} = useTranslation();
|
||||
return (
|
||||
<Card>
|
||||
<Card.Header>
|
||||
<h6 className="col-black" style={{width: '100%'}}>
|
||||
<Fa icon={faClock} className="col-teal"/> {t('html.label.worldPlaytime')}
|
||||
</h6>
|
||||
</Card.Header>
|
||||
<WorldPie
|
||||
id="world-pie"
|
||||
worldSeries={worldSeries}
|
||||
gmSeries={gmSeries}
|
||||
/>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
export default WorldPieCard;
|
@ -0,0 +1,10 @@
|
||||
import React from "react";
|
||||
import RecentSessionsCard from "../common/RecentSessionsCard";
|
||||
|
||||
const PlayerRecentSessionsCard = ({player}) => {
|
||||
return (
|
||||
<RecentSessionsCard sessions={player.sessions}/>
|
||||
)
|
||||
}
|
||||
|
||||
export default PlayerRecentSessionsCard;
|
@ -0,0 +1,13 @@
|
||||
import React from "react";
|
||||
import WorldPieCard from "../common/WorldPieCard";
|
||||
|
||||
const PlayerWorldPieCard = ({player}) => {
|
||||
return (
|
||||
<WorldPieCard
|
||||
worldSeries={player.world_pie_series}
|
||||
gmSeries={player.gm_series}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default PlayerWorldPieCard;
|
@ -0,0 +1,22 @@
|
||||
import {useTranslation} from "react-i18next";
|
||||
import {Card} from "react-bootstrap-v5";
|
||||
import {FontAwesomeIcon as Fa} from "@fortawesome/react-fontawesome";
|
||||
import {faCampground} from "@fortawesome/free-solid-svg-icons";
|
||||
import React from "react";
|
||||
import PvpPveAsNumbersTable from "../../table/PvpPveAsNumbersTable";
|
||||
|
||||
const PvpPveAsNumbersCard = ({player}) => {
|
||||
const {t} = useTranslation();
|
||||
return (
|
||||
<Card>
|
||||
<Card.Header>
|
||||
<h6 className="col-black">
|
||||
<Fa icon={faCampground} className="col-red"/> {t('html.label.pvpPveAsNumbers')}
|
||||
</h6>
|
||||
</Card.Header>
|
||||
<PvpPveAsNumbersTable killData={player.kill_data}/>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
export default PvpPveAsNumbersCard;
|
@ -0,0 +1,22 @@
|
||||
import {useTranslation} from "react-i18next";
|
||||
import {Card} from "react-bootstrap-v5";
|
||||
import {FontAwesomeIcon as Fa} from "@fortawesome/react-fontawesome";
|
||||
import {faBookOpen} from "@fortawesome/free-solid-svg-icons";
|
||||
import React from "react";
|
||||
import OnlineActivityAsNumbersTable from "../../table/OnlineActivityAsNumbersTable";
|
||||
|
||||
const OnlineActivityAsNumbersCard = () => {
|
||||
const {t} = useTranslation();
|
||||
return (
|
||||
<Card>
|
||||
<Card.Header>
|
||||
<h6 className="col-black">
|
||||
<Fa icon={faBookOpen} className="col-light-blue"/> {t('html.label.onlineActivityAsNumbers')}
|
||||
</h6>
|
||||
</Card.Header>
|
||||
<OnlineActivityAsNumbersTable/>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
export default OnlineActivityAsNumbersCard;
|
@ -0,0 +1,12 @@
|
||||
import React from "react";
|
||||
import InsightsFor30DaysCard from "../common/InsightsFor30DaysCard";
|
||||
|
||||
const OnlineActivityInsightsCard = () => {
|
||||
return (
|
||||
<InsightsFor30DaysCard>
|
||||
TODO
|
||||
</InsightsFor30DaysCard>
|
||||
)
|
||||
}
|
||||
|
||||
export default OnlineActivityInsightsCard;
|
@ -0,0 +1,22 @@
|
||||
import React from "react";
|
||||
import {useParams} from "react-router-dom";
|
||||
import {useDataRequest} from "../../../hooks/dataFetchHook";
|
||||
import {fetchSessions} from "../../../service/serverService";
|
||||
import {ErrorViewBody} from "../../../views/ErrorView";
|
||||
import RecentSessionsCard from "../common/RecentSessionsCard";
|
||||
|
||||
const ServerRecentSessionsCard = () => {
|
||||
|
||||
const {identifier} = useParams();
|
||||
|
||||
const {data, loadingError} = useDataRequest(fetchSessions, [identifier])
|
||||
|
||||
if (loadingError) return <ErrorViewBody error={loadingError}/>
|
||||
if (!data) return <></>;
|
||||
|
||||
return (
|
||||
<RecentSessionsCard sessions={data.sessions}/>
|
||||
)
|
||||
}
|
||||
|
||||
export default ServerRecentSessionsCard;
|
@ -0,0 +1,25 @@
|
||||
import React from "react";
|
||||
import WorldPieCard from "../common/WorldPieCard";
|
||||
import {useParams} from "react-router-dom";
|
||||
import {useDataRequest} from "../../../hooks/dataFetchHook";
|
||||
import {fetchWorldPie} from "../../../service/serverService";
|
||||
import {ErrorViewBody} from "../../../views/ErrorView";
|
||||
|
||||
const ServerWorldPieCard = () => {
|
||||
const {identifier} = useParams();
|
||||
|
||||
const {data, loadingError} = useDataRequest(fetchWorldPie, [identifier]);
|
||||
console.log(data);
|
||||
|
||||
if (loadingError) return <ErrorViewBody error={loadingError}/>
|
||||
if (!data) return <></>;
|
||||
|
||||
return (
|
||||
<WorldPieCard
|
||||
worldSeries={data.world_series}
|
||||
gmSeries={data.gm_series}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default ServerWorldPieCard;
|
@ -0,0 +1,12 @@
|
||||
import React from "react";
|
||||
import InsightsFor30DaysCard from "../common/InsightsFor30DaysCard";
|
||||
|
||||
const SessionInsightsCard = () => {
|
||||
return (
|
||||
<InsightsFor30DaysCard>
|
||||
TODO
|
||||
</InsightsFor30DaysCard>
|
||||
)
|
||||
}
|
||||
|
||||
export default SessionInsightsCard;
|
@ -0,0 +1,18 @@
|
||||
import {useTranslation} from "react-i18next";
|
||||
import AsNumbersTable, {TableRow} from "./AsNumbersTable";
|
||||
import {faUsers} from "@fortawesome/free-solid-svg-icons";
|
||||
import React from "react";
|
||||
|
||||
const OnlineActivityAsNumbersTable = () => {
|
||||
const {t} = useTranslation();
|
||||
return (
|
||||
<AsNumbersTable
|
||||
headers={[t('html.label.last30days'), t('html.label.last7days'), t('html.label.last24hours')]}
|
||||
>
|
||||
<TableRow icon={faUsers} color="light-blue" text={t('html.label.uniquePlayers')}
|
||||
values={["TODO"]}/>
|
||||
</AsNumbersTable>
|
||||
)
|
||||
}
|
||||
|
||||
export default OnlineActivityAsNumbersTable;
|
@ -0,0 +1,44 @@
|
||||
import {useTranslation} from "react-i18next";
|
||||
import AsNumbersTable, {TableRow} from "./AsNumbersTable";
|
||||
import {faCrosshairs, faSkull} from "@fortawesome/free-solid-svg-icons";
|
||||
import React from "react";
|
||||
|
||||
const PvpPveAsNumbersTable = ({killData}) => {
|
||||
const {t} = useTranslation();
|
||||
return (
|
||||
<AsNumbersTable
|
||||
headers={[t('html.label.allTime'), t('html.label.last30days'), t('html.label.last7days')]}
|
||||
>
|
||||
<TableRow icon={faCrosshairs} color="red" text={t('html.label.kdr')} bold
|
||||
values={[killData.player_kdr_total,
|
||||
killData.player_kdr_30d,
|
||||
killData.player_kdr_7d]}/>
|
||||
<TableRow icon={faCrosshairs} color="red" text={t('html.label.playerKills')}
|
||||
values={[killData.player_kills_total,
|
||||
killData.player_kills_30d,
|
||||
killData.player_kills_7d]}/>
|
||||
<TableRow icon={faSkull} color="red" text={t('html.label.playerDeaths')}
|
||||
values={[killData.player_deaths_total,
|
||||
killData.player_deaths_30d,
|
||||
killData.player_deaths_7d]}/>
|
||||
<TableRow icon={faCrosshairs} color="green" text={t('html.label.mobKdr')} bold
|
||||
values={[killData.mob_kdr_total,
|
||||
killData.mob_kdr_30d,
|
||||
killData.mob_kdr_7d]}/>
|
||||
<TableRow icon={faCrosshairs} color="green" text={t('html.label.mobKills')}
|
||||
values={[killData.mob_kills_total,
|
||||
killData.mob_kills_30d,
|
||||
killData.mob_kills_7d]}/>
|
||||
<TableRow icon={faSkull} color="green" text={t('html.label.mobDeaths')}
|
||||
values={[killData.mob_deaths_total,
|
||||
killData.mob_deaths_30d,
|
||||
killData.mob_deaths_7d]}/>
|
||||
<TableRow icon={faSkull} color="black" text={t('html.label.deaths')}
|
||||
values={[killData.deaths_total,
|
||||
killData.deaths_30d,
|
||||
killData.deaths_7d]}/>
|
||||
</AsNumbersTable>
|
||||
)
|
||||
}
|
||||
|
||||
export default PvpPveAsNumbersTable;
|
@ -6,6 +6,18 @@ export const fetchServerOverview = async (identifier) => {
|
||||
return doGetRequest(url);
|
||||
}
|
||||
|
||||
export const fetchOnlineActivityOverview = async (identifier) => {
|
||||
const timestamp = Date.now();
|
||||
const url = `/v1/onlineOverview?server=${identifier}×tamp=${timestamp}`;
|
||||
return doGetRequest(url);
|
||||
}
|
||||
|
||||
export const fetchSessions = async (identifier) => {
|
||||
const timestamp = Date.now();
|
||||
const url = `/v1/sessions?server=${identifier}×tamp=${timestamp}`;
|
||||
return doGetRequest(url);
|
||||
}
|
||||
|
||||
export const fetchPlayersOnlineGraph = async (identifier) => {
|
||||
const timestamp = Date.now();
|
||||
const url = `/v1/graph?type=playersOnline&server=${identifier}×tamp=${timestamp}`;
|
||||
@ -34,4 +46,10 @@ export const fetchPunchCardGraph = async (identifier) => {
|
||||
const timestamp = Date.now();
|
||||
const url = `/v1/graph?type=punchCard&server=${identifier}×tamp=${timestamp}`;
|
||||
return doGetRequest(url);
|
||||
}
|
||||
|
||||
export const fetchWorldPie = async (identifier) => {
|
||||
const timestamp = Date.now();
|
||||
const url = `/v1/graph?type=worldPie&server=${identifier}×tamp=${timestamp}`;
|
||||
return doGetRequest(url);
|
||||
}
|
@ -2,65 +2,12 @@ import React from "react";
|
||||
import {Card, Col, Row} from "react-bootstrap-v5";
|
||||
import {FontAwesomeIcon as Fa} from "@fortawesome/react-fontawesome";
|
||||
import {faLifeRing} from "@fortawesome/free-regular-svg-icons";
|
||||
import {faCampground, faCrosshairs, faKhanda, faSkull} from "@fortawesome/free-solid-svg-icons";
|
||||
import AsNumbersTable, {TableRow} from "../components/table/AsNumbersTable";
|
||||
import {faCrosshairs, faKhanda, faSkull} from "@fortawesome/free-solid-svg-icons";
|
||||
import Datapoint from "../components/Datapoint";
|
||||
import KillsTable from "../components/table/KillsTable";
|
||||
import {usePlayer} from "./PlayerPage";
|
||||
import {useTranslation} from "react-i18next";
|
||||
|
||||
|
||||
const PvpPveAsNumbersTable = ({player}) => {
|
||||
const {t} = useTranslation();
|
||||
return (
|
||||
<AsNumbersTable
|
||||
headers={[t('html.label.allTime'), t('html.label.last30days'), t('html.label.last7days')]}
|
||||
>
|
||||
<TableRow icon={faCrosshairs} color="red" text={t('html.label.kdr')} bold
|
||||
values={[player.kill_data.player_kdr_total,
|
||||
player.kill_data.player_kdr_30d,
|
||||
player.kill_data.player_kdr_7d]}/>
|
||||
<TableRow icon={faCrosshairs} color="red" text={t('html.label.playerKills')}
|
||||
values={[player.kill_data.player_kills_total,
|
||||
player.kill_data.player_kills_30d,
|
||||
player.kill_data.player_kills_7d]}/>
|
||||
<TableRow icon={faSkull} color="red" text={t('html.label.playerDeaths')}
|
||||
values={[player.kill_data.player_deaths_total,
|
||||
player.kill_data.player_deaths_30d,
|
||||
player.kill_data.player_deaths_7d]}/>
|
||||
<TableRow icon={faCrosshairs} color="green" text={t('html.label.mobKdr')} bold
|
||||
values={[player.kill_data.mob_kdr_total,
|
||||
player.kill_data.mob_kdr_30d,
|
||||
player.kill_data.mob_kdr_7d]}/>
|
||||
<TableRow icon={faCrosshairs} color="green" text={t('html.label.mobKills')}
|
||||
values={[player.kill_data.mob_kills_total,
|
||||
player.kill_data.mob_kills_30d,
|
||||
player.kill_data.mob_kills_7d]}/>
|
||||
<TableRow icon={faSkull} color="green" text={t('html.label.mobDeaths')}
|
||||
values={[player.kill_data.mob_deaths_total,
|
||||
player.kill_data.mob_deaths_30d,
|
||||
player.kill_data.mob_deaths_7d]}/>
|
||||
<TableRow icon={faSkull} color="black" text={t('html.label.deaths')}
|
||||
values={[player.kill_data.deaths_total,
|
||||
player.kill_data.deaths_30d,
|
||||
player.kill_data.deaths_7d]}/>
|
||||
</AsNumbersTable>
|
||||
)
|
||||
}
|
||||
|
||||
const PvpPveNumbersCard = ({player}) => {
|
||||
const {t} = useTranslation();
|
||||
return (
|
||||
<Card>
|
||||
<Card.Header>
|
||||
<h6 className="col-black">
|
||||
<Fa icon={faCampground} className="col-red"/> {t('html.label.pvpPveAsNumbers')}
|
||||
</h6>
|
||||
</Card.Header>
|
||||
<PvpPveAsNumbersTable player={player}/>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
import PvpPveAsNumbersCard from "../components/cards/player/PvpPveAsNumbersCard";
|
||||
|
||||
const InsightsCard = ({player}) => {
|
||||
const {t} = useTranslation();
|
||||
@ -117,7 +64,7 @@ const PlayerPvpPve = () => {
|
||||
<section className="player_pvp_pve">
|
||||
<Row>
|
||||
<Col lg={8}>
|
||||
<PvpPveNumbersCard player={player}/>
|
||||
<PvpPveAsNumbersCard player={player}/>
|
||||
</Col>
|
||||
<Col lg={4}>
|
||||
<InsightsCard player={player}/>
|
||||
|
@ -1,13 +1,12 @@
|
||||
import React from "react";
|
||||
import {Card, Col, Row} from "react-bootstrap-v5";
|
||||
import {FontAwesomeIcon as Fa} from "@fortawesome/react-fontawesome";
|
||||
import {faCalendar, faCalendarAlt, faClock, faHandPointer} from "@fortawesome/free-regular-svg-icons";
|
||||
import {faCalendarAlt} from "@fortawesome/free-regular-svg-icons";
|
||||
import PlayerSessionCalendar from "../components/calendar/PlayerSessionCalendar";
|
||||
import Scrollable from "../components/Scrollable";
|
||||
import SessionAccordion from "../components/accordion/SessionAccordion";
|
||||
import WorldPie from "../components/graphs/WorldPie";
|
||||
import {usePlayer} from "./PlayerPage";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import PlayerWorldPieCard from "../components/cards/player/PlayerWorldPieCard";
|
||||
import PlayerRecentSessionsCard from "../components/cards/player/PlayerRecentSessionsCard";
|
||||
|
||||
const SessionCalendarCard = ({player}) => {
|
||||
const {t} = useTranslation();
|
||||
@ -23,43 +22,6 @@ const SessionCalendarCard = ({player}) => {
|
||||
)
|
||||
}
|
||||
|
||||
const RecentSessionsCard = ({player}) => {
|
||||
const {t} = useTranslation();
|
||||
return (
|
||||
<Card>
|
||||
<Card.Header>
|
||||
<h6 className="col-black" style={{width: '100%'}}>
|
||||
<Fa icon={faCalendar} className="col-teal"/> {t('html.label.recentSessions')}
|
||||
<span className="float-end">
|
||||
<Fa icon={faHandPointer}/> <small>{t('html.text.clickToExpand')}</small>
|
||||
</span>
|
||||
</h6>
|
||||
</Card.Header>
|
||||
<Scrollable>
|
||||
<SessionAccordion sessions={player.sessions}/>
|
||||
</Scrollable>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
const WorldPieCard = ({player}) => {
|
||||
const {t} = useTranslation();
|
||||
return (
|
||||
<Card>
|
||||
<Card.Header>
|
||||
<h6 className="col-black" style={{width: '100%'}}>
|
||||
<Fa icon={faClock} className="col-teal"/> {t('html.label.worldPlaytime')}
|
||||
</h6>
|
||||
</Card.Header>
|
||||
<WorldPie
|
||||
id="world-pie"
|
||||
worldSeries={player.world_pie_series}
|
||||
gmSeries={player.gm_series}
|
||||
/>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
const PlayerSessions = () => {
|
||||
const {player} = usePlayer();
|
||||
return (
|
||||
@ -67,14 +29,14 @@ const PlayerSessions = () => {
|
||||
<Row>
|
||||
<Col lg={8}>
|
||||
<SessionCalendarCard player={player}/>
|
||||
<RecentSessionsCard player={player}/>
|
||||
<PlayerRecentSessionsCard player={player}/>
|
||||
</Col>
|
||||
<Col lg={4}>
|
||||
<WorldPieCard player={player}/>
|
||||
<PlayerWorldPieCard player={player}/>
|
||||
</Col>
|
||||
</Row>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
||||
export default PlayerSessions
|
||||
export default PlayerSessions;
|
@ -1,8 +1,21 @@
|
||||
import React from "react";
|
||||
import {Col, Row} from "react-bootstrap-v5";
|
||||
import OnlineActivityGraphsCard from "../components/cards/server/OnlineActivityGraphsCard";
|
||||
import OnlineActivityAsNumbersCard from "../components/cards/server/OnlineActivityAsNumbersCard";
|
||||
import {useParams} from "react-router-dom";
|
||||
import {useDataRequest} from "../hooks/dataFetchHook";
|
||||
import {fetchOnlineActivityOverview} from "../service/serverService";
|
||||
import {ErrorViewBody} from "./ErrorView";
|
||||
import OnlineActivityInsightsCard from "../components/cards/server/OnlineActivityInsightsCard";
|
||||
|
||||
const ServerOnlineActivity = () => {
|
||||
const {identifier} = useParams();
|
||||
|
||||
const {data, loadingError} = useDataRequest(fetchOnlineActivityOverview, [identifier])
|
||||
|
||||
if (loadingError) return <ErrorViewBody error={loadingError}/>
|
||||
if (!data) return <></>;
|
||||
|
||||
return (
|
||||
<section className="server_online_activity_overview">
|
||||
<Row>
|
||||
@ -11,9 +24,11 @@ const ServerOnlineActivity = () => {
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col lg={4}>
|
||||
</Col>
|
||||
<Col lg={8}>
|
||||
<OnlineActivityAsNumbersCard data={data}/>
|
||||
</Col>
|
||||
<Col lg={4}>
|
||||
<OnlineActivityInsightsCard data={data}/>
|
||||
</Col>
|
||||
</Row>
|
||||
</section>
|
||||
|
23
Plan/react/dashboard/src/views/ServerSessions.js
Normal file
23
Plan/react/dashboard/src/views/ServerSessions.js
Normal file
@ -0,0 +1,23 @@
|
||||
import {Col, Row} from "react-bootstrap-v5";
|
||||
import React from "react";
|
||||
import ServerWorldPieCard from "../components/cards/server/ServerWorldPieCard";
|
||||
import ServerRecentSessionsCard from "../components/cards/server/ServerRecentSessionsCard";
|
||||
import SessionInsightsCard from "../components/cards/server/SessionInsightsCard";
|
||||
|
||||
const ServerSessions = () => {
|
||||
return (
|
||||
<section className="server_sessions">
|
||||
<Row>
|
||||
<Col lg={8}>
|
||||
<ServerRecentSessionsCard/>
|
||||
</Col>
|
||||
<Col lg={4}>
|
||||
<ServerWorldPieCard/>
|
||||
<SessionInsightsCard/>
|
||||
</Col>
|
||||
</Row>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
||||
export default ServerSessions;
|
Loading…
Reference in New Issue
Block a user