@genspectrum/dashboard-components 0.6.4 → 0.6.5

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.
@@ -6,7 +6,6 @@ import {
6
6
  } from '../../query/queryMutationsOverTime';
7
7
  import { type Deletion, type Substitution } from '../../utils/mutations';
8
8
  import { compareTemporal, type Temporal, YearMonthDay } from '../../utils/temporal';
9
- import { UserFacingError } from '../components/error-display';
10
9
  import Tooltip from '../components/tooltip';
11
10
  import { singleGraphColorRGBByName } from '../shared/charts/colors';
12
11
  import { formatProportion } from '../shared/table/formatProportion';
@@ -18,49 +17,51 @@ export interface MutationsOverTimeGridProps {
18
17
  const MAX_NUMBER_OF_GRID_ROWS = 100;
19
18
 
20
19
  const MutationsOverTimeGrid: FunctionComponent<MutationsOverTimeGridProps> = ({ data }) => {
21
- const mutations = data.getFirstAxisKeys();
22
- if (mutations.length > MAX_NUMBER_OF_GRID_ROWS) {
23
- throw new UserFacingError(
24
- 'Too many mutations',
25
- `The dataset contains ${mutations.length} mutations. ` +
26
- `Please adapt the filters to reduce the number to below ${MAX_NUMBER_OF_GRID_ROWS}.`,
27
- );
28
- }
20
+ const allMutations = data.getFirstAxisKeys();
21
+ const shownMutations = allMutations.slice(0, MAX_NUMBER_OF_GRID_ROWS);
29
22
 
30
23
  const dates = data.getSecondAxisKeys().sort((a, b) => compareTemporal(a, b));
31
24
 
32
25
  return (
33
- <div
34
- style={{
35
- display: 'grid',
36
- gridTemplateRows: `repeat(${mutations.length}, 24px)`,
37
- gridTemplateColumns: `8rem repeat(${dates.length}, minmax(1.5rem, 1fr))`,
38
- }}
39
- >
40
- {mutations.map((mutation, i) => {
41
- return (
42
- <Fragment key={`fragment-${mutation.toString()}`}>
43
- <div
44
- key={`mutation-${mutation.toString()}`}
45
- style={{ gridRowStart: i + 1, gridColumnStart: 1 }}
46
- >
47
- <MutationCell mutation={mutation} />
48
- </div>
49
- {dates.map((date, j) => {
50
- const value = data.get(mutation, date) ?? { proportion: 0, count: 0 };
51
- return (
52
- <div
53
- style={{ gridRowStart: i + 1, gridColumnStart: j + 2 }}
54
- key={`${mutation.toString()}-${date.toString()}`}
55
- >
56
- <ProportionCell value={value} date={date} mutation={mutation} />
57
- </div>
58
- );
59
- })}
60
- </Fragment>
61
- );
62
- })}
63
- </div>
26
+ <>
27
+ {allMutations.length > MAX_NUMBER_OF_GRID_ROWS && (
28
+ <div className='pl-2'>
29
+ Showing {MAX_NUMBER_OF_GRID_ROWS} of {allMutations.length} mutations. You can narrow the filter to
30
+ reduce the number of mutations.
31
+ </div>
32
+ )}
33
+ <div
34
+ style={{
35
+ display: 'grid',
36
+ gridTemplateRows: `repeat(${shownMutations.length}, 24px)`,
37
+ gridTemplateColumns: `8rem repeat(${dates.length}, minmax(1.5rem, 1fr))`,
38
+ }}
39
+ >
40
+ {shownMutations.map((mutation, i) => {
41
+ return (
42
+ <Fragment key={`fragment-${mutation.toString()}`}>
43
+ <div
44
+ key={`mutation-${mutation.toString()}`}
45
+ style={{ gridRowStart: i + 1, gridColumnStart: 1 }}
46
+ >
47
+ <MutationCell mutation={mutation} />
48
+ </div>
49
+ {dates.map((date, j) => {
50
+ const value = data.get(mutation, date) ?? { proportion: 0, count: 0 };
51
+ return (
52
+ <div
53
+ style={{ gridRowStart: i + 1, gridColumnStart: j + 2 }}
54
+ key={`${mutation.toString()}-${date.toString()}`}
55
+ >
56
+ <ProportionCell value={value} date={date} mutation={mutation} />
57
+ </div>
58
+ );
59
+ })}
60
+ </Fragment>
61
+ );
62
+ })}
63
+ </div>
64
+ </>
64
65
  );
65
66
  };
66
67
 
@@ -1,6 +1,8 @@
1
1
  import { type Meta, type StoryObj } from '@storybook/preact';
2
+ import { expect, waitFor } from '@storybook/test';
2
3
 
3
4
  import aggregated_date from './__mockData__/aggregated_date.json';
5
+ import aggregated_tooManyMutations from './__mockData__/aggregated_tooManyMutations.json';
4
6
  import nucleotideMutation_01 from './__mockData__/nucleotideMutations_2024_01.json';
5
7
  import nucleotideMutation_02 from './__mockData__/nucleotideMutations_2024_02.json';
6
8
  import nucleotideMutation_03 from './__mockData__/nucleotideMutations_2024_03.json';
@@ -8,6 +10,7 @@ import nucleotideMutation_04 from './__mockData__/nucleotideMutations_2024_04.js
8
10
  import nucleotideMutation_05 from './__mockData__/nucleotideMutations_2024_05.json';
9
11
  import nucleotideMutation_06 from './__mockData__/nucleotideMutations_2024_06.json';
10
12
  import nucleotideMutation_07 from './__mockData__/nucleotideMutations_2024_07.json';
13
+ import nucleotideMutation_tooManyMutations from './__mockData__/nucleotideMutations_tooManyMutations.json';
11
14
  import { MutationsOverTime, type MutationsOverTimeProps } from './mutations-over-time';
12
15
  import { AGGREGATED_ENDPOINT, LAPIS_URL, NUCLEOTIDE_MUTATIONS_ENDPOINT } from '../../constants';
13
16
  import referenceGenome from '../../lapisApi/__mockData__/referenceGenome.json';
@@ -95,7 +98,7 @@ export const Default: StoryObj<MutationsOverTimeProps> = {
95
98
  pangoLineage: 'JN.1*',
96
99
  dateFrom: '2024-01-01',
97
100
  dateTo: '2024-01-31',
98
- minProportion: 0,
101
+ minProportion: 0.001,
99
102
  },
100
103
  },
101
104
  response: {
@@ -111,7 +114,7 @@ export const Default: StoryObj<MutationsOverTimeProps> = {
111
114
  pangoLineage: 'JN.1*',
112
115
  dateFrom: '2024-02-01',
113
116
  dateTo: '2024-02-29',
114
- minProportion: 0,
117
+ minProportion: 0.001,
115
118
  },
116
119
  },
117
120
  response: {
@@ -127,7 +130,7 @@ export const Default: StoryObj<MutationsOverTimeProps> = {
127
130
  pangoLineage: 'JN.1*',
128
131
  dateFrom: '2024-03-01',
129
132
  dateTo: '2024-03-31',
130
- minProportion: 0,
133
+ minProportion: 0.001,
131
134
  },
132
135
  response: {
133
136
  status: 200,
@@ -143,7 +146,7 @@ export const Default: StoryObj<MutationsOverTimeProps> = {
143
146
  pangoLineage: 'JN.1*',
144
147
  dateFrom: '2024-04-01',
145
148
  dateTo: '2024-04-30',
146
- minProportion: 0,
149
+ minProportion: 0.001,
147
150
  },
148
151
  response: {
149
152
  status: 200,
@@ -159,7 +162,7 @@ export const Default: StoryObj<MutationsOverTimeProps> = {
159
162
  pangoLineage: 'JN.1*',
160
163
  dateFrom: '2024-05-01',
161
164
  dateTo: '2024-05-31',
162
- minProportion: 0,
165
+ minProportion: 0.001,
163
166
  },
164
167
  response: {
165
168
  status: 200,
@@ -175,7 +178,7 @@ export const Default: StoryObj<MutationsOverTimeProps> = {
175
178
  pangoLineage: 'JN.1*',
176
179
  dateFrom: '2024-06-01',
177
180
  dateTo: '2024-06-30',
178
- minProportion: 0,
181
+ minProportion: 0.001,
179
182
  },
180
183
  response: {
181
184
  status: 200,
@@ -183,7 +186,6 @@ export const Default: StoryObj<MutationsOverTimeProps> = {
183
186
  },
184
187
  },
185
188
  },
186
-
187
189
  {
188
190
  matcher: {
189
191
  name: 'nucleotideMutations_07',
@@ -192,7 +194,7 @@ export const Default: StoryObj<MutationsOverTimeProps> = {
192
194
  pangoLineage: 'JN.1*',
193
195
  dateFrom: '2024-07-01',
194
196
  dateTo: '2024-07-31',
195
- minProportion: 0,
197
+ minProportion: 0.001,
196
198
  },
197
199
  response: {
198
200
  status: 200,
@@ -204,3 +206,55 @@ export const Default: StoryObj<MutationsOverTimeProps> = {
204
206
  },
205
207
  },
206
208
  };
209
+
210
+ export const ShowsMessageWhenTooManyMutations: StoryObj<MutationsOverTimeProps> = {
211
+ ...Template,
212
+ args: {
213
+ lapisFilter: { dateFrom: '2023-01-01', dateTo: '2023-12-31' },
214
+ sequenceType: 'nucleotide',
215
+ views: ['grid'],
216
+ width: '100%',
217
+ height: '700px',
218
+ granularity: 'year',
219
+ lapisDateField: 'date',
220
+ },
221
+ parameters: {
222
+ fetchMock: {
223
+ mocks: [
224
+ {
225
+ matcher: {
226
+ name: 'aggregated',
227
+ url: AGGREGATED_ENDPOINT,
228
+ body: {
229
+ dateFrom: '2023-01-01',
230
+ dateTo: '2023-12-31',
231
+ fields: ['date'],
232
+ },
233
+ },
234
+ response: {
235
+ status: 200,
236
+ body: aggregated_tooManyMutations,
237
+ },
238
+ },
239
+ {
240
+ matcher: {
241
+ name: 'nucleotideMutations',
242
+ url: NUCLEOTIDE_MUTATIONS_ENDPOINT,
243
+ body: {
244
+ dateFrom: '2023-01-01',
245
+ dateTo: '2023-12-31',
246
+ minProportion: 0.001,
247
+ },
248
+ response: {
249
+ status: 200,
250
+ body: nucleotideMutation_tooManyMutations,
251
+ },
252
+ },
253
+ },
254
+ ],
255
+ },
256
+ },
257
+ play: async ({ canvas }) => {
258
+ await waitFor(() => expect(canvas.getByText('Showing 100 of 137 mutations.', { exact: false })).toBeVisible());
259
+ },
260
+ };
@@ -17,11 +17,17 @@ import { PreactLitAdapterWithGridJsStyles } from '../PreactLitAdapterWithGridJsS
17
17
  *
18
18
  * The grid view shows the proportion for each mutation over date ranges.
19
19
  *
20
- * The grid will show at max 100 rows and 200 columns for browser performance reasons.
21
- * More data might make the browser unresponsive.
22
- * If the numbers are exceeded, an error message will be shown.
23
- * In both cases, the `lapisFilter` should be narrowed down to reduce the number of mutations or date ranges.
24
- * The number of date ranges can also be reduced by selecting a larger granularity (months instead of weeks).
20
+ * The grid limits the number of rows columns for browser performance reasons.
21
+ * Too much data might make the browser unresponsive.
22
+ *
23
+ * The number of columns is limited to 200.
24
+ * If this number are exceeded, an error message will be shown.
25
+ * It is your responsibility to make sure that this does not happen.
26
+ * Depending on the selected date range in the `lapisFilter`, you can adapt the granularity accordingly
27
+ * (e.g. use months instead of days).
28
+ *
29
+ * The number of rows is limited to 100.
30
+ * If there are more, the component will only show 100 mutations and notify the user.
25
31
  */
26
32
  @customElement('gs-mutations-over-time')
27
33
  export class MutationsOverTimeComponent extends PreactLitAdapterWithGridJsStyles {