import { ResponsiveLine } from '@nivo/line'; import { Box, Flex, Skeleton, Tile, ActionButton } from '@rocket.chat/fuselage'; import moment from 'moment'; import React, { useMemo } from 'react'; import { useTranslation } from '../../../../../../client/contexts/TranslationContext'; import { useEndpointData } from '../../../../../../client/hooks/useEndpointData'; import { useFormatDate } from '../../../../../../client/hooks/useFormatDate'; import CounterSet from '../../../../../../client/components/data/CounterSet'; import { LegendSymbol } from '../data/LegendSymbol'; import { Section } from '../Section'; import { downloadCsvAs } from '../../../../../../client/lib/download'; const ActiveUsersSection = ({ timezone }) => { const t = useTranslation(); const utc = timezone === 'utc'; const formatDate = useFormatDate(); const period = useMemo(() => ({ start: utc ? moment.utc().subtract(30, 'days') : moment().subtract(30, 'days'), end: utc ? moment.utc().subtract(1, 'days') : moment().subtract(1, 'days'), }), [utc]); const params = useMemo(() => ({ start: period.start.clone().subtract(29, 'days').toISOString(), end: period.end.toISOString(), }), [period]); const { value: data } = useEndpointData('engagement-dashboard/users/active-users', useMemo(() => params, [params])); const [ countDailyActiveUsers, diffDailyActiveUsers, countWeeklyActiveUsers, diffWeeklyActiveUsers, countMonthlyActiveUsers, diffMonthlyActiveUsers, dauValues, wauValues, mauValues, ] = useMemo(() => { if (!data) { return []; } const createPoint = (i) => ({ x: moment(period.start).add(i, 'days').toDate(), y: 0, }); const createPoints = () => Array.from({ length: moment(period.end).diff(period.start, 'days') + 1 }, (_, i) => createPoint(i)); const dauValues = createPoints(); const prevDauValue = createPoint(-1); const wauValues = createPoints(); const prevWauValue = createPoint(-1); const mauValues = createPoints(); const prevMauValue = createPoint(-1); const usersListsMap = data.month.reduce((map, dayData) => { const date = utc ? moment.utc({ year: dayData.year, month: dayData.month - 1, day: dayData.day }).endOf('day') : moment({ year: dayData.year, month: dayData.month - 1, day: dayData.day }).endOf('day'); const dateOffset = date.diff(period.start, 'days'); if (dateOffset >= 0) { map[dateOffset] = dayData.usersList; dauValues[dateOffset].y = dayData.users; } return map; }, {}); const distributeValueOverPoints = (usersListsMap, dateOffset, T, array) => { const usersSet = new Set(); for (let k = dateOffset; T > 0; k--, T--) { if (usersListsMap[k]) { usersListsMap[k].forEach((userId) => usersSet.add(userId)); } } array[dateOffset].y = usersSet.size; }; for (let i = 0; i < 30; i++) { distributeValueOverPoints(usersListsMap, i, 7, wauValues); distributeValueOverPoints(usersListsMap, i, 30, mauValues); } prevWauValue.y = wauValues[28].y; prevMauValue.y = mauValues[28].y; prevDauValue.y = dauValues[28].y; return [ dauValues[dauValues.length - 1].y, dauValues[dauValues.length - 1].y - prevDauValue.y, wauValues[wauValues.length - 1].y, wauValues[wauValues.length - 1].y - prevWauValue.y, mauValues[mauValues.length - 1].y, mauValues[mauValues.length - 1].y - prevMauValue.y, dauValues, wauValues, mauValues, ]; }, [data, period.end, period.start, utc]); const downloadData = () => { const data = [{ countDailyActiveUsers, diffDailyActiveUsers, countWeeklyActiveUsers, diffWeeklyActiveUsers, countMonthlyActiveUsers, diffMonthlyActiveUsers, dauValues, wauValues, mauValues, }]; downloadCsvAs(data, `ActiveUsersSection_start_${ params.start }_end_${ params.end }`); }; return
}> , variation: data ? diffDailyActiveUsers : 0, description: <> {t('Daily_Active_Users')}, }, { count: data ? countWeeklyActiveUsers : , variation: data ? diffWeeklyActiveUsers : 0, description: <> {t('Weekly_Active_Users')}, }, { count: data ? countMonthlyActiveUsers : , variation: data ? diffMonthlyActiveUsers : 0, description: <> {t('Monthly_Active_Users')}, }, ]} /> {data ? moment(date).format(dauValues.length === 7 ? 'dddd' : 'L'), }} animate={true} motionStiffness={90} motionDamping={15} theme={{ // TODO: Get it from theme axis: { ticks: { text: { fill: '#9EA2A8', fontFamily: 'Inter, -apple-system, system-ui, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Helvetica Neue", "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Meiryo UI", Arial, sans-serif', fontSize: '10px', fontStyle: 'normal', fontWeight: '600', letterSpacing: '0.2px', lineHeight: '12px', }, }, }, tooltip: { container: { backgroundColor: '#1F2329', boxShadow: '0px 0px 12px rgba(47, 52, 61, 0.12), 0px 0px 2px rgba(47, 52, 61, 0.08)', borderRadius: 2, }, }, }} enableSlices='x' sliceTooltip={({ slice: { points } }) => {formatDate(points[0].data.x)} {points.map(({ serieId, data: { y: activeUsers } }) => {(serieId === 'dau' && t('DAU_value', { value: activeUsers })) || (serieId === 'wau' && t('WAU_value', { value: activeUsers })) || (serieId === 'mau' && t('MAU_value', { value: activeUsers }))} )} } /> : }
; }; export default ActiveUsersSection;