@genspectrum/dashboard-components 0.10.3 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/custom-elements.json +384 -56
- package/dist/assets/mutationOverTimeWorker-BjjkMGzd.js.map +1 -0
- package/dist/components.d.ts +250 -31
- package/dist/components.js +1220 -198
- package/dist/components.js.map +1 -1
- package/dist/{dateRangeOption-DjtcAEWq.js → dateRangeOption-Bh2p78z0.js} +11 -5
- package/dist/dateRangeOption-Bh2p78z0.js.map +1 -0
- package/dist/style.css +5 -1
- package/dist/util.d.ts +626 -16
- package/dist/util.js +1 -1
- package/package.json +13 -7
- package/src/preact/aggregatedData/aggregate.stories.tsx +2 -2
- package/src/preact/aggregatedData/aggregate.tsx +11 -8
- package/src/preact/dateRangeSelector/date-range-selector.stories.tsx +4 -12
- package/src/preact/dateRangeSelector/date-range-selector.tsx +4 -4
- package/src/preact/lineageFilter/lineage-filter.stories.tsx +1 -1
- package/src/preact/locationFilter/location-filter.stories.tsx +1 -1
- package/src/preact/map/__mockData__/aggregatedGermany.json +83 -0
- package/src/preact/map/__mockData__/aggregatedWorld.json +259 -0
- package/src/preact/map/__mockData__/germanyMap.json +9083 -0
- package/src/preact/map/__mockData__/howToGenerateWorldMap.md +9 -0
- package/src/preact/map/__mockData__/worldAtlas.json +497127 -0
- package/src/preact/map/leafletStyleModifications.css +3 -0
- package/src/preact/map/sequences-by-location-map.tsx +202 -0
- package/src/preact/map/sequences-by-location-table.tsx +18 -0
- package/src/preact/map/sequences-by-location.stories.tsx +144 -0
- package/src/preact/map/sequences-by-location.tsx +151 -0
- package/src/preact/map/useGeoJsonMap.tsx +62 -0
- package/src/preact/mutationComparison/mutation-comparison.tsx +5 -7
- package/src/preact/mutationFilter/mutation-filter.tsx +4 -13
- package/src/preact/mutations/mutations.tsx +4 -4
- package/src/preact/mutationsOverTime/mutations-over-time.stories.tsx +1 -1
- package/src/preact/mutationsOverTime/mutations-over-time.tsx +4 -4
- package/src/preact/numberSequencesOverTime/number-sequences-over-time.stories.tsx +5 -14
- package/src/preact/numberSequencesOverTime/number-sequences-over-time.tsx +4 -4
- package/src/preact/prevalenceOverTime/prevalence-over-time.stories.tsx +15 -26
- package/src/preact/prevalenceOverTime/prevalence-over-time.tsx +8 -8
- package/src/preact/relativeGrowthAdvantage/relative-growth-advantage.stories.tsx +4 -15
- package/src/preact/relativeGrowthAdvantage/relative-growth-advantage.tsx +11 -7
- package/src/preact/shared/stories/expectErrorMessage.ts +21 -0
- package/src/preact/textInput/text-input.stories.tsx +1 -1
- package/src/preact/useQuery.ts +9 -1
- package/src/query/queryNumberOfSequencesOverTime.spec.ts +4 -4
- package/src/query/queryNumberOfSequencesOverTime.ts +1 -4
- package/src/query/queryPrevalenceOverTime.ts +1 -4
- package/src/styles/tailwind.css +1 -1
- package/src/types.ts +12 -4
- package/src/utilEntrypoint.ts +16 -4
- package/src/utils/utils.ts +0 -29
- package/src/web-components/app.ts +1 -1
- package/src/web-components/input/gs-date-range-selector.stories.ts +4 -4
- package/src/web-components/input/gs-date-range-selector.tsx +5 -5
- package/src/web-components/input/gs-lineage-filter.tsx +1 -1
- package/src/web-components/input/gs-location-filter.tsx +1 -1
- package/src/web-components/input/gs-mutation-filter.tsx +5 -8
- package/src/web-components/input/gs-text-input.tsx +1 -1
- package/src/web-components/visualization/gs-aggregate.stories.ts +3 -3
- package/src/web-components/visualization/gs-aggregate.tsx +10 -6
- package/src/web-components/visualization/gs-mutation-comparison.tsx +7 -2
- package/src/web-components/visualization/gs-mutations-over-time.tsx +7 -2
- package/src/web-components/visualization/gs-mutations.tsx +7 -2
- package/src/web-components/visualization/gs-number-sequences-over-time.stories.ts +5 -5
- package/src/web-components/visualization/gs-number-sequences-over-time.tsx +13 -15
- package/src/web-components/visualization/gs-prevalence-over-time.stories.ts +8 -8
- package/src/web-components/visualization/gs-prevalence-over-time.tsx +17 -14
- package/src/web-components/visualization/gs-relative-growth-advantage.stories.ts +4 -5
- package/src/web-components/visualization/gs-relative-growth-advantage.tsx +17 -15
- package/src/web-components/visualization/gs-sequences-by-location.stories.ts +234 -0
- package/src/web-components/visualization/gs-sequences-by-location.tsx +258 -0
- package/src/web-components/visualization/gs-statistics.tsx +12 -3
- package/src/web-components/visualization/index.ts +1 -0
- package/standalone-bundle/assets/mutationOverTimeWorker-DoUBht2e.js.map +1 -0
- package/standalone-bundle/dashboard-components.js +16208 -9408
- package/standalone-bundle/dashboard-components.js.map +1 -1
- package/standalone-bundle/style.css +1 -1
- package/dist/assets/mutationOverTimeWorker-CNg_ztNp.js.map +0 -1
- package/dist/dateRangeOption-DjtcAEWq.js.map +0 -1
- package/src/preact/shared/stories/expectInvalidAttributesErrorMessage.ts +0 -13
- package/src/utils/utils.spec.ts +0 -16
- package/standalone-bundle/assets/mutationOverTimeWorker-cIyshfj_.js.map +0 -1
|
@@ -6,7 +6,7 @@ import { LAPIS_URL } from '../../constants';
|
|
|
6
6
|
import referenceGenome from '../../lapisApi/__mockData__/referenceGenome.json';
|
|
7
7
|
import { LapisUrlContext } from '../LapisUrlContext';
|
|
8
8
|
import { ReferenceGenomeContext } from '../ReferenceGenomeContext';
|
|
9
|
-
import { expectInvalidAttributesErrorMessage } from '../shared/stories/
|
|
9
|
+
import { expectInvalidAttributesErrorMessage } from '../shared/stories/expectErrorMessage';
|
|
10
10
|
|
|
11
11
|
const meta: Meta<MutationsOverTimeProps> = {
|
|
12
12
|
title: 'Visualization/Mutation over time',
|
|
@@ -35,13 +35,13 @@ import { type DisplayedSegment, SegmentSelector, useDisplayedSegments } from '..
|
|
|
35
35
|
import Tabs from '../components/tabs';
|
|
36
36
|
import { useWebWorker } from '../webWorkers/useWebWorker';
|
|
37
37
|
|
|
38
|
-
const
|
|
39
|
-
export type
|
|
38
|
+
const mutationsOverTimeViewSchema = z.literal(views.grid);
|
|
39
|
+
export type MutationsOverTimeView = z.infer<typeof mutationsOverTimeViewSchema>;
|
|
40
40
|
|
|
41
41
|
const mutationOverTimeSchema = z.object({
|
|
42
42
|
lapisFilter: lapisFilterSchema,
|
|
43
43
|
sequenceType: sequenceTypeSchema,
|
|
44
|
-
views: z.array(
|
|
44
|
+
views: z.array(mutationsOverTimeViewSchema),
|
|
45
45
|
granularity: temporalGranularitySchema,
|
|
46
46
|
lapisDateField: z.string().min(1),
|
|
47
47
|
width: z.string(),
|
|
@@ -134,7 +134,7 @@ const MutationsOverTimeTabs: FunctionComponent<MutationOverTimeTabsProps> = ({
|
|
|
134
134
|
);
|
|
135
135
|
}, [mutationOverTimeData, overallMutationData, displayedSegments, displayedMutationTypes, proportionInterval]);
|
|
136
136
|
|
|
137
|
-
const getTab = (view:
|
|
137
|
+
const getTab = (view: MutationsOverTimeView) => {
|
|
138
138
|
if (filteredData === undefined) {
|
|
139
139
|
return {
|
|
140
140
|
title: 'Calculating',
|
|
@@ -6,7 +6,7 @@ import oneVariantEG from '../../preact/numberSequencesOverTime/__mockData__/oneV
|
|
|
6
6
|
import twoVariantsEG from '../../preact/numberSequencesOverTime/__mockData__/twoVariantsEG.json';
|
|
7
7
|
import twoVariantsJN1 from '../../preact/numberSequencesOverTime/__mockData__/twoVariantsJN1.json';
|
|
8
8
|
import { LapisUrlContext } from '../LapisUrlContext';
|
|
9
|
-
import { expectInvalidAttributesErrorMessage } from '../shared/stories/
|
|
9
|
+
import { expectInvalidAttributesErrorMessage } from '../shared/stories/expectErrorMessage';
|
|
10
10
|
|
|
11
11
|
export default {
|
|
12
12
|
title: 'Visualization/NumberSequencesOverTime',
|
|
@@ -30,21 +30,12 @@ export default {
|
|
|
30
30
|
const Template: StoryObj<NumberSequencesOverTimeProps> = {
|
|
31
31
|
render: (args) => (
|
|
32
32
|
<LapisUrlContext.Provider value={LAPIS_URL}>
|
|
33
|
-
<NumberSequencesOverTime
|
|
34
|
-
lapisFilter={args.lapisFilter}
|
|
35
|
-
lapisDateField={args.lapisDateField}
|
|
36
|
-
views={args.views}
|
|
37
|
-
width={args.width}
|
|
38
|
-
height={args.height}
|
|
39
|
-
granularity={args.granularity}
|
|
40
|
-
smoothingWindow={args.smoothingWindow}
|
|
41
|
-
pageSize={args.pageSize}
|
|
42
|
-
/>
|
|
33
|
+
<NumberSequencesOverTime {...args} />
|
|
43
34
|
</LapisUrlContext.Provider>
|
|
44
35
|
),
|
|
45
36
|
args: {
|
|
46
37
|
views: ['bar', 'line', 'table'],
|
|
47
|
-
|
|
38
|
+
lapisFilters: [
|
|
48
39
|
{ displayName: 'EG', lapisFilter: { country: 'USA', pangoLineage: 'EG*', dateFrom: '2022-12-01' } },
|
|
49
40
|
],
|
|
50
41
|
lapisDateField: 'date',
|
|
@@ -82,11 +73,11 @@ export const Table = {
|
|
|
82
73
|
...Template,
|
|
83
74
|
};
|
|
84
75
|
|
|
85
|
-
export const TwoVariants = {
|
|
76
|
+
export const TwoVariants: StoryObj<NumberSequencesOverTimeProps> = {
|
|
86
77
|
...Template,
|
|
87
78
|
args: {
|
|
88
79
|
...Template.args,
|
|
89
|
-
|
|
80
|
+
lapisFilters: [
|
|
90
81
|
{ displayName: 'EG', lapisFilter: { country: 'USA', pangoLineage: 'EG*', dateTo: '2023-06-30' } },
|
|
91
82
|
{ displayName: 'JN.1', lapisFilter: { country: 'USA', pangoLineage: 'JN.1*', dateFrom: '2023-01-01' } },
|
|
92
83
|
],
|
|
@@ -34,7 +34,7 @@ export type NumberSequencesOverTimeView = z.infer<typeof numberSequencesOverTime
|
|
|
34
34
|
const numberSequencesOverTimePropsSchema = z.object({
|
|
35
35
|
width: z.string(),
|
|
36
36
|
height: z.string(),
|
|
37
|
-
|
|
37
|
+
lapisFilters: z.array(namedLapisFilterSchema).min(1),
|
|
38
38
|
lapisDateField: z.string().min(1),
|
|
39
39
|
views: z.array(numberSequencesOverTimeViewSchema),
|
|
40
40
|
granularity: temporalGranularitySchema,
|
|
@@ -58,12 +58,12 @@ export const NumberSequencesOverTime = (componentProps: NumberSequencesOverTimeP
|
|
|
58
58
|
};
|
|
59
59
|
|
|
60
60
|
const NumberSequencesOverTimeInner = (componentProps: NumberSequencesOverTimeProps) => {
|
|
61
|
-
const {
|
|
61
|
+
const { lapisFilters, lapisDateField, granularity, smoothingWindow } = componentProps;
|
|
62
62
|
const lapis = useContext(LapisUrlContext);
|
|
63
63
|
|
|
64
64
|
const { data, error, isLoading } = useQuery(
|
|
65
|
-
() => queryNumberOfSequencesOverTime(lapis,
|
|
66
|
-
[lapis,
|
|
65
|
+
() => queryNumberOfSequencesOverTime(lapis, lapisFilters, lapisDateField, granularity, smoothingWindow),
|
|
66
|
+
[lapis, lapisFilters, lapisDateField, granularity, smoothingWindow],
|
|
67
67
|
);
|
|
68
68
|
|
|
69
69
|
if (isLoading) {
|
|
@@ -10,7 +10,7 @@ import numeratorFilterNoData from './__mockData__/numeratorFilterNoData.json';
|
|
|
10
10
|
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
|
-
import { expectInvalidAttributesErrorMessage } from '../shared/stories/
|
|
13
|
+
import { expectInvalidAttributesErrorMessage } from '../shared/stories/expectErrorMessage';
|
|
14
14
|
|
|
15
15
|
export default {
|
|
16
16
|
title: 'Visualization/PrevalenceOverTime',
|
|
@@ -19,8 +19,6 @@ export default {
|
|
|
19
19
|
fetchMock: {},
|
|
20
20
|
},
|
|
21
21
|
argTypes: {
|
|
22
|
-
numerator: { control: 'object' },
|
|
23
|
-
denominator: { control: 'object' },
|
|
24
22
|
granularity: {
|
|
25
23
|
options: ['day', 'week', 'month', 'year'],
|
|
26
24
|
control: { type: 'radio' },
|
|
@@ -45,20 +43,7 @@ export default {
|
|
|
45
43
|
const Template = {
|
|
46
44
|
render: (args: PrevalenceOverTimeProps) => (
|
|
47
45
|
<LapisUrlContext.Provider value={LAPIS_URL}>
|
|
48
|
-
<PrevalenceOverTime
|
|
49
|
-
numeratorFilter={args.numeratorFilter}
|
|
50
|
-
denominatorFilter={args.denominatorFilter}
|
|
51
|
-
granularity={args.granularity}
|
|
52
|
-
smoothingWindow={args.smoothingWindow}
|
|
53
|
-
views={args.views}
|
|
54
|
-
confidenceIntervalMethods={args.confidenceIntervalMethods}
|
|
55
|
-
width={args.width}
|
|
56
|
-
height={args.height}
|
|
57
|
-
lapisDateField={args.lapisDateField}
|
|
58
|
-
pageSize={args.pageSize}
|
|
59
|
-
yAxisMaxLinear={args.yAxisMaxLinear}
|
|
60
|
-
yAxisMaxLogarithmic={args.yAxisMaxLogarithmic}
|
|
61
|
-
/>
|
|
46
|
+
<PrevalenceOverTime {...args} />
|
|
62
47
|
</LapisUrlContext.Provider>
|
|
63
48
|
),
|
|
64
49
|
};
|
|
@@ -66,7 +51,7 @@ const Template = {
|
|
|
66
51
|
export const TwoVariants: StoryObj<PrevalenceOverTimeProps> = {
|
|
67
52
|
...Template,
|
|
68
53
|
args: {
|
|
69
|
-
|
|
54
|
+
numeratorFilters: [
|
|
70
55
|
{ displayName: 'EG', lapisFilter: { country: 'USA', pangoLineage: 'EG*', dateFrom: '2023-01-01' } },
|
|
71
56
|
{ displayName: 'JN.1', lapisFilter: { country: 'USA', pangoLineage: 'JN.1*', dateFrom: '2023-01-01' } },
|
|
72
57
|
],
|
|
@@ -140,10 +125,12 @@ export const TwoVariants: StoryObj<PrevalenceOverTimeProps> = {
|
|
|
140
125
|
export const OneVariant: StoryObj<PrevalenceOverTimeProps> = {
|
|
141
126
|
...Template,
|
|
142
127
|
args: {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
128
|
+
numeratorFilters: [
|
|
129
|
+
{
|
|
130
|
+
displayName: 'EG',
|
|
131
|
+
lapisFilter: { country: 'USA', pangoLineage: 'BA.2.86*', dateFrom: '2023-10-01' },
|
|
132
|
+
},
|
|
133
|
+
],
|
|
147
134
|
denominatorFilter: { country: 'USA', dateFrom: '2023-10-01' },
|
|
148
135
|
granularity: 'day',
|
|
149
136
|
smoothingWindow: 7,
|
|
@@ -198,10 +185,12 @@ export const OneVariant: StoryObj<PrevalenceOverTimeProps> = {
|
|
|
198
185
|
export const ShowsNoDataBanner: StoryObj<PrevalenceOverTimeProps> = {
|
|
199
186
|
...Template,
|
|
200
187
|
args: {
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
188
|
+
numeratorFilters: [
|
|
189
|
+
{
|
|
190
|
+
displayName: 'EG',
|
|
191
|
+
lapisFilter: { country: 'USA', pangoLineage: 'BA.2.86*', dateFrom: '2023-10-01' },
|
|
192
|
+
},
|
|
193
|
+
],
|
|
205
194
|
denominatorFilter: { country: 'USA', dateFrom: '2023-10-01' },
|
|
206
195
|
granularity: 'day',
|
|
207
196
|
smoothingWindow: 7,
|
|
@@ -25,22 +25,22 @@ import { axisMaxSchema } from '../shared/charts/getYAxisMax';
|
|
|
25
25
|
import { type ScaleType } from '../shared/charts/getYAxisScale';
|
|
26
26
|
import { useQuery } from '../useQuery';
|
|
27
27
|
|
|
28
|
-
const
|
|
28
|
+
const prevalenceOverTimeViewSchema = z.union([
|
|
29
29
|
z.literal(views.table),
|
|
30
30
|
z.literal(views.bar),
|
|
31
31
|
z.literal(views.line),
|
|
32
32
|
z.literal(views.bubble),
|
|
33
33
|
]);
|
|
34
|
-
export type
|
|
34
|
+
export type PrevalenceOverTimeView = z.infer<typeof prevalenceOverTimeViewSchema>;
|
|
35
35
|
|
|
36
36
|
const prevalenceOverTimePropsSchema = z.object({
|
|
37
37
|
width: z.string(),
|
|
38
38
|
height: z.string(),
|
|
39
|
-
|
|
39
|
+
numeratorFilters: z.array(namedLapisFilterSchema).min(1),
|
|
40
40
|
denominatorFilter: lapisFilterSchema,
|
|
41
41
|
granularity: temporalGranularitySchema,
|
|
42
42
|
smoothingWindow: z.number(),
|
|
43
|
-
views: z.array(
|
|
43
|
+
views: z.array(prevalenceOverTimeViewSchema),
|
|
44
44
|
confidenceIntervalMethods: z.array(confidenceIntervalMethodSchema),
|
|
45
45
|
lapisDateField: z.string().min(1),
|
|
46
46
|
pageSize: z.union([z.boolean(), z.number()]),
|
|
@@ -64,20 +64,20 @@ export const PrevalenceOverTime: FunctionComponent<PrevalenceOverTimeProps> = (c
|
|
|
64
64
|
};
|
|
65
65
|
|
|
66
66
|
export const PrevalenceOverTimeInner: FunctionComponent<PrevalenceOverTimeProps> = (componentProps) => {
|
|
67
|
-
const {
|
|
67
|
+
const { numeratorFilters, denominatorFilter, granularity, smoothingWindow, lapisDateField } = componentProps;
|
|
68
68
|
const lapis = useContext(LapisUrlContext);
|
|
69
69
|
|
|
70
70
|
const { data, error, isLoading } = useQuery(
|
|
71
71
|
() =>
|
|
72
72
|
queryPrevalenceOverTime(
|
|
73
|
-
|
|
73
|
+
numeratorFilters,
|
|
74
74
|
denominatorFilter,
|
|
75
75
|
granularity,
|
|
76
76
|
smoothingWindow,
|
|
77
77
|
lapis,
|
|
78
78
|
lapisDateField,
|
|
79
79
|
),
|
|
80
|
-
[lapis,
|
|
80
|
+
[lapis, numeratorFilters, denominatorFilter, granularity, smoothingWindow, lapisDateField],
|
|
81
81
|
);
|
|
82
82
|
|
|
83
83
|
if (isLoading) {
|
|
@@ -118,7 +118,7 @@ const PrevalenceOverTimeTabs: FunctionComponent<PrevalenceOverTimeTabsProps> = (
|
|
|
118
118
|
|
|
119
119
|
const yAxisMaxConfig = { linear: yAxisMaxLinear, logarithmic: yAxisMaxLogarithmic };
|
|
120
120
|
|
|
121
|
-
const getTab = (view:
|
|
121
|
+
const getTab = (view: PrevalenceOverTimeView) => {
|
|
122
122
|
switch (view) {
|
|
123
123
|
case 'bar':
|
|
124
124
|
return {
|
|
@@ -6,7 +6,7 @@ import numerator from './__mockData__/numeratorFilter.json';
|
|
|
6
6
|
import { RelativeGrowthAdvantage, type RelativeGrowthAdvantageProps } from './relative-growth-advantage';
|
|
7
7
|
import { AGGREGATED_ENDPOINT, LAPIS_URL } from '../../constants';
|
|
8
8
|
import { LapisUrlContext } from '../LapisUrlContext';
|
|
9
|
-
import { expectInvalidAttributesErrorMessage } from '../shared/stories/
|
|
9
|
+
import { expectInvalidAttributesErrorMessage } from '../shared/stories/expectErrorMessage';
|
|
10
10
|
|
|
11
11
|
export default {
|
|
12
12
|
title: 'Visualization/RelativeGrowthAdvantage',
|
|
@@ -31,16 +31,7 @@ export default {
|
|
|
31
31
|
export const Primary: StoryObj<RelativeGrowthAdvantageProps> = {
|
|
32
32
|
render: (args: RelativeGrowthAdvantageProps) => (
|
|
33
33
|
<LapisUrlContext.Provider value={LAPIS_URL}>
|
|
34
|
-
<RelativeGrowthAdvantage
|
|
35
|
-
numeratorFilter={args.numeratorFilter}
|
|
36
|
-
denominatorFilter={args.denominatorFilter}
|
|
37
|
-
generationTime={args.generationTime}
|
|
38
|
-
views={args.views}
|
|
39
|
-
width={args.width}
|
|
40
|
-
height={args.height}
|
|
41
|
-
lapisDateField={args.lapisDateField}
|
|
42
|
-
yAxisMaxConfig={args.yAxisMaxConfig}
|
|
43
|
-
/>
|
|
34
|
+
<RelativeGrowthAdvantage {...args} />
|
|
44
35
|
</LapisUrlContext.Provider>
|
|
45
36
|
),
|
|
46
37
|
args: {
|
|
@@ -56,10 +47,8 @@ export const Primary: StoryObj<RelativeGrowthAdvantageProps> = {
|
|
|
56
47
|
width: '100%',
|
|
57
48
|
height: '700px',
|
|
58
49
|
lapisDateField: 'date',
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
logarithmic: 1,
|
|
62
|
-
},
|
|
50
|
+
yAxisMaxLinear: 1,
|
|
51
|
+
yAxisMaxLogarithmic: 1,
|
|
63
52
|
},
|
|
64
53
|
parameters: {
|
|
65
54
|
fetchMock: {
|
|
@@ -18,12 +18,12 @@ import { NoDataDisplay } from '../components/no-data-display';
|
|
|
18
18
|
import { ResizeContainer } from '../components/resize-container';
|
|
19
19
|
import { ScalingSelector } from '../components/scaling-selector';
|
|
20
20
|
import Tabs from '../components/tabs';
|
|
21
|
-
import {
|
|
21
|
+
import { axisMaxSchema } from '../shared/charts/getYAxisMax';
|
|
22
22
|
import { type ScaleType } from '../shared/charts/getYAxisScale';
|
|
23
23
|
import { useQuery } from '../useQuery';
|
|
24
24
|
|
|
25
|
-
const
|
|
26
|
-
export type
|
|
25
|
+
const relativeGrowthAdvantageViewSchema = z.literal(views.line);
|
|
26
|
+
export type RelativeGrowthAdvantageView = z.infer<typeof relativeGrowthAdvantageViewSchema>;
|
|
27
27
|
|
|
28
28
|
export const relativeGrowthAdvantagePropsSchema = z.object({
|
|
29
29
|
width: z.string(),
|
|
@@ -31,9 +31,10 @@ export const relativeGrowthAdvantagePropsSchema = z.object({
|
|
|
31
31
|
numeratorFilter: lapisFilterSchema,
|
|
32
32
|
denominatorFilter: lapisFilterSchema,
|
|
33
33
|
generationTime: z.number(),
|
|
34
|
-
views: z.array(
|
|
34
|
+
views: z.array(relativeGrowthAdvantageViewSchema),
|
|
35
35
|
lapisDateField: z.string().min(1),
|
|
36
|
-
|
|
36
|
+
yAxisMaxLinear: axisMaxSchema,
|
|
37
|
+
yAxisMaxLogarithmic: axisMaxSchema,
|
|
37
38
|
});
|
|
38
39
|
export type RelativeGrowthAdvantageProps = z.infer<typeof relativeGrowthAdvantagePropsSchema>;
|
|
39
40
|
|
|
@@ -101,7 +102,7 @@ const RelativeGrowthAdvantageTabs: FunctionComponent<RelativeGrowthAdvantageTabs
|
|
|
101
102
|
setYAxisScaleType,
|
|
102
103
|
originalComponentProps,
|
|
103
104
|
}) => {
|
|
104
|
-
const getTab = (view:
|
|
105
|
+
const getTab = (view: RelativeGrowthAdvantageView) => {
|
|
105
106
|
switch (view) {
|
|
106
107
|
case 'line':
|
|
107
108
|
return {
|
|
@@ -114,7 +115,10 @@ const RelativeGrowthAdvantageTabs: FunctionComponent<RelativeGrowthAdvantageTabs
|
|
|
114
115
|
params: data.params,
|
|
115
116
|
}}
|
|
116
117
|
yAxisScaleType={yAxisScaleType}
|
|
117
|
-
yAxisMaxConfig={
|
|
118
|
+
yAxisMaxConfig={{
|
|
119
|
+
linear: originalComponentProps.yAxisMaxLinear,
|
|
120
|
+
logarithmic: originalComponentProps.yAxisMaxLogarithmic,
|
|
121
|
+
}}
|
|
118
122
|
/>
|
|
119
123
|
),
|
|
120
124
|
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { expect, waitFor, within } from '@storybook/test';
|
|
2
|
+
|
|
3
|
+
export function playThatExpectsErrorMessage(errorTitle: string, errorMessage: string) {
|
|
4
|
+
return async ({ canvasElement }: { canvasElement: HTMLElement }) => {
|
|
5
|
+
await expectErrorMessage(canvasElement, errorTitle, errorMessage);
|
|
6
|
+
};
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export async function expectErrorMessage(canvasElement: HTMLElement, errorTitle: string, errorMessage: string) {
|
|
10
|
+
const canvas = within(canvasElement);
|
|
11
|
+
|
|
12
|
+
await waitFor(() => expect(canvas.getByText(errorTitle, { exact: false })).toBeInTheDocument());
|
|
13
|
+
|
|
14
|
+
canvas.getByRole('button', { name: 'Show details.' }).click();
|
|
15
|
+
|
|
16
|
+
await waitFor(() => expect(canvas.getByText(errorMessage, { exact: false })).toBeVisible());
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export async function expectInvalidAttributesErrorMessage(canvasElement: HTMLElement, errorMessage: string) {
|
|
20
|
+
await expectErrorMessage(canvasElement, 'Error - Invalid component attributes', errorMessage);
|
|
21
|
+
}
|
|
@@ -6,7 +6,7 @@ import { TextInput, type TextInputProps } from './text-input';
|
|
|
6
6
|
import { previewHandles } from '../../../.storybook/preview';
|
|
7
7
|
import { AGGREGATED_ENDPOINT, LAPIS_URL } from '../../constants';
|
|
8
8
|
import { LapisUrlContext } from '../LapisUrlContext';
|
|
9
|
-
import { expectInvalidAttributesErrorMessage } from '../shared/stories/
|
|
9
|
+
import { expectInvalidAttributesErrorMessage } from '../shared/stories/expectErrorMessage';
|
|
10
10
|
|
|
11
11
|
const meta: Meta<TextInputProps> = {
|
|
12
12
|
title: 'Input/TextInput',
|
package/src/preact/useQuery.ts
CHANGED
|
@@ -23,5 +23,13 @@ export function useQuery<Data>(fetchDataCallback: () => Promise<Data>, dependenc
|
|
|
23
23
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
24
24
|
}, [JSON.stringify(dependencies)]);
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
if (isLoading) {
|
|
27
|
+
return { isLoading: true } as const;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (error !== null) {
|
|
31
|
+
return { error, isLoading: false as const };
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return { data: data!, error: null, isLoading: false as const };
|
|
27
35
|
}
|
|
@@ -21,7 +21,7 @@ describe('queryNumberOfSequencesOverTime', () => {
|
|
|
21
21
|
|
|
22
22
|
const result = await queryNumberOfSequencesOverTime(
|
|
23
23
|
DUMMY_LAPIS_URL,
|
|
24
|
-
{ displayName: 'displayName', lapisFilter },
|
|
24
|
+
[{ displayName: 'displayName', lapisFilter }],
|
|
25
25
|
lapisDateField,
|
|
26
26
|
'day',
|
|
27
27
|
0,
|
|
@@ -51,7 +51,7 @@ describe('queryNumberOfSequencesOverTime', () => {
|
|
|
51
51
|
|
|
52
52
|
const result = await queryNumberOfSequencesOverTime(
|
|
53
53
|
DUMMY_LAPIS_URL,
|
|
54
|
-
{ displayName: 'displayName', lapisFilter },
|
|
54
|
+
[{ displayName: 'displayName', lapisFilter }],
|
|
55
55
|
lapisDateField,
|
|
56
56
|
'day',
|
|
57
57
|
0,
|
|
@@ -87,7 +87,7 @@ describe('queryNumberOfSequencesOverTime', () => {
|
|
|
87
87
|
|
|
88
88
|
const result = await queryNumberOfSequencesOverTime(
|
|
89
89
|
DUMMY_LAPIS_URL,
|
|
90
|
-
{ displayName: 'displayName', lapisFilter },
|
|
90
|
+
[{ displayName: 'displayName', lapisFilter }],
|
|
91
91
|
lapisDateField,
|
|
92
92
|
'day',
|
|
93
93
|
3,
|
|
@@ -122,7 +122,7 @@ describe('queryNumberOfSequencesOverTime', () => {
|
|
|
122
122
|
|
|
123
123
|
const result = await queryNumberOfSequencesOverTime(
|
|
124
124
|
DUMMY_LAPIS_URL,
|
|
125
|
-
{ displayName: 'displayName', lapisFilter },
|
|
125
|
+
[{ displayName: 'displayName', lapisFilter }],
|
|
126
126
|
lapisDateField,
|
|
127
127
|
'month',
|
|
128
128
|
0,
|
|
@@ -1,19 +1,16 @@
|
|
|
1
1
|
import { queryAggregatedDataOverTime } from './queryAggregatedDataOverTime';
|
|
2
2
|
import { type NamedLapisFilter, type TemporalGranularity } from '../types';
|
|
3
3
|
import { sortNullToBeginningThenByDate } from '../utils/sort';
|
|
4
|
-
import { makeArray } from '../utils/utils';
|
|
5
4
|
|
|
6
5
|
export type NumberOfSequencesDatasets = Awaited<ReturnType<typeof queryNumberOfSequencesOverTime>>;
|
|
7
6
|
|
|
8
7
|
export async function queryNumberOfSequencesOverTime(
|
|
9
8
|
lapis: string,
|
|
10
|
-
|
|
9
|
+
lapisFilters: NamedLapisFilter[],
|
|
11
10
|
lapisDateField: string,
|
|
12
11
|
granularity: TemporalGranularity,
|
|
13
12
|
smoothingWindow: number,
|
|
14
13
|
) {
|
|
15
|
-
const lapisFilters = makeArray(lapisFilter);
|
|
16
|
-
|
|
17
14
|
const queries = lapisFilters.map(async ({ displayName, lapisFilter }) => {
|
|
18
15
|
const { content } = await queryAggregatedDataOverTime(
|
|
19
16
|
lapisFilter,
|
|
@@ -2,7 +2,6 @@ import { queryAggregatedDataOverTime } from './queryAggregatedDataOverTime';
|
|
|
2
2
|
import { DivisionOperator } from '../operator/DivisionOperator';
|
|
3
3
|
import { type LapisFilter, type NamedLapisFilter, type TemporalGranularity } from '../types';
|
|
4
4
|
import { type TemporalClass } from '../utils/temporalClass';
|
|
5
|
-
import { makeArray } from '../utils/utils';
|
|
6
5
|
|
|
7
6
|
export type PrevalenceOverTimeData = PrevalenceOverTimeVariantData[];
|
|
8
7
|
|
|
@@ -19,7 +18,7 @@ export type PrevalenceOverTimeVariantDataPoint = {
|
|
|
19
18
|
};
|
|
20
19
|
|
|
21
20
|
export function queryPrevalenceOverTime(
|
|
22
|
-
|
|
21
|
+
numeratorFilters: NamedLapisFilter[],
|
|
23
22
|
denominatorFilter: LapisFilter,
|
|
24
23
|
granularity: TemporalGranularity,
|
|
25
24
|
smoothingWindow: number,
|
|
@@ -27,8 +26,6 @@ export function queryPrevalenceOverTime(
|
|
|
27
26
|
lapisDateField: string,
|
|
28
27
|
signal?: AbortSignal,
|
|
29
28
|
): Promise<PrevalenceOverTimeData> {
|
|
30
|
-
const numeratorFilters = makeArray(numeratorFilter);
|
|
31
|
-
|
|
32
29
|
const denominatorData = queryAggregatedDataOverTime(
|
|
33
30
|
denominatorFilter,
|
|
34
31
|
granularity,
|
package/src/styles/tailwind.css
CHANGED
package/src/types.ts
CHANGED
|
@@ -9,7 +9,17 @@ import {
|
|
|
9
9
|
type SubstitutionClass,
|
|
10
10
|
} from './utils/mutations';
|
|
11
11
|
|
|
12
|
-
export const
|
|
12
|
+
export const mutationsFilterSchema = z.object({
|
|
13
|
+
nucleotideMutations: z.array(z.string()),
|
|
14
|
+
aminoAcidMutations: z.array(z.string()),
|
|
15
|
+
nucleotideInsertions: z.array(z.string()),
|
|
16
|
+
aminoAcidInsertions: z.array(z.string()),
|
|
17
|
+
});
|
|
18
|
+
export type MutationsFilter = z.infer<typeof mutationsFilterSchema>;
|
|
19
|
+
|
|
20
|
+
export const lapisFilterSchema = z
|
|
21
|
+
.record(z.union([z.string(), z.array(z.string()), z.number(), z.null(), z.boolean(), z.undefined()]))
|
|
22
|
+
.and(mutationsFilterSchema.partial());
|
|
13
23
|
export type LapisFilter = z.infer<typeof lapisFilterSchema>;
|
|
14
24
|
|
|
15
25
|
export const namedLapisFilterSchema = z.object({
|
|
@@ -64,7 +74,5 @@ export const views = {
|
|
|
64
74
|
bar: 'bar',
|
|
65
75
|
line: 'line',
|
|
66
76
|
bubble: 'bubble',
|
|
77
|
+
map: 'map',
|
|
67
78
|
} as const;
|
|
68
|
-
|
|
69
|
-
export const mutationComparisonViewSchema = z.union([z.literal(views.table), z.literal(views.venn)]);
|
|
70
|
-
export type MutationComparisonView = z.infer<typeof mutationComparisonViewSchema>;
|
package/src/utilEntrypoint.ts
CHANGED
|
@@ -10,12 +10,24 @@ export {
|
|
|
10
10
|
type LapisFilter,
|
|
11
11
|
type SequenceType,
|
|
12
12
|
views,
|
|
13
|
-
type MutationComparisonView,
|
|
14
13
|
type TemporalGranularity,
|
|
14
|
+
type MutationsFilter,
|
|
15
15
|
} from './types';
|
|
16
16
|
|
|
17
|
-
export {
|
|
17
|
+
export type { MutationComparisonView, MutationComparisonProps } from './preact/mutationComparison/mutation-comparison';
|
|
18
|
+
export type { MutationsView, MutationsProps } from './preact/mutations/mutations';
|
|
19
|
+
export type { AggregateView, AggregateProps } from './preact/aggregatedData/aggregate';
|
|
20
|
+
export type {
|
|
21
|
+
NumberSequencesOverTimeView,
|
|
22
|
+
NumberSequencesOverTimeProps,
|
|
23
|
+
} from './preact/numberSequencesOverTime/number-sequences-over-time';
|
|
24
|
+
export type { PrevalenceOverTimeView, PrevalenceOverTimeProps } from './preact/prevalenceOverTime/prevalence-over-time';
|
|
25
|
+
export type {
|
|
26
|
+
RelativeGrowthAdvantageView,
|
|
27
|
+
RelativeGrowthAdvantageProps,
|
|
28
|
+
} from './preact/relativeGrowthAdvantage/relative-growth-advantage';
|
|
29
|
+
export type { StatisticsProps } from './preact/statistic/statistics';
|
|
18
30
|
|
|
19
|
-
export {
|
|
31
|
+
export type { ConfidenceIntervalMethod } from './preact/shared/charts/confideceInterval';
|
|
20
32
|
|
|
21
|
-
export {
|
|
33
|
+
export type { AxisMax, YAxisMaxConfig } from './preact/shared/charts/getYAxisMax';
|
package/src/utils/utils.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { type LapisFilter } from '../types';
|
|
2
|
-
|
|
3
1
|
export function getMinMaxNumber(values: Iterable<number>): [number, number] | null {
|
|
4
2
|
let min = null;
|
|
5
3
|
let max = null;
|
|
@@ -16,30 +14,3 @@ export function getMinMaxNumber(values: Iterable<number>): [number, number] | nu
|
|
|
16
14
|
}
|
|
17
15
|
return [min, max];
|
|
18
16
|
}
|
|
19
|
-
|
|
20
|
-
export function mapLapisFilterToUrlParams(filter: LapisFilter): URLSearchParams {
|
|
21
|
-
const params = Object.entries(filter).map(([key, value]) => [key, stringifyLapisFilterValue(value)]);
|
|
22
|
-
|
|
23
|
-
return new URLSearchParams(params);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function stringifyLapisFilterValue(value: LapisFilter[string]) {
|
|
27
|
-
if (value === null) {
|
|
28
|
-
return 'null';
|
|
29
|
-
}
|
|
30
|
-
switch (typeof value) {
|
|
31
|
-
case 'boolean':
|
|
32
|
-
return value ? 'true' : 'false';
|
|
33
|
-
case 'number':
|
|
34
|
-
return value.toString();
|
|
35
|
-
case 'string':
|
|
36
|
-
return value;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export function makeArray<T>(arrayOrSingleItem: T | T[]) {
|
|
41
|
-
if (Array.isArray(arrayOrSingleItem)) {
|
|
42
|
-
return arrayOrSingleItem;
|
|
43
|
-
}
|
|
44
|
-
return [arrayOrSingleItem];
|
|
45
|
-
}
|
|
@@ -2,7 +2,7 @@ import { provide } from '@lit/context';
|
|
|
2
2
|
import { Task } from '@lit/task';
|
|
3
3
|
import { html, LitElement } from 'lit';
|
|
4
4
|
import { customElement, property } from 'lit/decorators.js';
|
|
5
|
-
import {
|
|
5
|
+
import type { DetailedHTMLProps, HTMLAttributes } from 'react';
|
|
6
6
|
import z from 'zod';
|
|
7
7
|
|
|
8
8
|
import { lapisContext } from './lapis-context';
|
|
@@ -20,7 +20,7 @@ const codeExample = String.raw`
|
|
|
20
20
|
initialDateFrom="2020-01-01"
|
|
21
21
|
initialDateTo="2021-01-01"
|
|
22
22
|
width="100%"
|
|
23
|
-
|
|
23
|
+
lapisDateField="myDateColumn"
|
|
24
24
|
></gs-date-range-selector>`;
|
|
25
25
|
|
|
26
26
|
const customDateRange = { label: 'CustomDateRange', dateFrom: '2021-01-01', dateTo: '2021-12-31' };
|
|
@@ -46,7 +46,7 @@ const meta: Meta<Required<DateRangeSelectorProps>> = {
|
|
|
46
46
|
},
|
|
47
47
|
options: [dateRangeOptionPresets.lastMonth.label, dateRangeOptionPresets.allTimes.label, 'CustomDateRange'],
|
|
48
48
|
},
|
|
49
|
-
|
|
49
|
+
lapisDateField: { control: { type: 'text' } },
|
|
50
50
|
dateRangeOptions: {
|
|
51
51
|
control: {
|
|
52
52
|
type: 'object',
|
|
@@ -72,7 +72,7 @@ const meta: Meta<Required<DateRangeSelectorProps>> = {
|
|
|
72
72
|
],
|
|
73
73
|
earliestDate: '1970-01-01',
|
|
74
74
|
initialValue: dateRangeOptionPresets.lastMonth.label,
|
|
75
|
-
|
|
75
|
+
lapisDateField: 'aDateColumn',
|
|
76
76
|
width: '100%',
|
|
77
77
|
initialDateFrom: undefined,
|
|
78
78
|
initialDateTo: undefined,
|
|
@@ -93,7 +93,7 @@ export const Default: StoryObj<Required<DateRangeSelectorProps>> = {
|
|
|
93
93
|
.initialDateFrom=${args.initialDateFrom}
|
|
94
94
|
.initialDateTo=${args.initialDateTo}
|
|
95
95
|
.width=${args.width}
|
|
96
|
-
.
|
|
96
|
+
.lapisDateField=${args.lapisDateField}
|
|
97
97
|
></gs-date-range-selector>
|
|
98
98
|
</div>
|
|
99
99
|
</gs-app>`,
|