diff --git a/assets/src/components/Digitizing.js b/assets/src/components/Digitizing.js index f3f86eb773..ddf01aaa0e 100644 --- a/assets/src/components/Digitizing.js +++ b/assets/src/components/Digitizing.js @@ -64,6 +64,18 @@ export default class Digitizing extends HTMLElement { this._availableTools = DigitizingAvailableTools.slice(1); } + /** + * Show an editing message popup for the selected tool + * @param {string} messageKey - The lizDict key for the message + */ + _showEditingMessage(messageKey) { + const msg = lizDict[messageKey]; + if (!msg) return; + // Remove any previous editing message + $('#lizmap-editing-message').remove(); + lizMap.addMessage(msg, 'info', true, 10000).attr('id', 'lizmap-editing-message'); + } + connectedCallback() { // Update available tools from attribute @@ -244,34 +256,45 @@ export default class Digitizing extends HTMLElement { `; - const mainTemplate = (toolSelected) => html` + const mainTemplate = (toolSelected) => { + // Evaluate on every render so it reflects current edition state + const isEditionPoint = this.context === 'edition' && mainLizmap.edition?.layerGeometry === 'point'; + + // For point layers in edition, no toolbar needed — drawing starts automatically + if (isEditionPoint) { + this.style.display = 'none'; + return html``; + } + this.style.display = ''; + + return html`
- ${toolButtonTemplate(this._availableTools, toolSelected)} - mainLizmap.digitizing._userChangedColor(event.target.value)} data-bs-toggle="tooltip" data-bs-title="${lizDict['digitizing.toolbar.color']}" - > - - - - ` : ''} + ${this.context !== 'edition' ? html` - ${this.measureAvailable ? measureButtonTemplate( + ` : ''} + ${this.measureAvailable && !isEditionPoint ? measureButtonTemplate( mainLizmap.digitizing.hasMeasureVisible, ) : ''} ${this.saveAvailable ? saveButtonTemplate( @@ -413,65 +451,29 @@ export default class Digitizing extends HTMLElement {
${lizDict['digitizing.toolbar.save.state']}
-
-
- - ${lizDict['digitizing.constraint.title']} - - ${lizDict['digitizing.constraint.details']} -
-
- mainLizmap.digitizing.distanceConstraint = event.target.value - } - > - m -
-
- mainLizmap.digitizing.angleConstraint = event.target.value - } - > - ° -
-
${this.textToolsAvailable ? textToolsTemplate( mainLizmap.digitizing.editedFeatures.length != 0 ) : ''}
`; + }; - render( - mainTemplate( - this.toolSelected, - ), - this, - ); - - const tooltipTriggerList = this.querySelectorAll('[data-bs-toggle="tooltip"]'); - [...tooltipTriggerList].map(tooltipTriggerEl => new bootstrap.Tooltip(tooltipTriggerEl, { - trigger: 'hover' - })); + this._renderTemplate = () => { + render(mainTemplate(this.toolSelected), this); + this._initTooltips(); + this._initDropdowns(); + }; mainEventDispatcher.addListener( () => { + // Sync component tool state with module when context matches + if (mainLizmap.digitizing.context === this.context) { + const moduleTool = mainLizmap.digitizing.toolSelected; + if (this._availableTools.includes(moduleTool)) { + this._toolSelected = moduleTool; + } + } if (!this.disabled) { - render( - mainTemplate( - this.toolSelected, - ), - this, - ); + this._renderTemplate(); } }, [ @@ -495,11 +497,39 @@ export default class Digitizing extends HTMLElement { 'digitizing.visibility', ] ); + + this._renderTemplate(); } disconnectedCallback() { } + + _initTooltips() { + // Dispose existing tooltips to avoid duplicates + this.querySelectorAll('[data-bs-toggle="tooltip"]').forEach(el => { + // Skip elements whose title resolves to null (e.g. missing lizDict key) + // to prevent Bootstrap from throwing a type-check error. + const title = el.getAttribute('data-bs-title') || el.getAttribute('title'); + if (!title) return; + const existing = bootstrap.Tooltip.getInstance(el); + if (existing) existing.dispose(); + new bootstrap.Tooltip(el, { trigger: 'hover' }); + }); + } + + _initDropdowns() { + // Use strategy:'fixed' so Popper positions the dropdown relative to the + // viewport, allowing it to escape overflow:auto containers (#mini-dock). + this.querySelectorAll('[data-bs-toggle="dropdown"]').forEach(el => { + if (!bootstrap.Dropdown.getInstance(el)) { + new bootstrap.Dropdown(el, { + popperConfig: { strategy: 'fixed' } + }); + } + }); + } + /** * Digitizing context * The element attribute: context diff --git a/assets/src/components/Snapping.js b/assets/src/components/Snapping.js index 48c69a63c0..e4d72dc1d0 100644 --- a/assets/src/components/Snapping.js +++ b/assets/src/components/Snapping.js @@ -26,23 +26,12 @@ export default class Snapping extends HTMLElement {

${lizDict['snapping.title']}

-
- - -
+
${mainLizmap.snapping.active ? html`
@@ -91,8 +80,7 @@ export default class Snapping extends HTMLElement { }, [ 'snapping.config', - 'snapping.active', - 'snapping.refreshable' + 'snapping.active' ] ); } diff --git a/assets/src/components/edition/PasteGeom.js b/assets/src/components/edition/PasteGeom.js index 673830e380..40703c9a78 100644 --- a/assets/src/components/edition/PasteGeom.js +++ b/assets/src/components/edition/PasteGeom.js @@ -44,23 +44,30 @@ export default class pasteGeom extends HTMLElement { * @returns {boolean} True if can activate */ _canActivate() { - const drawActive = mainLizmap?.edition?.drawFeatureActivated || false; + if (mainLizmap?.digitizing?.isSplitLocked) return false; + const digitizingActive = mainLizmap?.digitizing?.toolSelected !== 'deactivate' + || mainLizmap?.digitizing?.context === 'edition'; const hasLayerId = !!mainLizmap?.edition?.layerId; - return drawActive || hasLayerId; + return digitizingActive || hasLayerId; } connectedCallback() { - this._template = () => - html` - `; + }; render(this._template(), this); @@ -100,6 +107,12 @@ export default class pasteGeom extends HTMLElement { render(this._template(), this); }, 'edition.formClosed' ); + + mainEventDispatcher.addListener( + () => { + render(this._template(), this); + }, 'digitizing.splitLocked' + ); } disconnectedCallback() {} diff --git a/assets/src/components/edition/PasteStoredGeom.js b/assets/src/components/edition/PasteStoredGeom.js index 64d3af7d18..fd9f1df155 100644 --- a/assets/src/components/edition/PasteStoredGeom.js +++ b/assets/src/components/edition/PasteStoredGeom.js @@ -8,6 +8,7 @@ import { mainLizmap, mainEventDispatcher } from '../../modules/Globals.js'; import { html, render } from 'lit-html'; +import { Feature } from 'ol'; /** * Web component used to paste a geometry from featureStorage. @@ -36,105 +37,20 @@ export default class PasteStoredGeom extends HTMLElement { return; } - const feature = features[0]; - const geometry = feature.getGeometry(); - - // Convert OL6 geometry to OL2 format - const ol2Geometry = this._convertToOL2Geometry(geometry); - - if(!ol2Geometry){ - lizMap.addMessage(lizDict['edition.error.incompatibleGeometry'] || 'Incompatible geometry type', 'error', true); - return; - } - - // Add to appropriate layer - if(mainLizmap.edition?.drawControl){ - mainLizmap.edition.drawControl.layer.removeAllFeatures(); - mainLizmap.edition.drawControl.layer.addFeatures([new OpenLayers.Feature.Vector(ol2Geometry)]); - } else if (mainLizmap.edition.modifyFeatureControl.active){ - mainLizmap.edition.modifyFeatureControl.layer.destroyFeatures(); - mainLizmap.edition.modifyFeatureControl.layer.addFeatures([new OpenLayers.Feature.Vector(ol2Geometry)]); - } - - // Update geometry field in form - if(mainLizmap.edition.updateGeometryColumnFromFeature){ - mainLizmap.edition.updateGeometryColumnFromFeature(new OpenLayers.Feature.Vector(ol2Geometry)); - } + const geom = features[0].getGeometry().clone(); + const feature = new Feature(geom); + mainLizmap.digitizing._drawSource.clear(); + mainLizmap.digitizing._drawSource.addFeature(feature); + mainEventDispatcher.dispatch('digitizing.geometryChanged'); // Visual feedback lizMap.addMessage(lizDict['edition.geom.pasted'] || 'Geometry pasted successfully', 'info', true); } - /** - * Convert OL6 geometry to OL2 format - * @param {object} olGeometry - OpenLayers 6 geometry - * @returns {OpenLayers.Geometry} OpenLayers 2 geometry - */ - _convertToOL2Geometry(olGeometry){ - const geomType = olGeometry.getType(); - const coords = olGeometry.getCoordinates(); - - switch(geomType){ - case 'Point': - return new OpenLayers.Geometry.Point(coords[0], coords[1]); - - case 'LineString': { - const linePoints = coords.map(c => - new OpenLayers.Geometry.Point(c[0], c[1]) - ); - return new OpenLayers.Geometry.LineString(linePoints); - } - - case 'Polygon': { - const rings = coords.map(ring => { - const ringPoints = ring.map(c => - new OpenLayers.Geometry.Point(c[0], c[1]) - ); - return new OpenLayers.Geometry.LinearRing(ringPoints); - }); - return new OpenLayers.Geometry.Polygon(rings); - } - - case 'MultiPoint': { - const points = coords.map(c => - new OpenLayers.Geometry.Point(c[0], c[1]) - ); - return new OpenLayers.Geometry.MultiPoint(points); - } - - case 'MultiLineString': { - const lines = coords.map(line => { - const linePoints = line.map(c => - new OpenLayers.Geometry.Point(c[0], c[1]) - ); - return new OpenLayers.Geometry.LineString(linePoints); - }); - return new OpenLayers.Geometry.MultiLineString(lines); - } - - case 'MultiPolygon': { - const polygons = coords.map(poly => { - const rings = poly.map(ring => { - const ringPoints = ring.map(c => - new OpenLayers.Geometry.Point(c[0], c[1]) - ); - return new OpenLayers.Geometry.LinearRing(ringPoints); - }); - return new OpenLayers.Geometry.Polygon(rings); - }); - return new OpenLayers.Geometry.MultiPolygon(polygons); - } - - default: - console.error('Unsupported geometry type:', geomType); - return null; - } - } - connectedCallback() { this._template = () => html` -
-
+
{zone 'view~map_minidock', array('repository'=>$repository,'project'=>$project,'dockable'=>$minidockable)} diff --git a/lizmap/modules/view/templates/map_edition.tpl b/lizmap/modules/view/templates/map_edition.tpl index ebfb3f9300..9ce0854850 100644 --- a/lizmap/modules/view/templates/map_edition.tpl +++ b/lizmap/modules/view/templates/map_edition.tpl @@ -35,6 +35,12 @@
+ +<<<<<<< HEAD + {* lizmap-reverse-geom lives outside the legacy + #edition-geomtool-container so it stays visible after the + OL10 migration hides the legacy buttons. *} + + +======= +>>>>>>> c0bbf8cf1 (Migrate edition Draw/Modify/Select from OL2 to OL10)

{@view~edition.point.coord.title@}

-
-