@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.
Files changed (31) hide show
  1. package/custom-elements.json +18 -18
  2. package/dist/assets/mutationOverTimeWorker-BOCXtKzd.js.map +1 -0
  3. package/dist/dashboard-components.js +296 -302
  4. package/dist/dashboard-components.js.map +1 -1
  5. package/dist/genspectrum-components.d.ts +98 -48
  6. package/package.json +1 -3
  7. package/src/index.ts +1 -0
  8. package/src/preact/aggregatedData/aggregate.tsx +41 -33
  9. package/src/preact/dateRangeSelector/computeInitialValues.spec.ts +53 -38
  10. package/src/preact/dateRangeSelector/computeInitialValues.ts +17 -23
  11. package/src/preact/dateRangeSelector/date-range-selector.stories.tsx +46 -32
  12. package/src/preact/dateRangeSelector/date-range-selector.tsx +24 -26
  13. package/src/preact/dateRangeSelector/dateRangeOption.ts +65 -0
  14. package/src/preact/dateRangeSelector/selectableOptions.ts +17 -66
  15. package/src/preact/mutationComparison/mutation-comparison.tsx +32 -34
  16. package/src/preact/mutations/mutations.tsx +63 -56
  17. package/src/preact/mutationsOverTime/MutationOverTimeData.ts +20 -0
  18. package/src/preact/mutationsOverTime/getFilteredMutationsOverTime.spec.ts +2 -3
  19. package/src/preact/mutationsOverTime/getFilteredMutationsOverTimeData.ts +2 -2
  20. package/src/preact/mutationsOverTime/mutations-over-time-grid.tsx +3 -3
  21. package/src/preact/mutationsOverTime/mutations-over-time.tsx +40 -43
  22. package/src/preact/numberSequencesOverTime/number-sequences-over-time.tsx +46 -64
  23. package/src/preact/relativeGrowthAdvantage/relative-growth-advantage.tsx +29 -36
  24. package/src/query/queryMutationsOverTime.ts +3 -5
  25. package/src/utils/map2d.spec.ts +52 -13
  26. package/src/utils/map2d.ts +3 -4
  27. package/src/web-components/input/gs-date-range-selector.stories.ts +16 -28
  28. package/src/web-components/input/gs-date-range-selector.tsx +17 -32
  29. package/standalone-bundle/dashboard-components.js +14322 -15115
  30. package/standalone-bundle/dashboard-components.js.map +1 -1
  31. 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 MutationsInnerProps {
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 interface MutationsProps extends MutationsInnerProps {
42
- width: string;
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 {...innerProps} />
50
+ <MutationsInner {...componentProps} />
53
51
  </ResizeContainer>
54
52
  </ErrorBoundary>
55
53
  );
56
54
  };
57
55
 
58
- export const MutationsInner: FunctionComponent<MutationsInnerProps> = ({
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} sequenceType={sequenceType} views={views} pageSize={pageSize} />;
76
+ return <MutationsTabs mutationsData={data} originalComponentProps={componentProps} />;
82
77
  };
83
78
 
84
79
  type MutationTabsProps = {
85
80
  mutationsData: { insertions: InsertionEntry[]; substitutionsOrDeletions: SubstitutionOrDeletionEntry[] };
86
- sequenceType: SequenceType;
87
- views: View[];
88
- pageSize: boolean | number;
81
+ originalComponentProps: MutationsProps;
89
82
  };
90
83
 
91
- const MutationsTabs: FunctionComponent<MutationTabsProps> = ({ mutationsData, sequenceType, views, pageSize }) => {
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: <InsertionsTable data={filteredData.insertions} pageSize={pageSize} />,
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
- const MutationsInfo = () => (
218
- <Info>
219
- <InfoHeadline1>Mutations</InfoHeadline1>
220
- <InfoParagraph>
221
- This shows mutations of a variant. There are three types of mutations:{' '}
222
- <InfoLink href='https://www.genome.gov/genetics-glossary/Substitution'>substitutions</InfoLink>,{' '}
223
- <InfoLink href='https://www.genome.gov/genetics-glossary/Deletion'>deletions</InfoLink> and{' '}
224
- <InfoLink href='https://www.genome.gov/genetics-glossary/Insertion'>insertions</InfoLink>.
225
- </InfoParagraph>
226
- <InfoHeadline2>Proportion calculation</InfoHeadline2>
227
- <InfoParagraph>
228
- The proportion of a mutation is calculated by dividing the number of sequences with the mutation by the
229
- total number of sequences with a non-ambiguous symbol at the position.
230
- </InfoParagraph>
231
- <InfoParagraph>
232
- <b>Example:</b> Assume we look at nucleotide mutations at position 5 where the reference has a T and assume
233
- there are 10 sequences in total:
234
- <ul className='list-disc list-inside ml-2'>
235
- <li>3 sequences have a C,</li>
236
- <li>2 sequences have a T,</li>
237
- <li>1 sequence has a G,</li>
238
- <li>3 sequences have an N,</li>
239
- <li>1 sequence has a Y (which means T or C),</li>
240
- </ul>
241
- then the proportion of the T5C mutation is 50%. The 4 sequences that have an N or Y are excluded from the
242
- calculation.
243
- </InfoParagraph>
244
- </Info>
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 Map2dBase<Substitution | Deletion, TemporalClass, MutationOverTimeMutationValue>();
196
+ const data = new BaseMutationOverTimeDataMap();
198
197
 
199
198
  temporals.forEach((temporal) => {
200
199
  mutationEntries.forEach((entry) => {
@@ -1,4 +1,4 @@
1
- import { type MutationOverTimeData } from './mutations-over-time';
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: MutationOverTimeData,
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 MutationOverTimeData } from './mutations-over-time';
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 { toTemporalClass, type Temporal, type TemporalClass, YearMonthDayClass } from '../../utils/temporalClass';
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: MutationOverTimeData;
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 { type Temporal, toTemporalClass } from '../../utils/temporalClass';
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 MutationsOverTimeInnerProps {
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 interface MutationsOverTimeProps extends MutationsOverTimeInnerProps {
53
- width: string;
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 {...innerProps} />
56
+ <MutationsOverTimeInner {...componentProps} />
64
57
  </ResizeContainer>
65
58
  </ErrorBoundary>
66
59
  );
67
60
  };
68
61
 
69
- export const MutationsOverTimeInner: FunctionComponent<MutationsOverTimeInnerProps> = ({
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 Map2dBase(
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
- sequenceType={sequenceType}
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: MutationOverTimeData;
121
- sequenceType: SequenceType;
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
- sequenceType,
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: MutationOverTimeData;
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
- <Info>Info for mutations over time</Info>
215
+ <MutationsOverTimeInfo originalComponentProps={originalComponentProps} />
234
216
  <Fullscreen />
235
217
  </>
236
218
  );
237
219
  };
238
220
 
239
- function getDownloadData(filteredData: MutationOverTimeData) {
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) => {