@genspectrum/dashboard-components 0.11.3 → 0.11.4
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 +16 -0
- package/dist/components.d.ts +44 -44
- package/dist/components.js +181 -131
- package/dist/components.js.map +1 -1
- package/dist/style.css +2 -1
- package/dist/util.d.ts +44 -44
- package/package.json +2 -2
- package/src/preact/aggregatedData/aggregate.tsx +1 -1
- package/src/preact/map/__mockData__/aggregatedGermany.json +5 -1
- package/src/preact/map/{useGeoJsonMap.tsx → loadMapSource.tsx} +7 -24
- package/src/preact/map/sequences-by-location-map.tsx +13 -99
- package/src/preact/map/sequences-by-location-table.tsx +28 -5
- package/src/preact/map/sequences-by-location.tsx +32 -13
- package/src/preact/useQuery.ts +1 -1
- package/src/query/computeMapLocationData.spec.ts +103 -0
- package/src/query/computeMapLocationData.ts +136 -0
- package/src/query/querySequencesByLocationData.ts +18 -0
- package/src/utilEntrypoint.ts +1 -1
- package/src/web-components/visualization/gs-sequences-by-location.stories.ts +17 -0
- package/standalone-bundle/dashboard-components.js +2861 -2811
- package/standalone-bundle/dashboard-components.js.map +1 -1
- package/standalone-bundle/style.css +1 -1
package/dist/components.js
CHANGED
|
@@ -582,11 +582,11 @@ function GsAppError(error) {
|
|
|
582
582
|
var f$1 = 0;
|
|
583
583
|
function u$1(e2, t2, n3, o2, i2, u2) {
|
|
584
584
|
t2 || (t2 = {});
|
|
585
|
-
var a2, c2,
|
|
586
|
-
"ref" in
|
|
587
|
-
var
|
|
588
|
-
if ("function" == typeof e2 && (a2 = e2.defaultProps)) for (c2 in a2) void 0 ===
|
|
589
|
-
return options.vnode && options.vnode(
|
|
585
|
+
var a2, c2, p2 = t2;
|
|
586
|
+
if ("ref" in p2) for (c2 in p2 = {}, t2) "ref" == c2 ? a2 = t2[c2] : p2[c2] = t2[c2];
|
|
587
|
+
var l2 = { type: e2, props: p2, key: n3, ref: a2, __k: null, __: null, __b: 0, __e: null, __c: null, constructor: void 0, __v: --f$1, __i: -1, __u: 0, __source: i2, __self: u2 };
|
|
588
|
+
if ("function" == typeof e2 && (a2 = e2.defaultProps)) for (c2 in a2) void 0 === p2[c2] && (p2[c2] = a2[c2]);
|
|
589
|
+
return options.vnode && options.vnode(l2), l2;
|
|
590
590
|
}
|
|
591
591
|
var t, r, u, i, o = 0, f = [], c = options, e = c.__b, a = c.__r, v = c.diffed, l = c.__c, m = c.unmount, s = c.__;
|
|
592
592
|
function d(n3, t2) {
|
|
@@ -2037,7 +2037,7 @@ function useQuery(fetchDataCallback, dependencies) {
|
|
|
2037
2037
|
setIsLoading(false);
|
|
2038
2038
|
}
|
|
2039
2039
|
};
|
|
2040
|
-
fetchData();
|
|
2040
|
+
void fetchData();
|
|
2041
2041
|
}, [JSON.stringify(dependencies)]);
|
|
2042
2042
|
if (isLoading) {
|
|
2043
2043
|
return { isLoading: true };
|
|
@@ -2293,7 +2293,7 @@ const tailwindStyle = `*, ::before, ::after {
|
|
|
2293
2293
|
--tw-contain-paint: ;
|
|
2294
2294
|
--tw-contain-style: ;
|
|
2295
2295
|
}/*
|
|
2296
|
-
! tailwindcss v3.4.
|
|
2296
|
+
! tailwindcss v3.4.17 | MIT License | https://tailwindcss.com
|
|
2297
2297
|
*//*
|
|
2298
2298
|
1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4)
|
|
2299
2299
|
2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116)
|
|
@@ -2965,6 +2965,7 @@ html {
|
|
|
2965
2965
|
display: grid;
|
|
2966
2966
|
width: 100%;
|
|
2967
2967
|
overflow: hidden;
|
|
2968
|
+
direction: ltr;
|
|
2968
2969
|
container-type: inline-size;
|
|
2969
2970
|
grid-template-columns: auto 1fr;
|
|
2970
2971
|
}
|
|
@@ -8326,7 +8327,7 @@ const AggregateInner = (componentProps) => {
|
|
|
8326
8327
|
field: initialSortField,
|
|
8327
8328
|
direction: initialSortDirection
|
|
8328
8329
|
});
|
|
8329
|
-
}, [lapisFilter, fields, lapis]);
|
|
8330
|
+
}, [lapisFilter, fields, lapis, initialSortField, initialSortDirection]);
|
|
8330
8331
|
if (isLoading) {
|
|
8331
8332
|
return /* @__PURE__ */ u$1(LoadingDisplay, {});
|
|
8332
8333
|
}
|
|
@@ -10100,62 +10101,12 @@ svg.leaflet-image-layer.leaflet-interactive path {\r
|
|
|
10100
10101
|
}\r
|
|
10101
10102
|
`;
|
|
10102
10103
|
const leafletStyleModifications = ".leaflet-container {\n background: transparent;\n}\n";
|
|
10103
|
-
const mapSourceSchema = z$1.object({
|
|
10104
|
-
type: z$1.literal("topojson"),
|
|
10105
|
-
url: z$1.string().min(1),
|
|
10106
|
-
topologyObjectsKey: z$1.string().min(1)
|
|
10107
|
-
});
|
|
10108
|
-
function useGeoJsonMap(mapSource) {
|
|
10109
|
-
const {
|
|
10110
|
-
data: geojsonData,
|
|
10111
|
-
error,
|
|
10112
|
-
isLoading
|
|
10113
|
-
} = useQuery(async () => {
|
|
10114
|
-
switch (mapSource.type) {
|
|
10115
|
-
case "topojson":
|
|
10116
|
-
return await loadTopojsonMap(mapSource);
|
|
10117
|
-
}
|
|
10118
|
-
}, [mapSource]);
|
|
10119
|
-
if (isLoading) {
|
|
10120
|
-
return { isLoading };
|
|
10121
|
-
}
|
|
10122
|
-
if (error) {
|
|
10123
|
-
throw error;
|
|
10124
|
-
}
|
|
10125
|
-
return { geojsonData, isLoading: false };
|
|
10126
|
-
}
|
|
10127
|
-
async function loadTopojsonMap(mapSource) {
|
|
10128
|
-
var _a;
|
|
10129
|
-
const response = await fetch(mapSource.url);
|
|
10130
|
-
const topology = await response.json();
|
|
10131
|
-
if ((topology == null ? void 0 : topology.type) !== "Topology") {
|
|
10132
|
-
throw new UserFacingError(
|
|
10133
|
-
"Invalid map source",
|
|
10134
|
-
`JSON downloaded from ${mapSource.url} does not look like a topojson Topology definition: missing 'type: "Topology"', got '${JSON.stringify(topology).substring(0, 100)}'`
|
|
10135
|
-
);
|
|
10136
|
-
}
|
|
10137
|
-
const object = topology == null ? void 0 : topology.objects[mapSource.topologyObjectsKey];
|
|
10138
|
-
if ((object == null ? void 0 : object.type) !== "GeometryCollection") {
|
|
10139
|
-
throw new UserFacingError(
|
|
10140
|
-
"Invalid map source",
|
|
10141
|
-
`JSON downloaded from ${mapSource.url} does not have a GeometryCollection at key objects.${mapSource.topologyObjectsKey}, got '${(_a = JSON.stringify(topology)) == null ? void 0 : _a.substring(0, 100)}'`
|
|
10142
|
-
);
|
|
10143
|
-
}
|
|
10144
|
-
return topojson.feature(topology, object);
|
|
10145
|
-
}
|
|
10146
10104
|
const SequencesByLocationMap = ({
|
|
10147
|
-
|
|
10148
|
-
|
|
10149
|
-
|
|
10150
|
-
|
|
10151
|
-
|
|
10152
|
-
return /* @__PURE__ */ u$1(LoadingDisplay, {});
|
|
10153
|
-
}
|
|
10154
|
-
return /* @__PURE__ */ u$1(SequencesByLocationMapInner$1, { geojsonData, ...otherProps });
|
|
10155
|
-
};
|
|
10156
|
-
const SequencesByLocationMapInner$1 = ({
|
|
10157
|
-
geojsonData,
|
|
10158
|
-
locationData,
|
|
10105
|
+
locations,
|
|
10106
|
+
totalCount,
|
|
10107
|
+
countOfMatchedLocationData,
|
|
10108
|
+
nullCount,
|
|
10109
|
+
unmatchedLocations,
|
|
10159
10110
|
enableMapNavigation,
|
|
10160
10111
|
lapisLocationField,
|
|
10161
10112
|
zoom,
|
|
@@ -10163,22 +10114,7 @@ const SequencesByLocationMapInner$1 = ({
|
|
|
10163
10114
|
offsetY,
|
|
10164
10115
|
hasTableView
|
|
10165
10116
|
}) => {
|
|
10166
|
-
var _a;
|
|
10167
10117
|
const ref = A(null);
|
|
10168
|
-
const { locations, totalCount, countOfMatchedLocationData, unmatchedLocations } = T(() => {
|
|
10169
|
-
const countAndProportionByCountry = buildLookupByLocationField(locationData, lapisLocationField);
|
|
10170
|
-
const { locations: locations2, unmatchedLocations: unmatchedLocations2 } = matchLocationDataAndGeoJsonFeatures(
|
|
10171
|
-
geojsonData,
|
|
10172
|
-
countAndProportionByCountry,
|
|
10173
|
-
lapisLocationField
|
|
10174
|
-
);
|
|
10175
|
-
const totalCount2 = locationData.map((value) => value.count).reduce((sum, b3) => sum + b3, 0);
|
|
10176
|
-
const countOfMatchedLocationData2 = locations2.map((location) => {
|
|
10177
|
-
var _a2;
|
|
10178
|
-
return ((_a2 = location.properties.data) == null ? void 0 : _a2.count) ?? 0;
|
|
10179
|
-
}).reduce((sum, b3) => sum + b3, 0);
|
|
10180
|
-
return { locations: locations2, totalCount: totalCount2, countOfMatchedLocationData: countOfMatchedLocationData2, unmatchedLocations: unmatchedLocations2 };
|
|
10181
|
-
}, [geojsonData, locationData, lapisLocationField]);
|
|
10182
10118
|
y(() => {
|
|
10183
10119
|
if (!ref.current) {
|
|
10184
10120
|
return;
|
|
@@ -10194,9 +10130,9 @@ const SequencesByLocationMapInner$1 = ({
|
|
|
10194
10130
|
});
|
|
10195
10131
|
Leaflet.geoJson(locations, {
|
|
10196
10132
|
style: (feature) => {
|
|
10197
|
-
var
|
|
10133
|
+
var _a;
|
|
10198
10134
|
return {
|
|
10199
|
-
fillColor: getColor((
|
|
10135
|
+
fillColor: getColor((_a = feature == null ? void 0 : feature.properties.data) == null ? void 0 : _a.proportion),
|
|
10200
10136
|
fillOpacity: 1,
|
|
10201
10137
|
color: "#666666",
|
|
10202
10138
|
weight: 1
|
|
@@ -10207,7 +10143,6 @@ const SequencesByLocationMapInner$1 = ({
|
|
|
10207
10143
|
leafletMap.remove();
|
|
10208
10144
|
};
|
|
10209
10145
|
}, [ref, locations, enableMapNavigation, lapisLocationField, zoom, offsetX, offsetY]);
|
|
10210
|
-
const nullCount = ((_a = locationData.find((row) => row[lapisLocationField] === null)) == null ? void 0 : _a.count) ?? 0;
|
|
10211
10146
|
return /* @__PURE__ */ u$1("div", { className: "h-full", children: [
|
|
10212
10147
|
/* @__PURE__ */ u$1("div", { ref, className: "h-full" }),
|
|
10213
10148
|
/* @__PURE__ */ u$1("div", { className: "relative", children: /* @__PURE__ */ u$1(
|
|
@@ -10273,44 +10208,6 @@ const DataMatchInformation = ({
|
|
|
10273
10208
|
] })
|
|
10274
10209
|
] });
|
|
10275
10210
|
};
|
|
10276
|
-
function buildLookupByLocationField(locationData, lapisLocationField) {
|
|
10277
|
-
return new Map(
|
|
10278
|
-
locationData.filter((row) => typeof row[lapisLocationField] === "string").map((row) => [row[lapisLocationField], row])
|
|
10279
|
-
);
|
|
10280
|
-
}
|
|
10281
|
-
function matchLocationDataAndGeoJsonFeatures(geojsonData, countAndProportionByCountry, lapisLocationField) {
|
|
10282
|
-
const matchedLocations = [];
|
|
10283
|
-
const locations = geojsonData.features.map(
|
|
10284
|
-
(feature) => {
|
|
10285
|
-
var _a;
|
|
10286
|
-
const name = (_a = feature == null ? void 0 : feature.properties) == null ? void 0 : _a.name;
|
|
10287
|
-
if (typeof name !== "string") {
|
|
10288
|
-
throw new Error(
|
|
10289
|
-
`GeoJSON feature with id '${feature.id}' does not have 'properties.name' of type string, was: '${name}'`
|
|
10290
|
-
);
|
|
10291
|
-
}
|
|
10292
|
-
const data = countAndProportionByCountry.get(name) ?? null;
|
|
10293
|
-
if (data !== null) {
|
|
10294
|
-
matchedLocations.push(name);
|
|
10295
|
-
}
|
|
10296
|
-
return {
|
|
10297
|
-
...feature,
|
|
10298
|
-
properties: {
|
|
10299
|
-
...feature.properties,
|
|
10300
|
-
data
|
|
10301
|
-
}
|
|
10302
|
-
};
|
|
10303
|
-
}
|
|
10304
|
-
);
|
|
10305
|
-
const unmatchedLocations = [...countAndProportionByCountry.keys()].filter(
|
|
10306
|
-
(name) => !matchedLocations.includes(name)
|
|
10307
|
-
);
|
|
10308
|
-
if (unmatchedLocations.length > 0) {
|
|
10309
|
-
const unmatchedLocationsWarning = `gs-map: Found location data from LAPIS (aggregated by "${lapisLocationField}") that could not be matched on locations on the given map. Unmatched location names are: ${unmatchedLocations.map((it) => `"${it}"`).join(", ")}`;
|
|
10310
|
-
console.warn(unmatchedLocationsWarning);
|
|
10311
|
-
}
|
|
10312
|
-
return { locations, unmatchedLocations };
|
|
10313
|
-
}
|
|
10314
10211
|
function getColor(value) {
|
|
10315
10212
|
if (value === void 0) {
|
|
10316
10213
|
return "#DDDDDD";
|
|
@@ -10364,12 +10261,150 @@ function p({ innerText, className = "" }) {
|
|
|
10364
10261
|
return headline;
|
|
10365
10262
|
}
|
|
10366
10263
|
const SequencesByLocationTable = ({
|
|
10367
|
-
|
|
10264
|
+
tableData,
|
|
10368
10265
|
lapisLocationField,
|
|
10369
10266
|
pageSize
|
|
10370
10267
|
}) => {
|
|
10371
|
-
|
|
10268
|
+
const headers = [
|
|
10269
|
+
{
|
|
10270
|
+
name: lapisLocationField,
|
|
10271
|
+
sort: {
|
|
10272
|
+
compare: compareAscending
|
|
10273
|
+
}
|
|
10274
|
+
},
|
|
10275
|
+
{
|
|
10276
|
+
name: "count",
|
|
10277
|
+
sort: true
|
|
10278
|
+
},
|
|
10279
|
+
{
|
|
10280
|
+
name: "proportion",
|
|
10281
|
+
sort: true,
|
|
10282
|
+
formatter: (cell) => formatProportion(cell)
|
|
10283
|
+
},
|
|
10284
|
+
..."isShownOnMap" in tableData[0] ? [{ id: "isShownOnMap", name: "shown on map", sort: true, width: "20%" }] : []
|
|
10285
|
+
];
|
|
10286
|
+
return /* @__PURE__ */ u$1(Table, { data: tableData, columns: headers, pageSize });
|
|
10287
|
+
};
|
|
10288
|
+
const MapLocationDataType = {
|
|
10289
|
+
tableDataOnly: "tableDataOnly",
|
|
10290
|
+
tableAndMapData: "tableAndMapData"
|
|
10372
10291
|
};
|
|
10292
|
+
function computeMapLocationData(locationData, geojsonData, lapisLocationField) {
|
|
10293
|
+
var _a;
|
|
10294
|
+
if (geojsonData === void 0) {
|
|
10295
|
+
return { type: MapLocationDataType.tableDataOnly, tableData: locationData };
|
|
10296
|
+
}
|
|
10297
|
+
const countAndProportionByCountry = buildLookupByLocationField(locationData, lapisLocationField);
|
|
10298
|
+
const { locations, unmatchedLocations } = matchLocationDataAndGeoJsonFeatures(
|
|
10299
|
+
geojsonData,
|
|
10300
|
+
countAndProportionByCountry,
|
|
10301
|
+
lapisLocationField
|
|
10302
|
+
);
|
|
10303
|
+
const totalCount = locationData.map((value) => value.count).reduce((sum, b3) => sum + b3, 0);
|
|
10304
|
+
const countOfMatchedLocationData = locations.map((location) => {
|
|
10305
|
+
var _a2;
|
|
10306
|
+
return ((_a2 = location.properties.data) == null ? void 0 : _a2.count) ?? 0;
|
|
10307
|
+
}).reduce((sum, b3) => sum + b3, 0);
|
|
10308
|
+
const nullCount = ((_a = locationData.find((row) => row[lapisLocationField] === null)) == null ? void 0 : _a.count) ?? 0;
|
|
10309
|
+
const tableData = getSequencesByLocationTableData(locationData, unmatchedLocations, lapisLocationField);
|
|
10310
|
+
return {
|
|
10311
|
+
type: MapLocationDataType.tableAndMapData,
|
|
10312
|
+
locations,
|
|
10313
|
+
tableData,
|
|
10314
|
+
totalCount,
|
|
10315
|
+
countOfMatchedLocationData,
|
|
10316
|
+
unmatchedLocations,
|
|
10317
|
+
nullCount
|
|
10318
|
+
};
|
|
10319
|
+
}
|
|
10320
|
+
function buildLookupByLocationField(locationData, lapisLocationField) {
|
|
10321
|
+
return new Map(
|
|
10322
|
+
locationData.filter((row) => typeof row[lapisLocationField] === "string").map((row) => [row[lapisLocationField], row])
|
|
10323
|
+
);
|
|
10324
|
+
}
|
|
10325
|
+
function matchLocationDataAndGeoJsonFeatures(geojsonData, countAndProportionByCountry, lapisLocationField) {
|
|
10326
|
+
const matchedLocations = [];
|
|
10327
|
+
const locations = geojsonData.features.map(
|
|
10328
|
+
(feature) => {
|
|
10329
|
+
var _a;
|
|
10330
|
+
const name = (_a = feature == null ? void 0 : feature.properties) == null ? void 0 : _a.name;
|
|
10331
|
+
if (typeof name !== "string") {
|
|
10332
|
+
throw new Error(
|
|
10333
|
+
`GeoJSON feature with id '${feature.id}' does not have 'properties.name' of type string, was: '${name}'`
|
|
10334
|
+
);
|
|
10335
|
+
}
|
|
10336
|
+
const data = countAndProportionByCountry.get(name) ?? null;
|
|
10337
|
+
if (data !== null) {
|
|
10338
|
+
matchedLocations.push(name);
|
|
10339
|
+
}
|
|
10340
|
+
return {
|
|
10341
|
+
...feature,
|
|
10342
|
+
properties: {
|
|
10343
|
+
...feature.properties,
|
|
10344
|
+
data
|
|
10345
|
+
}
|
|
10346
|
+
};
|
|
10347
|
+
}
|
|
10348
|
+
);
|
|
10349
|
+
const unmatchedLocations = [...countAndProportionByCountry.keys()].filter(
|
|
10350
|
+
(name) => !matchedLocations.includes(name)
|
|
10351
|
+
);
|
|
10352
|
+
if (unmatchedLocations.length > 0) {
|
|
10353
|
+
const unmatchedLocationsWarning = `gs-map: Found location data from LAPIS (aggregated by "${lapisLocationField}") that could not be matched on locations on the given map. Unmatched location names are: ${unmatchedLocations.map((it) => `"${it}"`).join(", ")}`;
|
|
10354
|
+
console.warn(unmatchedLocationsWarning);
|
|
10355
|
+
}
|
|
10356
|
+
return { locations, unmatchedLocations };
|
|
10357
|
+
}
|
|
10358
|
+
function getSequencesByLocationTableData(locationData, unmatchedLocations, lapisLocationField) {
|
|
10359
|
+
return locationData.map((row) => ({
|
|
10360
|
+
...row,
|
|
10361
|
+
isShownOnMap: `${isShownOnMap(row, unmatchedLocations, lapisLocationField)}`
|
|
10362
|
+
}));
|
|
10363
|
+
}
|
|
10364
|
+
function isShownOnMap(row, unmatchedLocations, lapisLocationField) {
|
|
10365
|
+
const locationValue = row[lapisLocationField];
|
|
10366
|
+
if (locationValue === null) {
|
|
10367
|
+
return false;
|
|
10368
|
+
}
|
|
10369
|
+
return !unmatchedLocations.includes(locationValue);
|
|
10370
|
+
}
|
|
10371
|
+
const mapSourceSchema = z$1.object({
|
|
10372
|
+
type: z$1.literal("topojson"),
|
|
10373
|
+
url: z$1.string().min(1),
|
|
10374
|
+
topologyObjectsKey: z$1.string().min(1)
|
|
10375
|
+
});
|
|
10376
|
+
async function loadMapSource(mapSource) {
|
|
10377
|
+
switch (mapSource.type) {
|
|
10378
|
+
case "topojson":
|
|
10379
|
+
return await loadTopojsonMap(mapSource);
|
|
10380
|
+
}
|
|
10381
|
+
}
|
|
10382
|
+
async function loadTopojsonMap(mapSource) {
|
|
10383
|
+
var _a;
|
|
10384
|
+
const response = await fetch(mapSource.url);
|
|
10385
|
+
const topology = await response.json();
|
|
10386
|
+
if ((topology == null ? void 0 : topology.type) !== "Topology") {
|
|
10387
|
+
throw new UserFacingError(
|
|
10388
|
+
"Invalid map source",
|
|
10389
|
+
`JSON downloaded from ${mapSource.url} does not look like a topojson Topology definition: missing 'type: "Topology"', got '${JSON.stringify(topology).substring(0, 100)}'`
|
|
10390
|
+
);
|
|
10391
|
+
}
|
|
10392
|
+
const object = topology == null ? void 0 : topology.objects[mapSource.topologyObjectsKey];
|
|
10393
|
+
if ((object == null ? void 0 : object.type) !== "GeometryCollection") {
|
|
10394
|
+
throw new UserFacingError(
|
|
10395
|
+
"Invalid map source",
|
|
10396
|
+
`JSON downloaded from ${mapSource.url} does not have a GeometryCollection at key objects.${mapSource.topologyObjectsKey}, got '${(_a = JSON.stringify(topology)) == null ? void 0 : _a.substring(0, 100)}'`
|
|
10397
|
+
);
|
|
10398
|
+
}
|
|
10399
|
+
return topojson.feature(topology, object);
|
|
10400
|
+
}
|
|
10401
|
+
async function querySequencesByLocationData(lapisFilter, lapisLocationField, lapis, mapSource) {
|
|
10402
|
+
const [locationData, geojsonData] = await Promise.all([
|
|
10403
|
+
queryAggregateData(lapisFilter, [lapisLocationField], lapis),
|
|
10404
|
+
mapSource !== void 0 ? loadMapSource(mapSource) : void 0
|
|
10405
|
+
]);
|
|
10406
|
+
return computeMapLocationData(locationData, geojsonData, lapisLocationField);
|
|
10407
|
+
}
|
|
10373
10408
|
const sequencesByLocationViewSchema = z$1.union([z$1.literal(views.map), z$1.literal(views.table)]);
|
|
10374
10409
|
const sequencesByLocationPropsSchema = z$1.object({
|
|
10375
10410
|
lapisFilter: lapisFilterSchema,
|
|
@@ -10390,15 +10425,15 @@ const SequencesByLocation = (componentProps) => {
|
|
|
10390
10425
|
return /* @__PURE__ */ u$1(ErrorBoundary, { size, componentProps, schema: sequencesByLocationPropsSchema, children: /* @__PURE__ */ u$1(ResizeContainer, { size, children: /* @__PURE__ */ u$1(SequencesByLocationMapInner, { ...componentProps }) }) });
|
|
10391
10426
|
};
|
|
10392
10427
|
const SequencesByLocationMapInner = (props) => {
|
|
10393
|
-
const { lapisFilter, lapisLocationField } = props;
|
|
10428
|
+
const { lapisFilter, lapisLocationField, mapSource } = props;
|
|
10394
10429
|
const lapis = x(LapisUrlContext);
|
|
10395
10430
|
const {
|
|
10396
10431
|
data,
|
|
10397
10432
|
error,
|
|
10398
10433
|
isLoading: isLoadingLapisData
|
|
10399
10434
|
} = useQuery(
|
|
10400
|
-
async () =>
|
|
10401
|
-
[lapisFilter, lapisLocationField, lapis]
|
|
10435
|
+
async () => querySequencesByLocationData(lapisFilter, lapisLocationField, lapis, mapSource),
|
|
10436
|
+
[lapisFilter, lapisLocationField, lapis, mapSource]
|
|
10402
10437
|
);
|
|
10403
10438
|
if (isLoadingLapisData) {
|
|
10404
10439
|
return /* @__PURE__ */ u$1(LoadingDisplay, {});
|
|
@@ -10414,17 +10449,17 @@ const SequencesByLocationMapTabs = ({
|
|
|
10414
10449
|
}) => {
|
|
10415
10450
|
const getTab = (view) => {
|
|
10416
10451
|
switch (view) {
|
|
10417
|
-
case views.map:
|
|
10418
|
-
if (
|
|
10452
|
+
case views.map: {
|
|
10453
|
+
if (data.type !== MapLocationDataType.tableAndMapData) {
|
|
10419
10454
|
throw new Error("mapSource is required when using the map view");
|
|
10420
10455
|
}
|
|
10456
|
+
const { type: _type, tableData: _tableData, ...dataForMap } = data;
|
|
10421
10457
|
return {
|
|
10422
10458
|
title: "Map",
|
|
10423
10459
|
content: /* @__PURE__ */ u$1(
|
|
10424
10460
|
SequencesByLocationMap,
|
|
10425
10461
|
{
|
|
10426
|
-
|
|
10427
|
-
mapSource: originalComponentProps.mapSource,
|
|
10462
|
+
...dataForMap,
|
|
10428
10463
|
enableMapNavigation: originalComponentProps.enableMapNavigation,
|
|
10429
10464
|
lapisLocationField: originalComponentProps.lapisLocationField,
|
|
10430
10465
|
zoom: originalComponentProps.zoom,
|
|
@@ -10434,13 +10469,14 @@ const SequencesByLocationMapTabs = ({
|
|
|
10434
10469
|
}
|
|
10435
10470
|
)
|
|
10436
10471
|
};
|
|
10472
|
+
}
|
|
10437
10473
|
case views.table:
|
|
10438
10474
|
return {
|
|
10439
10475
|
title: "Table",
|
|
10440
10476
|
content: /* @__PURE__ */ u$1(
|
|
10441
10477
|
SequencesByLocationTable,
|
|
10442
10478
|
{
|
|
10443
|
-
|
|
10479
|
+
tableData: data.tableData,
|
|
10444
10480
|
lapisLocationField: originalComponentProps.lapisLocationField,
|
|
10445
10481
|
pageSize: originalComponentProps.pageSize
|
|
10446
10482
|
}
|
|
@@ -10449,10 +10485,24 @@ const SequencesByLocationMapTabs = ({
|
|
|
10449
10485
|
}
|
|
10450
10486
|
};
|
|
10451
10487
|
const tabs = originalComponentProps.views.map((view) => getTab(view));
|
|
10452
|
-
return /* @__PURE__ */ u$1(
|
|
10488
|
+
return /* @__PURE__ */ u$1(
|
|
10489
|
+
Tabs,
|
|
10490
|
+
{
|
|
10491
|
+
tabs,
|
|
10492
|
+
toolbar: /* @__PURE__ */ u$1(Toolbar, { originalComponentProps, tableData: data.tableData })
|
|
10493
|
+
}
|
|
10494
|
+
);
|
|
10453
10495
|
};
|
|
10454
|
-
const Toolbar = ({ originalComponentProps }) => {
|
|
10496
|
+
const Toolbar = ({ originalComponentProps, tableData }) => {
|
|
10455
10497
|
return /* @__PURE__ */ u$1("div", { class: "flex flex-row", children: [
|
|
10498
|
+
/* @__PURE__ */ u$1(
|
|
10499
|
+
CsvDownloadButton,
|
|
10500
|
+
{
|
|
10501
|
+
className: "mx-1 btn btn-xs",
|
|
10502
|
+
getData: () => tableData,
|
|
10503
|
+
filename: "sequences_by_location.csv"
|
|
10504
|
+
}
|
|
10505
|
+
),
|
|
10456
10506
|
/* @__PURE__ */ u$1(SequencesByLocationMapInfo, { originalComponentProps }),
|
|
10457
10507
|
/* @__PURE__ */ u$1(Fullscreen, {})
|
|
10458
10508
|
] });
|