Skip to content

Commit d383bee

Browse files
kangzjdognose24
andauthored
Stats: Add line chart for real-time stats prototype (#99141)
* add in line chart with fixture data * async load line chart * staging changes * fix styling * update charts to 0.7.1 * charts lib 0.8.0 * update charts to 0.8.1 * use jetpackTheme * refresh every minute * adjusted margins * resolution for @types/react-dom to fix conflict * yarn dedup --------- Co-authored-by: Dognose <[email protected]>
1 parent eaf3691 commit d383bee

File tree

5 files changed

+814
-55
lines changed

5 files changed

+814
-55
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import { LineChart, ThemeProvider, jetpackTheme } from '@automattic/charts';
2+
import { useTranslate } from 'i18n-calypso';
3+
import { Moment } from 'moment';
4+
import { useEffect, useState } from 'react';
5+
import { withLocalizedMoment } from 'calypso/components/localized-moment';
6+
import StatsEmptyState from '../../stats-empty-state';
7+
8+
const fixtureData = [
9+
{
10+
label: 'Views',
11+
options: {
12+
stroke: '#069e08',
13+
},
14+
data: [] as Array< { date: Date; value: number } >,
15+
},
16+
];
17+
18+
function StatsLineChart( {
19+
chartData = null,
20+
height = 400,
21+
moment,
22+
EmptyState = StatsEmptyState,
23+
}: {
24+
chartData: Array< {
25+
label: string;
26+
options: object;
27+
data: Array< { date: Date; value: number } >;
28+
} > | null;
29+
height?: number;
30+
moment: Moment;
31+
EmptyState: typeof StatsEmptyState;
32+
} ) {
33+
const [ data, setData ] = useState( () => chartData || fixtureData );
34+
const formatTime = ( value: number ) => {
35+
const date = new Date( value );
36+
return new Date( date ).toLocaleTimeString( moment.locale(), {
37+
hour: '2-digit',
38+
minute: '2-digit',
39+
hour12: true,
40+
} );
41+
};
42+
const translate = useTranslate();
43+
44+
useEffect( () => {
45+
const intervalId = setInterval( () => {
46+
if ( fixtureData[ 0 ].data.length > 30 ) {
47+
fixtureData[ 0 ].data.pop();
48+
}
49+
50+
const date = new Date();
51+
fixtureData[ 0 ].data.unshift( { date, value: Math.round( Math.random() * 60 ) } );
52+
setData( [ ...fixtureData ] );
53+
}, 60 * 1000 );
54+
return () => clearInterval( intervalId );
55+
}, [] );
56+
57+
return (
58+
<div className="stats-line-chart">
59+
{ data?.[ 0 ]?.data?.length === 0 && (
60+
<EmptyState
61+
headingText={ translate( 'Real-time views' ) }
62+
infoText={ translate( 'Collecting data… auto-refreshing in a minute…' ) }
63+
/>
64+
) }
65+
<ThemeProvider theme={ jetpackTheme }>
66+
<LineChart
67+
data={ data }
68+
withTooltips
69+
withGradientFill
70+
height={ height }
71+
/** naturalCurve sometime goes off the grid :( */
72+
margin={ { left: 15, top: 20, bottom: 20 } }
73+
options={ { axis: { x: { tickFormat: formatTime }, y: { orientation: 'right' } } } }
74+
/>
75+
</ThemeProvider>
76+
</div>
77+
);
78+
}
79+
80+
export default withLocalizedMoment( StatsLineChart );

client/my-sites/stats/pages/realtime/index.jsx

+9-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { useTranslate } from 'i18n-calypso';
33
import { useSelector } from 'react-redux';
44
import StatsNavigation from 'calypso/blocks/stats-navigation';
55
import { navItems } from 'calypso/blocks/stats-navigation/constants';
6+
import AsyncLoad from 'calypso/components/async-load';
67
import DocumentHead from 'calypso/components/data/document-head';
78
import JetpackColophon from 'calypso/components/jetpack-colophon';
89
import Main from 'calypso/components/main';
@@ -12,8 +13,11 @@ import { getSelectedSiteId, getSelectedSiteSlug } from 'calypso/state/ui/selecto
1213
import AnnualHighlightsSection from '../../sections/annual-highlights-section';
1314
import PageViewTracker from '../../stats-page-view-tracker';
1415
import statsStrings from '../../stats-strings';
16+
import PageLoading from '../shared/page-loading';
1517
import StatsModuleListing from '../shared/stats-module-listing';
1618

19+
import './style.scss';
20+
1721
function StatsRealtime() {
1822
const siteId = useSelector( ( state ) => getSelectedSiteId( state ) );
1923
const siteSlug = useSelector( ( state ) => getSelectedSiteSlug( state, siteId ) );
@@ -53,7 +57,11 @@ function StatsRealtime() {
5357
></NavigationHeader>
5458
<StatsNavigation selectedItem="realtime" siteId={ siteId } slug={ siteSlug } />
5559
<AnnualHighlightsSection siteId={ siteId } />
56-
60+
<AsyncLoad
61+
require="calypso/my-sites/stats/components/line-chart"
62+
height={ 425 }
63+
placeholder={ PageLoading }
64+
/>
5765
<StatsModuleListing className="stats__module-list--insights" siteId={ siteId }>
5866
<StatsModuleTopPosts
5967
moduleStrings={ moduleStrings.posts }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
.stats-line-chart {
2+
position: relative;
3+
margin: 32px 0;
4+
5+
.line-chart {
6+
background-color: var(--studio-white);
7+
border: 1px solid var(--studio-gray-5);
8+
border-radius: 4px;
9+
}
10+
11+
.stats__empty-state {
12+
max-width: 75%;
13+
position: absolute;
14+
top: 30%;
15+
left: 50%;
16+
transform: translate(-50%, 0);
17+
}
18+
}

package.json

+2
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@
149149
"@automattic/calypso-products": "workspace:^",
150150
"@automattic/calypso-razorpay": "workspace:^",
151151
"@automattic/calypso-router": "workspace:^",
152+
"@automattic/charts": "^0.8.1",
152153
"@automattic/color-studio": "^3.0.1",
153154
"@automattic/command-palette": "workspace:^",
154155
"@automattic/components": "workspace:^",
@@ -323,6 +324,7 @@
323324
},
324325
"resolutions": {
325326
"@types/react": "^18.2.6",
327+
"@types/react-dom": "^18.2.6",
326328
"@types/wordpress__block-editor": "npm:[email protected]",
327329
"@types/wordpress__editor": "npm:[email protected]",
328330
"keytar@npm:7.7.0/node-addon-api": "3.1.0",

0 commit comments

Comments
 (0)