mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2025-03-02 11:11:21 +01:00
Entered data for Online Activity Overview
This commit is contained in:
parent
7e1bd7f4a6
commit
f6ece8333b
@ -140,7 +140,8 @@ public enum HtmlLang implements Lang {
|
||||
COMPARING_15_DAYS("html.text.comparing15days", "Comparing 15 days"),
|
||||
TITLE_GRAPH_PUNCHCARD("html.label.punchcard30days", "Punchcard for 30 Days"),
|
||||
LABEL_ONLINE_FIRST_JOIN("html.label.onlineOnFirstJoin", "Players online on first join"),
|
||||
LABEL_FIRST_SESSION_LENGTH("html.label.firstSessionLength", "First session length"),
|
||||
LABEL_FIRST_SESSION_LENGTH_AVERAGE("html.label.firstSessionLength.average", "Average first session length"),
|
||||
LABEL_FIRST_SESSION_LENGTH_MEDIAN("html.label.firstSessionLength.median", "Median first session length"),
|
||||
LABEL_LONE_JOINS("html.label.loneJoins", "Lone joins"),
|
||||
LABEL_LONE_NEW_JOINS("html.label.loneNewbieJoins", "Lone newbie joins"),
|
||||
LABEL_MOST_ACTIVE_GAMEMODE("html.label.mostActiveGamemode", "Most Active Gamemode"),
|
||||
|
@ -158,9 +158,9 @@ function loadOnlineActivityOverviewValues(json, error) {
|
||||
element.querySelector('#data_new_players_7d_avg').innerText = data.new_players_7d_avg;
|
||||
element.querySelector('#data_new_players_24h_avg').innerText = data.new_players_24h_avg;
|
||||
|
||||
element.querySelector('#data_new_players_retention_30d').innerText = '(' + data.new_players_retention_30d + '/' + data.new_players_30d + ') ' + data.new_players_retention_30d_perc;
|
||||
element.querySelector('#data_new_players_retention_7d').innerText = '(' + data.new_players_retention_7d + '/' + data.new_players_7d + ') ' + data.new_players_retention_7d_perc;
|
||||
element.querySelector('#data_new_players_retention_24h').innerHTML = '(' + data.new_players_retention_24h + '/' + data.new_players_24h + ') ' + data.new_players_retention_24h_perc + ' <i class="far fa-fw fa-eye"></i>';
|
||||
element.querySelector('#data_new_players_retention_30d').innerText = `(${data.new_players_retention_30d}/${data.new_players_30d}) ${data.new_players_retention_30d_perc}`;
|
||||
element.querySelector('#data_new_players_retention_7d').innerText = `(${data.new_players_retention_7d}/${data.new_players_7d}) ${data.new_players_retention_7d_perc}`;
|
||||
element.querySelector('#data_new_players_retention_24h').innerHTML = `(${data.new_players_retention_24h}/${data.new_players_24h}) ${data.new_players_retention_24h_perc} <i class="far fa-fw fa-eye"></i>`;
|
||||
|
||||
element.querySelector('#data_playtime_30d').innerHTML = data.playtime_30d + smallTrend(data.playtime_30d_trend);
|
||||
element.querySelector('#data_playtime_7d').innerText = data.playtime_7d;
|
||||
|
@ -1,9 +1,6 @@
|
||||
import {FontAwesomeIcon as Fa} from "@fortawesome/react-fontawesome";
|
||||
import React from "react";
|
||||
|
||||
const End = ({children}) => (
|
||||
<span className="float-end">{children}</span>
|
||||
)
|
||||
import End from "./layout/End";
|
||||
|
||||
const Datapoint = ({icon, color, name, value, valueLabel, bold, boldTitle, title, trend}) => {
|
||||
const displayedValue = bold ? <b>{value}</b> : value;
|
||||
|
@ -1,10 +1,37 @@
|
||||
import React from "react";
|
||||
import InsightsFor30DaysCard from "../../common/InsightsFor30DaysCard";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import Datapoint from "../../../Datapoint";
|
||||
import {faUserClock, faUserGroup} from "@fortawesome/free-solid-svg-icons";
|
||||
import SmallTrend from "../../../trend/SmallTrend";
|
||||
import {faCalendar, faCalendarPlus} from "@fortawesome/free-regular-svg-icons";
|
||||
import ComparingLabel from "../../../trend/ComparingLabel";
|
||||
import End from "../../../layout/End";
|
||||
|
||||
const OnlineActivityInsightsCard = ({data}) => {
|
||||
const {t} = useTranslation();
|
||||
if (!data) return <></>
|
||||
|
||||
const OnlineActivityInsightsCard = () => {
|
||||
return (
|
||||
<InsightsFor30DaysCard>
|
||||
TODO
|
||||
<Datapoint name={t('html.label.onlineOnFirstJoin')} icon={faUserGroup} color="light-green"
|
||||
value={data.players_first_join_avg}
|
||||
trend={<SmallTrend trend={data.players_first_join_avg_trend}/>}/>
|
||||
<Datapoint name={t('html.label.firstSessionLength.average')} icon={faUserClock} color="light-green"
|
||||
value={data.first_session_length_avg}
|
||||
trend={<SmallTrend trend={data.first_session_length_avg_trend}/>}/>
|
||||
<Datapoint name={t('html.label.firstSessionLength.median')} icon={faUserClock} color="light-green"
|
||||
value={data.first_session_length_median}
|
||||
trend={<SmallTrend trend={data.first_session_length_median_trend}/>}/>
|
||||
<Datapoint name={t('html.label.loneJoins')} icon={faCalendar} color="teal"
|
||||
value={data.lone_joins}
|
||||
trend={<SmallTrend trend={data.lone_joins_trend}/>}/>
|
||||
<Datapoint name={t('html.label.loneNewbieJoins')} icon={faCalendarPlus} color="teal"
|
||||
value={data.lone_new_joins}
|
||||
trend={<SmallTrend trend={data.lone_new_joins_trend}/>}/>
|
||||
<End>
|
||||
<ComparingLabel>{t('html.text.comparing15days')}</ComparingLabel>
|
||||
</End>
|
||||
</InsightsFor30DaysCard>
|
||||
)
|
||||
}
|
||||
|
@ -5,6 +5,8 @@ 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";
|
||||
import End from "../../../layout/End";
|
||||
import ComparingLabel from "../../../trend/ComparingLabel";
|
||||
|
||||
const TwoPlayerChange = ({colorBefore, labelBefore, colorAfter, labelAfter}) => {
|
||||
return (
|
||||
@ -35,6 +37,7 @@ const PlayerbaseInsightsCard = ({data}) => {
|
||||
value={data.regular_to_inactive}
|
||||
trend={<SmallTrend trend={data.regular_to_inactive_trend}/>}
|
||||
/>
|
||||
<End><ComparingLabel>{t('html.text.comparing30daysAgo')}</ComparingLabel></End>
|
||||
</InsightsFor30DaysCard>
|
||||
)
|
||||
}
|
||||
|
@ -5,8 +5,10 @@ import {faBookOpen} from "@fortawesome/free-solid-svg-icons";
|
||||
import React from "react";
|
||||
import OnlineActivityAsNumbersTable from "../../../table/OnlineActivityAsNumbersTable";
|
||||
|
||||
const OnlineActivityAsNumbersCard = () => {
|
||||
const OnlineActivityAsNumbersCard = ({data}) => {
|
||||
const {t} = useTranslation();
|
||||
if (!data) return <></>
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<Card.Header>
|
||||
@ -14,7 +16,7 @@ const OnlineActivityAsNumbersCard = () => {
|
||||
<Fa icon={faBookOpen} className="col-light-blue"/> {t('html.label.onlineActivityAsNumbers')}
|
||||
</h6>
|
||||
</Card.Header>
|
||||
<OnlineActivityAsNumbersTable/>
|
||||
<OnlineActivityAsNumbersTable data={data}/>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
@ -3,10 +3,10 @@ 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";
|
||||
import {TableRow} from "../../../table/TableRow";
|
||||
|
||||
const PlayerbaseTrendsCard = ({data}) => {
|
||||
const {t} = useTranslation();
|
||||
|
@ -3,10 +3,10 @@ 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";
|
||||
import {TableRow} from "../../../table/TableRow";
|
||||
|
||||
const ServerWeekComparisonCard = ({data}) => {
|
||||
const {t} = useTranslation();
|
||||
|
7
Plan/react/dashboard/src/components/layout/End.js
Normal file
7
Plan/react/dashboard/src/components/layout/End.js
Normal file
@ -0,0 +1,7 @@
|
||||
import React from "react";
|
||||
|
||||
const End = ({children}) => (
|
||||
<span className="float-end">{children}</span>
|
||||
)
|
||||
|
||||
export default End;
|
@ -1,5 +1,4 @@
|
||||
import React from "react";
|
||||
import {FontAwesomeIcon as Fa} from "@fortawesome/react-fontawesome";
|
||||
import {useTheme} from "../../hooks/themeHook";
|
||||
|
||||
const AsNumbersTable = ({headers, children}) => {
|
||||
@ -18,14 +17,4 @@ const AsNumbersTable = ({headers, children}) => {
|
||||
</table>
|
||||
}
|
||||
|
||||
export const TableRow = ({icon, text, color, values, bold}) => {
|
||||
const label = (<><Fa icon={icon} className={'col-' + color}/> {text}</>);
|
||||
return (
|
||||
<tr>
|
||||
<td>{bold ? <b>{label}</b> : label}</td>
|
||||
{values.map((value, j) => <td key={j}>{value}</td>)}
|
||||
</tr>
|
||||
)
|
||||
}
|
||||
|
||||
export default AsNumbersTable
|
@ -1,21 +1,15 @@
|
||||
import React from "react";
|
||||
import {FontAwesomeIcon as Fa} from "@fortawesome/react-fontawesome";
|
||||
import {faCaretDown, faCaretUp} from "@fortawesome/free-solid-svg-icons";
|
||||
import {useTheme} from "../../hooks/themeHook";
|
||||
import ComparingLabel from "../trend/ComparingLabel";
|
||||
|
||||
const ComparisonTable = ({headers, children, comparisonHeader}) => {
|
||||
const {nightModeEnabled} = useTheme();
|
||||
|
||||
const zeroWidthIcon = {width: "0.7rem"}
|
||||
|
||||
return <table className={"table table-striped" + (nightModeEnabled ? " table-dark" : '')}>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
<Fa style={zeroWidthIcon} icon={faCaretUp} className="text-success"/><Fa style={zeroWidthIcon}
|
||||
icon={faCaretDown}
|
||||
className="text-danger"/>
|
||||
{' '}<small>{comparisonHeader}</small>
|
||||
<ComparingLabel>{comparisonHeader}</ComparingLabel>
|
||||
</th>
|
||||
{headers.map((header, i) => <th key={i}>{header}</th>)}
|
||||
</tr>
|
||||
@ -26,14 +20,4 @@ const ComparisonTable = ({headers, children, comparisonHeader}) => {
|
||||
</table>
|
||||
}
|
||||
|
||||
export const TableRow = ({icon, text, color, values, bold}) => {
|
||||
const label = (<><Fa icon={icon} className={'col-' + color}/> {text}</>);
|
||||
return (
|
||||
<tr>
|
||||
<td>{bold ? <b>{label}</b> : label}</td>
|
||||
{values.map((value, j) => <td key={j}>{value}</td>)}
|
||||
</tr>
|
||||
)
|
||||
}
|
||||
|
||||
export default ComparisonTable
|
@ -1,17 +1,85 @@
|
||||
import {useTranslation} from "react-i18next";
|
||||
import AsNumbersTable, {TableRow} from "./AsNumbersTable";
|
||||
import {faUsers} from "@fortawesome/free-solid-svg-icons";
|
||||
import {faUser, faUserCircle, faUserPlus, faUsers} from "@fortawesome/free-solid-svg-icons";
|
||||
import React from "react";
|
||||
import {TableRow} from "./TableRow";
|
||||
import ComparisonTable from "./ComparisonTable";
|
||||
import SmallTrend from "../trend/SmallTrend";
|
||||
import {FontAwesomeIcon as Fa} from "@fortawesome/react-fontawesome";
|
||||
import {faCalendarCheck, faClock, faEye} from "@fortawesome/free-regular-svg-icons";
|
||||
|
||||
const OnlineActivityAsNumbersTable = () => {
|
||||
const OnlineActivityAsNumbersTable = ({data}) => {
|
||||
const {t} = useTranslation();
|
||||
if (!data) return <></>;
|
||||
|
||||
return (
|
||||
<AsNumbersTable
|
||||
<ComparisonTable
|
||||
headers={[t('html.label.last30days'), t('html.label.last7days'), t('html.label.last24hours')]}
|
||||
comparisonHeader={t('html.text.comparing15days')}
|
||||
>
|
||||
<TableRow icon={faUsers} color="light-blue" text={t('html.label.uniquePlayers')}
|
||||
values={["TODO"]}/>
|
||||
</AsNumbersTable>
|
||||
values={[
|
||||
<>{data.unique_players_30d}{' '}<SmallTrend trend={data.unique_players_30d_trend}/></>,
|
||||
data.unique_players_7d,
|
||||
data.unique_players_24h
|
||||
]}/>
|
||||
<TableRow icon={faUser} color="light-blue"
|
||||
text={t('html.label.uniquePlayers') + ' ' + t('html.label.perDay')}
|
||||
values={[
|
||||
<>{data.unique_players_30d_avg}{' '}<SmallTrend
|
||||
trend={data.unique_players_30d_avg_trend}/></>,
|
||||
data.unique_players_7d_avg,
|
||||
data.unique_players_24h_avg
|
||||
]}/>
|
||||
<TableRow icon={faUsers} color="light-green" text={t('html.label.newPlayers')}
|
||||
values={[
|
||||
<>{data.new_players_30d}{' '}<SmallTrend trend={data.new_players_30d_trend}/></>,
|
||||
data.new_players_7d,
|
||||
data.new_players_24h
|
||||
]}/>
|
||||
<TableRow icon={faUserPlus} color="light-green"
|
||||
text={t('html.label.newPlayers') + ' ' + t('html.label.perDay')}
|
||||
values={[
|
||||
<>{data.new_players_30d_avg}{' '}<SmallTrend trend={data.new_players_30d_avg_trend}/></>,
|
||||
data.new_players_7d_avg,
|
||||
data.new_players_24h_avg
|
||||
]}/>
|
||||
<TableRow icon={faUserCircle} color="light-green" text={t('html.label.newPlayerRetention')}
|
||||
values={[
|
||||
`(${data.new_players_retention_30d}/${data.new_players_30d}) ${data.new_players_retention_30d_perc}`,
|
||||
`(${data.new_players_retention_7d}/${data.new_players_7d}) ${data.new_players_retention_7d_perc}`,
|
||||
<>{`(${data.new_players_retention_24h}/${data.new_players_24h}) ${data.new_players_retention_24h_perc}`}<Fa
|
||||
icon={faEye} title={t('html.description.newPlayerRetention')}/></>
|
||||
]}/>
|
||||
<TableRow icon={faClock} color="green"
|
||||
text={t('html.label.playtime')}
|
||||
values={[
|
||||
<>{data.playtime_30d}{' '}<SmallTrend trend={data.playtime_30d_trend}/></>,
|
||||
data.playtime_7d,
|
||||
data.playtime_24h
|
||||
]}/>
|
||||
<TableRow icon={faClock} color="green"
|
||||
text={t('html.label.averagePlaytime') + ' ' + t('html.label.perDay')}
|
||||
values={[
|
||||
<>{data.playtime_30d_avg}{' '}<SmallTrend trend={data.playtime_30d_avg_trend}/></>,
|
||||
data.playtime_7d_avg,
|
||||
data.playtime_24h_avg
|
||||
]}/>
|
||||
<TableRow icon={faClock} color="teal"
|
||||
text={t('html.label.averageSessionLength')}
|
||||
values={[
|
||||
<>{data.session_length_30d_avg}{' '}<SmallTrend
|
||||
trend={data.session_length_30d_avg_trend}/></>,
|
||||
data.session_length_7d_avg,
|
||||
data.session_length_24h_avg
|
||||
]}/>
|
||||
<TableRow icon={faCalendarCheck} color="teal"
|
||||
text={t('html.label.sessions')}
|
||||
values={[
|
||||
<>{data.sessions_30d}{' '}<SmallTrend trend={data.sessions_30d_trend}/></>,
|
||||
data.sessions_7d,
|
||||
data.sessions_24h
|
||||
]}/>
|
||||
</ComparisonTable>
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
import {useTranslation} from "react-i18next";
|
||||
import AsNumbersTable, {TableRow} from "./AsNumbersTable";
|
||||
import AsNumbersTable from "./AsNumbersTable";
|
||||
import {faCrosshairs, faSkull} from "@fortawesome/free-solid-svg-icons";
|
||||
import React from "react";
|
||||
import {TableRow} from "./TableRow";
|
||||
|
||||
const PlayerPvpPveAsNumbersTable = ({killData}) => {
|
||||
const {t} = useTranslation();
|
||||
|
@ -1,7 +1,8 @@
|
||||
import {useTranslation} from "react-i18next";
|
||||
import AsNumbersTable, {TableRow} from "./AsNumbersTable";
|
||||
import AsNumbersTable from "./AsNumbersTable";
|
||||
import {faCrosshairs, faSkull} from "@fortawesome/free-solid-svg-icons";
|
||||
import React from "react";
|
||||
import {TableRow} from "./TableRow";
|
||||
|
||||
const ServerPvpPveAsNumbersTable = ({killData}) => {
|
||||
const {t} = useTranslation();
|
||||
|
12
Plan/react/dashboard/src/components/table/TableRow.js
Normal file
12
Plan/react/dashboard/src/components/table/TableRow.js
Normal file
@ -0,0 +1,12 @@
|
||||
import {FontAwesomeIcon as Fa} from "@fortawesome/react-fontawesome";
|
||||
import React from "react";
|
||||
|
||||
export const TableRow = ({icon, text, color, values, bold}) => {
|
||||
const label = (<><Fa icon={icon} className={'col-' + color}/> {text}</>);
|
||||
return (
|
||||
<tr>
|
||||
<td>{bold ? <b>{label}</b> : label}</td>
|
||||
{values.map((value, j) => <td key={j}>{value}</td>)}
|
||||
</tr>
|
||||
)
|
||||
}
|
13
Plan/react/dashboard/src/components/trend/ComparingLabel.js
Normal file
13
Plan/react/dashboard/src/components/trend/ComparingLabel.js
Normal file
@ -0,0 +1,13 @@
|
||||
import {FontAwesomeIcon as Fa} from "@fortawesome/react-fontawesome";
|
||||
import {faCaretDown, faCaretUp} from "@fortawesome/free-solid-svg-icons";
|
||||
import React from "react";
|
||||
|
||||
const ComparingLabel = ({children}) => {
|
||||
return (<>
|
||||
<Fa icon={faCaretUp} className="comparing text-success"/>
|
||||
<Fa icon={faCaretDown} className="comparing text-danger"/>
|
||||
{' '}<small>{children}</small>
|
||||
</>);
|
||||
}
|
||||
|
||||
export default ComparingLabel;
|
@ -2,11 +2,11 @@ import React from "react";
|
||||
import {FontAwesomeIcon as Fa} from "@fortawesome/react-fontawesome";
|
||||
import {faCaretDown, faCaretRight, faCaretUp} from "@fortawesome/free-solid-svg-icons";
|
||||
|
||||
const TrendUpGood = ({value}) => <Fa icon={faCaretUp} className="text-success" title={value}/>;
|
||||
const TrendUpBad = ({value}) => <Fa icon={faCaretUp} className="text-danger" title={value}/>;
|
||||
const TrendDownBad = ({value}) => <Fa icon={faCaretDown} className="text-danger" title={value}/>;
|
||||
const TrendDownGood = ({value}) => <Fa icon={faCaretDown} className="text-success" title={value}/>;
|
||||
const TrendSame = ({value}) => <Fa icon={faCaretRight} className="text-warning" title={value}/>;
|
||||
const TrendUpGood = ({value}) => <Fa icon={faCaretUp} className="trend text-success" title={value}/>;
|
||||
const TrendUpBad = ({value}) => <Fa icon={faCaretUp} className="trend text-danger" title={value}/>;
|
||||
const TrendDownBad = ({value}) => <Fa icon={faCaretDown} className="trend text-danger" title={value}/>;
|
||||
const TrendDownGood = ({value}) => <Fa icon={faCaretDown} className="trend text-success" title={value}/>;
|
||||
const TrendSame = ({value}) => <Fa icon={faCaretRight} className="trend text-warning" title={value}/>;
|
||||
|
||||
|
||||
const SmallTrend = ({trend}) => {
|
||||
|
@ -4,8 +4,9 @@
|
||||
|
||||
p, span, td, .h3, a, button
|
||||
.svg-inline--fa, .fa, .far, .fas, .fab
|
||||
text-align: center !important
|
||||
width: 1.25em !important
|
||||
&:not(.comparing):not(.trend)
|
||||
text-align: center !important
|
||||
width: 1.25em !important
|
||||
|
||||
.card
|
||||
@extend .shadow
|
||||
|
@ -21,12 +21,13 @@ import {faSuperpowers} from "@fortawesome/free-brands-svg-icons";
|
||||
import Scrollable from "../../components/Scrollable";
|
||||
import PunchCard from "../../components/graphs/PunchCard";
|
||||
import Datapoint from "../../components/Datapoint";
|
||||
import AsNumbersTable, {TableRow} from "../../components/table/AsNumbersTable";
|
||||
import AsNumbersTable from "../../components/table/AsNumbersTable";
|
||||
import {useTheme} from "../../hooks/themeHook";
|
||||
import {usePlayer} from "../layout/PlayerPage";
|
||||
import {useMetadata} from "../../hooks/metadataHook";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import NicknamesCard from "../../components/cards/player/NicknamesCard";
|
||||
import {TableRow} from "../../components/table/TableRow";
|
||||
|
||||
const PlayerOverviewCard = ({player}) => {
|
||||
const {t} = useTranslation();
|
||||
|
@ -25,10 +25,10 @@ const OnlineActivity = () => {
|
||||
</Row>
|
||||
<Row>
|
||||
<Col lg={8}>
|
||||
<OnlineActivityAsNumbersCard data={data}/>
|
||||
<OnlineActivityAsNumbersCard data={data?.numbers}/>
|
||||
</Col>
|
||||
<Col lg={4}>
|
||||
<OnlineActivityInsightsCard data={data}/>
|
||||
<OnlineActivityInsightsCard data={data?.insights}/>
|
||||
</Col>
|
||||
</Row>
|
||||
</section>
|
||||
|
Loading…
Reference in New Issue
Block a user