@genspectrum/dashboard-components 0.6.19 → 0.7.1
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 +18 -18
- package/dist/assets/mutationOverTimeWorker-BOCXtKzd.js.map +1 -0
- package/dist/dashboard-components.js +296 -302
- package/dist/dashboard-components.js.map +1 -1
- package/dist/genspectrum-components.d.ts +98 -48
- package/package.json +1 -3
- package/src/index.ts +1 -0
- package/src/preact/aggregatedData/aggregate.tsx +41 -33
- package/src/preact/dateRangeSelector/computeInitialValues.spec.ts +53 -38
- package/src/preact/dateRangeSelector/computeInitialValues.ts +17 -23
- package/src/preact/dateRangeSelector/date-range-selector.stories.tsx +46 -32
- package/src/preact/dateRangeSelector/date-range-selector.tsx +24 -26
- package/src/preact/dateRangeSelector/dateRangeOption.ts +65 -0
- package/src/preact/dateRangeSelector/selectableOptions.ts +17 -66
- package/src/preact/mutationComparison/mutation-comparison.tsx +32 -34
- package/src/preact/mutations/mutations.tsx +63 -56
- package/src/preact/mutationsOverTime/MutationOverTimeData.ts +20 -0
- package/src/preact/mutationsOverTime/getFilteredMutationsOverTime.spec.ts +2 -3
- package/src/preact/mutationsOverTime/getFilteredMutationsOverTimeData.ts +2 -2
- package/src/preact/mutationsOverTime/mutations-over-time-grid.tsx +3 -3
- package/src/preact/mutationsOverTime/mutations-over-time.tsx +40 -43
- package/src/preact/numberSequencesOverTime/number-sequences-over-time.tsx +46 -64
- package/src/preact/relativeGrowthAdvantage/relative-growth-advantage.tsx +29 -36
- package/src/query/queryMutationsOverTime.ts +3 -5
- package/src/utils/map2d.spec.ts +52 -13
- package/src/utils/map2d.ts +3 -4
- package/src/web-components/input/gs-date-range-selector.stories.ts +16 -28
- package/src/web-components/input/gs-date-range-selector.tsx +17 -32
- package/standalone-bundle/dashboard-components.js +14322 -15115
- package/standalone-bundle/dashboard-components.js.map +1 -1
- package/dist/assets/mutationOverTimeWorker-BdzqDqvO.js.map +0 -1
|
@@ -18,7 +18,7 @@ import { CsvDownloadButton } from '../components/csv-download-button';
|
|
|
18
18
|
import { ErrorBoundary } from '../components/error-boundary';
|
|
19
19
|
import { ErrorDisplay } from '../components/error-display';
|
|
20
20
|
import { Fullscreen } from '../components/fullscreen';
|
|
21
|
-
import Info, { InfoHeadline1, InfoHeadline2, InfoLink, InfoParagraph } from '../components/info';
|
|
21
|
+
import Info, { InfoComponentCode, InfoHeadline1, InfoHeadline2, InfoLink, InfoParagraph } from '../components/info';
|
|
22
22
|
import { LoadingDisplay } from '../components/loading-display';
|
|
23
23
|
import { type DisplayedMutationType, MutationTypeSelector } from '../components/mutation-type-selector';
|
|
24
24
|
import { NoDataDisplay } from '../components/no-data-display';
|
|
@@ -31,37 +31,32 @@ import { useQuery } from '../useQuery';
|
|
|
31
31
|
|
|
32
32
|
export type View = 'table' | 'grid' | 'insertions';
|
|
33
33
|
|
|
34
|
-
export interface
|
|
34
|
+
export interface MutationsProps {
|
|
35
|
+
width: string;
|
|
36
|
+
height: string;
|
|
35
37
|
lapisFilter: LapisFilter;
|
|
36
38
|
sequenceType: SequenceType;
|
|
37
39
|
views: View[];
|
|
38
40
|
pageSize: boolean | number;
|
|
39
41
|
}
|
|
40
42
|
|
|
41
|
-
export
|
|
42
|
-
width
|
|
43
|
-
height: string;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export const Mutations: FunctionComponent<MutationsProps> = ({ width, height, ...innerProps }) => {
|
|
43
|
+
export const Mutations: FunctionComponent<MutationsProps> = (componentProps) => {
|
|
44
|
+
const { width, height } = componentProps;
|
|
47
45
|
const size = { height, width };
|
|
48
46
|
|
|
49
47
|
return (
|
|
50
48
|
<ErrorBoundary size={size}>
|
|
51
49
|
<ResizeContainer size={size}>
|
|
52
|
-
<MutationsInner {...
|
|
50
|
+
<MutationsInner {...componentProps} />
|
|
53
51
|
</ResizeContainer>
|
|
54
52
|
</ErrorBoundary>
|
|
55
53
|
);
|
|
56
54
|
};
|
|
57
55
|
|
|
58
|
-
export const MutationsInner: FunctionComponent<
|
|
59
|
-
lapisFilter,
|
|
60
|
-
sequenceType,
|
|
61
|
-
views,
|
|
62
|
-
pageSize,
|
|
63
|
-
}) => {
|
|
56
|
+
export const MutationsInner: FunctionComponent<MutationsProps> = (componentProps) => {
|
|
64
57
|
const lapis = useContext(LapisUrlContext);
|
|
58
|
+
const { lapisFilter, sequenceType } = componentProps;
|
|
59
|
+
|
|
65
60
|
const { data, error, isLoading } = useQuery(async () => {
|
|
66
61
|
return queryMutationsData(lapisFilter, sequenceType, lapis);
|
|
67
62
|
}, [lapisFilter, sequenceType, lapis]);
|
|
@@ -78,20 +73,18 @@ export const MutationsInner: FunctionComponent<MutationsInnerProps> = ({
|
|
|
78
73
|
return <NoDataDisplay />;
|
|
79
74
|
}
|
|
80
75
|
|
|
81
|
-
return <MutationsTabs mutationsData={data}
|
|
76
|
+
return <MutationsTabs mutationsData={data} originalComponentProps={componentProps} />;
|
|
82
77
|
};
|
|
83
78
|
|
|
84
79
|
type MutationTabsProps = {
|
|
85
80
|
mutationsData: { insertions: InsertionEntry[]; substitutionsOrDeletions: SubstitutionOrDeletionEntry[] };
|
|
86
|
-
|
|
87
|
-
views: View[];
|
|
88
|
-
pageSize: boolean | number;
|
|
81
|
+
originalComponentProps: MutationsProps;
|
|
89
82
|
};
|
|
90
83
|
|
|
91
|
-
const MutationsTabs: FunctionComponent<MutationTabsProps> = ({ mutationsData,
|
|
84
|
+
const MutationsTabs: FunctionComponent<MutationTabsProps> = ({ mutationsData, originalComponentProps }) => {
|
|
92
85
|
const [proportionInterval, setProportionInterval] = useState({ min: 0.05, max: 1 });
|
|
93
86
|
|
|
94
|
-
const [displayedSegments, setDisplayedSegments] = useDisplayedSegments(sequenceType);
|
|
87
|
+
const [displayedSegments, setDisplayedSegments] = useDisplayedSegments(originalComponentProps.sequenceType);
|
|
95
88
|
const [displayedMutationTypes, setDisplayedMutationTypes] = useState<DisplayedMutationType[]>([
|
|
96
89
|
{ label: 'Substitutions', checked: true, type: 'substitution' },
|
|
97
90
|
{ label: 'Deletions', checked: true, type: 'deletion' },
|
|
@@ -108,7 +101,7 @@ const MutationsTabs: FunctionComponent<MutationTabsProps> = ({ mutationsData, se
|
|
|
108
101
|
<MutationsTable
|
|
109
102
|
data={filteredData.tableData}
|
|
110
103
|
proportionInterval={proportionInterval}
|
|
111
|
-
pageSize={pageSize}
|
|
104
|
+
pageSize={originalComponentProps.pageSize}
|
|
112
105
|
/>
|
|
113
106
|
),
|
|
114
107
|
};
|
|
@@ -118,21 +111,23 @@ const MutationsTabs: FunctionComponent<MutationTabsProps> = ({ mutationsData, se
|
|
|
118
111
|
content: (
|
|
119
112
|
<MutationsGrid
|
|
120
113
|
data={filteredData.gridData}
|
|
121
|
-
sequenceType={sequenceType}
|
|
114
|
+
sequenceType={originalComponentProps.sequenceType}
|
|
122
115
|
proportionInterval={proportionInterval}
|
|
123
|
-
pageSize={pageSize}
|
|
116
|
+
pageSize={originalComponentProps.pageSize}
|
|
124
117
|
/>
|
|
125
118
|
),
|
|
126
119
|
};
|
|
127
120
|
case 'insertions':
|
|
128
121
|
return {
|
|
129
122
|
title: 'Insertions',
|
|
130
|
-
content:
|
|
123
|
+
content: (
|
|
124
|
+
<InsertionsTable data={filteredData.insertions} pageSize={originalComponentProps.pageSize} />
|
|
125
|
+
),
|
|
131
126
|
};
|
|
132
127
|
}
|
|
133
128
|
};
|
|
134
129
|
|
|
135
|
-
const tabs = views.map((view) => getTab(view));
|
|
130
|
+
const tabs = originalComponentProps.views.map((view) => getTab(view));
|
|
136
131
|
|
|
137
132
|
const toolbar = (activeTab: string) => (
|
|
138
133
|
<Toolbar
|
|
@@ -144,6 +139,7 @@ const MutationsTabs: FunctionComponent<MutationTabsProps> = ({ mutationsData, se
|
|
|
144
139
|
filteredData={filteredData}
|
|
145
140
|
proportionInterval={proportionInterval}
|
|
146
141
|
setProportionInterval={setProportionInterval}
|
|
142
|
+
originalComponentProps={originalComponentProps}
|
|
147
143
|
/>
|
|
148
144
|
);
|
|
149
145
|
|
|
@@ -159,6 +155,7 @@ type ToolbarProps = {
|
|
|
159
155
|
filteredData: { tableData: SubstitutionOrDeletionEntry[]; insertions: InsertionEntry[] };
|
|
160
156
|
proportionInterval: ProportionInterval;
|
|
161
157
|
setProportionInterval: Dispatch<StateUpdater<ProportionInterval>>;
|
|
158
|
+
originalComponentProps: MutationsProps;
|
|
162
159
|
};
|
|
163
160
|
|
|
164
161
|
const Toolbar: FunctionComponent<ToolbarProps> = ({
|
|
@@ -170,6 +167,7 @@ const Toolbar: FunctionComponent<ToolbarProps> = ({
|
|
|
170
167
|
filteredData,
|
|
171
168
|
proportionInterval,
|
|
172
169
|
setProportionInterval,
|
|
170
|
+
originalComponentProps,
|
|
173
171
|
}) => {
|
|
174
172
|
return (
|
|
175
173
|
<>
|
|
@@ -208,38 +206,47 @@ const Toolbar: FunctionComponent<ToolbarProps> = ({
|
|
|
208
206
|
filename='insertions.csv'
|
|
209
207
|
/>
|
|
210
208
|
)}
|
|
211
|
-
<MutationsInfo />
|
|
209
|
+
<MutationsInfo originalComponentProps={originalComponentProps} />
|
|
212
210
|
<Fullscreen />
|
|
213
211
|
</>
|
|
214
212
|
);
|
|
215
213
|
};
|
|
216
214
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
<
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
<
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
215
|
+
type MutationsInfoProps = {
|
|
216
|
+
originalComponentProps: MutationsProps;
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
const MutationsInfo: FunctionComponent<MutationsInfoProps> = ({ originalComponentProps }) => {
|
|
220
|
+
const lapis = useContext(LapisUrlContext);
|
|
221
|
+
|
|
222
|
+
return (
|
|
223
|
+
<Info>
|
|
224
|
+
<InfoHeadline1>Mutations</InfoHeadline1>
|
|
225
|
+
<InfoParagraph>
|
|
226
|
+
This shows mutations of a variant. There are three types of mutations:{' '}
|
|
227
|
+
<InfoLink href='https://www.genome.gov/genetics-glossary/Substitution'>substitutions</InfoLink>,{' '}
|
|
228
|
+
<InfoLink href='https://www.genome.gov/genetics-glossary/Deletion'>deletions</InfoLink> and{' '}
|
|
229
|
+
<InfoLink href='https://www.genome.gov/genetics-glossary/Insertion'>insertions</InfoLink>.
|
|
230
|
+
</InfoParagraph>
|
|
231
|
+
<InfoHeadline2>Proportion calculation</InfoHeadline2>
|
|
232
|
+
<InfoParagraph>
|
|
233
|
+
The proportion of a mutation is calculated by dividing the number of sequences with the mutation by the
|
|
234
|
+
total number of sequences with a non-ambiguous symbol at the position.
|
|
235
|
+
</InfoParagraph>
|
|
236
|
+
<InfoParagraph>
|
|
237
|
+
<b>Example:</b> Assume we look at nucleotide mutations at position 5 where the reference has a T and
|
|
238
|
+
assume there are 10 sequences in total:
|
|
239
|
+
<ul className='list-disc list-inside ml-2'>
|
|
240
|
+
<li>3 sequences have a C,</li>
|
|
241
|
+
<li>2 sequences have a T,</li>
|
|
242
|
+
<li>1 sequence has a G,</li>
|
|
243
|
+
<li>3 sequences have an N,</li>
|
|
244
|
+
<li>1 sequence has a Y (which means T or C),</li>
|
|
245
|
+
</ul>
|
|
246
|
+
then the proportion of the T5C mutation is 50%. The 4 sequences that have an N or Y are excluded from
|
|
247
|
+
the calculation.
|
|
248
|
+
</InfoParagraph>
|
|
249
|
+
<InfoComponentCode componentName='mutations' params={originalComponentProps} lapisUrl={lapis} />
|
|
250
|
+
</Info>
|
|
251
|
+
);
|
|
252
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type MutationOverTimeMutationValue,
|
|
3
|
+
serializeSubstitutionOrDeletion,
|
|
4
|
+
serializeTemporal,
|
|
5
|
+
} from '../../query/queryMutationsOverTime';
|
|
6
|
+
import { type Map2d, Map2dBase, type Map2DContents } from '../../utils/map2d';
|
|
7
|
+
import type { Deletion, Substitution } from '../../utils/mutations';
|
|
8
|
+
import type { Temporal } from '../../utils/temporalClass';
|
|
9
|
+
|
|
10
|
+
export type MutationOverTimeDataMap = Map2d<Substitution | Deletion, Temporal, MutationOverTimeMutationValue>;
|
|
11
|
+
|
|
12
|
+
export class BaseMutationOverTimeDataMap extends Map2dBase<
|
|
13
|
+
Substitution | Deletion,
|
|
14
|
+
Temporal,
|
|
15
|
+
MutationOverTimeMutationValue
|
|
16
|
+
> {
|
|
17
|
+
constructor(initialContent?: Map2DContents<Substitution | Deletion, Temporal, MutationOverTimeMutationValue>) {
|
|
18
|
+
super(serializeSubstitutionOrDeletion, serializeTemporal, initialContent);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest';
|
|
2
2
|
|
|
3
|
+
import { BaseMutationOverTimeDataMap } from './MutationOverTimeData';
|
|
3
4
|
import { getFilteredMutationOverTimeData } from './getFilteredMutationsOverTimeData';
|
|
4
|
-
import { type MutationOverTimeMutationValue } from '../../query/queryMutationsOverTime';
|
|
5
5
|
import { type DeletionEntry, type SubstitutionEntry } from '../../types';
|
|
6
|
-
import { Map2dBase } from '../../utils/map2d';
|
|
7
6
|
import { type Deletion, type Substitution } from '../../utils/mutations';
|
|
8
7
|
import { type TemporalClass } from '../../utils/temporalClass';
|
|
9
8
|
import { yearMonthDay } from '../../utils/temporalTestHelpers';
|
|
@@ -194,7 +193,7 @@ describe('getFilteredMutationOverTimeData', () => {
|
|
|
194
193
|
mutationEntries: (SubstitutionEntry<Substitution> | DeletionEntry<Deletion>)[],
|
|
195
194
|
temporals: TemporalClass[] = [someTemporal, anotherTemporal],
|
|
196
195
|
) {
|
|
197
|
-
const data = new
|
|
196
|
+
const data = new BaseMutationOverTimeDataMap();
|
|
198
197
|
|
|
199
198
|
temporals.forEach((temporal) => {
|
|
200
199
|
mutationEntries.forEach((entry) => {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type MutationOverTimeDataMap } from './MutationOverTimeData';
|
|
2
2
|
import { type SubstitutionOrDeletionEntry } from '../../types';
|
|
3
3
|
import { Map2dView } from '../../utils/map2d';
|
|
4
4
|
import type { Deletion, Substitution } from '../../utils/mutations';
|
|
@@ -6,7 +6,7 @@ import type { DisplayedMutationType } from '../components/mutation-type-selector
|
|
|
6
6
|
import type { DisplayedSegment } from '../components/segment-selector';
|
|
7
7
|
|
|
8
8
|
export function getFilteredMutationOverTimeData(
|
|
9
|
-
data:
|
|
9
|
+
data: MutationOverTimeDataMap,
|
|
10
10
|
overallMutationData: SubstitutionOrDeletionEntry<Substitution, Deletion>[],
|
|
11
11
|
displayedSegments: DisplayedSegment[],
|
|
12
12
|
displayedMutationTypes: DisplayedMutationType[],
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { Fragment, type FunctionComponent, type RefObject } from 'preact';
|
|
2
2
|
import { useEffect, useRef, useState } from 'preact/hooks';
|
|
3
3
|
|
|
4
|
-
import { type
|
|
4
|
+
import { type MutationOverTimeDataMap } from './MutationOverTimeData';
|
|
5
5
|
import { type MutationOverTimeMutationValue } from '../../query/queryMutationsOverTime';
|
|
6
6
|
import { type Deletion, type Substitution } from '../../utils/mutations';
|
|
7
|
-
import {
|
|
7
|
+
import { type Temporal, type TemporalClass, toTemporalClass, YearMonthDayClass } from '../../utils/temporalClass';
|
|
8
8
|
import { type ColorScale, getColorWithingScale, getTextColorForScale } from '../components/color-scale-selector';
|
|
9
9
|
import Tooltip, { type TooltipPosition } from '../components/tooltip';
|
|
10
10
|
import { formatProportion } from '../shared/table/formatProportion';
|
|
11
11
|
|
|
12
12
|
export interface MutationsOverTimeGridProps {
|
|
13
|
-
data:
|
|
13
|
+
data: MutationOverTimeDataMap;
|
|
14
14
|
colorScale: ColorScale;
|
|
15
15
|
}
|
|
16
16
|
|
|
@@ -3,24 +3,19 @@ import { type Dispatch, type StateUpdater, useContext, useMemo, useState } from
|
|
|
3
3
|
|
|
4
4
|
// @ts-expect-error -- uses subpath imports and vite worker import
|
|
5
5
|
import MutationOverTimeWorker from '#mutationOverTime?worker&inline';
|
|
6
|
+
import { BaseMutationOverTimeDataMap, type MutationOverTimeDataMap } from './MutationOverTimeData';
|
|
6
7
|
import { getFilteredMutationOverTimeData } from './getFilteredMutationsOverTimeData';
|
|
7
8
|
import { type MutationOverTimeWorkerResponse } from './mutationOverTimeWorker';
|
|
8
9
|
import MutationsOverTimeGrid from './mutations-over-time-grid';
|
|
9
|
-
import {
|
|
10
|
-
type MutationOverTimeMutationValue,
|
|
11
|
-
type MutationOverTimeQuery,
|
|
12
|
-
serializeSubstitutionOrDeletion,
|
|
13
|
-
serializeTemporal,
|
|
14
|
-
} from '../../query/queryMutationsOverTime';
|
|
10
|
+
import { type MutationOverTimeQuery } from '../../query/queryMutationsOverTime';
|
|
15
11
|
import {
|
|
16
12
|
type LapisFilter,
|
|
17
13
|
type SequenceType,
|
|
18
14
|
type SubstitutionOrDeletionEntry,
|
|
19
15
|
type TemporalGranularity,
|
|
20
16
|
} from '../../types';
|
|
21
|
-
import { type Map2d, Map2dBase } from '../../utils/map2d';
|
|
22
17
|
import { type Deletion, type Substitution } from '../../utils/mutations';
|
|
23
|
-
import {
|
|
18
|
+
import { toTemporalClass } from '../../utils/temporalClass';
|
|
24
19
|
import { LapisUrlContext } from '../LapisUrlContext';
|
|
25
20
|
import { type ColorScale } from '../components/color-scale-selector';
|
|
26
21
|
import { ColorScaleSelectorDropdown } from '../components/color-scale-selector-dropdown';
|
|
@@ -28,7 +23,7 @@ import { CsvDownloadButton } from '../components/csv-download-button';
|
|
|
28
23
|
import { ErrorBoundary } from '../components/error-boundary';
|
|
29
24
|
import { ErrorDisplay } from '../components/error-display';
|
|
30
25
|
import { Fullscreen } from '../components/fullscreen';
|
|
31
|
-
import Info from '../components/info';
|
|
26
|
+
import Info, { InfoComponentCode, InfoHeadline1, InfoParagraph } from '../components/info';
|
|
32
27
|
import { LoadingDisplay } from '../components/loading-display';
|
|
33
28
|
import { type DisplayedMutationType, MutationTypeSelector } from '../components/mutation-type-selector';
|
|
34
29
|
import { NoDataDisplay } from '../components/no-data-display';
|
|
@@ -41,7 +36,9 @@ import { useWebWorker } from '../webWorkers/useWebWorker';
|
|
|
41
36
|
|
|
42
37
|
export type View = 'grid';
|
|
43
38
|
|
|
44
|
-
export interface
|
|
39
|
+
export interface MutationsOverTimeProps {
|
|
40
|
+
width: string;
|
|
41
|
+
height: string;
|
|
45
42
|
lapisFilter: LapisFilter;
|
|
46
43
|
sequenceType: SequenceType;
|
|
47
44
|
views: View[];
|
|
@@ -49,31 +46,22 @@ export interface MutationsOverTimeInnerProps {
|
|
|
49
46
|
lapisDateField: string;
|
|
50
47
|
}
|
|
51
48
|
|
|
52
|
-
export
|
|
53
|
-
width
|
|
54
|
-
height: string;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export const MutationsOverTime: FunctionComponent<MutationsOverTimeProps> = ({ width, height, ...innerProps }) => {
|
|
49
|
+
export const MutationsOverTime: FunctionComponent<MutationsOverTimeProps> = (componentProps) => {
|
|
50
|
+
const { width, height } = componentProps;
|
|
58
51
|
const size = { height, width };
|
|
59
52
|
|
|
60
53
|
return (
|
|
61
54
|
<ErrorBoundary size={size}>
|
|
62
55
|
<ResizeContainer size={size}>
|
|
63
|
-
<MutationsOverTimeInner {...
|
|
56
|
+
<MutationsOverTimeInner {...componentProps} />
|
|
64
57
|
</ResizeContainer>
|
|
65
58
|
</ErrorBoundary>
|
|
66
59
|
);
|
|
67
60
|
};
|
|
68
61
|
|
|
69
|
-
export const MutationsOverTimeInner: FunctionComponent<
|
|
70
|
-
lapisFilter,
|
|
71
|
-
sequenceType,
|
|
72
|
-
views,
|
|
73
|
-
granularity,
|
|
74
|
-
lapisDateField,
|
|
75
|
-
}) => {
|
|
62
|
+
export const MutationsOverTimeInner: FunctionComponent<MutationsOverTimeProps> = (componentProps) => {
|
|
76
63
|
const lapis = useContext(LapisUrlContext);
|
|
64
|
+
const { lapisFilter, sequenceType, granularity, lapisDateField } = componentProps;
|
|
77
65
|
|
|
78
66
|
const { data, error, isLoading } = useWebWorker<MutationOverTimeQuery, MutationOverTimeWorkerResponse>(
|
|
79
67
|
{
|
|
@@ -99,40 +87,31 @@ export const MutationsOverTimeInner: FunctionComponent<MutationsOverTimeInnerPro
|
|
|
99
87
|
}
|
|
100
88
|
|
|
101
89
|
const { overallMutationData, mutationOverTimeSerialized } = data;
|
|
102
|
-
const mutationOverTimeData = new
|
|
103
|
-
serializeSubstitutionOrDeletion,
|
|
104
|
-
serializeTemporal,
|
|
105
|
-
mutationOverTimeSerialized,
|
|
106
|
-
);
|
|
90
|
+
const mutationOverTimeData = new BaseMutationOverTimeDataMap(mutationOverTimeSerialized);
|
|
107
91
|
return (
|
|
108
92
|
<MutationsOverTimeTabs
|
|
109
93
|
overallMutationData={overallMutationData}
|
|
110
94
|
mutationOverTimeData={mutationOverTimeData}
|
|
111
|
-
|
|
112
|
-
views={views}
|
|
95
|
+
originalComponentProps={componentProps}
|
|
113
96
|
/>
|
|
114
97
|
);
|
|
115
98
|
};
|
|
116
99
|
|
|
117
|
-
export type MutationOverTimeData = Map2d<Substitution | Deletion, Temporal, MutationOverTimeMutationValue>;
|
|
118
|
-
|
|
119
100
|
type MutationOverTimeTabsProps = {
|
|
120
|
-
mutationOverTimeData:
|
|
121
|
-
|
|
122
|
-
views: View[];
|
|
101
|
+
mutationOverTimeData: BaseMutationOverTimeDataMap;
|
|
102
|
+
originalComponentProps: MutationsOverTimeProps;
|
|
123
103
|
overallMutationData: SubstitutionOrDeletionEntry<Substitution, Deletion>[];
|
|
124
104
|
};
|
|
125
105
|
|
|
126
106
|
const MutationsOverTimeTabs: FunctionComponent<MutationOverTimeTabsProps> = ({
|
|
127
107
|
mutationOverTimeData,
|
|
128
|
-
|
|
129
|
-
views,
|
|
108
|
+
originalComponentProps,
|
|
130
109
|
overallMutationData,
|
|
131
110
|
}) => {
|
|
132
111
|
const [proportionInterval, setProportionInterval] = useState({ min: 0.05, max: 0.9 });
|
|
133
112
|
const [colorScale, setColorScale] = useState<ColorScale>({ min: 0, max: 1, color: 'indigo' });
|
|
134
113
|
|
|
135
|
-
const [displayedSegments, setDisplayedSegments] = useDisplayedSegments(sequenceType);
|
|
114
|
+
const [displayedSegments, setDisplayedSegments] = useDisplayedSegments(originalComponentProps.sequenceType);
|
|
136
115
|
const [displayedMutationTypes, setDisplayedMutationTypes] = useState<DisplayedMutationType[]>([
|
|
137
116
|
{ label: 'Substitutions', checked: true, type: 'substitution' },
|
|
138
117
|
{ label: 'Deletions', checked: true, type: 'deletion' },
|
|
@@ -164,7 +143,7 @@ const MutationsOverTimeTabs: FunctionComponent<MutationOverTimeTabsProps> = ({
|
|
|
164
143
|
}
|
|
165
144
|
};
|
|
166
145
|
|
|
167
|
-
const tabs = views.map((view) => getTab(view));
|
|
146
|
+
const tabs = originalComponentProps.views.map((view) => getTab(view));
|
|
168
147
|
|
|
169
148
|
const toolbar = (activeTab: string) => (
|
|
170
149
|
<Toolbar
|
|
@@ -178,6 +157,7 @@ const MutationsOverTimeTabs: FunctionComponent<MutationOverTimeTabsProps> = ({
|
|
|
178
157
|
filteredData={filteredData}
|
|
179
158
|
colorScale={colorScale}
|
|
180
159
|
setColorScale={setColorScale}
|
|
160
|
+
originalComponentProps={originalComponentProps}
|
|
181
161
|
/>
|
|
182
162
|
);
|
|
183
163
|
|
|
@@ -192,9 +172,10 @@ type ToolbarProps = {
|
|
|
192
172
|
setDisplayedMutationTypes: (types: DisplayedMutationType[]) => void;
|
|
193
173
|
proportionInterval: ProportionInterval;
|
|
194
174
|
setProportionInterval: Dispatch<StateUpdater<ProportionInterval>>;
|
|
195
|
-
filteredData:
|
|
175
|
+
filteredData: MutationOverTimeDataMap;
|
|
196
176
|
colorScale: ColorScale;
|
|
197
177
|
setColorScale: Dispatch<StateUpdater<ColorScale>>;
|
|
178
|
+
originalComponentProps: MutationsOverTimeProps;
|
|
198
179
|
};
|
|
199
180
|
|
|
200
181
|
const Toolbar: FunctionComponent<ToolbarProps> = ({
|
|
@@ -208,6 +189,7 @@ const Toolbar: FunctionComponent<ToolbarProps> = ({
|
|
|
208
189
|
filteredData,
|
|
209
190
|
colorScale,
|
|
210
191
|
setColorScale,
|
|
192
|
+
originalComponentProps,
|
|
211
193
|
}) => {
|
|
212
194
|
return (
|
|
213
195
|
<>
|
|
@@ -230,13 +212,28 @@ const Toolbar: FunctionComponent<ToolbarProps> = ({
|
|
|
230
212
|
getData={() => getDownloadData(filteredData)}
|
|
231
213
|
filename='mutations_over_time.csv'
|
|
232
214
|
/>
|
|
233
|
-
<
|
|
215
|
+
<MutationsOverTimeInfo originalComponentProps={originalComponentProps} />
|
|
234
216
|
<Fullscreen />
|
|
235
217
|
</>
|
|
236
218
|
);
|
|
237
219
|
};
|
|
238
220
|
|
|
239
|
-
|
|
221
|
+
type MutationsOverTimeInfoProps = {
|
|
222
|
+
originalComponentProps: MutationsOverTimeProps;
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
const MutationsOverTimeInfo: FunctionComponent<MutationsOverTimeInfoProps> = ({ originalComponentProps }) => {
|
|
226
|
+
const lapis = useContext(LapisUrlContext);
|
|
227
|
+
return (
|
|
228
|
+
<Info>
|
|
229
|
+
<InfoHeadline1>Info for mutations over time</InfoHeadline1>
|
|
230
|
+
<InfoParagraph>TODO: https://github.com/GenSpectrum/dashboard-components/issues/441</InfoParagraph>
|
|
231
|
+
<InfoComponentCode componentName='mutations-over-time' params={originalComponentProps} lapisUrl={lapis} />
|
|
232
|
+
</Info>
|
|
233
|
+
);
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
function getDownloadData(filteredData: MutationOverTimeDataMap) {
|
|
240
237
|
const dates = filteredData.getSecondAxisKeys().map((date) => toTemporalClass(date));
|
|
241
238
|
|
|
242
239
|
return filteredData.getFirstAxisKeys().map((mutation) => {
|