feat: show basic map for "fixed" assets

this is just to get our foot in the door so to speak.  not sure yet
how sophisticated this map needs to be etc. but thought it would be
nice to at least show something..since the data is available
This commit is contained in:
Lance Edgar 2026-03-14 22:38:30 -05:00
parent d65de5e8ce
commit eee2a1df65
3 changed files with 111 additions and 1 deletions

View file

@ -10,5 +10,74 @@
</b-notification>
% endif
<div style="display: flex; margin-right: 0.5rem;">
## main form
<div style="flex-grow: 1;">
${parent.page_content()}
</div>
## location map
% if map_polygon:
<div ref="map" style="flex-grow: 2; height: 500px;" />
% endif
</div>
</%def>
<%def name="modify_vue_vars()">
${parent.modify_vue_vars()}
% if map_polygon:
<script>
ThisPageData.map = null
ThisPage.mounted = function() {
this.map = new maplibregl.Map({
container: this.$refs.map,
style: 'https://tiles.openfreemap.org/styles/liberty',
center: ${json.dumps(map_center)|n},
zoom: 16,
})
this.map.on('load', () => {
this.map.addSource('assetGeometry', {
'type': 'geojson',
'data': {
'type': 'Feature',
'geometry': {
'type': 'Polygon',
'coordinates': ${json.dumps(map_polygon)|n},
}
}
})
this.map.addLayer({
'id': 'assetGeometry',
'source': 'assetGeometry',
'type': 'line',
'paint': {
'line-color': 'orange',
'line-width': 2,
},
})
this.map.fitBounds(${json.dumps(map_bounds)|n}, {
linear: true,
})
this.map.addControl(new maplibregl.FullscreenControl())
this.map.addControl(new maplibregl.NavigationControl(), 'top-left')
this.map.addControl(new maplibregl.ScaleControl({
maxWidth: 80,
unit: 'imperial',
}))
})
}
</script>
% endif
</%def>

View file

@ -1,6 +1,16 @@
<%inherit file="wuttaweb:templates/base.mako" />
<%namespace file="/wuttafarm-components.mako" import="make_wuttafarm_components" />
<%def name="head_tags()">
${parent.head_tags()}
## TODO: this likely does not belong in the base template, and should be
## included per template where actually needed. but this is easier for now.
<script src="https://unpkg.com/maplibre-gl@latest/dist/maplibre-gl.js"></script>
<link rel="stylesheet" href="https://unpkg.com/maplibre-gl@latest/dist/maplibre-gl.css" />
</%def>
<%def name="index_title_controls()">
${parent.index_title_controls()}

View file

@ -23,6 +23,7 @@
Master view for Assets
"""
import re
from collections import OrderedDict
from webhelpers2.html import tags
@ -359,6 +360,36 @@ class AssetMasterView(WuttaFarmMasterView):
return buttons
def get_template_context(self, context):
context = super().get_template_context(context)
if self.viewing:
asset = context["instance"]
# add location geometry if applicable
if asset.is_fixed and asset.farmos_uuid and not self.app.is_standalone():
# TODO: eventually sync GIS data, avoid this API call?
client = get_farmos_client_for_user(self.request)
result = client.asset.get_id(asset.asset_type, asset.farmos_uuid)
geometry = result["data"]["attributes"]["intrinsic_geometry"]
context["map_center"] = [geometry["lon"], geometry["lat"]]
context["map_bounds"] = [
[geometry["left"], geometry["bottom"]],
[geometry["right"], geometry["top"]],
]
if match := re.match(
r"^POLYGON \(\((?P<points>[^\)]+)\)\)$", geometry["value"]
):
points = match.group("points").split(", ")
points = [[float(pt) for pt in pair.split(" ")] for pair in points]
context["map_polygon"] = [points]
return context
def get_version_joins(self):
"""
We override this to declare the relationship between the