Skip to content

Conversation

@Magnusrm
Copy link
Contributor

@Magnusrm Magnusrm commented Dec 12, 2025

Description

Related Issue(s)

Verification/QA

  • Manual functionality testing
    • I have tested these changes manually
    • Creator of the original issue (or service owner) has been contacted for manual testing (or will be contacted when released in alpha)
    • No testing done/necessary
  • Automated tests
    • Unit test(s) have been added/updated
    • Cypress E2E test(s) have been added/updated
    • No automatic tests are needed here (no functional changes/additions)
    • I want someone to help me make some tests
  • UU/WCAG (follow these guidelines until we have our own)
    • I have tested with a screen reader/keyboard navigation/automated wcag validator
    • No testing done/necessary (no DOM/visual changes)
    • I want someone to help me perform accessibility testing
  • User documentation @ altinn-studio-docs
    • Has been added/updated
    • No functionality has been changed/added, so no documentation is needed
    • I will do that later/have created an issue
  • Support in Altinn Studio
    • Issue(s) created for support in Studio
    • This change/feature does not require any changes to Altinn Studio
  • Sprint board
    • The original issue (or this PR itself) has been added to the Team Apps project and to the current sprint board
    • I don't have permissions to do that, please help me out
  • Labels
    • I have added a kind/* and backport* label to this PR for proper release notes grouping
    • I don't have permissions to add labels, please help me out

Summary by CodeRabbit

  • New Features
    • Interactive map drawing toolbar with configurable shape tools and optional editable-geometry flag; supports GeoJSON and WKT formats and preserves item identifiers.
  • Bug Fixes / Improvements
    • Improved validation for geometry bindings and toolbar configuration.
    • Fixed map drawing toolbar icon styling and spritesheet path issues; included required draw styles.
  • Tests
    • New end-to-end tests covering polygon draw, delete, and save flows.
  • Chores
    • Updated map-drawing related dependencies and bumped public snapshots version.

✏️ Tip: You can customize this high-level summary in your review settings.

Magnusrm and others added 10 commits October 14, 2025 12:40
* Map refactoring

* Implementing reading new optional bindings

* Adding changes to map component from upstream/refactor/map

---------

Co-authored-by: Ole Martin Handeland <git@olemartin.org>
* Add toolbar config

* Add config validation

- Add config validation for geometryIsEditable & toolbar

* Update useValidateGeometriesBindings.ts

- Only check for geometryIsEditable if simpleBinding is not set when geometries are defined

* Update map config validation

- Update useValidateGeometriesBindings to check for geometryIsEditable if toolbar also is set
- Update Map.tsx to only show MapSingleMarker if simpleBinding is set

* Add PR fixes
- save to datamodel and load geometries to editable layer
* WIP edit geometry

* working editing geometries
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 12, 2025

📝 Walkthrough

Walkthrough

Adds Leaflet Draw support: new MapEditGeometries component and spritesheet-fix hook, toolbar config and binding (geometryIsEditable), geometry parsing/type additions (isEditable), binding validation updates, stylesheet import, dependency changes, and E2E tests for draw/delete flows. (39 words)

Changes

Cohort / File(s) Summary
Dependencies
package.json
Added leaflet-draw, react-leaflet-draw, @types/leaflet-draw, @terraformer/wkt; removed terraformer-wkt-parser.
Entry / Styles
src/index.tsx
Imported leaflet-draw/dist/leaflet.draw.css.
Map rendering & validation
src/layout/Map/Map.tsx, src/layout/Map/index.tsx
Render MapEditGeometries when a toolbar is present; conditionally render MapSingleMarker only when no toolbar and simpleBinding exists; add toolbar-aware binding validation using useExternalItem/useItemWhenType.
New editable geometries component
src/layout/Map/features/geometries/editable/MapEditGeometries.tsx
New exported component integrating Leaflet Draw: loads initial geometries, provides create/edit/delete handlers, syncs items to data model with UUID/ALTINN_ROW_ID, supports GeoJSON and WKT outputs.
Spritesheet CSS fix
src/layout/Map/features/geometries/editable/useLeafletDrawSpritesheetFix.ts
New hook injecting global CSS to fix leaflet-draw spritesheet URLs after bundling.
Static geometries rendering changes
src/layout/Map/features/geometries/fixed/MapGeometries.tsx, .../fixed/hooks.ts
Propagate isEditable through parsing pipeline; replace WKT parser with @terraformer/wkt (wktToGeoJSON); filter out editable geometries from static render when toolbar exists; use useItemWhenType.
Bindings validation updates
src/layout/Map/features/geometries/useValidateGeometriesBindings.ts, src/layout/Map/useValidateGeometriesBindings.ts
Extract/validate geometryIsEditable binding; include it in validation when toolbar present and enforce toolbar/simpleBinding interaction rules.
Types & config
src/layout/Map/types.ts, src/layout/Map/config.ts
Added isEditable?: boolean to RawGeometry and Geometry; added geometryIsEditable data binding and new toolbar config (polyline, polygon, rectangle, circle, marker boolean expressions).
E2E tests
test/e2e/integration/component-library/map.ts
New Cypress tests covering polygon draw and delete flows via the toolbar.
Version bump
snapshots.js
Bumped exported __version from "15.7.0" to "15.8.2".

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

🚥 Pre-merge checks | ✅ 3 | ❌ 2
❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive The PR description includes the main sections (Description, Related Issue(s), Verification/QA) and links to issue #3906, but lacks detailed explanation of what was changed and how. Add a detailed description of the technical changes made, such as new components, modified configurations, and the implementation approach for drawing and editing geometries.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Feat: Draw geometries on map' clearly and concisely summarizes the main feature addition in the changeset.
Linked Issues check ✅ Passed The PR fully implements the requirements from issue #3906: supports drawing multiple geometry types (rectangles, circles, lines, polygons), persists to data model, enables editing and deletion, and supports both GeoJSON and WKT formats.
Out of Scope Changes check ✅ Passed All code changes are directly related to implementing the map geometry drawing feature specified in issue #3906; no out-of-scope additions detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/3686-draw-on-map

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@Magnusrm Magnusrm added kind/product-feature Pull requests containing new features backport-ignore This PR is a new feature and should not be cherry-picked onto release branches labels Dec 12, 2025
@Magnusrm Magnusrm marked this pull request as ready for review January 5, 2026 08:09
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Fix all issues with AI Agents 🤖
In @package.json:
- Line 177: react-leaflet-draw 0.21.0 is incompatible with react-leaflet 5.0.0;
either pin react-leaflet to a pre-v5 compatible version or replace
react-leaflet-draw with a v5-compatible fork. Update package.json to remove or
replace "react-leaflet-draw": "0.21.0" with a maintained package (e.g.,
"@dbaltor00/react-leaflet-draw") or downgrade "react-leaflet" to a version
compatible with 0.21.0, then run install and update any imports/usages of
react-leaflet-draw in your codebase to the new package name (or adjust for API
differences) and run the app/tests to confirm everything works.

In @src/layout/Map/features/geometries/editable/MapEditGeometries.tsx:
- Line 52: Remove the debug console.log in the MapEditGeometries component that
prints initialGeometries: delete the line "console.log('Loading initial editable
geometries into MapEditGeometries', initialGeometries)" inside MapEditGeometries
(or replace it with a proper logger call like logger.debug if project logging is
required), ensure no other console.* calls remain in this file, and run the
linter/static analysis to confirm the warning is resolved.
- Around line 165-173: The update logic currently uses the index from the
filtered initialGeometries array which misaligns with the original form data;
change the lookup so you find the geometry's index in the unfiltered source by
matching altinnRowId (e.g. findIndex on the complete geometries array used to
build the form data) and then build the field path using that original index
(the same pattern used in onDeletedHandler), then call setLeafValue with the
corrected reference (keep using geometryBinding.field and geometryDataPath but
replace the filtered index with the found originalIndex) so the correct record
is updated.

In @src/layout/Map/features/geometries/useValidateGeometriesBindings.ts:
- Line 13: The call to useExternalItem(baseComponentId, 'Map') may return
undefined, so avoid directly accessing .toolbar; change the code that assigns
toolbar (the const toolbar = useExternalItem(baseComponentId, 'Map').toolbar
line) to first retrieve the item into a variable, check for existence (or use
optional chaining) and handle the missing-case (e.g., return early, provide a
default toolbar, or throw a clear error) so you never dereference undefined.
🧹 Nitpick comments (6)
package.json (1)

164-164: Consider pinning leaflet-draw to an exact version for consistency.

The project uses exact versioning for leaflet (1.9.4) but uses caret versioning for leaflet-draw (^1.0.4). For consistency and reproducible builds, consider pinning to an exact version.

src/layout/Map/features/geometries/fixed/MapGeometries.tsx (1)

33-36: Remove redundant optional chaining.

The optional chaining on geometries?.filter is unnecessary since the early return on lines 29-31 already guarantees geometries is truthy at this point.

🔎 Proposed fix
   // if toolbar is defined, we want to render editable geometries separately
   if (toolbar) {
-    geometries = geometries?.filter((g) => !g.isEditable);
+    geometries = geometries.filter((g) => !g.isEditable);
   }
src/layout/Map/features/geometries/editable/MapEditGeometries.tsx (4)

33-37: Consolidate repeated hook calls.

useDataModelBindingsFor is called three times with identical arguments. Extract the bindings once and destructure the needed properties.

🔎 Proposed fix
-  const geometryBinding = useDataModelBindingsFor(baseComponentId, 'Map')?.geometries;
-  const geometryDataBinding = useDataModelBindingsFor(baseComponentId, 'Map')?.geometryData;
-  const isEditableBinding = useDataModelBindingsFor(baseComponentId, 'Map')?.geometryIsEditable;
+  const bindings = useDataModelBindingsFor(baseComponentId, 'Map');
+  const geometryBinding = bindings?.geometries;
+  const geometryDataBinding = bindings?.geometryData;
+  const isEditableBinding = bindings?.geometryIsEditable;

155-156: Replace vague @ts-expect-error with proper typing.

Using @ts-expect-error with just "test" as the comment is poor practice. Either add proper typing for the layer or provide a meaningful explanation. As per coding guidelines, avoid type casting and any when possible.

🔎 Proposed fix
     e.layers.eachLayer((layer) => {
-      // @ts-expect-error test
-      const editedGeo = layer.toGeoJSON();
+      const editedGeo = (layer as L.GeoJSON).toGeoJSON() as FeatureWithId;

183-184: Same @ts-expect-error issue as in onEditedHandler.

🔎 Proposed fix
     e.layers.eachLayer((layer) => {
-      // @ts-expect-error test
-      const deletedGeo = layer.toGeoJSON();
+      const deletedGeo = (layer as L.GeoJSON).toGeoJSON() as FeatureWithId;

161-161: Use strict equality operator.

Using == instead of === can lead to unexpected type coercion.

🔎 Proposed fix
-      if (geometryType == 'WKT') {
+      if (geometryType === 'WKT') {
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 57d7ac0 and 971580d.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (11)
  • package.json
  • src/index.tsx
  • src/layout/Map/Map.tsx
  • src/layout/Map/config.ts
  • src/layout/Map/features/geometries/editable/MapEditGeometries.tsx
  • src/layout/Map/features/geometries/editable/useLeafletDrawSpritesheetFix.ts
  • src/layout/Map/features/geometries/fixed/MapGeometries.tsx
  • src/layout/Map/features/geometries/fixed/hooks.ts
  • src/layout/Map/features/geometries/useValidateGeometriesBindings.ts
  • src/layout/Map/index.tsx
  • src/layout/Map/types.ts
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Avoid using any type or type casting (as type) in TypeScript code; improve typing by avoiding casts and anys when refactoring
Use objects for managing query keys and functions, and queryOptions for sharing TanStack Query patterns across the system for central management

Files:

  • src/layout/Map/features/geometries/fixed/MapGeometries.tsx
  • src/layout/Map/features/geometries/editable/useLeafletDrawSpritesheetFix.ts
  • src/layout/Map/types.ts
  • src/layout/Map/Map.tsx
  • src/layout/Map/features/geometries/editable/MapEditGeometries.tsx
  • src/layout/Map/index.tsx
  • src/layout/Map/config.ts
  • src/layout/Map/features/geometries/fixed/hooks.ts
  • src/index.tsx
  • src/layout/Map/features/geometries/useValidateGeometriesBindings.ts
{**/*.module.css,**/*.{ts,tsx}}

📄 CodeRabbit inference engine (CLAUDE.md)

Use CSS Modules for component styling and leverage Digdir Design System components when possible

Files:

  • src/layout/Map/features/geometries/fixed/MapGeometries.tsx
  • src/layout/Map/features/geometries/editable/useLeafletDrawSpritesheetFix.ts
  • src/layout/Map/types.ts
  • src/layout/Map/Map.tsx
  • src/layout/Map/features/geometries/editable/MapEditGeometries.tsx
  • src/layout/Map/index.tsx
  • src/layout/Map/config.ts
  • src/layout/Map/features/geometries/fixed/hooks.ts
  • src/index.tsx
  • src/layout/Map/features/geometries/useValidateGeometriesBindings.ts
src/layout/*/{config,Component,index,config.generated}.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Layout components must follow standardized structure with config.ts, Component.tsx, index.tsx, and config.generated.ts files

Files:

  • src/layout/Map/index.tsx
  • src/layout/Map/config.ts
🧠 Learnings (2)
📚 Learning: 2025-11-25T12:53:54.399Z
Learnt from: CR
Repo: Altinn/app-frontend-react PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T12:53:54.399Z
Learning: Applies to src/layout/*/{config,Component,index,config.generated}.{ts,tsx} : Layout components must follow standardized structure with `config.ts`, `Component.tsx`, `index.tsx`, and `config.generated.ts` files

Applied to files:

  • src/layout/Map/config.ts
  • src/index.tsx
📚 Learning: 2025-11-25T12:53:54.399Z
Learnt from: CR
Repo: Altinn/app-frontend-react PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T12:53:54.399Z
Learning: Applies to {**/*.module.css,**/*.{ts,tsx}} : Use CSS Modules for component styling and leverage Digdir Design System components when possible

Applied to files:

  • src/index.tsx
🧬 Code graph analysis (7)
src/layout/Map/features/geometries/fixed/MapGeometries.tsx (2)
src/utils/layout/useNodeItem.ts (1)
  • useItemWhenType (15-33)
src/layout/Map/features/geometries/fixed/hooks.ts (1)
  • useMapParsedGeometries (52-65)
src/layout/Map/Map.tsx (5)
src/utils/layout/useNodeItem.ts (1)
  • useItemWhenType (15-33)
src/layout/Map/features/geometries/editable/MapEditGeometries.tsx (1)
  • MapEditGeometries (28-210)
src/layout/Map/features/layers/MapLayers.tsx (1)
  • MapLayers (41-62)
src/layout/Map/features/geometries/fixed/MapGeometries.tsx (1)
  • MapGeometries (25-62)
src/layout/Map/features/singleMarker/MapSingleMarker.tsx (1)
  • MapSingleMarker (39-87)
src/layout/Map/features/geometries/editable/MapEditGeometries.tsx (7)
src/utils/layout/useNodeItem.ts (1)
  • useItemWhenType (15-33)
src/utils/layout/hooks.ts (1)
  • useDataModelBindingsFor (102-112)
src/layout/Map/features/geometries/fixed/hooks.ts (1)
  • useMapParsedGeometries (52-65)
src/features/saveToGroup/useSaveToGroup.ts (1)
  • toRelativePath (19-24)
src/features/formData/FormDataWrite.tsx (1)
  • FD (720-1178)
src/layout/Map/features/geometries/editable/useLeafletDrawSpritesheetFix.ts (1)
  • useLeafletDrawSpritesheetFix (13-32)
src/features/formData/types.ts (1)
  • ALTINN_ROW_ID (39-39)
src/layout/Map/index.tsx (1)
src/utils/layout/hooks.ts (1)
  • useExternalItem (16-22)
src/layout/Map/config.ts (1)
src/codegen/CG.ts (1)
  • CG (25-57)
src/layout/Map/features/geometries/fixed/hooks.ts (1)
src/features/saveToGroup/useSaveToGroup.ts (1)
  • toRelativePath (19-24)
src/layout/Map/features/geometries/useValidateGeometriesBindings.ts (3)
src/features/datamodel/DataModelsProvider.tsx (1)
  • DataModels (381-429)
src/features/form/layout/LayoutsContext.tsx (1)
  • useLayoutLookups (102-102)
src/utils/layout/hooks.ts (1)
  • useExternalItem (16-22)
🪛 GitHub Check: Type-checks, eslint, unit tests and SonarCloud
src/layout/Map/features/geometries/editable/MapEditGeometries.tsx

[warning] 52-52:
Unexpected console statement. Only these console methods are allowed: warn, error

🔇 Additional comments (13)
src/index.tsx (1)

43-44: LGTM!

The leaflet-draw CSS import is correctly placed alongside the existing Leaflet CSS import, which is necessary for styling the drawing toolbar controls introduced in this PR.

src/layout/Map/types.ts (1)

3-14: LGTM!

The isEditable property additions to both RawGeometry and Geometry types are consistent and correctly typed as optional booleans, supporting the new geometry editing functionality.

src/layout/Map/index.tsx (1)

47-59: LGTM! Comprehensive validation logic.

The validation rules correctly enforce the mutual constraints:

  1. geometryIsEditable and simpleBinding are mutually exclusive
  2. geometryIsEditable requires a toolbar to be defined
  3. toolbar requires geometryIsEditable binding

The error messages are clear and actionable for developers.

src/layout/Map/features/geometries/editable/useLeafletDrawSpritesheetFix.ts (1)

13-31: LGTM! Good workaround for webpack asset path issues.

The hook correctly addresses the leaflet-draw spritesheet path problem by injecting a global style override once. The deduplication check via STYLE_ID prevents multiple injections across component remounts.

Note: The style element is intentionally not cleaned up on unmount since the fix should persist globally throughout the app's lifecycle.

src/layout/Map/Map.tsx (1)

55-66: LGTM! Clean conditional rendering logic.

The rendering flow correctly handles the two mutually exclusive modes:

  • Toolbar mode: Renders MapEditGeometries for drawing/editing geometries
  • Simple binding mode: Renders MapSingleMarker for single marker placement

This aligns well with the validation rules enforced in Map/index.tsx.

src/layout/Map/features/geometries/useValidateGeometriesBindings.ts (1)

42-57: Validation logic for geometryIsEditable looks correct.

The conditional addition of geometryIsEditable validation when a toolbar is present and geometries binding exists (without simpleBinding) aligns with the feature requirements.

src/layout/Map/config.ts (2)

43-50: Well-structured data model binding for geometryIsEditable.

The binding is correctly marked as optional with a clear description explaining that geometries won't be editable if not specified.


176-216: Toolbar configuration is well-designed.

The toolbar property uses expression-based boolean controls for each geometry type, with safe defaults (false). The structure aligns with the codegen patterns used elsewhere in the codebase. Based on learnings, this follows the standardized layout component structure.

src/layout/Map/features/geometries/editable/MapEditGeometries.tsx (1)

192-209: Render logic looks correct.

The EditControl is properly configured with toolbar options and event handlers. The FeatureGroup ref setup allows managing layers programmatically.

src/layout/Map/features/geometries/fixed/hooks.ts (4)

26-27: Proper isEditable propagation in raw geometry extraction.

The isEditablePath resolution follows the same pattern as labelPath and dataPath, with a sensible default of 'isEditable'. The field is correctly picked from form data items.

Also applies to: 40-40


43-49: Dependency array correctly updated.

Adding dataModelBindings?.geometryIsEditable ensures the memoized value recalculates when the isEditable binding changes.


78-85: isEditable correctly propagated through parsing.

Both WKT and GeoJSON parsing paths now include isEditable in the output geometry objects, maintaining consistency with the RawGeometry and Geometry type extensions.


3-3: Verified import migration to @terraformer/wkt.

The wktToGeoJSON function is the correct export from @terraformer/wkt for converting WKT geometry strings to GeoJSON objects, and its usage aligns with the package documentation.

Comment on lines +165 to +173
initialGeometries?.forEach((g, index) => {
if (g.altinnRowId === altinnRowId) {
const field = `${geometryBinding.field}[${index}].${geometryDataPath}`;
setLeafValue({
reference: { dataType: geometryDataBinding?.dataType, field },
newValue: geoString,
});
}
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check the file and examine how initialGeometries is derived
head -200 src/layout/Map/features/geometries/editable/MapEditGeometries.tsx | cat -n

Repository: Altinn/app-frontend-react

Length of output: 8103


🏁 Script executed:

#!/bin/bash
# Search for useMapParsedGeometries and related hooks
rg -n "useMapParsedGeometries|initialGeometries" src/layout/Map/features/geometries/ -B 2 -A 5

Repository: Altinn/app-frontend-react

Length of output: 8415


🏁 Script executed:

#!/bin/bash
# Check line 38 and surrounding context to understand the filtering
sed -n '30,50p' src/layout/Map/features/geometries/editable/MapEditGeometries.tsx | cat -n

Repository: Altinn/app-frontend-react

Length of output: 1184


🏁 Script executed:

#!/bin/bash
# Check useMapRawGeometries to understand the data structure
rg -n -A 20 "export function useMapRawGeometries" src/layout/Map/features/geometries/fixed/hooks.ts

Repository: Altinn/app-frontend-react

Length of output: 1147


🏁 Script executed:

#!/bin/bash
# Check if Geometry type includes original index information
rg -n "interface Geometry\|type Geometry" src/layout/Map/features/geometries/ -A 10

Repository: Altinn/app-frontend-react

Length of output: 51


🏁 Script executed:

#!/bin/bash
# Find the Geometry type definition
rg -n "export.*type Geometry|export.*interface Geometry" src/layout/Map/features/geometries/ -B 2 -A 8

Repository: Altinn/app-frontend-react

Length of output: 51


🏁 Script executed:

#!/bin/bash
# Check the full parseGeometries function to see how Geometry objects are created
rg -n -A 30 "function parseGeometries" src/layout/Map/features/geometries/fixed/hooks.ts

Repository: Altinn/app-frontend-react

Length of output: 1323


🏁 Script executed:

#!/bin/bash
# Verify the issue: check if Geometry type is exported and see its definition
cat src/layout/Map/features/geometries/fixed/hooks.ts | head -90 | tail -30

Repository: Altinn/app-frontend-react

Length of output: 996


🏁 Script executed:

#!/bin/bash
# Check the RawGeometry and Geometry types more carefully
rg -n "RawGeometry|interface Geometry\|type Geometry" src/layout/Map/features/geometries/fixed/hooks.ts -B 1 -A 5

Repository: Altinn/app-frontend-react

Length of output: 1395


🏁 Script executed:

#!/bin/bash
# Check the types definition file to see Geometry and RawGeometry structures
cat src/layout/Map/types.ts | head -100

Repository: Altinn/app-frontend-react

Length of output: 332


Use altinnRowId for field lookup instead of filtered array index.

The code finds the geometry by altinnRowId but then uses the index from the filtered initialGeometries array to build the update path. Since initialGeometries filters by isEditable, the indices no longer match the original form data array. For example, if form data contains 4 geometries but only 3 are editable, the filtered array indices will be off by one or more, causing updates to the wrong record.

The onDeletedHandler (below) already uses the correct pattern with altinnRowId-based lookup. Apply the same approach to onEditedHandler to find the record in the unfiltered data source:

initialGeometries?.forEach((g, index) => {
  if (g.altinnRowId === altinnRowId) {
    const field = `${geometryBinding.field}[${index}].${geometryDataPath}`;

Instead, look up the original index from the complete geometry list or use setLeafValue with a reference that supports altinnRowId matching.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In @src/layout/Map/features/geometries/editable/MapEditGeometries.tsx around
lines 165-173, The update logic currently uses the index from the filtered
initialGeometries array which misaligns with the original form data; change the
lookup so you find the geometry's index in the unfiltered source by matching
altinnRowId (e.g. findIndex on the complete geometries array used to build the
form data) and then build the field path using that original index (the same
pattern used in onDeletedHandler), then call setLeafValue with the corrected
reference (keep using geometryBinding.field and geometryDataPath but replace the
filtered index with the found originalIndex) so the correct record is updated.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
package.json (1)

177-177: Duplicate: react-leaflet-draw 0.21.0 compatibility issue with react-leaflet 5.0.0 remains unresolved.

As flagged in previous review comments, react-leaflet-draw 0.21.0 is incompatible with react-leaflet 5.0.0 due to breaking API changes in v5. The PR description mentions manual functionality testing was performed—please confirm whether this compatibility issue manifested during testing or if there's a workaround in place.

If the issue was not encountered, please verify by running the following script to check the actual react-leaflet version in use and search for any runtime compatibility patches or workarounds in the codebase:

#!/bin/bash
# Check react-leaflet version and search for compatibility workarounds

echo "=== Checking react-leaflet version ==="
grep '"react-leaflet"' package.json

echo -e "\n=== Searching for react-leaflet-draw usage ==="
rg -n --type=ts --type=tsx -C3 'react-leaflet-draw'

echo -e "\n=== Searching for potential compatibility patches or version checks ==="
rg -n --type=ts --type=tsx 'EditControl|FeatureGroup.*edit'
🧹 Nitpick comments (1)
src/layout/Map/features/geometries/useValidateGeometriesBindings.ts (1)

52-57: Consider adding a default property or explicit error for geometryIsEditable.

The geometryIsEditable validation entry lacks a defaultProperty (unlike geometryLabel and geometryData). If the binding is not provided when the toolbar exists, the validation loop will construct a field path containing the literal string "undefined" (e.g., geometries[0].undefined), leading to either a lookup error or a confusing error message referencing an "undefined" property.

While the validation will still catch the configuration error, the developer experience could be improved by either:

  1. Adding defaultProperty: 'isEditable' (if a default field name makes sense), or
  2. Adding an explicit check before the loop that produces a clearer error like: "geometryIsEditable binding is required when toolbar is present"
🔎 Option 1: Add a default property
   if (bindings?.geometries && !bindings?.simpleBinding && toolbar) {
     fieldsToValidate = [
       ...fieldsToValidate,
-      { binding: geometryIsEditable, name: 'geometryIsEditable', expectedType: 'boolean' },
+      { binding: geometryIsEditable, name: 'geometryIsEditable', expectedType: 'boolean', defaultProperty: 'isEditable' },
     ];
   }
🔎 Option 2: Add explicit validation with clearer error
   if (bindings?.geometries && !bindings?.simpleBinding && toolbar) {
+    if (!geometryIsEditable) {
+      errors.push('geometryIsEditable binding is required when toolbar is present');
+    }
     fieldsToValidate = [
       ...fieldsToValidate,
       { binding: geometryIsEditable, name: 'geometryIsEditable', expectedType: 'boolean' },
     ];
   }
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 971580d and fdf69f0.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (3)
  • package.json
  • src/layout/Map/features/geometries/editable/MapEditGeometries.tsx
  • src/layout/Map/features/geometries/useValidateGeometriesBindings.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/layout/Map/features/geometries/editable/MapEditGeometries.tsx
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Avoid using any type or type casting (as type) in TypeScript code; improve typing by avoiding casts and anys when refactoring
Use objects for managing query keys and functions, and queryOptions for sharing TanStack Query patterns across the system for central management

Files:

  • src/layout/Map/features/geometries/useValidateGeometriesBindings.ts
{**/*.module.css,**/*.{ts,tsx}}

📄 CodeRabbit inference engine (CLAUDE.md)

Use CSS Modules for component styling and leverage Digdir Design System components when possible

Files:

  • src/layout/Map/features/geometries/useValidateGeometriesBindings.ts
🧬 Code graph analysis (1)
src/layout/Map/features/geometries/useValidateGeometriesBindings.ts (4)
src/layout/layout.ts (1)
  • IDataModelBindings (61-64)
src/features/datamodel/DataModelsProvider.tsx (1)
  • DataModels (381-429)
src/features/form/layout/LayoutsContext.tsx (1)
  • useLayoutLookups (102-102)
src/utils/layout/hooks.ts (1)
  • useExternalItem (16-22)
🔇 Additional comments (2)
package.json (1)

57-57: Supporting dependencies look good, pending resolution of Line 177.

The additions of @types/leaflet-draw, @terraformer/wkt, and leaflet-draw are appropriate for the drawing functionality. The use of @terraformer/wkt instead of the deprecated terraformer-wkt-parser is a good choice. However, these dependencies' effectiveness depends on resolving the compatibility issue with react-leaflet-draw at Line 177.

Also applies to: 145-145, 164-164

src/layout/Map/features/geometries/useValidateGeometriesBindings.ts (1)

13-13: Toolbar retrieval now safely handles missing component.

The optional chaining (?.toolbar) properly addresses the past review concern about potential runtime errors when the component is not found.

@sonarqubecloud
Copy link

Quality Gate Failed Quality Gate failed

Failed conditions
16.7% Coverage on New Code (required ≥ 45%)
10.2% Condition Coverage on New Code (required ≥ 45%)
C Reliability Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport-ignore This PR is a new feature and should not be cherry-picked onto release branches kind/product-feature Pull requests containing new features

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Draw geometries on map component

2 participants