import {Fragment} from 'react';
import {useTheme} from '@emotion/react';
import styled from '@emotion/styled';
import moment from 'moment-timezone';
import JSXNode from 'sentry/components/stories/jsxNode';
import SideBySide from 'sentry/components/stories/sideBySide';
import SizingWindow from 'sentry/components/stories/sizingWindow';
import storyBook from 'sentry/stories/storyBook';
import type {DateString} from 'sentry/types/core';
import usePageFilters from 'sentry/utils/usePageFilters';
import type {Release, TimeseriesData} from '../common/types';
import {shiftTimeserieToNow} from '../timeSeriesWidget/shiftTimeserieToNow';
import {AreaChartWidget} from './areaChartWidget';
import sampleLatencyTimeSeries from './sampleLatencyTimeSeries.json';
import sampleSpanDurationTimeSeries from './sampleSpanDurationTimeSeries.json';
export default storyBook(AreaChartWidget, story => {
story('Getting Started', () => {
return (
is a Dashboard Widget Component. It displays
a timeseries chart with multiple timeseries, and the timeseries are stacked.
Each timeseries is shown using a solid block of color. This chart is used to
visualize multiple timeseries that represent parts of something. For example, a
chart that shows time spent in the app broken down by component. In all other
ways, it behaves like , though it doesn't
support features like "Previous Period Data".
NOTE: This chart is not appropriate for showing a single timeseries!
You should use instead.
);
});
story('Visualization', () => {
const {selection} = usePageFilters();
const {datetime} = selection;
const {start, end} = datetime;
const latencyTimeSeries = toTimeSeriesSelection(
sampleLatencyTimeSeries as unknown as TimeseriesData,
start,
end
);
const spanDurationTimeSeries = toTimeSeriesSelection(
sampleSpanDurationTimeSeries as unknown as TimeseriesData,
start,
end
);
return (
The visualization of a stacked area chart. It
has some bells and whistles including automatic axes labels, and a hover
tooltip. Like other widgets, it automatically fills the parent element.
The dataCompletenessDelay
prop indicates that this data is live,
and the last few buckets might not have complete data. The delay is a number in
seconds. Any data bucket that happens in that delay window will be plotted with
a fainter fill. By default the delay is 0
.
);
});
story('State', () => {
return (
supports the usual loading and error states.
The loading state shows a spinner. The error state shows a message, and an
optional "Retry" button.
{}}
/>
);
});
story('Colors', () => {
const theme = useTheme();
return (
You can control the color of each timeseries by setting the color
{' '}
attribute to a string that contains a valid hex color code.
);
});
story('Releases', () => {
const releases = [
{
version: 'ui@0.1.2',
timestamp: sampleLatencyTimeSeries.data.at(2)?.timestamp,
},
{
version: 'ui@0.1.3',
timestamp: sampleLatencyTimeSeries.data.at(20)?.timestamp,
},
].filter(hasTimestamp);
return (
supports the releases
prop. If
passed in, the widget will plot every release as a vertical line that overlays
the chart data. Clicking on a release line will open the release details page.
);
});
});
const MediumWidget = styled('div')`
width: 420px;
height: 250px;
`;
const SmallWidget = styled('div')`
width: 360px;
height: 160px;
`;
const SmallSizingWindow = styled(SizingWindow)`
width: 50%;
height: 300px;
`;
function toTimeSeriesSelection(
timeSeries: TimeseriesData,
start: DateString | null,
end: DateString | null
): TimeseriesData {
return {
...timeSeries,
data: timeSeries.data.filter(datum => {
if (start && moment(datum.timestamp).isBefore(moment.utc(start))) {
return false;
}
if (end && moment(datum.timestamp).isAfter(moment.utc(end))) {
return false;
}
return true;
}),
};
}
function hasTimestamp(release: Partial): release is Release {
return Boolean(release?.timestamp);
}