@sjvair/monitor-map 4.2.0 → 5.0.0-beta.0
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/LICENSE +21 -0
- package/README.md +61 -126
- package/dist/lib/MonitorDetailPanel.svelte +23 -20
- package/dist/lib/MonitorMapLayout.svelte +147 -77
- package/dist/lib/abort.d.ts +16 -0
- package/dist/lib/abort.js +51 -0
- package/dist/lib/components/DataBox.svelte +4 -1
- package/dist/lib/components/ui/range-calendar/range-calendar.svelte.d.ts +1 -1
- package/dist/lib/config.svelte.d.ts +7 -0
- package/dist/lib/config.svelte.js +10 -0
- package/dist/lib/core.d.ts +2 -2
- package/dist/lib/core.js +2 -1
- package/dist/lib/data-chart/DataChart.svelte +54 -24
- package/dist/lib/data-chart/DateRange.d.ts +13 -4
- package/dist/lib/data-chart/DateRange.js +50 -14
- package/dist/lib/data-chart/chart-utils.js +5 -7
- package/dist/lib/data-chart/level-colors.d.ts +3 -4
- package/dist/lib/data-chart/level-colors.js +7 -4
- package/dist/lib/data-chart/pacific-time.d.ts +9 -0
- package/dist/lib/data-chart/pacific-time.js +25 -0
- package/dist/lib/data-chart/requests.d.ts +2 -1
- package/dist/lib/data-chart/requests.js +5 -2
- package/dist/lib/data-chart/tooltip.js +2 -2
- package/{src/lib/ev-stations/components/EvStationTooltip.svelte → dist/lib/ev-stations/EvPopup.svelte} +6 -5
- package/dist/lib/ev-stations/EvPopup.svelte.d.ts +7 -0
- package/dist/lib/ev-stations/ev-plugin.svelte.d.ts +14 -0
- package/dist/lib/ev-stations/ev-plugin.svelte.js +71 -0
- package/dist/lib/ev-stations/ev-station-icons.d.ts +1 -4
- package/dist/lib/ev-stations/ev-station-icons.js +1 -13
- package/dist/lib/ev-stations/ev-stations.d.ts +7 -0
- package/dist/lib/ev-stations/ev-stations.js +53 -0
- package/dist/lib/ev-stations/ev-store.svelte.d.ts +21 -0
- package/dist/lib/ev-stations/ev-store.svelte.js +83 -0
- package/dist/lib/ev-stations/station-popup.svelte.d.ts +14 -0
- package/dist/lib/ev-stations/station-popup.svelte.js +54 -0
- package/dist/lib/ev-stations/types.d.ts +0 -29
- package/dist/lib/ev-stations/zip-codes.d.ts +11 -0
- package/dist/lib/ev-stations/zip-codes.js +28 -16
- package/dist/lib/index.d.ts +8 -56
- package/dist/lib/index.js +7 -46
- package/dist/lib/legend/Legend.svelte +18 -19
- package/dist/lib/legend/Legend.svelte.d.ts +2 -2
- package/dist/lib/levels.d.ts +7 -0
- package/dist/lib/levels.js +19 -0
- package/dist/lib/map/MapShell.svelte +17 -24
- package/dist/lib/map/MapShell.svelte.d.ts +4 -4
- package/dist/lib/map/basemaps.d.ts +25 -0
- package/dist/lib/map/basemaps.js +66 -0
- package/dist/lib/map/live-map.svelte.d.ts +3 -0
- package/dist/lib/map/live-map.svelte.js +22 -0
- package/dist/lib/map/sync-plugins.svelte.d.ts +19 -0
- package/dist/lib/map/sync-plugins.svelte.js +52 -0
- package/dist/lib/monitors/components/MonitorSubscriptionManager.svelte +82 -82
- package/dist/lib/monitors/filtered-source.svelte.d.ts +9 -0
- package/dist/lib/monitors/filtered-source.svelte.js +28 -0
- package/dist/lib/monitors/monitor-details.svelte.js +11 -3
- package/dist/lib/monitors/monitors.svelte.d.ts +29 -26
- package/dist/lib/monitors/monitors.svelte.js +35 -126
- package/dist/lib/monitors/retry-load.d.ts +8 -0
- package/dist/lib/monitors/retry-load.js +11 -0
- package/dist/lib/monitors/subscriptions.d.ts +3 -0
- package/dist/lib/monitors/subscriptions.js +9 -0
- package/dist/lib/monitors/types.d.ts +1 -41
- package/dist/lib/options/map-option-defaults.d.ts +25 -36
- package/dist/lib/options/map-option-defaults.js +12 -30
- package/dist/lib/options/map-options.svelte.d.ts +13 -0
- package/dist/lib/options/map-options.svelte.js +26 -0
- package/dist/lib/options/menus/LayersMenu.svelte +8 -20
- package/dist/lib/options/menus/LayersMenu.svelte.d.ts +17 -2
- package/dist/lib/options/menus/MonitorsMenu.svelte +34 -18
- package/dist/lib/options/menus/OverlaysMenu.svelte +2 -2
- package/dist/lib/options/menus/PollutantMenu.svelte +4 -9
- package/dist/lib/options/menus/SettingsMenu.svelte +32 -25
- package/dist/lib/options/menus/SettingsMenu.svelte.d.ts +5 -16
- package/dist/lib/options/plugin-order.d.ts +8 -0
- package/dist/lib/options/plugin-order.js +36 -0
- package/dist/lib/options/pollutant-param.d.ts +7 -5
- package/dist/lib/options/pollutant-param.js +9 -5
- package/dist/lib/options/row-icons.d.ts +8 -0
- package/dist/lib/options/row-icons.js +15 -0
- package/dist/lib/options/rows/MarkerIcon.svelte +5 -5
- package/dist/lib/options/rows/MarkerIcon.svelte.d.ts +1 -2
- package/dist/lib/search/Search.svelte +20 -33
- package/dist/lib/search/Search.svelte.d.ts +5 -1
- package/dist/lib/search/search-pin.svelte.d.ts +11 -0
- package/dist/lib/search/search-pin.svelte.js +28 -0
- package/dist/lib/search/service.d.ts +7 -2
- package/dist/lib/search/service.js +17 -10
- package/dist/lib/stores.svelte.d.ts +8 -0
- package/dist/lib/stores.svelte.js +9 -0
- package/dist/lib/wind/wind-plugin.d.ts +11 -0
- package/dist/lib/wind/wind-plugin.js +25 -0
- package/package.json +12 -10
- package/src/lib/MonitorDetailPanel.svelte +23 -20
- package/src/lib/MonitorMapLayout.svelte +147 -77
- package/src/lib/abort.ts +59 -0
- package/src/lib/components/DataBox.svelte +4 -1
- package/src/lib/config.svelte.ts +16 -0
- package/src/lib/core.ts +2 -2
- package/src/lib/data-chart/DataChart.svelte +54 -24
- package/src/lib/data-chart/DateRange.ts +58 -15
- package/src/lib/data-chart/chart-utils.ts +6 -7
- package/src/lib/data-chart/level-colors.ts +8 -9
- package/src/lib/data-chart/pacific-time.ts +31 -0
- package/src/lib/data-chart/requests.ts +14 -7
- package/src/lib/data-chart/tooltip.ts +2 -2
- package/{dist/lib/ev-stations/components/EvStationTooltip.svelte → src/lib/ev-stations/EvPopup.svelte} +6 -5
- package/src/lib/ev-stations/ev-plugin.svelte.ts +86 -0
- package/src/lib/ev-stations/ev-station-icons.ts +1 -17
- package/src/lib/ev-stations/ev-stations.ts +72 -0
- package/src/lib/ev-stations/ev-store.svelte.ts +117 -0
- package/src/lib/ev-stations/station-popup.svelte.ts +64 -0
- package/src/lib/ev-stations/types.ts +0 -34
- package/src/lib/ev-stations/zip-codes.ts +29 -16
- package/src/lib/index.ts +8 -99
- package/src/lib/legend/Legend.svelte +18 -19
- package/src/lib/levels.ts +24 -0
- package/src/lib/map/MapShell.svelte +17 -24
- package/src/lib/map/basemaps.ts +76 -0
- package/src/lib/map/live-map.svelte.ts +24 -0
- package/src/lib/map/sync-plugins.svelte.ts +69 -0
- package/src/lib/monitors/components/MonitorSubscriptionManager.svelte +82 -82
- package/src/lib/monitors/filtered-source.svelte.ts +38 -0
- package/src/lib/monitors/monitor-details.svelte.ts +12 -3
- package/src/lib/monitors/monitors.svelte.ts +62 -153
- package/src/lib/monitors/retry-load.ts +14 -0
- package/src/lib/monitors/subscriptions.ts +17 -0
- package/src/lib/monitors/types.ts +1 -47
- package/src/lib/options/map-option-defaults.ts +30 -53
- package/src/lib/options/map-options.svelte.ts +30 -0
- package/src/lib/options/menus/LayersMenu.svelte +8 -20
- package/src/lib/options/menus/MonitorsMenu.svelte +34 -18
- package/src/lib/options/menus/OverlaysMenu.svelte +2 -2
- package/src/lib/options/menus/PollutantMenu.svelte +4 -9
- package/src/lib/options/menus/SettingsMenu.svelte +32 -25
- package/src/lib/options/plugin-order.ts +38 -0
- package/src/lib/options/pollutant-param.ts +14 -9
- package/src/lib/options/row-icons.ts +17 -0
- package/src/lib/options/rows/MarkerIcon.svelte +5 -5
- package/src/lib/search/Search.svelte +20 -33
- package/src/lib/search/search-pin.svelte.ts +35 -0
- package/src/lib/search/service.ts +34 -15
- package/src/lib/stores.svelte.ts +15 -0
- package/src/lib/wind/wind-plugin.ts +33 -0
- package/dist/lib/collocation-sites/CollocationTooltip.svelte +0 -98
- package/dist/lib/collocation-sites/CollocationTooltip.svelte.d.ts +0 -7
- package/dist/lib/collocation-sites/collocations-icon-manager.svelte.d.ts +0 -7
- package/dist/lib/collocation-sites/collocations-icon-manager.svelte.js +0 -18
- package/dist/lib/collocation-sites/collocations-map-integration.svelte.d.ts +0 -21
- package/dist/lib/collocation-sites/collocations-map-integration.svelte.js +0 -113
- package/dist/lib/collocation-sites/collocations.svelte.d.ts +0 -9
- package/dist/lib/collocation-sites/collocations.svelte.js +0 -17
- package/dist/lib/collocation-sites/types.d.ts +0 -8
- package/dist/lib/collocation-sites/types.js +0 -1
- package/dist/lib/ev-stations/components/EvStationClusterTooltip.svelte +0 -16
- package/dist/lib/ev-stations/components/EvStationClusterTooltip.svelte.d.ts +0 -7
- package/dist/lib/ev-stations/components/EvStationTooltip.svelte.d.ts +0 -7
- package/dist/lib/ev-stations/ev-stations-cluster-renderer.d.ts +0 -19
- package/dist/lib/ev-stations/ev-stations-cluster-renderer.js +0 -131
- package/dist/lib/ev-stations/ev-stations-map-integration.svelte.d.ts +0 -31
- package/dist/lib/ev-stations/ev-stations-map-integration.svelte.js +0 -226
- package/dist/lib/ev-stations/ev-stations.svelte.d.ts +0 -9
- package/dist/lib/ev-stations/ev-stations.svelte.js +0 -55
- package/dist/lib/hms/hms-fire-icon-manager.d.ts +0 -13
- package/dist/lib/hms/hms-fire-icon-manager.js +0 -39
- package/dist/lib/hms/hms-fire-map-integration.svelte.d.ts +0 -23
- package/dist/lib/hms/hms-fire-map-integration.svelte.js +0 -94
- package/dist/lib/hms/hms-smoke-map-integration.svelte.d.ts +0 -39
- package/dist/lib/hms/hms-smoke-map-integration.svelte.js +0 -87
- package/dist/lib/hms/hms.svelte.d.ts +0 -19
- package/dist/lib/hms/hms.svelte.js +0 -227
- package/dist/lib/legend/LegendBar.svelte +0 -45
- package/dist/lib/legend/LegendBar.svelte.d.ts +0 -7
- package/dist/lib/legend/legend-data.d.ts +0 -40
- package/dist/lib/legend/legend-data.js +0 -65
- package/dist/lib/map/Map.svelte +0 -13
- package/dist/lib/map/Map.svelte.d.ts +0 -8
- package/dist/lib/map/basemap.d.ts +0 -14
- package/dist/lib/map/basemap.js +0 -10
- package/dist/lib/map/icons.d.ts +0 -7
- package/dist/lib/map/icons.js +0 -33
- package/dist/lib/map/integrations/base-layer-seperator.d.ts +0 -9
- package/dist/lib/map/integrations/base-layer-seperator.js +0 -11
- package/dist/lib/map/integrations/click-manager.d.ts +0 -14
- package/dist/lib/map/integrations/click-manager.js +0 -52
- package/dist/lib/map/integrations/integrations-manager.d.ts +0 -8
- package/dist/lib/map/integrations/integrations-manager.js +0 -20
- package/dist/lib/map/integrations/map-display-option.svelte.d.ts +0 -7
- package/dist/lib/map/integrations/map-display-option.svelte.js +0 -10
- package/dist/lib/map/integrations/map-geojson-integration.svelte.d.ts +0 -32
- package/dist/lib/map/integrations/map-geojson-integration.svelte.js +0 -60
- package/dist/lib/map/integrations/map-icon-manager.d.ts +0 -15
- package/dist/lib/map/integrations/map-icon-manager.js +0 -52
- package/dist/lib/map/integrations/map-integration.svelte.d.ts +0 -6
- package/dist/lib/map/integrations/map-integration.svelte.js +0 -2
- package/dist/lib/map/integrations/map-layer-integration.svelte.d.ts +0 -11
- package/dist/lib/map/integrations/map-layer-integration.svelte.js +0 -40
- package/dist/lib/map/integrations/tooltip.svelte.d.ts +0 -36
- package/dist/lib/map/integrations/tooltip.svelte.js +0 -131
- package/dist/lib/map/integrations/types.d.ts +0 -14
- package/dist/lib/map/integrations/types.js +0 -1
- package/dist/lib/map/map-manager.svelte.d.ts +0 -20
- package/dist/lib/map/map-manager.svelte.js +0 -63
- package/dist/lib/map/map-style-state.svelte.d.ts +0 -23
- package/dist/lib/map/map-style-state.svelte.js +0 -86
- package/dist/lib/map/utils.d.ts +0 -7
- package/dist/lib/map/utils.js +0 -36
- package/dist/lib/monitors/components/MonitorClusterTooltip.svelte +0 -112
- package/dist/lib/monitors/components/MonitorClusterTooltip.svelte.d.ts +0 -7
- package/dist/lib/monitors/components/MonitorTooltip.svelte +0 -61
- package/dist/lib/monitors/components/MonitorTooltip.svelte.d.ts +0 -7
- package/dist/lib/monitors/monitor-utils.d.ts +0 -4
- package/dist/lib/monitors/monitor-utils.js +0 -41
- package/dist/lib/monitors/monitors-cluster-renderer.d.ts +0 -33
- package/dist/lib/monitors/monitors-cluster-renderer.js +0 -221
- package/dist/lib/monitors/monitors-icon-manager.svelte.d.ts +0 -15
- package/dist/lib/monitors/monitors-icon-manager.svelte.js +0 -78
- package/dist/lib/monitors/monitors-map-integration.svelte.d.ts +0 -43
- package/dist/lib/monitors/monitors-map-integration.svelte.js +0 -301
- package/dist/lib/options/reset-map-options.d.ts +0 -2
- package/dist/lib/options/reset-map-options.js +0 -24
- package/dist/lib/reactivity.svelte.d.ts +0 -0
- package/dist/lib/reactivity.svelte.js +0 -83
- package/dist/lib/wind/wind.svelte.d.ts +0 -10
- package/dist/lib/wind/wind.svelte.js +0 -13
- package/src/lib/collocation-sites/CollocationTooltip.svelte +0 -98
- package/src/lib/collocation-sites/collocations-icon-manager.svelte.ts +0 -21
- package/src/lib/collocation-sites/collocations-map-integration.svelte.ts +0 -136
- package/src/lib/collocation-sites/collocations.svelte.ts +0 -24
- package/src/lib/collocation-sites/types.ts +0 -10
- package/src/lib/ev-stations/components/EvStationClusterTooltip.svelte +0 -16
- package/src/lib/ev-stations/ev-stations-cluster-renderer.ts +0 -162
- package/src/lib/ev-stations/ev-stations-map-integration.svelte.ts +0 -248
- package/src/lib/ev-stations/ev-stations.svelte.ts +0 -79
- package/src/lib/hms/hms-fire-icon-manager.ts +0 -48
- package/src/lib/hms/hms-fire-map-integration.svelte.ts +0 -109
- package/src/lib/hms/hms-smoke-map-integration.svelte.ts +0 -105
- package/src/lib/hms/hms.svelte.ts +0 -264
- package/src/lib/legend/LegendBar.svelte +0 -45
- package/src/lib/legend/legend-data.ts +0 -101
- package/src/lib/map/Map.svelte +0 -13
- package/src/lib/map/basemap.ts +0 -24
- package/src/lib/map/icons.ts +0 -42
- package/src/lib/map/integrations/base-layer-seperator.ts +0 -17
- package/src/lib/map/integrations/click-manager.ts +0 -64
- package/src/lib/map/integrations/integrations-manager.ts +0 -25
- package/src/lib/map/integrations/map-display-option.svelte.ts +0 -13
- package/src/lib/map/integrations/map-geojson-integration.svelte.ts +0 -77
- package/src/lib/map/integrations/map-icon-manager.ts +0 -67
- package/src/lib/map/integrations/map-integration.svelte.ts +0 -8
- package/src/lib/map/integrations/map-layer-integration.svelte.ts +0 -49
- package/src/lib/map/integrations/tooltip.svelte.ts +0 -153
- package/src/lib/map/integrations/types.ts +0 -24
- package/src/lib/map/map-manager.svelte.ts +0 -83
- package/src/lib/map/map-style-state.svelte.ts +0 -94
- package/src/lib/map/utils.ts +0 -53
- package/src/lib/monitors/components/MonitorClusterTooltip.svelte +0 -112
- package/src/lib/monitors/components/MonitorTooltip.svelte +0 -61
- package/src/lib/monitors/monitor-utils.ts +0 -57
- package/src/lib/monitors/monitors-cluster-renderer.ts +0 -285
- package/src/lib/monitors/monitors-icon-manager.svelte.ts +0 -98
- package/src/lib/monitors/monitors-map-integration.svelte.ts +0 -318
- package/src/lib/options/reset-map-options.ts +0 -28
- package/src/lib/reactivity.svelte.ts +0 -82
- package/src/lib/wind/wind.svelte.ts +0 -20
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import { asDataURI, circle, square, triangle } from "../map/icons";
|
|
2
|
-
import { MapIconManager } from "../map/integrations/map-icon-manager";
|
|
3
|
-
import { mapManager } from "../map/map-manager.svelte.js";
|
|
4
|
-
const MONITOR_ICONS = { circle, square, triangle };
|
|
5
|
-
const MONITOR_ICON_BORDER_WIDTH = 2;
|
|
6
|
-
const MONITOR_ICON_DEFAULT_COLOR = "#969696"; // light gray
|
|
7
|
-
const MONITOR_ICON_DISPLAY_COLOR = "#48c78e"; // light gray
|
|
8
|
-
export function getIconId(monitor, level) {
|
|
9
|
-
const id = `${monitor.location}-${monitor.is_active ? level.name : "default"}`;
|
|
10
|
-
switch (monitor.type) {
|
|
11
|
-
case "airnow":
|
|
12
|
-
case "aqview":
|
|
13
|
-
case "bam1022":
|
|
14
|
-
case "aqlite":
|
|
15
|
-
return `${id}-triangle`;
|
|
16
|
-
case "airgradient":
|
|
17
|
-
case "purpleair":
|
|
18
|
-
case "vozbox":
|
|
19
|
-
return `${id}-circle`;
|
|
20
|
-
default:
|
|
21
|
-
throw new Error(`Map icon for ${monitor.device} has not been set`);
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
export class MonitorShapeIconManager extends MapIconManager {
|
|
25
|
-
dataSource;
|
|
26
|
-
get iconSize() {
|
|
27
|
-
return 24;
|
|
28
|
-
}
|
|
29
|
-
constructor(dataSource) {
|
|
30
|
-
super();
|
|
31
|
-
this.dataSource = dataSource;
|
|
32
|
-
$effect.root(() => {
|
|
33
|
-
$effect(() => {
|
|
34
|
-
if (this.dataSource.levels) {
|
|
35
|
-
const iconLevels = [
|
|
36
|
-
...this.dataSource.levels,
|
|
37
|
-
{ name: "default", color: MONITOR_ICON_DEFAULT_COLOR },
|
|
38
|
-
{ name: "display", color: MONITOR_ICON_DISPLAY_COLOR }
|
|
39
|
-
];
|
|
40
|
-
for (const location of ["inside", "outside"]) {
|
|
41
|
-
for (const [shapeName, shape] of Object.entries(MONITOR_ICONS)) {
|
|
42
|
-
for (const level of iconLevels) {
|
|
43
|
-
const parts = [this.idPrefix, location, level.name, shapeName].filter(Boolean);
|
|
44
|
-
const id = parts.join("-");
|
|
45
|
-
const src = asDataURI(this.transformSvg(shape(level.color, MONITOR_ICON_BORDER_WIDTH, location === "inside" ? "#000000" : undefined)));
|
|
46
|
-
if (this.icons.has(id)) {
|
|
47
|
-
const icon = this.icons.get(id);
|
|
48
|
-
if (icon.image.src !== src) {
|
|
49
|
-
icon.image.src = src;
|
|
50
|
-
if (mapManager.map?.hasImage(id)) {
|
|
51
|
-
this.updateImage(icon, mapManager.map);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
continue;
|
|
55
|
-
}
|
|
56
|
-
else {
|
|
57
|
-
const icon = new Image();
|
|
58
|
-
icon.src = src;
|
|
59
|
-
icon.width = this.iconSize;
|
|
60
|
-
icon.height = this.iconSize;
|
|
61
|
-
this.register(id, icon);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
});
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
export class MonitorsIconManager extends MonitorShapeIconManager {
|
|
72
|
-
get idPrefix() {
|
|
73
|
-
return "";
|
|
74
|
-
}
|
|
75
|
-
transformSvg(svg) {
|
|
76
|
-
return svg;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { type FilterSpecification, type Map as MaptilerMap } from "@maptiler/sdk";
|
|
2
|
-
import type { SJVAirEntryLevel } from "@sjvair/sdk";
|
|
3
|
-
import { MapIconLayerIntegration } from "../map/integrations/map-geojson-integration.svelte";
|
|
4
|
-
import { MonitorsIconManager } from "./monitors-icon-manager.svelte";
|
|
5
|
-
import { TooltipManager } from "../map/integrations/tooltip.svelte";
|
|
6
|
-
import { MapDisplayOption } from "../map/integrations/map-display-option.svelte";
|
|
7
|
-
import type { MonitorMapFeature, MonitorMarkerProperties, MonitorsDataSource } from "./types";
|
|
8
|
-
declare class MonitorsMapIntegration extends MapIconLayerIntegration<MonitorMarkerProperties> {
|
|
9
|
-
private dataSource;
|
|
10
|
-
referenceId: string;
|
|
11
|
-
enabled: boolean;
|
|
12
|
-
clustered: boolean;
|
|
13
|
-
icons: MonitorsIconManager;
|
|
14
|
-
tooltipManager: TooltipManager;
|
|
15
|
-
private renderer;
|
|
16
|
-
displayOptions: {
|
|
17
|
-
airnow: MapDisplayOption;
|
|
18
|
-
aqlite: MapDisplayOption;
|
|
19
|
-
aqview: MapDisplayOption;
|
|
20
|
-
bam1022: MapDisplayOption;
|
|
21
|
-
airgradient: MapDisplayOption;
|
|
22
|
-
purpleair: MapDisplayOption;
|
|
23
|
-
vozbox: MapDisplayOption;
|
|
24
|
-
inactive: MapDisplayOption;
|
|
25
|
-
inside: MapDisplayOption;
|
|
26
|
-
};
|
|
27
|
-
/** Set by the app to handle navigation when a monitor is clicked. Receives the monitor ID. */
|
|
28
|
-
onMonitorClick: ((id: string) => void) | null;
|
|
29
|
-
selectedMonitorId: string | null;
|
|
30
|
-
private handleMonitorClick;
|
|
31
|
-
features: Array<MonitorMapFeature>;
|
|
32
|
-
filters: FilterSpecification;
|
|
33
|
-
featuresByType: Record<string, MonitorMapFeature[]>;
|
|
34
|
-
clusterIconThresholds: Array<SJVAirEntryLevel>;
|
|
35
|
-
get mapLayer(): Parameters<MaptilerMap["addLayer"]>[0];
|
|
36
|
-
get mapSource(): Parameters<MaptilerMap["addSource"]>[1];
|
|
37
|
-
constructor(dataSource?: MonitorsDataSource);
|
|
38
|
-
apply(): void;
|
|
39
|
-
remove(): void;
|
|
40
|
-
private applySelectedState;
|
|
41
|
-
}
|
|
42
|
-
export declare const monitorsMapIntegration: MonitorsMapIntegration;
|
|
43
|
-
export { MonitorsMapIntegration };
|
|
@@ -1,301 +0,0 @@
|
|
|
1
|
-
import { untrack } from "svelte";
|
|
2
|
-
import { mapManager } from "../map/map-manager.svelte.js";
|
|
3
|
-
import { clickManager } from "../map/integrations/click-manager";
|
|
4
|
-
import { MapIconLayerIntegration } from "../map/integrations/map-geojson-integration.svelte";
|
|
5
|
-
import { monitorsManager } from "./monitors.svelte";
|
|
6
|
-
import { getIconId, MonitorsIconManager } from "./monitors-icon-manager.svelte";
|
|
7
|
-
import { TooltipManager } from "../map/integrations/tooltip.svelte";
|
|
8
|
-
import { MapDisplayOption } from "../map/integrations/map-display-option.svelte";
|
|
9
|
-
import { getCurrentLevel, getOrder } from "./monitor-utils";
|
|
10
|
-
import { MonitorsClusterRenderer, monitorTooltip } from "./monitors-cluster-renderer";
|
|
11
|
-
const filters = {
|
|
12
|
-
monitor(deviceType) {
|
|
13
|
-
return ["==", ["get", "type"], deviceType];
|
|
14
|
-
}
|
|
15
|
-
};
|
|
16
|
-
class MonitorsMapIntegration extends MapIconLayerIntegration {
|
|
17
|
-
dataSource;
|
|
18
|
-
referenceId = "monitors";
|
|
19
|
-
enabled = $state(true);
|
|
20
|
-
clustered = $state(true);
|
|
21
|
-
icons;
|
|
22
|
-
tooltipManager = new TooltipManager();
|
|
23
|
-
renderer = new MonitorsClusterRenderer(this);
|
|
24
|
-
displayOptions = $derived.by(() => ({
|
|
25
|
-
airnow: new MapDisplayOption("AirNow", true, this.icons.get("outside-display-triangle")),
|
|
26
|
-
aqlite: new MapDisplayOption("AQLite", true, this.icons.get("outside-display-triangle")),
|
|
27
|
-
aqview: new MapDisplayOption("AQview", true, this.icons.get("outside-display-triangle")),
|
|
28
|
-
bam1022: new MapDisplayOption("SJVAir", true, this.icons.get("outside-display-triangle")),
|
|
29
|
-
airgradient: new MapDisplayOption("AirGradient", true, this.icons.get("outside-display-circle")),
|
|
30
|
-
purpleair: new MapDisplayOption("PurpleAir", true, this.icons.get("outside-display-circle")),
|
|
31
|
-
vozbox: new MapDisplayOption("VOZbox", true, this.icons.get("outside-display-circle")),
|
|
32
|
-
inactive: new MapDisplayOption("Inactive", false, this.icons.get("outside-default-circle")),
|
|
33
|
-
inside: new MapDisplayOption("Inside", false, this.icons.get("inside-display-circle"))
|
|
34
|
-
}));
|
|
35
|
-
/** Set by the app to handle navigation when a monitor is clicked. Receives the monitor ID. */
|
|
36
|
-
onMonitorClick = null;
|
|
37
|
-
selectedMonitorId = $state(null);
|
|
38
|
-
handleMonitorClick = (features) => {
|
|
39
|
-
if (!this.onMonitorClick)
|
|
40
|
-
return;
|
|
41
|
-
const sorted = [...features].sort((a, b) => (b.properties?.order ?? 0) - (a.properties?.order ?? 0));
|
|
42
|
-
const top = sorted[0];
|
|
43
|
-
if (!top?.properties?.id)
|
|
44
|
-
return;
|
|
45
|
-
this.selectedMonitorId = top.properties.id;
|
|
46
|
-
this.onMonitorClick(this.selectedMonitorId);
|
|
47
|
-
if (top.geometry.type !== "Point")
|
|
48
|
-
return;
|
|
49
|
-
const coords = top.geometry.coordinates;
|
|
50
|
-
mapManager.map?.easeTo({
|
|
51
|
-
center: coords,
|
|
52
|
-
zoom: Math.max(mapManager.map.getZoom(), 12)
|
|
53
|
-
});
|
|
54
|
-
};
|
|
55
|
-
features = $derived.by(() => {
|
|
56
|
-
if (!this.dataSource.meta || !this.dataSource.latest || !this.dataSource.pollutant) {
|
|
57
|
-
return [];
|
|
58
|
-
}
|
|
59
|
-
const levels = this.dataSource.meta.entryType(this.dataSource.pollutant).asIter.levels;
|
|
60
|
-
return Array.from(this.dataSource.latest.values().map((m) => {
|
|
61
|
-
const feature = {
|
|
62
|
-
type: "Feature",
|
|
63
|
-
properties: {
|
|
64
|
-
icon: "outside-default-square",
|
|
65
|
-
id: m.id,
|
|
66
|
-
is_active: m.is_active,
|
|
67
|
-
is_sjvair: m.is_sjvair,
|
|
68
|
-
location: m.location,
|
|
69
|
-
name: m.name,
|
|
70
|
-
order: getOrder(m),
|
|
71
|
-
type: m.type,
|
|
72
|
-
value: m.latest.value
|
|
73
|
-
},
|
|
74
|
-
geometry: m.position
|
|
75
|
-
};
|
|
76
|
-
if (levels) {
|
|
77
|
-
const level = getCurrentLevel(m.latest.value, levels);
|
|
78
|
-
if (level) {
|
|
79
|
-
feature.properties.icon = getIconId(m, level);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
return feature;
|
|
83
|
-
}));
|
|
84
|
-
});
|
|
85
|
-
filters = $derived.by(() => {
|
|
86
|
-
const monitorFilters = ["any"];
|
|
87
|
-
const locationFilters = [
|
|
88
|
-
"any",
|
|
89
|
-
["==", ["get", "location"], "outside"]
|
|
90
|
-
];
|
|
91
|
-
const statusFilters = ["any", ["==", ["get", "is_active"], true]];
|
|
92
|
-
if (this.displayOptions.airnow.value)
|
|
93
|
-
monitorFilters.push(filters.monitor("airnow"));
|
|
94
|
-
if (this.displayOptions.aqlite.value)
|
|
95
|
-
monitorFilters.push(filters.monitor("aqlite"));
|
|
96
|
-
if (this.displayOptions.aqview.value)
|
|
97
|
-
monitorFilters.push(filters.monitor("aqview"));
|
|
98
|
-
if (this.displayOptions.bam1022.value)
|
|
99
|
-
monitorFilters.push(filters.monitor("bam1022"));
|
|
100
|
-
if (this.displayOptions.airgradient.value)
|
|
101
|
-
monitorFilters.push(filters.monitor("airgradient"));
|
|
102
|
-
if (this.displayOptions.purpleair.value)
|
|
103
|
-
monitorFilters.push(filters.monitor("purpleair"));
|
|
104
|
-
if (this.displayOptions.vozbox.value)
|
|
105
|
-
monitorFilters.push(filters.monitor("vozbox"));
|
|
106
|
-
if (this.displayOptions.inside.value)
|
|
107
|
-
locationFilters.push(["==", ["get", "location"], "inside"]);
|
|
108
|
-
if (this.displayOptions.inactive.value)
|
|
109
|
-
statusFilters.push(["==", ["get", "is_active"], false]);
|
|
110
|
-
return ["all", monitorFilters, locationFilters, statusFilters];
|
|
111
|
-
});
|
|
112
|
-
// Groups features by monitor type for per-type cluster sources, applying display option
|
|
113
|
-
// filters so cluster aggregates only include visible monitors.
|
|
114
|
-
featuresByType = $derived.by(() => {
|
|
115
|
-
const opts = this.displayOptions;
|
|
116
|
-
const byType = {};
|
|
117
|
-
for (const feat of this.features) {
|
|
118
|
-
const p = feat.properties;
|
|
119
|
-
if (!p.is_active && !opts.inactive.value)
|
|
120
|
-
continue;
|
|
121
|
-
if (p.location === "inside" && !opts.inside.value)
|
|
122
|
-
continue;
|
|
123
|
-
const typeVisible = {
|
|
124
|
-
airnow: opts.airnow.value,
|
|
125
|
-
aqlite: opts.aqlite.value,
|
|
126
|
-
aqview: opts.aqview.value,
|
|
127
|
-
bam1022: opts.bam1022.value,
|
|
128
|
-
airgradient: opts.airgradient.value,
|
|
129
|
-
purpleair: opts.purpleair.value,
|
|
130
|
-
vozbox: opts.vozbox.value
|
|
131
|
-
};
|
|
132
|
-
if (!(typeVisible[p.type] ?? true))
|
|
133
|
-
continue;
|
|
134
|
-
const arr = byType[p.type] ?? [];
|
|
135
|
-
arr.push(feat);
|
|
136
|
-
byType[p.type] = arr;
|
|
137
|
-
}
|
|
138
|
-
return byType;
|
|
139
|
-
});
|
|
140
|
-
clusterIconThresholds = $derived.by(() => {
|
|
141
|
-
if (!this.dataSource.meta || !this.dataSource.pollutant)
|
|
142
|
-
return [];
|
|
143
|
-
return this.dataSource.meta.entryType(this.dataSource.pollutant).asIter.levels ?? [];
|
|
144
|
-
});
|
|
145
|
-
get mapLayer() {
|
|
146
|
-
return {
|
|
147
|
-
id: this.referenceId,
|
|
148
|
-
type: "symbol",
|
|
149
|
-
source: this.referenceId,
|
|
150
|
-
filter: this.filters,
|
|
151
|
-
layout: {
|
|
152
|
-
"symbol-sort-key": ["coalesce", ["get", "order"], 0],
|
|
153
|
-
"icon-allow-overlap": true,
|
|
154
|
-
"icon-ignore-placement": true,
|
|
155
|
-
"icon-image": ["get", "icon"],
|
|
156
|
-
"icon-size": 1
|
|
157
|
-
},
|
|
158
|
-
paint: {}
|
|
159
|
-
};
|
|
160
|
-
}
|
|
161
|
-
get mapSource() {
|
|
162
|
-
return {
|
|
163
|
-
type: "geojson",
|
|
164
|
-
promoteId: "id",
|
|
165
|
-
data: {
|
|
166
|
-
type: "FeatureCollection",
|
|
167
|
-
features: this.features
|
|
168
|
-
}
|
|
169
|
-
};
|
|
170
|
-
}
|
|
171
|
-
constructor(dataSource = monitorsManager) {
|
|
172
|
-
super();
|
|
173
|
-
this.dataSource = dataSource;
|
|
174
|
-
this.icons = new MonitorsIconManager(dataSource);
|
|
175
|
-
$effect.root(() => {
|
|
176
|
-
// Every effect below early-returns while disabled (Pollutant = None) so a data refresh
|
|
177
|
-
// can't re-add the layer. `enabled` is read untracked: the base class's own effect
|
|
178
|
-
// already applies/removes on enabled changes, and tracking it here would apply twice.
|
|
179
|
-
// The guard comes after each effect's tracked reads so its dependencies are always
|
|
180
|
-
// collected; returning before reading anything would leave the effect permanently dead.
|
|
181
|
-
// Push filter changes to the active layer(s) imperatively
|
|
182
|
-
$effect(() => {
|
|
183
|
-
const filter = this.filters;
|
|
184
|
-
const clustered = this.clustered;
|
|
185
|
-
if (!mapManager.map)
|
|
186
|
-
return;
|
|
187
|
-
if (!untrack(() => this.enabled))
|
|
188
|
-
return;
|
|
189
|
-
if (clustered) {
|
|
190
|
-
this.renderer.syncFilter();
|
|
191
|
-
}
|
|
192
|
-
else {
|
|
193
|
-
if (mapManager.map.getLayer(this.referenceId)) {
|
|
194
|
-
mapManager.map.setFilter(this.referenceId, filter);
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
});
|
|
198
|
-
// Sync unclustered source data when features change
|
|
199
|
-
$effect(() => {
|
|
200
|
-
const features = this.features;
|
|
201
|
-
if (!mapManager.map || this.clustered)
|
|
202
|
-
return;
|
|
203
|
-
if (!untrack(() => this.enabled))
|
|
204
|
-
return;
|
|
205
|
-
mapManager.setDataSource(this.referenceId, features);
|
|
206
|
-
});
|
|
207
|
-
// Keep cluster source data in sync when features or display options change
|
|
208
|
-
$effect(() => {
|
|
209
|
-
void this.featuresByType;
|
|
210
|
-
if (!mapManager.map || !this.clustered)
|
|
211
|
-
return;
|
|
212
|
-
if (!untrack(() => this.enabled))
|
|
213
|
-
return;
|
|
214
|
-
this.renderer.syncFeatures();
|
|
215
|
-
});
|
|
216
|
-
// Push updated icon expressions to cluster layers when the pollutant changes
|
|
217
|
-
$effect(() => {
|
|
218
|
-
const thresholds = this.clusterIconThresholds;
|
|
219
|
-
if (!mapManager.map || !this.clustered || !thresholds.length)
|
|
220
|
-
return;
|
|
221
|
-
if (!untrack(() => this.enabled))
|
|
222
|
-
return;
|
|
223
|
-
this.renderer.syncThresholds();
|
|
224
|
-
});
|
|
225
|
-
// Re-apply when clustered mode switches or when data first arrives (cold load).
|
|
226
|
-
// featuresByType is tracked so this fires once data is available; untrack on apply()
|
|
227
|
-
// prevents reactive reads inside it from leaking into this effect's dependency graph.
|
|
228
|
-
$effect(() => {
|
|
229
|
-
void this.clustered;
|
|
230
|
-
const hasFeatures = Object.keys(this.featuresByType).length > 0;
|
|
231
|
-
if (!untrack(() => mapManager.map) || !hasFeatures)
|
|
232
|
-
return;
|
|
233
|
-
if (!untrack(() => this.enabled))
|
|
234
|
-
return;
|
|
235
|
-
untrack(() => this.apply());
|
|
236
|
-
});
|
|
237
|
-
// Sync selected icon scale via feature state
|
|
238
|
-
$effect(() => {
|
|
239
|
-
void this.selectedMonitorId;
|
|
240
|
-
if (!mapManager.map)
|
|
241
|
-
return;
|
|
242
|
-
untrack(() => this.applySelectedState());
|
|
243
|
-
});
|
|
244
|
-
});
|
|
245
|
-
}
|
|
246
|
-
apply() {
|
|
247
|
-
if (!mapManager.map)
|
|
248
|
-
return;
|
|
249
|
-
if (!this.tooltipManager.has(this.referenceId)) {
|
|
250
|
-
this.tooltipManager.register(this.referenceId, monitorTooltip);
|
|
251
|
-
}
|
|
252
|
-
if (this.clustered) {
|
|
253
|
-
if (mapManager.map.getLayer(this.referenceId))
|
|
254
|
-
mapManager.map.removeLayer(this.referenceId);
|
|
255
|
-
if (mapManager.map.getSource(this.referenceId))
|
|
256
|
-
mapManager.map.removeSource(this.referenceId);
|
|
257
|
-
clickManager.unregister([this.referenceId]);
|
|
258
|
-
this.tooltipManager.disable();
|
|
259
|
-
this.renderer.remove();
|
|
260
|
-
// Clustering may be toggled again before the icons arrive; only the latest apply runs.
|
|
261
|
-
this.supersedePending();
|
|
262
|
-
this.whenIconsLoad(() => {
|
|
263
|
-
this.renderer.apply(this.handleMonitorClick);
|
|
264
|
-
this.tooltipManager.enable();
|
|
265
|
-
this.applySelectedState();
|
|
266
|
-
});
|
|
267
|
-
}
|
|
268
|
-
else {
|
|
269
|
-
this.tooltipManager.disable();
|
|
270
|
-
this.renderer.remove();
|
|
271
|
-
this.tooltipManager.enable();
|
|
272
|
-
clickManager.unregister([this.referenceId]);
|
|
273
|
-
super.apply();
|
|
274
|
-
this.whenIconsLoad(() => {
|
|
275
|
-
clickManager.register([this.referenceId], this.handleMonitorClick);
|
|
276
|
-
this.applySelectedState();
|
|
277
|
-
});
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
remove() {
|
|
281
|
-
this.tooltipManager.disable();
|
|
282
|
-
clickManager.unregister([this.referenceId]);
|
|
283
|
-
this.renderer.remove();
|
|
284
|
-
super.remove();
|
|
285
|
-
}
|
|
286
|
-
applySelectedState() {
|
|
287
|
-
if (!mapManager.map)
|
|
288
|
-
return;
|
|
289
|
-
const layerIds = this.clustered ? this.renderer.unclusteredLayerIds : [this.referenceId];
|
|
290
|
-
const iconSize = this.selectedMonitorId
|
|
291
|
-
? ["match", ["get", "id"], this.selectedMonitorId, 1.3, 1]
|
|
292
|
-
: 1;
|
|
293
|
-
for (const layerId of layerIds) {
|
|
294
|
-
if (!mapManager.map.getLayer(layerId))
|
|
295
|
-
continue;
|
|
296
|
-
mapManager.map.setLayoutProperty(layerId, "icon-size", iconSize);
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
export const monitorsMapIntegration = new MonitorsMapIntegration();
|
|
301
|
-
export { MonitorsMapIntegration };
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { monitorsManager } from "../monitors/monitors.svelte";
|
|
2
|
-
import { monitorsMapIntegration } from "../monitors/monitors-map-integration.svelte";
|
|
3
|
-
import { collocationSitesMapIntegration } from "../collocation-sites/collocations-map-integration.svelte";
|
|
4
|
-
import { hmsFireMapIntegration } from "../hms/hms-fire-map-integration.svelte";
|
|
5
|
-
import { hmsSmokeMapIntegration } from "../hms/hms-smoke-map-integration.svelte";
|
|
6
|
-
import { evStationsMapIntegration } from "../ev-stations/ev-stations-map-integration.svelte";
|
|
7
|
-
import { windMapIntegration } from "../wind/wind.svelte";
|
|
8
|
-
import { mapStyleState } from "../map/map-style-state.svelte.js";
|
|
9
|
-
import { applyMapOptionDefaults } from "./map-option-defaults";
|
|
10
|
-
/** "Reset Map Options": restores every map option to its default. */
|
|
11
|
-
export function resetMapOptions() {
|
|
12
|
-
applyMapOptionDefaults({
|
|
13
|
-
manager: monitorsManager,
|
|
14
|
-
integration: monitorsMapIntegration,
|
|
15
|
-
collocationSites: collocationSitesMapIntegration,
|
|
16
|
-
hmsFire: hmsFireMapIntegration,
|
|
17
|
-
hmsSmoke: hmsSmokeMapIntegration,
|
|
18
|
-
evStations: evStationsMapIntegration,
|
|
19
|
-
wind: windMapIntegration,
|
|
20
|
-
// The basemap reset may start loading a new style; integrations skip the style while
|
|
21
|
-
// mapManager.styleLoading is set and the refresh on "style.load" re-applies them.
|
|
22
|
-
mapStyle: mapStyleState
|
|
23
|
-
}, monitorsManager.meta?.default_pollutant ?? null);
|
|
24
|
-
}
|
|
File without changes
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
//class ReactiveState<T> {
|
|
3
|
-
// private internalValue?: T = $state();
|
|
4
|
-
//
|
|
5
|
-
// constructor(initialValue?: T) {
|
|
6
|
-
// this.internalValue = initialValue;
|
|
7
|
-
// }
|
|
8
|
-
// get value(): T | undefined {
|
|
9
|
-
// return this.internalValue;
|
|
10
|
-
// }
|
|
11
|
-
//
|
|
12
|
-
// set value(newValue: T) {
|
|
13
|
-
// // Perform any validation or side effects here
|
|
14
|
-
// this.internalValue = newValue; // Update the reactive state
|
|
15
|
-
// }
|
|
16
|
-
//}
|
|
17
|
-
//
|
|
18
|
-
//class ShallowReactiveState<T> {
|
|
19
|
-
// private internalValue?: T = $state.raw();
|
|
20
|
-
//
|
|
21
|
-
// constructor(initialValue?: T) {
|
|
22
|
-
// this.internalValue = initialValue;
|
|
23
|
-
// }
|
|
24
|
-
// get value(): T | undefined {
|
|
25
|
-
// return this.internalValue;
|
|
26
|
-
// }
|
|
27
|
-
//
|
|
28
|
-
// set value(newValue: T) {
|
|
29
|
-
// // Perform any validation or side effects here
|
|
30
|
-
// this.internalValue = newValue; // Update the reactive state
|
|
31
|
-
// }
|
|
32
|
-
//}
|
|
33
|
-
//
|
|
34
|
-
//
|
|
35
|
-
//class DerivedReactiveState<T> {
|
|
36
|
-
// private internalValue?: T;
|
|
37
|
-
//
|
|
38
|
-
// constructor(expression: () => T) {
|
|
39
|
-
// this.internalValue = $derived.by(expression);
|
|
40
|
-
// }
|
|
41
|
-
// get value(): T | undefined {
|
|
42
|
-
// return this.internalValue;
|
|
43
|
-
// }
|
|
44
|
-
// set value(newValue: T) {
|
|
45
|
-
// this.internalValue = newValue;
|
|
46
|
-
// }
|
|
47
|
-
//}
|
|
48
|
-
//
|
|
49
|
-
//export function Derived<V>(value: () => V) {
|
|
50
|
-
// let ref: DerivedReactiveState<V> = new DerivedReactiveState<V>(value);
|
|
51
|
-
// return function <V, T = unknown>(
|
|
52
|
-
// _target: ClassAccessorDecoratorTarget<T, V>,
|
|
53
|
-
// _ctx: ClassAccessorDecoratorContext,
|
|
54
|
-
// ): ClassAccessorDecoratorResult<T, V> {
|
|
55
|
-
//
|
|
56
|
-
// return {
|
|
57
|
-
// get() {
|
|
58
|
-
// return ref.value as V;
|
|
59
|
-
// },
|
|
60
|
-
// };
|
|
61
|
-
// }
|
|
62
|
-
//}
|
|
63
|
-
//export function Reactive(shallow?: boolean) {
|
|
64
|
-
// return function <V, T = unknown>(
|
|
65
|
-
// _target: ClassAccessorDecoratorTarget<T, V>,
|
|
66
|
-
// _ctx: ClassAccessorDecoratorContext,
|
|
67
|
-
// ): ClassAccessorDecoratorResult<T, V> {
|
|
68
|
-
// let ref = shallow ? new ShallowReactiveState<V>() : new ReactiveState<V>();
|
|
69
|
-
//
|
|
70
|
-
// return {
|
|
71
|
-
// get(): V {
|
|
72
|
-
// return ref.value as V;
|
|
73
|
-
// },
|
|
74
|
-
// set(newValue): void {
|
|
75
|
-
// ref.value = newValue;
|
|
76
|
-
// },
|
|
77
|
-
// init(initialValue: V): V {
|
|
78
|
-
// ref.value = initialValue;
|
|
79
|
-
// return ref.value as V;
|
|
80
|
-
// }
|
|
81
|
-
// };
|
|
82
|
-
// };
|
|
83
|
-
//}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { Map as MaptilerMap } from "@maptiler/sdk";
|
|
2
|
-
import { MapLayerIntegration } from "../map/integrations/map-layer-integration.svelte";
|
|
3
|
-
declare class WindMapIntegration extends MapLayerIntegration {
|
|
4
|
-
referenceId: string;
|
|
5
|
-
beforeLayer: string;
|
|
6
|
-
enabled: boolean;
|
|
7
|
-
mapLayer: Parameters<MaptilerMap["addLayer"]>[0];
|
|
8
|
-
}
|
|
9
|
-
export declare const windMapIntegration: WindMapIntegration;
|
|
10
|
-
export type { WindMapIntegration };
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { WindLayer } from "@maptiler/weather";
|
|
2
|
-
import { baseLayerSeperator } from "../map/integrations/base-layer-seperator";
|
|
3
|
-
import { MapLayerIntegration } from "../map/integrations/map-layer-integration.svelte";
|
|
4
|
-
class WindMapIntegration extends MapLayerIntegration {
|
|
5
|
-
referenceId = "MapTiler Wind";
|
|
6
|
-
beforeLayer = baseLayerSeperator.referenceId;
|
|
7
|
-
enabled = $state(false);
|
|
8
|
-
mapLayer = new WindLayer({
|
|
9
|
-
id: this.referenceId,
|
|
10
|
-
opacity: 0.5
|
|
11
|
-
});
|
|
12
|
-
}
|
|
13
|
-
export const windMapIntegration = new WindMapIntegration();
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import { format, formatDistanceToNow } from "date-fns";
|
|
3
|
-
import DataBox from "$lib/components/DataBox.svelte";
|
|
4
|
-
import type { CollocationSiteMapFeature } from "./types";
|
|
5
|
-
import { monitorsManager } from "$lib/monitors/monitors.svelte";
|
|
6
|
-
import { getCurrentLevel } from "$lib/monitors/monitor-utils";
|
|
7
|
-
import type { MonitorLatest, SJVAirEntryLevel } from "@sjvair/sdk";
|
|
8
|
-
|
|
9
|
-
interface CollocationTooltipProps {
|
|
10
|
-
feature: CollocationSiteMapFeature;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const { feature }: CollocationTooltipProps = $props();
|
|
14
|
-
|
|
15
|
-
const data = $derived.by(() => {
|
|
16
|
-
const collocated = monitorsManager.latest?.get(feature.properties.colocated_id);
|
|
17
|
-
const reference = monitorsManager.latest?.get(feature.properties.reference_id);
|
|
18
|
-
|
|
19
|
-
return {
|
|
20
|
-
collocated: getMonitorData(collocated),
|
|
21
|
-
reference: getMonitorData(reference)
|
|
22
|
-
};
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
function getMonitorData(monitor: MonitorLatest | undefined) {
|
|
26
|
-
if (!monitor || !("value" in monitor.latest) || !monitorsManager.meta) return;
|
|
27
|
-
|
|
28
|
-
const entryType = monitorsManager.meta.entryType(monitor.latest.entry_type);
|
|
29
|
-
const level: SJVAirEntryLevel | undefined = getCurrentLevel(
|
|
30
|
-
monitor.latest.value,
|
|
31
|
-
entryType.asIter.levels!
|
|
32
|
-
);
|
|
33
|
-
|
|
34
|
-
const updateDuration = monitorsManager.meta.monitorType(monitor.type).expected_interval;
|
|
35
|
-
|
|
36
|
-
return {
|
|
37
|
-
color: level?.color ?? "",
|
|
38
|
-
header: entryType.label,
|
|
39
|
-
date: {
|
|
40
|
-
formatted: format(monitor.latest.timestamp, "h:mm:aaa EEEE MMM dd, yyyy"),
|
|
41
|
-
diference: formatDistanceToNow(monitor.latest.timestamp, {
|
|
42
|
-
addSuffix: true,
|
|
43
|
-
includeSeconds: true
|
|
44
|
-
})
|
|
45
|
-
},
|
|
46
|
-
monitorName: monitor.name,
|
|
47
|
-
subheading: `(${updateDuration} avg)`,
|
|
48
|
-
value: Math.round(parseInt(monitor.latest.value, 10)).toString()
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
</script>
|
|
52
|
-
|
|
53
|
-
{#if data}
|
|
54
|
-
<div class="flex flex-col gap-4">
|
|
55
|
-
{#if data.reference}
|
|
56
|
-
<div class="flex gap-2">
|
|
57
|
-
<DataBox
|
|
58
|
-
color={data.reference.color}
|
|
59
|
-
header={data.reference.header}
|
|
60
|
-
subheading={data.reference.subheading}
|
|
61
|
-
value={data.reference.value}
|
|
62
|
-
/>
|
|
63
|
-
<div class="flex flex-col">
|
|
64
|
-
<p class="leading-none">{data.reference.date.formatted}</p>
|
|
65
|
-
<h1 class="text-lg font-bold underline">{data.reference.monitorName}</h1>
|
|
66
|
-
<p class="leading-none">Reference monitor</p>
|
|
67
|
-
<div class="mt-auto">
|
|
68
|
-
<p class="text-base leading-none">Last updated</p>
|
|
69
|
-
<p class="text-base leading-none">{data.reference.date.diference}</p>
|
|
70
|
-
</div>
|
|
71
|
-
</div>
|
|
72
|
-
</div>
|
|
73
|
-
{:else}
|
|
74
|
-
<h1>Reference monitor disabled</h1>
|
|
75
|
-
{/if}
|
|
76
|
-
{#if data.collocated}
|
|
77
|
-
<div class="flex flex-row-reverse gap-2">
|
|
78
|
-
<DataBox
|
|
79
|
-
color={data.collocated.color}
|
|
80
|
-
header={data.collocated.header}
|
|
81
|
-
subheading={data.collocated.subheading}
|
|
82
|
-
value={data.collocated.value}
|
|
83
|
-
/>
|
|
84
|
-
<div class="flex flex-col">
|
|
85
|
-
<p class="leading-none">{data.collocated.date.formatted}</p>
|
|
86
|
-
<h1 class="text-lg font-bold underline">{data.collocated.monitorName}</h1>
|
|
87
|
-
<p class="leading-none">Collocated monitor</p>
|
|
88
|
-
<div class="mt-auto">
|
|
89
|
-
<p class="text-base leading-none">Last updated</p>
|
|
90
|
-
<p class="text-base leading-none">{data.collocated.date.diference}</p>
|
|
91
|
-
</div>
|
|
92
|
-
</div>
|
|
93
|
-
</div>
|
|
94
|
-
{:else}
|
|
95
|
-
<h1>Collocated monitor disabled</h1>
|
|
96
|
-
{/if}
|
|
97
|
-
</div>
|
|
98
|
-
{/if}
|