mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-08 00:03:07 +00:00
* Remove $$props.field usage * Rename slots to ensure no hyphen * _props * _trigger * OnSelectedIteration type correct capitalization * rename _content * Remove afterUpdate * Migrate everything to svelte 5 * array bind * Fix popover * type never * nit fixes * Fixed many trivial errors * onClick * Fix errors * use let: * nit typing * fix: wrap state_referenced_locally vars with untrack() Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Add untrack import * Fix all syntax errors due to untrack migration * Fix undefined errors * Fix more undefined errors * untrack(() => initialOpen) * svelte-ignore * Fix state_descriptors_fixed error in Chart.svelte Use $state.snapshot() to pass plain copies of data/options to Chart.js instead of $state proxies. Chart.js's listenArrayEvents tries to define property descriptors on data arrays, which Svelte 5 proxies reject. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * nit typing * Merge issue * Fix "path is not set" error in resource picker / editor * Fix InputTransformForm error when rerunning some flows * fix npm run check --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
159 lines
3.5 KiB
Svelte
159 lines
3.5 KiB
Svelte
<script lang="ts">
|
|
import { run } from 'svelte/legacy';
|
|
|
|
import { Map, View, Feature } from 'ol'
|
|
import { Fill, Stroke, Style, Text } from 'ol/style.js'
|
|
import { useGeographic } from 'ol/proj.js'
|
|
import { OSM, Vector as VectorSource } from 'ol/source.js'
|
|
import { Vector as VectorLayer, Tile as TileLayer } from 'ol/layer.js'
|
|
import { Point } from 'ol/geom.js'
|
|
import { defaults as defaultControls } from 'ol/control.js'
|
|
import CircleStyle from 'ol/style/Circle.js'
|
|
|
|
interface Marker {
|
|
lon: number
|
|
lat: number
|
|
title?: string
|
|
radius?: number
|
|
color?: string
|
|
strokeWidth?: number
|
|
strokeColor?: string
|
|
}
|
|
|
|
interface Props {
|
|
lon?: number | undefined;
|
|
lat?: number | undefined;
|
|
zoom?: number | undefined;
|
|
markers?: Marker[] | string | undefined;
|
|
}
|
|
|
|
let {
|
|
lon = undefined,
|
|
lat = undefined,
|
|
zoom = undefined,
|
|
markers = undefined
|
|
}: Props = $props();
|
|
|
|
const LAYER_NAME = {
|
|
MARKER: 'Marker'
|
|
} as const
|
|
|
|
let map: Map | undefined = $state(undefined)
|
|
let mapElement: HTMLDivElement | undefined = $state(undefined)
|
|
|
|
function getLayersByName(name: keyof typeof LAYER_NAME) {
|
|
return map
|
|
?.getLayers()
|
|
?.getArray()
|
|
?.filter((l) => l.getProperties().name === LAYER_NAME[name])
|
|
}
|
|
|
|
function getMarkerArray(): Marker[] | undefined {
|
|
let array: Marker[] | undefined = undefined
|
|
try {
|
|
if (typeof markers === 'string') {
|
|
const json = JSON.parse(markers)
|
|
array = Array.isArray(json) ? json : [json]
|
|
} else {
|
|
array = markers
|
|
}
|
|
return array?.filter((m) => !isNaN(+m.lat) && !isNaN(+m.lon))
|
|
} catch (error) {
|
|
console.log(error)
|
|
return undefined
|
|
}
|
|
}
|
|
|
|
function createMarkerLayers() {
|
|
const markerArray = getMarkerArray()
|
|
return markerArray?.map((m) => {
|
|
return new VectorLayer({
|
|
properties: {
|
|
name: LAYER_NAME.MARKER
|
|
},
|
|
source: new VectorSource({
|
|
features: [
|
|
new Feature({
|
|
geometry: new Point([+m.lon, +m.lat]),
|
|
label: m.title,
|
|
name: m.title
|
|
})
|
|
]
|
|
}),
|
|
style: new Style({
|
|
image: new CircleStyle({
|
|
radius: m.radius ?? 5,
|
|
fill: new Fill({
|
|
color: m.color ?? '#dc2626'
|
|
}),
|
|
stroke: new Stroke({
|
|
color: m.strokeColor ?? '#fca5a5',
|
|
width: m.strokeWidth ?? 3
|
|
})
|
|
}),
|
|
text: new Text({
|
|
text: m.title,
|
|
offsetY: -15,
|
|
fill: new Fill({
|
|
color: '#000'
|
|
})
|
|
})
|
|
})
|
|
})
|
|
})
|
|
}
|
|
|
|
function updateMarkers() {
|
|
const layers = getLayersByName('MARKER')
|
|
if (layers?.length) {
|
|
layers.forEach((l) => map?.removeLayer(l))
|
|
}
|
|
createMarkerLayers()?.forEach((l) => map?.addLayer(l))
|
|
}
|
|
|
|
run(() => {
|
|
if (!map && mapElement) {
|
|
useGeographic()
|
|
map = new Map({
|
|
target: mapElement,
|
|
layers: [
|
|
new TileLayer({
|
|
source: new OSM()
|
|
}),
|
|
...(createMarkerLayers() || [])
|
|
],
|
|
view: new View({
|
|
center: [lon ?? 0, lat ?? 0],
|
|
zoom: zoom ?? 2
|
|
}),
|
|
controls: defaultControls({
|
|
attribution: false
|
|
})
|
|
})
|
|
if (lat && lon) {
|
|
map.getView().setCenter([lon, lat])
|
|
}
|
|
|
|
if (map && zoom) {
|
|
map.getView().setZoom(zoom)
|
|
}
|
|
|
|
if (map && markers) {
|
|
updateMarkers()
|
|
}
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<div bind:this={mapElement} class="w-full h-[300px]"></div>
|
|
|
|
<style global lang="postcss">
|
|
.ol-overlaycontainer-stopevent {
|
|
@apply flex flex-col justify-start items-end;
|
|
}
|
|
.ol-control button {
|
|
@apply w-7 h-7 center-center bg-surface border text-secondary
|
|
rounded mt-1 mr-1 shadow duration-200 hover:bg-surface-hover focus:bg-surface-hover;
|
|
}
|
|
</style>
|