feat: add map framing save button and prevent initial load save
All checks were successful
Deploy / Build and Deploy to Production (push) Successful in 17s

- Add "Définir le cadrage" button in multi mode to save current map
  center and zoom as default framing
- Add getCurrentZoom() method in MapPreview to retrieve current zoom level
- Fix: prevent automatic save on initial load with isInitialLoad flag
  to avoid marking page as modified when loading existing data
- Style: dark button theme for save framing button

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
isUnknown 2026-02-06 09:20:12 +01:00
parent 8e67431622
commit 5531aebc04
4 changed files with 20738 additions and 606 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -17,6 +17,17 @@
<!-- Map preview -->
<div class="map-preview-container">
<!-- Save framing button (multi mode only) -->
<button
v-if="mode === 'multi'"
class="save-framing-button"
type="button"
@click="saveCurrentFraming"
title="Utiliser le niveau de zoom et centrage actuel comme cadrage par défaut"
>
Définir le cadrage
</button>
<MapPreview
v-if="mapReady"
ref="mapPreview"
@ -100,6 +111,7 @@ export default {
const mapReady = ref(false);
const mapPreview = ref(null);
const selectedMarkerId = ref(null);
const isInitialLoad = ref(true);
// Extract page ID from field name
// For single mode, we don't need the API
@ -132,14 +144,15 @@ export default {
? useMarkersApi(pageId.value)
: { markers: ref([]), loading: ref(false), error: ref(null) };
const { center, zoom, loadMapData, debouncedSave } = useMapData({
defaultCenter: {
lat: props.defaultCenter[0],
lon: props.defaultCenter[1],
},
defaultZoom: props.defaultZoom,
onSave: (yamlString) => emit('input', yamlString),
});
const { center, zoom, loadMapData, saveMapData, debouncedSave } =
useMapData({
defaultCenter: {
lat: props.defaultCenter[0],
lon: props.defaultCenter[1],
},
defaultZoom: props.defaultZoom,
onSave: (yamlString) => emit('input', yamlString),
});
// Computed: markers based on mode
const markers = computed(() => {
@ -290,13 +303,19 @@ export default {
await nextTick();
mapReady.value = true;
// Mark initial load as complete
// Use nextTick to ensure all reactive updates from loadMapData are done
await nextTick();
isInitialLoad.value = false;
});
// Watch center and zoom for automatic save (multi mode only)
watch(
[center, zoom],
() => {
if (props.mode === 'multi') {
// Don't save during initial load to avoid marking page as modified
if (props.mode === 'multi' && !isInitialLoad.value) {
debouncedSave();
}
},
@ -484,6 +503,32 @@ export default {
}
}
/**
* Save current map framing (center + zoom)
*/
function saveCurrentFraming() {
if (!mapPreview.value) return;
// Get current center and zoom from the map
const currentCenter = mapPreview.value.getCurrentCenter
? mapPreview.value.getCurrentCenter()
: { lat: center.value.lat, lon: center.value.lon };
const currentZoom = mapPreview.value.getCurrentZoom
? mapPreview.value.getCurrentZoom()
: zoom.value;
// Update state
center.value = {
lat: currentCenter.lat,
lon: currentCenter.lon,
};
zoom.value = currentZoom;
// Save immediately (not debounced)
saveMapData();
}
return {
// State
center,
@ -504,6 +549,7 @@ export default {
handleLocationSelect,
deleteMarker,
editMarker,
saveCurrentFraming,
};
},
};
@ -537,4 +583,29 @@ export default {
background: #f0f0f0;
min-width: 0;
}
.save-framing-button {
position: absolute;
top: 10px;
right: 10px;
z-index: 1000;
padding: 8px 16px;
background: var(--color-black);
border: 1px solid var(--color-border);
border-radius: var(--rounded);
font-size: 13px;
font-weight: 500;
cursor: pointer;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
transition: all 0.2s;
}
.save-framing-button:hover {
background: var(--color-gray-700);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}
.save-framing-button:active {
transform: translateY(1px);
}
</style>

View file

@ -309,6 +309,13 @@ export default {
};
}
function getCurrentZoom() {
if (map.value && map.value.loaded()) {
return map.value.getZoom();
}
return props.zoom;
}
function centerOnPosition(lat, lon) {
if (map.value && map.value.loaded()) {
map.value.flyTo({
@ -323,6 +330,7 @@ export default {
mapContainer,
loading,
getCurrentCenter,
getCurrentZoom,
centerOnPosition
};
}