Skip to content

fix(desktop): scrub Print Layout blocks when their layer is deleted - #1995

Merged
giswqs merged 1 commit into
mainfrom
fix/1992-print-layout-followup
Aug 18, 2026
Merged

fix(desktop): scrub Print Layout blocks when their layer is deleted#1995
giswqs merged 1 commit into
mainfrom
fix/1992-print-layout-followup

Conversation

@giswqs

@giswqs giswqs commented Aug 18, 2026

Copy link
Copy Markdown
Member

Follow-up to #1994. Its last review round raised two findings after the PR had already been merged, so they land here instead.

Dangling layer id in a saved project

removeLayer and deleteLayerGroup already scrub storymap, widgets, comments and legend for the layers being deleted, but not the new printLayout. Deleting a layer that a Print Layout data or atlas block referenced, then saving without reopening the composer, wrote a block pointing at a layer the file no longer carries. It self-healed on the next project load (via the load-time scrub) or the next time the composer was opened, leaving a window where the saved file disagreed with its own layer set, unlike every sibling section.

Adds scrubPrintLayoutForRemovedLayers, the delete-time counterpart of the existing load-time scrubPrintLayoutForLayers, taking string | Iterable<string> to match scrubLegendForRemovedLayers and its siblings. Both entry points now share one block-clearing helper, so they cannot drift.

Opening a project could mark it dirty

One effect writing a persisted field was still ungated on open:

if (!isMmPage && atlasExtentMode === "scale") setAtlasExtentMode("margin");

The dialog is mounted for the whole session and remounts on every project load, so this ran before the composer had ever been opened. A project pairing a pixel page size with atlasExtentMode: "scale" (only reachable by hand-editing today, since the live UI keeps the two in sync) would be corrected on load, which pushed the corrected config into the store and marked the project dirty purely from opening it. Gated on open, like the three layer-defaulting effects in #1994. Nothing acts on the pairing while the composer is closed, and opening it runs the correction.

I audited every useEffect in the file that writes one of the persisted fields; this was the last ungated one, and all four are now gated.

Verification

npm run build and npm run test:frontend (6348 pass) are green. New tests cover the delete-time scrub (single id, id set, and the no-op case) and the store path: deleting a layer a block references clears that block and leaves a block on a surviving layer alone.

Refs #1992

Summary by CodeRabbit

  • Bug Fixes
    • Fixed print layout settings not updating correctly when layers are removed.
    • Removed layers are now automatically cleared from related tables, charts, and atlas settings.
    • Preserved unrelated print layout configurations during layer deletion.
    • Corrected pixel-sized page handling when opening the print layout dialog.

Follow-up to #1994, which landed before these two review findings could be
folded into it.

- Scrub the Print Layout data/atlas blocks in removeLayer and deleteLayerGroup,
  alongside the storymap/widget/comment/legend scrubbing already there.
  Deleting a layer a block referenced, then saving without reopening the
  composer, wrote a dangling layer id into the project file; it only self-healed
  on the next load. Adds scrubPrintLayoutForRemovedLayers, the delete-time
  counterpart of the load-time scrub, matching scrubLegendForRemovedLayers'
  shape.
- Gate the "fixed scale needs a physical page" correction on `open`, the last
  effect still writing a persisted field ungated. It also runs on the mount that
  every project load triggers, so a hand-edited file pairing a pixel page with
  scale mode would be corrected, and the project marked dirty, before the
  composer had ever been opened.

Refs #1992
Copilot AI lite review requested due to automatic review settings August 18, 2026 22:34

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@coderabbitai

coderabbitai Bot commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: b2e3375d-2d99-4371-997b-f35163415093

📥 Commits

Reviewing files that changed from the base of the PR and between e681d24 and 6593c08.

📒 Files selected for processing (5)
  • apps/geolibre-desktop/src/components/layout/PrintLayoutDialog.tsx
  • packages/core/src/print-layout-config.ts
  • packages/core/src/store.ts
  • tests/core-project.test.ts
  • tests/print-layout-config.test.ts

Included review availability: Your plan provides up to 8 included reviews per hour; 1 remains after this review.


📝 Walkthrough

Walkthrough

The change adds shared print layout cleanup for removed layers, integrates it with layer and group deletion persistence, and limits atlas extent-mode normalization to open print layout dialogs.

Changes

Print Layout Layer Cleanup

Layer / File(s) Summary
Shared scrubbing and validation
packages/core/src/print-layout-config.ts, tests/print-layout-config.test.ts
The new scrubPrintLayoutForRemovedLayers function clears references to removed layers and disables affected table, chart, and atlas blocks. Tests cover single and multiple IDs, unchanged blocks, and reference identity.
Store deletion integration
packages/core/src/store.ts, tests/core-project.test.ts
Layer deletion and destructive group deletion scrub print layout references before persistence. Non-destructive group removal leaves the layout unchanged.
Dialog-scoped atlas normalization
apps/geolibre-desktop/src/components/layout/PrintLayoutDialog.tsx
Atlas extent-mode correction runs only while the print layout dialog is open. Pixel-sized pages using scale mode switch to margin mode on dialog opening.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk: ⚪ Minimal · up to 6593c

The change removes deleted-layer references from saved Print Layout data and prevents project opening from marking valid projects dirty. No actionable merge-blocking risk remains beyond normal checks and review.

Sequence Diagram(s)

sequenceDiagram
  participant Store
  participant PrintLayoutCleanup
  participant Persistence
  Store->>PrintLayoutCleanup: remove layer or destructive group
  PrintLayoutCleanup-->>Store: cleaned print layout configuration
  Store->>Persistence: persist updated state
Loading

Possibly related PRs

  • opengeos/GeoLibre#1627: Extends layer-removal cleanup in store.ts and shared configuration scrubbing.
  • opengeos/GeoLibre#1994: Adds related print layout reference cleanup in print-layout-config.ts and store deletion flows.

Poem

A rabbit hops through layers bright,
And clears stale links from print tonight.
Tables, charts, and atlases align,
While open dialogs draw the line.
Delete with care, then save anew—
The layout keeps what still belongs to you.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the primary delete-time cleanup change for Print Layout blocks when referenced layers are removed.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/1992-print-layout-followup

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

apps/geolibre-desktop/src/components/layout/PrintLayoutDialog.tsx

typescript-eslint does not support TS 7.0.
Please see https://devblogs.microsoft.com/typescript/announcing-typescript-7-0/#running-side-by-side-with-typescript-6.0 to run typescript-eslint using the TS 6 API.
See also typescript-eslint/typescript-eslint#10940 for tracking typescript-eslint's support for TS >=7.1

Oops! Something went wrong! :(

ESLint: 10.8.1

Error: typescript-eslint does not support TS 7.0.
at Object. (/node_modules/typescript-eslint/dist/index.js:52:11)
at Module._compile (node:internal/modules/cjs/loader:1830:14)
at Object..js (node:internal/modules/cjs/loader:1961:10)
at Module.load (node:internal/modules/cjs/loader:1553:32)
at Module._load (node:internal/modules/cjs/loader:1355:12)
at wrapModuleLoad (node:internal/modules/cjs/loader:255:19)
at loadCJSModuleWithModuleLoad (node:internal/modules/esm/translators:326:3)
at ModuleWrap. (node:internal/modules/esm/translators:231:7)
at ModuleJob.run (node:internal/modules/esm/module_job:437:25)
at async node:internal/modules/esm/loader:639:26

packages/core/src/print-layout-config.ts

ESLint skipped: the matched ESLint configuration already failed (config-incompatibility).

packages/core/src/store.ts

ESLint skipped: the matched ESLint configuration already failed (config-incompatibility).

  • 2 others

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.

@github-actions

Copy link
Copy Markdown
Contributor

Everything checks out. The tests correctly verify the new function's behavior, including reference-equality no-op returns. No inline comments are warranted — I'll finalize with a clean summary.

Code review

Reviewed the diff and cross-checked against the sibling scrub helpers (scrubWidgetsForRemovedLayers, scrubCommentsForRemovedLayers, scrubLegendForRemovedLayers in layer-ref-scrub.ts), both call sites in store.ts (removeLayer and removeLayerGroup), the open-gating pattern already used by the three sibling effects in PrintLayoutDialog.tsx, and the new tests.

Bugs: None found. clearBlocksForMissingLayers correctly treats "" as "no reference" (never scrubbed), the new scrubPrintLayoutForRemovedLayers is wired into both layer-removal paths (matching exactly the two call sites used by every sibling scrub, so no removal path was missed), and the open gate on the atlas-extent-mode effect mirrors the three already-gated effects with no stale-closure risk since isMmPage is recomputed every render. (Confidence: high)

Security: No concerns — no user input handling, injection surface, or secrets involved. (Confidence: high)

Performance: No issues — scrub functions return the same object reference when nothing changes, avoiding unnecessary re-renders/writes, consistent with existing helpers. (Confidence: high)

Quality: Clean refactor — extracting clearBlocksForMissingLayers as a shared helper between the load-time and delete-time scrub avoids duplicating the block-clearing logic, and the new function's signature (string | Iterable<string>) matches its siblings exactly. Tests cover the single-id, set-of-ids, and no-op cases for both the pure function and the store integration. (Confidence: high)

CLAUDE.md: No violations — this is a bug fix, not a new abstraction, and doesn't touch any of the mirrored-constant or catalog-generation conventions called out in CLAUDE.md.

Overall: a small, well-scoped, well-tested fix that faithfully follows the codebase's established scrub-on-delete pattern. Nothing to flag.

@github-actions

Copy link
Copy Markdown
Contributor

🔍 Cloudflare PR preview

Item Value
Site https://aa028516.geolibre-preview.pages.dev
Demo app https://aa028516.geolibre-preview.pages.dev/demo/
Commit 6593c08

@github-actions

Copy link
Copy Markdown
Contributor

🔍 GitHub Pages PR preview

Item Value
Site https://opengeos.org/pages-preview/GeoLibre/pr-1995/
Demo app https://opengeos.org/pages-preview/GeoLibre/pr-1995/demo/
Commit 6593c08

Note

GitHub Pages built this preview successfully, but its serving edge returned HTTP 403 when checked. The links may still be propagating.

@giswqs
giswqs merged commit 3c2c5be into main Aug 18, 2026
19 checks passed
@giswqs
giswqs deleted the fix/1992-print-layout-followup branch August 18, 2026 22:52
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