@sqlrooms/deck 0.29.0-rc.5 → 0.29.0-rc.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.
- package/README.md +24 -2
- package/dist/DeckJsonMap.d.ts +1 -1
- package/dist/DeckJsonMap.d.ts.map +1 -1
- package/dist/DeckJsonMap.js +16 -11
- package/dist/DeckJsonMap.js.map +1 -1
- package/dist/LatitudeSelector.d.ts +11 -0
- package/dist/LatitudeSelector.d.ts.map +1 -0
- package/dist/LatitudeSelector.js +25 -0
- package/dist/LatitudeSelector.js.map +1 -0
- package/dist/LongitudeSelector.d.ts +11 -0
- package/dist/LongitudeSelector.d.ts.map +1 -0
- package/dist/LongitudeSelector.js +27 -0
- package/dist/LongitudeSelector.js.map +1 -0
- package/dist/MapSettings.d.ts +10 -0
- package/dist/MapSettings.d.ts.map +1 -0
- package/dist/MapSettings.js +94 -0
- package/dist/MapSettings.js.map +1 -0
- package/dist/ai.d.ts +168 -0
- package/dist/ai.d.ts.map +1 -0
- package/dist/ai.js +232 -0
- package/dist/ai.js.map +1 -0
- package/dist/dashboard.d.ts.map +1 -1
- package/dist/dashboard.js +72 -105
- package/dist/dashboard.js.map +1 -1
- package/dist/dashboardConfig.d.ts +22 -6
- package/dist/dashboardConfig.d.ts.map +1 -1
- package/dist/dashboardConfig.js +2 -5
- package/dist/dashboardConfig.js.map +1 -1
- package/dist/dashboardIntegration.d.ts +3 -0
- package/dist/dashboardIntegration.d.ts.map +1 -0
- package/dist/dashboardIntegration.js +16 -0
- package/dist/dashboardIntegration.js.map +1 -0
- package/dist/datasets/PreparedDatasetStore.js +2 -1
- package/dist/datasets/PreparedDatasetStore.js.map +1 -1
- package/dist/index.d.ts +8 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/json/colorScaleFunction.d.ts +1 -1
- package/dist/json/colorScaleFunction.d.ts.map +1 -1
- package/dist/json/colorScaleFunction.js +7 -1
- package/dist/json/colorScaleFunction.js.map +1 -1
- package/dist/json/extractColorScaleLegends.d.ts.map +1 -1
- package/dist/json/extractColorScaleLegends.js +0 -1
- package/dist/json/extractColorScaleLegends.js.map +1 -1
- package/dist/json/layerCompatibility.d.ts.map +1 -1
- package/dist/json/layerCompatibility.js +2 -0
- package/dist/json/layerCompatibility.js.map +1 -1
- package/dist/mapConfigUtils.d.ts +62 -0
- package/dist/mapConfigUtils.d.ts.map +1 -0
- package/dist/mapConfigUtils.js +233 -0
- package/dist/mapConfigUtils.js.map +1 -0
- package/dist/mapDataPolicy.d.ts +4 -0
- package/dist/mapDataPolicy.d.ts.map +1 -0
- package/dist/mapDataPolicy.js +25 -0
- package/dist/mapDataPolicy.js.map +1 -0
- package/dist/mapLayerConfigUtils.d.ts +38 -0
- package/dist/mapLayerConfigUtils.d.ts.map +1 -0
- package/dist/mapLayerConfigUtils.js +185 -0
- package/dist/mapLayerConfigUtils.js.map +1 -0
- package/dist/prepare/wkbDecoder.d.ts.map +1 -1
- package/dist/prepare/wkbDecoder.js +266 -67
- package/dist/prepare/wkbDecoder.js.map +1 -1
- package/dist/prepare/wkbParser.d.ts +19 -0
- package/dist/prepare/wkbParser.d.ts.map +1 -0
- package/dist/prepare/wkbParser.js +115 -0
- package/dist/prepare/wkbParser.js.map +1 -0
- package/dist/types.d.ts +8 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +8 -6
- package/dist/useDeckLayersReadyRedraw.d.ts +0 -13
- package/dist/useDeckLayersReadyRedraw.d.ts.map +0 -1
- package/dist/useDeckLayersReadyRedraw.js +0 -35
- package/dist/useDeckLayersReadyRedraw.js.map +0 -1
package/dist/dashboard.js
CHANGED
|
@@ -2,13 +2,25 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { WebMercatorViewport } from '@deck.gl/core';
|
|
3
3
|
import { escapeId, getColValAsNumber, useStoreWithDuckDb, } from '@sqlrooms/duckdb';
|
|
4
4
|
import { column, sql, useMosaicClient, useStoreWithMosaicDashboard, } from '@sqlrooms/mosaic';
|
|
5
|
-
import { Button } from '@sqlrooms/ui';
|
|
6
|
-
import { FocusIcon, MapIcon } from 'lucide-react';
|
|
5
|
+
import { Button, Tooltip, TooltipContent, TooltipTrigger } from '@sqlrooms/ui';
|
|
6
|
+
import { FocusIcon, MapIcon, SettingsIcon } from 'lucide-react';
|
|
7
7
|
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
8
8
|
import { DeckMapConfigPopoverEditor } from './DeckMapConfigPopoverEditor';
|
|
9
9
|
import { DeckJsonMap } from './DeckJsonMap';
|
|
10
|
-
import {
|
|
11
|
-
|
|
10
|
+
import { MapSettingsPanel } from './MapSettings';
|
|
11
|
+
import { MosaicDashboardPanelLayout } from '@sqlrooms/mosaic';
|
|
12
|
+
import { asDeckJsonMapConfig, createDeckMapDashboardDatasetQuery, createDeckMapDashboardDatasets, DECK_MAP_DASHBOARD_PANEL_TYPE, resolveDeckMapDashboardDatasetSource, } from './dashboardConfig';
|
|
13
|
+
import { getDeckMapDataPolicy } from './mapDataPolicy';
|
|
14
|
+
import { createDeckMapDashboardPanelConfigForTable, findGeometryColumn, findLongitudeLatitudeColumns, } from './mapConfigUtils';
|
|
15
|
+
function DeckMapRuntimeIssuePanel({ issue }) {
|
|
16
|
+
const title = issue.kind === 'too-much-data'
|
|
17
|
+
? 'Too much data'
|
|
18
|
+
: issue.kind === 'sql-error'
|
|
19
|
+
? 'Map query failed'
|
|
20
|
+
: 'Unable to display map';
|
|
21
|
+
return (_jsxs("div", { className: "flex h-full min-h-[200px] flex-col items-center justify-center p-4", children: [_jsx("div", { className: "mb-2 text-center font-semibold", children: title }), _jsx("div", { className: "text-center text-sm whitespace-pre-wrap", children: issue.message })] }));
|
|
22
|
+
}
|
|
23
|
+
function DeckMapDashboardDatasetClient({ dashboard, dataset, datasetId, dataPolicy, panel, onDatasetState, runtimeIssueContext, runtimeIssueReporter, selectionName, }) {
|
|
12
24
|
const source = useMemo(() => resolveDeckMapDashboardDatasetSource({
|
|
13
25
|
dashboard,
|
|
14
26
|
panel,
|
|
@@ -21,7 +33,10 @@ function DeckMapDashboardDatasetClient({ dashboard, dataset, datasetId, panel, o
|
|
|
21
33
|
id: `${panel.id}:${datasetId}`,
|
|
22
34
|
selectionName,
|
|
23
35
|
query,
|
|
36
|
+
dataPolicy,
|
|
24
37
|
enabled: Boolean(source),
|
|
38
|
+
runtimeIssueContext,
|
|
39
|
+
runtimeIssueReporter,
|
|
25
40
|
});
|
|
26
41
|
useEffect(() => {
|
|
27
42
|
onDatasetState(datasetId, {
|
|
@@ -134,19 +149,35 @@ function DeckMapDashboardHeaderActions({ dashboardId, panel, }) {
|
|
|
134
149
|
const updatePanel = useStoreWithMosaicDashboard((state) => state.mosaicDashboard.updatePanel);
|
|
135
150
|
const mapConfig = asDeckJsonMapConfig(panel.config);
|
|
136
151
|
const canFitView = Boolean(mapConfig?.fitToData);
|
|
152
|
+
const isSettingsOpen = Boolean(mapConfig?.settingsOpen);
|
|
137
153
|
const handleConfigApply = useCallback((nextConfig) => {
|
|
138
154
|
updatePanel(dashboardId, panel.id, {
|
|
139
155
|
config: nextConfig,
|
|
140
156
|
});
|
|
141
157
|
}, [dashboardId, panel.id, updatePanel]);
|
|
142
|
-
|
|
158
|
+
const handleToggleSettings = useCallback(() => {
|
|
159
|
+
updatePanel(dashboardId, panel.id, {
|
|
160
|
+
config: { ...panel.config, settingsOpen: !isSettingsOpen },
|
|
161
|
+
});
|
|
162
|
+
}, [dashboardId, isSettingsOpen, panel.config, panel.id, updatePanel]);
|
|
163
|
+
return (_jsxs("div", { className: "flex items-center gap-0.5", children: [_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(Button, { variant: "ghost", size: "icon", className: "data-[state=active]:bg-accent h-6 w-6", title: "Map settings", onClick: handleToggleSettings, "data-state": isSettingsOpen ? 'active' : 'inactive', children: _jsx(SettingsIcon, { className: "h-3.5 w-3.5" }) }) }), _jsx(TooltipContent, { children: "Map settings" })] }), _jsx(DeckMapConfigPopoverEditor, { value: panel.config, onApply: handleConfigApply }), _jsx(Button, { variant: "ghost", size: "icon", className: "h-6 w-6", title: canFitView
|
|
143
164
|
? 'Fit map view to data'
|
|
144
165
|
: 'Fit view unavailable for this map', disabled: !canFitView, onClick: () => emitDeckMapDashboardFitRequest(panel.id), children: _jsx(FocusIcon, { className: "h-3.5 w-3.5" }) })] }));
|
|
145
166
|
}
|
|
146
|
-
function DeckMapDashboardRenderer({ dashboard, panel, selectionName, }) {
|
|
167
|
+
function DeckMapDashboardRenderer({ dashboard, dashboardId, panel, selectionName, }) {
|
|
147
168
|
const mapConfig = asDeckJsonMapConfig(panel.config);
|
|
148
169
|
const getSelection = useStoreWithMosaicDashboard((state) => state.mosaic.getSelection);
|
|
170
|
+
const updatePanel = useStoreWithMosaicDashboard((state) => state.mosaicDashboard.updatePanel);
|
|
171
|
+
const issue = useStoreWithMosaicDashboard((state) => state.mosaicDashboard.getPanelIssue(dashboardId, panel.id));
|
|
172
|
+
const reportPanelIssue = useStoreWithMosaicDashboard((state) => state.mosaicDashboard.reportPanelIssue);
|
|
173
|
+
const clearPanelIssue = useStoreWithMosaicDashboard((state) => state.mosaicDashboard.clearPanelIssue);
|
|
149
174
|
const executeSql = useStoreWithDuckDb((state) => state.db.executeSql);
|
|
175
|
+
const isSettingsOpen = Boolean(panel.config.settingsOpen);
|
|
176
|
+
const handleSettingsOpenChange = useCallback((isOpen) => {
|
|
177
|
+
updatePanel(dashboardId, panel.id, {
|
|
178
|
+
config: { ...panel.config, settingsOpen: isOpen },
|
|
179
|
+
});
|
|
180
|
+
}, [dashboardId, panel.config, panel.id, updatePanel]);
|
|
150
181
|
const selection = useMemo(() => getSelection(selectionName, 'crossfilter'), [getSelection, selectionName]);
|
|
151
182
|
const containerRef = useRef(null);
|
|
152
183
|
const [datasetStates, setDatasetStates] = useState({});
|
|
@@ -163,6 +194,19 @@ function DeckMapDashboardRenderer({ dashboard, panel, selectionName, }) {
|
|
|
163
194
|
return next;
|
|
164
195
|
});
|
|
165
196
|
}, []);
|
|
197
|
+
const dataPolicy = useMemo(() => getDeckMapDataPolicy(mapConfig), [mapConfig]);
|
|
198
|
+
const runtimeIssueContext = useMemo(() => ({
|
|
199
|
+
panelId: panel.id,
|
|
200
|
+
chartType: DECK_MAP_DASHBOARD_PANEL_TYPE,
|
|
201
|
+
}), [panel.id]);
|
|
202
|
+
const runtimeIssueReporter = useMemo(() => ({
|
|
203
|
+
reportIssue: (issueToReport) => {
|
|
204
|
+
reportPanelIssue(dashboardId, panel.id, issueToReport);
|
|
205
|
+
},
|
|
206
|
+
clearIssue: () => {
|
|
207
|
+
clearPanelIssue(dashboardId, panel.id);
|
|
208
|
+
},
|
|
209
|
+
}), [clearPanelIssue, dashboardId, panel.id, reportPanelIssue]);
|
|
166
210
|
useEffect(() => {
|
|
167
211
|
const container = containerRef.current;
|
|
168
212
|
if (!container)
|
|
@@ -180,12 +224,6 @@ function DeckMapDashboardRenderer({ dashboard, panel, selectionName, }) {
|
|
|
180
224
|
observer.disconnect();
|
|
181
225
|
};
|
|
182
226
|
}, []);
|
|
183
|
-
const deckDatasets = useMemo(() => {
|
|
184
|
-
if (!mapConfig) {
|
|
185
|
-
return {};
|
|
186
|
-
}
|
|
187
|
-
return createDeckMapDashboardDatasets(mapConfig, datasetStates);
|
|
188
|
-
}, [datasetStates, mapConfig]);
|
|
189
227
|
const fitToData = mapConfig?.fitToData ?? null;
|
|
190
228
|
const fitToDataSource = useMemo(() => fitToData
|
|
191
229
|
? resolveDeckMapDashboardDatasetSource({
|
|
@@ -354,112 +392,41 @@ function DeckMapDashboardRenderer({ dashboard, panel, selectionName, }) {
|
|
|
354
392
|
};
|
|
355
393
|
});
|
|
356
394
|
}, [didAutoFit, fitStateKey, fitToData, viewState]);
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
}
|
|
364
|
-
const datasetErrors = Object.entries(datasetStates).filter(([, state]) => state.error);
|
|
365
|
-
const interactionEvent = mapConfig.interaction?.event ?? 'hover';
|
|
366
|
-
const interactionDeckProps = mapConfig.interaction
|
|
367
|
-
? interactionEvent === 'click'
|
|
368
|
-
? { onClick: handleBrushEvent }
|
|
369
|
-
: { onHover: handleBrushEvent }
|
|
370
|
-
: {};
|
|
371
|
-
return (_jsxs("div", { ref: containerRef, className: "relative h-full w-full", children: [datasetEntries.map(([datasetId, dataset]) => (_jsx(DeckMapDashboardDatasetClient, { dashboard: dashboard, dataset: dataset, datasetId: datasetId, panel: panel, onDatasetState: handleDatasetState, selectionName: selectionName }, datasetId))), datasetErrors.length ? (_jsx("div", { className: "bg-background/90 text-destructive absolute inset-x-4 top-4 z-10 rounded-md border p-3 text-sm shadow", children: datasetErrors.map(([datasetId, state]) => (_jsxs("div", { children: ["Failed to load dataset \"", datasetId, "\":", ' ', state.error?.message] }, datasetId))) })) : null, _jsx(DeckJsonMap, { className: "h-full w-full", spec: mapConfig.spec, datasets: deckDatasets, mapStyle: mapConfig.mapStyle, mapProps: mapConfig.mapProps, showLegends: mapConfig.showLegends, deckProps: {
|
|
395
|
+
const settingsContent = (_jsx(MapSettingsPanel, { dashboardId: dashboardId, panel: panel, onClose: () => handleSettingsOpenChange(false) }));
|
|
396
|
+
const mapContent = !mapConfig ? (_jsx("div", { className: "text-muted-foreground flex h-full items-center justify-center p-4 text-sm", children: "Invalid map panel config." })) : issue ? (_jsx(DeckMapRuntimeIssuePanel, { issue: issue })) : Object.entries(mapConfig.datasets).length === 0 ? (_jsx("div", { className: "text-muted-foreground flex h-full items-center justify-center p-4 text-sm", children: "Map panels require at least one dataset." })) : (_jsxs("div", { ref: containerRef, className: "relative h-full w-full", children: [Object.entries(mapConfig.datasets).map(([datasetId, dataset]) => (_jsx(DeckMapDashboardDatasetClient, { dashboard: dashboard, dataset: dataset, datasetId: datasetId, dataPolicy: dataPolicy, panel: panel, onDatasetState: handleDatasetState, runtimeIssueContext: runtimeIssueContext, runtimeIssueReporter: runtimeIssueReporter, selectionName: selectionName }, datasetId))), Object.entries(datasetStates)
|
|
397
|
+
.filter(([, state]) => state.error)
|
|
398
|
+
.map(([datasetId, state]) => (_jsxs("div", { className: "bg-background/90 text-destructive absolute inset-x-4 top-4 z-10 rounded-md border p-3 text-sm shadow", children: ["Failed to load dataset \"", datasetId, "\":", ' ', state.error?.message] }, datasetId))), _jsx(DeckJsonMap, { className: "h-full w-full", spec: mapConfig.spec, datasets: mapConfig
|
|
399
|
+
? createDeckMapDashboardDatasets(mapConfig, datasetStates)
|
|
400
|
+
: {}, mapStyle: mapConfig.mapStyle, mapProps: mapConfig.mapProps, showLegends: mapConfig.showLegends, deckProps: {
|
|
372
401
|
controller: true,
|
|
373
402
|
...(viewState ? { viewState } : {}),
|
|
374
403
|
onViewStateChange: handleViewStateChange,
|
|
375
|
-
...
|
|
404
|
+
...(mapConfig.interaction
|
|
405
|
+
? (mapConfig.interaction.event ?? 'hover') === 'click'
|
|
406
|
+
? { onClick: handleBrushEvent }
|
|
407
|
+
: { onHover: handleBrushEvent }
|
|
408
|
+
: {}),
|
|
376
409
|
} })] }));
|
|
410
|
+
return (_jsx("div", { className: "h-full min-h-0", children: _jsx(MosaicDashboardPanelLayout, { isOpen: isSettingsOpen, onIsOpenChange: handleSettingsOpenChange, settings: settingsContent, content: mapContent }) }));
|
|
377
411
|
}
|
|
378
412
|
export const deckMapDashboardPanelRenderer = {
|
|
379
413
|
component: DeckMapDashboardRenderer,
|
|
380
414
|
headerActions: DeckMapDashboardHeaderActions,
|
|
381
415
|
icon: MapIcon,
|
|
382
416
|
};
|
|
383
|
-
const LONGITUDE_COLUMN_NAMES = ['longitude', 'lon', 'lng', 'long', 'x'];
|
|
384
|
-
const LATITUDE_COLUMN_NAMES = ['latitude', 'lat', 'y'];
|
|
385
|
-
function findColumnByName(table, candidates) {
|
|
386
|
-
const candidateSet = new Set(candidates);
|
|
387
|
-
return table.columns.find((column) => candidateSet.has(column.name.toLowerCase()))?.name;
|
|
388
|
-
}
|
|
389
|
-
function findLongitudeLatitudeColumns(table) {
|
|
390
|
-
if (!table)
|
|
391
|
-
return null;
|
|
392
|
-
const longitudeColumn = findColumnByName(table, LONGITUDE_COLUMN_NAMES);
|
|
393
|
-
const latitudeColumn = findColumnByName(table, LATITUDE_COLUMN_NAMES);
|
|
394
|
-
return longitudeColumn && latitudeColumn
|
|
395
|
-
? { longitudeColumn, latitudeColumn }
|
|
396
|
-
: null;
|
|
397
|
-
}
|
|
398
|
-
function quoteSqlIdentifier(identifier) {
|
|
399
|
-
return `"${identifier.replace(/"/g, '""')}"`;
|
|
400
|
-
}
|
|
401
|
-
function quoteTableReference(table) {
|
|
402
|
-
const qualifiedName = table.table;
|
|
403
|
-
return [qualifiedName.database, qualifiedName.schema, qualifiedName.table]
|
|
404
|
-
.filter((part) => Boolean(part))
|
|
405
|
-
.map(quoteSqlIdentifier)
|
|
406
|
-
.join('.');
|
|
407
|
-
}
|
|
408
|
-
function createDeckMapPanelForTable(table) {
|
|
409
|
-
const coordinates = findLongitudeLatitudeColumns(table);
|
|
410
|
-
if (!coordinates)
|
|
411
|
-
return undefined;
|
|
412
|
-
const { longitudeColumn, latitudeColumn } = coordinates;
|
|
413
|
-
const datasetId = table.tableName;
|
|
414
|
-
const geometryColumn = '__sqlrooms_geom';
|
|
415
|
-
const quotedLongitude = quoteSqlIdentifier(longitudeColumn);
|
|
416
|
-
const quotedLatitude = quoteSqlIdentifier(latitudeColumn);
|
|
417
|
-
return createDeckMapDashboardPanelConfig({
|
|
418
|
-
title: `${table.tableName} map`,
|
|
419
|
-
source: { tableName: table.tableName },
|
|
420
|
-
spec: {
|
|
421
|
-
initialViewState: { longitude: 0, latitude: 20, zoom: 1.5 },
|
|
422
|
-
layers: [
|
|
423
|
-
{
|
|
424
|
-
'@@type': 'GeoArrowScatterplotLayer',
|
|
425
|
-
id: datasetId,
|
|
426
|
-
_sqlroomsBinding: { dataset: datasetId },
|
|
427
|
-
filled: true,
|
|
428
|
-
stroked: false,
|
|
429
|
-
pickable: true,
|
|
430
|
-
radiusUnits: 'pixels',
|
|
431
|
-
getRadius: 4,
|
|
432
|
-
getFillColor: [56, 189, 248, 180],
|
|
433
|
-
},
|
|
434
|
-
],
|
|
435
|
-
},
|
|
436
|
-
datasets: {
|
|
437
|
-
[datasetId]: {
|
|
438
|
-
source: {
|
|
439
|
-
sqlQuery: [
|
|
440
|
-
`SELECT *, ST_AsWKB(ST_Point(${quotedLongitude}, ${quotedLatitude})) AS ${quoteSqlIdentifier(geometryColumn)}`,
|
|
441
|
-
`FROM ${quoteTableReference(table)}`,
|
|
442
|
-
`WHERE ${quotedLongitude} IS NOT NULL AND ${quotedLatitude} IS NOT NULL`,
|
|
443
|
-
].join(' '),
|
|
444
|
-
},
|
|
445
|
-
geometryColumn,
|
|
446
|
-
geometryEncodingHint: 'wkb',
|
|
447
|
-
},
|
|
448
|
-
},
|
|
449
|
-
fitToData: {
|
|
450
|
-
dataset: datasetId,
|
|
451
|
-
longitudeColumn,
|
|
452
|
-
latitudeColumn,
|
|
453
|
-
padding: 40,
|
|
454
|
-
maxZoom: 12,
|
|
455
|
-
},
|
|
456
|
-
});
|
|
457
|
-
}
|
|
458
417
|
export const deckMapDashboardAddPanelAction = {
|
|
459
418
|
type: DECK_MAP_DASHBOARD_PANEL_TYPE,
|
|
460
419
|
label: 'Map',
|
|
461
420
|
icon: MapIcon,
|
|
462
|
-
isEnabled: ({ selectedTable }) => Boolean(findLongitudeLatitudeColumns(selectedTable)
|
|
463
|
-
|
|
421
|
+
isEnabled: ({ selectedTable }) => Boolean(findLongitudeLatitudeColumns(selectedTable) ??
|
|
422
|
+
findGeometryColumn(selectedTable)),
|
|
423
|
+
createPanel: ({ selectedTable }) => selectedTable
|
|
424
|
+
? createDeckMapDashboardPanelConfigForTable({
|
|
425
|
+
title: `${selectedTable.tableName} map`,
|
|
426
|
+
tableName: selectedTable.tableName,
|
|
427
|
+
columns: selectedTable.columns,
|
|
428
|
+
tableReference: selectedTable.table,
|
|
429
|
+
})
|
|
430
|
+
: undefined,
|
|
464
431
|
};
|
|
465
432
|
//# sourceMappingURL=dashboard.js.map
|
package/dist/dashboard.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dashboard.js","sourceRoot":"","sources":["../src/dashboard.tsx"],"names":[],"mappings":"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","sourcesContent":["import {WebMercatorViewport} from '@deck.gl/core';\nimport type {ComponentProps} from 'react';\nimport type DeckGLReact from '@deck.gl/react';\n\ntype DeckProps = ComponentProps<typeof DeckGLReact>;\nimport {\n escapeId,\n getColValAsNumber,\n useStoreWithDuckDb,\n type DataTable,\n} from '@sqlrooms/duckdb';\nimport {\n column,\n type MosaicDashboardEntryType,\n type MosaicDashboardPanelConfigType,\n type MosaicDashboardPanelRenderer,\n type MosaicDashboardPanelRendererProps,\n sql,\n useMosaicClient,\n useStoreWithMosaicDashboard,\n} from '@sqlrooms/mosaic';\nimport {Button} from '@sqlrooms/ui';\nimport type {MosaicClient} from '@uwdata/mosaic-core';\nimport type {Selection} from '@uwdata/mosaic-core';\nimport type {Table as ArrowTable} from 'apache-arrow';\nimport {FocusIcon, MapIcon} from 'lucide-react';\nimport {useCallback, useEffect, useMemo, useRef, useState} from 'react';\nimport {DeckMapConfigPopoverEditor} from './DeckMapConfigPopoverEditor';\nimport {DeckJsonMap} from './DeckJsonMap';\nimport type {DeckJsonMapProps} from './types';\nimport {\n asDeckJsonMapConfig,\n createDeckMapDashboardDatasetQuery,\n createDeckMapDashboardDatasets,\n createDeckMapDashboardPanelConfig,\n DECK_MAP_DASHBOARD_PANEL_TYPE,\n resolveDeckMapDashboardDatasetSource,\n type DeckMapDashboardFitToDataConfig,\n type DeckMapDashboardDatasetClientState,\n type DeckMapDashboardDatasetConfig,\n type DeckMapDashboardInteractionConfig,\n} from './dashboardConfig';\n\nfunction DeckMapDashboardDatasetClient({\n dashboard,\n dataset,\n datasetId,\n panel,\n onDatasetState,\n selectionName,\n}: {\n dashboard: MosaicDashboardEntryType;\n dataset: DeckMapDashboardDatasetConfig;\n datasetId: string;\n panel: MosaicDashboardPanelConfigType;\n onDatasetState: (\n datasetId: string,\n state: DeckMapDashboardDatasetClientState | undefined,\n ) => void;\n selectionName: string;\n}) {\n const source = useMemo(\n () =>\n resolveDeckMapDashboardDatasetSource({\n dashboard,\n panel,\n dataset,\n }),\n [dashboard, dataset, panel],\n );\n const query = useCallback(\n (filter: unknown) =>\n source\n ? createDeckMapDashboardDatasetQuery(source, filter)\n : createDeckMapDashboardDatasetQuery(\n {tableName: '__missing_dashboard_map_dataset__'},\n filter,\n ),\n [source],\n );\n const {data, error, isLoading, client} = useMosaicClient({\n id: `${panel.id}:${datasetId}`,\n selectionName,\n query,\n enabled: Boolean(source),\n });\n\n useEffect(() => {\n onDatasetState(datasetId, {\n arrowTable: data ?? undefined,\n error,\n isLoading,\n client,\n });\n\n return () => {\n onDatasetState(datasetId, undefined);\n };\n }, [client, data, datasetId, error, isLoading, onDatasetState]);\n\n return null;\n}\n\nfunction createPointRadiusPredicate(\n interaction: DeckMapDashboardInteractionConfig,\n coordinate: [number, number],\n) {\n const [longitude, latitude] = coordinate;\n const radiusMeters = interaction.radiusMeters ?? 500;\n const metersPerDegree = 111_320;\n const cosLatitude = Math.cos(latitude * (Math.PI / 180));\n const radiusSquared = radiusMeters * radiusMeters;\n\n return sql`(\n pow((${column(interaction.longitudeColumn)} - ${longitude}) * ${\n cosLatitude * metersPerDegree\n }, 2) +\n pow((${column(interaction.latitudeColumn)} - ${latitude}) * ${\n metersPerDegree\n }, 2)\n ) < ${radiusSquared}`;\n}\n\ntype DeckMapInteractionEvent = {\n coordinate?: number[] | null;\n object?: unknown;\n index?: number;\n picked?: boolean;\n};\n\nfunction getCoordinate(\n info: DeckMapInteractionEvent,\n): [number, number] | undefined {\n return info.coordinate && info.coordinate.length >= 2\n ? [info.coordinate[0]!, info.coordinate[1]!]\n : undefined;\n}\n\nfunction isPickedMapFeature(info: DeckMapInteractionEvent) {\n return Boolean(info.picked || info.object || (info.index ?? -1) >= 0);\n}\n\nfunction createDeckMapBoundsQuery(options: {\n source: {tableName?: string; sqlQuery?: string};\n fitToData: DeckMapDashboardFitToDataConfig;\n}) {\n const {source, fitToData} = options;\n const baseSourceSql = source.sqlQuery\n ? `SELECT * FROM (${source.sqlQuery}) AS \"__sqlrooms_dashboard_map_source\"`\n : `SELECT * FROM ${(source.tableName ?? '')\n .split('.')\n .map(escapeId)\n .join('.')}`;\n const longitudeColumn = escapeId(fitToData.longitudeColumn);\n const latitudeColumn = escapeId(fitToData.latitudeColumn);\n\n return `\n SELECT\n ST_XMin(extent) AS min_longitude,\n ST_YMin(extent) AS min_latitude,\n ST_XMax(extent) AS max_longitude,\n ST_YMax(extent) AS max_latitude\n FROM (\n SELECT ST_Extent_Agg(ST_Point(${longitudeColumn}, ${latitudeColumn})) AS extent\n FROM (${baseSourceSql}) AS \"__sqlrooms_dashboard_map_points\"\n WHERE ${longitudeColumn} IS NOT NULL AND ${latitudeColumn} IS NOT NULL\n ) AS \"__sqlrooms_dashboard_map_extent\"\n WHERE extent IS NOT NULL\n `;\n}\n\nfunction readBoundsFromExtentResult(result: ArrowTable) {\n const minLongitude = getColValAsNumber(result, 'min_longitude');\n const minLatitude = getColValAsNumber(result, 'min_latitude');\n const maxLongitude = getColValAsNumber(result, 'max_longitude');\n const maxLatitude = getColValAsNumber(result, 'max_latitude');\n if (\n !Number.isFinite(minLongitude) ||\n !Number.isFinite(minLatitude) ||\n !Number.isFinite(maxLongitude) ||\n !Number.isFinite(maxLatitude)\n ) {\n return null;\n }\n\n return [\n [\n minLongitude === maxLongitude ? minLongitude - 0.01 : minLongitude,\n minLatitude === maxLatitude ? minLatitude - 0.01 : minLatitude,\n ],\n [\n minLongitude === maxLongitude ? maxLongitude + 0.01 : maxLongitude,\n minLatitude === maxLatitude ? maxLatitude + 0.01 : maxLatitude,\n ],\n ] as const;\n}\n\nfunction fitViewStateToBounds(options: {\n bounds: readonly [readonly [number, number], readonly [number, number]];\n width: number;\n height: number;\n padding?: number;\n maxZoom?: number;\n}) {\n const {bounds, width, height, padding = 40, maxZoom = 12} = options;\n const viewport = new WebMercatorViewport({\n width: Math.max(width, 1),\n height: Math.max(height, 1),\n });\n const fitted = viewport.fitBounds(\n [\n [bounds[0][0], bounds[0][1]],\n [bounds[1][0], bounds[1][1]],\n ],\n {padding},\n ) as WebMercatorViewport & {\n longitude: number;\n latitude: number;\n zoom: number;\n };\n\n return {\n longitude: fitted.longitude,\n latitude: fitted.latitude,\n zoom: Math.min(fitted.zoom, maxZoom),\n };\n}\n\nconst deckMapDashboardFitRequestTarget = new EventTarget();\n\nfunction emitDeckMapDashboardFitRequest(panelId: string) {\n deckMapDashboardFitRequestTarget.dispatchEvent(\n new CustomEvent('fit-view', {detail: {panelId}}),\n );\n}\n\ntype DeckMapDashboardFitState = {\n key: string;\n viewState: DeckProps['viewState'];\n didAutoFit: boolean;\n fitRequestVersion: number;\n handledFitRequestVersion: number;\n};\n\nfunction createInitialDeckMapDashboardFitState(\n key: string,\n): DeckMapDashboardFitState {\n return {\n key,\n viewState: undefined,\n didAutoFit: false,\n fitRequestVersion: 0,\n handledFitRequestVersion: 0,\n };\n}\n\nfunction DeckMapDashboardHeaderActions({\n dashboardId,\n panel,\n}: MosaicDashboardPanelRendererProps) {\n const updatePanel = useStoreWithMosaicDashboard(\n (state) => state.mosaicDashboard.updatePanel,\n );\n const mapConfig = asDeckJsonMapConfig(panel.config);\n const canFitView = Boolean(mapConfig?.fitToData);\n const handleConfigApply = useCallback(\n (nextConfig: Record<string, unknown>) => {\n updatePanel(dashboardId, panel.id, {\n config: nextConfig,\n });\n },\n [dashboardId, panel.id, updatePanel],\n );\n\n return (\n <div className=\"flex items-center gap-0.5\">\n <DeckMapConfigPopoverEditor\n value={panel.config}\n onApply={handleConfigApply}\n />\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-6 w-6\"\n title={\n canFitView\n ? 'Fit map view to data'\n : 'Fit view unavailable for this map'\n }\n disabled={!canFitView}\n onClick={() => emitDeckMapDashboardFitRequest(panel.id)}\n >\n <FocusIcon className=\"h-3.5 w-3.5\" />\n </Button>\n </div>\n );\n}\n\nfunction DeckMapDashboardRenderer({\n dashboard,\n panel,\n selectionName,\n}: MosaicDashboardPanelRendererProps) {\n const mapConfig = asDeckJsonMapConfig(panel.config);\n const getSelection = useStoreWithMosaicDashboard(\n (state) => state.mosaic.getSelection,\n );\n const executeSql = useStoreWithDuckDb((state) => state.db.executeSql);\n const selection = useMemo<Selection>(\n () => getSelection(selectionName, 'crossfilter'),\n [getSelection, selectionName],\n );\n const containerRef = useRef<HTMLDivElement | null>(null);\n const [datasetStates, setDatasetStates] = useState<\n Record<string, DeckMapDashboardDatasetClientState>\n >({});\n const [containerSize, setContainerSize] = useState({width: 0, height: 0});\n\n const handleDatasetState = useCallback(\n (\n datasetId: string,\n state: DeckMapDashboardDatasetClientState | undefined,\n ) => {\n setDatasetStates((current) => {\n const next = {...current};\n if (state) {\n next[datasetId] = state;\n } else {\n delete next[datasetId];\n }\n return next;\n });\n },\n [],\n );\n\n useEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n\n const updateSize = () => {\n setContainerSize({\n width: container.clientWidth,\n height: container.clientHeight,\n });\n };\n\n updateSize();\n const observer = new ResizeObserver(updateSize);\n observer.observe(container);\n\n return () => {\n observer.disconnect();\n };\n }, []);\n\n const deckDatasets = useMemo<DeckJsonMapProps['datasets']>(() => {\n if (!mapConfig) {\n return {};\n }\n\n return createDeckMapDashboardDatasets(mapConfig, datasetStates);\n }, [datasetStates, mapConfig]);\n const fitToData = mapConfig?.fitToData ?? null;\n const fitToDataSource = useMemo(\n () =>\n fitToData\n ? resolveDeckMapDashboardDatasetSource({\n dashboard,\n panel,\n dataset: mapConfig?.datasets[fitToData.dataset],\n })\n : undefined,\n [dashboard, fitToData, mapConfig?.datasets, panel],\n );\n const fitToDataKey = useMemo(\n () =>\n fitToData && fitToDataSource\n ? JSON.stringify({\n source: fitToDataSource,\n fitToData,\n })\n : null,\n [fitToData, fitToDataSource],\n );\n const fitStateKey = useMemo(\n () => JSON.stringify({panelId: panel.id, fitToDataKey}),\n [fitToDataKey, panel.id],\n );\n const [fitState, setFitState] = useState<DeckMapDashboardFitState>(() =>\n createInitialDeckMapDashboardFitState(fitStateKey),\n );\n const activeFitState =\n fitState.key === fitStateKey\n ? fitState\n : createInitialDeckMapDashboardFitState(fitStateKey);\n const {didAutoFit, fitRequestVersion, handledFitRequestVersion, viewState} =\n activeFitState;\n\n useEffect(() => {\n const handleFitRequest = (event: Event) => {\n const detail = (event as CustomEvent<{panelId?: string}>).detail;\n if (detail?.panelId === panel.id) {\n setFitState((current) => {\n const scoped =\n current.key === fitStateKey\n ? current\n : createInitialDeckMapDashboardFitState(fitStateKey);\n return {\n ...scoped,\n fitRequestVersion: scoped.fitRequestVersion + 1,\n };\n });\n }\n };\n\n deckMapDashboardFitRequestTarget.addEventListener(\n 'fit-view',\n handleFitRequest,\n );\n return () => {\n deckMapDashboardFitRequestTarget.removeEventListener(\n 'fit-view',\n handleFitRequest,\n );\n };\n }, [fitStateKey, panel.id]);\n\n useEffect(() => {\n const hasManualFitRequest = fitRequestVersion > handledFitRequestVersion;\n if (\n !fitToData ||\n !fitToDataSource ||\n containerSize.width <= 0 ||\n containerSize.height <= 0 ||\n (!hasManualFitRequest && didAutoFit)\n ) {\n return;\n }\n\n let isCancelled = false;\n\n const fitToDataBounds = async () => {\n try {\n const handle = await executeSql(\n createDeckMapBoundsQuery({\n source: fitToDataSource,\n fitToData,\n }),\n );\n const result = handle ? await handle : null;\n if (isCancelled || !result) {\n return;\n }\n\n const bounds = readBoundsFromExtentResult(result);\n if (!bounds) {\n setFitState((current) => {\n const scoped =\n current.key === fitStateKey\n ? current\n : createInitialDeckMapDashboardFitState(fitStateKey);\n return {\n ...scoped,\n didAutoFit: true,\n handledFitRequestVersion: fitRequestVersion,\n };\n });\n return;\n }\n\n const nextViewState = fitViewStateToBounds({\n bounds,\n width: containerSize.width,\n height: containerSize.height,\n padding: fitToData.padding,\n maxZoom: fitToData.maxZoom,\n });\n setFitState((current) => {\n const scoped =\n current.key === fitStateKey\n ? current\n : createInitialDeckMapDashboardFitState(fitStateKey);\n return {\n ...scoped,\n viewState: nextViewState,\n didAutoFit: true,\n handledFitRequestVersion: fitRequestVersion,\n };\n });\n } catch {\n if (!isCancelled) {\n setFitState((current) => {\n const scoped =\n current.key === fitStateKey\n ? current\n : createInitialDeckMapDashboardFitState(fitStateKey);\n return {\n ...scoped,\n didAutoFit: true,\n handledFitRequestVersion: fitRequestVersion,\n };\n });\n }\n }\n };\n\n void fitToDataBounds();\n\n return () => {\n isCancelled = true;\n };\n }, [\n containerSize.height,\n containerSize.width,\n didAutoFit,\n executeSql,\n fitRequestVersion,\n fitStateKey,\n fitToData,\n fitToDataSource,\n handledFitRequestVersion,\n ]);\n\n const handleBrushEvent = useCallback(\n (info: DeckMapInteractionEvent) => {\n const interaction = mapConfig?.interaction;\n if (!interaction) {\n return;\n }\n\n const client = datasetStates[interaction.dataset]?.client as\n | MosaicClient\n | null\n | undefined;\n if (!client) {\n return;\n }\n const coordinate = getCoordinate(info);\n if (!coordinate) {\n return;\n }\n if (interaction.event !== 'click' && !isPickedMapFeature(info)) {\n selection.reset(\n selection.clauses.filter((clause) => clause.source === client),\n );\n return;\n }\n\n const radiusMeters = interaction.radiusMeters ?? 500;\n selection.update({\n source: client,\n clients: new Set([client]),\n value: [coordinate[0], coordinate[1], radiusMeters],\n predicate: createPointRadiusPredicate(interaction, coordinate),\n });\n },\n [datasetStates, mapConfig?.interaction, selection],\n );\n\n const handleViewStateChange = useCallback(\n ({\n viewState: nextViewState,\n interactionState,\n }: {\n viewState: any;\n interactionState?: any;\n }) => {\n const hasUserInteraction = Boolean(\n interactionState &&\n ['isDragging', 'isPanning', 'isRotating', 'isZooming'].some((key) =>\n Boolean(interactionState[key]),\n ),\n );\n if (\n fitToData &&\n !didAutoFit &&\n viewState === null &&\n !hasUserInteraction\n ) {\n return;\n }\n\n setFitState((current) => {\n const scoped =\n current.key === fitStateKey\n ? current\n : createInitialDeckMapDashboardFitState(fitStateKey);\n return {\n ...scoped,\n viewState: nextViewState,\n didAutoFit: hasUserInteraction || scoped.didAutoFit || !fitToData,\n };\n });\n },\n [didAutoFit, fitStateKey, fitToData, viewState],\n );\n\n if (!mapConfig) {\n return (\n <div className=\"text-muted-foreground flex h-full items-center justify-center p-4 text-sm\">\n Invalid map panel config.\n </div>\n );\n }\n\n const datasetEntries = Object.entries(mapConfig.datasets);\n if (!datasetEntries.length) {\n return (\n <div className=\"text-muted-foreground flex h-full items-center justify-center p-4 text-sm\">\n Map panels require at least one dataset.\n </div>\n );\n }\n const datasetErrors = Object.entries(datasetStates).filter(\n ([, state]) => state.error,\n );\n\n const interactionEvent = mapConfig.interaction?.event ?? 'hover';\n const interactionDeckProps: DeckJsonMapProps['deckProps'] =\n mapConfig.interaction\n ? interactionEvent === 'click'\n ? {onClick: handleBrushEvent}\n : {onHover: handleBrushEvent}\n : {};\n\n return (\n <div ref={containerRef} className=\"relative h-full w-full\">\n {datasetEntries.map(([datasetId, dataset]) => (\n <DeckMapDashboardDatasetClient\n key={datasetId}\n dashboard={dashboard}\n dataset={dataset}\n datasetId={datasetId}\n panel={panel}\n onDatasetState={handleDatasetState}\n selectionName={selectionName}\n />\n ))}\n {datasetErrors.length ? (\n <div className=\"bg-background/90 text-destructive absolute inset-x-4 top-4 z-10 rounded-md border p-3 text-sm shadow\">\n {datasetErrors.map(([datasetId, state]) => (\n <div key={datasetId}>\n Failed to load dataset "{datasetId}":{' '}\n {state.error?.message}\n </div>\n ))}\n </div>\n ) : null}\n <DeckJsonMap\n className=\"h-full w-full\"\n spec={mapConfig.spec}\n datasets={deckDatasets}\n mapStyle={mapConfig.mapStyle}\n mapProps={mapConfig.mapProps}\n showLegends={mapConfig.showLegends}\n deckProps={{\n controller: true,\n ...(viewState ? {viewState} : {}),\n onViewStateChange: handleViewStateChange,\n ...interactionDeckProps,\n }}\n />\n </div>\n );\n}\n\nexport const deckMapDashboardPanelRenderer: MosaicDashboardPanelRenderer = {\n component: DeckMapDashboardRenderer,\n headerActions: DeckMapDashboardHeaderActions,\n icon: MapIcon,\n};\n\nconst LONGITUDE_COLUMN_NAMES = ['longitude', 'lon', 'lng', 'long', 'x'];\nconst LATITUDE_COLUMN_NAMES = ['latitude', 'lat', 'y'];\n\nfunction findColumnByName(table: DataTable, candidates: string[]) {\n const candidateSet = new Set(candidates);\n return table.columns.find((column) =>\n candidateSet.has(column.name.toLowerCase()),\n )?.name;\n}\n\nfunction findLongitudeLatitudeColumns(table?: DataTable) {\n if (!table) return null;\n const longitudeColumn = findColumnByName(table, LONGITUDE_COLUMN_NAMES);\n const latitudeColumn = findColumnByName(table, LATITUDE_COLUMN_NAMES);\n return longitudeColumn && latitudeColumn\n ? {longitudeColumn, latitudeColumn}\n : null;\n}\n\nfunction quoteSqlIdentifier(identifier: string) {\n return `\"${identifier.replace(/\"/g, '\"\"')}\"`;\n}\n\nfunction quoteTableReference(table: DataTable) {\n const qualifiedName = table.table;\n return [qualifiedName.database, qualifiedName.schema, qualifiedName.table]\n .filter((part): part is string => Boolean(part))\n .map(quoteSqlIdentifier)\n .join('.');\n}\n\nfunction createDeckMapPanelForTable(table: DataTable) {\n const coordinates = findLongitudeLatitudeColumns(table);\n if (!coordinates) return undefined;\n\n const {longitudeColumn, latitudeColumn} = coordinates;\n const datasetId = table.tableName;\n const geometryColumn = '__sqlrooms_geom';\n const quotedLongitude = quoteSqlIdentifier(longitudeColumn);\n const quotedLatitude = quoteSqlIdentifier(latitudeColumn);\n\n return createDeckMapDashboardPanelConfig({\n title: `${table.tableName} map`,\n source: {tableName: table.tableName},\n spec: {\n initialViewState: {longitude: 0, latitude: 20, zoom: 1.5},\n layers: [\n {\n '@@type': 'GeoArrowScatterplotLayer',\n id: datasetId,\n _sqlroomsBinding: {dataset: datasetId},\n filled: true,\n stroked: false,\n pickable: true,\n radiusUnits: 'pixels',\n getRadius: 4,\n getFillColor: [56, 189, 248, 180],\n },\n ],\n },\n datasets: {\n [datasetId]: {\n source: {\n sqlQuery: [\n `SELECT *, ST_AsWKB(ST_Point(${quotedLongitude}, ${quotedLatitude})) AS ${quoteSqlIdentifier(geometryColumn)}`,\n `FROM ${quoteTableReference(table)}`,\n `WHERE ${quotedLongitude} IS NOT NULL AND ${quotedLatitude} IS NOT NULL`,\n ].join(' '),\n },\n geometryColumn,\n geometryEncodingHint: 'wkb',\n },\n },\n fitToData: {\n dataset: datasetId,\n longitudeColumn,\n latitudeColumn,\n padding: 40,\n maxZoom: 12,\n },\n });\n}\n\nexport const deckMapDashboardAddPanelAction: import('@sqlrooms/mosaic').MosaicDashboardAddPanelAction =\n {\n type: DECK_MAP_DASHBOARD_PANEL_TYPE,\n label: 'Map',\n icon: MapIcon,\n isEnabled: ({selectedTable}) =>\n Boolean(findLongitudeLatitudeColumns(selectedTable)),\n createPanel: ({selectedTable}) =>\n selectedTable ? createDeckMapPanelForTable(selectedTable) : undefined,\n };\n"]}
|
|
1
|
+
{"version":3,"file":"dashboard.js","sourceRoot":"","sources":["../src/dashboard.tsx"],"names":[],"mappings":"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","sourcesContent":["import {WebMercatorViewport} from '@deck.gl/core';\nimport type {ComponentProps} from 'react';\nimport type DeckGLReact from '@deck.gl/react';\n\ntype DeckProps = ComponentProps<typeof DeckGLReact>;\nimport {\n escapeId,\n getColValAsNumber,\n useStoreWithDuckDb,\n} from '@sqlrooms/duckdb';\nimport {\n column,\n type MosaicDashboardEntryType,\n type MosaicDashboardPanelConfigType,\n type MosaicDashboardPanelRenderer,\n type MosaicDashboardPanelRendererProps,\n sql,\n type ChartDataPolicy,\n type ChartRuntimeIssue,\n type ChartRuntimeIssueContext,\n type ChartRuntimeIssueReporter,\n useMosaicClient,\n useStoreWithMosaicDashboard,\n} from '@sqlrooms/mosaic';\nimport {Button, Tooltip, TooltipContent, TooltipTrigger} from '@sqlrooms/ui';\nimport type {MosaicClient} from '@uwdata/mosaic-core';\nimport type {Selection} from '@uwdata/mosaic-core';\nimport type {Table as ArrowTable} from 'apache-arrow';\nimport {FocusIcon, MapIcon, SettingsIcon} from 'lucide-react';\nimport {useCallback, useEffect, useMemo, useRef, useState} from 'react';\nimport {DeckMapConfigPopoverEditor} from './DeckMapConfigPopoverEditor';\nimport {DeckJsonMap} from './DeckJsonMap';\nimport {MapSettingsPanel} from './MapSettings';\nimport {MosaicDashboardPanelLayout} from '@sqlrooms/mosaic';\nimport {\n asDeckJsonMapConfig,\n createDeckMapDashboardDatasetQuery,\n createDeckMapDashboardDatasets,\n DECK_MAP_DASHBOARD_PANEL_TYPE,\n resolveDeckMapDashboardDatasetSource,\n type DeckMapDashboardFitToDataConfig,\n type DeckMapDashboardDatasetClientState,\n type DeckMapDashboardDatasetConfig,\n type DeckMapDashboardInteractionConfig,\n type DeckMapDashboardPanelConfig,\n} from './dashboardConfig';\nimport {getDeckMapDataPolicy} from './mapDataPolicy';\nimport {\n createDeckMapDashboardPanelConfigForTable,\n findGeometryColumn,\n findLongitudeLatitudeColumns,\n} from './mapConfigUtils';\n\nfunction DeckMapRuntimeIssuePanel({issue}: {issue: ChartRuntimeIssue}) {\n const title =\n issue.kind === 'too-much-data'\n ? 'Too much data'\n : issue.kind === 'sql-error'\n ? 'Map query failed'\n : 'Unable to display map';\n\n return (\n <div className=\"flex h-full min-h-[200px] flex-col items-center justify-center p-4\">\n <div className=\"mb-2 text-center font-semibold\">{title}</div>\n <div className=\"text-center text-sm whitespace-pre-wrap\">\n {issue.message}\n </div>\n </div>\n );\n}\n\nfunction DeckMapDashboardDatasetClient({\n dashboard,\n dataset,\n datasetId,\n dataPolicy,\n panel,\n onDatasetState,\n runtimeIssueContext,\n runtimeIssueReporter,\n selectionName,\n}: {\n dashboard: MosaicDashboardEntryType;\n dataset: DeckMapDashboardDatasetConfig;\n datasetId: string;\n dataPolicy?: ChartDataPolicy | null;\n panel: MosaicDashboardPanelConfigType;\n onDatasetState: (\n datasetId: string,\n state: DeckMapDashboardDatasetClientState | undefined,\n ) => void;\n runtimeIssueContext?: ChartRuntimeIssueContext;\n runtimeIssueReporter?: ChartRuntimeIssueReporter;\n selectionName: string;\n}) {\n const source = useMemo(\n () =>\n resolveDeckMapDashboardDatasetSource({\n dashboard,\n panel,\n dataset,\n }),\n [dashboard, dataset, panel],\n );\n const query = useCallback(\n (filter: unknown) =>\n source\n ? createDeckMapDashboardDatasetQuery(source, filter)\n : createDeckMapDashboardDatasetQuery(\n {tableName: '__missing_dashboard_map_dataset__'},\n filter,\n ),\n [source],\n );\n const {data, error, isLoading, client} = useMosaicClient({\n id: `${panel.id}:${datasetId}`,\n selectionName,\n query,\n dataPolicy,\n enabled: Boolean(source),\n runtimeIssueContext,\n runtimeIssueReporter,\n });\n\n useEffect(() => {\n onDatasetState(datasetId, {\n arrowTable: data ?? undefined,\n error,\n isLoading,\n client,\n });\n\n return () => {\n onDatasetState(datasetId, undefined);\n };\n }, [client, data, datasetId, error, isLoading, onDatasetState]);\n\n return null;\n}\n\nfunction createPointRadiusPredicate(\n interaction: DeckMapDashboardInteractionConfig,\n coordinate: [number, number],\n) {\n const [longitude, latitude] = coordinate;\n const radiusMeters = interaction.radiusMeters ?? 500;\n const metersPerDegree = 111_320;\n const cosLatitude = Math.cos(latitude * (Math.PI / 180));\n const radiusSquared = radiusMeters * radiusMeters;\n\n return sql`(\n pow((${column(interaction.longitudeColumn)} - ${longitude}) * ${\n cosLatitude * metersPerDegree\n }, 2) +\n pow((${column(interaction.latitudeColumn)} - ${latitude}) * ${\n metersPerDegree\n }, 2)\n ) < ${radiusSquared}`;\n}\n\ntype DeckMapInteractionEvent = {\n coordinate?: number[] | null;\n object?: unknown;\n index?: number;\n picked?: boolean;\n};\n\nfunction getCoordinate(\n info: DeckMapInteractionEvent,\n): [number, number] | undefined {\n return info.coordinate && info.coordinate.length >= 2\n ? [info.coordinate[0]!, info.coordinate[1]!]\n : undefined;\n}\n\nfunction isPickedMapFeature(info: DeckMapInteractionEvent) {\n return Boolean(info.picked || info.object || (info.index ?? -1) >= 0);\n}\n\nfunction createDeckMapBoundsQuery(options: {\n source: {tableName?: string; sqlQuery?: string};\n fitToData: DeckMapDashboardFitToDataConfig;\n}) {\n const {source, fitToData} = options;\n const baseSourceSql = source.sqlQuery\n ? `SELECT * FROM (${source.sqlQuery}) AS \"__sqlrooms_dashboard_map_source\"`\n : `SELECT * FROM ${(source.tableName ?? '')\n .split('.')\n .map(escapeId)\n .join('.')}`;\n const longitudeColumn = escapeId(fitToData.longitudeColumn);\n const latitudeColumn = escapeId(fitToData.latitudeColumn);\n\n return `\n SELECT\n ST_XMin(extent) AS min_longitude,\n ST_YMin(extent) AS min_latitude,\n ST_XMax(extent) AS max_longitude,\n ST_YMax(extent) AS max_latitude\n FROM (\n SELECT ST_Extent_Agg(ST_Point(${longitudeColumn}, ${latitudeColumn})) AS extent\n FROM (${baseSourceSql}) AS \"__sqlrooms_dashboard_map_points\"\n WHERE ${longitudeColumn} IS NOT NULL AND ${latitudeColumn} IS NOT NULL\n ) AS \"__sqlrooms_dashboard_map_extent\"\n WHERE extent IS NOT NULL\n `;\n}\n\nfunction readBoundsFromExtentResult(result: ArrowTable) {\n const minLongitude = getColValAsNumber(result, 'min_longitude');\n const minLatitude = getColValAsNumber(result, 'min_latitude');\n const maxLongitude = getColValAsNumber(result, 'max_longitude');\n const maxLatitude = getColValAsNumber(result, 'max_latitude');\n if (\n !Number.isFinite(minLongitude) ||\n !Number.isFinite(minLatitude) ||\n !Number.isFinite(maxLongitude) ||\n !Number.isFinite(maxLatitude)\n ) {\n return null;\n }\n\n return [\n [\n minLongitude === maxLongitude ? minLongitude - 0.01 : minLongitude,\n minLatitude === maxLatitude ? minLatitude - 0.01 : minLatitude,\n ],\n [\n minLongitude === maxLongitude ? maxLongitude + 0.01 : maxLongitude,\n minLatitude === maxLatitude ? maxLatitude + 0.01 : maxLatitude,\n ],\n ] as const;\n}\n\nfunction fitViewStateToBounds(options: {\n bounds: readonly [readonly [number, number], readonly [number, number]];\n width: number;\n height: number;\n padding?: number;\n maxZoom?: number;\n}) {\n const {bounds, width, height, padding = 40, maxZoom = 12} = options;\n const viewport = new WebMercatorViewport({\n width: Math.max(width, 1),\n height: Math.max(height, 1),\n });\n const fitted = viewport.fitBounds(\n [\n [bounds[0][0], bounds[0][1]],\n [bounds[1][0], bounds[1][1]],\n ],\n {padding},\n ) as WebMercatorViewport & {\n longitude: number;\n latitude: number;\n zoom: number;\n };\n\n return {\n longitude: fitted.longitude,\n latitude: fitted.latitude,\n zoom: Math.min(fitted.zoom, maxZoom),\n };\n}\n\nconst deckMapDashboardFitRequestTarget = new EventTarget();\n\nfunction emitDeckMapDashboardFitRequest(panelId: string) {\n deckMapDashboardFitRequestTarget.dispatchEvent(\n new CustomEvent('fit-view', {detail: {panelId}}),\n );\n}\n\ntype DeckMapDashboardFitState = {\n key: string;\n viewState: DeckProps['viewState'];\n didAutoFit: boolean;\n fitRequestVersion: number;\n handledFitRequestVersion: number;\n};\n\nfunction createInitialDeckMapDashboardFitState(\n key: string,\n): DeckMapDashboardFitState {\n return {\n key,\n viewState: undefined,\n didAutoFit: false,\n fitRequestVersion: 0,\n handledFitRequestVersion: 0,\n };\n}\n\nfunction DeckMapDashboardHeaderActions({\n dashboardId,\n panel,\n}: MosaicDashboardPanelRendererProps) {\n const updatePanel = useStoreWithMosaicDashboard(\n (state) => state.mosaicDashboard.updatePanel,\n );\n const mapConfig = asDeckJsonMapConfig(panel.config);\n const canFitView = Boolean(mapConfig?.fitToData);\n\n const isSettingsOpen = Boolean(mapConfig?.settingsOpen);\n\n const handleConfigApply = useCallback(\n (nextConfig: Record<string, unknown>) => {\n updatePanel(dashboardId, panel.id, {\n config: nextConfig,\n });\n },\n [dashboardId, panel.id, updatePanel],\n );\n\n const handleToggleSettings = useCallback(() => {\n updatePanel(dashboardId, panel.id, {\n config: {...panel.config, settingsOpen: !isSettingsOpen},\n });\n }, [dashboardId, isSettingsOpen, panel.config, panel.id, updatePanel]);\n\n return (\n <div className=\"flex items-center gap-0.5\">\n <Tooltip>\n <TooltipTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"data-[state=active]:bg-accent h-6 w-6\"\n title=\"Map settings\"\n onClick={handleToggleSettings}\n data-state={isSettingsOpen ? 'active' : 'inactive'}\n >\n <SettingsIcon className=\"h-3.5 w-3.5\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>Map settings</TooltipContent>\n </Tooltip>\n <DeckMapConfigPopoverEditor\n value={panel.config}\n onApply={handleConfigApply}\n />\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-6 w-6\"\n title={\n canFitView\n ? 'Fit map view to data'\n : 'Fit view unavailable for this map'\n }\n disabled={!canFitView}\n onClick={() => emitDeckMapDashboardFitRequest(panel.id)}\n >\n <FocusIcon className=\"h-3.5 w-3.5\" />\n </Button>\n </div>\n );\n}\n\nfunction DeckMapDashboardRenderer({\n dashboard,\n dashboardId,\n panel,\n selectionName,\n}: MosaicDashboardPanelRendererProps) {\n const mapConfig = asDeckJsonMapConfig(panel.config);\n const getSelection = useStoreWithMosaicDashboard(\n (state) => state.mosaic.getSelection,\n );\n const updatePanel = useStoreWithMosaicDashboard(\n (state) => state.mosaicDashboard.updatePanel,\n );\n const issue = useStoreWithMosaicDashboard((state) =>\n state.mosaicDashboard.getPanelIssue(dashboardId, panel.id),\n );\n const reportPanelIssue = useStoreWithMosaicDashboard(\n (state) => state.mosaicDashboard.reportPanelIssue,\n );\n const clearPanelIssue = useStoreWithMosaicDashboard(\n (state) => state.mosaicDashboard.clearPanelIssue,\n );\n const executeSql = useStoreWithDuckDb((state) => state.db.executeSql);\n\n const isSettingsOpen = Boolean(\n (panel.config as DeckMapDashboardPanelConfig).settingsOpen,\n );\n\n const handleSettingsOpenChange = useCallback(\n (isOpen: boolean) => {\n updatePanel(dashboardId, panel.id, {\n config: {...panel.config, settingsOpen: isOpen},\n });\n },\n [dashboardId, panel.config, panel.id, updatePanel],\n );\n const selection = useMemo<Selection>(\n () => getSelection(selectionName, 'crossfilter'),\n [getSelection, selectionName],\n );\n const containerRef = useRef<HTMLDivElement | null>(null);\n const [datasetStates, setDatasetStates] = useState<\n Record<string, DeckMapDashboardDatasetClientState>\n >({});\n const [containerSize, setContainerSize] = useState({width: 0, height: 0});\n\n const handleDatasetState = useCallback(\n (\n datasetId: string,\n state: DeckMapDashboardDatasetClientState | undefined,\n ) => {\n setDatasetStates((current) => {\n const next = {...current};\n if (state) {\n next[datasetId] = state;\n } else {\n delete next[datasetId];\n }\n return next;\n });\n },\n [],\n );\n\n const dataPolicy = useMemo<ChartDataPolicy>(\n () => getDeckMapDataPolicy(mapConfig),\n [mapConfig],\n );\n const runtimeIssueContext = useMemo(\n () => ({\n panelId: panel.id,\n chartType: DECK_MAP_DASHBOARD_PANEL_TYPE,\n }),\n [panel.id],\n );\n const runtimeIssueReporter = useMemo<ChartRuntimeIssueReporter>(\n () => ({\n reportIssue: (issueToReport) => {\n reportPanelIssue(dashboardId, panel.id, issueToReport);\n },\n clearIssue: () => {\n clearPanelIssue(dashboardId, panel.id);\n },\n }),\n [clearPanelIssue, dashboardId, panel.id, reportPanelIssue],\n );\n\n useEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n\n const updateSize = () => {\n setContainerSize({\n width: container.clientWidth,\n height: container.clientHeight,\n });\n };\n\n updateSize();\n const observer = new ResizeObserver(updateSize);\n observer.observe(container);\n\n return () => {\n observer.disconnect();\n };\n }, []);\n\n const fitToData = mapConfig?.fitToData ?? null;\n const fitToDataSource = useMemo(\n () =>\n fitToData\n ? resolveDeckMapDashboardDatasetSource({\n dashboard,\n panel,\n dataset: mapConfig?.datasets[fitToData.dataset],\n })\n : undefined,\n [dashboard, fitToData, mapConfig?.datasets, panel],\n );\n const fitToDataKey = useMemo(\n () =>\n fitToData && fitToDataSource\n ? JSON.stringify({\n source: fitToDataSource,\n fitToData,\n })\n : null,\n [fitToData, fitToDataSource],\n );\n const fitStateKey = useMemo(\n () => JSON.stringify({panelId: panel.id, fitToDataKey}),\n [fitToDataKey, panel.id],\n );\n const [fitState, setFitState] = useState<DeckMapDashboardFitState>(() =>\n createInitialDeckMapDashboardFitState(fitStateKey),\n );\n const activeFitState =\n fitState.key === fitStateKey\n ? fitState\n : createInitialDeckMapDashboardFitState(fitStateKey);\n const {didAutoFit, fitRequestVersion, handledFitRequestVersion, viewState} =\n activeFitState;\n\n useEffect(() => {\n const handleFitRequest = (event: Event) => {\n const detail = (event as CustomEvent<{panelId?: string}>).detail;\n if (detail?.panelId === panel.id) {\n setFitState((current) => {\n const scoped =\n current.key === fitStateKey\n ? current\n : createInitialDeckMapDashboardFitState(fitStateKey);\n return {\n ...scoped,\n fitRequestVersion: scoped.fitRequestVersion + 1,\n };\n });\n }\n };\n\n deckMapDashboardFitRequestTarget.addEventListener(\n 'fit-view',\n handleFitRequest,\n );\n return () => {\n deckMapDashboardFitRequestTarget.removeEventListener(\n 'fit-view',\n handleFitRequest,\n );\n };\n }, [fitStateKey, panel.id]);\n\n useEffect(() => {\n const hasManualFitRequest = fitRequestVersion > handledFitRequestVersion;\n if (\n !fitToData ||\n !fitToDataSource ||\n containerSize.width <= 0 ||\n containerSize.height <= 0 ||\n (!hasManualFitRequest && didAutoFit)\n ) {\n return;\n }\n\n let isCancelled = false;\n\n const fitToDataBounds = async () => {\n try {\n const handle = await executeSql(\n createDeckMapBoundsQuery({\n source: fitToDataSource,\n fitToData,\n }),\n );\n const result = handle ? await handle : null;\n if (isCancelled || !result) {\n return;\n }\n\n const bounds = readBoundsFromExtentResult(result);\n if (!bounds) {\n setFitState((current) => {\n const scoped =\n current.key === fitStateKey\n ? current\n : createInitialDeckMapDashboardFitState(fitStateKey);\n return {\n ...scoped,\n didAutoFit: true,\n handledFitRequestVersion: fitRequestVersion,\n };\n });\n return;\n }\n\n const nextViewState = fitViewStateToBounds({\n bounds,\n width: containerSize.width,\n height: containerSize.height,\n padding: fitToData.padding,\n maxZoom: fitToData.maxZoom,\n });\n setFitState((current) => {\n const scoped =\n current.key === fitStateKey\n ? current\n : createInitialDeckMapDashboardFitState(fitStateKey);\n return {\n ...scoped,\n viewState: nextViewState,\n didAutoFit: true,\n handledFitRequestVersion: fitRequestVersion,\n };\n });\n } catch {\n if (!isCancelled) {\n setFitState((current) => {\n const scoped =\n current.key === fitStateKey\n ? current\n : createInitialDeckMapDashboardFitState(fitStateKey);\n return {\n ...scoped,\n didAutoFit: true,\n handledFitRequestVersion: fitRequestVersion,\n };\n });\n }\n }\n };\n\n void fitToDataBounds();\n\n return () => {\n isCancelled = true;\n };\n }, [\n containerSize.height,\n containerSize.width,\n didAutoFit,\n executeSql,\n fitRequestVersion,\n fitStateKey,\n fitToData,\n fitToDataSource,\n handledFitRequestVersion,\n ]);\n\n const handleBrushEvent = useCallback(\n (info: DeckMapInteractionEvent) => {\n const interaction = mapConfig?.interaction;\n if (!interaction) {\n return;\n }\n\n const client = datasetStates[interaction.dataset]?.client as\n | MosaicClient\n | null\n | undefined;\n if (!client) {\n return;\n }\n const coordinate = getCoordinate(info);\n if (!coordinate) {\n return;\n }\n if (interaction.event !== 'click' && !isPickedMapFeature(info)) {\n selection.reset(\n selection.clauses.filter((clause) => clause.source === client),\n );\n return;\n }\n\n const radiusMeters = interaction.radiusMeters ?? 500;\n selection.update({\n source: client,\n clients: new Set([client]),\n value: [coordinate[0], coordinate[1], radiusMeters],\n predicate: createPointRadiusPredicate(interaction, coordinate),\n });\n },\n [datasetStates, mapConfig?.interaction, selection],\n );\n\n const handleViewStateChange = useCallback(\n ({\n viewState: nextViewState,\n interactionState,\n }: {\n viewState: any;\n interactionState?: any;\n }) => {\n const hasUserInteraction = Boolean(\n interactionState &&\n ['isDragging', 'isPanning', 'isRotating', 'isZooming'].some((key) =>\n Boolean(interactionState[key]),\n ),\n );\n if (\n fitToData &&\n !didAutoFit &&\n viewState === null &&\n !hasUserInteraction\n ) {\n return;\n }\n\n setFitState((current) => {\n const scoped =\n current.key === fitStateKey\n ? current\n : createInitialDeckMapDashboardFitState(fitStateKey);\n return {\n ...scoped,\n viewState: nextViewState,\n didAutoFit: hasUserInteraction || scoped.didAutoFit || !fitToData,\n };\n });\n },\n [didAutoFit, fitStateKey, fitToData, viewState],\n );\n\n const settingsContent = (\n <MapSettingsPanel\n dashboardId={dashboardId}\n panel={panel}\n onClose={() => handleSettingsOpenChange(false)}\n />\n );\n\n const mapContent = !mapConfig ? (\n <div className=\"text-muted-foreground flex h-full items-center justify-center p-4 text-sm\">\n Invalid map panel config.\n </div>\n ) : issue ? (\n <DeckMapRuntimeIssuePanel issue={issue} />\n ) : Object.entries(mapConfig.datasets).length === 0 ? (\n <div className=\"text-muted-foreground flex h-full items-center justify-center p-4 text-sm\">\n Map panels require at least one dataset.\n </div>\n ) : (\n <div ref={containerRef} className=\"relative h-full w-full\">\n {Object.entries(mapConfig.datasets).map(([datasetId, dataset]) => (\n <DeckMapDashboardDatasetClient\n key={datasetId}\n dashboard={dashboard}\n dataset={dataset}\n datasetId={datasetId}\n dataPolicy={dataPolicy}\n panel={panel}\n onDatasetState={handleDatasetState}\n runtimeIssueContext={runtimeIssueContext}\n runtimeIssueReporter={runtimeIssueReporter}\n selectionName={selectionName}\n />\n ))}\n {Object.entries(datasetStates)\n .filter(([, state]) => state.error)\n .map(([datasetId, state]) => (\n <div\n key={datasetId}\n className=\"bg-background/90 text-destructive absolute inset-x-4 top-4 z-10 rounded-md border p-3 text-sm shadow\"\n >\n Failed to load dataset "{datasetId}":{' '}\n {state.error?.message}\n </div>\n ))}\n <DeckJsonMap\n className=\"h-full w-full\"\n spec={mapConfig.spec}\n datasets={\n mapConfig\n ? createDeckMapDashboardDatasets(mapConfig, datasetStates)\n : {}\n }\n mapStyle={mapConfig.mapStyle}\n mapProps={mapConfig.mapProps}\n showLegends={mapConfig.showLegends}\n deckProps={{\n controller: true,\n ...(viewState ? {viewState} : {}),\n onViewStateChange: handleViewStateChange,\n ...(mapConfig.interaction\n ? (mapConfig.interaction.event ?? 'hover') === 'click'\n ? {onClick: handleBrushEvent}\n : {onHover: handleBrushEvent}\n : {}),\n }}\n />\n </div>\n );\n\n return (\n <div className=\"h-full min-h-0\">\n <MosaicDashboardPanelLayout\n isOpen={isSettingsOpen}\n onIsOpenChange={handleSettingsOpenChange}\n settings={settingsContent}\n content={mapContent}\n />\n </div>\n );\n}\n\nexport const deckMapDashboardPanelRenderer: MosaicDashboardPanelRenderer = {\n component: DeckMapDashboardRenderer,\n headerActions: DeckMapDashboardHeaderActions,\n icon: MapIcon,\n};\n\nexport const deckMapDashboardAddPanelAction: import('@sqlrooms/mosaic').MosaicDashboardAddPanelAction =\n {\n type: DECK_MAP_DASHBOARD_PANEL_TYPE,\n label: 'Map',\n icon: MapIcon,\n isEnabled: ({selectedTable}) =>\n Boolean(\n findLongitudeLatitudeColumns(selectedTable) ??\n findGeometryColumn(selectedTable),\n ),\n createPanel: ({selectedTable}) =>\n selectedTable\n ? createDeckMapDashboardPanelConfigForTable({\n title: `${selectedTable.tableName} map`,\n tableName: selectedTable.tableName,\n columns: selectedTable.columns,\n tableReference: selectedTable.table,\n })\n : undefined,\n };\n"]}
|
|
@@ -1,9 +1,18 @@
|
|
|
1
|
-
import { type MosaicDashboardEntryType, type MosaicDashboardPanelConfigType
|
|
1
|
+
import { type MosaicDashboardEntryType, type MosaicDashboardPanelConfigType } from '@sqlrooms/mosaic';
|
|
2
2
|
import type { Table as ArrowTable } from 'apache-arrow';
|
|
3
3
|
import type { DeckJsonMapProps, DeckSqlDatasetInput } from './types';
|
|
4
4
|
export declare const DECK_MAP_DASHBOARD_PANEL_TYPE = "deck-json-map";
|
|
5
|
+
export declare const DEFAULT_DECK_MAP_MAX_DATA_POINTS = 100000;
|
|
6
|
+
export type DeckMapDataPolicyOverride = {
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
maxRows?: number;
|
|
9
|
+
reason?: string;
|
|
10
|
+
};
|
|
5
11
|
export type DeckMapDashboardDatasetConfig = Omit<DeckSqlDatasetInput, 'sqlQuery'> & {
|
|
6
|
-
source?:
|
|
12
|
+
source?: {
|
|
13
|
+
tableName?: string;
|
|
14
|
+
sqlQuery?: string;
|
|
15
|
+
};
|
|
7
16
|
};
|
|
8
17
|
export type DeckMapDashboardInteractionConfig = {
|
|
9
18
|
type: 'point-radius-brush';
|
|
@@ -28,10 +37,11 @@ export type DeckMapDashboardPanelConfig = {
|
|
|
28
37
|
showLegends?: boolean;
|
|
29
38
|
interaction?: DeckMapDashboardInteractionConfig;
|
|
30
39
|
fitToData?: DeckMapDashboardFitToDataConfig;
|
|
40
|
+
dataPolicy?: DeckMapDataPolicyOverride;
|
|
41
|
+
settingsOpen?: boolean;
|
|
31
42
|
};
|
|
32
43
|
export type CreateDeckMapDashboardPanelConfigOptions = DeckMapDashboardPanelConfig & {
|
|
33
44
|
title?: string;
|
|
34
|
-
source?: MosaicDashboardPanelSourceType;
|
|
35
45
|
};
|
|
36
46
|
export type DeckMapDashboardDatasetClientState = {
|
|
37
47
|
arrowTable?: ArrowTable;
|
|
@@ -40,12 +50,18 @@ export type DeckMapDashboardDatasetClientState = {
|
|
|
40
50
|
client: unknown;
|
|
41
51
|
};
|
|
42
52
|
export declare function asDeckJsonMapConfig(config: Record<string, unknown>): DeckMapDashboardPanelConfig | null;
|
|
43
|
-
export declare function createDeckMapDashboardPanelConfig(options: CreateDeckMapDashboardPanelConfigOptions):
|
|
53
|
+
export declare function createDeckMapDashboardPanelConfig(options: CreateDeckMapDashboardPanelConfigOptions): any;
|
|
44
54
|
export declare function resolveDeckMapDashboardDatasetSource(options: {
|
|
45
55
|
dashboard: MosaicDashboardEntryType;
|
|
46
56
|
panel: MosaicDashboardPanelConfigType;
|
|
47
57
|
dataset?: DeckMapDashboardDatasetConfig;
|
|
48
|
-
}):
|
|
49
|
-
|
|
58
|
+
}): {
|
|
59
|
+
tableName?: string;
|
|
60
|
+
sqlQuery?: string;
|
|
61
|
+
} | undefined;
|
|
62
|
+
export declare function createDeckMapDashboardDatasetQuery(source: {
|
|
63
|
+
tableName?: string;
|
|
64
|
+
sqlQuery?: string;
|
|
65
|
+
}, filter: unknown): import("@uwdata/mosaic-sql").SelectQuery;
|
|
50
66
|
export declare function createDeckMapDashboardDatasets(mapConfig: DeckMapDashboardPanelConfig, datasetStates: Record<string, Pick<DeckMapDashboardDatasetClientState, 'arrowTable'>>): DeckJsonMapProps['datasets'];
|
|
51
67
|
//# sourceMappingURL=dashboardConfig.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dashboardConfig.d.ts","sourceRoot":"","sources":["../src/dashboardConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,wBAAwB,EAC7B,KAAK,8BAA8B,
|
|
1
|
+
{"version":3,"file":"dashboardConfig.d.ts","sourceRoot":"","sources":["../src/dashboardConfig.ts"],"names":[],"mappings":"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"}
|
package/dist/dashboardConfig.js
CHANGED
|
@@ -2,6 +2,7 @@ import { Query, } from '@sqlrooms/mosaic';
|
|
|
2
2
|
import { createId } from '@paralleldrive/cuid2';
|
|
3
3
|
import { verbatim } from '@uwdata/mosaic-sql';
|
|
4
4
|
export const DECK_MAP_DASHBOARD_PANEL_TYPE = 'deck-json-map';
|
|
5
|
+
export const DEFAULT_DECK_MAP_MAX_DATA_POINTS = 100_000;
|
|
5
6
|
export function asDeckJsonMapConfig(config) {
|
|
6
7
|
if (!config.spec ||
|
|
7
8
|
!config.datasets ||
|
|
@@ -12,12 +13,11 @@ export function asDeckJsonMapConfig(config) {
|
|
|
12
13
|
return config;
|
|
13
14
|
}
|
|
14
15
|
export function createDeckMapDashboardPanelConfig(options) {
|
|
15
|
-
const { title,
|
|
16
|
+
const { title, ...config } = options;
|
|
16
17
|
return {
|
|
17
18
|
id: createId(),
|
|
18
19
|
type: DECK_MAP_DASHBOARD_PANEL_TYPE,
|
|
19
20
|
title: title ?? 'Map',
|
|
20
|
-
...(source ? { source } : {}),
|
|
21
21
|
config: JSON.parse(JSON.stringify(config)),
|
|
22
22
|
};
|
|
23
23
|
}
|
|
@@ -26,9 +26,6 @@ export function resolveDeckMapDashboardDatasetSource(options) {
|
|
|
26
26
|
if (datasetSource?.sqlQuery || datasetSource?.tableName) {
|
|
27
27
|
return datasetSource;
|
|
28
28
|
}
|
|
29
|
-
if (options.panel.source?.sqlQuery || options.panel.source?.tableName) {
|
|
30
|
-
return options.panel.source;
|
|
31
|
-
}
|
|
32
29
|
return options.dashboard.selectedTable
|
|
33
30
|
? { tableName: options.dashboard.selectedTable }
|
|
34
31
|
: undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dashboardConfig.js","sourceRoot":"","sources":["../src/dashboardConfig.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"dashboardConfig.js","sourceRoot":"","sources":["../src/dashboardConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,GACN,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAC,QAAQ,EAAC,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAC,QAAQ,EAAC,MAAM,oBAAoB,CAAC;AAI5C,MAAM,CAAC,MAAM,6BAA6B,GAAG,eAAe,CAAC;AAC7D,MAAM,CAAC,MAAM,gCAAgC,GAAG,OAAO,CAAC;AAwDxD,MAAM,UAAU,mBAAmB,CACjC,MAA+B;IAE/B,IACE,CAAC,MAAM,CAAC,IAAI;QACZ,CAAC,MAAM,CAAC,QAAQ;QAChB,OAAO,MAAM,CAAC,QAAQ,KAAK,QAAQ;QACnC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,EAC9B,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,MAAqC,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,iCAAiC,CAC/C,OAAiD;IAEjD,MAAM,EAAC,KAAK,EAAE,GAAG,MAAM,EAAC,GAAG,OAAO,CAAC;IACnC,OAAO;QACL,EAAE,EAAE,QAAQ,EAAE;QACd,IAAI,EAAE,6BAA6B;QACnC,KAAK,EAAE,KAAK,IAAI,KAAK;QACrB,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAA4B;KACtE,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,oCAAoC,CAAC,OAIpD;IACC,MAAM,aAAa,GAAG,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC;IAC9C,IAAI,aAAa,EAAE,QAAQ,IAAI,aAAa,EAAE,SAAS,EAAE,CAAC;QACxD,OAAO,aAAa,CAAC;IACvB,CAAC;IACD,OAAO,OAAO,CAAC,SAAS,CAAC,aAAa;QACpC,CAAC,CAAC,EAAC,SAAS,EAAE,OAAO,CAAC,SAAS,CAAC,aAAa,EAAC;QAC9C,CAAC,CAAC,SAAS,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,kCAAkC,CAChD,MAA+C,EAC/C,MAAe;IAEf,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ;QAC3B,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC;YACT,uBAAuB,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,QAAQ,GAAG,CAAC;SAC1D,CAAC;QACJ,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;IAEvC,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,MAAe,CAAC,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,8BAA8B,CAC5C,SAAsC,EACtC,aAGC;IAED,OAAO,MAAM,CAAC,WAAW,CACvB,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC;QAC/D,SAAS;QACT;YACE,UAAU,EAAE,aAAa,CAAC,SAAS,CAAC,EAAE,UAAU;YAChD,cAAc,EAAE,OAAO,CAAC,cAAc;YACtC,oBAAoB,EAAE,OAAO,CAAC,oBAAoB;SACnD;KACF,CAAC,CACH,CAAC;AACJ,CAAC","sourcesContent":["import {\n type MosaicDashboardEntryType,\n type MosaicDashboardPanelConfigType,\n Query,\n} from '@sqlrooms/mosaic';\nimport {createId} from '@paralleldrive/cuid2';\nimport {verbatim} from '@uwdata/mosaic-sql';\nimport type {Table as ArrowTable} from 'apache-arrow';\nimport type {DeckJsonMapProps, DeckSqlDatasetInput} from './types';\n\nexport const DECK_MAP_DASHBOARD_PANEL_TYPE = 'deck-json-map';\nexport const DEFAULT_DECK_MAP_MAX_DATA_POINTS = 100_000;\n\nexport type DeckMapDataPolicyOverride = {\n disabled?: boolean;\n maxRows?: number;\n reason?: string;\n};\n\nexport type DeckMapDashboardDatasetConfig = Omit<\n DeckSqlDatasetInput,\n 'sqlQuery'\n> & {\n source?: {tableName?: string; sqlQuery?: string};\n};\n\nexport type DeckMapDashboardInteractionConfig = {\n type: 'point-radius-brush';\n dataset: string;\n longitudeColumn: string;\n latitudeColumn: string;\n radiusMeters?: number;\n event?: 'hover' | 'click';\n};\n\nexport type DeckMapDashboardFitToDataConfig = {\n dataset: string;\n longitudeColumn: string;\n latitudeColumn: string;\n padding?: number;\n maxZoom?: number;\n};\n\nexport type DeckMapDashboardPanelConfig = {\n spec: DeckJsonMapProps['spec'];\n datasets: Record<string, DeckMapDashboardDatasetConfig>;\n mapStyle?: string;\n mapProps?: Record<string, unknown>;\n showLegends?: boolean;\n interaction?: DeckMapDashboardInteractionConfig;\n fitToData?: DeckMapDashboardFitToDataConfig;\n dataPolicy?: DeckMapDataPolicyOverride;\n settingsOpen?: boolean;\n};\n\nexport type CreateDeckMapDashboardPanelConfigOptions =\n DeckMapDashboardPanelConfig & {\n title?: string;\n };\n\nexport type DeckMapDashboardDatasetClientState = {\n arrowTable?: ArrowTable;\n isLoading: boolean;\n error?: Error;\n client: unknown;\n};\n\nexport function asDeckJsonMapConfig(\n config: Record<string, unknown>,\n): DeckMapDashboardPanelConfig | null {\n if (\n !config.spec ||\n !config.datasets ||\n typeof config.datasets !== 'object' ||\n Array.isArray(config.datasets)\n ) {\n return null;\n }\n\n return config as DeckMapDashboardPanelConfig;\n}\n\nexport function createDeckMapDashboardPanelConfig(\n options: CreateDeckMapDashboardPanelConfigOptions,\n): any {\n const {title, ...config} = options;\n return {\n id: createId(),\n type: DECK_MAP_DASHBOARD_PANEL_TYPE,\n title: title ?? 'Map',\n config: JSON.parse(JSON.stringify(config)) as Record<string, unknown>,\n };\n}\n\nexport function resolveDeckMapDashboardDatasetSource(options: {\n dashboard: MosaicDashboardEntryType;\n panel: MosaicDashboardPanelConfigType;\n dataset?: DeckMapDashboardDatasetConfig;\n}): {tableName?: string; sqlQuery?: string} | undefined {\n const datasetSource = options.dataset?.source;\n if (datasetSource?.sqlQuery || datasetSource?.tableName) {\n return datasetSource;\n }\n return options.dashboard.selectedTable\n ? {tableName: options.dashboard.selectedTable}\n : undefined;\n}\n\nexport function createDeckMapDashboardDatasetQuery(\n source: {tableName?: string; sqlQuery?: string},\n filter: unknown,\n) {\n const query = source.sqlQuery\n ? Query.from({\n __dashboard_map_dataset: verbatim(`(${source.sqlQuery})`),\n })\n : Query.from(source.tableName ?? '');\n\n return query.select('*').where(filter as never);\n}\n\nexport function createDeckMapDashboardDatasets(\n mapConfig: DeckMapDashboardPanelConfig,\n datasetStates: Record<\n string,\n Pick<DeckMapDashboardDatasetClientState, 'arrowTable'>\n >,\n): DeckJsonMapProps['datasets'] {\n return Object.fromEntries(\n Object.entries(mapConfig.datasets).map(([datasetId, dataset]) => [\n datasetId,\n {\n arrowTable: datasetStates[datasetId]?.arrowTable,\n geometryColumn: dataset.geometryColumn,\n geometryEncodingHint: dataset.geometryEncodingHint,\n },\n ]),\n );\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dashboardIntegration.d.ts","sourceRoot":"","sources":["../src/dashboardIntegration.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,+BAA+B,EACrC,MAAM,kBAAkB,CAAC;AAO1B,wBAAgB,kCAAkC,IAAI,+BAA+B,CAWpF"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { createDefaultChartTypes, createDefaultMosaicDashboardPanelRenderers, defaultAddPanelActions, } from '@sqlrooms/mosaic';
|
|
2
|
+
import { deckMapDashboardAddPanelAction, deckMapDashboardPanelRenderer, } from './dashboard';
|
|
3
|
+
import { DECK_MAP_DASHBOARD_PANEL_TYPE } from './dashboardConfig';
|
|
4
|
+
export function createDeckMapDashboardSliceOptions() {
|
|
5
|
+
return {
|
|
6
|
+
panelRenderers: createDefaultMosaicDashboardPanelRenderers({
|
|
7
|
+
[DECK_MAP_DASHBOARD_PANEL_TYPE]: deckMapDashboardPanelRenderer,
|
|
8
|
+
}),
|
|
9
|
+
addPanelActions: [
|
|
10
|
+
...defaultAddPanelActions,
|
|
11
|
+
deckMapDashboardAddPanelAction,
|
|
12
|
+
],
|
|
13
|
+
chartTypes: createDefaultChartTypes(),
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=dashboardIntegration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dashboardIntegration.js","sourceRoot":"","sources":["../src/dashboardIntegration.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uBAAuB,EACvB,0CAA0C,EAC1C,sBAAsB,GAEvB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,8BAA8B,EAC9B,6BAA6B,GAC9B,MAAM,aAAa,CAAC;AACrB,OAAO,EAAC,6BAA6B,EAAC,MAAM,mBAAmB,CAAC;AAEhE,MAAM,UAAU,kCAAkC;IAChD,OAAO;QACL,cAAc,EAAE,0CAA0C,CAAC;YACzD,CAAC,6BAA6B,CAAC,EAAE,6BAA6B;SAC/D,CAAC;QACF,eAAe,EAAE;YACf,GAAG,sBAAsB;YACzB,8BAA8B;SAC/B;QACD,UAAU,EAAE,uBAAuB,EAAE;KACtC,CAAC;AACJ,CAAC","sourcesContent":["import {\n createDefaultChartTypes,\n createDefaultMosaicDashboardPanelRenderers,\n defaultAddPanelActions,\n type CreateMosaicDashboardSliceProps,\n} from '@sqlrooms/mosaic';\nimport {\n deckMapDashboardAddPanelAction,\n deckMapDashboardPanelRenderer,\n} from './dashboard';\nimport {DECK_MAP_DASHBOARD_PANEL_TYPE} from './dashboardConfig';\n\nexport function createDeckMapDashboardSliceOptions(): CreateMosaicDashboardSliceProps {\n return {\n panelRenderers: createDefaultMosaicDashboardPanelRenderers({\n [DECK_MAP_DASHBOARD_PANEL_TYPE]: deckMapDashboardPanelRenderer,\n }),\n addPanelActions: [\n ...defaultAddPanelActions,\n deckMapDashboardAddPanelAction,\n ],\n chartTypes: createDefaultChartTypes(),\n };\n}\n"]}
|
|
@@ -173,7 +173,8 @@ export function createPreparedDatasetStore(options = {}) {
|
|
|
173
173
|
}
|
|
174
174
|
nextEntries[cacheKey] = cloneEntryWithConsumers(entry, consumers);
|
|
175
175
|
}
|
|
176
|
-
const
|
|
176
|
+
const nextConsumerKeys = { ...state.consumerKeys };
|
|
177
|
+
delete nextConsumerKeys[consumerId];
|
|
177
178
|
return {
|
|
178
179
|
...state,
|
|
179
180
|
consumerKeys: nextConsumerKeys,
|