Skip to content

Feat/crs assign - #556

Open
MaxNumerique wants to merge 29 commits into
nextfrom
feat/crs_assign
Open

MaxNumerique wants to merge 29 commits into
nextfrom
feat/crs_assign

Conversation

@MaxNumerique

Copy link
Copy Markdown
Contributor

No description provided.

@MaxNumerique

Copy link
Copy Markdown
Contributor Author

CRS support — shared front part

Part of the CRS work for Geode-solutions/Vease#798. Overview of the 4 PRs and merge order: see Geode-solutions/Vease#818. Merge after Geode-solutions/OpenGeodeWeb-Back#286: the front calls the new crs/* routes, and the old geographic_coordinate_systems route is removed.

Design rule: the shared components only display the CRS and request an edit. The dialog lives in the host app (Vease), which opts in with enableCrsEdit(). Apps that do not opt in show the CRS without edit buttons.

New

  • stores/crs.ts — useCrsStore
    • geographicList(geodeObjectType): session cache of the CRS list (~13k entries), one Map entry per type holding the promise, so concurrent calls share one request. A failed or rejected request is removed from the cache so the next call retries.
    • crsEditEnabled / enableCrsEdit(): the host app says it can edit a CRS.
    • crsEditRequest / requestCrsEdit(id) / clearCrsEditRequest(): edit request channel.
  • utils/crs.ts: formatCrs(crs) → EPSG:2154 — RGF93 v1 / Lambert-93 or None; formatCrsCode(crs) → EPSG:2154 or None.
  • composables/live_data_item.ts — useLiveDataItem(id): live Dexie view of a data item whose id can change (virtual tree rows are reused; the info card follows the last object). One effect scope per id, stopped on id change and unmount.

Changed

  • stores/data.ts: crs?: CRSList on DataItem / NewDataItem, copied in addItem. It survives project save/load (exportStores / import). Not indexed, so no Dexie version bump.
  • ItemLabel.vue (+ show-crs in GlobalObjects.vue only): tooltip line CRS: <formatCrs> and an editCrsBtn when edit is enabled. The stored item is only read while the tooltip is open (v-tooltip v-model), so a long tree does not keep one live query per row.
  • InfoCard.vue: CRS badge for data (not model components), code only with the full name in a tooltip, infoEditCrsBtn as a v-btn (keyboard accessible). Reads the item live, falls back to metaData.crs.
  • CrsSelector.vue:
    • list from useCrsStore().geographicList (cached), held in a shallowRef;
    • row key authority:code (codes are only unique within an authority, e.g. EPSG:4812 vs ESRI:4812);
    • new compact prop for narrow panels: 2 columns (EPSG:2154, then the name truncated with an ellipsis and a tooltip), all with Vuetify header options (nowrap, width, maxWidth), search icon inside the field;
    • page sizes 10/25/50/100: no "All" (it would render every CRS at once);
    • API change: keyToUpdate prop and the stepper emits (update_values, increment_step) are removed. No consumer used them in the workspace; no BREAKING CHANGE footer since there is no compatibility to keep yet.
  • Feedback — stores/feedback.ts, FeedBack/Snackers.vue: add_success(description, action?) / add_warning(description, action?) with FeedbackAction = { label, onClick } (exported). The snackbar shows a pencil button (feedbackActionBtn, tooltip = label); a click runs the action, then closes the snackbar, even if the action throws. The close button gets feedbackCloseBtn. Existing calls are unchanged.
  • utils/import_workflow.ts: reloadObject(id, { rebuildActor = false }) extracted from applyTimeSeriesWorkflow. rebuildActor: true (convert/align) rebuilds the local actor from the new light viewable; time series keep the previous behavior (actor kept).
  • internal/stores/hybrid_viewer/scene.ts — addItem: when an actor is replaced, the camera is no longer reset; new actors get the current z-scale (setScale(1, 1, zScale)).

Tests

stores/crs (shared request, failures not cached, edit requests), utils/crs, stores/data (crs copied, save/load), stores/feedback (action stored or absent), Snackers (no button without action, action then close, failing action still closes), ItemLabel (CRS row, edit button, virtual list reuse, no read while closed), InfoCard (CRS, button is a <button>, no row for model components, live value), CrsSelector (store, authority collision, compact columns, no "All"), import_workflow (rebuildActor on/off, time series).

Known limitations

  • FeedbackAction always shows a pencil icon and add_error takes no action: enough for the CRS use, to extend if another use comes.

@MaxNumerique
MaxNumerique requested a review from BotellaA October 26, 2026 08:53
@MaxNumerique
MaxNumerique marked this pull request as ready for review October 26, 2026 08:53
@MaxNumerique
MaxNumerique force-pushed the feat/crs_assign branch 2 times, most recently from d246ebf to a76c7a3 Compare October 27, 2026 09:28
MaxNumerique and others added 3 commits October 27, 2026 14:05
OpenGeode geosciences lists the same geographic CRS for 2D and 3D data:
the list is cached once, whatever the object type, instead of once per
type. It is still only requested when a CRS selector is shown, and a
failed request is not cached. The back keeps checking each CRS against
the list of the data dimension.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Comment thread app/components/CrsSelector.vue Resolved
MaxNumerique and others added 3 commits November 2, 2026 14:33
The project CRS was deduced on the fly from the oldest georeferenced
data. It is now a state of the crs store: the first georeferenced data
sets it, then only an explicit project CRS change does. It is exported
with the project and restored on import; a project saved before falls
back to the CRS of its oldest data. The store also lists the data whose
CRS differs from the project one (data without CRS are not listed).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A warning icon follows the name of a data whose CRS differs from the
project one, with a tooltip naming both CRS. The rows read the store
list, so the whole tree costs a single database query.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A compact button in the bottom right corner of the scene, under the XYZ
axes, shows the project CRS ("No CRS" before the first georeferenced
data). A click asks the host app for a project CRS edit; it is disabled
when no app hosts the dialog.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxNumerique and others added 7 commits November 2, 2026 14:53
A project saved without a project CRS fell back on the stored items, but
they are added after the store imports, with the import time as creation
date: the project CRS ended up random. The fallback now reads the
snapshot items, which keep their original creation date.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The project CRS follows its data: as soon as every georeferenced data is
in one CRS, that CRS becomes the project one; mixed data keep the
current project CRS. Data without CRS are now listed as not in the
project CRS. The CRS features read the data once, through a light query
that keeps only id, name, crs and creation date, instead of copying
every item with its geometry on each change. sameCrsState also treats
two data without CRS as in the same state.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Data left without CRS while the project has one get the warning icon,
with a tooltip asking to georeference them. The project CRS widget is
larger and moved away from the corner.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Loading a project added its data one chunk at a time after the project
CRS was restored: on the first data alone, the project CRS followed
them and the saved one was lost. The project CRS is now restored once
every data item is added.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A click on the warning icon of a data opens its CRS dialog, when the app
hosts it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	app/components/Viewer/ObjectTree/Base/ItemLabel.vue
#	app/stores/data.ts
#	tests/unit/composables/project_manager.nuxt.test.ts
#	tests/unit/stores/data.nuxt.test.ts
The table selection holds the "AUTHORITY:CODE" keys given by item-value:
it is typed as strings, and the selected CRS as a CRSList.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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