META-INF.resources.js.components.TrafficSources.js Maven / Gradle / Ivy
/**
* SPDX-FileCopyrightText: (c) 2000 Liferay, Inc. https://liferay.com
* SPDX-License-Identifier: LGPL-2.1-or-later OR LicenseRef-Liferay-DXP-EULA-2.0.0-2023-06
*/
import ClayButton from '@clayui/button';
import ClayLoadingIndicator from '@clayui/loading-indicator';
import {useIsMounted, useStateSafe} from '@liferay/frontend-js-react-web';
import className from 'classnames';
import PropTypes from 'prop-types';
import React, {useContext, useEffect, useMemo, useState} from 'react';
import {Cell, Pie, PieChart, Tooltip} from 'recharts';
import {
ChartDispatchContext,
ChartStateContext,
} from '../context/ChartStateContext';
import ConnectionContext from '../context/ConnectionContext';
import {StoreDispatchContext, StoreStateContext} from '../context/StoreContext';
import {numberFormat} from '../utils/numberFormat';
import EmptyPieChart from './EmptyPieChart';
import Hint from './Hint';
const COLORS_MAP = {
direct: '#FF73C3',
organic: '#4B9FFF',
paid: '#FFB46E',
referral: '#FF5F5F',
social: '#50D2A0',
};
const PIE_CHART_SIZES = {
height: 140,
innerRadius: 40,
outerRadius: 70,
paddingAngle: 1,
width: 140,
};
/**
* Used when the traffic source name is not within the COLORS_MAP
*/
const FALLBACK_COLOR = '#e92563';
const getColorByName = (name) => COLORS_MAP[name] || FALLBACK_COLOR;
export default function TrafficSources({dataProvider, onTrafficSourceClick}) {
const [highlighted, setHighlighted] = useState(null);
const isMounted = useIsMounted();
const {validAnalyticsConnection} = useContext(ConnectionContext);
const dispatch = useContext(StoreDispatchContext);
const chartDispatch = useContext(ChartDispatchContext);
const {languageTag, publishedToday} = useContext(StoreStateContext);
const {pieChartLoading, timeSpanKey, timeSpanOffset} =
useContext(ChartStateContext);
const [trafficSources, setTrafficSources] = useStateSafe([]);
const pieChartWrapperClasses = className('pie-chart-wrapper', {
'pie-chart-wrapper--loading': pieChartLoading,
});
useEffect(() => {
if (validAnalyticsConnection) {
chartDispatch({
payload: {
loading: true,
},
type: 'SET_PIE_CHART_LOADING',
});
dataProvider()
.then((trafficSources) => {
if (isMounted()) {
setTrafficSources(trafficSources);
}
})
.catch(() => {
if (isMounted()) {
setTrafficSources([]);
dispatch({type: 'ADD_WARNING'});
}
})
.finally(() => {
if (isMounted()) {
chartDispatch({
payload: {
loading: false,
},
type: 'SET_PIE_CHART_LOADING',
});
}
});
}
}, [
chartDispatch,
dispatch,
dataProvider,
setTrafficSources,
timeSpanKey,
timeSpanOffset,
validAnalyticsConnection,
isMounted,
]);
const fullPieChart = useMemo(
() =>
validAnalyticsConnection &&
!publishedToday &&
trafficSources?.some(({value}) => value),
[publishedToday, trafficSources, validAnalyticsConnection]
);
const missingTrafficSourceValue = useMemo(
() => trafficSources?.some(({value}) => value === undefined),
[trafficSources]
);
useEffect(() => {
if (missingTrafficSourceValue) {
dispatch({type: 'ADD_WARNING'});
}
}, [dispatch, missingTrafficSourceValue]);
function handleLegendMouseEnter(name) {
setHighlighted(name);
}
function handleLegendMouseLeave() {
setHighlighted(null);
}
return (
<>
{Liferay.Language.get('traffic-channels')}
{!fullPieChart && !missingTrafficSourceValue && (
{Liferay.Language.get(
'your-page-has-no-incoming-traffic-from-traffic-channels-yet'
)}
)}
{pieChartLoading && (
)}
{trafficSources?.map((entry) => {
const hasDetails =
entry?.value > 0 && entry?.endpointURL;
return (
handleLegendMouseEnter(
entry.name
)
}
>
handleLegendMouseEnter(
entry.name
)
}
>
{validAnalyticsConnection &&
!publishedToday &&
hasDetails ? (
onTrafficSourceClick(
trafficSources,
entry.name,
false
)
}
small
>
{entry.title}
) : (
{entry.title}
)}
{validAnalyticsConnection &&
!publishedToday &&
entry.value !== undefined
? numberFormat(
languageTag,
entry.value,
{
useCompact: true,
}
)
: '-'}
);
})}
{!fullPieChart && (
)}
{fullPieChart && (
{trafficSources.map((entry, i) => {
const fillColor = getColorByName(
entry.name
);
const cellClasses = className({
dim:
highlighted &&
entry.name !== highlighted,
});
return (
handleLegendMouseEnter(
entry.name
)
}
/>
);
})}
|
}
formatter={(value, name, iconType) => {
return [
numberFormat(languageTag, value),
name,
iconType,
];
}}
separator=": "
/>
)}
>
);
}
function TrafficSourcesCustomTooltip(props) {
const {formatter, payload, separator = ''} = props;
return (
{
// eslint-disable-next-line @liferay/no-length-jsx-expression
payload.length && payload[0].payload.title
}
<>
{payload.map((item) => {
// eslint-disable-next-line no-unused-vars
const [value, _name, iconType] = formatter
? formatter(item.value, item.name, item.iconType)
: [item.value, item.name, item.iconType];
const {payload} = item;
return (
-
{Liferay.Language.get('visitors')}
{separator}
{value}
-
{Liferay.Language.get('traffic-share')}
{separator}
{`${payload.share}%`}
);
})}
>
);
}
TrafficSources.propTypes = {
dataProvider: PropTypes.func.isRequired,
onTrafficSourceClick: PropTypes.func.isRequired,
};