Use the join address selection in Player Retention
This commit is contained in:
parent
69a3dd96f2
commit
1af5f470ec
|
@ -0,0 +1,29 @@
|
|||
import LoadIn from "../../animation/LoadIn.jsx";
|
||||
import ExtendableRow from "../../layout/extension/ExtendableRow.jsx";
|
||||
import {Col} from "react-bootstrap";
|
||||
import PlayerRetentionGraphCard from "./PlayerRetentionGraphCard.jsx";
|
||||
import React, {useState} from "react";
|
||||
import {JoinAddressListContextProvider} from "../../../hooks/context/joinAddressListContextHook.jsx";
|
||||
import AddressGroupSelectorRow from "./AddressGroupSelectorRow.jsx";
|
||||
|
||||
const PlayerRetention = ({id, seeRetention, identifier}) => {
|
||||
const [selectedGroupBy, setSelectedGroupBy] = useState('none');
|
||||
return (
|
||||
<LoadIn>
|
||||
{seeRetention && <section className={id}>
|
||||
<JoinAddressListContextProvider identifier={identifier} loadIndividualAddresses>
|
||||
<ExtendableRow id={`row-${id}-0`}>
|
||||
<Col lg={12}>
|
||||
<PlayerRetentionGraphCard identifier={identifier}
|
||||
selectedGroupBy={selectedGroupBy}
|
||||
setSelectedGroupBy={setSelectedGroupBy}/>
|
||||
</Col>
|
||||
</ExtendableRow>
|
||||
{selectedGroupBy === 'joinAddress' && <AddressGroupSelectorRow/>}
|
||||
</JoinAddressListContextProvider>
|
||||
</section>}
|
||||
</LoadIn>
|
||||
)
|
||||
};
|
||||
|
||||
export default PlayerRetention
|
|
@ -17,6 +17,7 @@ import {useTheme} from "../../../hooks/themeHook";
|
|||
import {useNavigation} from "../../../hooks/navigationHook";
|
||||
import {FontAwesomeIcon as Fa} from "@fortawesome/react-fontawesome";
|
||||
import {faQuestionCircle} from "@fortawesome/free-regular-svg-icons";
|
||||
import {useJoinAddressListContext} from "../../../hooks/context/joinAddressListContextHook.jsx";
|
||||
|
||||
const dayMs = 24 * 3600000;
|
||||
const getWeek = (date) => {
|
||||
|
@ -26,7 +27,7 @@ const getWeek = (date) => {
|
|||
return Math.ceil(dayOfYear / 7)
|
||||
};
|
||||
|
||||
const PlayerRetentionGraphCard = ({identifier}) => {
|
||||
const PlayerRetentionGraphCard = ({identifier, selectedGroupBy, setSelectedGroupBy}) => {
|
||||
const {t} = useTranslation();
|
||||
const {nightModeEnabled} = useTheme();
|
||||
const {setHelpModalTopic} = useNavigation();
|
||||
|
@ -40,6 +41,8 @@ const PlayerRetentionGraphCard = ({identifier}) => {
|
|||
loadingError: joinAddressLoadingError
|
||||
} = useDataRequest(fetchPlayerJoinAddresses, [identifier]);
|
||||
|
||||
const {list, playerAddresses} = useJoinAddressListContext();
|
||||
|
||||
const [selectedWindow, setSelectedWindow] = useState('days');
|
||||
const windowOptions = useMemo(() => [
|
||||
{name: 'hours', displayName: t('html.label.time.hours'), increment: 3600000},
|
||||
|
@ -57,7 +60,7 @@ const PlayerRetentionGraphCard = ({identifier}) => {
|
|||
{name: 'registered-2y', displayName: t('html.label.retention.inLast730d'), start: time - 2 * 365 * dayMs},
|
||||
{name: 'registered-ever', displayName: t('html.label.retention.inAnytime'), start: 0},
|
||||
], [t, time]);
|
||||
const [selectedGroupBy, setSelectedGroupBy] = useState('none');
|
||||
// State moved to higher level for join address group selection
|
||||
const groupByOptions = useMemo(() => [
|
||||
{name: 'none', displayName: t('html.label.retention.groupByNone')},
|
||||
{name: 'days', displayName: t('html.label.time.day')},
|
||||
|
@ -165,8 +168,12 @@ const PlayerRetentionGraphCard = ({identifier}) => {
|
|||
break;
|
||||
case 'joinAddress':
|
||||
const joinAddress = joinAddressData[point.playerUUID];
|
||||
if (!grouped[joinAddress]) grouped[joinAddress] = [];
|
||||
grouped[joinAddress].push(point);
|
||||
const joinAddressGroups = list.filter(g => g.addresses.includes(joinAddress)).map(g => g.name);
|
||||
for (const joinAddressGroup of joinAddressGroups) {
|
||||
if (!grouped[joinAddressGroup]) grouped[joinAddressGroup] = [];
|
||||
grouped[joinAddressGroup].push(point);
|
||||
}
|
||||
|
||||
break;
|
||||
case 'none':
|
||||
default:
|
||||
|
@ -175,7 +182,7 @@ const PlayerRetentionGraphCard = ({identifier}) => {
|
|||
}
|
||||
}
|
||||
return grouped;
|
||||
}, [groupByOptions, selectedGroupBy]);
|
||||
}, [groupByOptions, selectedGroupBy, list]);
|
||||
|
||||
const createSeries = useCallback(async (retentionData, joinAddressData) => {
|
||||
|
||||
|
@ -207,10 +214,10 @@ const PlayerRetentionGraphCard = ({identifier}) => {
|
|||
}, [nightModeEnabled, mapToData, groupOptions, selectedGroup, selectedYAxis, group]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!data || !joinAddressData) return;
|
||||
if (!data || !playerAddresses) return;
|
||||
|
||||
createSeries(data.player_retention, joinAddressData.joinAddressByPlayer).then(series => setSeries(series.flat()));
|
||||
}, [data, joinAddressData, createSeries, setSeries]);
|
||||
createSeries(data.player_retention, playerAddresses).then(series => setSeries(series.flat()));
|
||||
}, [data, playerAddresses, createSeries, setSeries]);
|
||||
|
||||
useEffect(() => {
|
||||
const windowName = windowOptions.find(option => option.name === selectedWindow).displayName;
|
||||
|
|
|
@ -7,7 +7,7 @@ import {useTranslation} from "react-i18next";
|
|||
|
||||
const JoinAddressListContext = createContext({});
|
||||
|
||||
export const JoinAddressListContextProvider = ({identifier, children}) => {
|
||||
export const JoinAddressListContextProvider = ({identifier, children, loadIndividualAddresses}) => {
|
||||
const {t} = useTranslation();
|
||||
const {updateRequested} = useNavigation();
|
||||
const {preferencesLoaded, getKeyedPreference, setSomePreferences} = usePreferences();
|
||||
|
@ -46,17 +46,19 @@ export const JoinAddressListContextProvider = ({identifier, children}) => {
|
|||
}, [updateList, list]);
|
||||
|
||||
const [allAddresses, setAllAddresses] = useState([]);
|
||||
const [playerAddresses, setPlayerAddresses] = useState([]);
|
||||
const loadAddresses = useCallback(async () => {
|
||||
const {data, error} = await fetchPlayerJoinAddresses(updateRequested, identifier, true);
|
||||
const {data, error} = await fetchPlayerJoinAddresses(updateRequested, identifier, !loadIndividualAddresses);
|
||||
setAllAddresses(data?.joinAddresses || [error]);
|
||||
setPlayerAddresses(data?.joinAddressByPlayer || {});
|
||||
}, [setAllAddresses, identifier, updateRequested]);
|
||||
useEffect(() => {
|
||||
loadAddresses();
|
||||
}, [loadAddresses]);
|
||||
|
||||
const sharedState = useMemo(() => {
|
||||
return {list, add, remove, replace, allAddresses};
|
||||
}, [list, add, remove, replace, allAddresses]);
|
||||
return {list, add, remove, replace, allAddresses, playerAddresses};
|
||||
}, [list, add, remove, replace, allAddresses, playerAddresses]);
|
||||
return (<JoinAddressListContext.Provider value={sharedState}>
|
||||
{children}
|
||||
</JoinAddressListContext.Provider>
|
||||
|
|
|
@ -1,24 +1,12 @@
|
|||
import React from 'react';
|
||||
import ExtendableRow from "../../components/layout/extension/ExtendableRow";
|
||||
import {Col} from "react-bootstrap";
|
||||
import LoadIn from "../../components/animation/LoadIn";
|
||||
import PlayerRetentionGraphCard from "../../components/cards/common/PlayerRetentionGraphCard";
|
||||
import {useAuth} from "../../hooks/authenticationHook";
|
||||
import PlayerRetention from "../../components/cards/common/PlayerRetention.jsx";
|
||||
|
||||
const NetworkPlayerRetention = () => {
|
||||
const {hasPermission} = useAuth();
|
||||
|
||||
const seeRetention = hasPermission('page.network.retention');
|
||||
return (
|
||||
<LoadIn>
|
||||
{seeRetention && <section className="network-retention">
|
||||
<ExtendableRow id={'row-network-retention-0'}>
|
||||
<Col lg={12}>
|
||||
<PlayerRetentionGraphCard identifier={null}/>
|
||||
</Col>
|
||||
</ExtendableRow>
|
||||
</section>}
|
||||
</LoadIn>
|
||||
<PlayerRetention id={"network-retention"} identifier={null} seeRetention={seeRetention}/>
|
||||
)
|
||||
};
|
||||
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
import React from 'react';
|
||||
import ExtendableRow from "../../components/layout/extension/ExtendableRow";
|
||||
import {Col} from "react-bootstrap";
|
||||
import LoadIn from "../../components/animation/LoadIn";
|
||||
import PlayerRetentionGraphCard from "../../components/cards/common/PlayerRetentionGraphCard";
|
||||
import {useParams} from "react-router-dom";
|
||||
import {useAuth} from "../../hooks/authenticationHook";
|
||||
import PlayerRetention from "../../components/cards/common/PlayerRetention.jsx";
|
||||
|
||||
const ServerPlayerRetention = () => {
|
||||
const {hasPermission} = useAuth();
|
||||
|
@ -12,15 +9,7 @@ const ServerPlayerRetention = () => {
|
|||
|
||||
const seeRetention = hasPermission('page.server.retention');
|
||||
return (
|
||||
<LoadIn>
|
||||
<section className="server-retention">
|
||||
{seeRetention && <ExtendableRow id={'row-server-retention-0'}>
|
||||
<Col lg={12}>
|
||||
<PlayerRetentionGraphCard identifier={identifier}/>
|
||||
</Col>
|
||||
</ExtendableRow>}
|
||||
</section>
|
||||
</LoadIn>
|
||||
<PlayerRetention id={"server-retention"} identifier={identifier} seeRetention={seeRetention}/>
|
||||
)
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue