@genspectrum/dashboard-components 0.18.5 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -2
- package/custom-elements.json +3 -3
- package/dist/assets/{mutationOverTimeWorker--b8ZHlji.js.map → mutationOverTimeWorker-ChQTFL68.js.map} +1 -1
- package/dist/components.d.ts +15 -14
- package/dist/components.js +1602 -332
- package/dist/components.js.map +1 -1
- package/dist/util.d.ts +14 -14
- package/package.json +3 -4
- package/src/preact/MutationAnnotationsContext.tsx +34 -27
- package/src/preact/components/dropdown.tsx +1 -1
- package/src/preact/components/info.tsx +1 -2
- package/src/preact/components/min-max-range-slider.tsx +0 -2
- package/src/preact/components/mutations-over-time-text-filter.stories.tsx +57 -0
- package/src/preact/components/mutations-over-time-text-filter.tsx +63 -0
- package/src/preact/components/segment-selector.tsx +1 -1
- package/src/preact/components/table.tsx +0 -2
- package/src/preact/dateRangeFilter/date-picker.tsx +15 -10
- package/src/preact/mutationFilter/mutation-filter.stories.tsx +169 -50
- package/src/preact/mutationFilter/mutation-filter.tsx +239 -234
- package/src/preact/mutationFilter/parseAndValidateMutation.ts +62 -10
- package/src/preact/mutationFilter/parseMutation.spec.ts +62 -47
- package/src/preact/mutationsOverTime/getFilteredMutationsOverTime.spec.ts +128 -0
- package/src/preact/mutationsOverTime/getFilteredMutationsOverTimeData.ts +39 -2
- package/src/preact/mutationsOverTime/mutations-over-time-grid.tsx +8 -11
- package/src/preact/mutationsOverTime/mutations-over-time.stories.tsx +27 -0
- package/src/preact/mutationsOverTime/mutations-over-time.tsx +26 -5
- package/src/preact/shared/tanstackTable/pagination-context.tsx +30 -0
- package/src/preact/shared/tanstackTable/pagination.tsx +19 -6
- package/src/preact/shared/tanstackTable/tanstackTable.tsx +17 -3
- package/src/preact/wastewater/mutationsOverTime/wastewater-mutations-over-time.stories.tsx +19 -1
- package/src/preact/wastewater/mutationsOverTime/wastewater-mutations-over-time.tsx +6 -1
- package/src/styles/replaceCssProperties.stories.tsx +49 -0
- package/src/styles/replaceCssProperties.ts +25 -0
- package/src/styles/tailwind.css +1 -0
- package/src/web-components/PreactLitAdapter.tsx +6 -3
- package/src/web-components/PreactLitAdapterWithGridJsStyles.tsx +0 -2
- package/src/web-components/gs-app.stories.ts +6 -2
- package/src/web-components/gs-app.ts +4 -1
- package/src/web-components/input/gs-date-range-filter.tsx +6 -0
- package/src/web-components/input/gs-mutation-filter.stories.ts +4 -4
- package/src/web-components/visualization/gs-prevalence-over-time.stories.ts +1 -1
- package/standalone-bundle/assets/mutationOverTimeWorker-jChgWnwp.js.map +1 -1
- package/standalone-bundle/dashboard-components.js +10836 -11289
- package/standalone-bundle/dashboard-components.js.map +1 -1
- package/dist/style.css +0 -392
- package/standalone-bundle/style.css +0 -1
|
@@ -44,7 +44,7 @@ export const Default: StoryObj<MutationFilterProps> = {
|
|
|
44
44
|
},
|
|
45
45
|
};
|
|
46
46
|
|
|
47
|
-
export const
|
|
47
|
+
export const EnterSingleMutationByClick: StoryObj<MutationFilterProps> = {
|
|
48
48
|
...Default,
|
|
49
49
|
play: async ({ canvasElement, step }) => {
|
|
50
50
|
const { canvas, changedListenerMock } = await prepare(canvasElement, step);
|
|
@@ -65,9 +65,101 @@ export const FiresFilterMultipleCommaSeparatedQueries: StoryObj<MutationFilterPr
|
|
|
65
65
|
),
|
|
66
66
|
);
|
|
67
67
|
});
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export const EnterSingleMutationByEnter: StoryObj<MutationFilterProps> = {
|
|
72
|
+
...Default,
|
|
73
|
+
play: async ({ canvasElement, step }) => {
|
|
74
|
+
const { canvas, changedListenerMock } = await prepare(canvasElement, step);
|
|
75
|
+
|
|
76
|
+
await step('Enter a valid mutation', async () => {
|
|
77
|
+
await submitMutation(canvas, 'A123T', 'enter');
|
|
78
|
+
|
|
79
|
+
await waitFor(() =>
|
|
80
|
+
expect(changedListenerMock).toHaveBeenCalledWith(
|
|
81
|
+
expect.objectContaining({
|
|
82
|
+
detail: {
|
|
83
|
+
nucleotideMutations: ['A123T'],
|
|
84
|
+
aminoAcidMutations: [],
|
|
85
|
+
nucleotideInsertions: [],
|
|
86
|
+
aminoAcidInsertions: [],
|
|
87
|
+
},
|
|
88
|
+
}),
|
|
89
|
+
),
|
|
90
|
+
);
|
|
91
|
+
});
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
export const IgnoreDuplicates: StoryObj<MutationFilterProps> = {
|
|
96
|
+
...Default,
|
|
97
|
+
play: async ({ canvasElement, step }) => {
|
|
98
|
+
const { canvas } = await prepare(canvasElement, step);
|
|
99
|
+
|
|
100
|
+
await step('Enter duplicate', async () => {
|
|
101
|
+
await userEvent.type(inputField(canvas), 'A123T', INPUT_DELAY);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
await step('Should not show duplicate', async () => {
|
|
105
|
+
const options = await canvas.findAllByRole('option');
|
|
106
|
+
expect(options.length === 1);
|
|
107
|
+
|
|
108
|
+
const firstOption = await canvas.findByRole('option', { name: 'A123' });
|
|
109
|
+
await expect(firstOption).toBeVisible();
|
|
110
|
+
});
|
|
111
|
+
},
|
|
112
|
+
args: {
|
|
113
|
+
...Default.args,
|
|
114
|
+
initialValue: {
|
|
115
|
+
nucleotideMutations: ['A123T'],
|
|
116
|
+
aminoAcidMutations: [],
|
|
117
|
+
nucleotideInsertions: [],
|
|
118
|
+
aminoAcidInsertions: [],
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
export const RemoveMutationByClick: StoryObj<MutationFilterProps> = {
|
|
124
|
+
...Default,
|
|
125
|
+
args: {
|
|
126
|
+
...Default.args,
|
|
127
|
+
initialValue: {
|
|
128
|
+
nucleotideMutations: ['A234T'],
|
|
129
|
+
aminoAcidMutations: ['S:A123G'],
|
|
130
|
+
nucleotideInsertions: ['ins_123:AAA'],
|
|
131
|
+
aminoAcidInsertions: ['ins_S:123:AAA'],
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
play: async ({ canvasElement, step }) => {
|
|
135
|
+
const { canvas, changedListenerMock } = await prepare(canvasElement, step);
|
|
136
|
+
|
|
137
|
+
await step('Remove a mutation', async () => {
|
|
138
|
+
await fireEvent.click(canvas.getByRole('button', { name: 'remove mutation filter A234T' }));
|
|
139
|
+
|
|
140
|
+
await waitFor(() =>
|
|
141
|
+
expect(changedListenerMock).toHaveBeenCalledWith(
|
|
142
|
+
expect.objectContaining({
|
|
143
|
+
detail: {
|
|
144
|
+
nucleotideMutations: [],
|
|
145
|
+
aminoAcidMutations: ['S:A123G'],
|
|
146
|
+
nucleotideInsertions: ['ins_123:AAA'],
|
|
147
|
+
aminoAcidInsertions: ['ins_S:123:AAA'],
|
|
148
|
+
},
|
|
149
|
+
}),
|
|
150
|
+
),
|
|
151
|
+
);
|
|
152
|
+
});
|
|
153
|
+
},
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
export const PasteCommaSeparatedList: StoryObj<MutationFilterProps> = {
|
|
157
|
+
...Default,
|
|
158
|
+
play: async ({ canvasElement, step }) => {
|
|
159
|
+
const { canvas, changedListenerMock } = await prepare(canvasElement, step);
|
|
68
160
|
|
|
69
161
|
await step('Enter a comma separated list of valid and invalid mutations', async () => {
|
|
70
|
-
await pasteMutations(canvas, 'A123T, error_insX, A234T, ins_123:AA');
|
|
162
|
+
await pasteMutations(canvas, 'A123T, error_insX, A234T, notAMutation, ins_123:AA');
|
|
71
163
|
|
|
72
164
|
await waitFor(() =>
|
|
73
165
|
expect(changedListenerMock).toHaveBeenCalledWith(
|
|
@@ -83,27 +175,45 @@ export const FiresFilterMultipleCommaSeparatedQueries: StoryObj<MutationFilterPr
|
|
|
83
175
|
);
|
|
84
176
|
await expect(canvas.queryByText('A123T')).toBeVisible();
|
|
85
177
|
await expect(canvas.queryByText('A234T')).toBeVisible();
|
|
86
|
-
await expect(inputField(canvas)).toHaveValue('error_insX');
|
|
178
|
+
await expect(inputField(canvas)).toHaveValue('error_insX,notAMutation');
|
|
87
179
|
});
|
|
180
|
+
},
|
|
181
|
+
};
|
|
88
182
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
183
|
+
export const IgnoresDuplicatesOnPasteCommaSeparatedList: StoryObj<MutationFilterProps> = {
|
|
184
|
+
...Default,
|
|
185
|
+
play: async ({ canvasElement, step }) => {
|
|
186
|
+
const { canvas, changedListenerMock } = await prepare(canvasElement, step);
|
|
187
|
+
|
|
188
|
+
await step('Enter a comma separated list with duplicates', async () => {
|
|
189
|
+
await pasteMutations(canvas, 'A123T, error_insX, A234T, A234T');
|
|
92
190
|
|
|
93
191
|
await waitFor(() =>
|
|
94
192
|
expect(changedListenerMock).toHaveBeenCalledWith(
|
|
95
193
|
expect.objectContaining({
|
|
96
194
|
detail: {
|
|
97
|
-
nucleotideMutations: ['A123T'],
|
|
195
|
+
nucleotideMutations: ['A123T', 'A234T'],
|
|
98
196
|
aminoAcidMutations: [],
|
|
99
|
-
nucleotideInsertions: [
|
|
197
|
+
nucleotideInsertions: [],
|
|
100
198
|
aminoAcidInsertions: [],
|
|
101
199
|
},
|
|
102
200
|
}),
|
|
103
201
|
),
|
|
104
202
|
);
|
|
203
|
+
await expect(canvas.queryByText('A123T')).toBeVisible();
|
|
204
|
+
await expect(canvas.queryByText('A234T')).toBeVisible();
|
|
205
|
+
await expect(inputField(canvas)).toHaveValue('error_insX');
|
|
105
206
|
});
|
|
106
207
|
},
|
|
208
|
+
args: {
|
|
209
|
+
...Default.args,
|
|
210
|
+
initialValue: {
|
|
211
|
+
nucleotideMutations: ['A123T'],
|
|
212
|
+
aminoAcidMutations: [],
|
|
213
|
+
nucleotideInsertions: [],
|
|
214
|
+
aminoAcidInsertions: [],
|
|
215
|
+
},
|
|
216
|
+
},
|
|
107
217
|
};
|
|
108
218
|
|
|
109
219
|
export const FiresFilterChangedEvents: StoryObj<MutationFilterProps> = {
|
|
@@ -115,7 +225,7 @@ export const FiresFilterChangedEvents: StoryObj<MutationFilterProps> = {
|
|
|
115
225
|
await testNoOptionsExist(canvas, 'notAMutation');
|
|
116
226
|
await expect(changedListenerMock).not.toHaveBeenCalled();
|
|
117
227
|
|
|
118
|
-
await userEvent.type(inputField(canvas), '{backspace>12/}');
|
|
228
|
+
await userEvent.type(inputField(canvas), '{backspace>12/}', INPUT_DELAY);
|
|
119
229
|
});
|
|
120
230
|
|
|
121
231
|
await step('Enter a valid mutation', async () => {
|
|
@@ -138,46 +248,51 @@ export const FiresFilterChangedEvents: StoryObj<MutationFilterProps> = {
|
|
|
138
248
|
await step('Enter a second valid nucleotide mutation', async () => {
|
|
139
249
|
await submitMutation(canvas, 'A234-');
|
|
140
250
|
|
|
141
|
-
await
|
|
142
|
-
expect.
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
251
|
+
await waitFor(() =>
|
|
252
|
+
expect(changedListenerMock).toHaveBeenCalledWith(
|
|
253
|
+
expect.objectContaining({
|
|
254
|
+
detail: {
|
|
255
|
+
nucleotideMutations: ['A123T', 'A234-'],
|
|
256
|
+
aminoAcidMutations: [],
|
|
257
|
+
nucleotideInsertions: [],
|
|
258
|
+
aminoAcidInsertions: [],
|
|
259
|
+
},
|
|
260
|
+
}),
|
|
261
|
+
),
|
|
150
262
|
);
|
|
151
263
|
});
|
|
152
264
|
|
|
153
265
|
await step('Enter another valid mutation', async () => {
|
|
154
266
|
await submitMutation(canvas, 'ins_123:AA', 'enter');
|
|
155
267
|
|
|
156
|
-
await
|
|
157
|
-
expect.
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
268
|
+
await waitFor(() =>
|
|
269
|
+
expect(changedListenerMock).toHaveBeenCalledWith(
|
|
270
|
+
expect.objectContaining({
|
|
271
|
+
detail: {
|
|
272
|
+
nucleotideMutations: ['A123T', 'A234-'],
|
|
273
|
+
aminoAcidMutations: [],
|
|
274
|
+
nucleotideInsertions: ['ins_123:AA'],
|
|
275
|
+
aminoAcidInsertions: [],
|
|
276
|
+
},
|
|
277
|
+
}),
|
|
278
|
+
),
|
|
165
279
|
);
|
|
166
280
|
});
|
|
167
281
|
|
|
168
282
|
await step('Remove the first mutation', async () => {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
283
|
+
await fireEvent.click(canvas.getByRole('button', { name: 'remove mutation filter A234-' }));
|
|
284
|
+
|
|
285
|
+
await waitFor(() =>
|
|
286
|
+
expect(changedListenerMock).toHaveBeenCalledWith(
|
|
287
|
+
expect.objectContaining({
|
|
288
|
+
detail: {
|
|
289
|
+
nucleotideMutations: ['A123T'],
|
|
290
|
+
aminoAcidMutations: [],
|
|
291
|
+
nucleotideInsertions: ['ins_123:AA'],
|
|
292
|
+
aminoAcidInsertions: [],
|
|
293
|
+
},
|
|
294
|
+
}),
|
|
295
|
+
),
|
|
181
296
|
);
|
|
182
297
|
});
|
|
183
298
|
},
|
|
@@ -206,15 +321,17 @@ export const WithInitialValue: StoryObj<MutationFilterProps> = {
|
|
|
206
321
|
await step('Add input to initial value', async () => {
|
|
207
322
|
await submitMutation(canvas, 'G500T');
|
|
208
323
|
|
|
209
|
-
await
|
|
210
|
-
expect.
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
324
|
+
await waitFor(() =>
|
|
325
|
+
expect(changedListenerMock).toHaveBeenCalledWith(
|
|
326
|
+
expect.objectContaining({
|
|
327
|
+
detail: {
|
|
328
|
+
nucleotideMutations: ['A234T', 'G500T'],
|
|
329
|
+
aminoAcidMutations: ['S:A123G'],
|
|
330
|
+
nucleotideInsertions: ['ins_123:AAA'],
|
|
331
|
+
aminoAcidInsertions: ['ins_S:123:AAA'],
|
|
332
|
+
},
|
|
333
|
+
}),
|
|
334
|
+
),
|
|
218
335
|
);
|
|
219
336
|
});
|
|
220
337
|
},
|
|
@@ -254,12 +371,14 @@ async function prepare(canvasElement: HTMLElement, step: StepFunction<PreactRend
|
|
|
254
371
|
|
|
255
372
|
export type SubmissionMethod = 'click' | 'enter';
|
|
256
373
|
|
|
374
|
+
const INPUT_DELAY = { delay: 50 };
|
|
375
|
+
|
|
257
376
|
const submitMutation = async (
|
|
258
377
|
canvas: ReturnType<typeof within>,
|
|
259
378
|
mutation: string,
|
|
260
379
|
submissionMethod: SubmissionMethod = 'click',
|
|
261
380
|
) => {
|
|
262
|
-
await userEvent.type(inputField(canvas), mutation);
|
|
381
|
+
await userEvent.type(inputField(canvas), mutation, INPUT_DELAY);
|
|
263
382
|
const firstOption = await canvas.findByRole('option', { name: mutation });
|
|
264
383
|
if (submissionMethod === 'click') {
|
|
265
384
|
await userEvent.click(firstOption);
|
|
@@ -275,7 +394,7 @@ const pasteMutations = async (canvas: ReturnType<typeof within>, mutation: strin
|
|
|
275
394
|
};
|
|
276
395
|
|
|
277
396
|
const testNoOptionsExist = async (canvas: ReturnType<typeof within>, mutation: string) => {
|
|
278
|
-
await userEvent.type(inputField(canvas), mutation);
|
|
397
|
+
await userEvent.type(inputField(canvas), mutation, INPUT_DELAY);
|
|
279
398
|
const options = canvas.queryAllByRole('option');
|
|
280
399
|
|
|
281
400
|
await expect(options).toHaveLength(0);
|