@genspectrum/dashboard-components 0.10.4 → 0.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/custom-elements.json +58 -58
  2. package/dist/components.d.ts +82 -32
  3. package/dist/components.js +57 -65
  4. package/dist/components.js.map +1 -1
  5. package/dist/{dateRangeOption-Doo6WHKu.js → dateRangeOption-Bh2p78z0.js} +9 -4
  6. package/dist/dateRangeOption-Bh2p78z0.js.map +1 -0
  7. package/dist/util.d.ts +623 -14
  8. package/dist/util.js +1 -1
  9. package/package.json +5 -5
  10. package/src/preact/aggregatedData/aggregate.stories.tsx +1 -1
  11. package/src/preact/aggregatedData/aggregate.tsx +11 -8
  12. package/src/preact/dateRangeSelector/date-range-selector.stories.tsx +3 -11
  13. package/src/preact/dateRangeSelector/date-range-selector.tsx +4 -4
  14. package/src/preact/mutationComparison/mutation-comparison.tsx +4 -6
  15. package/src/preact/mutationFilter/mutation-filter.tsx +4 -13
  16. package/src/preact/mutations/mutations.tsx +4 -4
  17. package/src/preact/mutationsOverTime/mutations-over-time.tsx +4 -4
  18. package/src/preact/numberSequencesOverTime/number-sequences-over-time.stories.tsx +4 -13
  19. package/src/preact/numberSequencesOverTime/number-sequences-over-time.tsx +4 -4
  20. package/src/preact/prevalenceOverTime/prevalence-over-time.stories.tsx +14 -25
  21. package/src/preact/prevalenceOverTime/prevalence-over-time.tsx +8 -8
  22. package/src/preact/relativeGrowthAdvantage/relative-growth-advantage.stories.tsx +3 -14
  23. package/src/preact/relativeGrowthAdvantage/relative-growth-advantage.tsx +11 -7
  24. package/src/query/queryNumberOfSequencesOverTime.spec.ts +4 -4
  25. package/src/query/queryNumberOfSequencesOverTime.ts +1 -4
  26. package/src/query/queryPrevalenceOverTime.ts +1 -4
  27. package/src/types.ts +11 -4
  28. package/src/utilEntrypoint.ts +17 -4
  29. package/src/utils/utils.ts +0 -29
  30. package/src/web-components/app.ts +1 -1
  31. package/src/web-components/input/gs-date-range-selector.stories.ts +4 -4
  32. package/src/web-components/input/gs-date-range-selector.tsx +5 -5
  33. package/src/web-components/input/gs-lineage-filter.tsx +1 -1
  34. package/src/web-components/input/gs-location-filter.tsx +1 -1
  35. package/src/web-components/input/gs-mutation-filter.tsx +5 -8
  36. package/src/web-components/input/gs-text-input.tsx +1 -1
  37. package/src/web-components/visualization/gs-aggregate.stories.ts +3 -3
  38. package/src/web-components/visualization/gs-aggregate.tsx +10 -6
  39. package/src/web-components/visualization/gs-mutation-comparison.tsx +7 -2
  40. package/src/web-components/visualization/gs-mutations-over-time.tsx +7 -2
  41. package/src/web-components/visualization/gs-mutations.tsx +7 -2
  42. package/src/web-components/visualization/gs-number-sequences-over-time.stories.ts +5 -5
  43. package/src/web-components/visualization/gs-number-sequences-over-time.tsx +13 -15
  44. package/src/web-components/visualization/gs-prevalence-over-time.stories.ts +8 -8
  45. package/src/web-components/visualization/gs-prevalence-over-time.tsx +17 -14
  46. package/src/web-components/visualization/gs-relative-growth-advantage.stories.ts +4 -5
  47. package/src/web-components/visualization/gs-relative-growth-advantage.tsx +17 -15
  48. package/src/web-components/visualization/gs-sequences-by-location.tsx +6 -1
  49. package/src/web-components/visualization/gs-statistics.tsx +12 -3
  50. package/standalone-bundle/dashboard-components.js +2520 -2516
  51. package/standalone-bundle/dashboard-components.js.map +1 -1
  52. package/dist/dateRangeOption-Doo6WHKu.js.map +0 -1
  53. package/src/utils/utils.spec.ts +0 -16
package/dist/util.js CHANGED
@@ -1,4 +1,4 @@
1
- import { D, d, v } from "./dateRangeOption-Doo6WHKu.js";
1
+ import { D, d, v } from "./dateRangeOption-Bh2p78z0.js";
2
2
  export {
3
3
  D as DateRangeOptionChangedEvent,
4
4
  d as dateRangeOptionPresets,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@genspectrum/dashboard-components",
3
- "version": "0.10.4",
3
+ "version": "0.11.1",
4
4
  "description": "GenSpectrum web components for building dashboards",
5
5
  "type": "module",
6
6
  "license": "AGPL-3.0-only",
@@ -28,14 +28,14 @@
28
28
  },
29
29
  "exports": {
30
30
  "./components": {
31
+ "types": "./dist/components.d.ts",
31
32
  "import": "./dist/components.js",
32
- "require": "./dist/components.js",
33
- "types": "./dist/components.d.ts"
33
+ "require": "./dist/components.js"
34
34
  },
35
35
  "./util": {
36
+ "types": "./dist/util.d.ts",
36
37
  "import": "./dist/util.js",
37
- "require": "./dist/util.js",
38
- "types": "./dist/util.d.ts"
38
+ "require": "./dist/util.js"
39
39
  },
40
40
  "./custom-elements.json": "./custom-elements.json",
41
41
  "./package.json": "./package.json",
@@ -51,7 +51,7 @@ export const Default: StoryObj<AggregateProps> = {
51
51
  args: {
52
52
  fields: ['division', 'host'],
53
53
  views: ['table'],
54
- filter: {
54
+ lapisFilter: {
55
55
  country: 'USA',
56
56
  },
57
57
  width: '100%',
@@ -16,13 +16,13 @@ import { ResizeContainer } from '../components/resize-container';
16
16
  import Tabs from '../components/tabs';
17
17
  import { useQuery } from '../useQuery';
18
18
 
19
- const viewSchema = z.literal(views.table);
20
- export type View = z.infer<typeof viewSchema>;
19
+ const aggregateViewSchema = z.literal(views.table);
20
+ export type AggregateView = z.infer<typeof aggregateViewSchema>;
21
21
 
22
22
  const aggregatePropsSchema = z.object({
23
- filter: lapisFilterSchema,
23
+ lapisFilter: lapisFilterSchema,
24
24
  fields: z.array(z.string().min(1)),
25
- views: z.array(viewSchema),
25
+ views: z.array(aggregateViewSchema),
26
26
  initialSortField: z.string(),
27
27
  initialSortDirection: z.union([z.literal('ascending'), z.literal('descending')]),
28
28
  pageSize: z.union([z.boolean(), z.number()]),
@@ -45,12 +45,15 @@ export const Aggregate: FunctionComponent<AggregateProps> = (componentProps) =>
45
45
  };
46
46
 
47
47
  export const AggregateInner: FunctionComponent<AggregateProps> = (componentProps) => {
48
- const { fields, filter, initialSortField, initialSortDirection } = componentProps;
48
+ const { fields, lapisFilter, initialSortField, initialSortDirection } = componentProps;
49
49
  const lapis = useContext(LapisUrlContext);
50
50
 
51
51
  const { data, error, isLoading } = useQuery(async () => {
52
- return queryAggregateData(filter, fields, lapis, { field: initialSortField, direction: initialSortDirection });
53
- }, [filter, fields, lapis]);
52
+ return queryAggregateData(lapisFilter, fields, lapis, {
53
+ field: initialSortField,
54
+ direction: initialSortDirection,
55
+ });
56
+ }, [lapisFilter, fields, lapis]);
54
57
 
55
58
  if (isLoading) {
56
59
  return <LoadingDisplay />;
@@ -73,7 +76,7 @@ type AggregatedDataTabsProps = {
73
76
  };
74
77
 
75
78
  const AggregatedDataTabs: FunctionComponent<AggregatedDataTabsProps> = ({ data, originalComponentProps }) => {
76
- const getTab = (view: View) => {
79
+ const getTab = (view: AggregateView) => {
77
80
  switch (view) {
78
81
  case 'table':
79
82
  return {
@@ -54,7 +54,7 @@ const meta: Meta<DateRangeSelectorProps> = {
54
54
  dateRangeOptions: [dateRangeOptionPresets.lastMonth, dateRangeOptionPresets.allTimes, customDateRange],
55
55
  earliestDate,
56
56
  initialValue: dateRangeOptionPresets.lastMonth.label,
57
- dateColumn: 'aDateColumn',
57
+ lapisDateField: 'aDateColumn',
58
58
  width: '100%',
59
59
  initialDateFrom: undefined,
60
60
  initialDateTo: undefined,
@@ -66,15 +66,7 @@ export default meta;
66
66
  export const Primary: StoryObj<DateRangeSelectorProps> = {
67
67
  render: (args) => (
68
68
  <LapisUrlContext.Provider value={LAPIS_URL}>
69
- <DateRangeSelector
70
- dateRangeOptions={args.dateRangeOptions}
71
- earliestDate={args.earliestDate}
72
- initialValue={args.initialValue}
73
- initialDateFrom={args.initialDateFrom}
74
- initialDateTo={args.initialDateTo}
75
- width={args.width}
76
- dateColumn={args.dateColumn}
77
- />
69
+ <DateRangeSelector {...args} />
78
70
  </LapisUrlContext.Provider>
79
71
  ),
80
72
  };
@@ -226,7 +218,7 @@ export const WithNoDateColumn: StoryObj<DateRangeSelectorProps> = {
226
218
  ...Primary,
227
219
  args: {
228
220
  ...Primary.args,
229
- dateColumn: '',
221
+ lapisDateField: '',
230
222
  },
231
223
  play: async ({ canvasElement, step }) => {
232
224
  step('expect error message', async () => {
@@ -19,7 +19,7 @@ const dateRangeSelectorInnerPropsSchema = z.object({
19
19
  initialValue: z.string().optional(),
20
20
  initialDateFrom: z.string().date().optional(),
21
21
  initialDateTo: z.string().date().optional(),
22
- dateColumn: z.string().min(1),
22
+ lapisDateField: z.string().min(1),
23
23
  });
24
24
 
25
25
  const dateRangeSelectorPropsSchema = dateRangeSelectorInnerPropsSchema.extend({
@@ -46,7 +46,7 @@ export const DateRangeSelectorInner = ({
46
46
  dateRangeOptions,
47
47
  earliestDate = '1900-01-01',
48
48
  initialValue,
49
- dateColumn,
49
+ lapisDateField,
50
50
  initialDateFrom,
51
51
  initialDateTo,
52
52
  }: DateRangeSelectorInnerProps) => {
@@ -171,8 +171,8 @@ export const DateRangeSelectorInner = ({
171
171
  const dateTo = dateToPicker?.selectedDates[0];
172
172
 
173
173
  const detail = {
174
- ...(dateFrom !== undefined && { [`${dateColumn}From`]: toYYYYMMDD(dateFrom) }),
175
- ...(dateTo !== undefined && { [`${dateColumn}To`]: toYYYYMMDD(dateTo) }),
174
+ ...(dateFrom !== undefined && { [`${lapisDateField}From`]: toYYYYMMDD(dateFrom) }),
175
+ ...(dateTo !== undefined && { [`${lapisDateField}To`]: toYYYYMMDD(dateTo) }),
176
176
  };
177
177
 
178
178
  divRef.current?.dispatchEvent(
@@ -6,12 +6,7 @@ import { getMutationComparisonTableData } from './getMutationComparisonTableData
6
6
  import { MutationComparisonTable } from './mutation-comparison-table';
7
7
  import { MutationComparisonVenn } from './mutation-comparison-venn';
8
8
  import { filterMutationData, type MutationData, queryMutationData } from './queryMutationData';
9
- import {
10
- type MutationComparisonView,
11
- mutationComparisonViewSchema,
12
- namedLapisFilterSchema,
13
- sequenceTypeSchema,
14
- } from '../../types';
9
+ import { namedLapisFilterSchema, sequenceTypeSchema, views } from '../../types';
15
10
  import { LapisUrlContext } from '../LapisUrlContext';
16
11
  import { CsvDownloadButton } from '../components/csv-download-button';
17
12
  import { ErrorBoundary } from '../components/error-boundary';
@@ -27,6 +22,9 @@ import { type DisplayedSegment, SegmentSelector, useDisplayedSegments } from '..
27
22
  import Tabs from '../components/tabs';
28
23
  import { useQuery } from '../useQuery';
29
24
 
25
+ export const mutationComparisonViewSchema = z.union([z.literal(views.table), z.literal(views.venn)]);
26
+ export type MutationComparisonView = z.infer<typeof mutationComparisonViewSchema>;
27
+
30
28
  const mutationComparisonPropsSchema = z.object({
31
29
  width: z.string(),
32
30
  height: z.string(),
@@ -5,20 +5,14 @@ import z from 'zod';
5
5
  import { MutationFilterInfo } from './mutation-filter-info';
6
6
  import { parseAndValidateMutation, type ParsedMutationFilter } from './parseAndValidateMutation';
7
7
  import { type ReferenceGenome } from '../../lapisApi/ReferenceGenome';
8
+ import { type MutationsFilter, mutationsFilterSchema } from '../../types';
8
9
  import { type DeletionClass, type InsertionClass, type SubstitutionClass } from '../../utils/mutations';
9
10
  import { ReferenceGenomeContext } from '../ReferenceGenomeContext';
10
11
  import { ErrorBoundary } from '../components/error-boundary';
11
12
  import { singleGraphColorRGBByName } from '../shared/charts/colors';
12
13
 
13
- const selectedMutationFilterStringsSchema = z.object({
14
- nucleotideMutations: z.array(z.string()),
15
- aminoAcidMutations: z.array(z.string()),
16
- nucleotideInsertions: z.array(z.string()),
17
- aminoAcidInsertions: z.array(z.string()),
18
- });
19
- export type SelectedMutationFilterStrings = z.infer<typeof selectedMutationFilterStringsSchema>;
20
14
  const mutationFilterInnerPropsSchema = z.object({
21
- initialValue: z.union([selectedMutationFilterStringsSchema.optional(), z.array(z.string()), z.undefined()]),
15
+ initialValue: z.union([mutationsFilterSchema.optional(), z.array(z.string()), z.undefined()]),
22
16
  });
23
17
 
24
18
  const mutationFilterPropsSchema = mutationFilterInnerPropsSchema.extend({
@@ -73,7 +67,7 @@ export const MutationFilterInner: FunctionComponent<MutationFilterInnerProps> =
73
67
  const detail = mapToMutationFilterStrings(selectedFilters);
74
68
 
75
69
  filterRef.current?.dispatchEvent(
76
- new CustomEvent<SelectedMutationFilterStrings>('gs-mutation-filter-changed', {
70
+ new CustomEvent<MutationsFilter>('gs-mutation-filter-changed', {
77
71
  detail,
78
72
  bubbles: true,
79
73
  composed: true,
@@ -105,10 +99,7 @@ export const MutationFilterInner: FunctionComponent<MutationFilterInnerProps> =
105
99
  );
106
100
  };
107
101
 
108
- function getInitialState(
109
- initialValue: SelectedMutationFilterStrings | string[] | undefined,
110
- referenceGenome: ReferenceGenome,
111
- ) {
102
+ function getInitialState(initialValue: MutationsFilter | string[] | undefined, referenceGenome: ReferenceGenome) {
112
103
  if (initialValue === undefined) {
113
104
  return {
114
105
  nucleotideMutations: [],
@@ -30,13 +30,13 @@ import { type DisplayedSegment, SegmentSelector, useDisplayedSegments } from '..
30
30
  import Tabs from '../components/tabs';
31
31
  import { useQuery } from '../useQuery';
32
32
 
33
- const viewSchema = z.union([z.literal(views.table), z.literal(views.grid), z.literal(views.insertions)]);
34
- export type View = z.infer<typeof viewSchema>;
33
+ const mutationsViewSchema = z.union([z.literal(views.table), z.literal(views.grid), z.literal(views.insertions)]);
34
+ export type MutationsView = z.infer<typeof mutationsViewSchema>;
35
35
 
36
36
  const mutationsPropsSchema = z.object({
37
37
  lapisFilter: lapisFilterSchema,
38
38
  sequenceType: sequenceTypeSchema,
39
- views: viewSchema.array(),
39
+ views: mutationsViewSchema.array(),
40
40
  pageSize: z.union([z.boolean(), z.number()]),
41
41
  width: z.string(),
42
42
  height: z.string(),
@@ -95,7 +95,7 @@ const MutationsTabs: FunctionComponent<MutationTabsProps> = ({ mutationsData, or
95
95
 
96
96
  const filteredData = filterMutationsData(mutationsData, displayedSegments, displayedMutationTypes);
97
97
 
98
- const getTab = (view: View) => {
98
+ const getTab = (view: MutationsView) => {
99
99
  switch (view) {
100
100
  case 'table':
101
101
  return {
@@ -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 viewSchema = z.literal(views.grid);
39
- export type View = z.infer<typeof viewSchema>;
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(viewSchema),
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: View) => {
137
+ const getTab = (view: MutationsOverTimeView) => {
138
138
  if (filteredData === undefined) {
139
139
  return {
140
140
  title: 'Calculating',
@@ -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
- lapisFilter: [
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
- lapisFilter: [
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
- lapisFilter: z.union([namedLapisFilterSchema, z.array(namedLapisFilterSchema)]),
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 { lapisFilter, lapisDateField, granularity, smoothingWindow } = componentProps;
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, lapisFilter, lapisDateField, granularity, smoothingWindow),
66
- [lapis, lapisFilter, lapisDateField, granularity, smoothingWindow],
65
+ () => queryNumberOfSequencesOverTime(lapis, lapisFilters, lapisDateField, granularity, smoothingWindow),
66
+ [lapis, lapisFilters, lapisDateField, granularity, smoothingWindow],
67
67
  );
68
68
 
69
69
  if (isLoading) {
@@ -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
- numeratorFilter: [
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
- numeratorFilter: {
144
- displayName: 'EG',
145
- lapisFilter: { country: 'USA', pangoLineage: 'BA.2.86*', dateFrom: '2023-10-01' },
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
- numeratorFilter: {
202
- displayName: 'EG',
203
- lapisFilter: { country: 'USA', pangoLineage: 'BA.2.86*', dateFrom: '2023-10-01' },
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 viewSchema = z.union([
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 View = z.infer<typeof viewSchema>;
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
- numeratorFilter: z.union([namedLapisFilterSchema, z.array(namedLapisFilterSchema)]),
39
+ numeratorFilters: z.array(namedLapisFilterSchema).min(1),
40
40
  denominatorFilter: lapisFilterSchema,
41
41
  granularity: temporalGranularitySchema,
42
42
  smoothingWindow: z.number(),
43
- views: z.array(viewSchema),
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 { numeratorFilter, denominatorFilter, granularity, smoothingWindow, lapisDateField } = componentProps;
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
- numeratorFilter,
73
+ numeratorFilters,
74
74
  denominatorFilter,
75
75
  granularity,
76
76
  smoothingWindow,
77
77
  lapis,
78
78
  lapisDateField,
79
79
  ),
80
- [lapis, numeratorFilter, denominatorFilter, granularity, smoothingWindow, lapisDateField],
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: View) => {
121
+ const getTab = (view: PrevalenceOverTimeView) => {
122
122
  switch (view) {
123
123
  case 'bar':
124
124
  return {
@@ -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
- yAxisMaxConfig: {
60
- linear: 1,
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 { yAxisMaxConfigSchema } from '../shared/charts/getYAxisMax';
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 viewSchema = z.literal(views.line);
26
- export type View = z.infer<typeof viewSchema>;
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(viewSchema),
34
+ views: z.array(relativeGrowthAdvantageViewSchema),
35
35
  lapisDateField: z.string().min(1),
36
- yAxisMaxConfig: yAxisMaxConfigSchema,
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: 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={originalComponentProps.yAxisMaxConfig}
118
+ yAxisMaxConfig={{
119
+ linear: originalComponentProps.yAxisMaxLinear,
120
+ logarithmic: originalComponentProps.yAxisMaxLogarithmic,
121
+ }}
118
122
  />
119
123
  ),
120
124
  };
@@ -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
- lapisFilter: NamedLapisFilter | NamedLapisFilter[],
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
- numeratorFilter: NamedLapisFilter | NamedLapisFilter[],
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,