@genspectrum/dashboard-components 0.11.5 → 0.11.6
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/custom-elements.json +54 -3
- package/dist/components.d.ts +19 -5
- package/dist/components.js +172 -24
- package/dist/components.js.map +1 -1
- package/dist/style.css +3 -0
- package/dist/util.d.ts +11 -8
- package/package.json +1 -1
- package/src/preact/aggregatedData/__mockData__/aggregatedWith1Field.json +399 -0
- package/src/preact/aggregatedData/__mockData__/aggregatedWith2Fields.json +1771 -0
- package/src/preact/aggregatedData/aggregate-bar-chart.tsx +177 -0
- package/src/preact/aggregatedData/aggregate-table.tsx +24 -2
- package/src/preact/aggregatedData/aggregate.stories.tsx +61 -2
- package/src/preact/aggregatedData/aggregate.tsx +18 -6
- package/src/preact/mutationsOverTime/mutations-over-time-grid.tsx +1 -1
- package/src/preact/shared/charts/colors.ts +1 -1
- package/src/query/queryAggregateData.spec.ts +16 -109
- package/src/query/queryAggregateData.ts +2 -12
- package/src/query/queryGeneralStatistics.ts +2 -2
- package/src/web-components/visualization/gs-aggregate.stories.ts +90 -20
- package/src/web-components/visualization/gs-aggregate.tsx +20 -0
- package/standalone-bundle/dashboard-components.js +4336 -4207
- package/standalone-bundle/dashboard-components.js.map +1 -1
- package/standalone-bundle/style.css +1 -1
package/custom-elements.json
CHANGED
|
@@ -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({
|
|
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": {
|
package/dist/components.d.ts
CHANGED
|
@@ -22,6 +22,16 @@ import { TemplateResult } from 'lit-html';
|
|
|
22
22
|
* along with the aggregated value and its proportion.
|
|
23
23
|
* The proportion represents the ratio of the aggregated value to the total count of the data
|
|
24
24
|
* (considering the applied filter).
|
|
25
|
+
*
|
|
26
|
+
* ### Bar Chart View
|
|
27
|
+
*
|
|
28
|
+
* In the bar chart view, the data is presented in vertical bars.
|
|
29
|
+
* The bar chart is supported when `fields` contains one or two entries.
|
|
30
|
+
* The first field will be used as the y-axis.
|
|
31
|
+
* If a second field is provided, it's values will be stacked along the x-axis for each key on the y-axis.
|
|
32
|
+
*
|
|
33
|
+
* The chart shows the bars with the highest aggregated `count`.
|
|
34
|
+
* The number of bars can be adjusted with the `maxNumberOfBars` property.
|
|
25
35
|
*/
|
|
26
36
|
export declare class AggregateComponent extends PreactLitAdapterWithGridJsStyles {
|
|
27
37
|
/**
|
|
@@ -72,12 +82,16 @@ export declare class AggregateComponent extends PreactLitAdapterWithGridJsStyles
|
|
|
72
82
|
* Set to `false` to disable pagination. Set to `true` to enable pagination with a default limit (10).
|
|
73
83
|
*/
|
|
74
84
|
pageSize: boolean | number;
|
|
85
|
+
/**
|
|
86
|
+
* The maximum number of bars to display in the bar chart view.
|
|
87
|
+
*/
|
|
88
|
+
maxNumberOfBars: number;
|
|
75
89
|
render(): JSX_2.Element;
|
|
76
90
|
}
|
|
77
91
|
|
|
78
92
|
declare type AggregateView = default_2.infer<typeof aggregateViewSchema>;
|
|
79
93
|
|
|
80
|
-
declare const aggregateViewSchema: default_2.ZodLiteral<"table">;
|
|
94
|
+
declare const aggregateViewSchema: default_2.ZodUnion<[default_2.ZodLiteral<"table">, default_2.ZodLiteral<"bar">]>;
|
|
81
95
|
|
|
82
96
|
/**
|
|
83
97
|
* ## Context
|
|
@@ -1301,7 +1315,7 @@ declare global {
|
|
|
1301
1315
|
|
|
1302
1316
|
declare global {
|
|
1303
1317
|
interface HTMLElementTagNameMap {
|
|
1304
|
-
'gs-
|
|
1318
|
+
'gs-number-sequences-over-time': NumberSequencesOverTimeComponent;
|
|
1305
1319
|
}
|
|
1306
1320
|
}
|
|
1307
1321
|
|
|
@@ -1309,7 +1323,7 @@ declare global {
|
|
|
1309
1323
|
declare global {
|
|
1310
1324
|
namespace JSX {
|
|
1311
1325
|
interface IntrinsicElements {
|
|
1312
|
-
'gs-
|
|
1326
|
+
'gs-number-sequences-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1313
1327
|
}
|
|
1314
1328
|
}
|
|
1315
1329
|
}
|
|
@@ -1317,7 +1331,7 @@ declare global {
|
|
|
1317
1331
|
|
|
1318
1332
|
declare global {
|
|
1319
1333
|
interface HTMLElementTagNameMap {
|
|
1320
|
-
'gs-
|
|
1334
|
+
'gs-mutations-over-time': MutationsOverTimeComponent;
|
|
1321
1335
|
}
|
|
1322
1336
|
}
|
|
1323
1337
|
|
|
@@ -1325,7 +1339,7 @@ declare global {
|
|
|
1325
1339
|
declare global {
|
|
1326
1340
|
namespace JSX {
|
|
1327
1341
|
interface IntrinsicElements {
|
|
1328
|
-
'gs-
|
|
1342
|
+
'gs-mutations-over-time': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>;
|
|
1329
1343
|
}
|
|
1330
1344
|
}
|
|
1331
1345
|
}
|
package/dist/components.js
CHANGED
|
@@ -4,7 +4,7 @@ import { LitElement, html, unsafeCSS } from "lit";
|
|
|
4
4
|
import z$1 from "zod";
|
|
5
5
|
import { options, createContext as createContext$1, Fragment, render } from "preact";
|
|
6
6
|
import { Grid } from "gridjs";
|
|
7
|
-
import { Chart, registerables, Scale } from "chart.js";
|
|
7
|
+
import { Chart, registerables, Scale, BarController } from "chart.js";
|
|
8
8
|
import { VennDiagramController, ArcSlice, extractSets } from "chartjs-chart-venn";
|
|
9
9
|
import { v as views, n as namedLapisFilterSchema, s as sequenceTypeSchema, l as lapisFilterSchema, t as temporalGranularitySchema, a as dateRangeOptionSchema, b as toYYYYMMDD, D as DateRangeOptionChangedEvent, m as mutationsFilterSchema } from "./dateRangeOption-Bh2p78z0.js";
|
|
10
10
|
import { autoUpdate, computePosition, offset, shift, flip } from "@floating-ui/dom";
|
|
@@ -4742,6 +4742,9 @@ input.tab:checked + .tab-content,
|
|
|
4742
4742
|
.static {
|
|
4743
4743
|
position: static;
|
|
4744
4744
|
}
|
|
4745
|
+
.fixed {
|
|
4746
|
+
position: fixed;
|
|
4747
|
+
}
|
|
4745
4748
|
.absolute {
|
|
4746
4749
|
position: absolute;
|
|
4747
4750
|
}
|
|
@@ -5935,7 +5938,7 @@ const ColorsRGB = {
|
|
|
5935
5938
|
const singleGraphColorRGBAById = (id, alpha = 1) => {
|
|
5936
5939
|
const keys = Object.keys(ColorsRGB);
|
|
5937
5940
|
const key = keys[id % keys.length];
|
|
5938
|
-
return
|
|
5941
|
+
return singleGraphColorRGBByName(key, alpha);
|
|
5939
5942
|
};
|
|
5940
5943
|
const singleGraphColorRGBByName = (name, alpha = 1) => {
|
|
5941
5944
|
return `rgba(${ColorsRGB[name].join(",")},${alpha})`;
|
|
@@ -8244,15 +8247,9 @@ const compareAscending = (a2, b3) => {
|
|
|
8244
8247
|
const strB = b3 != null ? String(b3) : "";
|
|
8245
8248
|
return strA.localeCompare(strB);
|
|
8246
8249
|
};
|
|
8247
|
-
async function queryAggregateData(lapisFilter, fields, lapis,
|
|
8248
|
-
const validSortFields = ["count", "proportion", ...fields];
|
|
8249
|
-
if (!validSortFields.includes(initialSort.field)) {
|
|
8250
|
-
throw new Error(`InitialSort field not in fields. Valid fields are: ${validSortFields.join(", ")}`);
|
|
8251
|
-
}
|
|
8250
|
+
async function queryAggregateData(lapisFilter, fields, lapis, signal) {
|
|
8252
8251
|
const fetchData = new FetchAggregatedOperator(lapisFilter, fields);
|
|
8253
|
-
const sortData = new SortOperator(fetchData, (a2, b3) =>
|
|
8254
|
-
return initialSort.direction === "ascending" ? compareAscending(a2[initialSort.field], b3[initialSort.field]) : compareAscending(b3[initialSort.field], a2[initialSort.field]);
|
|
8255
|
-
});
|
|
8252
|
+
const sortData = new SortOperator(fetchData, (a2, b3) => compareAscending(b3.count, a2.count));
|
|
8256
8253
|
const data = (await sortData.evaluate(lapis, signal)).content;
|
|
8257
8254
|
const total = data.reduce((acc, row) => acc + row.count, 0);
|
|
8258
8255
|
return data.map(
|
|
@@ -8262,7 +8259,13 @@ async function queryAggregateData(lapisFilter, fields, lapis, initialSort = { fi
|
|
|
8262
8259
|
})
|
|
8263
8260
|
);
|
|
8264
8261
|
}
|
|
8265
|
-
const AggregateTable = ({
|
|
8262
|
+
const AggregateTable = ({
|
|
8263
|
+
data,
|
|
8264
|
+
fields,
|
|
8265
|
+
pageSize,
|
|
8266
|
+
initialSortField,
|
|
8267
|
+
initialSortDirection
|
|
8268
|
+
}) => {
|
|
8266
8269
|
const headers = [
|
|
8267
8270
|
...fields.map((field) => {
|
|
8268
8271
|
return {
|
|
@@ -8282,9 +8285,137 @@ const AggregateTable = ({ data, fields, pageSize }) => {
|
|
|
8282
8285
|
formatter: (cell) => formatProportion(cell)
|
|
8283
8286
|
}
|
|
8284
8287
|
];
|
|
8285
|
-
|
|
8288
|
+
const sortedData = T(() => {
|
|
8289
|
+
const validSortFields = ["count", "proportion", ...fields];
|
|
8290
|
+
if (!validSortFields.includes(initialSortField)) {
|
|
8291
|
+
throw new Error(`InitialSort field not in fields. Valid fields are: ${validSortFields.join(", ")}`);
|
|
8292
|
+
}
|
|
8293
|
+
return data.sort(
|
|
8294
|
+
(a2, b3) => initialSortDirection === "ascending" ? compareAscending(a2[initialSortField], b3[initialSortField]) : compareAscending(b3[initialSortField], a2[initialSortField])
|
|
8295
|
+
);
|
|
8296
|
+
}, [data, initialSortField, initialSortDirection, fields]);
|
|
8297
|
+
return /* @__PURE__ */ u$1(Table, { data: sortedData, columns: headers, pageSize });
|
|
8298
|
+
};
|
|
8299
|
+
Chart.register(...registerables, BarController);
|
|
8300
|
+
const AggregateBarChart = ({ data, fields, maxNumberOfBars }) => {
|
|
8301
|
+
if (data.length === 0) {
|
|
8302
|
+
return /* @__PURE__ */ u$1(NoDataDisplay, {});
|
|
8303
|
+
}
|
|
8304
|
+
if (fields.length === 0) {
|
|
8305
|
+
throw new UserFacingError(
|
|
8306
|
+
"No fields given",
|
|
8307
|
+
'Cannot display a bar chart when the "fields" attribute of this component is empty, i.e. there are no fields given that the data should be stratified by. This must be fixed by the administrator of this page.'
|
|
8308
|
+
);
|
|
8309
|
+
}
|
|
8310
|
+
if (fields.length > 2) {
|
|
8311
|
+
throw new UserFacingError(
|
|
8312
|
+
"Too many fields given",
|
|
8313
|
+
`Cannot display a bar chart when the "fields" attribute of this component contains more than two values. Got the fields: ${fields.join(", ")}. This must be fixed by the administrator of this page.`
|
|
8314
|
+
);
|
|
8315
|
+
}
|
|
8316
|
+
return /* @__PURE__ */ u$1(AggregateBarChartInner, { data, fields, maxNumberOfBars });
|
|
8317
|
+
};
|
|
8318
|
+
const AggregateBarChartInner = ({ data, fields, maxNumberOfBars }) => {
|
|
8319
|
+
const config = T(() => {
|
|
8320
|
+
const { datasets: datasets2, countsOfEachBar } = getDatasets$2(fields, maxNumberOfBars, data);
|
|
8321
|
+
return {
|
|
8322
|
+
type: "bar",
|
|
8323
|
+
data: {
|
|
8324
|
+
datasets: datasets2
|
|
8325
|
+
},
|
|
8326
|
+
options: {
|
|
8327
|
+
maintainAspectRatio: false,
|
|
8328
|
+
animation: false,
|
|
8329
|
+
indexAxis: "y",
|
|
8330
|
+
scales: {
|
|
8331
|
+
x: {
|
|
8332
|
+
stacked: true
|
|
8333
|
+
},
|
|
8334
|
+
y: {
|
|
8335
|
+
stacked: true
|
|
8336
|
+
}
|
|
8337
|
+
},
|
|
8338
|
+
plugins: {
|
|
8339
|
+
legend: {
|
|
8340
|
+
display: false
|
|
8341
|
+
},
|
|
8342
|
+
tooltip: {
|
|
8343
|
+
mode: "y",
|
|
8344
|
+
callbacks: {
|
|
8345
|
+
afterTitle: countsOfEachBar === void 0 ? void 0 : (tooltipItems) => {
|
|
8346
|
+
return `Total: ${countsOfEachBar.get(tooltipItems[0].label)}`;
|
|
8347
|
+
},
|
|
8348
|
+
label: (context) => {
|
|
8349
|
+
const { x: x2, proportion } = context.dataset.data[context.dataIndex];
|
|
8350
|
+
return fields.length === 1 ? `${x2} (${formatProportion(proportion)})` : `${context.dataset.label}: ${x2} (${formatProportion(proportion)})`;
|
|
8351
|
+
}
|
|
8352
|
+
}
|
|
8353
|
+
}
|
|
8354
|
+
}
|
|
8355
|
+
}
|
|
8356
|
+
};
|
|
8357
|
+
}, [data, fields, maxNumberOfBars]);
|
|
8358
|
+
return /* @__PURE__ */ u$1(GsChart, { configuration: config });
|
|
8286
8359
|
};
|
|
8287
|
-
|
|
8360
|
+
function getDatasets$2(fields, maxNumberOfBars, data) {
|
|
8361
|
+
var _a;
|
|
8362
|
+
const sortedData = data.sort((a2, b3) => b3.count - a2.count);
|
|
8363
|
+
if (fields.length === 1) {
|
|
8364
|
+
return {
|
|
8365
|
+
datasets: [
|
|
8366
|
+
{
|
|
8367
|
+
borderWidth: 1,
|
|
8368
|
+
backgroundColor: singleGraphColorRGBAById(0, 0.3),
|
|
8369
|
+
borderColor: singleGraphColorRGBAById(0),
|
|
8370
|
+
data: sortedData.slice(0, maxNumberOfBars).map((row) => ({
|
|
8371
|
+
y: row[fields[0]],
|
|
8372
|
+
x: row.count,
|
|
8373
|
+
proportion: row.proportion
|
|
8374
|
+
}))
|
|
8375
|
+
}
|
|
8376
|
+
]
|
|
8377
|
+
};
|
|
8378
|
+
}
|
|
8379
|
+
const map = /* @__PURE__ */ new Map();
|
|
8380
|
+
const countsOfEachBar = /* @__PURE__ */ new Map();
|
|
8381
|
+
for (const row of sortedData) {
|
|
8382
|
+
const yValue = row[fields[0]];
|
|
8383
|
+
const secondaryValue = row[fields[1]];
|
|
8384
|
+
if (yValue === null || secondaryValue === null) {
|
|
8385
|
+
continue;
|
|
8386
|
+
}
|
|
8387
|
+
const yAxisKey = String(yValue);
|
|
8388
|
+
const secondaryKey = String(secondaryValue);
|
|
8389
|
+
if (!map.has(secondaryKey)) {
|
|
8390
|
+
map.set(secondaryKey, []);
|
|
8391
|
+
}
|
|
8392
|
+
(_a = map.get(secondaryKey)) == null ? void 0 : _a.push({
|
|
8393
|
+
y: yAxisKey,
|
|
8394
|
+
x: row.count,
|
|
8395
|
+
proportion: row.proportion
|
|
8396
|
+
});
|
|
8397
|
+
countsOfEachBar.set(yAxisKey, (countsOfEachBar.get(yAxisKey) ?? 0) + row.count);
|
|
8398
|
+
}
|
|
8399
|
+
const datasets2 = Array.from(map.entries()).map(sortAndTruncateYAxisKeys(countsOfEachBar, maxNumberOfBars)).map(([key, value], index) => ({
|
|
8400
|
+
borderWidth: 1,
|
|
8401
|
+
backgroundColor: singleGraphColorRGBAById(index, 0.3),
|
|
8402
|
+
borderColor: singleGraphColorRGBAById(index),
|
|
8403
|
+
label: key,
|
|
8404
|
+
data: value
|
|
8405
|
+
}));
|
|
8406
|
+
return { datasets: datasets2, countsOfEachBar };
|
|
8407
|
+
}
|
|
8408
|
+
function sortAndTruncateYAxisKeys(countsOfEachBar, maxNumberOfBars) {
|
|
8409
|
+
const yAxisKeysToConsider = new Set(
|
|
8410
|
+
Array.from(countsOfEachBar.entries()).sort((a2, b3) => b3[1] - a2[1]).slice(0, maxNumberOfBars).map(([key]) => key)
|
|
8411
|
+
);
|
|
8412
|
+
return ([key, value]) => {
|
|
8413
|
+
const sortedValues = value.sort((a2, b3) => (countsOfEachBar.get(b3.y) ?? 0) - (countsOfEachBar.get(a2.y) ?? 0));
|
|
8414
|
+
const valuesWithLargestBars = sortedValues.slice(0, maxNumberOfBars).filter((v2) => yAxisKeysToConsider.has(v2.y));
|
|
8415
|
+
return [key, valuesWithLargestBars];
|
|
8416
|
+
};
|
|
8417
|
+
}
|
|
8418
|
+
const aggregateViewSchema = z$1.union([z$1.literal(views.table), z$1.literal(views.bar)]);
|
|
8288
8419
|
const aggregatePropsSchema = z$1.object({
|
|
8289
8420
|
lapisFilter: lapisFilterSchema,
|
|
8290
8421
|
fields: z$1.array(z$1.string().min(1)),
|
|
@@ -8293,7 +8424,8 @@ const aggregatePropsSchema = z$1.object({
|
|
|
8293
8424
|
initialSortDirection: z$1.union([z$1.literal("ascending"), z$1.literal("descending")]),
|
|
8294
8425
|
pageSize: z$1.union([z$1.boolean(), z$1.number()]),
|
|
8295
8426
|
width: z$1.string(),
|
|
8296
|
-
height: z$1.string()
|
|
8427
|
+
height: z$1.string(),
|
|
8428
|
+
maxNumberOfBars: z$1.number()
|
|
8297
8429
|
});
|
|
8298
8430
|
const Aggregate = (componentProps) => {
|
|
8299
8431
|
const { width, height } = componentProps;
|
|
@@ -8304,10 +8436,7 @@ const AggregateInner = (componentProps) => {
|
|
|
8304
8436
|
const { fields, lapisFilter, initialSortField, initialSortDirection } = componentProps;
|
|
8305
8437
|
const lapis = x(LapisUrlContext);
|
|
8306
8438
|
const { data, error, isLoading } = useQuery(async () => {
|
|
8307
|
-
return queryAggregateData(lapisFilter, fields, lapis
|
|
8308
|
-
field: initialSortField,
|
|
8309
|
-
direction: initialSortDirection
|
|
8310
|
-
});
|
|
8439
|
+
return queryAggregateData(lapisFilter, fields, lapis);
|
|
8311
8440
|
}, [lapisFilter, fields, lapis, initialSortField, initialSortDirection]);
|
|
8312
8441
|
if (isLoading) {
|
|
8313
8442
|
return /* @__PURE__ */ u$1(LoadingDisplay, {});
|
|
@@ -8323,7 +8452,7 @@ const AggregateInner = (componentProps) => {
|
|
|
8323
8452
|
const AggregatedDataTabs = ({ data, originalComponentProps }) => {
|
|
8324
8453
|
const getTab = (view) => {
|
|
8325
8454
|
switch (view) {
|
|
8326
|
-
case
|
|
8455
|
+
case views.table:
|
|
8327
8456
|
return {
|
|
8328
8457
|
title: "Table",
|
|
8329
8458
|
content: /* @__PURE__ */ u$1(
|
|
@@ -8331,7 +8460,21 @@ const AggregatedDataTabs = ({ data, originalComponentProps }) => {
|
|
|
8331
8460
|
{
|
|
8332
8461
|
data,
|
|
8333
8462
|
fields: originalComponentProps.fields,
|
|
8334
|
-
pageSize: originalComponentProps.pageSize
|
|
8463
|
+
pageSize: originalComponentProps.pageSize,
|
|
8464
|
+
initialSortField: originalComponentProps.initialSortField,
|
|
8465
|
+
initialSortDirection: originalComponentProps.initialSortDirection
|
|
8466
|
+
}
|
|
8467
|
+
)
|
|
8468
|
+
};
|
|
8469
|
+
case views.bar:
|
|
8470
|
+
return {
|
|
8471
|
+
title: "Bar",
|
|
8472
|
+
content: /* @__PURE__ */ u$1(
|
|
8473
|
+
AggregateBarChart,
|
|
8474
|
+
{
|
|
8475
|
+
data,
|
|
8476
|
+
fields: originalComponentProps.fields,
|
|
8477
|
+
maxNumberOfBars: originalComponentProps.maxNumberOfBars
|
|
8335
8478
|
}
|
|
8336
8479
|
)
|
|
8337
8480
|
};
|
|
@@ -8381,6 +8524,7 @@ let AggregateComponent = class extends PreactLitAdapterWithGridJsStyles {
|
|
|
8381
8524
|
this.initialSortField = "count";
|
|
8382
8525
|
this.initialSortDirection = "descending";
|
|
8383
8526
|
this.pageSize = false;
|
|
8527
|
+
this.maxNumberOfBars = 20;
|
|
8384
8528
|
}
|
|
8385
8529
|
render() {
|
|
8386
8530
|
return /* @__PURE__ */ u$1(
|
|
@@ -8393,7 +8537,8 @@ let AggregateComponent = class extends PreactLitAdapterWithGridJsStyles {
|
|
|
8393
8537
|
height: this.height,
|
|
8394
8538
|
initialSortField: this.initialSortField,
|
|
8395
8539
|
initialSortDirection: this.initialSortDirection,
|
|
8396
|
-
pageSize: this.pageSize
|
|
8540
|
+
pageSize: this.pageSize,
|
|
8541
|
+
maxNumberOfBars: this.maxNumberOfBars
|
|
8397
8542
|
}
|
|
8398
8543
|
);
|
|
8399
8544
|
}
|
|
@@ -8422,6 +8567,9 @@ __decorateClass$9([
|
|
|
8422
8567
|
__decorateClass$9([
|
|
8423
8568
|
n2({ type: Object })
|
|
8424
8569
|
], AggregateComponent.prototype, "pageSize", 2);
|
|
8570
|
+
__decorateClass$9([
|
|
8571
|
+
n2({ type: Object })
|
|
8572
|
+
], AggregateComponent.prototype, "maxNumberOfBars", 2);
|
|
8425
8573
|
AggregateComponent = __decorateClass$9([
|
|
8426
8574
|
t$2("gs-aggregate")
|
|
8427
8575
|
], AggregateComponent);
|
|
@@ -9103,7 +9251,7 @@ const MutationsOverTimeGrid = ({ data, colorScale }) => {
|
|
|
9103
9251
|
] });
|
|
9104
9252
|
};
|
|
9105
9253
|
function getTooltipPosition(rowIndex, rows, columnIndex, columns) {
|
|
9106
|
-
const tooltipX = rowIndex < rows / 2 ? "bottom" : "top";
|
|
9254
|
+
const tooltipX = rowIndex < rows / 2 || rowIndex < 6 ? "bottom" : "top";
|
|
9107
9255
|
const tooltipY = columnIndex < columns / 2 ? "start" : "end";
|
|
9108
9256
|
return `${tooltipX}-${tooltipY}`;
|
|
9109
9257
|
}
|
|
@@ -10580,8 +10728,8 @@ SequencesByLocationComponent = __decorateClass$6([
|
|
|
10580
10728
|
t$2("gs-sequences-by-location")
|
|
10581
10729
|
], SequencesByLocationComponent);
|
|
10582
10730
|
async function queryGeneralStatistics(numeratorFilter, denominatorFilter, lapis, signal) {
|
|
10583
|
-
const numeratorCount = await queryAggregateData(numeratorFilter, [], lapis,
|
|
10584
|
-
const denominatorCount = await queryAggregateData(denominatorFilter, [], lapis,
|
|
10731
|
+
const numeratorCount = await queryAggregateData(numeratorFilter, [], lapis, signal);
|
|
10732
|
+
const denominatorCount = await queryAggregateData(denominatorFilter, [], lapis, signal);
|
|
10585
10733
|
if (numeratorCount.length === 0 || denominatorCount.length === 0) {
|
|
10586
10734
|
throw new Error("No data found for the given filters");
|
|
10587
10735
|
}
|