@genspectrum/dashboard-components 0.13.7 → 0.14.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.
- package/custom-elements.json +13 -51
- package/dist/{LineageFilterChangedEvent-GedKNGFI.js → LineageFilterChangedEvent-C9dXOxt6.js} +11 -3
- package/dist/LineageFilterChangedEvent-C9dXOxt6.js.map +1 -0
- package/dist/components.d.ts +61 -67
- package/dist/components.js +95 -84
- package/dist/components.js.map +1 -1
- package/dist/util.d.ts +60 -50
- package/dist/util.js +1 -1
- package/package.json +1 -1
- package/src/preact/LapisUrlContext.ts +14 -1
- package/src/preact/aggregatedData/aggregate.stories.tsx +3 -3
- package/src/preact/aggregatedData/aggregate.tsx +3 -4
- package/src/preact/dateRangeSelector/computeInitialValues.spec.ts +34 -20
- package/src/preact/dateRangeSelector/computeInitialValues.ts +25 -21
- package/src/preact/dateRangeSelector/date-range-selector.stories.tsx +104 -40
- package/src/preact/dateRangeSelector/date-range-selector.tsx +29 -20
- package/src/preact/dateRangeSelector/dateRangeOption.ts +11 -1
- package/src/preact/lineageFilter/lineage-filter.stories.tsx +3 -3
- package/src/preact/lineageFilter/lineage-filter.tsx +3 -4
- package/src/preact/locationFilter/location-filter.stories.tsx +3 -3
- package/src/preact/locationFilter/location-filter.tsx +4 -4
- package/src/preact/map/sequences-by-location.stories.tsx +3 -3
- package/src/preact/map/sequences-by-location.tsx +3 -4
- package/src/preact/mutationComparison/mutation-comparison.stories.tsx +3 -3
- package/src/preact/mutationComparison/mutation-comparison.tsx +4 -4
- package/src/preact/mutationFilter/mutation-filter-info.tsx +3 -3
- package/src/preact/mutationFilter/mutation-filter.stories.tsx +5 -5
- package/src/preact/mutations/mutations.stories.tsx +3 -3
- package/src/preact/mutations/mutations.tsx +4 -4
- package/src/preact/mutationsOverTime/mutations-over-time.stories.tsx +3 -3
- package/src/preact/mutationsOverTime/mutations-over-time.tsx +4 -4
- package/src/preact/numberSequencesOverTime/number-sequences-over-time.stories.tsx +3 -3
- package/src/preact/numberSequencesOverTime/number-sequences-over-time.tsx +4 -4
- package/src/preact/prevalenceOverTime/prevalence-over-time.stories.tsx +3 -3
- package/src/preact/prevalenceOverTime/prevalence-over-time.tsx +4 -4
- package/src/preact/relativeGrowthAdvantage/relative-growth-advantage.stories.tsx +3 -3
- package/src/preact/relativeGrowthAdvantage/relative-growth-advantage.tsx +4 -4
- package/src/preact/statistic/statistics.stories.tsx +3 -3
- package/src/preact/statistic/statistics.tsx +2 -3
- package/src/preact/textInput/text-input.stories.tsx +3 -3
- package/src/preact/textInput/text-input.tsx +3 -4
- package/src/preact/wastewater/mutationsOverTime/wastewater-mutations-over-time.stories.tsx +3 -3
- package/src/preact/wastewater/mutationsOverTime/wastewater-mutations-over-time.tsx +4 -4
- package/src/web-components/PreactLitAdapter.tsx +3 -3
- package/src/web-components/gs-app.ts +3 -1
- package/src/web-components/input/gs-date-range-selector.stories.ts +5 -12
- package/src/web-components/input/gs-date-range-selector.tsx +15 -38
- package/standalone-bundle/dashboard-components.js +6078 -6072
- package/standalone-bundle/dashboard-components.js.map +1 -1
- package/dist/LineageFilterChangedEvent-GedKNGFI.js.map +0 -1
|
@@ -2,11 +2,12 @@ import { type Meta, type PreactRenderer, type StoryObj } from '@storybook/preact
|
|
|
2
2
|
import { expect, fn, userEvent, waitFor, within } from '@storybook/test';
|
|
3
3
|
import type { StepFunction } from '@storybook/types';
|
|
4
4
|
import dayjs from 'dayjs/esm';
|
|
5
|
+
import { useEffect, useRef, useState } from 'preact/hooks';
|
|
5
6
|
|
|
6
7
|
import { DateRangeSelector, type DateRangeSelectorProps } from './date-range-selector';
|
|
7
8
|
import { previewHandles } from '../../../.storybook/preview';
|
|
8
9
|
import { LAPIS_URL } from '../../constants';
|
|
9
|
-
import {
|
|
10
|
+
import { LapisUrlContextProvider } from '../LapisUrlContext';
|
|
10
11
|
import { dateRangeOptionPresets } from './dateRangeOption';
|
|
11
12
|
import { expectInvalidAttributesErrorMessage } from '../shared/stories/expectErrorMessage';
|
|
12
13
|
|
|
@@ -28,11 +29,10 @@ const meta: Meta<DateRangeSelectorProps> = {
|
|
|
28
29
|
fetchMock: {},
|
|
29
30
|
},
|
|
30
31
|
argTypes: {
|
|
31
|
-
|
|
32
|
+
value: {
|
|
32
33
|
control: {
|
|
33
|
-
type: '
|
|
34
|
+
type: 'object',
|
|
34
35
|
},
|
|
35
|
-
options: [dateRangeOptionPresets.lastMonth.label, dateRangeOptionPresets.allTimes.label, 'CustomDateRange'],
|
|
36
36
|
},
|
|
37
37
|
dateRangeOptions: {
|
|
38
38
|
control: {
|
|
@@ -53,21 +53,19 @@ const meta: Meta<DateRangeSelectorProps> = {
|
|
|
53
53
|
args: {
|
|
54
54
|
dateRangeOptions: [dateRangeOptionPresets.lastMonth, dateRangeOptionPresets.allTimes, customDateRange],
|
|
55
55
|
earliestDate,
|
|
56
|
-
|
|
56
|
+
value: undefined,
|
|
57
57
|
lapisDateField: 'aDateColumn',
|
|
58
58
|
width: '100%',
|
|
59
|
-
initialDateFrom: undefined,
|
|
60
|
-
initialDateTo: undefined,
|
|
61
59
|
},
|
|
62
60
|
};
|
|
63
61
|
|
|
64
62
|
export default meta;
|
|
65
63
|
|
|
66
|
-
|
|
64
|
+
const Primary: StoryObj<DateRangeSelectorProps> = {
|
|
67
65
|
render: (args) => (
|
|
68
|
-
<
|
|
66
|
+
<LapisUrlContextProvider value={LAPIS_URL}>
|
|
69
67
|
<DateRangeSelector {...args} />
|
|
70
|
-
</
|
|
68
|
+
</LapisUrlContextProvider>
|
|
71
69
|
),
|
|
72
70
|
};
|
|
73
71
|
|
|
@@ -75,15 +73,15 @@ export const SetCorrectInitialValues: StoryObj<DateRangeSelectorProps> = {
|
|
|
75
73
|
...Primary,
|
|
76
74
|
args: {
|
|
77
75
|
...Primary.args,
|
|
78
|
-
|
|
76
|
+
value: 'CustomDateRange',
|
|
79
77
|
},
|
|
80
78
|
play: async ({ canvasElement }) => {
|
|
81
79
|
const canvas = within(canvasElement);
|
|
82
80
|
|
|
83
|
-
await waitFor(() => {
|
|
84
|
-
expect(selectField(canvas)).toHaveValue('CustomDateRange');
|
|
85
|
-
expect(dateFromPicker(canvas)).toHaveValue('2021-01-01');
|
|
86
|
-
expect(dateToPicker(canvas)).toHaveValue('2021-12-31');
|
|
81
|
+
await waitFor(async () => {
|
|
82
|
+
await expect(selectField(canvas)).toHaveValue('CustomDateRange');
|
|
83
|
+
await expect(dateFromPicker(canvas)).toHaveValue('2021-01-01');
|
|
84
|
+
await expect(dateToPicker(canvas)).toHaveValue('2021-12-31');
|
|
87
85
|
});
|
|
88
86
|
},
|
|
89
87
|
};
|
|
@@ -94,15 +92,15 @@ export const SetCorrectInitialDateFrom: StoryObj<DateRangeSelectorProps> = {
|
|
|
94
92
|
...Primary,
|
|
95
93
|
args: {
|
|
96
94
|
...Primary.args,
|
|
97
|
-
initialDateFrom,
|
|
95
|
+
value: { dateFrom: initialDateFrom },
|
|
98
96
|
},
|
|
99
97
|
play: async ({ canvasElement }) => {
|
|
100
98
|
const canvas = within(canvasElement);
|
|
101
99
|
|
|
102
|
-
await waitFor(() => {
|
|
103
|
-
expect(selectField(canvas)).toHaveValue('Custom');
|
|
104
|
-
expect(dateFromPicker(canvas)).toHaveValue(initialDateFrom);
|
|
105
|
-
expect(dateToPicker(canvas)).toHaveValue(dayjs().format('YYYY-MM-DD'));
|
|
100
|
+
await waitFor(async () => {
|
|
101
|
+
await expect(selectField(canvas)).toHaveValue('Custom');
|
|
102
|
+
await expect(dateFromPicker(canvas)).toHaveValue(initialDateFrom);
|
|
103
|
+
await expect(dateToPicker(canvas)).toHaveValue(dayjs().format('YYYY-MM-DD'));
|
|
106
104
|
});
|
|
107
105
|
},
|
|
108
106
|
};
|
|
@@ -113,35 +111,39 @@ export const SetCorrectInitialDateTo: StoryObj<DateRangeSelectorProps> = {
|
|
|
113
111
|
...Primary,
|
|
114
112
|
args: {
|
|
115
113
|
...Primary.args,
|
|
116
|
-
initialDateTo,
|
|
114
|
+
value: { dateTo: initialDateTo },
|
|
117
115
|
},
|
|
118
116
|
play: async ({ canvasElement }) => {
|
|
119
117
|
const canvas = within(canvasElement);
|
|
120
118
|
|
|
121
|
-
await waitFor(() => {
|
|
122
|
-
expect(selectField(canvas)).toHaveValue('Custom');
|
|
123
|
-
expect(dateFromPicker(canvas)).toHaveValue(earliestDate);
|
|
124
|
-
expect(dateToPicker(canvas)).toHaveValue(initialDateTo);
|
|
119
|
+
await waitFor(async () => {
|
|
120
|
+
await expect(selectField(canvas)).toHaveValue('Custom');
|
|
121
|
+
await expect(dateFromPicker(canvas)).toHaveValue(earliestDate);
|
|
122
|
+
await expect(dateToPicker(canvas)).toHaveValue(initialDateTo);
|
|
125
123
|
});
|
|
126
124
|
},
|
|
127
125
|
};
|
|
128
126
|
|
|
129
127
|
export const ChangingDateSetsOptionToCustom: StoryObj<DateRangeSelectorProps> = {
|
|
130
128
|
...Primary,
|
|
129
|
+
args: {
|
|
130
|
+
...Primary.args,
|
|
131
|
+
value: dateRangeOptionPresets.lastMonth.label,
|
|
132
|
+
},
|
|
131
133
|
play: async ({ canvasElement, step }) => {
|
|
132
134
|
const { canvas, filterChangedListenerMock, optionChangedListenerMock } = await prepare(canvasElement, step);
|
|
133
135
|
|
|
134
|
-
await waitFor(() => {
|
|
135
|
-
expect(selectField(canvas)).toHaveValue('Last month');
|
|
136
|
+
await waitFor(async () => {
|
|
137
|
+
await expect(selectField(canvas)).toHaveValue('Last month');
|
|
136
138
|
});
|
|
137
139
|
|
|
138
|
-
step('Change date to custom value', async () => {
|
|
140
|
+
await step('Change date to custom value', async () => {
|
|
139
141
|
await userEvent.type(dateFromPicker(canvas), '{backspace>12}');
|
|
140
142
|
await userEvent.type(dateFromPicker(canvas), '2000-01-01');
|
|
141
143
|
await userEvent.click(dateToPicker(canvas));
|
|
142
144
|
|
|
143
|
-
await waitFor(() => {
|
|
144
|
-
expect(selectField(canvas)).toHaveValue('Custom');
|
|
145
|
+
await waitFor(async () => {
|
|
146
|
+
await expect(selectField(canvas)).toHaveValue('Custom');
|
|
145
147
|
});
|
|
146
148
|
|
|
147
149
|
await expect(filterChangedListenerMock).toHaveBeenCalledWith(
|
|
@@ -165,20 +167,82 @@ export const ChangingDateSetsOptionToCustom: StoryObj<DateRangeSelectorProps> =
|
|
|
165
167
|
},
|
|
166
168
|
};
|
|
167
169
|
|
|
168
|
-
export const
|
|
170
|
+
export const ChangingTheValueProgrammatically: StoryObj<DateRangeSelectorProps> = {
|
|
169
171
|
...Primary,
|
|
172
|
+
render: (args) => {
|
|
173
|
+
const StatefulWrapper = () => {
|
|
174
|
+
const [value, setValue] = useState('Last month');
|
|
175
|
+
const ref = useRef<HTMLDivElement>(null);
|
|
176
|
+
|
|
177
|
+
useEffect(() => {
|
|
178
|
+
ref.current?.addEventListener('gs-date-range-option-changed', (event) => {
|
|
179
|
+
setValue((event as CustomEvent).detail);
|
|
180
|
+
});
|
|
181
|
+
}, []);
|
|
182
|
+
|
|
183
|
+
return (
|
|
184
|
+
<div ref={ref}>
|
|
185
|
+
<LapisUrlContextProvider value={LAPIS_URL}>
|
|
186
|
+
<DateRangeSelector {...args} value={value} />
|
|
187
|
+
</LapisUrlContextProvider>
|
|
188
|
+
<button className='btn' onClick={() => setValue(customDateRange.label)}>
|
|
189
|
+
Set to Custom
|
|
190
|
+
</button>
|
|
191
|
+
<button className='btn' onClick={() => setValue(dateRangeOptionPresets.lastMonth.label)}>
|
|
192
|
+
Set to Last month
|
|
193
|
+
</button>
|
|
194
|
+
</div>
|
|
195
|
+
);
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
return <StatefulWrapper />;
|
|
199
|
+
},
|
|
170
200
|
play: async ({ canvasElement, step }) => {
|
|
171
201
|
const { canvas, filterChangedListenerMock, optionChangedListenerMock } = await prepare(canvasElement, step);
|
|
172
202
|
|
|
173
|
-
await waitFor(() => {
|
|
174
|
-
expect(selectField(canvas)).toHaveValue('Last month');
|
|
203
|
+
await waitFor(async () => {
|
|
204
|
+
await expect(selectField(canvas)).toHaveValue('Last month');
|
|
175
205
|
});
|
|
176
206
|
|
|
177
|
-
step('Change
|
|
178
|
-
await userEvent.
|
|
207
|
+
await step('Change the value of the component programmatically', async () => {
|
|
208
|
+
await userEvent.click(canvas.getByRole('button', { name: 'Set to Custom' }));
|
|
209
|
+
await waitFor(async () => {
|
|
210
|
+
await expect(selectField(canvas)).toHaveValue(customDateRange.label);
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
await userEvent.click(canvas.getByRole('button', { name: 'Set to Last month' }));
|
|
214
|
+
await waitFor(async () => {
|
|
215
|
+
await expect(selectField(canvas)).toHaveValue('Last month');
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
await expect(filterChangedListenerMock).toHaveBeenCalledTimes(0);
|
|
219
|
+
await expect(optionChangedListenerMock).toHaveBeenCalledTimes(0);
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
await step('Changing the value from within the component is still possible', async () => {
|
|
223
|
+
await userEvent.selectOptions(selectField(canvas), 'All times');
|
|
224
|
+
await waitFor(async () => {
|
|
225
|
+
await expect(selectField(canvas)).toHaveValue('All times');
|
|
226
|
+
});
|
|
227
|
+
await expect(filterChangedListenerMock).toHaveBeenCalledTimes(1);
|
|
228
|
+
await expect(optionChangedListenerMock).toHaveBeenCalledTimes(1);
|
|
229
|
+
});
|
|
230
|
+
},
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
export const ChangingDateOption: StoryObj<DateRangeSelectorProps> = {
|
|
234
|
+
...Primary,
|
|
235
|
+
play: async ({ canvasElement, step }) => {
|
|
236
|
+
const { canvas, filterChangedListenerMock, optionChangedListenerMock } = await prepare(canvasElement, step);
|
|
237
|
+
|
|
238
|
+
await waitFor(async () => {
|
|
239
|
+
await expect(selectField(canvas)).toHaveValue('Custom');
|
|
240
|
+
});
|
|
179
241
|
|
|
180
|
-
|
|
181
|
-
|
|
242
|
+
await step('Change date to custom', async () => {
|
|
243
|
+
await waitFor(async () => {
|
|
244
|
+
await userEvent.selectOptions(selectField(canvas), 'CustomDateRange');
|
|
245
|
+
await expect(selectField(canvas)).toHaveValue('CustomDateRange');
|
|
182
246
|
});
|
|
183
247
|
|
|
184
248
|
await expect(filterChangedListenerMock).toHaveBeenCalledWith(
|
|
@@ -203,13 +267,13 @@ export const HandlesInvalidInitialDateFrom: StoryObj<DateRangeSelectorProps> = {
|
|
|
203
267
|
...Primary,
|
|
204
268
|
args: {
|
|
205
269
|
...Primary.args,
|
|
206
|
-
|
|
270
|
+
value: { dateFrom: 'not a date' },
|
|
207
271
|
},
|
|
208
272
|
play: async ({ canvasElement }) => {
|
|
209
273
|
const canvas = within(canvasElement);
|
|
210
274
|
|
|
211
|
-
await waitFor(() => {
|
|
212
|
-
expect(canvas.getByText('Oops! Something went wrong.')).toBeVisible();
|
|
275
|
+
await waitFor(async () => {
|
|
276
|
+
await expect(canvas.getByText('Oops! Something went wrong.')).toBeVisible();
|
|
213
277
|
});
|
|
214
278
|
},
|
|
215
279
|
};
|
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
import flatpickr from 'flatpickr';
|
|
2
2
|
import 'flatpickr/dist/flatpickr.min.css';
|
|
3
|
-
import { useEffect, useRef, useState } from 'preact/hooks';
|
|
3
|
+
import { useEffect, useMemo, useRef, useState } from 'preact/hooks';
|
|
4
4
|
import z from 'zod';
|
|
5
5
|
|
|
6
6
|
import { computeInitialValues } from './computeInitialValues';
|
|
7
7
|
import { toYYYYMMDD } from './dateConversion';
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
DateRangeOptionChangedEvent,
|
|
10
|
+
dateRangeOptionSchema,
|
|
11
|
+
type DateRangeSelectOption,
|
|
12
|
+
dateRangeValueSchema,
|
|
13
|
+
} from './dateRangeOption';
|
|
9
14
|
import { getDatesForSelectorValue, getSelectableOptions } from './selectableOptions';
|
|
10
15
|
import { ErrorBoundary } from '../components/error-boundary';
|
|
11
16
|
import { Select } from '../components/select';
|
|
@@ -16,9 +21,7 @@ const customOption = 'Custom';
|
|
|
16
21
|
const dateRangeSelectorInnerPropsSchema = z.object({
|
|
17
22
|
dateRangeOptions: z.array(dateRangeOptionSchema),
|
|
18
23
|
earliestDate: z.string().date(),
|
|
19
|
-
|
|
20
|
-
initialDateFrom: z.string().date().optional(),
|
|
21
|
-
initialDateTo: z.string().date().optional(),
|
|
24
|
+
value: dateRangeValueSchema.optional(),
|
|
22
25
|
lapisDateField: z.string().min(1),
|
|
23
26
|
});
|
|
24
27
|
|
|
@@ -45,17 +48,12 @@ export const DateRangeSelector = (props: DateRangeSelectorProps) => {
|
|
|
45
48
|
export const DateRangeSelectorInner = ({
|
|
46
49
|
dateRangeOptions,
|
|
47
50
|
earliestDate = '1900-01-01',
|
|
48
|
-
|
|
51
|
+
value,
|
|
49
52
|
lapisDateField,
|
|
50
|
-
initialDateFrom,
|
|
51
|
-
initialDateTo,
|
|
52
53
|
}: DateRangeSelectorInnerProps) => {
|
|
53
|
-
const initialValues =
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
initialDateTo,
|
|
57
|
-
earliestDate,
|
|
58
|
-
dateRangeOptions,
|
|
54
|
+
const initialValues = useMemo(
|
|
55
|
+
() => computeInitialValues(value, earliestDate, dateRangeOptions),
|
|
56
|
+
[value, earliestDate, dateRangeOptions],
|
|
59
57
|
);
|
|
60
58
|
|
|
61
59
|
const fromDatePickerRef = useRef<HTMLInputElement>(null);
|
|
@@ -74,6 +72,12 @@ export const DateRangeSelectorInner = ({
|
|
|
74
72
|
});
|
|
75
73
|
|
|
76
74
|
useEffect(() => {
|
|
75
|
+
setSelectedDateRange(initialValues.initialSelectedDateRange);
|
|
76
|
+
setSelectedDates({
|
|
77
|
+
dateFrom: initialValues.initialSelectedDateFrom,
|
|
78
|
+
dateTo: initialValues.initialSelectedDateTo,
|
|
79
|
+
});
|
|
80
|
+
|
|
77
81
|
const commonConfig = {
|
|
78
82
|
allowInput: true,
|
|
79
83
|
dateFormat: 'Y-m-d',
|
|
@@ -83,7 +87,7 @@ export const DateRangeSelectorInner = ({
|
|
|
83
87
|
setDateFromPicker(
|
|
84
88
|
flatpickr(fromDatePickerRef.current, {
|
|
85
89
|
...commonConfig,
|
|
86
|
-
defaultDate:
|
|
90
|
+
defaultDate: initialValues.initialSelectedDateFrom,
|
|
87
91
|
}),
|
|
88
92
|
);
|
|
89
93
|
}
|
|
@@ -92,17 +96,22 @@ export const DateRangeSelectorInner = ({
|
|
|
92
96
|
setDateToPicker(
|
|
93
97
|
flatpickr(toDatePickerRef.current, {
|
|
94
98
|
...commonConfig,
|
|
95
|
-
defaultDate:
|
|
99
|
+
defaultDate: initialValues.initialSelectedDateTo,
|
|
96
100
|
}),
|
|
97
101
|
);
|
|
98
102
|
}
|
|
99
103
|
|
|
100
104
|
return () => {
|
|
101
|
-
|
|
102
|
-
|
|
105
|
+
setDateFromPicker((prev) => {
|
|
106
|
+
prev?.destroy();
|
|
107
|
+
return null;
|
|
108
|
+
});
|
|
109
|
+
setDateToPicker((prev) => {
|
|
110
|
+
prev?.destroy();
|
|
111
|
+
return null;
|
|
112
|
+
});
|
|
103
113
|
};
|
|
104
|
-
|
|
105
|
-
}, [fromDatePickerRef, toDatePickerRef]);
|
|
114
|
+
}, [fromDatePickerRef, toDatePickerRef, initialValues]);
|
|
106
115
|
|
|
107
116
|
const onSelectChange = (value: string) => {
|
|
108
117
|
setSelectedDateRange(value);
|
|
@@ -22,7 +22,17 @@ export const dateRangeOptionSchema = z.object({
|
|
|
22
22
|
|
|
23
23
|
export type DateRangeOption = z.infer<typeof dateRangeOptionSchema>;
|
|
24
24
|
|
|
25
|
-
export
|
|
25
|
+
export const dateRangeValueSchema = z.union([
|
|
26
|
+
z.string(),
|
|
27
|
+
z.object({
|
|
28
|
+
dateFrom: z.string().date().optional(),
|
|
29
|
+
dateTo: z.string().date().optional(),
|
|
30
|
+
}),
|
|
31
|
+
]);
|
|
32
|
+
|
|
33
|
+
export type DateRangeValue = z.infer<typeof dateRangeValueSchema>;
|
|
34
|
+
|
|
35
|
+
export type DateRangeSelectOption = Required<DateRangeValue>;
|
|
26
36
|
|
|
27
37
|
export class DateRangeOptionChangedEvent extends CustomEvent<DateRangeSelectOption> {
|
|
28
38
|
constructor(detail: DateRangeSelectOption) {
|
|
@@ -6,7 +6,7 @@ import { LineageFilter, type LineageFilterProps } from './lineage-filter';
|
|
|
6
6
|
import { previewHandles } from '../../../.storybook/preview';
|
|
7
7
|
import { AGGREGATED_ENDPOINT, LAPIS_URL } from '../../constants';
|
|
8
8
|
import aggregatedData from '../../preact/lineageFilter/__mockData__/aggregated.json';
|
|
9
|
-
import {
|
|
9
|
+
import { LapisUrlContextProvider } from '../LapisUrlContext';
|
|
10
10
|
import { expectInvalidAttributesErrorMessage } from '../shared/stories/expectErrorMessage';
|
|
11
11
|
|
|
12
12
|
const meta: Meta = {
|
|
@@ -78,9 +78,9 @@ export default meta;
|
|
|
78
78
|
|
|
79
79
|
export const Default: StoryObj<LineageFilterProps> = {
|
|
80
80
|
render: (args) => (
|
|
81
|
-
<
|
|
81
|
+
<LapisUrlContextProvider value={LAPIS_URL}>
|
|
82
82
|
<LineageFilter {...args} />
|
|
83
|
-
</
|
|
83
|
+
</LapisUrlContextProvider>
|
|
84
84
|
),
|
|
85
85
|
play: async ({ canvasElement, step }) => {
|
|
86
86
|
const { canvas, lineageChangedListenerMock } = await prepare(canvasElement, step);
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { type FunctionComponent } from 'preact';
|
|
2
|
-
import { useContext } from 'preact/hooks';
|
|
3
2
|
import z from 'zod';
|
|
4
3
|
|
|
5
|
-
import {
|
|
6
|
-
import { LapisUrlContext } from '../LapisUrlContext';
|
|
4
|
+
import { useLapisUrl } from '../LapisUrlContext';
|
|
7
5
|
import { LineageFilterChangedEvent } from './LineageFilterChangedEvent';
|
|
6
|
+
import { fetchLineageAutocompleteList } from './fetchLineageAutocompleteList';
|
|
8
7
|
import { lapisFilterSchema } from '../../types';
|
|
9
8
|
import { DownshiftCombobox } from '../components/downshift-combobox';
|
|
10
9
|
import { ErrorBoundary } from '../components/error-boundary';
|
|
@@ -47,7 +46,7 @@ const LineageFilterInner: FunctionComponent<LineageFilterInnerProps> = ({
|
|
|
47
46
|
value,
|
|
48
47
|
lapisFilter,
|
|
49
48
|
}) => {
|
|
50
|
-
const lapis =
|
|
49
|
+
const lapis = useLapisUrl();
|
|
51
50
|
|
|
52
51
|
const { data, error, isLoading } = useQuery(
|
|
53
52
|
() => fetchLineageAutocompleteList({ lapis, field: lapisField, lapisFilter }),
|
|
@@ -6,7 +6,7 @@ import data from './__mockData__/aggregated.json';
|
|
|
6
6
|
import { LocationFilter, type LocationFilterProps } from './location-filter';
|
|
7
7
|
import { previewHandles } from '../../../.storybook/preview';
|
|
8
8
|
import { AGGREGATED_ENDPOINT, LAPIS_URL } from '../../constants';
|
|
9
|
-
import {
|
|
9
|
+
import { LapisUrlContextProvider } from '../LapisUrlContext';
|
|
10
10
|
import { expectInvalidAttributesErrorMessage } from '../shared/stories/expectErrorMessage';
|
|
11
11
|
|
|
12
12
|
const meta: Meta<LocationFilterProps> = {
|
|
@@ -77,9 +77,9 @@ export default meta;
|
|
|
77
77
|
|
|
78
78
|
export const Primary: StoryObj<LocationFilterProps> = {
|
|
79
79
|
render: (args) => (
|
|
80
|
-
<
|
|
80
|
+
<LapisUrlContextProvider value={LAPIS_URL}>
|
|
81
81
|
<LocationFilter {...args} />
|
|
82
|
-
</
|
|
82
|
+
</LapisUrlContextProvider>
|
|
83
83
|
),
|
|
84
84
|
play: async ({ canvasElement, step }) => {
|
|
85
85
|
const { canvas, locationChangedListenerMock } = await prepare(canvasElement, step);
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { type FunctionComponent } from 'preact';
|
|
2
|
-
import {
|
|
2
|
+
import { useMemo } from 'preact/hooks';
|
|
3
3
|
import z from 'zod';
|
|
4
4
|
|
|
5
|
-
import { fetchAutocompletionList, type LocationEntry } from './fetchAutocompletionList';
|
|
6
|
-
import { LapisUrlContext } from '../LapisUrlContext';
|
|
7
5
|
import { LocationChangedEvent } from './LocationChangedEvent';
|
|
6
|
+
import { fetchAutocompletionList, type LocationEntry } from './fetchAutocompletionList';
|
|
8
7
|
import { lapisFilterSchema, type LapisLocationFilter, lapisLocationFilterSchema } from '../../types';
|
|
8
|
+
import { useLapisUrl } from '../LapisUrlContext';
|
|
9
9
|
import { DownshiftCombobox } from '../components/downshift-combobox';
|
|
10
10
|
import { ErrorBoundary } from '../components/error-boundary';
|
|
11
11
|
import { LoadingDisplay } from '../components/loading-display';
|
|
@@ -40,7 +40,7 @@ export const LocationFilter: FunctionComponent<LocationFilterProps> = (props) =>
|
|
|
40
40
|
};
|
|
41
41
|
|
|
42
42
|
export const LocationFilterInner = ({ value, fields, placeholderText, lapisFilter }: LocationFilterInnerProps) => {
|
|
43
|
-
const lapis =
|
|
43
|
+
const lapis = useLapisUrl();
|
|
44
44
|
|
|
45
45
|
const { data, error, isLoading } = useQuery(
|
|
46
46
|
() => fetchAutocompletionList({ fields, lapis, lapisFilter }),
|
|
@@ -2,7 +2,7 @@ import { type Meta, type StoryObj } from '@storybook/preact';
|
|
|
2
2
|
|
|
3
3
|
import worldAtlas from './__mockData__/worldAtlas.json';
|
|
4
4
|
import { AGGREGATED_ENDPOINT, LAPIS_URL } from '../../constants';
|
|
5
|
-
import {
|
|
5
|
+
import { LapisUrlContextProvider } from '../LapisUrlContext';
|
|
6
6
|
import aggregatedWorld from './__mockData__/aggregatedWorld.json';
|
|
7
7
|
import { SequencesByLocation, type SequencesByLocationProps } from './sequences-by-location';
|
|
8
8
|
import { expectInvalidAttributesErrorMessage, playThatExpectsErrorMessage } from '../shared/stories/expectErrorMessage';
|
|
@@ -37,9 +37,9 @@ const aggregatedWorldMatcher = {
|
|
|
37
37
|
|
|
38
38
|
export const Default: StoryObj<SequencesByLocationProps> = {
|
|
39
39
|
render: (args) => (
|
|
40
|
-
<
|
|
40
|
+
<LapisUrlContextProvider value={LAPIS_URL}>
|
|
41
41
|
<SequencesByLocation {...args} />
|
|
42
|
-
</
|
|
42
|
+
</LapisUrlContextProvider>
|
|
43
43
|
),
|
|
44
44
|
args: {
|
|
45
45
|
lapisFilter: { dateFrom: '2022-01-01', dateTo: '2022-04-01' },
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { FunctionComponent } from 'preact';
|
|
2
|
-
import { useContext } from 'preact/hooks';
|
|
3
2
|
import z from 'zod';
|
|
4
3
|
|
|
4
|
+
import { useLapisUrl } from '../LapisUrlContext';
|
|
5
5
|
import { SequencesByLocationMap } from './sequences-by-location-map';
|
|
6
6
|
import { SequencesByLocationTable } from './sequences-by-location-table';
|
|
7
7
|
import {
|
|
@@ -11,7 +11,6 @@ import {
|
|
|
11
11
|
} from '../../query/computeMapLocationData';
|
|
12
12
|
import { type AggregateData } from '../../query/queryAggregateData';
|
|
13
13
|
import { querySequencesByLocationData } from '../../query/querySequencesByLocationData';
|
|
14
|
-
import { LapisUrlContext } from '../LapisUrlContext';
|
|
15
14
|
import { CsvDownloadButton } from '../components/csv-download-button';
|
|
16
15
|
import { ErrorBoundary } from '../components/error-boundary';
|
|
17
16
|
import { Fullscreen } from '../components/fullscreen';
|
|
@@ -58,7 +57,7 @@ export const SequencesByLocation: FunctionComponent<SequencesByLocationProps> =
|
|
|
58
57
|
const SequencesByLocationMapInner: FunctionComponent<SequencesByLocationProps> = (props) => {
|
|
59
58
|
const { lapisFilter, lapisLocationField, mapSource } = props;
|
|
60
59
|
|
|
61
|
-
const lapis =
|
|
60
|
+
const lapis = useLapisUrl();
|
|
62
61
|
const {
|
|
63
62
|
data,
|
|
64
63
|
error,
|
|
@@ -158,7 +157,7 @@ type SequencesByLocationMapInfoProps = {
|
|
|
158
157
|
};
|
|
159
158
|
|
|
160
159
|
const SequencesByLocationMapInfo: FunctionComponent<SequencesByLocationMapInfoProps> = ({ originalComponentProps }) => {
|
|
161
|
-
const lapis =
|
|
160
|
+
const lapis = useLapisUrl();
|
|
162
161
|
return (
|
|
163
162
|
<Info>
|
|
164
163
|
<InfoHeadline1>Prevalence by location</InfoHeadline1>
|
|
@@ -6,7 +6,7 @@ import nucleotideMutationsSomeDataset from './__mockData__/nucleotideMutationsSo
|
|
|
6
6
|
import { MutationComparison, type MutationComparisonProps } from './mutation-comparison';
|
|
7
7
|
import { LAPIS_URL, NUCLEOTIDE_MUTATIONS_ENDPOINT } from '../../constants';
|
|
8
8
|
import referenceGenome from '../../lapisApi/__mockData__/referenceGenome.json';
|
|
9
|
-
import {
|
|
9
|
+
import { LapisUrlContextProvider } from '../LapisUrlContext';
|
|
10
10
|
import { ReferenceGenomeContext } from '../ReferenceGenomeContext';
|
|
11
11
|
|
|
12
12
|
const dateToSomeDataset = '2022-01-01';
|
|
@@ -76,7 +76,7 @@ export default meta;
|
|
|
76
76
|
|
|
77
77
|
const Template: StoryObj<MutationComparisonProps> = {
|
|
78
78
|
render: (args) => (
|
|
79
|
-
<
|
|
79
|
+
<LapisUrlContextProvider value={LAPIS_URL}>
|
|
80
80
|
<ReferenceGenomeContext.Provider value={referenceGenome}>
|
|
81
81
|
<MutationComparison
|
|
82
82
|
lapisFilters={args.lapisFilters}
|
|
@@ -87,7 +87,7 @@ const Template: StoryObj<MutationComparisonProps> = {
|
|
|
87
87
|
pageSize={args.pageSize}
|
|
88
88
|
/>
|
|
89
89
|
</ReferenceGenomeContext.Provider>
|
|
90
|
-
</
|
|
90
|
+
</LapisUrlContextProvider>
|
|
91
91
|
),
|
|
92
92
|
};
|
|
93
93
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type FunctionComponent } from 'preact';
|
|
2
|
-
import { type Dispatch, type StateUpdater,
|
|
2
|
+
import { type Dispatch, type StateUpdater, useMemo, useState } from 'preact/hooks';
|
|
3
3
|
import z from 'zod';
|
|
4
4
|
|
|
5
5
|
import { getMutationComparisonTableData } from './getMutationComparisonTableData';
|
|
@@ -7,7 +7,7 @@ import { MutationComparisonTable } from './mutation-comparison-table';
|
|
|
7
7
|
import { MutationComparisonVenn } from './mutation-comparison-venn';
|
|
8
8
|
import { filterMutationData, type MutationData, queryMutationData } from './queryMutationData';
|
|
9
9
|
import { namedLapisFilterSchema, sequenceTypeSchema, views } from '../../types';
|
|
10
|
-
import {
|
|
10
|
+
import { useLapisUrl } from '../LapisUrlContext';
|
|
11
11
|
import { CsvDownloadButton } from '../components/csv-download-button';
|
|
12
12
|
import { ErrorBoundary } from '../components/error-boundary';
|
|
13
13
|
import { Fullscreen } from '../components/fullscreen';
|
|
@@ -52,7 +52,7 @@ export const MutationComparison: FunctionComponent<MutationComparisonProps> = (c
|
|
|
52
52
|
|
|
53
53
|
const MutationComparisonInner: FunctionComponent<MutationComparisonProps> = (componentProps) => {
|
|
54
54
|
const { lapisFilters, sequenceType } = componentProps;
|
|
55
|
-
const lapis =
|
|
55
|
+
const lapis = useLapisUrl();
|
|
56
56
|
|
|
57
57
|
const { data, error, isLoading } = useQuery(async () => {
|
|
58
58
|
return queryMutationData(lapisFilters, sequenceType, lapis);
|
|
@@ -187,7 +187,7 @@ type MutationComparisonInfoProps = {
|
|
|
187
187
|
};
|
|
188
188
|
|
|
189
189
|
const MutationComparisonInfo: FunctionComponent<MutationComparisonInfoProps> = ({ originalComponentProps }) => {
|
|
190
|
-
const lapis =
|
|
190
|
+
const lapis = useLapisUrl();
|
|
191
191
|
return (
|
|
192
192
|
<Info>
|
|
193
193
|
<InfoHeadline1>Info for mutation comparison</InfoHeadline1>
|
|
@@ -55,13 +55,13 @@ const QuickStart = () => {
|
|
|
55
55
|
)}
|
|
56
56
|
</ul>
|
|
57
57
|
</InfoParagraph>
|
|
58
|
-
|
|
59
|
-
{referenceGenome.nucleotideSequences.length > 1 ? (
|
|
58
|
+
{referenceGenome.nucleotideSequences.length > 1 && (
|
|
60
59
|
<InfoParagraph>
|
|
61
60
|
This organism has the following segments:{' '}
|
|
62
61
|
{referenceGenome.nucleotideSequences.map((gene) => gene.name).join(', ')}.
|
|
63
62
|
</InfoParagraph>
|
|
64
|
-
)
|
|
63
|
+
)}
|
|
64
|
+
{referenceGenome.nucleotideSequences.length === 0 && (
|
|
65
65
|
<InfoParagraph>This organism doesn't support nucleotide sequences.</InfoParagraph>
|
|
66
66
|
)}
|
|
67
67
|
{referenceGenome.genes.length !== 0 ? (
|
|
@@ -6,7 +6,7 @@ import { MutationFilter, type MutationFilterProps } from './mutation-filter';
|
|
|
6
6
|
import { previewHandles } from '../../../.storybook/preview';
|
|
7
7
|
import { LAPIS_URL } from '../../constants';
|
|
8
8
|
import referenceGenome from '../../lapisApi/__mockData__/referenceGenome.json';
|
|
9
|
-
import {
|
|
9
|
+
import { LapisUrlContextProvider } from '../LapisUrlContext';
|
|
10
10
|
import { ReferenceGenomeContext } from '../ReferenceGenomeContext';
|
|
11
11
|
|
|
12
12
|
const meta: Meta<MutationFilterProps> = {
|
|
@@ -32,11 +32,11 @@ export default meta;
|
|
|
32
32
|
|
|
33
33
|
export const Default: StoryObj<MutationFilterProps> = {
|
|
34
34
|
render: (args) => (
|
|
35
|
-
<
|
|
35
|
+
<LapisUrlContextProvider value={LAPIS_URL}>
|
|
36
36
|
<ReferenceGenomeContext.Provider value={referenceGenome}>
|
|
37
37
|
<MutationFilter width={args.width} initialValue={args.initialValue} />
|
|
38
38
|
</ReferenceGenomeContext.Provider>
|
|
39
|
-
</
|
|
39
|
+
</LapisUrlContextProvider>
|
|
40
40
|
),
|
|
41
41
|
args: {
|
|
42
42
|
width: '100%',
|
|
@@ -184,11 +184,11 @@ export const FiresFilterChangedEvents: StoryObj<MutationFilterProps> = {
|
|
|
184
184
|
|
|
185
185
|
export const WithInitialValue: StoryObj<MutationFilterProps> = {
|
|
186
186
|
render: (args) => (
|
|
187
|
-
<
|
|
187
|
+
<LapisUrlContextProvider value={LAPIS_URL}>
|
|
188
188
|
<ReferenceGenomeContext.Provider value={referenceGenome}>
|
|
189
189
|
<MutationFilter initialValue={args.initialValue} width={args.width} />
|
|
190
190
|
</ReferenceGenomeContext.Provider>
|
|
191
|
-
</
|
|
191
|
+
</LapisUrlContextProvider>
|
|
192
192
|
),
|
|
193
193
|
args: {
|
|
194
194
|
initialValue: {
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
import referenceGenome from '../../lapisApi/__mockData__/referenceGenome.json';
|
|
14
14
|
import baselineNucleotideMutations from '../../preact/mutations/__mockData__/baselineNucleotideMutations.json';
|
|
15
15
|
import overallVariantCount from '../../preact/mutations/__mockData__/overallVariantCount.json';
|
|
16
|
-
import {
|
|
16
|
+
import { LapisUrlContextProvider } from '../LapisUrlContext';
|
|
17
17
|
import { ReferenceGenomeContext } from '../ReferenceGenomeContext';
|
|
18
18
|
|
|
19
19
|
const meta: Meta<MutationsProps> = {
|
|
@@ -39,11 +39,11 @@ export default meta;
|
|
|
39
39
|
|
|
40
40
|
const Template = {
|
|
41
41
|
render: (args: MutationsProps) => (
|
|
42
|
-
<
|
|
42
|
+
<LapisUrlContextProvider value={LAPIS_URL}>
|
|
43
43
|
<ReferenceGenomeContext.Provider value={referenceGenome}>
|
|
44
44
|
<Mutations {...args} />
|
|
45
45
|
</ReferenceGenomeContext.Provider>
|
|
46
|
-
</
|
|
46
|
+
</LapisUrlContextProvider>
|
|
47
47
|
),
|
|
48
48
|
};
|
|
49
49
|
|