@genspectrum/dashboard-components 0.19.5 → 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 +45 -14
- package/dist/components.js +48 -15
- package/dist/components.js.map +1 -1
- package/dist/util.d.ts +15 -14
- 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/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 +2 -0
- package/src/preact/wastewater/mutationsOverTime/wastewater-mutations-over-time.tsx +4 -1
- 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 +6933 -6904
- 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
package/dist/util.d.ts
CHANGED
|
@@ -151,6 +151,7 @@ declare const dateRangeValueSchema: default_2.ZodNullable<default_2.ZodUnion<[de
|
|
|
151
151
|
|
|
152
152
|
export declare const gsEventNames: {
|
|
153
153
|
readonly error: "gs-error";
|
|
154
|
+
readonly componentFinishedLoading: "gs-component-finished-loading";
|
|
154
155
|
readonly dateRangeFilterChanged: "gs-date-range-filter-changed";
|
|
155
156
|
readonly dateRangeOptionChanged: "gs-date-range-option-changed";
|
|
156
157
|
readonly mutationFilterChanged: "gs-mutation-filter-changed";
|
|
@@ -943,7 +944,7 @@ declare global {
|
|
|
943
944
|
|
|
944
945
|
declare global {
|
|
945
946
|
interface HTMLElementTagNameMap {
|
|
946
|
-
'gs-
|
|
947
|
+
'gs-mutations-component': MutationsComponent;
|
|
947
948
|
}
|
|
948
949
|
}
|
|
949
950
|
|
|
@@ -951,7 +952,7 @@ declare global {
|
|
|
951
952
|
declare global {
|
|
952
953
|
namespace JSX {
|
|
953
954
|
interface IntrinsicElements {
|
|
954
|
-
'gs-
|
|
955
|
+
'gs-mutations-component': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
955
956
|
}
|
|
956
957
|
}
|
|
957
958
|
}
|
|
@@ -959,7 +960,7 @@ declare global {
|
|
|
959
960
|
|
|
960
961
|
declare global {
|
|
961
962
|
interface HTMLElementTagNameMap {
|
|
962
|
-
'gs-
|
|
963
|
+
'gs-mutation-comparison-component': MutationComparisonComponent;
|
|
963
964
|
}
|
|
964
965
|
}
|
|
965
966
|
|
|
@@ -967,7 +968,7 @@ declare global {
|
|
|
967
968
|
declare global {
|
|
968
969
|
namespace JSX {
|
|
969
970
|
interface IntrinsicElements {
|
|
970
|
-
'gs-
|
|
971
|
+
'gs-mutation-comparison-component': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
971
972
|
}
|
|
972
973
|
}
|
|
973
974
|
}
|
|
@@ -1007,7 +1008,7 @@ declare global {
|
|
|
1007
1008
|
|
|
1008
1009
|
declare global {
|
|
1009
1010
|
interface HTMLElementTagNameMap {
|
|
1010
|
-
'gs-
|
|
1011
|
+
'gs-number-sequences-over-time': NumberSequencesOverTimeComponent;
|
|
1011
1012
|
}
|
|
1012
1013
|
}
|
|
1013
1014
|
|
|
@@ -1015,7 +1016,7 @@ declare global {
|
|
|
1015
1016
|
declare global {
|
|
1016
1017
|
namespace JSX {
|
|
1017
1018
|
interface IntrinsicElements {
|
|
1018
|
-
'gs-
|
|
1019
|
+
'gs-number-sequences-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1019
1020
|
}
|
|
1020
1021
|
}
|
|
1021
1022
|
}
|
|
@@ -1023,7 +1024,7 @@ declare global {
|
|
|
1023
1024
|
|
|
1024
1025
|
declare global {
|
|
1025
1026
|
interface HTMLElementTagNameMap {
|
|
1026
|
-
'gs-
|
|
1027
|
+
'gs-aggregate': AggregateComponent;
|
|
1027
1028
|
}
|
|
1028
1029
|
}
|
|
1029
1030
|
|
|
@@ -1031,7 +1032,7 @@ declare global {
|
|
|
1031
1032
|
declare global {
|
|
1032
1033
|
namespace JSX {
|
|
1033
1034
|
interface IntrinsicElements {
|
|
1034
|
-
'gs-
|
|
1035
|
+
'gs-aggregate': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1035
1036
|
}
|
|
1036
1037
|
}
|
|
1037
1038
|
}
|
|
@@ -1123,10 +1124,10 @@ declare global {
|
|
|
1123
1124
|
|
|
1124
1125
|
declare global {
|
|
1125
1126
|
interface HTMLElementTagNameMap {
|
|
1126
|
-
'gs-
|
|
1127
|
+
'gs-location-filter': LocationFilterComponent;
|
|
1127
1128
|
}
|
|
1128
1129
|
interface HTMLElementEventMap {
|
|
1129
|
-
[gsEventNames.
|
|
1130
|
+
[gsEventNames.locationChanged]: LocationChangedEvent;
|
|
1130
1131
|
}
|
|
1131
1132
|
}
|
|
1132
1133
|
|
|
@@ -1134,7 +1135,7 @@ declare global {
|
|
|
1134
1135
|
declare global {
|
|
1135
1136
|
namespace JSX {
|
|
1136
1137
|
interface IntrinsicElements {
|
|
1137
|
-
'gs-
|
|
1138
|
+
'gs-location-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1138
1139
|
}
|
|
1139
1140
|
}
|
|
1140
1141
|
}
|
|
@@ -1142,10 +1143,10 @@ declare global {
|
|
|
1142
1143
|
|
|
1143
1144
|
declare global {
|
|
1144
1145
|
interface HTMLElementTagNameMap {
|
|
1145
|
-
'gs-
|
|
1146
|
+
'gs-text-filter': TextFilterComponent;
|
|
1146
1147
|
}
|
|
1147
1148
|
interface HTMLElementEventMap {
|
|
1148
|
-
[gsEventNames.
|
|
1149
|
+
[gsEventNames.textFilterChanged]: TextFilterChangedEvent;
|
|
1149
1150
|
}
|
|
1150
1151
|
}
|
|
1151
1152
|
|
|
@@ -1153,7 +1154,7 @@ declare global {
|
|
|
1153
1154
|
declare global {
|
|
1154
1155
|
namespace JSX {
|
|
1155
1156
|
interface IntrinsicElements {
|
|
1156
|
-
'gs-
|
|
1157
|
+
'gs-text-filter': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1157
1158
|
}
|
|
1158
1159
|
}
|
|
1159
1160
|
}
|
package/dist/util.js
CHANGED
package/package.json
CHANGED
|
@@ -6,6 +6,7 @@ import { Aggregate, type AggregateProps } from './aggregate';
|
|
|
6
6
|
import { AGGREGATED_ENDPOINT, LAPIS_URL } from '../../constants';
|
|
7
7
|
import { LapisUrlContextProvider } from '../LapisUrlContext';
|
|
8
8
|
import { expectInvalidAttributesErrorMessage, playThatExpectsErrorMessage } from '../shared/stories/expectErrorMessage';
|
|
9
|
+
import { playThatExpectsFinishedLoadingEvent } from '../shared/stories/expectFinishedLoadingEvent';
|
|
9
10
|
|
|
10
11
|
const meta: Meta<AggregateProps> = {
|
|
11
12
|
title: 'Visualization/Aggregate',
|
|
@@ -62,6 +63,11 @@ export const Default: StoryObj<AggregateProps> = {
|
|
|
62
63
|
},
|
|
63
64
|
};
|
|
64
65
|
|
|
66
|
+
export const FiresFinishedLoadingEvent: StoryObj<AggregateProps> = {
|
|
67
|
+
...Default,
|
|
68
|
+
play: playThatExpectsFinishedLoadingEvent(),
|
|
69
|
+
};
|
|
70
|
+
|
|
65
71
|
export const FailsLoadingData: StoryObj<AggregateProps> = {
|
|
66
72
|
...Default,
|
|
67
73
|
parameters: {
|
|
@@ -5,6 +5,7 @@ import { useLapisUrl } from '../LapisUrlContext';
|
|
|
5
5
|
import { AggregateTable } from './aggregate-table';
|
|
6
6
|
import { type AggregateData, queryAggregateData } from '../../query/queryAggregateData';
|
|
7
7
|
import { lapisFilterSchema, views } from '../../types';
|
|
8
|
+
import { useDispatchFinishedLoadingEvent } from '../../utils/useDispatchFinishedLoadingEvent';
|
|
8
9
|
import { CsvDownloadButton } from '../components/csv-download-button';
|
|
9
10
|
import { ErrorBoundary } from '../components/error-boundary';
|
|
10
11
|
import { Fullscreen } from '../components/fullscreen';
|
|
@@ -75,6 +76,8 @@ type AggregatedDataTabsProps = {
|
|
|
75
76
|
};
|
|
76
77
|
|
|
77
78
|
const AggregatedDataTabs: FunctionComponent<AggregatedDataTabsProps> = ({ data, originalComponentProps }) => {
|
|
79
|
+
const tabsRef = useDispatchFinishedLoadingEvent();
|
|
80
|
+
|
|
78
81
|
const maintainAspectRatio = getMaintainAspectRatio(originalComponentProps.height);
|
|
79
82
|
|
|
80
83
|
const getTab = (view: AggregateView) => {
|
|
@@ -109,7 +112,13 @@ const AggregatedDataTabs: FunctionComponent<AggregatedDataTabsProps> = ({ data,
|
|
|
109
112
|
|
|
110
113
|
const tabs = originalComponentProps.views.map((view) => getTab(view));
|
|
111
114
|
|
|
112
|
-
return
|
|
115
|
+
return (
|
|
116
|
+
<Tabs
|
|
117
|
+
ref={tabsRef}
|
|
118
|
+
tabs={tabs}
|
|
119
|
+
toolbar={<Toolbar data={data} originalComponentProps={originalComponentProps} />}
|
|
120
|
+
/>
|
|
121
|
+
);
|
|
113
122
|
};
|
|
114
123
|
|
|
115
124
|
type ToolbarProps = {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { forwardRef } from 'preact/compat';
|
|
2
2
|
import { useState } from 'preact/hooks';
|
|
3
3
|
import { type JSXInternal } from 'preact/src/jsx';
|
|
4
4
|
|
|
@@ -12,7 +12,7 @@ interface ComponentTabsProps {
|
|
|
12
12
|
toolbar?: JSXInternal.Element | ((activeTab: string) => JSXInternal.Element);
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
const Tabs
|
|
15
|
+
const Tabs = forwardRef<HTMLDivElement, ComponentTabsProps>(({ tabs, toolbar }, ref) => {
|
|
16
16
|
const [activeTab, setActiveTab] = useState(tabs[0]?.title);
|
|
17
17
|
|
|
18
18
|
const tabElements = (
|
|
@@ -40,7 +40,7 @@ const Tabs: FunctionComponent<ComponentTabsProps> = ({ tabs, toolbar }) => {
|
|
|
40
40
|
const toolbarElement = typeof toolbar === 'function' ? toolbar(activeTab) : toolbar;
|
|
41
41
|
|
|
42
42
|
return (
|
|
43
|
-
<div className='h-full w-full flex flex-col'>
|
|
43
|
+
<div ref={ref} className='h-full w-full flex flex-col'>
|
|
44
44
|
<div className='flex flex-row justify-between flex-wrap'>
|
|
45
45
|
{tabElements}
|
|
46
46
|
{toolbar && <div className='py-2 flex flex-wrap gap-y-1'>{toolbarElement}</div>}
|
|
@@ -54,6 +54,6 @@ const Tabs: FunctionComponent<ComponentTabsProps> = ({ tabs, toolbar }) => {
|
|
|
54
54
|
</div>
|
|
55
55
|
</div>
|
|
56
56
|
);
|
|
57
|
-
};
|
|
57
|
+
});
|
|
58
58
|
|
|
59
59
|
export default Tabs;
|
|
@@ -2,6 +2,7 @@ import { Fragment, type FunctionComponent } from 'preact';
|
|
|
2
2
|
import { useMemo, useState } from 'preact/hooks';
|
|
3
3
|
|
|
4
4
|
import { type CDSFeature } from './loadGff3';
|
|
5
|
+
import { useDispatchFinishedLoadingEvent } from '../../utils/useDispatchFinishedLoadingEvent';
|
|
5
6
|
import { MinMaxRangeSlider } from '../components/min-max-range-slider';
|
|
6
7
|
import Tooltip from '../components/tooltip';
|
|
7
8
|
import { singleGraphColorRGBByName } from '../shared/charts/colors';
|
|
@@ -183,6 +184,8 @@ interface CDSProps {
|
|
|
183
184
|
}
|
|
184
185
|
|
|
185
186
|
const CDSPlot: FunctionComponent<CDSProps> = (componentProps) => {
|
|
187
|
+
const ref = useDispatchFinishedLoadingEvent();
|
|
188
|
+
|
|
186
189
|
const { gffData, genomeLength, width } = componentProps;
|
|
187
190
|
|
|
188
191
|
const [zoomStart, setZoomStart] = useState(0);
|
|
@@ -197,7 +200,7 @@ const CDSPlot: FunctionComponent<CDSProps> = (componentProps) => {
|
|
|
197
200
|
};
|
|
198
201
|
|
|
199
202
|
return (
|
|
200
|
-
<div class='p-4'>
|
|
203
|
+
<div ref={ref} class='p-4'>
|
|
201
204
|
<CDSBars gffData={gffData} zoomStart={zoomStart} zoomEnd={zoomEnd} />
|
|
202
205
|
<XAxis zoomStart={zoomStart} zoomEnd={zoomEnd} fullWidth={width} />
|
|
203
206
|
<div class='relative w-full h-5'>
|
|
@@ -2,6 +2,7 @@ import { type Meta, type StoryObj } from '@storybook/preact';
|
|
|
2
2
|
|
|
3
3
|
import { GenomeDataViewer, type GenomeDataViewerProps } from './genome-data-viewer';
|
|
4
4
|
import { playThatExpectsErrorMessage } from '../shared/stories/expectErrorMessage';
|
|
5
|
+
import { playThatExpectsFinishedLoadingEvent } from '../shared/stories/expectFinishedLoadingEvent';
|
|
5
6
|
|
|
6
7
|
const meta: Meta<GenomeDataViewerProps> = {
|
|
7
8
|
title: 'Visualization/GenomeDataViewer',
|
|
@@ -75,6 +76,11 @@ export const Default: StoryObj<GenomeDataViewerProps> = {
|
|
|
75
76
|
},
|
|
76
77
|
};
|
|
77
78
|
|
|
79
|
+
export const FiresFinishedLoadingEvent: StoryObj<GenomeDataViewerProps> = {
|
|
80
|
+
...Default,
|
|
81
|
+
play: playThatExpectsFinishedLoadingEvent(),
|
|
82
|
+
};
|
|
83
|
+
|
|
78
84
|
export const InvalidProps: StoryObj<GenomeDataViewerProps> = {
|
|
79
85
|
...Default,
|
|
80
86
|
args: {
|
|
@@ -10,6 +10,7 @@ import { type MutationAnnotations } from '../../web-components/mutation-annotati
|
|
|
10
10
|
import { LapisUrlContextProvider } from '../LapisUrlContext';
|
|
11
11
|
import { MutationAnnotationsContextProvider } from '../MutationAnnotationsContext';
|
|
12
12
|
import { ReferenceGenomeContext } from '../ReferenceGenomeContext';
|
|
13
|
+
import { playThatExpectsFinishedLoadingEvent } from '../shared/stories/expectFinishedLoadingEvent';
|
|
13
14
|
import { expectMutationAnnotation } from '../shared/stories/expectMutationAnnotation';
|
|
14
15
|
|
|
15
16
|
const dateToSomeDataset = '2022-01-01';
|
|
@@ -142,6 +143,11 @@ export const TwoVariants: StoryObj<MutationComparisonProps> = {
|
|
|
142
143
|
},
|
|
143
144
|
};
|
|
144
145
|
|
|
146
|
+
export const FiresFinishedLoadingEvent: StoryObj<MutationComparisonProps> = {
|
|
147
|
+
...TwoVariants,
|
|
148
|
+
play: playThatExpectsFinishedLoadingEvent(),
|
|
149
|
+
};
|
|
150
|
+
|
|
145
151
|
export const FilterForOnlyDeletions: StoryObj<MutationComparisonProps> = {
|
|
146
152
|
...TwoVariants,
|
|
147
153
|
play: async ({ canvasElement }) => {
|
|
@@ -7,6 +7,7 @@ import { MutationComparisonTable } from './mutation-comparison-table';
|
|
|
7
7
|
import { MutationComparisonVenn } from './mutation-comparison-venn';
|
|
8
8
|
import { filterMutationData, type MutationData, queryMutationData } from './queryMutationData';
|
|
9
9
|
import { namedLapisFilterSchema, sequenceTypeSchema, views } from '../../types';
|
|
10
|
+
import { useDispatchFinishedLoadingEvent } from '../../utils/useDispatchFinishedLoadingEvent';
|
|
10
11
|
import { useLapisUrl } from '../LapisUrlContext';
|
|
11
12
|
import { CsvDownloadButton } from '../components/csv-download-button';
|
|
12
13
|
import { ErrorBoundary } from '../components/error-boundary';
|
|
@@ -80,6 +81,8 @@ type MutationComparisonTabsProps = {
|
|
|
80
81
|
};
|
|
81
82
|
|
|
82
83
|
const MutationComparisonTabs: FunctionComponent<MutationComparisonTabsProps> = ({ data, originalComponentProps }) => {
|
|
84
|
+
const tabsRef = useDispatchFinishedLoadingEvent();
|
|
85
|
+
|
|
83
86
|
const [proportionInterval, setProportionInterval] = useState({ min: 0.5, max: 1 });
|
|
84
87
|
const [displayedMutationTypes, setDisplayedMutationTypes] = useState<DisplayedMutationType[]>([
|
|
85
88
|
{ label: 'Substitutions', checked: true, type: 'substitution' },
|
|
@@ -127,6 +130,7 @@ const MutationComparisonTabs: FunctionComponent<MutationComparisonTabsProps> = (
|
|
|
127
130
|
|
|
128
131
|
return (
|
|
129
132
|
<Tabs
|
|
133
|
+
ref={tabsRef}
|
|
130
134
|
tabs={tabs}
|
|
131
135
|
toolbar={
|
|
132
136
|
<Toolbar
|
|
@@ -17,6 +17,7 @@ import { type MutationAnnotations } from '../../web-components/mutation-annotati
|
|
|
17
17
|
import { LapisUrlContextProvider } from '../LapisUrlContext';
|
|
18
18
|
import { MutationAnnotationsContextProvider } from '../MutationAnnotationsContext';
|
|
19
19
|
import { ReferenceGenomeContext } from '../ReferenceGenomeContext';
|
|
20
|
+
import { playThatExpectsFinishedLoadingEvent } from '../shared/stories/expectFinishedLoadingEvent';
|
|
20
21
|
import { expectMutationAnnotation } from '../shared/stories/expectMutationAnnotation';
|
|
21
22
|
|
|
22
23
|
const meta: Meta<MutationsProps> = {
|
|
@@ -147,6 +148,11 @@ export const Default: StoryObj<MutationsProps> = {
|
|
|
147
148
|
},
|
|
148
149
|
};
|
|
149
150
|
|
|
151
|
+
export const FiresFinishedLoadingEvent: StoryObj<MutationsProps> = {
|
|
152
|
+
...Default,
|
|
153
|
+
play: playThatExpectsFinishedLoadingEvent(),
|
|
154
|
+
};
|
|
155
|
+
|
|
150
156
|
export const GridTab: StoryObj<MutationsProps> = {
|
|
151
157
|
...Default,
|
|
152
158
|
play: async ({ canvasElement, step }) => {
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
type SubstitutionOrDeletionEntry,
|
|
16
16
|
views,
|
|
17
17
|
} from '../../types';
|
|
18
|
+
import { useDispatchFinishedLoadingEvent } from '../../utils/useDispatchFinishedLoadingEvent';
|
|
18
19
|
import { useLapisUrl } from '../LapisUrlContext';
|
|
19
20
|
import { CsvDownloadButton } from '../components/csv-download-button';
|
|
20
21
|
import { ErrorBoundary } from '../components/error-boundary';
|
|
@@ -87,6 +88,8 @@ type MutationTabsProps = {
|
|
|
87
88
|
};
|
|
88
89
|
|
|
89
90
|
const MutationsTabs: FunctionComponent<MutationTabsProps> = ({ mutationsData, originalComponentProps }) => {
|
|
91
|
+
const tabsRef = useDispatchFinishedLoadingEvent();
|
|
92
|
+
|
|
90
93
|
const [proportionInterval, setProportionInterval] = useState({ min: 0.05, max: 1 });
|
|
91
94
|
|
|
92
95
|
const [displayedSegments, setDisplayedSegments] = useDisplayedSegments(originalComponentProps.sequenceType);
|
|
@@ -153,7 +156,7 @@ const MutationsTabs: FunctionComponent<MutationTabsProps> = ({ mutationsData, or
|
|
|
153
156
|
/>
|
|
154
157
|
);
|
|
155
158
|
|
|
156
|
-
return <Tabs tabs={tabs} toolbar={toolbar} />;
|
|
159
|
+
return <Tabs ref={tabsRef} tabs={tabs} toolbar={toolbar} />;
|
|
157
160
|
};
|
|
158
161
|
|
|
159
162
|
type ToolbarProps = {
|
|
@@ -10,6 +10,7 @@ import { LapisUrlContextProvider } from '../LapisUrlContext';
|
|
|
10
10
|
import { MutationAnnotationsContextProvider } from '../MutationAnnotationsContext';
|
|
11
11
|
import { ReferenceGenomeContext } from '../ReferenceGenomeContext';
|
|
12
12
|
import { expectInvalidAttributesErrorMessage } from '../shared/stories/expectErrorMessage';
|
|
13
|
+
import { playThatExpectsFinishedLoadingEvent } from '../shared/stories/expectFinishedLoadingEvent';
|
|
13
14
|
import { expectMutationAnnotation } from '../shared/stories/expectMutationAnnotation';
|
|
14
15
|
|
|
15
16
|
const meta: Meta<MutationsOverTimeProps> = {
|
|
@@ -83,6 +84,11 @@ export const Default: StoryObj<MutationsOverTimeProps> = {
|
|
|
83
84
|
},
|
|
84
85
|
};
|
|
85
86
|
|
|
87
|
+
export const FiresFinishedLoadingEvent: StoryObj<MutationsOverTimeProps> = {
|
|
88
|
+
...Default,
|
|
89
|
+
play: playThatExpectsFinishedLoadingEvent(),
|
|
90
|
+
};
|
|
91
|
+
|
|
86
92
|
export const ShowsMutationAnnotations: StoryObj<MutationsOverTimeProps> = {
|
|
87
93
|
...Default,
|
|
88
94
|
play: async ({ canvasElement }) => {
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
} from '../../types';
|
|
19
19
|
import { type Deletion, type Substitution } from '../../utils/mutations';
|
|
20
20
|
import { toTemporalClass } from '../../utils/temporalClass';
|
|
21
|
+
import { useDispatchFinishedLoadingEvent } from '../../utils/useDispatchFinishedLoadingEvent';
|
|
21
22
|
import { useLapisUrl } from '../LapisUrlContext';
|
|
22
23
|
import { useMutationAnnotationsProvider } from '../MutationAnnotationsContext';
|
|
23
24
|
import { type ColorScale } from '../components/color-scale-selector';
|
|
@@ -126,6 +127,8 @@ const MutationsOverTimeTabs: FunctionComponent<MutationOverTimeTabsProps> = ({
|
|
|
126
127
|
originalComponentProps,
|
|
127
128
|
overallMutationData,
|
|
128
129
|
}) => {
|
|
130
|
+
const tabsRef = useDispatchFinishedLoadingEvent();
|
|
131
|
+
|
|
129
132
|
const [mutationFilterValue, setMutationFilterValue] = useState('');
|
|
130
133
|
const annotationProvider = useMutationAnnotationsProvider();
|
|
131
134
|
|
|
@@ -207,7 +210,7 @@ const MutationsOverTimeTabs: FunctionComponent<MutationOverTimeTabsProps> = ({
|
|
|
207
210
|
|
|
208
211
|
return (
|
|
209
212
|
<PageSizeContextProvider pageSizes={originalComponentProps.pageSizes}>
|
|
210
|
-
<Tabs tabs={tabs} toolbar={toolbar} />
|
|
213
|
+
<Tabs ref={tabsRef} tabs={tabs} toolbar={toolbar} />
|
|
211
214
|
</PageSizeContextProvider>
|
|
212
215
|
);
|
|
213
216
|
};
|
|
@@ -7,6 +7,7 @@ import twoVariantsEG from '../../preact/numberSequencesOverTime/__mockData__/two
|
|
|
7
7
|
import twoVariantsJN1 from '../../preact/numberSequencesOverTime/__mockData__/twoVariantsJN1.json';
|
|
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/NumberSequencesOverTime',
|
|
@@ -71,8 +72,9 @@ const Template: StoryObj<NumberSequencesOverTimeProps> = {
|
|
|
71
72
|
},
|
|
72
73
|
};
|
|
73
74
|
|
|
74
|
-
export const
|
|
75
|
+
export const FiresFinishedLoadingEvent: StoryObj<NumberSequencesOverTimeProps> = {
|
|
75
76
|
...Template,
|
|
77
|
+
play: playThatExpectsFinishedLoadingEvent(),
|
|
76
78
|
};
|
|
77
79
|
|
|
78
80
|
export const TwoVariants: StoryObj<NumberSequencesOverTimeProps> = {
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
queryNumberOfSequencesOverTime,
|
|
12
12
|
} from '../../query/queryNumberOfSequencesOverTime';
|
|
13
13
|
import { namedLapisFilterSchema, temporalGranularitySchema, views } from '../../types';
|
|
14
|
+
import { useDispatchFinishedLoadingEvent } from '../../utils/useDispatchFinishedLoadingEvent';
|
|
14
15
|
import { useLapisUrl } from '../LapisUrlContext';
|
|
15
16
|
import { CsvDownloadButton } from '../components/csv-download-button';
|
|
16
17
|
import { ErrorBoundary } from '../components/error-boundary';
|
|
@@ -88,6 +89,8 @@ interface NumberSequencesOverTimeTabsProps {
|
|
|
88
89
|
}
|
|
89
90
|
|
|
90
91
|
const NumberSequencesOverTimeTabs = ({ data, originalComponentProps }: NumberSequencesOverTimeTabsProps) => {
|
|
92
|
+
const tabsRef = useDispatchFinishedLoadingEvent();
|
|
93
|
+
|
|
91
94
|
const [yAxisScaleType, setYAxisScaleType] = useState<ScaleType>('linear');
|
|
92
95
|
|
|
93
96
|
const maintainAspectRatio = getMaintainAspectRatio(originalComponentProps.height);
|
|
@@ -134,6 +137,7 @@ const NumberSequencesOverTimeTabs = ({ data, originalComponentProps }: NumberSeq
|
|
|
134
137
|
|
|
135
138
|
return (
|
|
136
139
|
<Tabs
|
|
140
|
+
ref={tabsRef}
|
|
137
141
|
tabs={originalComponentProps.views.map((view) => getTab(view))}
|
|
138
142
|
toolbar={(activeTab) => (
|
|
139
143
|
<Toolbar
|
|
@@ -11,6 +11,7 @@ import numeratorOneDataset from './__mockData__/numeratorFilterOneDataset.json';
|
|
|
11
11
|
import { PrevalenceOverTime, type PrevalenceOverTimeProps } from './prevalence-over-time';
|
|
12
12
|
import { AGGREGATED_ENDPOINT, LAPIS_URL } from '../../constants';
|
|
13
13
|
import { expectInvalidAttributesErrorMessage } from '../shared/stories/expectErrorMessage';
|
|
14
|
+
import { playThatExpectsFinishedLoadingEvent } from '../shared/stories/expectFinishedLoadingEvent';
|
|
14
15
|
|
|
15
16
|
export default {
|
|
16
17
|
title: 'Visualization/PrevalenceOverTime',
|
|
@@ -121,6 +122,11 @@ export const TwoVariants: StoryObj<PrevalenceOverTimeProps> = {
|
|
|
121
122
|
},
|
|
122
123
|
};
|
|
123
124
|
|
|
125
|
+
export const FiresFinishedLoadingEvent: StoryObj<PrevalenceOverTimeProps> = {
|
|
126
|
+
...TwoVariants,
|
|
127
|
+
play: playThatExpectsFinishedLoadingEvent(),
|
|
128
|
+
};
|
|
129
|
+
|
|
124
130
|
export const OneVariant: StoryObj<PrevalenceOverTimeProps> = {
|
|
125
131
|
...Template,
|
|
126
132
|
args: {
|
|
@@ -9,6 +9,7 @@ import PrevalenceOverTimeLineChart from './prevalence-over-time-line-chart';
|
|
|
9
9
|
import PrevalenceOverTimeTable from './prevalence-over-time-table';
|
|
10
10
|
import { type PrevalenceOverTimeData, queryPrevalenceOverTime } from '../../query/queryPrevalenceOverTime';
|
|
11
11
|
import { lapisFilterSchema, namedLapisFilterSchema, temporalGranularitySchema, views } from '../../types';
|
|
12
|
+
import { useDispatchFinishedLoadingEvent } from '../../utils/useDispatchFinishedLoadingEvent';
|
|
12
13
|
import { useLapisUrl } from '../LapisUrlContext';
|
|
13
14
|
import { ConfidenceIntervalSelector } from '../components/confidence-interval-selector';
|
|
14
15
|
import { CsvDownloadButton } from '../components/csv-download-button';
|
|
@@ -101,6 +102,8 @@ type PrevalenceOverTimeTabsProps = PrevalenceOverTimeProps & {
|
|
|
101
102
|
};
|
|
102
103
|
|
|
103
104
|
const PrevalenceOverTimeTabs: FunctionComponent<PrevalenceOverTimeTabsProps> = ({ data, ...componentProps }) => {
|
|
105
|
+
const tabsRef = useDispatchFinishedLoadingEvent();
|
|
106
|
+
|
|
104
107
|
const { views, granularity, confidenceIntervalMethods, pageSize, yAxisMaxLinear, yAxisMaxLogarithmic } =
|
|
105
108
|
componentProps;
|
|
106
109
|
const [yAxisScaleType, setYAxisScaleType] = useState<ScaleType>('linear');
|
|
@@ -182,7 +185,7 @@ const PrevalenceOverTimeTabs: FunctionComponent<PrevalenceOverTimeTabsProps> = (
|
|
|
182
185
|
/>
|
|
183
186
|
);
|
|
184
187
|
|
|
185
|
-
return <Tabs tabs={tabs} toolbar={toolbar} />;
|
|
188
|
+
return <Tabs ref={tabsRef} tabs={tabs} toolbar={toolbar} />;
|
|
186
189
|
};
|
|
187
190
|
|
|
188
191
|
type ToolbarProps = PrevalenceOverTimeProps & {
|
|
@@ -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>
|