fix: capture map image immediately on "Définir le cadrage" click
All checks were successful
Deploy / Build and Deploy to Production (push) Successful in 21s

Save map data directly via API instead of emit('input') to avoid
draft state. Capture image, clear flag, then reload — the panel
shows the correct image in a single reload.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
isUnknown 2026-02-24 15:26:40 +01:00
parent e806f6ac48
commit 9ea02b2465
4 changed files with 158 additions and 44 deletions

File diff suppressed because one or more lines are too long

View file

@ -56,6 +56,7 @@ Kirby::plugin('geoproject/map-editor', [
require __DIR__ . '/routes/markers/update.php',
require __DIR__ . '/routes/markers/delete.php',
require __DIR__ . '/routes/position/update.php',
require __DIR__ . '/routes/mapdata/save.php',
require __DIR__ . '/routes/image/capture.php',
require __DIR__ . '/routes/image/check-flag.php',
require __DIR__ . '/routes/image/clear-flag.php',

View file

@ -0,0 +1,69 @@
<?php
/**
* PATCH save map data (center, zoom) directly to the page content
*/
return [
'pattern' => 'map-editor/pages/(:all)/mapdata',
'method' => 'PATCH',
'auth' => false,
'action' => function (string $pageId) {
try {
$user = kirby()->user();
if (!$user && !kirby()->option('debug', false)) {
return [
'status' => 'error',
'message' => 'Unauthorized',
'code' => 401
];
}
$page = kirby()->page($pageId);
if (!$page) {
return [
'status' => 'error',
'message' => 'Page not found',
'code' => 404
];
}
if (!$page->permissions()->can('update')) {
return [
'status' => 'error',
'message' => 'Forbidden',
'code' => 403
];
}
$data = kirby()->request()->data();
if (!isset($data['mapdata'])) {
return [
'status' => 'error',
'message' => 'mapdata is required',
'code' => 400
];
}
$page->update([
'mapdata' => $data['mapdata']
]);
return [
'status' => 'success',
'data' => [
'message' => 'Map data saved successfully'
]
];
} catch (Exception $e) {
return [
'status' => 'error',
'message' => $e->getMessage(),
'code' => 500
];
}
}
];

View file

@ -22,10 +22,11 @@
v-if="mode === 'multi'"
class="save-framing-button"
type="button"
:disabled="isCapturing"
@click="saveCurrentFraming"
title="Utiliser le niveau de zoom et centrage actuel comme cadrage par défaut"
>
Définir le cadrage
{{ isCapturing ? 'Capture en cours…' : 'Définir le cadrage' }}
</button>
<MapPreview
@ -55,6 +56,7 @@ import {
onBeforeUnmount,
nextTick,
} from 'vue';
import yaml from 'js-yaml';
import MapPreview from '../map/MapPreview.vue';
import MarkerList from '../map/MarkerList.vue';
import { useMarkersApi } from '../../composables/useMarkersApi.js';
@ -112,6 +114,7 @@ export default {
const mapPreview = ref(null);
const selectedMarkerId = ref(null);
const isInitialLoad = ref(true);
const isCapturing = ref(false);
// Extract page ID from field name
// For single mode, we don't need the API
@ -508,10 +511,19 @@ export default {
}
}
// Get CSRF token (same logic as useMarkersApi)
const getCsrfToken = () => {
if (window.panel && window.panel.csrf) return window.panel.csrf;
const meta = document.querySelector('meta[name="csrf"]');
if (meta && meta.content) return meta.content;
if (window.csrf) return window.csrf;
return '';
};
/**
* Save current map framing (center + zoom)
* Save current map framing (center + zoom) and capture image immediately
*/
function saveCurrentFraming() {
async function saveCurrentFraming() {
if (!mapPreview.value) return;
// Get current center and zoom from the map
@ -530,8 +542,39 @@ export default {
};
zoom.value = currentZoom;
// Save immediately (not debounced)
saveMapData();
isCapturing.value = true;
try {
// Save map data directly via API (bypasses emit('input') no draft state)
const yamlString = yaml.dump({
background: { type: 'osm' },
center: { lat: center.value.lat, lon: center.value.lon },
zoom: zoom.value,
}, { indent: 2, lineWidth: -1, noRefs: true });
await fetch(`/api/map-editor/pages/${pageId.value}/mapdata`, {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
'X-CSRF': getCsrfToken(),
},
body: JSON.stringify({ mapdata: yamlString }),
});
// Capture image directly (map is already rendered)
await captureAndSaveMapImage();
// Clear the regeneration flag (set by the hook after page update)
await fetch(
`/api/map-editor/pages/${pageId.value}/clear-regenerate-flag`,
{ method: 'DELETE' }
);
// Reload to show the new image in the panel
window.location.reload();
} catch (error) {
console.error('Failed to save framing:', error);
isCapturing.value = false;
}
}
/**
@ -648,6 +691,7 @@ export default {
mapReady,
mapPreview,
canAddMarker,
isCapturing,
loading: markersApi.loading,
error: markersApi.error,