@genspectrum/dashboard-components 0.7.0 → 0.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/mutationOverTimeWorker-BOCXtKzd.js.map +1 -1
- package/dist/dashboard-components.js +216 -207
- package/dist/dashboard-components.js.map +1 -1
- package/dist/genspectrum-components.d.ts +40 -40
- package/package.json +2 -2
- package/src/operator/SlidingOperator.ts +3 -0
- package/src/preact/aggregatedData/aggregate.tsx +41 -33
- package/src/preact/components/error-display.tsx +1 -0
- package/src/preact/mutationComparison/mutation-comparison.tsx +32 -34
- package/src/preact/mutations/mutations.tsx +63 -56
- package/src/preact/mutationsOverTime/mutations-over-time.tsx +33 -25
- package/src/preact/numberSequencesOverTime/number-sequences-over-time.tsx +46 -64
- package/src/preact/prevalenceOverTime/__mockData__/numeratorFilterNoData.json +11 -0
- package/src/preact/prevalenceOverTime/prevalence-over-time-bar-chart.tsx +13 -6
- package/src/preact/prevalenceOverTime/prevalence-over-time-bubble-chart.tsx +13 -6
- package/src/preact/prevalenceOverTime/prevalence-over-time-line-chart.tsx +13 -6
- package/src/preact/prevalenceOverTime/prevalence-over-time.stories.tsx +74 -11
- package/src/preact/prevalenceOverTime/prevalence-over-time.tsx +1 -1
- package/src/preact/relativeGrowthAdvantage/relative-growth-advantage.stories.tsx +12 -5
- package/src/preact/relativeGrowthAdvantage/relative-growth-advantage.tsx +29 -36
- package/standalone-bundle/dashboard-components.js +9842 -9847
- package/standalone-bundle/dashboard-components.js.map +1 -1
|
@@ -4,6 +4,7 @@ import { type TooltipItem } from 'chart.js/dist/types';
|
|
|
4
4
|
import { maxInData } from './prevalence-over-time';
|
|
5
5
|
import { type PrevalenceOverTimeData, type PrevalenceOverTimeVariantData } from '../../query/queryPrevalenceOverTime';
|
|
6
6
|
import GsChart from '../components/chart';
|
|
7
|
+
import { NoDataDisplay } from '../components/no-data-display';
|
|
7
8
|
import { LogitScale } from '../shared/charts/LogitScale';
|
|
8
9
|
import { singleGraphColorRGBAById } from '../shared/charts/colors';
|
|
9
10
|
import {
|
|
@@ -29,12 +30,18 @@ const PrevalenceOverTimeLineChart = ({
|
|
|
29
30
|
confidenceIntervalMethod,
|
|
30
31
|
yAxisMaxConfig,
|
|
31
32
|
}: PrevalenceOverTimeLineChartProps) => {
|
|
32
|
-
const nonNullDateRangeData = data
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
33
|
+
const nonNullDateRangeData = data
|
|
34
|
+
.filter((prevalenceOverTimeData) => prevalenceOverTimeData.content.length > 0)
|
|
35
|
+
.map((variantData) => {
|
|
36
|
+
return {
|
|
37
|
+
content: variantData.content.filter((dataPoint) => dataPoint.dateRange !== null),
|
|
38
|
+
displayName: variantData.displayName,
|
|
39
|
+
};
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
if (nonNullDateRangeData.length === 0) {
|
|
43
|
+
return <NoDataDisplay />;
|
|
44
|
+
}
|
|
38
45
|
|
|
39
46
|
const datasets = nonNullDateRangeData
|
|
40
47
|
.map((graphData, index) => getDataset(graphData, index, confidenceIntervalMethod))
|
|
@@ -1,11 +1,15 @@
|
|
|
1
|
+
import type { StoryObj } from '@storybook/preact';
|
|
2
|
+
import { expect, waitFor } from '@storybook/test';
|
|
3
|
+
|
|
4
|
+
import { LapisUrlContext } from '../LapisUrlContext';
|
|
1
5
|
import denominatorFilter from './__mockData__/denominatorFilter.json';
|
|
2
6
|
import denominatorOneDataset from './__mockData__/denominatorFilterOneDataset.json';
|
|
3
7
|
import numeratorFilterEG from './__mockData__/numeratorFilterEG.json';
|
|
4
8
|
import numeratorFilterJN1 from './__mockData__/numeratorFilterJN1.json';
|
|
9
|
+
import numeratorFilterNoData from './__mockData__/numeratorFilterNoData.json';
|
|
5
10
|
import numeratorOneDataset from './__mockData__/numeratorFilterOneDataset.json';
|
|
6
11
|
import { PrevalenceOverTime, type PrevalenceOverTimeProps } from './prevalence-over-time';
|
|
7
12
|
import { AGGREGATED_ENDPOINT, LAPIS_URL } from '../../constants';
|
|
8
|
-
import { LapisUrlContext } from '../LapisUrlContext';
|
|
9
13
|
|
|
10
14
|
export default {
|
|
11
15
|
title: 'Visualization/PrevalenceOverTime',
|
|
@@ -58,7 +62,7 @@ const Template = {
|
|
|
58
62
|
),
|
|
59
63
|
};
|
|
60
64
|
|
|
61
|
-
export const TwoVariants = {
|
|
65
|
+
export const TwoVariants: StoryObj<PrevalenceOverTimeProps> = {
|
|
62
66
|
...Template,
|
|
63
67
|
args: {
|
|
64
68
|
numeratorFilter: [
|
|
@@ -74,10 +78,8 @@ export const TwoVariants = {
|
|
|
74
78
|
height: '700px',
|
|
75
79
|
lapisDateField: 'date',
|
|
76
80
|
pageSize: 10,
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
logarithmic: 1,
|
|
80
|
-
},
|
|
81
|
+
yAxisMaxLinear: 1,
|
|
82
|
+
yAxisMaxLogarithmic: 1,
|
|
81
83
|
},
|
|
82
84
|
parameters: {
|
|
83
85
|
fetchMock: {
|
|
@@ -134,7 +136,7 @@ export const TwoVariants = {
|
|
|
134
136
|
},
|
|
135
137
|
};
|
|
136
138
|
|
|
137
|
-
export const OneVariant = {
|
|
139
|
+
export const OneVariant: StoryObj<PrevalenceOverTimeProps> = {
|
|
138
140
|
...Template,
|
|
139
141
|
args: {
|
|
140
142
|
numeratorFilter: {
|
|
@@ -150,10 +152,8 @@ export const OneVariant = {
|
|
|
150
152
|
height: '700px',
|
|
151
153
|
lapisDateField: 'date',
|
|
152
154
|
pageSize: 10,
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
logarithmic: 1,
|
|
156
|
-
},
|
|
155
|
+
yAxisMaxLinear: 1,
|
|
156
|
+
yAxisMaxLogarithmic: 1,
|
|
157
157
|
},
|
|
158
158
|
parameters: {
|
|
159
159
|
fetchMock: {
|
|
@@ -193,3 +193,66 @@ export const OneVariant = {
|
|
|
193
193
|
},
|
|
194
194
|
},
|
|
195
195
|
};
|
|
196
|
+
|
|
197
|
+
export const ShowsNoDataBanner: StoryObj<PrevalenceOverTimeProps> = {
|
|
198
|
+
...Template,
|
|
199
|
+
args: {
|
|
200
|
+
numeratorFilter: {
|
|
201
|
+
displayName: 'EG',
|
|
202
|
+
lapisFilter: { country: 'USA', pangoLineage: 'BA.2.86*', dateFrom: '2023-10-01' },
|
|
203
|
+
},
|
|
204
|
+
denominatorFilter: { country: 'USA', dateFrom: '2023-10-01' },
|
|
205
|
+
granularity: 'day',
|
|
206
|
+
smoothingWindow: 7,
|
|
207
|
+
views: ['bar', 'line', 'bubble', 'table'],
|
|
208
|
+
confidenceIntervalMethods: ['wilson'],
|
|
209
|
+
width: '100%',
|
|
210
|
+
height: '700px',
|
|
211
|
+
lapisDateField: 'date',
|
|
212
|
+
pageSize: 10,
|
|
213
|
+
yAxisMaxLinear: 1,
|
|
214
|
+
yAxisMaxLogarithmic: 1,
|
|
215
|
+
},
|
|
216
|
+
parameters: {
|
|
217
|
+
fetchMock: {
|
|
218
|
+
mocks: [
|
|
219
|
+
{
|
|
220
|
+
matcher: {
|
|
221
|
+
name: 'numeratorOneVariant',
|
|
222
|
+
url: AGGREGATED_ENDPOINT,
|
|
223
|
+
body: {
|
|
224
|
+
country: 'USA',
|
|
225
|
+
pangoLineage: 'BA.2.86*',
|
|
226
|
+
dateFrom: '2023-10-01',
|
|
227
|
+
fields: ['date'],
|
|
228
|
+
},
|
|
229
|
+
},
|
|
230
|
+
response: {
|
|
231
|
+
status: 200,
|
|
232
|
+
body: numeratorFilterNoData,
|
|
233
|
+
},
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
matcher: {
|
|
237
|
+
name: 'denominatorOneVariant',
|
|
238
|
+
url: AGGREGATED_ENDPOINT,
|
|
239
|
+
body: {
|
|
240
|
+
country: 'USA',
|
|
241
|
+
dateFrom: '2023-10-01',
|
|
242
|
+
fields: ['date'],
|
|
243
|
+
},
|
|
244
|
+
},
|
|
245
|
+
response: {
|
|
246
|
+
status: 200,
|
|
247
|
+
body: numeratorFilterNoData,
|
|
248
|
+
},
|
|
249
|
+
},
|
|
250
|
+
],
|
|
251
|
+
},
|
|
252
|
+
},
|
|
253
|
+
play: async ({ canvas }) => {
|
|
254
|
+
await waitFor(() => expect(canvas.getByText('No data available.', { exact: false })).toBeVisible(), {
|
|
255
|
+
timeout: 10000,
|
|
256
|
+
});
|
|
257
|
+
},
|
|
258
|
+
};
|
|
@@ -80,7 +80,7 @@ export const PrevalenceOverTimeInner: FunctionComponent<PrevalenceOverTimeProps>
|
|
|
80
80
|
return <ErrorDisplay error={error} />;
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
-
if (data === null) {
|
|
83
|
+
if (data === null || data.every((variant) => variant.content.length === 0)) {
|
|
84
84
|
return <NoDataDisplay />;
|
|
85
85
|
}
|
|
86
86
|
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { type StoryObj } from '@storybook/preact';
|
|
2
|
+
|
|
1
3
|
import denominator from './__mockData__/denominatorFilter.json';
|
|
2
4
|
import numerator from './__mockData__/numeratorFilter.json';
|
|
3
5
|
import { RelativeGrowthAdvantage, type RelativeGrowthAdvantageProps } from './relative-growth-advantage';
|
|
@@ -11,8 +13,8 @@ export default {
|
|
|
11
13
|
fetchMock: {},
|
|
12
14
|
},
|
|
13
15
|
argTypes: {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
+
numeratorFilter: { control: 'object' },
|
|
17
|
+
denominatorFilter: { control: 'object' },
|
|
16
18
|
generationTime: { control: 'number' },
|
|
17
19
|
views: {
|
|
18
20
|
options: ['line'],
|
|
@@ -24,7 +26,7 @@ export default {
|
|
|
24
26
|
},
|
|
25
27
|
};
|
|
26
28
|
|
|
27
|
-
export const Primary = {
|
|
29
|
+
export const Primary: StoryObj<RelativeGrowthAdvantageProps> = {
|
|
28
30
|
render: (args: RelativeGrowthAdvantageProps) => (
|
|
29
31
|
<LapisUrlContext.Provider value={LAPIS_URL}>
|
|
30
32
|
<RelativeGrowthAdvantage
|
|
@@ -40,8 +42,13 @@ export const Primary = {
|
|
|
40
42
|
</LapisUrlContext.Provider>
|
|
41
43
|
),
|
|
42
44
|
args: {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
+
numeratorFilter: {
|
|
46
|
+
country: 'Switzerland',
|
|
47
|
+
pangoLineage: 'B.1.1.7',
|
|
48
|
+
dateFrom: '2020-12-01',
|
|
49
|
+
dateTo: '2021-03-01',
|
|
50
|
+
},
|
|
51
|
+
denominatorFilter: { country: 'Switzerland', dateFrom: '2020-12-01', dateTo: '2021-03-01' },
|
|
45
52
|
generationTime: 7,
|
|
46
53
|
views: ['line'],
|
|
47
54
|
width: '100%',
|
|
@@ -11,7 +11,7 @@ import { LapisUrlContext } from '../LapisUrlContext';
|
|
|
11
11
|
import { ErrorBoundary } from '../components/error-boundary';
|
|
12
12
|
import { ErrorDisplay } from '../components/error-display';
|
|
13
13
|
import { Fullscreen } from '../components/fullscreen';
|
|
14
|
-
import Info, { InfoHeadline1, InfoHeadline2, InfoLink, InfoParagraph } from '../components/info';
|
|
14
|
+
import Info, { InfoComponentCode, InfoHeadline1, InfoHeadline2, InfoLink, InfoParagraph } from '../components/info';
|
|
15
15
|
import { LoadingDisplay } from '../components/loading-display';
|
|
16
16
|
import { NoDataDisplay } from '../components/no-data-display';
|
|
17
17
|
import { ResizeContainer } from '../components/resize-container';
|
|
@@ -23,12 +23,9 @@ import { useQuery } from '../useQuery';
|
|
|
23
23
|
|
|
24
24
|
export type View = 'line';
|
|
25
25
|
|
|
26
|
-
export interface RelativeGrowthAdvantageProps
|
|
26
|
+
export interface RelativeGrowthAdvantageProps {
|
|
27
27
|
width: string;
|
|
28
28
|
height: string;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export interface RelativeGrowthAdvantagePropsInner {
|
|
32
29
|
numeratorFilter: LapisFilter;
|
|
33
30
|
denominatorFilter: LapisFilter;
|
|
34
31
|
generationTime: number;
|
|
@@ -37,36 +34,28 @@ export interface RelativeGrowthAdvantagePropsInner {
|
|
|
37
34
|
yAxisMaxConfig: YAxisMaxConfig;
|
|
38
35
|
}
|
|
39
36
|
|
|
40
|
-
export const RelativeGrowthAdvantage: FunctionComponent<RelativeGrowthAdvantageProps> = ({
|
|
41
|
-
width,
|
|
42
|
-
height,
|
|
43
|
-
...innerProps
|
|
44
|
-
}) => {
|
|
37
|
+
export const RelativeGrowthAdvantage: FunctionComponent<RelativeGrowthAdvantageProps> = (componentProps) => {
|
|
38
|
+
const { width, height } = componentProps;
|
|
45
39
|
const size = { height, width };
|
|
46
40
|
|
|
47
41
|
return (
|
|
48
42
|
<ErrorBoundary size={size}>
|
|
49
43
|
<ResizeContainer size={size}>
|
|
50
|
-
<RelativeGrowthAdvantageInner {...
|
|
44
|
+
<RelativeGrowthAdvantageInner {...componentProps} />
|
|
51
45
|
</ResizeContainer>
|
|
52
46
|
</ErrorBoundary>
|
|
53
47
|
);
|
|
54
48
|
};
|
|
55
49
|
|
|
56
|
-
export const RelativeGrowthAdvantageInner: FunctionComponent<
|
|
57
|
-
numeratorFilter,
|
|
58
|
-
denominatorFilter,
|
|
59
|
-
generationTime,
|
|
60
|
-
views,
|
|
61
|
-
lapisDateField,
|
|
62
|
-
yAxisMaxConfig,
|
|
63
|
-
}) => {
|
|
50
|
+
export const RelativeGrowthAdvantageInner: FunctionComponent<RelativeGrowthAdvantageProps> = (componentProps) => {
|
|
64
51
|
const lapis = useContext(LapisUrlContext);
|
|
52
|
+
const { numeratorFilter, denominatorFilter, generationTime, lapisDateField } = componentProps;
|
|
53
|
+
|
|
65
54
|
const [yAxisScaleType, setYAxisScaleType] = useState<ScaleType>('linear');
|
|
66
55
|
|
|
67
56
|
const { data, error, isLoading } = useQuery(
|
|
68
57
|
() => queryRelativeGrowthAdvantage(numeratorFilter, denominatorFilter, generationTime, lapis, lapisDateField),
|
|
69
|
-
[lapis, numeratorFilter, denominatorFilter, generationTime,
|
|
58
|
+
[lapis, numeratorFilter, denominatorFilter, generationTime, lapisDateField],
|
|
70
59
|
);
|
|
71
60
|
|
|
72
61
|
if (isLoading) {
|
|
@@ -86,9 +75,7 @@ export const RelativeGrowthAdvantageInner: FunctionComponent<RelativeGrowthAdvan
|
|
|
86
75
|
data={data}
|
|
87
76
|
yAxisScaleType={yAxisScaleType}
|
|
88
77
|
setYAxisScaleType={setYAxisScaleType}
|
|
89
|
-
|
|
90
|
-
generationTime={generationTime}
|
|
91
|
-
yAxisMaxConfig={yAxisMaxConfig}
|
|
78
|
+
originalComponentProps={componentProps}
|
|
92
79
|
/>
|
|
93
80
|
);
|
|
94
81
|
};
|
|
@@ -97,18 +84,14 @@ type RelativeGrowthAdvantageTabsProps = {
|
|
|
97
84
|
data: NonNullable<RelativeGrowthAdvantageData>;
|
|
98
85
|
yAxisScaleType: ScaleType;
|
|
99
86
|
setYAxisScaleType: (scaleType: ScaleType) => void;
|
|
100
|
-
|
|
101
|
-
generationTime: number;
|
|
102
|
-
yAxisMaxConfig: YAxisMaxConfig;
|
|
87
|
+
originalComponentProps: RelativeGrowthAdvantageProps;
|
|
103
88
|
};
|
|
104
89
|
|
|
105
90
|
const RelativeGrowthAdvantageTabs: FunctionComponent<RelativeGrowthAdvantageTabsProps> = ({
|
|
106
91
|
data,
|
|
107
92
|
yAxisScaleType,
|
|
108
93
|
setYAxisScaleType,
|
|
109
|
-
|
|
110
|
-
generationTime,
|
|
111
|
-
yAxisMaxConfig,
|
|
94
|
+
originalComponentProps,
|
|
112
95
|
}) => {
|
|
113
96
|
const getTab = (view: View) => {
|
|
114
97
|
switch (view) {
|
|
@@ -123,17 +106,17 @@ const RelativeGrowthAdvantageTabs: FunctionComponent<RelativeGrowthAdvantageTabs
|
|
|
123
106
|
params: data.params,
|
|
124
107
|
}}
|
|
125
108
|
yAxisScaleType={yAxisScaleType}
|
|
126
|
-
yAxisMaxConfig={yAxisMaxConfig}
|
|
109
|
+
yAxisMaxConfig={originalComponentProps.yAxisMaxConfig}
|
|
127
110
|
/>
|
|
128
111
|
),
|
|
129
112
|
};
|
|
130
113
|
}
|
|
131
114
|
};
|
|
132
115
|
|
|
133
|
-
const tabs = views.map((view) => getTab(view));
|
|
116
|
+
const tabs = originalComponentProps.views.map((view) => getTab(view));
|
|
134
117
|
const toolbar = () => (
|
|
135
118
|
<RelativeGrowthAdvantageToolbar
|
|
136
|
-
|
|
119
|
+
originalComponentProps={originalComponentProps}
|
|
137
120
|
yAxisScaleType={yAxisScaleType}
|
|
138
121
|
setYAxisScaleType={setYAxisScaleType}
|
|
139
122
|
/>
|
|
@@ -145,24 +128,29 @@ const RelativeGrowthAdvantageTabs: FunctionComponent<RelativeGrowthAdvantageTabs
|
|
|
145
128
|
type RelativeGrowthAdvantageToolbarProps = {
|
|
146
129
|
yAxisScaleType: ScaleType;
|
|
147
130
|
setYAxisScaleType: (scaleType: ScaleType) => void;
|
|
148
|
-
|
|
131
|
+
originalComponentProps: RelativeGrowthAdvantageProps;
|
|
149
132
|
};
|
|
150
133
|
|
|
151
134
|
const RelativeGrowthAdvantageToolbar: FunctionComponent<RelativeGrowthAdvantageToolbarProps> = ({
|
|
152
135
|
yAxisScaleType,
|
|
153
136
|
setYAxisScaleType,
|
|
154
|
-
|
|
137
|
+
originalComponentProps,
|
|
155
138
|
}) => {
|
|
156
139
|
return (
|
|
157
140
|
<>
|
|
158
141
|
<ScalingSelector yAxisScaleType={yAxisScaleType} setYAxisScaleType={setYAxisScaleType} />
|
|
159
|
-
<RelativeGrowthAdvantageInfo
|
|
142
|
+
<RelativeGrowthAdvantageInfo originalComponentProps={originalComponentProps} />
|
|
160
143
|
<Fullscreen />
|
|
161
144
|
</>
|
|
162
145
|
);
|
|
163
146
|
};
|
|
164
147
|
|
|
165
|
-
const RelativeGrowthAdvantageInfo: FunctionComponent<{
|
|
148
|
+
const RelativeGrowthAdvantageInfo: FunctionComponent<{ originalComponentProps: RelativeGrowthAdvantageProps }> = ({
|
|
149
|
+
originalComponentProps,
|
|
150
|
+
}) => {
|
|
151
|
+
const lapis = useContext(LapisUrlContext);
|
|
152
|
+
const generationTime = originalComponentProps.generationTime;
|
|
153
|
+
|
|
166
154
|
return (
|
|
167
155
|
<Info>
|
|
168
156
|
<InfoHeadline1>Relative growth advantage</InfoHeadline1>
|
|
@@ -193,6 +181,11 @@ const RelativeGrowthAdvantageInfo: FunctionComponent<{ generationTime: number }>
|
|
|
193
181
|
10.1016/j.epidem.2021.100480
|
|
194
182
|
</InfoLink>
|
|
195
183
|
</InfoParagraph>
|
|
184
|
+
<InfoComponentCode
|
|
185
|
+
componentName='relative-growth-advantage'
|
|
186
|
+
params={originalComponentProps}
|
|
187
|
+
lapisUrl={lapis}
|
|
188
|
+
/>
|
|
196
189
|
</Info>
|
|
197
190
|
);
|
|
198
191
|
};
|