@genspectrum/dashboard-components 0.19.4 → 0.19.6
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 +99 -0
- package/dist/{LineageFilterChangedEvent-GgkxoF3X.js → LineageFilterChangedEvent-Cqa8Frcf.js} +2 -1
- package/dist/{LineageFilterChangedEvent-GgkxoF3X.js.map → LineageFilterChangedEvent-Cqa8Frcf.js.map} +1 -1
- package/dist/assets/mutationOverTimeWorker-DQGh08AS.js.map +1 -0
- package/dist/components.d.ts +64 -33
- package/dist/components.js +82 -22
- package/dist/components.js.map +1 -1
- package/dist/util.d.ts +47 -33
- package/dist/util.js +1 -1
- package/package.json +1 -1
- package/src/preact/aggregatedData/aggregate.stories.tsx +6 -0
- package/src/preact/aggregatedData/aggregate.tsx +10 -1
- package/src/preact/components/tabs.tsx +4 -4
- package/src/preact/genomeViewer/CDSPlot.tsx +4 -1
- package/src/preact/genomeViewer/genome-data-viewer.stories.tsx +6 -0
- package/src/preact/mutationComparison/mutation-comparison.stories.tsx +6 -0
- package/src/preact/mutationComparison/mutation-comparison.tsx +4 -0
- package/src/preact/mutations/mutations.stories.tsx +6 -0
- package/src/preact/mutations/mutations.tsx +4 -1
- package/src/preact/mutationsOverTime/getFilteredMutationsOverTimeData.ts +4 -2
- package/src/preact/mutationsOverTime/mutations-over-time.stories.tsx +6 -0
- package/src/preact/mutationsOverTime/mutations-over-time.tsx +4 -1
- package/src/preact/numberSequencesOverTime/number-sequences-over-time.stories.tsx +3 -1
- package/src/preact/numberSequencesOverTime/number-sequences-over-time.tsx +4 -0
- package/src/preact/prevalenceOverTime/prevalence-over-time.stories.tsx +6 -0
- package/src/preact/prevalenceOverTime/prevalence-over-time.tsx +4 -1
- package/src/preact/relativeGrowthAdvantage/relative-growth-advantage.stories.tsx +6 -0
- package/src/preact/relativeGrowthAdvantage/relative-growth-advantage.tsx +4 -1
- package/src/preact/sequencesByLocation/sequences-by-location.stories.tsx +6 -0
- package/src/preact/sequencesByLocation/sequences-by-location.tsx +4 -0
- package/src/preact/shared/stories/expectFinishedLoadingEvent.ts +12 -0
- package/src/preact/statistic/statistics.stories.tsx +6 -0
- package/src/preact/statistic/statistics.tsx +4 -1
- package/src/preact/wastewater/mutationsOverTime/wastewater-mutations-over-time.stories.tsx +37 -1
- package/src/preact/wastewater/mutationsOverTime/wastewater-mutations-over-time.tsx +44 -4
- package/src/utilEntrypoint.ts +2 -0
- package/src/utils/gsEventNames.ts +1 -0
- package/src/utils/useDispatchFinishedLoadingEvent.ts +19 -0
- package/src/web-components/visualization/gs-aggregate.tsx +3 -0
- package/src/web-components/visualization/gs-genome-data-viewer.tsx +2 -0
- package/src/web-components/visualization/gs-mutation-comparison.tsx +3 -0
- package/src/web-components/visualization/gs-mutations-over-time.tsx +3 -0
- package/src/web-components/visualization/gs-mutations.tsx +2 -0
- package/src/web-components/visualization/gs-number-sequences-over-time.tsx +3 -0
- package/src/web-components/visualization/gs-prevalence-over-time.tsx +3 -0
- package/src/web-components/visualization/gs-relative-growth-advantage.tsx +3 -0
- package/src/web-components/visualization/gs-sequences-by-location.tsx +3 -0
- package/src/web-components/visualization/gs-statistics.tsx +3 -0
- package/src/web-components/wastewaterVisualization/gs-wastewater-mutations-over-time.tsx +3 -0
- package/standalone-bundle/assets/mutationOverTimeWorker-DAf2_NiP.js.map +1 -0
- package/standalone-bundle/dashboard-components.js +7012 -6961
- package/standalone-bundle/dashboard-components.js.map +1 -1
- package/dist/assets/mutationOverTimeWorker-ChQTFL68.js.map +0 -1
- package/standalone-bundle/assets/mutationOverTimeWorker-jChgWnwp.js.map +0 -1
|
@@ -7,6 +7,7 @@ import { RelativeGrowthAdvantage, type RelativeGrowthAdvantageProps } from './re
|
|
|
7
7
|
import { AGGREGATED_ENDPOINT, LAPIS_URL } from '../../constants';
|
|
8
8
|
import { LapisUrlContextProvider } from '../LapisUrlContext';
|
|
9
9
|
import { expectInvalidAttributesErrorMessage } from '../shared/stories/expectErrorMessage';
|
|
10
|
+
import { playThatExpectsFinishedLoadingEvent } from '../shared/stories/expectFinishedLoadingEvent';
|
|
10
11
|
|
|
11
12
|
export default {
|
|
12
13
|
title: 'Visualization/RelativeGrowthAdvantage',
|
|
@@ -90,6 +91,11 @@ export const Primary: StoryObj<RelativeGrowthAdvantageProps> = {
|
|
|
90
91
|
},
|
|
91
92
|
};
|
|
92
93
|
|
|
94
|
+
export const FiresFinishedLoadingEvent: StoryObj<RelativeGrowthAdvantageProps> = {
|
|
95
|
+
...Primary,
|
|
96
|
+
play: playThatExpectsFinishedLoadingEvent(),
|
|
97
|
+
};
|
|
98
|
+
|
|
93
99
|
export const TooFewDataToComputeGrowthAdvantage: StoryObj<RelativeGrowthAdvantageProps> = {
|
|
94
100
|
...Primary,
|
|
95
101
|
args: {
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
type RelativeGrowthAdvantageData,
|
|
10
10
|
} from '../../query/queryRelativeGrowthAdvantage';
|
|
11
11
|
import { lapisFilterSchema, views } from '../../types';
|
|
12
|
+
import { useDispatchFinishedLoadingEvent } from '../../utils/useDispatchFinishedLoadingEvent';
|
|
12
13
|
import { useLapisUrl } from '../LapisUrlContext';
|
|
13
14
|
import { ErrorBoundary } from '../components/error-boundary';
|
|
14
15
|
import { Fullscreen } from '../components/fullscreen';
|
|
@@ -103,6 +104,8 @@ const RelativeGrowthAdvantageTabs: FunctionComponent<RelativeGrowthAdvantageTabs
|
|
|
103
104
|
setYAxisScaleType,
|
|
104
105
|
originalComponentProps,
|
|
105
106
|
}) => {
|
|
107
|
+
const tabsRef = useDispatchFinishedLoadingEvent();
|
|
108
|
+
|
|
106
109
|
const maintainAspectRatio = getMaintainAspectRatio(originalComponentProps.height);
|
|
107
110
|
|
|
108
111
|
const getTab = (view: RelativeGrowthAdvantageView) => {
|
|
@@ -138,7 +141,7 @@ const RelativeGrowthAdvantageTabs: FunctionComponent<RelativeGrowthAdvantageTabs
|
|
|
138
141
|
/>
|
|
139
142
|
);
|
|
140
143
|
|
|
141
|
-
return <Tabs tabs={tabs} toolbar={toolbar} />;
|
|
144
|
+
return <Tabs ref={tabsRef} tabs={tabs} toolbar={toolbar} />;
|
|
142
145
|
};
|
|
143
146
|
|
|
144
147
|
type RelativeGrowthAdvantageToolbarProps = {
|
|
@@ -7,6 +7,7 @@ import { LapisUrlContextProvider } from '../LapisUrlContext';
|
|
|
7
7
|
import aggregatedWorld from './__mockData__/aggregatedWorld.json';
|
|
8
8
|
import { SequencesByLocation, type SequencesByLocationProps } from './sequences-by-location';
|
|
9
9
|
import { expectInvalidAttributesErrorMessage, playThatExpectsErrorMessage } from '../shared/stories/expectErrorMessage';
|
|
10
|
+
import { playThatExpectsFinishedLoadingEvent } from '../shared/stories/expectFinishedLoadingEvent';
|
|
10
11
|
|
|
11
12
|
import 'leaflet/dist/leaflet.css';
|
|
12
13
|
import './leafletStyleModifications.css';
|
|
@@ -92,6 +93,11 @@ export const Default: StoryObj<SequencesByLocationProps> = {
|
|
|
92
93
|
},
|
|
93
94
|
};
|
|
94
95
|
|
|
96
|
+
export const FiresFinishedLoadingEvent: StoryObj<SequencesByLocationProps> = {
|
|
97
|
+
...Default,
|
|
98
|
+
play: playThatExpectsFinishedLoadingEvent(),
|
|
99
|
+
};
|
|
100
|
+
|
|
95
101
|
export const NoData: StoryObj<SequencesByLocationProps> = {
|
|
96
102
|
...Default,
|
|
97
103
|
parameters: {
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
} from '../../query/computeMapLocationData';
|
|
12
12
|
import { type AggregateData } from '../../query/queryAggregateData';
|
|
13
13
|
import { querySequencesByLocationData } from '../../query/querySequencesByLocationData';
|
|
14
|
+
import { useDispatchFinishedLoadingEvent } from '../../utils/useDispatchFinishedLoadingEvent';
|
|
14
15
|
import { CsvDownloadButton } from '../components/csv-download-button';
|
|
15
16
|
import { ErrorBoundary } from '../components/error-boundary';
|
|
16
17
|
import { Fullscreen } from '../components/fullscreen';
|
|
@@ -93,6 +94,8 @@ const SequencesByLocationMapTabs: FunctionComponent<SequencesByLocationMapTabsPr
|
|
|
93
94
|
originalComponentProps,
|
|
94
95
|
data,
|
|
95
96
|
}) => {
|
|
97
|
+
const tabsRef = useDispatchFinishedLoadingEvent();
|
|
98
|
+
|
|
96
99
|
const maintainAspectRatio = getMaintainAspectRatio(originalComponentProps.height);
|
|
97
100
|
|
|
98
101
|
const getTab = (view: SequencesByLocationMapView) => {
|
|
@@ -136,6 +139,7 @@ const SequencesByLocationMapTabs: FunctionComponent<SequencesByLocationMapTabsPr
|
|
|
136
139
|
|
|
137
140
|
return (
|
|
138
141
|
<Tabs
|
|
142
|
+
ref={tabsRef}
|
|
139
143
|
tabs={tabs}
|
|
140
144
|
toolbar={<Toolbar originalComponentProps={originalComponentProps} tableData={data.tableData} />}
|
|
141
145
|
/>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { expect, fn, waitFor } from '@storybook/test';
|
|
2
|
+
|
|
3
|
+
import { gsEventNames } from '../../../utils/gsEventNames';
|
|
4
|
+
|
|
5
|
+
export function playThatExpectsFinishedLoadingEvent() {
|
|
6
|
+
return async ({ canvasElement }: { canvasElement: HTMLElement }) => {
|
|
7
|
+
const componentFinishedLoadingListenerMock = fn();
|
|
8
|
+
canvasElement.addEventListener(gsEventNames.componentFinishedLoading, componentFinishedLoadingListenerMock);
|
|
9
|
+
|
|
10
|
+
await waitFor(() => expect(componentFinishedLoadingListenerMock).toHaveBeenCalled());
|
|
11
|
+
};
|
|
12
|
+
}
|
|
@@ -6,6 +6,7 @@ import { LapisUrlContextProvider } from '../LapisUrlContext';
|
|
|
6
6
|
import denominatorData from './__mockData__/denominator.json';
|
|
7
7
|
import numeratorData from './__mockData__/numerator.json';
|
|
8
8
|
import { Statistics, type StatisticsProps } from './statistics';
|
|
9
|
+
import { playThatExpectsFinishedLoadingEvent } from '../shared/stories/expectFinishedLoadingEvent';
|
|
9
10
|
|
|
10
11
|
const meta: Meta<StatisticsProps> = {
|
|
11
12
|
title: 'Visualization/Statistics',
|
|
@@ -78,3 +79,8 @@ export const Default: StoryObj<StatisticsProps> = {
|
|
|
78
79
|
});
|
|
79
80
|
},
|
|
80
81
|
};
|
|
82
|
+
|
|
83
|
+
export const FiresFinishedLoadingEvent: StoryObj<StatisticsProps> = {
|
|
84
|
+
...Default,
|
|
85
|
+
play: playThatExpectsFinishedLoadingEvent(),
|
|
86
|
+
};
|
|
@@ -3,6 +3,7 @@ import z from 'zod';
|
|
|
3
3
|
|
|
4
4
|
import { queryGeneralStatistics } from '../../query/queryGeneralStatistics';
|
|
5
5
|
import { lapisFilterSchema } from '../../types';
|
|
6
|
+
import { useDispatchFinishedLoadingEvent } from '../../utils/useDispatchFinishedLoadingEvent';
|
|
6
7
|
import { useLapisUrl } from '../LapisUrlContext';
|
|
7
8
|
import { ErrorBoundary } from '../components/error-boundary';
|
|
8
9
|
import { LoadingDisplay } from '../components/loading-display';
|
|
@@ -60,9 +61,11 @@ type MetricDataTabsProps = {
|
|
|
60
61
|
};
|
|
61
62
|
|
|
62
63
|
const MetricDataTabs: FunctionComponent<MetricDataTabsProps> = ({ data }) => {
|
|
64
|
+
const ref = useDispatchFinishedLoadingEvent();
|
|
65
|
+
|
|
63
66
|
const { count, proportion } = data;
|
|
64
67
|
return (
|
|
65
|
-
<div className='flex flex-col sm:flex-row rounded-md border-2 border-gray-100 min-w-[180px]'>
|
|
68
|
+
<div ref={ref} className='flex flex-col sm:flex-row rounded-md border-2 border-gray-100 min-w-[180px]'>
|
|
66
69
|
<div className='stat'>
|
|
67
70
|
<div className='stat-title'>Sequences</div>
|
|
68
71
|
<div className='stat-value text-2xl sm:text-4xl'>{count.toLocaleString('en-us')}</div>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type Meta, type StoryObj } from '@storybook/preact';
|
|
2
|
-
import { expect, userEvent } from '@storybook/test';
|
|
2
|
+
import { expect, userEvent, waitFor } from '@storybook/test';
|
|
3
|
+
import type { Canvas } from '@storybook/types';
|
|
3
4
|
|
|
4
5
|
import { WastewaterMutationsOverTime, type WastewaterMutationsOverTimeProps } from './wastewater-mutations-over-time';
|
|
5
6
|
import { WISE_DETAILS_ENDPOINT, WISE_LAPIS_URL } from '../../../constants';
|
|
@@ -7,6 +8,8 @@ import referenceGenome from '../../../lapisApi/__mockData__/referenceGenome.json
|
|
|
7
8
|
import { LapisUrlContextProvider } from '../../LapisUrlContext';
|
|
8
9
|
import { ReferenceGenomeContext } from '../../ReferenceGenomeContext';
|
|
9
10
|
import details from './__mockData__/details.json';
|
|
11
|
+
import type { MutationsOverTimeProps } from '../../mutationsOverTime/mutations-over-time';
|
|
12
|
+
import { playThatExpectsFinishedLoadingEvent } from '../../shared/stories/expectFinishedLoadingEvent';
|
|
10
13
|
|
|
11
14
|
const meta: Meta<WastewaterMutationsOverTimeProps> = {
|
|
12
15
|
title: 'Wastewater visualization/Wastewater mutations over time',
|
|
@@ -65,6 +68,7 @@ export const Default: StoryObj<WastewaterMutationsOverTimeProps> = {
|
|
|
65
68
|
],
|
|
66
69
|
},
|
|
67
70
|
},
|
|
71
|
+
play: playThatExpectsFinishedLoadingEvent(),
|
|
68
72
|
};
|
|
69
73
|
|
|
70
74
|
export const ChangingRowsPerPageChangesItForEveryTag: StoryObj<WastewaterMutationsOverTimeProps> = {
|
|
@@ -108,3 +112,35 @@ export const AminoAcids: StoryObj<WastewaterMutationsOverTimeProps> = {
|
|
|
108
112
|
});
|
|
109
113
|
},
|
|
110
114
|
};
|
|
115
|
+
|
|
116
|
+
export const UsesMutationFilter: StoryObj<MutationsOverTimeProps> = {
|
|
117
|
+
...Default,
|
|
118
|
+
play: async ({ canvas, step }) => {
|
|
119
|
+
await expectMutationOnPage(canvas, 'A966C');
|
|
120
|
+
|
|
121
|
+
await step('input filter', async () => {
|
|
122
|
+
const filterButton = canvas.getByRole('button', { name: 'Filter mutations' });
|
|
123
|
+
await userEvent.click(filterButton);
|
|
124
|
+
|
|
125
|
+
const filterInput = canvas.getByPlaceholderText('Filter');
|
|
126
|
+
await userEvent.type(filterInput, '26');
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
await step('should show only matching filter', async () => {
|
|
130
|
+
await expectMutationOnPage(canvas, 'T4026G');
|
|
131
|
+
await expectMutationOnPage(canvas, 'T5260C');
|
|
132
|
+
|
|
133
|
+
await waitFor(async () => {
|
|
134
|
+
const filteredMutation = canvas.queryByText('A966C');
|
|
135
|
+
await expect(filteredMutation).not.toBeInTheDocument();
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
async function expectMutationOnPage(canvas: Canvas, mutation: string) {
|
|
142
|
+
await waitFor(async () => {
|
|
143
|
+
const mutationOnFirstPage = canvas.getAllByText(mutation)[0];
|
|
144
|
+
await expect(mutationOnFirstPage).toBeVisible();
|
|
145
|
+
});
|
|
146
|
+
}
|
|
@@ -3,20 +3,24 @@ import { type Dispatch, type StateUpdater, useMemo, useState } from 'preact/hook
|
|
|
3
3
|
import z from 'zod';
|
|
4
4
|
|
|
5
5
|
import { computeWastewaterMutationsOverTimeDataPerLocation } from './computeWastewaterMutationsOverTimeDataPerLocation';
|
|
6
|
-
import { lapisFilterSchema, sequenceTypeSchema } from '../../../types';
|
|
6
|
+
import { lapisFilterSchema, type SequenceType, sequenceTypeSchema } from '../../../types';
|
|
7
7
|
import { Map2dView } from '../../../utils/map2d';
|
|
8
|
+
import { useDispatchFinishedLoadingEvent } from '../../../utils/useDispatchFinishedLoadingEvent';
|
|
8
9
|
import { useLapisUrl } from '../../LapisUrlContext';
|
|
10
|
+
import { useMutationAnnotationsProvider } from '../../MutationAnnotationsContext';
|
|
9
11
|
import { type ColorScale } from '../../components/color-scale-selector';
|
|
10
12
|
import { ColorScaleSelectorDropdown } from '../../components/color-scale-selector-dropdown';
|
|
11
13
|
import { ErrorBoundary } from '../../components/error-boundary';
|
|
12
14
|
import { Fullscreen } from '../../components/fullscreen';
|
|
13
15
|
import Info, { InfoComponentCode, InfoHeadline1, InfoParagraph } from '../../components/info';
|
|
14
16
|
import { LoadingDisplay } from '../../components/loading-display';
|
|
17
|
+
import { MutationsOverTimeTextFilter } from '../../components/mutations-over-time-text-filter';
|
|
15
18
|
import { NoDataDisplay } from '../../components/no-data-display';
|
|
16
19
|
import { ResizeContainer } from '../../components/resize-container';
|
|
17
20
|
import { type DisplayedSegment, SegmentSelector } from '../../components/segment-selector';
|
|
18
21
|
import Tabs from '../../components/tabs';
|
|
19
22
|
import { type MutationOverTimeDataMap } from '../../mutationsOverTime/MutationOverTimeData';
|
|
23
|
+
import { mutationOrAnnotationDoNotMatchFilter } from '../../mutationsOverTime/getFilteredMutationsOverTimeData';
|
|
20
24
|
import MutationsOverTimeGrid from '../../mutationsOverTime/mutations-over-time-grid';
|
|
21
25
|
import { pageSizesSchema } from '../../shared/tanstackTable/pagination';
|
|
22
26
|
import { PageSizeContextProvider } from '../../shared/tanstackTable/pagination-context';
|
|
@@ -111,13 +115,23 @@ type MutationOverTimeTabsProps = {
|
|
|
111
115
|
function getFilteredMutationOverTimeData({
|
|
112
116
|
data,
|
|
113
117
|
displayedSegments,
|
|
118
|
+
mutationFilterValue,
|
|
119
|
+
annotationProvider,
|
|
120
|
+
sequenceType,
|
|
114
121
|
}: {
|
|
115
122
|
data: MutationOverTimeDataMap;
|
|
116
123
|
displayedSegments: DisplayedSegment[];
|
|
124
|
+
mutationFilterValue: string;
|
|
125
|
+
sequenceType: SequenceType;
|
|
126
|
+
annotationProvider: ReturnType<typeof useMutationAnnotationsProvider>;
|
|
117
127
|
}): MutationOverTimeDataMap {
|
|
118
128
|
const filteredData = new Map2dView(data);
|
|
119
129
|
|
|
120
130
|
const mutationsToFilterOut = data.getFirstAxisKeys().filter((entry) => {
|
|
131
|
+
if (mutationOrAnnotationDoNotMatchFilter(entry, sequenceType, mutationFilterValue, annotationProvider)) {
|
|
132
|
+
return true;
|
|
133
|
+
}
|
|
134
|
+
|
|
121
135
|
return displayedSegments.some((segment) => segment.segment === entry.segment && !segment.checked);
|
|
122
136
|
});
|
|
123
137
|
|
|
@@ -132,6 +146,11 @@ const MutationsOverTimeTabs: FunctionComponent<MutationOverTimeTabsProps> = ({
|
|
|
132
146
|
mutationOverTimeDataPerLocation,
|
|
133
147
|
originalComponentProps,
|
|
134
148
|
}) => {
|
|
149
|
+
const tabsRef = useDispatchFinishedLoadingEvent();
|
|
150
|
+
|
|
151
|
+
const [mutationFilterValue, setMutationFilterValue] = useState('');
|
|
152
|
+
const annotationProvider = useMutationAnnotationsProvider();
|
|
153
|
+
|
|
135
154
|
const [colorScale, setColorScale] = useState<ColorScale>({ min: 0, max: 1, color: 'indigo' });
|
|
136
155
|
const [displayedSegments, setDisplayedSegments] = useDisplayedSegments(mutationOverTimeDataPerLocation);
|
|
137
156
|
|
|
@@ -141,14 +160,28 @@ const MutationsOverTimeTabs: FunctionComponent<MutationOverTimeTabsProps> = ({
|
|
|
141
160
|
title: location,
|
|
142
161
|
content: (
|
|
143
162
|
<MutationsOverTimeGrid
|
|
144
|
-
data={getFilteredMutationOverTimeData({
|
|
163
|
+
data={getFilteredMutationOverTimeData({
|
|
164
|
+
data,
|
|
165
|
+
displayedSegments,
|
|
166
|
+
mutationFilterValue,
|
|
167
|
+
annotationProvider,
|
|
168
|
+
sequenceType: originalComponentProps.sequenceType,
|
|
169
|
+
})}
|
|
145
170
|
colorScale={colorScale}
|
|
146
171
|
pageSizes={originalComponentProps.pageSizes}
|
|
147
172
|
sequenceType={originalComponentProps.sequenceType}
|
|
148
173
|
/>
|
|
149
174
|
),
|
|
150
175
|
})),
|
|
151
|
-
[
|
|
176
|
+
[
|
|
177
|
+
mutationOverTimeDataPerLocation,
|
|
178
|
+
displayedSegments,
|
|
179
|
+
mutationFilterValue,
|
|
180
|
+
annotationProvider,
|
|
181
|
+
colorScale,
|
|
182
|
+
originalComponentProps.pageSizes,
|
|
183
|
+
originalComponentProps.sequenceType,
|
|
184
|
+
],
|
|
152
185
|
);
|
|
153
186
|
|
|
154
187
|
const toolbar = (
|
|
@@ -159,12 +192,14 @@ const MutationsOverTimeTabs: FunctionComponent<MutationOverTimeTabsProps> = ({
|
|
|
159
192
|
data={mutationOverTimeDataPerLocation}
|
|
160
193
|
displayedSegments={displayedSegments}
|
|
161
194
|
setDisplayedSegments={setDisplayedSegments}
|
|
195
|
+
setFilterValue={setMutationFilterValue}
|
|
196
|
+
mutationFilterValue={mutationFilterValue}
|
|
162
197
|
/>
|
|
163
198
|
);
|
|
164
199
|
|
|
165
200
|
return (
|
|
166
201
|
<PageSizeContextProvider pageSizes={originalComponentProps.pageSizes}>
|
|
167
|
-
<Tabs tabs={tabs} toolbar={toolbar} />
|
|
202
|
+
<Tabs ref={tabsRef} tabs={tabs} toolbar={toolbar} />
|
|
168
203
|
</PageSizeContextProvider>
|
|
169
204
|
);
|
|
170
205
|
};
|
|
@@ -176,6 +211,8 @@ type ToolbarProps = {
|
|
|
176
211
|
data: MutationOverTimeDataPerLocation;
|
|
177
212
|
displayedSegments: DisplayedSegment[];
|
|
178
213
|
setDisplayedSegments: (segments: DisplayedSegment[]) => void;
|
|
214
|
+
mutationFilterValue: string;
|
|
215
|
+
setFilterValue: (filterValue: string) => void;
|
|
179
216
|
};
|
|
180
217
|
|
|
181
218
|
const Toolbar: FunctionComponent<ToolbarProps> = ({
|
|
@@ -184,9 +221,12 @@ const Toolbar: FunctionComponent<ToolbarProps> = ({
|
|
|
184
221
|
originalComponentProps,
|
|
185
222
|
displayedSegments,
|
|
186
223
|
setDisplayedSegments,
|
|
224
|
+
setFilterValue,
|
|
225
|
+
mutationFilterValue,
|
|
187
226
|
}) => {
|
|
188
227
|
return (
|
|
189
228
|
<>
|
|
229
|
+
<MutationsOverTimeTextFilter setFilterValue={setFilterValue} value={mutationFilterValue} />
|
|
190
230
|
<ColorScaleSelectorDropdown colorScale={colorScale} setColorScale={setColorScale} />
|
|
191
231
|
<SegmentSelector
|
|
192
232
|
displayedSegments={displayedSegments}
|
package/src/utilEntrypoint.ts
CHANGED
|
@@ -40,3 +40,5 @@ export { TextFilterChangedEvent } from './preact/textFilter/TextFilterChangedEve
|
|
|
40
40
|
export type { MutationAnnotations, MutationAnnotation } from './web-components/mutation-annotations-context';
|
|
41
41
|
|
|
42
42
|
export { gsEventNames } from './utils/gsEventNames';
|
|
43
|
+
|
|
44
|
+
export { type NumberRange } from './preact/numberRangeFilter/NumberRangeFilterChangedEvent';
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export const gsEventNames = {
|
|
2
2
|
error: 'gs-error',
|
|
3
|
+
componentFinishedLoading: 'gs-component-finished-loading',
|
|
3
4
|
dateRangeFilterChanged: 'gs-date-range-filter-changed',
|
|
4
5
|
dateRangeOptionChanged: 'gs-date-range-option-changed',
|
|
5
6
|
mutationFilterChanged: 'gs-mutation-filter-changed',
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { useEffect, useRef } from 'preact/hooks';
|
|
2
|
+
|
|
3
|
+
import { gsEventNames } from './gsEventNames';
|
|
4
|
+
|
|
5
|
+
export function useDispatchFinishedLoadingEvent() {
|
|
6
|
+
const ref = useRef<HTMLDivElement>(null);
|
|
7
|
+
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
if (ref.current === null) {
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
ref.current.dispatchEvent(
|
|
14
|
+
new CustomEvent(gsEventNames.componentFinishedLoading, { bubbles: true, composed: true }),
|
|
15
|
+
);
|
|
16
|
+
}, [ref]);
|
|
17
|
+
|
|
18
|
+
return ref;
|
|
19
|
+
}
|
|
@@ -30,6 +30,9 @@ import { PreactLitAdapterWithGridJsStyles } from '../PreactLitAdapterWithGridJsS
|
|
|
30
30
|
*
|
|
31
31
|
* The chart shows the bars with the highest aggregated `count`.
|
|
32
32
|
* The number of bars can be adjusted with the `maxNumberOfBars` property.
|
|
33
|
+
*
|
|
34
|
+
* @fires {CustomEvent<undefined>} gs-component-finished-loading
|
|
35
|
+
* Fired when the component has finished loading the required data from LAPIS.
|
|
33
36
|
*/
|
|
34
37
|
@customElement('gs-aggregate')
|
|
35
38
|
export class AggregateComponent extends PreactLitAdapterWithGridJsStyles {
|
|
@@ -10,6 +10,8 @@ import { PreactLitAdapter } from '../PreactLitAdapter';
|
|
|
10
10
|
* This component shows the Coding Sequence (CDS) of a genome using a gff3 file as input.
|
|
11
11
|
* The CDS shows which parts of the genome are translated into proteins.
|
|
12
12
|
*
|
|
13
|
+
* @fires {CustomEvent<undefined>} gs-component-finished-loading
|
|
14
|
+
* Fired when the component has finished loading the required data.
|
|
13
15
|
*/
|
|
14
16
|
@customElement('gs-genome-data-viewer')
|
|
15
17
|
export class GenomeDataViewerComponent extends PreactLitAdapter {
|
|
@@ -34,6 +34,9 @@ import { type MutationAnnotations, mutationAnnotationsContext } from '../mutatio
|
|
|
34
34
|
* selected proportion interval.
|
|
35
35
|
* Thus, changing the proportion interval may change a mutations from being "common" between the datasets
|
|
36
36
|
* to being "for one dataset only".
|
|
37
|
+
*
|
|
38
|
+
* @fires {CustomEvent<undefined>} gs-component-finished-loading
|
|
39
|
+
* Fired when the component has finished loading the required data from LAPIS.
|
|
37
40
|
*/
|
|
38
41
|
@customElement('gs-mutation-comparison')
|
|
39
42
|
export class MutationComparisonComponent extends PreactLitAdapterWithGridJsStyles {
|
|
@@ -38,6 +38,9 @@ import { type MutationAnnotations, mutationAnnotationsContext } from '../mutatio
|
|
|
38
38
|
* Users can filter the displayed rows by mean proportion via a slider in the toolbar.
|
|
39
39
|
* The mean proportion of each row is calculated by LAPIS over the whole data range that the component displays.
|
|
40
40
|
* The initial mean proportion can be set via `initialMeanProportionInterval`.
|
|
41
|
+
*
|
|
42
|
+
* @fires {CustomEvent<undefined>} gs-component-finished-loading
|
|
43
|
+
* Fired when the component has finished loading the required data from LAPIS.
|
|
41
44
|
*/
|
|
42
45
|
@customElement('gs-mutations-over-time')
|
|
43
46
|
export class MutationsOverTimeComponent extends PreactLitAdapterWithGridJsStyles {
|
|
@@ -60,6 +60,8 @@ import { type MutationAnnotations, mutationAnnotationsContext } from '../mutatio
|
|
|
60
60
|
*
|
|
61
61
|
* The insertions view shows the count of all insertions for the dataset.
|
|
62
62
|
*
|
|
63
|
+
* @fires {CustomEvent<undefined>} gs-component-finished-loading
|
|
64
|
+
* Fired when the component has finished loading the required data from LAPIS.
|
|
63
65
|
*/
|
|
64
66
|
@customElement('gs-mutations')
|
|
65
67
|
export class MutationsComponent extends PreactLitAdapterWithGridJsStyles {
|
|
@@ -19,6 +19,9 @@ import { PreactLitAdapterWithGridJsStyles } from '../PreactLitAdapterWithGridJsS
|
|
|
19
19
|
* Thus, the `lapisFilter` implicitly also defines the range that is shown on the x-axis.
|
|
20
20
|
* If you want to restrict the x-axis to a smaller date range,
|
|
21
21
|
* then you need to set appropriate filter values in the `lapisFilter`.
|
|
22
|
+
*
|
|
23
|
+
* @fires {CustomEvent<undefined>} gs-component-finished-loading
|
|
24
|
+
* Fired when the component has finished loading the required data from LAPIS.
|
|
22
25
|
*/
|
|
23
26
|
@customElement('gs-number-sequences-over-time')
|
|
24
27
|
export class NumberSequencesOverTimeComponent extends PreactLitAdapterWithGridJsStyles {
|
|
@@ -41,6 +41,9 @@ import { PreactLitAdapterWithGridJsStyles } from '../PreactLitAdapterWithGridJsS
|
|
|
41
41
|
* ### Table View
|
|
42
42
|
*
|
|
43
43
|
* Displays the prevalence over time as a table with one row per time point.
|
|
44
|
+
*
|
|
45
|
+
* @fires {CustomEvent<undefined>} gs-component-finished-loading
|
|
46
|
+
* Fired when the component has finished loading the required data from LAPIS.
|
|
44
47
|
*/
|
|
45
48
|
@customElement('gs-prevalence-over-time')
|
|
46
49
|
export class PrevalenceOverTimeComponent extends PreactLitAdapterWithGridJsStyles {
|
|
@@ -33,6 +33,9 @@ import { PreactLitAdapter } from '../PreactLitAdapter';
|
|
|
33
33
|
* The dots in the plot show the proportions of the focal variant (defined by the `numeratorFilter`) to the baseline variant (defined by the `denominatorFilter`)
|
|
34
34
|
* for every day as observed in the data.
|
|
35
35
|
* The line shows a logistic curve fitted to the data points, including a 95% confidence interval.
|
|
36
|
+
*
|
|
37
|
+
* @fires {CustomEvent<undefined>} gs-component-finished-loading
|
|
38
|
+
* Fired when the component has finished loading the required data from LAPIS.
|
|
36
39
|
*/
|
|
37
40
|
@customElement('gs-relative-growth-advantage')
|
|
38
41
|
export class RelativeGrowthAdvantageComponent extends PreactLitAdapter {
|
|
@@ -94,6 +94,9 @@ const leafletModificationsCss = unsafeCSS(leafletStyleModifications);
|
|
|
94
94
|
* - `lapisLocationField`,
|
|
95
95
|
* - `count` (the number of samples in this location matching the `lapisFilter`),
|
|
96
96
|
* - `proportion` (`count` / sum of the `count` of all locations).
|
|
97
|
+
*
|
|
98
|
+
* @fires {CustomEvent<undefined>} gs-component-finished-loading
|
|
99
|
+
* Fired when the component has finished loading the required data from LAPIS.
|
|
97
100
|
*/
|
|
98
101
|
@customElement('gs-sequences-by-location')
|
|
99
102
|
export class SequencesByLocationComponent extends PreactLitAdapterWithGridJsStyles {
|
|
@@ -10,6 +10,9 @@ import { PreactLitAdapterWithGridJsStyles } from '../PreactLitAdapterWithGridJsS
|
|
|
10
10
|
*
|
|
11
11
|
* This component displays general statistics (number of sequences, overall proportion)
|
|
12
12
|
* for a given numerator and denominator filter.
|
|
13
|
+
*
|
|
14
|
+
* @fires {CustomEvent<undefined>} gs-component-finished-loading
|
|
15
|
+
* Fired when the component has finished loading the required data from LAPIS.
|
|
13
16
|
*/
|
|
14
17
|
@customElement('gs-statistics')
|
|
15
18
|
export class StatisticsComponent extends PreactLitAdapterWithGridJsStyles {
|
|
@@ -24,6 +24,9 @@ import { type MutationAnnotations, mutationAnnotationsContext } from '../mutatio
|
|
|
24
24
|
* This component also assumes that the LAPIS instance has the field `date` which can be used for the time axis.
|
|
25
25
|
*
|
|
26
26
|
* @slot infoText - Additional information text to be shown in the info modal (the "?" button).
|
|
27
|
+
*
|
|
28
|
+
* @fires {CustomEvent<undefined>} gs-component-finished-loading
|
|
29
|
+
* Fired when the component has finished loading the required data from LAPIS.
|
|
27
30
|
*/
|
|
28
31
|
@customElement('gs-wastewater-mutations-over-time')
|
|
29
32
|
export class WastewaterMutationsOverTimeComponent extends PreactLitAdapterWithGridJsStyles {
|