Entered data for Online Activity Overview

This commit is contained in:
Aurora Lahtela 2022-05-23 19:46:01 +03:00
parent 7e1bd7f4a6
commit f6ece8333b
20 changed files with 168 additions and 61 deletions

View File

@ -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"),

View File

@ -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;

View File

@ -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;

View File

@ -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>
)
}

View File

@ -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>
)
}

View File

@ -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>
)
}

View File

@ -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();

View File

@ -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();

View File

@ -0,0 +1,7 @@
import React from "react";
const End = ({children}) => (
<span className="float-end">{children}</span>
)
export default End;

View File

@ -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

View File

@ -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

View File

@ -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>
)
}

View File

@ -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();

View File

@ -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();

View 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>
)
}

View 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;

View File

@ -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}) => {

View File

@ -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

View File

@ -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();

View File

@ -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>