@genspectrum/dashboard-components 0.11.5 → 0.11.7

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 (41) hide show
  1. package/custom-elements.json +92 -6
  2. package/dist/assets/{mutationOverTimeWorker-CWneD7i5.js.map → mutationOverTimeWorker-DTv93Ere.js.map} +1 -1
  3. package/dist/components.d.ts +67 -19
  4. package/dist/components.js +301 -90
  5. package/dist/components.js.map +1 -1
  6. package/dist/style.css +3 -0
  7. package/dist/util.d.ts +53 -22
  8. package/package.json +1 -1
  9. package/src/preact/aggregatedData/__mockData__/aggregatedWith1Field.json +399 -0
  10. package/src/preact/aggregatedData/__mockData__/aggregatedWith2Fields.json +1771 -0
  11. package/src/preact/aggregatedData/aggregate-bar-chart.tsx +177 -0
  12. package/src/preact/aggregatedData/aggregate-table.tsx +24 -2
  13. package/src/preact/aggregatedData/aggregate.stories.tsx +61 -2
  14. package/src/preact/aggregatedData/aggregate.tsx +18 -6
  15. package/src/preact/mutations/__mockData__/baselineNucleotideMutations.json +337412 -0
  16. package/src/preact/mutations/__mockData__/overallVariantCount.json +14 -0
  17. package/src/preact/mutations/getMutationsTableData.spec.ts +20 -3
  18. package/src/preact/mutations/getMutationsTableData.ts +37 -2
  19. package/src/preact/mutations/mutations-table.tsx +47 -27
  20. package/src/preact/mutations/mutations.stories.tsx +41 -9
  21. package/src/preact/mutations/mutations.tsx +22 -6
  22. package/src/preact/mutations/queryMutations.ts +28 -8
  23. package/src/preact/mutationsOverTime/__mockData__/aminoAcidMutationsByDay.ts +11077 -3062
  24. package/src/preact/mutationsOverTime/__mockData__/byWeek.ts +3883 -6606
  25. package/src/preact/mutationsOverTime/__mockData__/defaultMockData.ts +17624 -2203
  26. package/src/preact/mutationsOverTime/mutations-over-time-grid.tsx +1 -1
  27. package/src/preact/mutationsOverTime/mutations-over-time.tsx +1 -1
  28. package/src/preact/shared/charts/colors.ts +1 -1
  29. package/src/query/queryAggregateData.spec.ts +16 -109
  30. package/src/query/queryAggregateData.ts +2 -12
  31. package/src/query/queryGeneralStatistics.ts +2 -2
  32. package/src/query/queryMutationsOverTime.spec.ts +144 -4
  33. package/src/query/queryMutationsOverTime.ts +17 -1
  34. package/src/web-components/visualization/gs-aggregate.stories.ts +90 -20
  35. package/src/web-components/visualization/gs-aggregate.tsx +20 -0
  36. package/src/web-components/visualization/gs-mutations.stories.ts +62 -4
  37. package/src/web-components/visualization/gs-mutations.tsx +44 -0
  38. package/standalone-bundle/assets/{mutationOverTimeWorker-x1ipPFL0.js.map → mutationOverTimeWorker-DEybsZ5r.js.map} +1 -1
  39. package/standalone-bundle/dashboard-components.js +4136 -3956
  40. package/standalone-bundle/dashboard-components.js.map +1 -1
  41. package/standalone-bundle/style.css +1 -1
@@ -1369,7 +1369,7 @@
1369
1369
  "type": {
1370
1370
  "text": "Meta<Required<AggregateProps>>"
1371
1371
  },
1372
- "default": "{ title: 'Visualization/Aggregate', component: 'gs-aggregate', argTypes: { fields: [{ control: 'object' }], views: { options: ['table'], control: { type: 'check' }, }, width: { control: 'text' }, height: { control: 'text' }, pageSize: { control: 'object' }, initialSortField: { control: 'text' }, initialSortDirection: { options: ['ascending', 'descending'], control: { type: 'radio' }, }, }, parameters: withComponentDocs({ fetchMock: { mocks: [ { matcher: { name: 'aggregatedData', url: AGGREGATED_ENDPOINT, body: { fields: ['division', 'host'], country: 'USA', }, }, response: { status: 200, body: aggregatedData, }, }, ], }, componentDocs: { opensShadowDom: true, expectsChildren: false, codeExample, }, }), tags: ['autodocs'], }"
1372
+ "default": "{ title: 'Visualization/Aggregate', component: 'gs-aggregate', argTypes: { fields: [{ control: 'object' }], views: { options: ['table', 'bar'], control: { type: 'check' }, }, width: { control: 'text' }, height: { control: 'text' }, pageSize: { control: 'object' }, initialSortField: { control: 'text' }, initialSortDirection: { options: ['ascending', 'descending'], control: { type: 'radio' }, }, }, parameters: withComponentDocs({ componentDocs: { opensShadowDom: true, expectsChildren: false, codeExample, }, }), tags: ['autodocs'], }"
1373
1373
  },
1374
1374
  {
1375
1375
  "kind": "variable",
@@ -1377,7 +1377,23 @@
1377
1377
  "type": {
1378
1378
  "text": "StoryObj<Required<AggregateProps>>"
1379
1379
  },
1380
- "default": "{ render: (args) => html` <gs-app lapis=\"${LAPIS_URL}\"> <gs-aggregate .fields=${args.fields} .lapisFilter=${args.lapisFilter} .views=${args.views} .width=${args.width} .height=${args.height} .initialSortField=${args.initialSortField} .initialSortDirection=${args.initialSortDirection} .pageSize=${args.pageSize} ></gs-aggregate> </gs-app> `, args: { fields: ['division', 'host'], views: ['table'], lapisFilter: { country: 'USA', }, width: '100%', height: '700px', initialSortField: 'count', initialSortDirection: 'descending', pageSize: 10, }, }"
1380
+ "default": "{ render: (args) => html` <gs-app lapis=\"${LAPIS_URL}\"> <gs-aggregate .fields=${args.fields} .lapisFilter=${args.lapisFilter} .views=${args.views} .width=${args.width} .height=${args.height} .initialSortField=${args.initialSortField} .initialSortDirection=${args.initialSortDirection} .pageSize=${args.pageSize} .maxNumberOfBars=${args.maxNumberOfBars} ></gs-aggregate> </gs-app> `, parameters: { fetchMock: { mocks: [ { matcher: { name: 'aggregatedData', url: AGGREGATED_ENDPOINT, body: { fields: ['division', 'host'], country: 'USA', }, }, response: { status: 200, body: aggregatedData, }, }, ], }, }, args: { fields: ['division', 'host'], views: ['table', 'bar'], lapisFilter: { country: 'USA', }, width: '100%', height: '700px', initialSortField: 'count', initialSortDirection: 'descending', pageSize: 10, maxNumberOfBars: 10, }, }"
1381
+ },
1382
+ {
1383
+ "kind": "variable",
1384
+ "name": "BarChartWithOneField",
1385
+ "type": {
1386
+ "text": "StoryObj<Required<AggregateProps>>"
1387
+ },
1388
+ "default": "{ ...Table, args: { ...Table.args, fields: ['division'], views: ['bar', 'table'], }, parameters: { fetchMock: { mocks: [ { matcher: { name: 'aggregatedData', url: AGGREGATED_ENDPOINT, body: { fields: ['division'], country: 'USA', }, }, response: { status: 200, body: aggregatedDataWith1Field, }, }, ], }, }, }"
1389
+ },
1390
+ {
1391
+ "kind": "variable",
1392
+ "name": "BarChartWithTwoFields",
1393
+ "type": {
1394
+ "text": "StoryObj<Required<AggregateProps>>"
1395
+ },
1396
+ "default": "{ ...Table, args: { ...Table.args, fields: ['division', 'nextstrainClade'], lapisFilter: { country: 'Germany', dateTo: '2022-02-01', }, views: ['bar', 'table'], }, parameters: { fetchMock: { mocks: [ { matcher: { name: 'aggregatedData', url: AGGREGATED_ENDPOINT, body: { fields: ['division', 'nextstrainClade'], country: 'Germany', dateTo: '2022-02-01', }, }, response: { status: 200, body: aggregatedDataWith2Fields, }, }, ], }, }, }"
1381
1397
  }
1382
1398
  ],
1383
1399
  "exports": [
@@ -1396,6 +1412,22 @@
1396
1412
  "name": "Table",
1397
1413
  "module": "src/web-components/visualization/gs-aggregate.stories.ts"
1398
1414
  }
1415
+ },
1416
+ {
1417
+ "kind": "js",
1418
+ "name": "BarChartWithOneField",
1419
+ "declaration": {
1420
+ "name": "BarChartWithOneField",
1421
+ "module": "src/web-components/visualization/gs-aggregate.stories.ts"
1422
+ }
1423
+ },
1424
+ {
1425
+ "kind": "js",
1426
+ "name": "BarChartWithTwoFields",
1427
+ "declaration": {
1428
+ "name": "BarChartWithTwoFields",
1429
+ "module": "src/web-components/visualization/gs-aggregate.stories.ts"
1430
+ }
1399
1431
  }
1400
1432
  ]
1401
1433
  },
@@ -1405,7 +1437,7 @@
1405
1437
  "declarations": [
1406
1438
  {
1407
1439
  "kind": "class",
1408
- "description": "## Context\n\nThis component displays aggregated data in a table, which can provide an overview of the underlying data.\n\nIt expects a list of `fields` to aggregate by and a `filter` to apply to the data.\n\n## Views\n\n### Table View\n\nIn the table view, the data is presented in a table format where each field is a column,\nalong with the aggregated value and its proportion.\nThe proportion represents the ratio of the aggregated value to the total count of the data\n(considering the applied filter).",
1440
+ "description": "## Context\n\nThis component displays aggregated data in a table, which can provide an overview of the underlying data.\n\nIt expects a list of `fields` to aggregate by and a `filter` to apply to the data.\n\n## Views\n\n### Table View\n\nIn the table view, the data is presented in a table format where each field is a column,\nalong with the aggregated value and its proportion.\nThe proportion represents the ratio of the aggregated value to the total count of the data\n(considering the applied filter).\n\n### Bar Chart View\n\nIn the bar chart view, the data is presented in vertical bars.\nThe bar chart is supported when `fields` contains one or two entries.\nThe first field will be used as the y-axis.\nIf a second field is provided, it's values will be stacked along the x-axis for each key on the y-axis.\n\nThe chart shows the bars with the highest aggregated `count`.\nThe number of bars can be adjusted with the `maxNumberOfBars` property.",
1409
1441
  "name": "AggregateComponent",
1410
1442
  "members": [
1411
1443
  {
@@ -1487,6 +1519,16 @@
1487
1519
  "default": "false",
1488
1520
  "description": "The maximum number of rows to display in the table view.\nSet to `false` to disable pagination. Set to `true` to enable pagination with a default limit (10).",
1489
1521
  "attribute": "pageSize"
1522
+ },
1523
+ {
1524
+ "kind": "field",
1525
+ "name": "maxNumberOfBars",
1526
+ "type": {
1527
+ "text": "number"
1528
+ },
1529
+ "default": "20",
1530
+ "description": "The maximum number of bars to display in the bar chart view.",
1531
+ "attribute": "maxNumberOfBars"
1490
1532
  }
1491
1533
  ],
1492
1534
  "attributes": [
@@ -1561,6 +1603,15 @@
1561
1603
  "default": "false",
1562
1604
  "description": "The maximum number of rows to display in the table view.\nSet to `false` to disable pagination. Set to `true` to enable pagination with a default limit (10).",
1563
1605
  "fieldName": "pageSize"
1606
+ },
1607
+ {
1608
+ "name": "maxNumberOfBars",
1609
+ "type": {
1610
+ "text": "number"
1611
+ },
1612
+ "default": "20",
1613
+ "description": "The maximum number of bars to display in the bar chart view.",
1614
+ "fieldName": "maxNumberOfBars"
1564
1615
  }
1565
1616
  ],
1566
1617
  "superclass": {
@@ -2069,7 +2120,7 @@
2069
2120
  "type": {
2070
2121
  "text": "Meta<Required<MutationsProps>>"
2071
2122
  },
2072
- "default": "{ title: 'Visualization/Mutations', component: 'gs-mutations', argTypes: { lapisFilter: { control: 'object' }, sequenceType: { options: ['nucleotide', 'amino acid'], control: { type: 'radio' }, }, views: { options: ['table', 'grid', 'insertions'], control: { type: 'check' }, }, width: { control: 'text' }, height: { control: 'text' }, pageSize: { control: 'object' }, }, args: { lapisFilter: { country: 'Switzerland', pangoLineage: 'B.1.1.7', dateTo: '2022-01-01' }, sequenceType: 'nucleotide', views: ['grid', 'table', 'insertions'], width: '100%', height: '700px', pageSize: 10, }, parameters: withComponentDocs({ componentDocs: { opensShadowDom: true, expectsChildren: false, codeExample, }, }), tags: ['autodocs'], }"
2123
+ "default": "{ title: 'Visualization/Mutations', component: 'gs-mutations', argTypes: { lapisFilter: { control: 'object' }, baselineLapisFilter: { control: 'object' }, sequenceType: { options: ['nucleotide', 'amino acid'], control: { type: 'radio' }, }, views: { options: ['table', 'grid', 'insertions'], control: { type: 'check' }, }, width: { control: 'text' }, height: { control: 'text' }, pageSize: { control: 'object' }, }, args: { lapisFilter: { country: 'Switzerland', pangoLineage: 'B.1.1.7', dateTo: '2022-01-01' }, baselineLapisFilter: { country: 'Switzerland', dateTo: '2022-01-01' }, sequenceType: 'nucleotide', views: ['grid', 'table', 'insertions'], width: '100%', height: '700px', pageSize: 10, }, parameters: withComponentDocs({ componentDocs: { opensShadowDom: true, expectsChildren: false, codeExample, }, }), tags: ['autodocs'], }"
2073
2124
  },
2074
2125
  {
2075
2126
  "kind": "variable",
@@ -2077,7 +2128,7 @@
2077
2128
  "type": {
2078
2129
  "text": "StoryObj<Required<MutationsProps>>"
2079
2130
  },
2080
- "default": "{ ...Template, parameters: { fetchMock: { mocks: [ { matcher: { name: 'nucleotideMutations', url: NUCLEOTIDE_MUTATIONS_ENDPOINT, body: { country: 'Switzerland', pangoLineage: 'B.1.1.7', dateTo: '2022-01-01', minProportion: 0, }, }, response: { status: 200, body: nucleotideMutations, }, }, { matcher: { name: 'nucleotideInsertions', url: NUCLEOTIDE_INSERTIONS_ENDPOINT, body: { country: 'Switzerland', pangoLineage: 'B.1.1.7', dateTo: '2022-01-01' }, }, response: { status: 200, body: nucleotideInsertions, }, }, ], }, }, }"
2131
+ "default": "{ ...Template, parameters: { fetchMock: { mocks: [ { matcher: { name: 'nucleotideMutations', url: NUCLEOTIDE_MUTATIONS_ENDPOINT, body: { country: 'Switzerland', pangoLineage: 'B.1.1.7', dateTo: '2022-01-01', minProportion: 0, }, }, response: { status: 200, body: nucleotideMutations, }, }, { matcher: { name: 'baselineNucleotideMutations', url: NUCLEOTIDE_MUTATIONS_ENDPOINT, body: { country: 'Switzerland', dateTo: '2022-01-01', minProportion: 0, }, }, response: { status: 200, body: baselineNucleotideMutations, }, }, { matcher: { name: 'overallVariantCount', url: AGGREGATED_ENDPOINT, body: { country: 'Switzerland', pangoLineage: 'B.1.1.7', dateTo: '2022-01-01', fields: [], }, }, response: { status: 200, body: overallVariantCount, }, }, { matcher: { name: 'nucleotideInsertions', url: NUCLEOTIDE_INSERTIONS_ENDPOINT, body: { country: 'Switzerland', pangoLineage: 'B.1.1.7', dateTo: '2022-01-01' }, }, response: { status: 200, body: nucleotideInsertions, }, }, ], }, }, }"
2081
2132
  },
2082
2133
  {
2083
2134
  "kind": "variable",
@@ -2087,6 +2138,14 @@
2087
2138
  },
2088
2139
  "default": "{ ...Default, play: async ({ canvasElement }) => { const canvas = await withinShadowRoot(canvasElement, 'gs-mutations'); await waitFor(() => expect(canvas.getByRole('button', { name: 'Table' })).toBeInTheDocument()); await fireEvent.click(canvas.getByRole('button', { name: 'Table' })); }, }"
2089
2140
  },
2141
+ {
2142
+ "kind": "variable",
2143
+ "name": "OnTableTabWithoutJaccardSimilarity",
2144
+ "type": {
2145
+ "text": "StoryObj<Required<MutationsProps>>"
2146
+ },
2147
+ "default": "{ ...Default, args: { ...Default.args, baselineLapisFilter: undefined, }, play: async ({ canvasElement }) => { const canvas = await withinShadowRoot(canvasElement, 'gs-mutations'); await waitFor(() => expect(canvas.getByRole('button', { name: 'Table' })).toBeInTheDocument()); await fireEvent.click(canvas.getByRole('button', { name: 'Table' })); }, }"
2148
+ },
2090
2149
  {
2091
2150
  "kind": "variable",
2092
2151
  "name": "OnInsertionsTab",
@@ -2121,6 +2180,14 @@
2121
2180
  "module": "src/web-components/visualization/gs-mutations.stories.ts"
2122
2181
  }
2123
2182
  },
2183
+ {
2184
+ "kind": "js",
2185
+ "name": "OnTableTabWithoutJaccardSimilarity",
2186
+ "declaration": {
2187
+ "name": "OnTableTabWithoutJaccardSimilarity",
2188
+ "module": "src/web-components/visualization/gs-mutations.stories.ts"
2189
+ }
2190
+ },
2124
2191
  {
2125
2192
  "kind": "js",
2126
2193
  "name": "OnInsertionsTab",
@@ -2137,7 +2204,7 @@
2137
2204
  "declarations": [
2138
2205
  {
2139
2206
  "kind": "class",
2140
- "description": "## Context\n\nThis component displays mutations (substitutions, deletions and insertions) for a dataset selected by a LAPIS filter.\n\n## Views\n\n### Table View\n\nThe table view shows all substitutions and deletions for the dataset.\nIt shows the type (substitution or deletion), the total count of the mutation\nand the proportion of the mutation in the dataset.\nThe proportion is relative to the total number of sequences matching\nthe specified sequence filters with non-ambiguous reads at that position.\n\nThe proportion interval filter can be used to filter the displayed mutations on client side.\n\n### Grid View\n\nThe grid view shows the proportion of each sequence symbol (nucleotide or amino acid) for each position that has a mutation.\nOnly positions with at least one mutation in the selected proportion interval are shown.\n\n### Insertions View\n\nThe insertions view shows the count of all insertions for the dataset.",
2207
+ "description": "## Context\n\nThis component displays mutations (substitutions, deletions and insertions) for a dataset selected by a LAPIS filter.\n\n## Views\n\n### Table View\n\nThe table view shows all substitutions and deletions for the dataset.\nIt shows the type (substitution or deletion), the total count of the mutation\nand the proportion of the mutation in the dataset.\nThe proportion is relative to the total number of sequences matching\nthe specified sequence filters with non-ambiguous reads at that position.\n\nThe proportion interval filter can be used to filter the displayed mutations on client side.\n\n#### Jaccard Similarity\n\nIf the `baselineLapisFilter` attribute is set,\nthe [Jaccard similarity](https://en.wikipedia.org/wiki/Jaccard_index) is computed for each mutation.\nIt is computed as `variantWithMutationCount / (variantCount + mutationCount - variantWithMutationCount)`,\n- `variantCount` is the number of sequences of the variant (i.e. the number of sequences that match the `lapisFilter`),\n- `mutationCount` is the number of sequences with the mutation\n (i.e. the number of sequences matching the `baselineLapisFilter` that have the mutation),\n- `variantWithMutationCount` is the number of sequences that belong to the variant and have the mutation\n (i.e. the `count` value that is shown in the table).\n\nTypically, this is useful when you query mutations of a certain \"variant\"\n(i.e. a certain lineage or a certain set of mutations).\nThen the `baselineLapisFilter` should be the `lapisFilter` but without the lineage or mutations.\n\nFor example:\nYou are interested in a certain lineage in a certain country: `lapisFilter={country: 'Switzerland', linage: 'XY.1.2.3'}`.\nThen the \"baseline\" should be the same filter but without the lineage: `baselineLapisFilter={country: 'Switzerland'}`.\n\nComputing the Jaccard similarity is not always meaningful, because you might not have a \"variant\"\n(e.g. when you only query for a certain country).\nIn this case you can simply omit the `baselineLapisFilter`.\n\n### Grid View\n\nThe grid view shows the proportion of each sequence symbol (nucleotide or amino acid) for each position that has a mutation.\nOnly positions with at least one mutation in the selected proportion interval are shown.\n\n### Insertions View\n\nThe insertions view shows the count of all insertions for the dataset.",
2141
2208
  "name": "MutationsComponent",
2142
2209
  "members": [
2143
2210
  {
@@ -2150,6 +2217,16 @@
2150
2217
  "description": "LAPIS filter to select the displayed data. If not provided, all data is displayed.",
2151
2218
  "attribute": "lapisFilter"
2152
2219
  },
2220
+ {
2221
+ "kind": "field",
2222
+ "name": "baselineLapisFilter",
2223
+ "type": {
2224
+ "text": "(Record<string, string | string[] | number | null | boolean | undefined> & {\n nucleotideMutations?: string[];\n aminoAcidMutations?: string[];\n nucleotideInsertions?: string[];\n aminoAcidInsertions?: string[];\n })\n | undefined"
2225
+ },
2226
+ "default": "undefined",
2227
+ "description": "LAPIS filter to select the mutation counts that are used to compute the Jaccard similarity.\nIf not provided, the Jaccard similarity is not computed.\nFor details, see the [Jaccard Similarity](#jaccard-similarity) section in the component description.",
2228
+ "attribute": "baselineLapisFilter"
2229
+ },
2153
2230
  {
2154
2231
  "kind": "field",
2155
2232
  "name": "sequenceType",
@@ -2211,6 +2288,15 @@
2211
2288
  "description": "LAPIS filter to select the displayed data. If not provided, all data is displayed.",
2212
2289
  "fieldName": "lapisFilter"
2213
2290
  },
2291
+ {
2292
+ "name": "baselineLapisFilter",
2293
+ "type": {
2294
+ "text": "(Record<string, string | string[] | number | null | boolean | undefined> & {\n nucleotideMutations?: string[];\n aminoAcidMutations?: string[];\n nucleotideInsertions?: string[];\n aminoAcidInsertions?: string[];\n })\n | undefined"
2295
+ },
2296
+ "default": "undefined",
2297
+ "description": "LAPIS filter to select the mutation counts that are used to compute the Jaccard similarity.\nIf not provided, the Jaccard similarity is not computed.\nFor details, see the [Jaccard Similarity](#jaccard-similarity) section in the component description.",
2298
+ "fieldName": "baselineLapisFilter"
2299
+ },
2214
2300
  {
2215
2301
  "name": "sequenceType",
2216
2302
  "type": {