@genspectrum/dashboard-components 0.1.5 → 0.3.0
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/custom-elements.json +1161 -928
- package/dist/dashboard-components.js +663 -237
- package/dist/dashboard-components.js.map +1 -1
- package/dist/genspectrum-components.d.ts +177 -140
- package/dist/style.css +247 -50
- package/package.json +2 -3
- package/src/constants.ts +1 -1
- package/src/lapisApi/lapisApi.ts +46 -2
- package/src/lapisApi/lapisTypes.ts +14 -0
- package/src/preact/aggregatedData/aggregate.stories.tsx +4 -2
- package/src/preact/aggregatedData/aggregate.tsx +31 -29
- package/src/preact/components/error-boundary.stories.tsx +54 -0
- package/src/preact/components/error-boundary.tsx +22 -0
- package/src/preact/components/error-display.stories.tsx +32 -4
- package/src/preact/components/error-display.tsx +48 -1
- package/src/preact/components/loading-display.stories.tsx +6 -6
- package/src/preact/components/loading-display.tsx +1 -1
- package/src/preact/components/no-data-display.tsx +5 -1
- package/src/preact/components/resize-container.tsx +5 -14
- package/src/preact/dateRangeSelector/date-range-selector.stories.tsx +19 -0
- package/src/preact/dateRangeSelector/date-range-selector.tsx +38 -7
- package/src/preact/locationFilter/fetchAutocompletionList.ts +15 -1
- package/src/preact/locationFilter/location-filter.stories.tsx +23 -6
- package/src/preact/locationFilter/location-filter.tsx +28 -18
- package/src/preact/mutationComparison/mutation-comparison.stories.tsx +6 -3
- package/src/preact/mutationComparison/mutation-comparison.tsx +33 -32
- package/src/preact/mutationComparison/queryMutationData.ts +2 -3
- package/src/preact/mutationFilter/mutation-filter.stories.tsx +18 -3
- package/src/preact/mutationFilter/mutation-filter.tsx +26 -7
- package/src/preact/mutations/mutations.stories.tsx +6 -3
- package/src/preact/mutations/mutations.tsx +28 -26
- package/src/preact/prevalenceOverTime/prevalence-over-time.stories.tsx +14 -7
- package/src/preact/prevalenceOverTime/prevalence-over-time.tsx +50 -32
- package/src/preact/relativeGrowthAdvantage/relative-growth-advantage.stories.tsx +6 -3
- package/src/preact/relativeGrowthAdvantage/relative-growth-advantage.tsx +46 -32
- package/src/preact/textInput/text-input.stories.tsx +26 -0
- package/src/preact/textInput/text-input.tsx +25 -3
- package/src/query/queryPrevalenceOverTime.ts +4 -10
- package/src/types.ts +4 -1
- package/src/web-components/ResizeContainer.mdx +13 -0
- package/src/web-components/app.stories.ts +1 -2
- package/src/web-components/app.ts +7 -3
- package/src/web-components/index.ts +1 -1
- package/src/web-components/input/{date-range-selector-component.stories.ts → gs-date-range-selector.stories.ts} +29 -4
- package/src/web-components/input/{date-range-selector-component.tsx → gs-date-range-selector.tsx} +32 -10
- package/src/web-components/input/{location-filter-component.stories.ts → gs-location-filter.stories.ts} +32 -5
- package/src/web-components/input/{location-filter-component.tsx → gs-location-filter.tsx} +11 -1
- package/src/web-components/input/{mutation-filter-component.stories.ts → gs-mutation-filter.stories.ts} +23 -4
- package/src/web-components/input/gs-mutation-filter.tsx +126 -0
- package/src/web-components/input/{text-input-component.stories.ts → gs-text-input.stories.ts} +34 -6
- package/src/web-components/input/{text-input-component.tsx → gs-text-input.tsx} +16 -4
- package/src/web-components/input/index.ts +4 -4
- package/src/web-components/input/introduction.mdx +11 -0
- package/src/web-components/introduction.mdx +15 -0
- package/src/web-components/visualization/data_visualization_statistical_analysis.mdx +26 -0
- package/src/web-components/{display/aggregate-component.stories.ts → visualization/gs-aggregate.stories.ts} +23 -11
- package/src/web-components/visualization/gs-aggregate.tsx +88 -0
- package/src/web-components/{display/mutation-comparison-component.stories.ts → visualization/gs-mutation-comparison.stories.ts} +21 -16
- package/src/web-components/{display/mutation-comparison-component.tsx → visualization/gs-mutation-comparison.tsx} +27 -18
- package/src/web-components/{display/mutations-component.stories.ts → visualization/gs-mutations.stories.ts} +20 -15
- package/src/web-components/{display/mutations-component.tsx → visualization/gs-mutations.tsx} +20 -10
- package/src/web-components/{display/prevalence-over-time-component.stories.ts → visualization/gs-prevalence-over-time.stories.ts} +29 -20
- package/src/web-components/{display/prevalence-over-time-component.tsx → visualization/gs-prevalence-over-time.tsx} +47 -22
- package/src/web-components/{display/relative-growth-advantage-component.stories.ts → visualization/gs-relative-growth-advantage.stories.ts} +12 -7
- package/src/web-components/{display/relative-growth-advantage-component.tsx → visualization/gs-relative-growth-advantage.tsx} +21 -9
- package/src/web-components/visualization/index.ts +5 -0
- package/src/web-components/display/aggregate-component.tsx +0 -72
- package/src/web-components/display/index.ts +0 -5
- package/src/web-components/input/mutation-filter-component.tsx +0 -83
|
@@ -5,10 +5,11 @@ import { getMutationComparisonTableData } from './getMutationComparisonTableData
|
|
|
5
5
|
import { MutationComparisonTable } from './mutation-comparison-table';
|
|
6
6
|
import { MutationComparisonVenn } from './mutation-comparison-venn';
|
|
7
7
|
import { filterMutationData, type MutationData, queryMutationData } from './queryMutationData';
|
|
8
|
-
import { type
|
|
8
|
+
import { type NamedLapisFilter, type SequenceType } from '../../types';
|
|
9
9
|
import { LapisUrlContext } from '../LapisUrlContext';
|
|
10
10
|
import { type DisplayedSegment, SegmentSelector, useDisplayedSegments } from '../components/SegmentSelector';
|
|
11
11
|
import { CsvDownloadButton } from '../components/csv-download-button';
|
|
12
|
+
import { ErrorBoundary } from '../components/error-boundary';
|
|
12
13
|
import { ErrorDisplay } from '../components/error-display';
|
|
13
14
|
import Headline from '../components/headline';
|
|
14
15
|
import Info from '../components/info';
|
|
@@ -17,31 +18,49 @@ import { type DisplayedMutationType, MutationTypeSelector } from '../components/
|
|
|
17
18
|
import { NoDataDisplay } from '../components/no-data-display';
|
|
18
19
|
import { type ProportionInterval } from '../components/proportion-selector';
|
|
19
20
|
import { ProportionSelectorDropdown } from '../components/proportion-selector-dropdown';
|
|
20
|
-
import { ResizeContainer
|
|
21
|
+
import { ResizeContainer } from '../components/resize-container';
|
|
21
22
|
import Tabs from '../components/tabs';
|
|
22
23
|
import { useQuery } from '../useQuery';
|
|
23
24
|
|
|
24
25
|
export type View = 'table' | 'venn';
|
|
25
26
|
|
|
26
|
-
export interface
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
export interface MutationComparisonProps extends MutationComparisonInnerProps {
|
|
28
|
+
width: string;
|
|
29
|
+
height: string;
|
|
30
|
+
headline?: string;
|
|
29
31
|
}
|
|
30
32
|
|
|
31
|
-
export interface
|
|
32
|
-
variants:
|
|
33
|
+
export interface MutationComparisonInnerProps {
|
|
34
|
+
variants: NamedLapisFilter[];
|
|
33
35
|
sequenceType: SequenceType;
|
|
34
36
|
views: View[];
|
|
35
|
-
size?: Size;
|
|
36
|
-
headline?: string;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
export const MutationComparison: FunctionComponent<MutationComparisonProps> = ({
|
|
40
40
|
variants,
|
|
41
41
|
sequenceType,
|
|
42
42
|
views,
|
|
43
|
-
|
|
43
|
+
width,
|
|
44
|
+
height,
|
|
44
45
|
headline = 'Mutation comparison',
|
|
46
|
+
}) => {
|
|
47
|
+
const size = { height, width };
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<ErrorBoundary size={size} headline={headline}>
|
|
51
|
+
<ResizeContainer size={size}>
|
|
52
|
+
<Headline heading={headline}>
|
|
53
|
+
<MutationComparisonInner variants={variants} sequenceType={sequenceType} views={views} />
|
|
54
|
+
</Headline>
|
|
55
|
+
</ResizeContainer>
|
|
56
|
+
</ErrorBoundary>
|
|
57
|
+
);
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export const MutationComparisonInner: FunctionComponent<MutationComparisonInnerProps> = ({
|
|
61
|
+
variants,
|
|
62
|
+
sequenceType,
|
|
63
|
+
views,
|
|
45
64
|
}) => {
|
|
46
65
|
const lapis = useContext(LapisUrlContext);
|
|
47
66
|
|
|
@@ -50,36 +69,18 @@ export const MutationComparison: FunctionComponent<MutationComparisonProps> = ({
|
|
|
50
69
|
}, [variants, sequenceType, lapis]);
|
|
51
70
|
|
|
52
71
|
if (isLoading) {
|
|
53
|
-
return
|
|
54
|
-
<Headline heading={headline}>
|
|
55
|
-
<LoadingDisplay />
|
|
56
|
-
</Headline>
|
|
57
|
-
);
|
|
72
|
+
return <LoadingDisplay />;
|
|
58
73
|
}
|
|
59
74
|
|
|
60
75
|
if (error !== null) {
|
|
61
|
-
return
|
|
62
|
-
<Headline heading={headline}>
|
|
63
|
-
<ErrorDisplay error={error} />
|
|
64
|
-
</Headline>
|
|
65
|
-
);
|
|
76
|
+
return <ErrorDisplay error={error} />;
|
|
66
77
|
}
|
|
67
78
|
|
|
68
79
|
if (data === null) {
|
|
69
|
-
return
|
|
70
|
-
<Headline heading={headline}>
|
|
71
|
-
<NoDataDisplay />
|
|
72
|
-
</Headline>
|
|
73
|
-
);
|
|
80
|
+
return <NoDataDisplay />;
|
|
74
81
|
}
|
|
75
82
|
|
|
76
|
-
return
|
|
77
|
-
<ResizeContainer size={size} defaultSize={{ height: '700px', width: '100%' }}>
|
|
78
|
-
<Headline heading={headline}>
|
|
79
|
-
<MutationComparisonTabs data={data.mutationData} sequenceType={sequenceType} views={views} />
|
|
80
|
-
</Headline>
|
|
81
|
-
</ResizeContainer>
|
|
82
|
-
);
|
|
83
|
+
return <MutationComparisonTabs data={data.mutationData} sequenceType={sequenceType} views={views} />;
|
|
83
84
|
};
|
|
84
85
|
|
|
85
86
|
type MutationComparisonTabsProps = {
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { type MutationComparisonVariant } from './mutation-comparison';
|
|
2
1
|
import { querySubstitutionsOrDeletions } from '../../query/querySubstitutionsOrDeletions';
|
|
3
|
-
import { type SubstitutionOrDeletionEntry } from '../../types';
|
|
2
|
+
import { type NamedLapisFilter, type SubstitutionOrDeletionEntry } from '../../types';
|
|
4
3
|
import { type DisplayedSegment } from '../components/SegmentSelector';
|
|
5
4
|
import { type DisplayedMutationType } from '../components/mutation-type-selector';
|
|
6
5
|
|
|
@@ -10,7 +9,7 @@ export type MutationData = {
|
|
|
10
9
|
};
|
|
11
10
|
|
|
12
11
|
export async function queryMutationData(
|
|
13
|
-
variants:
|
|
12
|
+
variants: NamedLapisFilter[],
|
|
14
13
|
sequenceType: 'nucleotide' | 'amino acid',
|
|
15
14
|
lapis: string,
|
|
16
15
|
) {
|
|
@@ -18,19 +18,32 @@ const meta: Meta<MutationFilterProps> = {
|
|
|
18
18
|
},
|
|
19
19
|
fetchMock: {},
|
|
20
20
|
},
|
|
21
|
+
argTypes: {
|
|
22
|
+
width: { control: 'text' },
|
|
23
|
+
height: { control: 'text' },
|
|
24
|
+
initialValue: {
|
|
25
|
+
control: {
|
|
26
|
+
type: 'object',
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
},
|
|
21
30
|
decorators: [withActions],
|
|
22
31
|
};
|
|
23
32
|
|
|
24
33
|
export default meta;
|
|
25
34
|
|
|
26
35
|
export const Default: StoryObj<MutationFilterProps> = {
|
|
27
|
-
render: () => (
|
|
36
|
+
render: (args) => (
|
|
28
37
|
<LapisUrlContext.Provider value={LAPIS_URL}>
|
|
29
38
|
<ReferenceGenomeContext.Provider value={referenceGenome}>
|
|
30
|
-
<MutationFilter />
|
|
39
|
+
<MutationFilter width={args.width} height={args.height} initialValue={args.initialValue} />
|
|
31
40
|
</ReferenceGenomeContext.Provider>
|
|
32
41
|
</LapisUrlContext.Provider>
|
|
33
42
|
),
|
|
43
|
+
args: {
|
|
44
|
+
width: '100%',
|
|
45
|
+
height: '700px',
|
|
46
|
+
},
|
|
34
47
|
};
|
|
35
48
|
|
|
36
49
|
export const FiresFilterChangedEvents: StoryObj<MutationFilterProps> = {
|
|
@@ -140,7 +153,7 @@ export const WithInitialValue: StoryObj<MutationFilterProps> = {
|
|
|
140
153
|
render: (args) => (
|
|
141
154
|
<LapisUrlContext.Provider value={LAPIS_URL}>
|
|
142
155
|
<ReferenceGenomeContext.Provider value={referenceGenome}>
|
|
143
|
-
<MutationFilter initialValue={args.initialValue} />
|
|
156
|
+
<MutationFilter initialValue={args.initialValue} width={args.width} height={args.height} />
|
|
144
157
|
</ReferenceGenomeContext.Provider>
|
|
145
158
|
</LapisUrlContext.Provider>
|
|
146
159
|
),
|
|
@@ -151,6 +164,8 @@ export const WithInitialValue: StoryObj<MutationFilterProps> = {
|
|
|
151
164
|
nucleotideInsertions: ['ins_123:AAA'],
|
|
152
165
|
aminoAcidInsertions: ['ins_S:123:AAA'],
|
|
153
166
|
},
|
|
167
|
+
width: '100%',
|
|
168
|
+
height: '700px',
|
|
154
169
|
},
|
|
155
170
|
play: async ({ canvasElement, step }) => {
|
|
156
171
|
const { canvas, onBlurListenerMock } = await prepare(canvasElement, step);
|
|
@@ -5,13 +5,20 @@ import { parseAndValidateMutation } from './parseAndValidateMutation';
|
|
|
5
5
|
import { type ReferenceGenome } from '../../lapisApi/ReferenceGenome';
|
|
6
6
|
import { type Deletion, type Insertion, type Mutation, type Substitution } from '../../utils/mutations';
|
|
7
7
|
import { ReferenceGenomeContext } from '../ReferenceGenomeContext';
|
|
8
|
+
import { ErrorBoundary } from '../components/error-boundary';
|
|
8
9
|
import Info from '../components/info';
|
|
10
|
+
import { ResizeContainer } from '../components/resize-container';
|
|
9
11
|
import { singleGraphColorRGBByName } from '../shared/charts/colors';
|
|
10
12
|
import { DeleteIcon } from '../shared/icons/DeleteIcon';
|
|
11
13
|
|
|
12
|
-
export
|
|
14
|
+
export interface MutationFilterInnerProps {
|
|
13
15
|
initialValue?: SelectedMutationFilterStrings | string[] | undefined;
|
|
14
|
-
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface MutationFilterProps extends MutationFilterInnerProps {
|
|
19
|
+
width: string;
|
|
20
|
+
height: string;
|
|
21
|
+
}
|
|
15
22
|
|
|
16
23
|
export type SelectedFilters = {
|
|
17
24
|
nucleotideMutations: (Substitution | Deletion)[];
|
|
@@ -24,7 +31,19 @@ export type SelectedMutationFilterStrings = {
|
|
|
24
31
|
[Key in keyof SelectedFilters]: string[];
|
|
25
32
|
};
|
|
26
33
|
|
|
27
|
-
export const MutationFilter: FunctionComponent<MutationFilterProps> = ({ initialValue }) => {
|
|
34
|
+
export const MutationFilter: FunctionComponent<MutationFilterProps> = ({ initialValue, width, height }) => {
|
|
35
|
+
const size = { height, width };
|
|
36
|
+
|
|
37
|
+
return (
|
|
38
|
+
<ErrorBoundary size={size}>
|
|
39
|
+
<ResizeContainer size={size}>
|
|
40
|
+
<MutationFilterInner initialValue={initialValue} />
|
|
41
|
+
</ResizeContainer>
|
|
42
|
+
</ErrorBoundary>
|
|
43
|
+
);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export const MutationFilterInner: FunctionComponent<MutationFilterInnerProps> = ({ initialValue }) => {
|
|
28
47
|
const referenceGenome = useContext(ReferenceGenomeContext);
|
|
29
48
|
const [selectedFilters, setSelectedFilters] = useState<SelectedFilters>(
|
|
30
49
|
getInitialState(initialValue, referenceGenome),
|
|
@@ -83,7 +102,7 @@ export const MutationFilter: FunctionComponent<MutationFilterProps> = ({ initial
|
|
|
83
102
|
};
|
|
84
103
|
|
|
85
104
|
return (
|
|
86
|
-
<div class={`rounded-lg border border-gray-300 bg-white p-2`}>
|
|
105
|
+
<div class={`h-full w-full rounded-lg border border-gray-300 bg-white p-2 overflow-scroll`}>
|
|
87
106
|
<div class='flex justify-between'>
|
|
88
107
|
<SelectedMutationDisplay
|
|
89
108
|
selectedFilters={selectedFilters}
|
|
@@ -295,11 +314,11 @@ const SelectedFilter = <MutationType extends Mutation>({
|
|
|
295
314
|
}: SelectedFilterProps<MutationType>) => {
|
|
296
315
|
return (
|
|
297
316
|
<div
|
|
298
|
-
class='flex items-center flex-nowrap gap-1 rounded me-1 px-2.5 py-0.5 font-medium text-xs mb-1'
|
|
317
|
+
class='flex items-center flex-nowrap gap-1 rounded me-1 px-2.5 py-0.5 font-medium text-xs mb-1 min-w-max'
|
|
299
318
|
style={{ backgroundColor, color: textColor }}
|
|
300
319
|
>
|
|
301
|
-
<div>{mutation.toString()}</div>
|
|
302
|
-
<button onClick={() => onDelete(mutation)}>
|
|
320
|
+
<div className='whitespace-nowrap min-w-max'>{mutation.toString()}</div>
|
|
321
|
+
<button type='button' onClick={() => onDelete(mutation)}>
|
|
303
322
|
<DeleteIcon />
|
|
304
323
|
</button>
|
|
305
324
|
</div>
|
|
@@ -22,7 +22,8 @@ const meta: Meta<MutationsProps> = {
|
|
|
22
22
|
options: ['table', 'grid', 'insertions'],
|
|
23
23
|
control: { type: 'check' },
|
|
24
24
|
},
|
|
25
|
-
|
|
25
|
+
width: { control: 'text' },
|
|
26
|
+
height: { control: 'text' },
|
|
26
27
|
headline: { control: 'text' },
|
|
27
28
|
},
|
|
28
29
|
};
|
|
@@ -37,7 +38,8 @@ const Template = {
|
|
|
37
38
|
variant={args.variant}
|
|
38
39
|
sequenceType={args.sequenceType}
|
|
39
40
|
views={args.views}
|
|
40
|
-
|
|
41
|
+
width={args.width}
|
|
42
|
+
height={args.height}
|
|
41
43
|
headline={args.headline}
|
|
42
44
|
/>
|
|
43
45
|
</ReferenceGenomeContext.Provider>
|
|
@@ -51,7 +53,8 @@ export const Default: StoryObj<MutationsProps> = {
|
|
|
51
53
|
variant: { country: 'Switzerland', pangoLineage: 'B.1.1.7', dateTo: '2022-01-01' },
|
|
52
54
|
sequenceType: 'nucleotide',
|
|
53
55
|
views: ['grid', 'table', 'insertions'],
|
|
54
|
-
|
|
56
|
+
width: '100%',
|
|
57
|
+
height: '700px',
|
|
55
58
|
headline: 'Mutations',
|
|
56
59
|
},
|
|
57
60
|
parameters: {
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
import { LapisUrlContext } from '../LapisUrlContext';
|
|
17
17
|
import { type DisplayedSegment, SegmentSelector, useDisplayedSegments } from '../components/SegmentSelector';
|
|
18
18
|
import { CsvDownloadButton } from '../components/csv-download-button';
|
|
19
|
+
import { ErrorBoundary } from '../components/error-boundary';
|
|
19
20
|
import { ErrorDisplay } from '../components/error-display';
|
|
20
21
|
import Headline from '../components/headline';
|
|
21
22
|
import Info from '../components/info';
|
|
@@ -24,17 +25,21 @@ import { type DisplayedMutationType, MutationTypeSelector } from '../components/
|
|
|
24
25
|
import { NoDataDisplay } from '../components/no-data-display';
|
|
25
26
|
import type { ProportionInterval } from '../components/proportion-selector';
|
|
26
27
|
import { ProportionSelectorDropdown } from '../components/proportion-selector-dropdown';
|
|
27
|
-
import { ResizeContainer
|
|
28
|
+
import { ResizeContainer } from '../components/resize-container';
|
|
28
29
|
import Tabs from '../components/tabs';
|
|
29
30
|
import { useQuery } from '../useQuery';
|
|
30
31
|
|
|
31
32
|
export type View = 'table' | 'grid' | 'insertions';
|
|
32
33
|
|
|
33
|
-
export interface
|
|
34
|
+
export interface MutationsInnerProps {
|
|
34
35
|
variant: LapisFilter;
|
|
35
36
|
sequenceType: SequenceType;
|
|
36
37
|
views: View[];
|
|
37
|
-
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface MutationsProps extends MutationsInnerProps {
|
|
41
|
+
width: string;
|
|
42
|
+
height: string;
|
|
38
43
|
headline?: string;
|
|
39
44
|
}
|
|
40
45
|
|
|
@@ -42,45 +47,42 @@ export const Mutations: FunctionComponent<MutationsProps> = ({
|
|
|
42
47
|
variant,
|
|
43
48
|
sequenceType,
|
|
44
49
|
views,
|
|
45
|
-
|
|
50
|
+
width,
|
|
51
|
+
height,
|
|
46
52
|
headline = 'Mutations',
|
|
47
53
|
}) => {
|
|
54
|
+
const size = { height, width };
|
|
55
|
+
|
|
56
|
+
return (
|
|
57
|
+
<ErrorBoundary size={size} headline={headline}>
|
|
58
|
+
<ResizeContainer size={size}>
|
|
59
|
+
<Headline heading={headline}>
|
|
60
|
+
<MutationsInner variant={variant} sequenceType={sequenceType} views={views} />
|
|
61
|
+
</Headline>
|
|
62
|
+
</ResizeContainer>
|
|
63
|
+
</ErrorBoundary>
|
|
64
|
+
);
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export const MutationsInner: FunctionComponent<MutationsInnerProps> = ({ variant, sequenceType, views }) => {
|
|
48
68
|
const lapis = useContext(LapisUrlContext);
|
|
49
69
|
const { data, error, isLoading } = useQuery(async () => {
|
|
50
70
|
return queryMutationsData(variant, sequenceType, lapis);
|
|
51
71
|
}, [variant, sequenceType, lapis]);
|
|
52
72
|
|
|
53
73
|
if (isLoading) {
|
|
54
|
-
return
|
|
55
|
-
<Headline heading={headline}>
|
|
56
|
-
<LoadingDisplay />
|
|
57
|
-
</Headline>
|
|
58
|
-
);
|
|
74
|
+
return <LoadingDisplay />;
|
|
59
75
|
}
|
|
60
76
|
|
|
61
77
|
if (error !== null) {
|
|
62
|
-
return
|
|
63
|
-
<Headline heading={headline}>
|
|
64
|
-
<ErrorDisplay error={error} />
|
|
65
|
-
</Headline>
|
|
66
|
-
);
|
|
78
|
+
return <ErrorDisplay error={error} />;
|
|
67
79
|
}
|
|
68
80
|
|
|
69
81
|
if (data === null) {
|
|
70
|
-
return
|
|
71
|
-
<Headline heading={headline}>
|
|
72
|
-
<NoDataDisplay />
|
|
73
|
-
</Headline>
|
|
74
|
-
);
|
|
82
|
+
return <NoDataDisplay />;
|
|
75
83
|
}
|
|
76
84
|
|
|
77
|
-
return
|
|
78
|
-
<ResizeContainer size={size} defaultSize={{ height: '700px', width: '100%' }}>
|
|
79
|
-
<Headline heading={headline}>
|
|
80
|
-
<MutationsTabs mutationsData={data} sequenceType={sequenceType} views={views} />
|
|
81
|
-
</Headline>
|
|
82
|
-
</ResizeContainer>
|
|
83
|
-
);
|
|
85
|
+
return <MutationsTabs mutationsData={data} sequenceType={sequenceType} views={views} />;
|
|
84
86
|
};
|
|
85
87
|
|
|
86
88
|
type MutationTabsProps = {
|
|
@@ -29,7 +29,8 @@ export default {
|
|
|
29
29
|
options: ['wilson'],
|
|
30
30
|
control: { type: 'check' },
|
|
31
31
|
},
|
|
32
|
-
|
|
32
|
+
width: { control: 'text' },
|
|
33
|
+
height: { control: 'text' },
|
|
33
34
|
headline: { control: 'text' },
|
|
34
35
|
},
|
|
35
36
|
};
|
|
@@ -44,7 +45,8 @@ const Template = {
|
|
|
44
45
|
smoothingWindow={args.smoothingWindow}
|
|
45
46
|
views={args.views}
|
|
46
47
|
confidenceIntervalMethods={args.confidenceIntervalMethods}
|
|
47
|
-
|
|
48
|
+
width={args.width}
|
|
49
|
+
height={args.height}
|
|
48
50
|
headline={args.headline}
|
|
49
51
|
/>
|
|
50
52
|
</LapisUrlContext.Provider>
|
|
@@ -55,15 +57,16 @@ export const TwoVariants = {
|
|
|
55
57
|
...Template,
|
|
56
58
|
args: {
|
|
57
59
|
numerator: [
|
|
58
|
-
{ displayName: 'EG', country: 'USA', pangoLineage: 'EG*', dateFrom: '2023-01-01' },
|
|
59
|
-
{ displayName: 'JN.1', country: 'USA', pangoLineage: 'JN.1*', dateFrom: '2023-01-01' },
|
|
60
|
+
{ displayName: 'EG', lapisFilter: { country: 'USA', pangoLineage: 'EG*', dateFrom: '2023-01-01' } },
|
|
61
|
+
{ displayName: 'JN.1', lapisFilter: { country: 'USA', pangoLineage: 'JN.1*', dateFrom: '2023-01-01' } },
|
|
60
62
|
],
|
|
61
63
|
denominator: { country: 'USA', dateFrom: '2023-01-01' },
|
|
62
64
|
granularity: 'month',
|
|
63
65
|
smoothingWindow: 0,
|
|
64
66
|
views: ['bar', 'line', 'bubble', 'table'],
|
|
65
67
|
confidenceIntervalMethods: ['wilson'],
|
|
66
|
-
|
|
68
|
+
width: '100%',
|
|
69
|
+
height: '700px',
|
|
67
70
|
headline: 'Prevalence over time',
|
|
68
71
|
},
|
|
69
72
|
parameters: {
|
|
@@ -124,13 +127,17 @@ export const TwoVariants = {
|
|
|
124
127
|
export const OneVariant = {
|
|
125
128
|
...Template,
|
|
126
129
|
args: {
|
|
127
|
-
numerator: {
|
|
130
|
+
numerator: {
|
|
131
|
+
displayName: 'EG',
|
|
132
|
+
lapisFilter: { country: 'USA', pangoLineage: 'BA.2.86*', dateFrom: '2023-10-01' },
|
|
133
|
+
},
|
|
128
134
|
denominator: { country: 'USA', dateFrom: '2023-10-01' },
|
|
129
135
|
granularity: 'day',
|
|
130
136
|
smoothingWindow: 7,
|
|
131
137
|
views: ['bar', 'line', 'bubble', 'table'],
|
|
132
138
|
confidenceIntervalMethods: ['wilson'],
|
|
133
|
-
|
|
139
|
+
width: '100%',
|
|
140
|
+
height: '700px',
|
|
134
141
|
headline: 'Prevalence over time',
|
|
135
142
|
},
|
|
136
143
|
parameters: {
|
|
@@ -7,16 +7,17 @@ import PrevalenceOverTimeBubbleChart from './prevalence-over-time-bubble-chart';
|
|
|
7
7
|
import PrevalenceOverTimeLineChart from './prevalence-over-time-line-chart';
|
|
8
8
|
import PrevalenceOverTimeTable from './prevalence-over-time-table';
|
|
9
9
|
import { type PrevalenceOverTimeData, queryPrevalenceOverTime } from '../../query/queryPrevalenceOverTime';
|
|
10
|
-
import { type NamedLapisFilter, type TemporalGranularity } from '../../types';
|
|
10
|
+
import { type LapisFilter, type NamedLapisFilter, type TemporalGranularity } from '../../types';
|
|
11
11
|
import { LapisUrlContext } from '../LapisUrlContext';
|
|
12
12
|
import { ConfidenceIntervalSelector } from '../components/confidence-interval-selector';
|
|
13
13
|
import { CsvDownloadButton } from '../components/csv-download-button';
|
|
14
|
+
import { ErrorBoundary } from '../components/error-boundary';
|
|
14
15
|
import { ErrorDisplay } from '../components/error-display';
|
|
15
16
|
import Headline from '../components/headline';
|
|
16
17
|
import Info, { InfoHeadline1, InfoParagraph } from '../components/info';
|
|
17
18
|
import { LoadingDisplay } from '../components/loading-display';
|
|
18
19
|
import { NoDataDisplay } from '../components/no-data-display';
|
|
19
|
-
import { ResizeContainer
|
|
20
|
+
import { ResizeContainer } from '../components/resize-container';
|
|
20
21
|
import { ScalingSelector } from '../components/scaling-selector';
|
|
21
22
|
import Tabs from '../components/tabs';
|
|
22
23
|
import { type ConfidenceIntervalMethod } from '../shared/charts/confideceInterval';
|
|
@@ -25,15 +26,19 @@ import { useQuery } from '../useQuery';
|
|
|
25
26
|
|
|
26
27
|
export type View = 'bar' | 'line' | 'bubble' | 'table';
|
|
27
28
|
|
|
28
|
-
export interface PrevalenceOverTimeProps {
|
|
29
|
+
export interface PrevalenceOverTimeProps extends PrevalenceOverTimeInnerProps {
|
|
30
|
+
width: string;
|
|
31
|
+
height: string;
|
|
32
|
+
headline?: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface PrevalenceOverTimeInnerProps {
|
|
29
36
|
numerator: NamedLapisFilter | NamedLapisFilter[];
|
|
30
|
-
denominator:
|
|
37
|
+
denominator: LapisFilter;
|
|
31
38
|
granularity: TemporalGranularity;
|
|
32
39
|
smoothingWindow: number;
|
|
33
40
|
views: View[];
|
|
34
41
|
confidenceIntervalMethods: ConfidenceIntervalMethod[];
|
|
35
|
-
size?: Size;
|
|
36
|
-
headline?: string;
|
|
37
42
|
}
|
|
38
43
|
|
|
39
44
|
export const PrevalenceOverTime: FunctionComponent<PrevalenceOverTimeProps> = ({
|
|
@@ -43,8 +48,37 @@ export const PrevalenceOverTime: FunctionComponent<PrevalenceOverTimeProps> = ({
|
|
|
43
48
|
smoothingWindow,
|
|
44
49
|
views,
|
|
45
50
|
confidenceIntervalMethods,
|
|
46
|
-
|
|
51
|
+
width,
|
|
52
|
+
height,
|
|
47
53
|
headline = 'Prevalence over time',
|
|
54
|
+
}) => {
|
|
55
|
+
const size = { height, width };
|
|
56
|
+
|
|
57
|
+
return (
|
|
58
|
+
<ErrorBoundary size={size} headline={headline}>
|
|
59
|
+
<ResizeContainer size={size}>
|
|
60
|
+
<Headline heading={headline}>
|
|
61
|
+
<PrevalenceOverTimeInner
|
|
62
|
+
numerator={numerator}
|
|
63
|
+
denominator={denominator}
|
|
64
|
+
granularity={granularity}
|
|
65
|
+
smoothingWindow={smoothingWindow}
|
|
66
|
+
views={views}
|
|
67
|
+
confidenceIntervalMethods={confidenceIntervalMethods}
|
|
68
|
+
/>
|
|
69
|
+
</Headline>
|
|
70
|
+
</ResizeContainer>
|
|
71
|
+
</ErrorBoundary>
|
|
72
|
+
);
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
export const PrevalenceOverTimeInner: FunctionComponent<PrevalenceOverTimeInnerProps> = ({
|
|
76
|
+
numerator,
|
|
77
|
+
denominator,
|
|
78
|
+
granularity,
|
|
79
|
+
smoothingWindow,
|
|
80
|
+
views,
|
|
81
|
+
confidenceIntervalMethods,
|
|
48
82
|
}) => {
|
|
49
83
|
const lapis = useContext(LapisUrlContext);
|
|
50
84
|
|
|
@@ -54,40 +88,24 @@ export const PrevalenceOverTime: FunctionComponent<PrevalenceOverTimeProps> = ({
|
|
|
54
88
|
);
|
|
55
89
|
|
|
56
90
|
if (isLoading) {
|
|
57
|
-
return
|
|
58
|
-
<Headline heading={headline}>
|
|
59
|
-
<LoadingDisplay />
|
|
60
|
-
</Headline>
|
|
61
|
-
);
|
|
91
|
+
return <LoadingDisplay />;
|
|
62
92
|
}
|
|
63
93
|
|
|
64
94
|
if (error !== null) {
|
|
65
|
-
return
|
|
66
|
-
<Headline heading={headline}>
|
|
67
|
-
<ErrorDisplay error={error} />
|
|
68
|
-
</Headline>
|
|
69
|
-
);
|
|
95
|
+
return <ErrorDisplay error={error} />;
|
|
70
96
|
}
|
|
71
97
|
|
|
72
98
|
if (data === null) {
|
|
73
|
-
return
|
|
74
|
-
<Headline heading={headline}>
|
|
75
|
-
<NoDataDisplay />
|
|
76
|
-
</Headline>
|
|
77
|
-
);
|
|
99
|
+
return <NoDataDisplay />;
|
|
78
100
|
}
|
|
79
101
|
|
|
80
102
|
return (
|
|
81
|
-
<
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
confidenceIntervalMethods={confidenceIntervalMethods}
|
|
88
|
-
/>
|
|
89
|
-
</Headline>
|
|
90
|
-
</ResizeContainer>
|
|
103
|
+
<PrevalenceOverTimeTabs
|
|
104
|
+
views={views}
|
|
105
|
+
data={data}
|
|
106
|
+
granularity={granularity}
|
|
107
|
+
confidenceIntervalMethods={confidenceIntervalMethods}
|
|
108
|
+
/>
|
|
91
109
|
);
|
|
92
110
|
};
|
|
93
111
|
|
|
@@ -18,7 +18,8 @@ export default {
|
|
|
18
18
|
options: ['line'],
|
|
19
19
|
control: { type: 'check' },
|
|
20
20
|
},
|
|
21
|
-
|
|
21
|
+
width: { control: 'text' },
|
|
22
|
+
height: { control: 'text' },
|
|
22
23
|
headline: { control: 'text' },
|
|
23
24
|
},
|
|
24
25
|
};
|
|
@@ -31,7 +32,8 @@ export const Primary = {
|
|
|
31
32
|
denominator={args.denominator}
|
|
32
33
|
generationTime={args.generationTime}
|
|
33
34
|
views={args.views}
|
|
34
|
-
|
|
35
|
+
width={args.width}
|
|
36
|
+
height={args.height}
|
|
35
37
|
headline={args.headline}
|
|
36
38
|
/>
|
|
37
39
|
</LapisUrlContext.Provider>
|
|
@@ -41,7 +43,8 @@ export const Primary = {
|
|
|
41
43
|
denominator: { country: 'Switzerland', dateFrom: '2020-12-01', dateTo: '2021-03-01' },
|
|
42
44
|
generationTime: 7,
|
|
43
45
|
views: ['line'],
|
|
44
|
-
|
|
46
|
+
width: '100%',
|
|
47
|
+
height: '700px',
|
|
45
48
|
headline: 'Relative growth advantage',
|
|
46
49
|
},
|
|
47
50
|
parameters: {
|