@genspectrum/dashboard-components 0.6.1 → 0.6.3

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 (40) hide show
  1. package/custom-elements.json +228 -0
  2. package/dist/dashboard-components.js +778 -244
  3. package/dist/dashboard-components.js.map +1 -1
  4. package/dist/genspectrum-components.d.ts +119 -9
  5. package/dist/style.css +7 -4
  6. package/package.json +3 -1
  7. package/src/constants.ts +1 -1
  8. package/src/lapisApi/lapisTypes.ts +1 -0
  9. package/src/operator/FillMissingOperator.spec.ts +3 -1
  10. package/src/operator/FillMissingOperator.ts +4 -2
  11. package/src/preact/mutationComparison/queryMutationData.ts +12 -4
  12. package/src/preact/mutationsOverTime/__mockData__/aggregated_date.json +642 -0
  13. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_2024_01.json +1747 -0
  14. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_2024_02.json +1774 -0
  15. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_2024_03.json +1819 -0
  16. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_2024_04.json +1864 -0
  17. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_2024_05.json +1927 -0
  18. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_2024_06.json +1864 -0
  19. package/src/preact/mutationsOverTime/__mockData__/nucleotideMutations_2024_07.json +9 -0
  20. package/src/preact/mutationsOverTime/getFilteredMutationsOverTime.spec.ts +86 -0
  21. package/src/preact/mutationsOverTime/getFilteredMutationsOverTimeData.ts +62 -0
  22. package/src/preact/mutationsOverTime/mutations-over-time-grid.tsx +92 -0
  23. package/src/preact/mutationsOverTime/mutations-over-time.stories.tsx +206 -0
  24. package/src/preact/mutationsOverTime/mutations-over-time.tsx +170 -0
  25. package/src/preact/numberSequencesOverTime/getNumberOfSequencesOverTimeTableData.ts +1 -1
  26. package/src/preact/prevalenceOverTime/prevalence-over-time.stories.tsx +1 -0
  27. package/src/preact/shared/table/formatProportion.ts +2 -2
  28. package/src/query/queryAggregatedDataOverTime.ts +8 -33
  29. package/src/query/queryMutationsOverTime.spec.ts +352 -0
  30. package/src/query/queryMutationsOverTime.ts +164 -0
  31. package/src/query/queryNumberOfSequencesOverTime.ts +0 -1
  32. package/src/query/queryRelativeGrowthAdvantage.ts +3 -3
  33. package/src/utils/Map2d.ts +75 -0
  34. package/src/utils/map2d.spec.ts +94 -0
  35. package/src/utils/mutations.ts +5 -1
  36. package/src/utils/temporal.ts +64 -5
  37. package/src/web-components/input/index.ts +1 -0
  38. package/src/web-components/visualization/gs-mutations-over-time.stories.ts +225 -0
  39. package/src/web-components/visualization/gs-mutations-over-time.tsx +107 -0
  40. package/src/web-components/visualization/index.ts +1 -0
@@ -180,6 +180,53 @@ export declare class DateRangeSelectorComponent extends PreactLitAdapter {
180
180
 
181
181
  declare type LapisFilter = Record<string, string | number | null | boolean>;
182
182
 
183
+ /**
184
+ *
185
+ * ## Context
186
+ *
187
+ * This component provides a text input field to filter by lineages.
188
+ * Currently, it is designed to work well with Pango Lineages,
189
+ * but it may also be used for other lineage types, if suitable.
190
+ *
191
+ * It fetches all available values of the `lapisField` from the LAPIS instance
192
+ * and provides an autocomplete list with the available values of the lineage and sublineage queries
193
+ * (a `*` appended to the lineage value).
194
+ *
195
+ * @fires {CustomEvent<Record<string, string>>} gs-lineage-filter-changed
196
+ * Fired when the input field is changed.
197
+ * The `details` of this event contain an object with the `lapisField` as key and the input value as value.
198
+ * Example:
199
+ * ```
200
+ * {
201
+ * "pangoLineage": "B.1.1.7"
202
+ * }
203
+ * ```
204
+ */
205
+ export declare class LineageFilterComponent extends PreactLitAdapter {
206
+ /**
207
+ * The initial value to use for this lineage filter.
208
+ */
209
+ initialValue: string;
210
+ /**
211
+ * Required.
212
+ *
213
+ * The LAPIS field name to use for this lineage filter.
214
+ * The field must exist on this LAPIS instance.
215
+ */
216
+ lapisField: string;
217
+ /**
218
+ * The placeholder text to display in the input field.
219
+ */
220
+ placeholderText: string;
221
+ /**
222
+ * The width of the component.
223
+ *
224
+ * Visit https://genspectrum.github.io/dashboard-components/?path=/docs/components-size-of-components--docs for more information.
225
+ */
226
+ width: string;
227
+ render(): JSX_2.Element;
228
+ }
229
+
183
230
  /**
184
231
  * ## Context
185
232
  *
@@ -441,6 +488,62 @@ export declare class MutationsComponent extends PreactLitAdapterWithGridJsStyles
441
488
  render(): JSX_2.Element;
442
489
  }
443
490
 
491
+ /**
492
+ * ## Context
493
+ *
494
+ * This component displays mutations (substitutions and deletions) over time for a dataset selected by a LAPIS filter.
495
+ * The shown date range is determined by the date field in the LAPIS filter.
496
+ * If the date field is not set, the date range is determined by all available dates in the dataset.
497
+ *
498
+ * ## Views
499
+ *
500
+ * ### Grid View
501
+ *
502
+ * The grid view shows the proportion for each mutation over date ranges.
503
+ *
504
+ */
505
+ export declare class MutationsOverTimeComponent extends PreactLitAdapterWithGridJsStyles {
506
+ /**
507
+ * Required.
508
+ *
509
+ * LAPIS filter to select the displayed data.
510
+ */
511
+ lapisFilter: Record<string, string | number | null | boolean>;
512
+ /**
513
+ * The type of the sequence for which the mutations should be shown.
514
+ */
515
+ sequenceType: 'nucleotide' | 'amino acid';
516
+ /**
517
+ * A list of tabs with views that this component should provide.
518
+ */
519
+ views: 'grid'[];
520
+ /**
521
+ * The width of the component.
522
+ *
523
+ * Visit https://genspectrum.github.io/dashboard-components/?path=/docs/components-size-of-components--docs for more information.
524
+ */
525
+ width: string;
526
+ /**
527
+ * The height of the component.
528
+ *
529
+ * Visit https://genspectrum.github.io/dashboard-components/?path=/docs/components-size-of-components--docs for more information.
530
+ */
531
+ height: string;
532
+ /**
533
+ * The granularity of the time axis.
534
+ */
535
+ granularity: 'day' | 'week' | 'month' | 'year';
536
+ /**
537
+ * Required.
538
+ *
539
+ * The LAPIS field that the data should be aggregated by.
540
+ * The values will be used for the columns of the grid.
541
+ * Must be a field of type `date` in LAPIS.
542
+ */
543
+ lapisDateField: string;
544
+ render(): JSX_2.Element;
545
+ }
546
+
444
547
  /**
445
548
  * ## Context
446
549
  *
@@ -888,6 +991,13 @@ declare global {
888
991
  }
889
992
 
890
993
 
994
+ declare global {
995
+ interface HTMLElementTagNameMap {
996
+ 'gs-mutations-over-time-component': MutationsOverTimeComponent;
997
+ }
998
+ }
999
+
1000
+
891
1001
  declare global {
892
1002
  interface HTMLElementTagNameMap {
893
1003
  'gs-date-range-selector': DateRangeSelectorComponent;
@@ -929,15 +1039,6 @@ declare global {
929
1039
  }
930
1040
 
931
1041
 
932
- declare module 'chart.js' {
933
- interface CartesianScaleTypeRegistry {
934
- logit: {
935
- options: CoreScaleOptions;
936
- };
937
- }
938
- }
939
-
940
-
941
1042
  declare global {
942
1043
  interface HTMLElementTagNameMap {
943
1044
  'gs-lineage-filter': LineageFilterComponent;
@@ -947,3 +1048,12 @@ declare global {
947
1048
  }
948
1049
  }
949
1050
 
1051
+
1052
+ declare module 'chart.js' {
1053
+ interface CartesianScaleTypeRegistry {
1054
+ logit: {
1055
+ options: CoreScaleOptions;
1056
+ };
1057
+ }
1058
+ }
1059
+
package/dist/style.css CHANGED
@@ -376,7 +376,7 @@ input[type="range"] {
376
376
  background-color: #C6C6C6;
377
377
  pointer-events: none;
378
378
  }/*
379
- ! tailwindcss v3.4.4 | MIT License | https://tailwindcss.com
379
+ ! tailwindcss v3.4.6 | MIT License | https://tailwindcss.com
380
380
  *//*
381
381
  1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4)
382
382
  2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116)
@@ -2825,9 +2825,6 @@ input.tab:checked + .tab-content,
2825
2825
  .mb-2 {
2826
2826
  margin-bottom: 0.5rem;
2827
2827
  }
2828
- .ml-2 {
2829
- margin-left: 0.5rem;
2830
- }
2831
2828
  .ml-2\.5 {
2832
2829
  margin-left: 0.625rem;
2833
2830
  }
@@ -3032,6 +3029,9 @@ input.tab:checked + .tab-content,
3032
3029
  padding-top: 1rem;
3033
3030
  padding-bottom: 1rem;
3034
3031
  }
3032
+ .text-center {
3033
+ text-align: center;
3034
+ }
3035
3035
  .text-justify {
3036
3036
  text-align: justify;
3037
3037
  }
@@ -3123,6 +3123,9 @@ input.tab:checked + .tab-content,
3123
3123
  --tw-bg-opacity: 1;
3124
3124
  background-color: rgb(243 244 246 / var(--tw-bg-opacity));
3125
3125
  }
3126
+ .hover\:font-bold:hover {
3127
+ font-weight: 700;
3128
+ }
3126
3129
  .hover\:text-blue-700:hover {
3127
3130
  --tw-text-opacity: 1;
3128
3131
  color: rgb(29 78 216 / var(--tw-text-opacity));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@genspectrum/dashboard-components",
3
- "version": "0.6.1",
3
+ "version": "0.6.3",
4
4
  "description": "GenSpectrum web components for building dashboards",
5
5
  "type": "module",
6
6
  "license": "AGPL-3.0-only",
@@ -68,6 +68,7 @@
68
68
  "flatpickr": "^4.6.13",
69
69
  "gridjs": "^6.2.0",
70
70
  "lit": "^3.1.3",
71
+ "object-hash": "^3.0.0",
71
72
  "preact": "^10.20.1",
72
73
  "zod": "^3.23.0"
73
74
  },
@@ -87,6 +88,7 @@
87
88
  "@storybook/web-components": "^8.0.9",
88
89
  "@storybook/web-components-vite": "^8.0.9",
89
90
  "@types/node": "^20.12.7",
91
+ "@types/object-hash": "^3.0.6",
90
92
  "@typescript-eslint/eslint-plugin": "^7.14.1",
91
93
  "@typescript-eslint/parser": "^7.14.1",
92
94
  "autoprefixer": "^10.4.19",
package/src/constants.ts CHANGED
@@ -1,4 +1,4 @@
1
- export const LAPIS_URL = 'https://lapis.cov-spectrum.org/open/v2/';
1
+ export const LAPIS_URL = 'https://lapis.cov-spectrum.org/open/v2';
2
2
 
3
3
  export const AGGREGATED_ENDPOINT = `${LAPIS_URL}/sample/aggregated`;
4
4
  export const NUCLEOTIDE_MUTATIONS_ENDPOINT = `${LAPIS_URL}/sample/nucleotideMutations`;
@@ -30,6 +30,7 @@ const mutationProportionCount = z.object({
30
30
  position: z.number(),
31
31
  });
32
32
  export const mutationsResponse = makeLapisResponse(z.array(mutationProportionCount));
33
+ export type MutationsResponse = z.infer<typeof mutationsResponse>;
33
34
 
34
35
  const insertionCount = z.object({
35
36
  insertion: z.string(),
@@ -10,7 +10,9 @@ describe('FillMissingOperator', () => {
10
10
  const query = new FillMissingOperator(
11
11
  child,
12
12
  'id',
13
- (ids) => [Math.min(...ids), Math.max(...ids)],
13
+ (ids) => {
14
+ return { min: Math.min(...ids), max: Math.max(...ids) };
15
+ },
14
16
  (min, max) => {
15
17
  const result = [];
16
18
  for (let i = min; i <= max; i++) {
@@ -5,7 +5,9 @@ export class FillMissingOperator<Data, KeyToFill extends keyof Data> implements
5
5
  constructor(
6
6
  private child: Operator<Data>,
7
7
  private keyField: KeyToFill,
8
- private getMinMaxFn: (values: Iterable<Data[KeyToFill]>) => [Data[KeyToFill], Data[KeyToFill]] | null,
8
+ private getMinMaxFn: (
9
+ values: Iterable<Data[KeyToFill]>,
10
+ ) => { min: Data[KeyToFill]; max: Data[KeyToFill] } | null,
9
11
  private getAllRequiredKeysFn: (min: Data[KeyToFill], max: Data[KeyToFill]) => Data[KeyToFill][],
10
12
  private defaultValueFn: (key: Data[KeyToFill]) => Data,
11
13
  ) {}
@@ -17,7 +19,7 @@ export class FillMissingOperator<Data, KeyToFill extends keyof Data> implements
17
19
  if (minMax === null) {
18
20
  return childEvaluated;
19
21
  }
20
- const [min, max] = minMax;
22
+ const { min, max } = minMax;
21
23
  const requiredKeys = this.getAllRequiredKeysFn(min, max);
22
24
  const content = childEvaluated.content;
23
25
  for (const key of requiredKeys) {
@@ -28,6 +28,17 @@ export function filterMutationData(
28
28
  data: MutationData[],
29
29
  displayedSegments: DisplayedSegment[],
30
30
  displayedMutationTypes: DisplayedMutationType[],
31
+ ) {
32
+ return data.map((mutationEntry) => ({
33
+ displayName: mutationEntry.displayName,
34
+ data: filterBySegmentAndMutationType(mutationEntry.data, displayedSegments, displayedMutationTypes),
35
+ }));
36
+ }
37
+
38
+ export function filterBySegmentAndMutationType(
39
+ data: SubstitutionOrDeletionEntry[],
40
+ displayedSegments: DisplayedSegment[],
41
+ displayedMutationTypes: DisplayedMutationType[],
31
42
  ) {
32
43
  const byDisplayedSegments = (mutationEntry: SubstitutionOrDeletionEntry) => {
33
44
  if (mutationEntry.mutation.segment === undefined) {
@@ -45,8 +56,5 @@ export function filterMutationData(
45
56
  );
46
57
  };
47
58
 
48
- return data.map((mutationEntry) => ({
49
- displayName: mutationEntry.displayName,
50
- data: mutationEntry.data.filter(byDisplayedSegments).filter(byDisplayedMutationTypes),
51
- }));
59
+ return data.filter(byDisplayedSegments).filter(byDisplayedMutationTypes);
52
60
  }