MySQL query optimization. Added loading component.

This commit is contained in:
Mike Cao 2020-08-27 23:45:37 -07:00
parent a7e7469d22
commit ccb98f836f
13 changed files with 158 additions and 109 deletions

View file

@ -0,0 +1,13 @@
import React from 'react';
import classNames from 'classnames';
import styles from './Loading.module.css';
export default function Loading({ className }) {
return (
<div className={classNames(styles.loading, className)}>
<div />
<div />
<div />
</div>
);
}

View file

@ -0,0 +1,41 @@
@keyframes blink {
0% {
opacity: 0.2;
}
20% {
opacity: 1;
}
100% {
opacity: 0.2;
}
}
.loading {
display: flex;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
margin: 0;
}
.loading div {
width: 10px;
height: 10px;
border-radius: 100%;
background: var(--gray400);
animation: blink 1.4s infinite;
animation-fill-mode: both;
}
.loading div + div {
margin-left: 10px;
}
.loading div:nth-child(2) {
animation-delay: 0.2s;
}
.loading div:nth-child(3) {
animation-delay: 0.4s;
}

View file

@ -10,6 +10,7 @@
}
.container .content {
position: relative;
border-left: 1px solid var(--gray300);
padding-left: 30px;
}

View file

@ -120,6 +120,7 @@ export default function BarChart({
options.scales.xAxes[0].time.unit = unit;
options.scales.xAxes[0].ticks.callback = renderLabel;
options.animation.duration = animationDuration;
onUpdate(chart.current);
};
@ -133,7 +134,7 @@ export default function BarChart({
updateChart();
}
}
}, [datasets]);
}, [datasets, unit, animationDuration]);
return (
<>

View file

@ -42,7 +42,7 @@ export default function EventsChart({ websiteId, startDate, endDate, unit }) {
unit,
tz: getTimezone(),
});
console.log({ data });
const map = data.reduce((obj, { x, t, y }) => {
if (!obj[x]) {
obj[x] = [];

View file

@ -8,6 +8,7 @@ import { get } from 'lib/web';
import { percentFilter } from 'lib/filters';
import { formatNumber, formatLongNumber } from 'lib/format';
import styles from './MetricsTable.module.css';
import Loading from '../common/Loading';
export default function MetricsTable({
title,
@ -79,35 +80,37 @@ export default function MetricsTable({
}
}, [websiteId, startDate, endDate, type]);
if (!data) {
return null;
}
return (
<div className={classNames(styles.container, className)}>
<div className={styles.header}>
<div className={styles.title}>{title}</div>
{headerComponent}
<div className={styles.metric} onClick={handleSetFormat}>
{metric}
</div>
</div>
<div className={styles.body}>
{limit
? rankings.map(row => getRow(row))
: data?.length > 0 && (
<FixedSizeList height={500} itemCount={rankings.length} itemSize={30}>
{Row}
</FixedSizeList>
{data ? (
<>
<div className={styles.header}>
<div className={styles.title}>{title}</div>
{headerComponent}
<div className={styles.metric} onClick={handleSetFormat}>
{metric}
</div>
</div>
<div className={styles.body}>
{limit
? rankings.map(row => getRow(row))
: data?.length > 0 && (
<FixedSizeList height={500} itemCount={rankings.length} itemSize={30}>
{Row}
</FixedSizeList>
)}
</div>
<div className={styles.footer}>
{limit && data.length > limit && (
<Button icon={<Arrow />} size="xsmall" onClick={() => onExpand(type)}>
<div>More</div>
</Button>
)}
</div>
<div className={styles.footer}>
{limit && data.length > limit && (
<Button icon={<Arrow />} size="xsmall" onClick={() => onExpand(type)}>
<div>More</div>
</Button>
)}
</div>
</div>
</>
) : (
<Loading />
)}
</div>
);
}

View file

@ -1,16 +1,15 @@
import React from 'react';
import CheckVisible from 'components/helpers/CheckVisible';
import BarChart from './BarChart';
export default function PageviewsChart({ websiteId, data, unit, className, animationDuration }) {
export default function PageviewsChart({ websiteId, data, unit, className }) {
const handleUpdate = chart => {
const {
data: { datasets },
options,
} = chart;
datasets[0].data = data.uniques;
datasets[1].data = data.pageviews;
options.animation.duration = animationDuration;
chart.update();
};
@ -20,30 +19,35 @@ export default function PageviewsChart({ websiteId, data, unit, className, anima
}
return (
<BarChart
className={className}
chartId={websiteId}
datasets={[
{
label: 'unique visitors',
data: data.uniques,
lineTension: 0,
backgroundColor: 'rgb(38, 128, 235, 0.4)',
borderColor: 'rgb(13, 102, 208, 0.4)',
borderWidth: 1,
},
{
label: 'page views',
data: data.pageviews,
lineTension: 0,
backgroundColor: 'rgb(38, 128, 235, 0.2)',
borderColor: 'rgb(13, 102, 208, 0.2)',
borderWidth: 1,
},
]}
unit={unit}
records={data.pageviews.length}
onUpdate={handleUpdate}
/>
<CheckVisible>
{visible => (
<BarChart
className={className}
chartId={websiteId}
datasets={[
{
label: 'unique visitors',
data: data.uniques,
lineTension: 0,
backgroundColor: 'rgb(38, 128, 235, 0.4)',
borderColor: 'rgb(13, 102, 208, 0.4)',
borderWidth: 1,
},
{
label: 'page views',
data: data.pageviews,
lineTension: 0,
backgroundColor: 'rgb(38, 128, 235, 0.2)',
borderColor: 'rgb(13, 102, 208, 0.2)',
borderWidth: 1,
},
]}
unit={unit}
records={data.pageviews.length}
animationDuration={visible ? 300 : 0}
onUpdate={handleUpdate}
/>
)}
</CheckVisible>
);
}

View file

@ -1,7 +1,6 @@
import React, { useState, useEffect, useMemo, useRef } from 'react';
import React, { useState, useEffect, useMemo } from 'react';
import classNames from 'classnames';
import PageviewsChart from './PageviewsChart';
import CheckVisible from '../helpers/CheckVisible';
import MetricsBar from './MetricsBar';
import QuickButtons from './QuickButtons';
import DateFilter from '../common/DateFilter';
@ -74,19 +73,10 @@ export default function WebsiteChart({
</StickyHeader>
</div>
<div className="row">
<CheckVisible className="col">
{visible => (
<>
<PageviewsChart
websiteId={websiteId}
data={{ pageviews, uniques }}
unit={unit}
animationDuration={visible ? 300 : 0}
/>
<QuickButtons value={value} onChange={handleDateChange} />
</>
)}
</CheckVisible>
<div className="col">
<PageviewsChart websiteId={websiteId} data={{ pageviews, uniques }} unit={unit} />
<QuickButtons value={value} onChange={handleDateChange} />
</div>
</div>
</>
);