@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.
Files changed (80) hide show
  1. package/custom-elements.json +384 -56
  2. package/dist/assets/mutationOverTimeWorker-BjjkMGzd.js.map +1 -0
  3. package/dist/components.d.ts +250 -31
  4. package/dist/components.js +1220 -198
  5. package/dist/components.js.map +1 -1
  6. package/dist/{dateRangeOption-DjtcAEWq.js → dateRangeOption-Bh2p78z0.js} +11 -5
  7. package/dist/dateRangeOption-Bh2p78z0.js.map +1 -0
  8. package/dist/style.css +5 -1
  9. package/dist/util.d.ts +626 -16
  10. package/dist/util.js +1 -1
  11. package/package.json +13 -7
  12. package/src/preact/aggregatedData/aggregate.stories.tsx +2 -2
  13. package/src/preact/aggregatedData/aggregate.tsx +11 -8
  14. package/src/preact/dateRangeSelector/date-range-selector.stories.tsx +4 -12
  15. package/src/preact/dateRangeSelector/date-range-selector.tsx +4 -4
  16. package/src/preact/lineageFilter/lineage-filter.stories.tsx +1 -1
  17. package/src/preact/locationFilter/location-filter.stories.tsx +1 -1
  18. package/src/preact/map/__mockData__/aggregatedGermany.json +83 -0
  19. package/src/preact/map/__mockData__/aggregatedWorld.json +259 -0
  20. package/src/preact/map/__mockData__/germanyMap.json +9083 -0
  21. package/src/preact/map/__mockData__/howToGenerateWorldMap.md +9 -0
  22. package/src/preact/map/__mockData__/worldAtlas.json +497127 -0
  23. package/src/preact/map/leafletStyleModifications.css +3 -0
  24. package/src/preact/map/sequences-by-location-map.tsx +202 -0
  25. package/src/preact/map/sequences-by-location-table.tsx +18 -0
  26. package/src/preact/map/sequences-by-location.stories.tsx +144 -0
  27. package/src/preact/map/sequences-by-location.tsx +151 -0
  28. package/src/preact/map/useGeoJsonMap.tsx +62 -0
  29. package/src/preact/mutationComparison/mutation-comparison.tsx +5 -7
  30. package/src/preact/mutationFilter/mutation-filter.tsx +4 -13
  31. package/src/preact/mutations/mutations.tsx +4 -4
  32. package/src/preact/mutationsOverTime/mutations-over-time.stories.tsx +1 -1
  33. package/src/preact/mutationsOverTime/mutations-over-time.tsx +4 -4
  34. package/src/preact/numberSequencesOverTime/number-sequences-over-time.stories.tsx +5 -14
  35. package/src/preact/numberSequencesOverTime/number-sequences-over-time.tsx +4 -4
  36. package/src/preact/prevalenceOverTime/prevalence-over-time.stories.tsx +15 -26
  37. package/src/preact/prevalenceOverTime/prevalence-over-time.tsx +8 -8
  38. package/src/preact/relativeGrowthAdvantage/relative-growth-advantage.stories.tsx +4 -15
  39. package/src/preact/relativeGrowthAdvantage/relative-growth-advantage.tsx +11 -7
  40. package/src/preact/shared/stories/expectErrorMessage.ts +21 -0
  41. package/src/preact/textInput/text-input.stories.tsx +1 -1
  42. package/src/preact/useQuery.ts +9 -1
  43. package/src/query/queryNumberOfSequencesOverTime.spec.ts +4 -4
  44. package/src/query/queryNumberOfSequencesOverTime.ts +1 -4
  45. package/src/query/queryPrevalenceOverTime.ts +1 -4
  46. package/src/styles/tailwind.css +1 -1
  47. package/src/types.ts +12 -4
  48. package/src/utilEntrypoint.ts +16 -4
  49. package/src/utils/utils.ts +0 -29
  50. package/src/web-components/app.ts +1 -1
  51. package/src/web-components/input/gs-date-range-selector.stories.ts +4 -4
  52. package/src/web-components/input/gs-date-range-selector.tsx +5 -5
  53. package/src/web-components/input/gs-lineage-filter.tsx +1 -1
  54. package/src/web-components/input/gs-location-filter.tsx +1 -1
  55. package/src/web-components/input/gs-mutation-filter.tsx +5 -8
  56. package/src/web-components/input/gs-text-input.tsx +1 -1
  57. package/src/web-components/visualization/gs-aggregate.stories.ts +3 -3
  58. package/src/web-components/visualization/gs-aggregate.tsx +10 -6
  59. package/src/web-components/visualization/gs-mutation-comparison.tsx +7 -2
  60. package/src/web-components/visualization/gs-mutations-over-time.tsx +7 -2
  61. package/src/web-components/visualization/gs-mutations.tsx +7 -2
  62. package/src/web-components/visualization/gs-number-sequences-over-time.stories.ts +5 -5
  63. package/src/web-components/visualization/gs-number-sequences-over-time.tsx +13 -15
  64. package/src/web-components/visualization/gs-prevalence-over-time.stories.ts +8 -8
  65. package/src/web-components/visualization/gs-prevalence-over-time.tsx +17 -14
  66. package/src/web-components/visualization/gs-relative-growth-advantage.stories.ts +4 -5
  67. package/src/web-components/visualization/gs-relative-growth-advantage.tsx +17 -15
  68. package/src/web-components/visualization/gs-sequences-by-location.stories.ts +234 -0
  69. package/src/web-components/visualization/gs-sequences-by-location.tsx +258 -0
  70. package/src/web-components/visualization/gs-statistics.tsx +12 -3
  71. package/src/web-components/visualization/index.ts +1 -0
  72. package/standalone-bundle/assets/mutationOverTimeWorker-DoUBht2e.js.map +1 -0
  73. package/standalone-bundle/dashboard-components.js +16208 -9408
  74. package/standalone-bundle/dashboard-components.js.map +1 -1
  75. package/standalone-bundle/style.css +1 -1
  76. package/dist/assets/mutationOverTimeWorker-CNg_ztNp.js.map +0 -1
  77. package/dist/dateRangeOption-DjtcAEWq.js.map +0 -1
  78. package/src/preact/shared/stories/expectInvalidAttributesErrorMessage.ts +0 -13
  79. package/src/utils/utils.spec.ts +0 -16
  80. 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/expectInvalidAttributesErrorMessage';
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 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',
@@ -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/expectInvalidAttributesErrorMessage';
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
- 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) {
@@ -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/expectInvalidAttributesErrorMessage';
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
- 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 {
@@ -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/expectInvalidAttributesErrorMessage';
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
- 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
  };
@@ -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/expectInvalidAttributesErrorMessage';
9
+ import { expectInvalidAttributesErrorMessage } from '../shared/stories/expectErrorMessage';
10
10
 
11
11
  const meta: Meta<TextInputProps> = {
12
12
  title: 'Input/TextInput',
@@ -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
- return { data, error, isLoading };
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
- 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,
@@ -1,3 +1,3 @@
1
1
  @tailwind base;
2
2
  @tailwind components;
3
- @tailwind utilities;
3
+ @tailwind utilities;
package/src/types.ts CHANGED
@@ -9,7 +9,17 @@ import {
9
9
  type SubstitutionClass,
10
10
  } from './utils/mutations';
11
11
 
12
- export const lapisFilterSchema = z.record(z.union([z.string(), z.number(), z.null(), z.boolean()]));
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>;
@@ -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 { type SelectedMutationFilterStrings } from './preact/mutationFilter/mutation-filter';
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 { type ConfidenceIntervalMethod } from './preact/shared/charts/confideceInterval';
31
+ export type { ConfidenceIntervalMethod } from './preact/shared/charts/confideceInterval';
20
32
 
21
- export { type AxisMax, type YAxisMaxConfig } from './preact/shared/charts/getYAxisMax';
33
+ export type { AxisMax, YAxisMaxConfig } from './preact/shared/charts/getYAxisMax';
@@ -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 { type DetailedHTMLProps, type HTMLAttributes } from 'react';
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
- dateColumn="myDateColumn"
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
- dateColumn: { control: { type: 'text' } },
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
- dateColumn: 'aDateColumn',
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
- .dateColumn=${args.dateColumn}
96
+ .lapisDateField=${args.lapisDateField}
97
97
  ></gs-date-range-selector>
98
98
  </div>
99
99
  </gs-app>`,