Skip to content

feat(gui): multi-layer Map component (sync to development) - #592

Merged
ArmenSl merged 11 commits into
developmentfrom
sync/maps-to-development
Sep 8, 2026
Merged

ArmenSl merged 11 commits into
developmentfrom
sync/maps-to-development

Conversation

@ArmenSl

@ArmenSl ArmenSl commented Sep 8, 2026

Copy link
Copy Markdown
Collaborator

Sync of the Map component feature (with all review fixes, 6245221) to development. #589 was accidentally based on and merged into master; this lands the identical commits on development so the v7.14.0 release PR (#591) reconciles cleanly.

ArmenSl and others added 11 commits July 6, 2026 14:26
release: v7.11.1 — honest Multiplicity.max typing + idiomatic empty lists
release: v7.11.2 — B-UML export keeps every object model in multi-object projects
release: v7.12.0 — Ollama support for agents
release: v7.13.0 — LLM-driven GUI personalization
- Replace OSM iframe preview with react-leaflet MapContainer + TileLayer
- Add data-source trait (class picker) + latitude-field, longitude-field,
  marker-label-field selects; geo-field options populate dynamically when
  a class is chosen
- Inject Leaflet CSS into GrapesJS iframe canvas to fix tile/marker rendering
- Fix: remove 'map' from removeUnwantedBlocks — our custom block used the
  same id and was being deleted on every editor load
- Add leaflet ^1.9.4, react-leaflet ^4.2.1, @types/leaflet to package.json
- Add latitudeField, longitudeField, markerLabelField i18n keys to all 6 locales
New Map view component end-to-end across the BESSER stack. Markers bind to
a domain Class with lat/lng attributes and are fetched from the auto-generated
REST endpoint. No API key required.

- Metamodel: rewrite Map(ViewComponent) with center_lat/lng, zoom,
  latitude_field, longitude_field, marker_label_field, data_binding;
  WorldMap/LocationMap kept as thin subclasses
- json_to_buml: add parse_map(); re-route type==map away from EmbeddedContent
- buml_to_json: add _apply_map_attributes(); add Map/WorldMap/LocationMap
  to exec() safe_globals
- Code builder: add _write_map() for Python codegen round-trips
- React generator: new MapBlock.tsx (react-leaflet, OSM tiles, per-row
  markers); leaflet/react-leaflet added to package.json.j2
- Flutter generator: FlutterMap widget on main screen; flutter_map + latlong2
  added to pubspec.yaml.j2
- Docs: gui.rst Map Component section; react.rst MapBlock; flutter.rst FlutterMap
- Tests: 20 new tests (metamodel, converter round-trip, code builder,
  React generator, Flutter generator)
- Submodule: bump frontend pointer to feat/maps_webapp_component
Replace the single-binding flat-field Map with a layers list. Each
MapLayer declares a type (points / geojson / choropleth / heatmap),
binds its own domain class, and carries typed field references with
auto-detection when layer_type is omitted.

Metamodel (besser/BUML/metamodel/gui/dashboard.py)
- Add MapLayerType enum (points, geojson, choropleth, heatmap)
- Add MapLayer(NamedElement) with field-ref setters and
  effective_layer_type() auto-detection
- Rewrite Map.__init__ to accept layers: List[MapLayer]; remove flat
  latitude_field / longitude_field / marker_label_field

Converters
- json_to_buml: rewrite parse_map to parse map-layers JSON attribute
  into MapLayer list, resolving class/field UUIDs with name fallback
- buml_to_json: rewrite _apply_map_attributes to serialise layers list;
  add MapLayer/MapLayerType to exec sandbox safe_globals; add missing
  builtins (next, hasattr, getattr, isinstance)

Code builder (besser/utilities/buml_code_builder/gui_model_builder.py)
- Add _write_map_layer helper; rewrite _write_map to emit MapLayer list
  with field lookups via direct domain_model variable reference

React generator (besser/generators/react/)
- serialization.py: emit node[layers] list per Map component
- page_builder.py: pass layers= prop to <MapBlock>
- Rebuild MapBlock.tsx template: four labelled layer renderers
  (PointsLayer, GeoJsonLayer, ChoroplethLayer, HeatLayer), graceful
  degradation, choropleth legend, custom-icon extension block
- package.json.j2: add leaflet.heat ^0.2.0 + @types/leaflet.heat ^0.2.4

Docs
- Add docs/source/generators/maps.rst (layer contracts, auto-detection
  rules, worked example, extending guide)
- Update gui.rst Map section with MapLayer/MapLayerType reference
- Update react.rst dependency table; add maps to generators.rst toctree

Tests
- Add tests/BUML/metamodel/gui/test_map_layer.py (22 tests)
- Add tests/utilities/.../test_map_converter_roundtrip.py (12 tests)
- Update tests/generators/react/test_react_generator.py — MapLayer
  fixture, leaflet.heat assertion
- Update tests/BUML/metamodel/gui/test_gui.py — migrate 5 stale
  flat-field Map tests to the new layers API
…und-trip

- .gitmodules: restore upstream frontend submodule URL/branch; reset the
  submodule pointer to the development one (frontend changes land via the
  frontend PR).
- MapBlock.tsx: rewrite on plain leaflet (react-leaflet is Hippocratic-2.1
  licensed); popup labels and legend titles are now HTML-escaped, marker
  icons are an inline SVG (no unpkg CDN), heat layers no longer stack on
  re-fetch, and centre/zoom prop changes move the map after mount.
- package.json.j2 + react.py: leaflet deps and MapBlock.tsx only ship when
  the GUI model contains a Map component; react-leaflet removed.
- gui_model_builder: resolve domain_model via globals().get() again (bare
  reference raised NameError for chart/table exports without a domain
  model); emit concrete Map subclass names, layer styling, created_vars.
- dashboard.py: Map() params are keyword-only with real defaults
  (0.0/0.0/10) and a deprecated no-op data kwarg so pre-7.14 callers fail
  loudly or keep working instead of silently binding rows to title;
  layer_type raises ValueError like other enum setters; drop
  getattr/except-pass guards.
- gui_diagram_converter: map-layers is assigned unconditionally (setdefault
  resurrected deleted layers; empty list now representable as []).
- chart_parsers: replace blanket per-layer except with an isinstance guard.
- flutter: OSM attribution widget, drop unused http/dart:convert imports
  and http pubspec dep; docs no longer claim data-bound markers (React-only
  for now — the FlutterGenerator criterion of #479 stays open).
- docs/tests updated accordingly; pubspec test no longer rmtree's a real
  cwd/output directory.
@ArmenSl
ArmenSl merged commit b666e9b into development Sep 8, 2026
4 checks passed
@ArmenSl
ArmenSl deleted the sync/maps-to-development branch September 8, 2026 13:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants