@genspectrum/dashboard-components 0.6.18 → 0.6.19

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 (108) hide show
  1. package/README.md +5 -12
  2. package/custom-elements.json +4 -4
  3. package/dist/assets/mutationOverTimeWorker-BdzqDqvO.js.map +1 -0
  4. package/dist/dashboard-components.js +216 -214
  5. package/dist/dashboard-components.js.map +1 -1
  6. package/dist/genspectrum-components.d.ts +40 -40
  7. package/dist/style.css +3 -2
  8. package/package.json +13 -2
  9. package/src/operator/FetchInsertionsOperator.ts +2 -2
  10. package/src/operator/FetchSubstitutionsOrDeletionsOperator.ts +3 -3
  11. package/src/preact/mutationComparison/fetchMutationData.spec.ts +3 -3
  12. package/src/preact/mutationComparison/getMutationComparisonTableData.spec.ts +11 -11
  13. package/src/preact/mutationComparison/getMutationComparisonTableData.ts +4 -4
  14. package/src/preact/mutationComparison/mutation-comparison-table.tsx +2 -2
  15. package/src/preact/mutationFilter/mutation-filter.tsx +27 -18
  16. package/src/preact/mutationFilter/parseAndValidateMutation.ts +4 -4
  17. package/src/preact/mutationFilter/parseMutation.spec.ts +17 -17
  18. package/src/preact/mutations/getInsertionsTableData.spec.ts +3 -3
  19. package/src/preact/mutations/getMutationsGridData.spec.ts +9 -9
  20. package/src/preact/mutations/getMutationsTableData.spec.ts +7 -7
  21. package/src/preact/mutations/mutations-insertions-table.tsx +3 -3
  22. package/src/preact/mutations/mutations-table.tsx +3 -3
  23. package/src/preact/mutationsOverTime/__mockData__/aminoAcidMutationsByDay.ts +45686 -0
  24. package/src/preact/mutationsOverTime/__mockData__/byWeek.ts +58989 -0
  25. package/src/preact/mutationsOverTime/__mockData__/defaultMockData.ts +103991 -0
  26. package/src/preact/mutationsOverTime/__mockData__/mockConversion.ts +54 -0
  27. package/src/preact/mutationsOverTime/__mockData__/showsMessageWhenTooManyMutations.ts +63690 -0
  28. package/src/preact/mutationsOverTime/getFilteredMutationsOverTime.spec.ts +176 -159
  29. package/src/preact/mutationsOverTime/getFilteredMutationsOverTimeData.ts +17 -59
  30. package/src/preact/mutationsOverTime/mutationOverTimeWorker.mock.ts +27 -0
  31. package/src/preact/mutationsOverTime/mutationOverTimeWorker.ts +29 -0
  32. package/src/preact/mutationsOverTime/mutations-over-time-grid.tsx +13 -14
  33. package/src/preact/mutationsOverTime/mutations-over-time.stories.tsx +9 -334
  34. package/src/preact/mutationsOverTime/mutations-over-time.tsx +68 -52
  35. package/src/preact/numberSequencesOverTime/getNumberOfSequencesOverTimeTableData.ts +3 -3
  36. package/src/preact/prevalenceOverTime/getPrevalenceOverTimeTableData.spec.ts +5 -5
  37. package/src/preact/prevalenceOverTime/prevalence-over-time-bubble-chart.tsx +1 -1
  38. package/src/preact/relativeGrowthAdvantage/relative-growth-advantage-chart.tsx +2 -2
  39. package/src/preact/shared/sort/sortInsertions.spec.ts +11 -11
  40. package/src/preact/shared/sort/sortInsertions.ts +2 -2
  41. package/src/preact/shared/sort/sortSubstitutionsAndDeletions.spec.ts +13 -13
  42. package/src/preact/shared/sort/sortSubstitutionsAndDeletions.ts +7 -4
  43. package/src/preact/webWorkers/useWebWorker.ts +51 -0
  44. package/src/preact/webWorkers/workerFunction.ts +14 -0
  45. package/src/query/queryAggregatedDataOverTime.ts +3 -3
  46. package/src/query/queryMutationsOverTime.spec.ts +272 -51
  47. package/src/query/queryMutationsOverTime.ts +114 -45
  48. package/src/query/queryPrevalenceOverTime.ts +2 -2
  49. package/src/query/queryRelativeGrowthAdvantage.ts +3 -3
  50. package/src/types.ts +25 -5
  51. package/src/utils/map2d.spec.ts +29 -1
  52. package/src/utils/map2d.ts +22 -1
  53. package/src/utils/mutations.spec.ts +20 -20
  54. package/src/utils/mutations.ts +80 -17
  55. package/src/utils/sort.ts +5 -2
  56. package/src/utils/temporal.spec.ts +27 -24
  57. package/src/utils/{temporal.ts → temporalClass.ts} +170 -72
  58. package/src/utils/temporalTestHelpers.ts +3 -3
  59. package/src/web-components/introduction.mdx +46 -0
  60. package/src/web-components/visualization/gs-mutations-over-time.stories.ts +6 -699
  61. package/src/web-components/visualization/gs-mutations-over-time.tsx +2 -2
  62. package/standalone-bundle/dashboard-components.js +13763 -13754
  63. package/standalone-bundle/dashboard-components.js.map +1 -1
  64. package/src/preact/mutationsOverTime/__mockData__/aggregated_2024_01.json +0 -13
  65. package/src/preact/mutationsOverTime/__mockData__/aggregated_2024_02.json +0 -13
  66. package/src/preact/mutationsOverTime/__mockData__/aggregated_2024_03.json +0 -13
  67. package/src/preact/mutationsOverTime/__mockData__/aggregated_2024_04.json +0 -13
  68. package/src/preact/mutationsOverTime/__mockData__/aggregated_2024_05.json +0 -13
  69. package/src/preact/mutationsOverTime/__mockData__/aggregated_2024_06.json +0 -13
  70. package/src/preact/mutationsOverTime/__mockData__/aggregated_2024_07.json +0 -13
  71. package/src/preact/mutationsOverTime/__mockData__/aggregated_20_01_2024.json +0 -13
  72. package/src/preact/mutationsOverTime/__mockData__/aggregated_21_01_2024.json +0 -13
  73. package/src/preact/mutationsOverTime/__mockData__/aggregated_22_01_2024.json +0 -13
  74. package/src/preact/mutationsOverTime/__mockData__/aggregated_23_01_2024.json +0 -13
  75. package/src/preact/mutationsOverTime/__mockData__/aggregated_24_01_2024.json +0 -13
  76. package/src/preact/mutationsOverTime/__mockData__/aggregated_25_01_2024.json +0 -13
  77. package/src/preact/mutationsOverTime/__mockData__/aggregated_26_01_2024.json +0 -13
  78. package/src/preact/mutationsOverTime/__mockData__/aggregated_byDay.json +0 -38
  79. package/src/preact/mutationsOverTime/__mockData__/aggregated_byWeek.json +0 -122
  80. package/src/preact/mutationsOverTime/__mockData__/aggregated_date.json +0 -642
  81. package/src/preact/mutationsOverTime/__mockData__/aggregated_tooManyMutations.json +0 -1470
  82. package/src/preact/mutationsOverTime/__mockData__/aggregated_tooManyMutations_total.json +0 -13
  83. package/src/preact/mutationsOverTime/__mockData__/aggregated_week3_2024.json +0 -13
  84. package/src/preact/mutationsOverTime/__mockData__/aggregated_week4_2024.json +0 -13
  85. package/src/preact/mutationsOverTime/__mockData__/aggregated_week5_2024.json +0 -13
  86. package/src/preact/mutationsOverTime/__mockData__/aggregated_week6_2024.json +0 -13
  87. package/src/preact/mutationsOverTime/__mockData__/aminoAcidMutations_20_01_2024.json +0 -6778
  88. package/src/preact/mutationsOverTime/__mockData__/aminoAcidMutations_21_01_2024.json +0 -7129
  89. package/src/preact/mutationsOverTime/__mockData__/aminoAcidMutations_22_01_2024.json +0 -4681
  90. package/src/preact/mutationsOverTime/__mockData__/aminoAcidMutations_23_01_2024.json +0 -10738
  91. package/src/preact/mutationsOverTime/__mockData__/aminoAcidMutations_24_01_2024.json +0 -11710
  92. package/src/preact/mutationsOverTime/__mockData__/aminoAcidMutations_25_01_2024.json +0 -11557
  93. package/src/preact/mutationsOverTime/__mockData__/aminoAcidMutations_26_01_2024.json +0 -8596
  94. package/src/preact/mutationsOverTime/__mockData__/aminoAcidMutations_byDayOverall.json +0 -4726
  95. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_2024_01.json +0 -1747
  96. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_2024_02.json +0 -1774
  97. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_2024_03.json +0 -1819
  98. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_2024_04.json +0 -1864
  99. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_2024_05.json +0 -1927
  100. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_2024_06.json +0 -1864
  101. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_2024_07.json +0 -9
  102. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_byMonthOverall.json +0 -11143
  103. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_byWeekOverall.json +0 -9154
  104. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_tooManyMutations.json +0 -16453
  105. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_week3_2024.json +0 -8812
  106. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_week4_2024.json +0 -9730
  107. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_week5_2024.json +0 -9865
  108. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_week6_2024.json +0 -11314
@@ -13,37 +13,37 @@ dayjs.extend(advancedFormat);
13
13
  const FORMAT_ISO_WEEK_YEAR_WEEK = 'GGGG-[W]WW';
14
14
 
15
15
  export class TemporalCache {
16
- private yearMonthDayCache = new Map<string, YearMonthDay>();
17
- private yearWeekCache = new Map<string, YearWeek>();
18
- private yearMonthCache = new Map<string, YearMonth>();
19
- private yearCache = new Map<string, Year>();
16
+ private yearMonthDayCache = new Map<string, YearMonthDayClass>();
17
+ private yearWeekCache = new Map<string, YearWeekClass>();
18
+ private yearMonthCache = new Map<string, YearMonthClass>();
19
+ private yearCache = new Map<string, YearClass>();
20
20
 
21
21
  private constructor() {}
22
22
 
23
- getYearMonthDay(s: string): YearMonthDay {
23
+ getYearMonthDay(s: string): YearMonthDayClass {
24
24
  if (!this.yearMonthDayCache.has(s)) {
25
- this.yearMonthDayCache.set(s, YearMonthDay.parse(s, this));
25
+ this.yearMonthDayCache.set(s, YearMonthDayClass.parse(s, this));
26
26
  }
27
27
  return this.yearMonthDayCache.get(s)!;
28
28
  }
29
29
 
30
- getYearMonth(s: string): YearMonth {
30
+ getYearMonth(s: string): YearMonthClass {
31
31
  if (!this.yearMonthCache.has(s)) {
32
- this.yearMonthCache.set(s, YearMonth.parse(s, this));
32
+ this.yearMonthCache.set(s, YearMonthClass.parse(s, this));
33
33
  }
34
34
  return this.yearMonthCache.get(s)!;
35
35
  }
36
36
 
37
- getYearWeek(s: string): YearWeek {
37
+ getYearWeek(s: string): YearWeekClass {
38
38
  if (!this.yearWeekCache.has(s)) {
39
- this.yearWeekCache.set(s, YearWeek.parse(s, this));
39
+ this.yearWeekCache.set(s, YearWeekClass.parse(s, this));
40
40
  }
41
41
  return this.yearWeekCache.get(s)!;
42
42
  }
43
43
 
44
- getYear(s: string): Year {
44
+ getYear(s: string): YearClass {
45
45
  if (!this.yearCache.has(s)) {
46
- this.yearCache.set(s, Year.parse(s, this));
46
+ this.yearCache.set(s, YearClass.parse(s, this));
47
47
  }
48
48
  return this.yearCache.get(s)!;
49
49
  }
@@ -55,9 +55,19 @@ export class TemporalCache {
55
55
  }
56
56
  }
57
57
 
58
- export class YearMonthDay {
58
+ interface YearMonthDay {
59
+ type: 'YearMonthDay';
60
+ yearNumber: number;
61
+ monthNumber: number;
62
+ dayNumber: number;
63
+ dateString: string;
64
+ }
65
+
66
+ export class YearMonthDayClass implements YearMonthDay {
67
+ readonly type = 'YearMonthDay';
59
68
  readonly date;
60
69
  readonly dayjs;
70
+ readonly dateString;
61
71
 
62
72
  constructor(
63
73
  readonly yearNumber: number,
@@ -67,6 +77,7 @@ export class YearMonthDay {
67
77
  ) {
68
78
  this.date = new Date(this.yearNumber, this.monthNumber - 1, this.dayNumber);
69
79
  this.dayjs = dayjs(this.date);
80
+ this.dateString = this.toString();
70
81
  }
71
82
 
72
83
  get text(): string {
@@ -81,48 +92,60 @@ export class YearMonthDay {
81
92
  return this.dayjs.format('dddd, MMMM D, YYYY');
82
93
  }
83
94
 
84
- get firstDay(): YearMonthDay {
95
+ get firstDay(): YearMonthDayClass {
85
96
  return this;
86
97
  }
87
98
 
88
- get lastDay(): YearMonthDay {
99
+ get lastDay(): YearMonthDayClass {
89
100
  return this;
90
101
  }
91
102
 
92
- get year(): Year {
103
+ get year(): YearClass {
93
104
  return this.cache.getYear(`${this.yearNumber}`);
94
105
  }
95
106
 
96
- get month(): YearMonth {
107
+ get month(): YearMonthClass {
97
108
  return this.cache.getYearMonth(this.dayjs.format('YYYY-MM'));
98
109
  }
99
110
 
100
- get week(): YearWeek {
111
+ get week(): YearWeekClass {
101
112
  return this.cache.getYearWeek(this.dayjs.format(FORMAT_ISO_WEEK_YEAR_WEEK));
102
113
  }
103
114
 
104
- addDays(days: number): YearMonthDay {
115
+ addDays(days: number): YearMonthDayClass {
105
116
  const date = this.dayjs.add(days, 'day');
106
117
  const s = date.format('YYYY-MM-DD');
107
118
  return this.cache.getYearMonthDay(s);
108
119
  }
109
120
 
110
- minus(other: YearMonthDay): number {
121
+ minus(other: YearMonthDayClass): number {
111
122
  return this.dayjs.diff(other.dayjs, 'day');
112
123
  }
113
124
 
114
- static parse(s: string, cache: TemporalCache): YearMonthDay {
125
+ static parse(s: string, cache: TemporalCache): YearMonthDayClass {
115
126
  const [year, month, day] = s.split('-').map((s) => parseInt(s, 10));
116
- return new YearMonthDay(year, month, day, cache);
127
+ return new YearMonthDayClass(year, month, day, cache);
117
128
  }
118
129
  }
119
130
 
120
- export class YearWeek {
131
+ interface YearWeek {
132
+ type: 'YearWeek';
133
+ isoYearNumber: number;
134
+ isoWeekNumber: number;
135
+ dateString: string;
136
+ }
137
+
138
+ export class YearWeekClass implements YearWeek {
139
+ readonly type = 'YearWeek';
140
+ readonly dateString;
141
+
121
142
  constructor(
122
143
  readonly isoYearNumber: number,
123
144
  readonly isoWeekNumber: number,
124
145
  readonly cache: TemporalCache,
125
- ) {}
146
+ ) {
147
+ this.dateString = this.toString();
148
+ }
126
149
 
127
150
  get text(): string {
128
151
  return this.firstDay.dayjs.format(FORMAT_ISO_WEEK_YEAR_WEEK);
@@ -136,7 +159,7 @@ export class YearWeek {
136
159
  return `Week ${this.isoWeekNumber}, ${this.isoYearNumber}`;
137
160
  }
138
161
 
139
- get firstDay(): YearMonthDay {
162
+ get firstDay(): YearMonthDayClass {
140
163
  // "The first week of the year, hence, always contains 4 January." https://en.wikipedia.org/wiki/ISO_week_date
141
164
  const firstDay = dayjs()
142
165
  .year(this.isoYearNumber)
@@ -147,7 +170,7 @@ export class YearWeek {
147
170
  return this.cache.getYearMonthDay(firstDay.format('YYYY-MM-DD'));
148
171
  }
149
172
 
150
- get lastDay(): YearMonthDay {
173
+ get lastDay(): YearMonthDayClass {
151
174
  const firstDay = dayjs()
152
175
  .year(this.isoYearNumber)
153
176
  .startOf('year')
@@ -159,32 +182,44 @@ export class YearWeek {
159
182
  return this.cache.getYearMonthDay(lastDay.format('YYYY-MM-DD'));
160
183
  }
161
184
 
162
- get year(): Year {
185
+ get year(): YearClass {
163
186
  return this.cache.getYear(`${this.isoYearNumber}`);
164
187
  }
165
188
 
166
- addWeeks(weeks: number): YearWeek {
189
+ addWeeks(weeks: number): YearWeekClass {
167
190
  const date = this.firstDay.dayjs.add(weeks, 'week');
168
191
  const s = date.format(FORMAT_ISO_WEEK_YEAR_WEEK);
169
192
  return this.cache.getYearWeek(s);
170
193
  }
171
194
 
172
- minus(other: YearWeek): number {
195
+ minus(other: YearWeekClass): number {
173
196
  return this.firstDay.dayjs.diff(other.firstDay.dayjs, 'week');
174
197
  }
175
198
 
176
- static parse(s: string, cache: TemporalCache): YearWeek {
199
+ static parse(s: string, cache: TemporalCache): YearWeekClass {
177
200
  const [year, week] = s.split('-W').map((s) => parseInt(s, 10));
178
- return new YearWeek(year, week, cache);
201
+ return new YearWeekClass(year, week, cache);
179
202
  }
180
203
  }
181
204
 
182
- export class YearMonth {
205
+ interface YearMonth {
206
+ type: 'YearMonth';
207
+ yearNumber: number;
208
+ monthNumber: number;
209
+ dateString: string;
210
+ }
211
+
212
+ export class YearMonthClass implements YearMonth {
213
+ readonly type = 'YearMonth';
214
+ readonly dateString;
215
+
183
216
  constructor(
184
217
  readonly yearNumber: number,
185
218
  readonly monthNumber: number,
186
219
  readonly cache: TemporalCache,
187
- ) {}
220
+ ) {
221
+ this.dateString = this.toString();
222
+ }
188
223
 
189
224
  get text(): string {
190
225
  return this.firstDay.dayjs.format('YYYY-MM');
@@ -198,41 +233,52 @@ export class YearMonth {
198
233
  return `${monthName(this.monthNumber)} ${this.yearNumber}`;
199
234
  }
200
235
 
201
- get firstDay(): YearMonthDay {
236
+ get firstDay(): YearMonthDayClass {
202
237
  return this.cache.getYearMonthDay(dayjs(`${this.yearNumber}-${this.monthNumber}-01`).format('YYYY-MM-DD'));
203
238
  }
204
239
 
205
- get lastDay(): YearMonthDay {
240
+ get lastDay(): YearMonthDayClass {
206
241
  return this.cache.getYearMonthDay(
207
242
  dayjs(`${this.yearNumber}-${this.monthNumber}-01`).endOf('month').format('YYYY-MM-DD'),
208
243
  );
209
244
  }
210
245
 
211
- get year(): Year {
246
+ get year(): YearClass {
212
247
  return this.cache.getYear(`${this.yearNumber}`);
213
248
  }
214
249
 
215
- addMonths(months: number): YearMonth {
250
+ addMonths(months: number): YearMonthClass {
216
251
  const date = this.firstDay.dayjs.add(months, 'month');
217
252
  const s = date.format('YYYY-MM');
218
253
  return this.cache.getYearMonth(s);
219
254
  }
220
255
 
221
- minus(other: YearMonth): number {
256
+ minus(other: YearMonthClass): number {
222
257
  return this.firstDay.dayjs.diff(other.firstDay.dayjs, 'month');
223
258
  }
224
259
 
225
- static parse(s: string, cache: TemporalCache): YearMonth {
260
+ static parse(s: string, cache: TemporalCache): YearMonthClass {
226
261
  const [year, month] = s.split('-').map((s) => parseInt(s, 10));
227
- return new YearMonth(year, month, cache);
262
+ return new YearMonthClass(year, month, cache);
228
263
  }
229
264
  }
230
265
 
231
- export class Year {
266
+ interface Year {
267
+ type: 'Year';
268
+ year: number;
269
+ dateString: string;
270
+ }
271
+
272
+ export class YearClass implements Year {
273
+ readonly type = 'Year';
274
+ readonly dateString;
275
+
232
276
  constructor(
233
277
  readonly year: number,
234
278
  readonly cache: TemporalCache,
235
- ) {}
279
+ ) {
280
+ this.dateString = this.toString();
281
+ }
236
282
 
237
283
  get text(): string {
238
284
  return this.firstDay.dayjs.format('YYYY');
@@ -246,35 +292,35 @@ export class Year {
246
292
  return this.year.toString();
247
293
  }
248
294
 
249
- get firstMonth(): YearMonth {
295
+ get firstMonth(): YearMonthClass {
250
296
  return this.cache.getYearMonth(`${this.year}-01`);
251
297
  }
252
298
 
253
- get lastMonth(): YearMonth {
299
+ get lastMonth(): YearMonthClass {
254
300
  return this.cache.getYearMonth(`${this.year}-12`);
255
301
  }
256
302
 
257
- get firstDay(): YearMonthDay {
303
+ get firstDay(): YearMonthDayClass {
258
304
  return this.firstMonth.firstDay;
259
305
  }
260
306
 
261
- get lastDay(): YearMonthDay {
307
+ get lastDay(): YearMonthDayClass {
262
308
  return this.lastMonth.lastDay;
263
309
  }
264
310
 
265
- addYears(years: number): Year {
311
+ addYears(years: number): YearClass {
266
312
  const date = this.firstDay.dayjs.add(years, 'year');
267
313
  const s = date.format('YYYY');
268
314
  return this.cache.getYear(s);
269
315
  }
270
316
 
271
- minus(other: Year): number {
317
+ minus(other: YearClass): number {
272
318
  return this.firstDay.dayjs.diff(other.firstDay.dayjs, 'year');
273
319
  }
274
320
 
275
- static parse(s: string, cache: TemporalCache): Year {
321
+ static parse(s: string, cache: TemporalCache): YearClass {
276
322
  const year = parseInt(s, 10);
277
- return new Year(year, cache);
323
+ return new YearClass(year, cache);
278
324
  }
279
325
  }
280
326
 
@@ -284,9 +330,61 @@ function monthName(month: number): string {
284
330
  .format('MMMM');
285
331
  }
286
332
 
333
+ export type TemporalClass = YearMonthDayClass | YearWeekClass | YearMonthClass | YearClass;
287
334
  export type Temporal = YearMonthDay | YearWeek | YearMonth | Year;
288
335
 
289
- export function generateAllDaysInRange(start: YearMonthDay, end: YearMonthDay): YearMonthDay[] {
336
+ export function toTemporalClass(temporal: Temporal) {
337
+ switch (temporal.type) {
338
+ case 'YearMonthDay':
339
+ return new YearMonthDayClass(
340
+ temporal.yearNumber,
341
+ temporal.monthNumber,
342
+ temporal.dayNumber,
343
+ TemporalCache.getInstance(),
344
+ );
345
+ case 'YearWeek':
346
+ return new YearWeekClass(temporal.isoYearNumber, temporal.isoWeekNumber, TemporalCache.getInstance());
347
+ case 'YearMonth':
348
+ return new YearMonthClass(temporal.yearNumber, temporal.monthNumber, TemporalCache.getInstance());
349
+ case 'Year':
350
+ return new YearClass(temporal.year, TemporalCache.getInstance());
351
+ }
352
+ }
353
+
354
+ export function toTemporal(temporalClass: TemporalClass): Temporal {
355
+ switch (temporalClass.type) {
356
+ case 'YearMonthDay':
357
+ return {
358
+ type: 'YearMonthDay',
359
+ yearNumber: temporalClass.yearNumber,
360
+ monthNumber: temporalClass.monthNumber,
361
+ dayNumber: temporalClass.dayNumber,
362
+ dateString: temporalClass.dateString,
363
+ };
364
+ case 'YearWeek':
365
+ return {
366
+ type: 'YearWeek',
367
+ isoYearNumber: temporalClass.isoYearNumber,
368
+ isoWeekNumber: temporalClass.isoWeekNumber,
369
+ dateString: temporalClass.dateString,
370
+ };
371
+ case 'YearMonth':
372
+ return {
373
+ type: 'YearMonth',
374
+ yearNumber: temporalClass.yearNumber,
375
+ monthNumber: temporalClass.monthNumber,
376
+ dateString: temporalClass.dateString,
377
+ };
378
+ case 'Year':
379
+ return {
380
+ type: 'Year',
381
+ year: temporalClass.year,
382
+ dateString: temporalClass.dateString,
383
+ };
384
+ }
385
+ }
386
+
387
+ export function generateAllDaysInRange(start: YearMonthDayClass, end: YearMonthDayClass): YearMonthDayClass[] {
290
388
  const days = [];
291
389
  const daysInBetween = end.minus(start);
292
390
  for (let i = 0; i <= daysInBetween; i++) {
@@ -295,7 +393,7 @@ export function generateAllDaysInRange(start: YearMonthDay, end: YearMonthDay):
295
393
  return days;
296
394
  }
297
395
 
298
- export function generateAllWeeksInRange(start: YearWeek, end: YearWeek): YearWeek[] {
396
+ export function generateAllWeeksInRange(start: YearWeekClass, end: YearWeekClass): YearWeekClass[] {
299
397
  const weeks = [];
300
398
  const weeksInBetween = end.minus(start);
301
399
  for (let i = 0; i <= weeksInBetween; i++) {
@@ -304,7 +402,7 @@ export function generateAllWeeksInRange(start: YearWeek, end: YearWeek): YearWee
304
402
  return weeks;
305
403
  }
306
404
 
307
- export function generateAllMonthsInRange(start: YearMonth, end: YearMonth): YearMonth[] {
405
+ export function generateAllMonthsInRange(start: YearMonthClass, end: YearMonthClass): YearMonthClass[] {
308
406
  const months = [];
309
407
  const monthsInBetween = end.minus(start);
310
408
  for (let i = 0; i <= monthsInBetween; i++) {
@@ -313,7 +411,7 @@ export function generateAllMonthsInRange(start: YearMonth, end: YearMonth): Year
313
411
  return months;
314
412
  }
315
413
 
316
- export function generateAllYearsInRange(start: Year, end: Year): Year[] {
414
+ export function generateAllYearsInRange(start: YearClass, end: YearClass): YearClass[] {
317
415
  const years = [];
318
416
  const yearsInBetween = end.minus(start);
319
417
  for (let i = 0; i <= yearsInBetween; i++) {
@@ -322,42 +420,42 @@ export function generateAllYearsInRange(start: Year, end: Year): Year[] {
322
420
  return years;
323
421
  }
324
422
 
325
- export function generateAllInRange(start: Temporal | null, end: Temporal | null): Temporal[] {
423
+ export function generateAllInRange(start: TemporalClass | null, end: TemporalClass | null): TemporalClass[] {
326
424
  if (start === null || end === null) {
327
425
  return [];
328
426
  }
329
- if (start instanceof YearMonthDay && end instanceof YearMonthDay) {
427
+ if (start instanceof YearMonthDayClass && end instanceof YearMonthDayClass) {
330
428
  return generateAllDaysInRange(start, end);
331
429
  }
332
- if (start instanceof YearWeek && end instanceof YearWeek) {
430
+ if (start instanceof YearWeekClass && end instanceof YearWeekClass) {
333
431
  return generateAllWeeksInRange(start, end);
334
432
  }
335
- if (start instanceof YearMonth && end instanceof YearMonth) {
433
+ if (start instanceof YearMonthClass && end instanceof YearMonthClass) {
336
434
  return generateAllMonthsInRange(start, end);
337
435
  }
338
- if (start instanceof Year && end instanceof Year) {
436
+ if (start instanceof YearClass && end instanceof YearClass) {
339
437
  return generateAllYearsInRange(start, end);
340
438
  }
341
439
  throw new Error(`Invalid arguments: start and end must be of the same type: ${start}, ${end}`);
342
440
  }
343
441
 
344
- export function minusTemporal(a: Temporal, b: Temporal): number {
345
- if (a instanceof YearMonthDay && b instanceof YearMonthDay) {
442
+ export function minusTemporal(a: TemporalClass, b: TemporalClass): number {
443
+ if (a instanceof YearMonthDayClass && b instanceof YearMonthDayClass) {
346
444
  return a.minus(b);
347
445
  }
348
- if (a instanceof YearWeek && b instanceof YearWeek) {
446
+ if (a instanceof YearWeekClass && b instanceof YearWeekClass) {
349
447
  return a.minus(b);
350
448
  }
351
- if (a instanceof YearMonth && b instanceof YearMonth) {
449
+ if (a instanceof YearMonthClass && b instanceof YearMonthClass) {
352
450
  return a.minus(b);
353
451
  }
354
- if (a instanceof Year && b instanceof Year) {
452
+ if (a instanceof YearClass && b instanceof YearClass) {
355
453
  return a.minus(b);
356
454
  }
357
455
  throw new Error(`Cannot compare ${a} and ${b}`);
358
456
  }
359
457
 
360
- export function compareTemporal(a: Temporal | null, b: Temporal | null): number {
458
+ export function compareTemporal(a: TemporalClass | null, b: TemporalClass | null): number {
361
459
  if (a === null) {
362
460
  return 1;
363
461
  }
@@ -374,7 +472,7 @@ export function compareTemporal(a: Temporal | null, b: Temporal | null): number
374
472
  return 0;
375
473
  }
376
474
 
377
- export function getMinMaxTemporal<T extends Temporal>(values: Iterable<T | null>) {
475
+ export function getMinMaxTemporal<T extends TemporalClass>(values: Iterable<T | null>) {
378
476
  let min: T | null = null;
379
477
  let max: T | null = null;
380
478
  for (const value of values) {
@@ -394,17 +492,17 @@ export function getMinMaxTemporal<T extends Temporal>(values: Iterable<T | null>
394
492
  return { min, max };
395
493
  }
396
494
 
397
- export function addUnit(temporal: Temporal, amount: number): Temporal {
398
- if (temporal instanceof YearMonthDay) {
495
+ export function addUnit(temporal: TemporalClass, amount: number): TemporalClass {
496
+ if (temporal instanceof YearMonthDayClass) {
399
497
  return temporal.addDays(amount);
400
498
  }
401
- if (temporal instanceof YearWeek) {
499
+ if (temporal instanceof YearWeekClass) {
402
500
  return temporal.addWeeks(amount);
403
501
  }
404
- if (temporal instanceof YearMonth) {
502
+ if (temporal instanceof YearMonthClass) {
405
503
  return temporal.addMonths(amount);
406
504
  }
407
- if (temporal instanceof Year) {
505
+ if (temporal instanceof YearClass) {
408
506
  return temporal.addYears(amount);
409
507
  }
410
508
  throw new Error(`Invalid argument: ${temporal}`);
@@ -425,7 +523,7 @@ export function parseDateStringToTemporal(date: string, granularity: TemporalGra
425
523
  }
426
524
  }
427
525
 
428
- export function dateRangeCompare(a: { dateRange: Temporal | null }, b: { dateRange: Temporal | null }) {
526
+ export function dateRangeCompare(a: { dateRange: TemporalClass | null }, b: { dateRange: TemporalClass | null }) {
429
527
  if (a.dateRange === null) {
430
528
  return 1;
431
529
  }
@@ -1,9 +1,9 @@
1
- import { TemporalCache, YearMonth, YearMonthDay } from './temporal';
1
+ import { TemporalCache, YearMonthClass, YearMonthDayClass } from './temporalClass';
2
2
 
3
3
  export function yearMonthDay(date: string) {
4
- return YearMonthDay.parse(date, TemporalCache.getInstance());
4
+ return YearMonthDayClass.parse(date, TemporalCache.getInstance());
5
5
  }
6
6
 
7
7
  export function yearMonth(date: string) {
8
- return YearMonth.parse(date, TemporalCache.getInstance());
8
+ return YearMonthClass.parse(date, TemporalCache.getInstance());
9
9
  }
@@ -4,6 +4,21 @@ import { Meta } from '@storybook/blocks';
4
4
 
5
5
  # Introduction
6
6
 
7
+ <a
8
+ style={{ display: 'flex', 'align-items': 'center', 'justify-content': 'right' }}
9
+ href='https://github.com/GenSpectrum/dashboard-components'
10
+ >
11
+ <svg style={{ width: '3%', height: '3%' }} viewBox='0 0 98 96' xmlns='http://www.w3.org/2000/svg'>
12
+ <path
13
+ fill-rule='evenodd'
14
+ clip-rule='evenodd'
15
+ d='M48.854 0C21.839 0 0 22 0 49.217c0 21.756 13.993 40.172 33.405 46.69 2.427.49 3.316-1.059 3.316-2.362 0-1.141-.08-5.052-.08-9.127-13.59 2.934-16.42-5.867-16.42-5.867-2.184-5.704-5.42-7.17-5.42-7.17-4.448-3.015.324-3.015.324-3.015 4.934.326 7.523 5.052 7.523 5.052 4.367 7.496 11.404 5.378 14.235 4.074.404-3.178 1.699-5.378 3.074-6.6-10.839-1.141-22.243-5.378-22.243-24.283 0-5.378 1.94-9.778 5.014-13.2-.485-1.222-2.184-6.275.486-13.038 0 0 4.125-1.304 13.426 5.052a46.97 46.97 0 0 1 12.214-1.63c4.125 0 8.33.571 12.213 1.63 9.302-6.356 13.427-5.052 13.427-5.052 2.67 6.763.97 11.816.485 13.038 3.155 3.422 5.015 7.822 5.015 13.2 0 18.905-11.404 23.06-22.324 24.283 1.78 1.548 3.316 4.481 3.316 9.126 0 6.6-.08 11.897-.08 13.526 0 1.304.89 2.853 3.316 2.364 19.412-6.52 33.405-24.935 33.405-46.691C97.707 22 75.788 0 48.854 0z'
16
+ fill='#24292f'
17
+ />
18
+ </svg>
19
+ <span style={{ 'margin-left': '4px' }}>Visit on GitHub</span>
20
+ </a>
21
+
7
22
  This package provides a collection of web components to build interactive dashboards that visualize
8
23
  data of a specific instance of [LAPIS](https://github.com/GenSpectrum/LAPIS).
9
24
 
@@ -13,3 +28,34 @@ We primarily provide two kinds of components:
13
28
  Those components fetch data from the LAPIS instance and visualize it.
14
29
  - Input components that let you specify sequence filters for the LAPIS requests.
15
30
  Input changes will fire events that can be listened to by the visualization components. It is the responsibility of the dashbaord maintainer to listen to those events and to wire the data correctly into the visualization components.
31
+
32
+ ## Installation
33
+
34
+ ```bash
35
+ npm i @genspectrum/dashboard-components
36
+ ```
37
+
38
+ ## Usage
39
+
40
+ All components must be children of a `gs-app` element.
41
+
42
+ ```html
43
+ <gs-app lapis="https://url.to.lapis">
44
+ <gs-location-filter
45
+ fields='["region", "country"]'
46
+ initialValue="Europe / Switzerland"
47
+ width="100%"
48
+ placeholderText="Enter a location"
49
+ ></gs-location-filter>
50
+ <gs-aggregate
51
+ fields='["division", "host"]'
52
+ filter='{"country": "USA"}'
53
+ views='["table"]'
54
+ width="100%"
55
+ height="700px"
56
+ initialSortField="count"
57
+ initialSortDirection="descending"
58
+ pageSize="10"
59
+ ></gs-aggregate>
60
+ </gs-app>
61
+ ```