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
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:
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
|
|
@ -17,6 +17,17 @@
|
||||||
|
|
||||||
<!-- Map preview -->
|
<!-- Map preview -->
|
||||||
<div class="map-preview-container">
|
<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
|
<MapPreview
|
||||||
v-if="mapReady"
|
v-if="mapReady"
|
||||||
ref="mapPreview"
|
ref="mapPreview"
|
||||||
|
|
@ -100,6 +111,7 @@ export default {
|
||||||
const mapReady = ref(false);
|
const mapReady = ref(false);
|
||||||
const mapPreview = ref(null);
|
const mapPreview = ref(null);
|
||||||
const selectedMarkerId = ref(null);
|
const selectedMarkerId = ref(null);
|
||||||
|
const isInitialLoad = ref(true);
|
||||||
|
|
||||||
// Extract page ID from field name
|
// Extract page ID from field name
|
||||||
// For single mode, we don't need the API
|
// For single mode, we don't need the API
|
||||||
|
|
@ -132,14 +144,15 @@ export default {
|
||||||
? useMarkersApi(pageId.value)
|
? useMarkersApi(pageId.value)
|
||||||
: { markers: ref([]), loading: ref(false), error: ref(null) };
|
: { markers: ref([]), loading: ref(false), error: ref(null) };
|
||||||
|
|
||||||
const { center, zoom, loadMapData, debouncedSave } = useMapData({
|
const { center, zoom, loadMapData, saveMapData, debouncedSave } =
|
||||||
defaultCenter: {
|
useMapData({
|
||||||
lat: props.defaultCenter[0],
|
defaultCenter: {
|
||||||
lon: props.defaultCenter[1],
|
lat: props.defaultCenter[0],
|
||||||
},
|
lon: props.defaultCenter[1],
|
||||||
defaultZoom: props.defaultZoom,
|
},
|
||||||
onSave: (yamlString) => emit('input', yamlString),
|
defaultZoom: props.defaultZoom,
|
||||||
});
|
onSave: (yamlString) => emit('input', yamlString),
|
||||||
|
});
|
||||||
|
|
||||||
// Computed: markers based on mode
|
// Computed: markers based on mode
|
||||||
const markers = computed(() => {
|
const markers = computed(() => {
|
||||||
|
|
@ -290,13 +303,19 @@ export default {
|
||||||
|
|
||||||
await nextTick();
|
await nextTick();
|
||||||
mapReady.value = true;
|
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 and zoom for automatic save (multi mode only)
|
||||||
watch(
|
watch(
|
||||||
[center, zoom],
|
[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();
|
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 {
|
return {
|
||||||
// State
|
// State
|
||||||
center,
|
center,
|
||||||
|
|
@ -504,6 +549,7 @@ export default {
|
||||||
handleLocationSelect,
|
handleLocationSelect,
|
||||||
deleteMarker,
|
deleteMarker,
|
||||||
editMarker,
|
editMarker,
|
||||||
|
saveCurrentFraming,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
@ -537,4 +583,29 @@ export default {
|
||||||
background: #f0f0f0;
|
background: #f0f0f0;
|
||||||
min-width: 0;
|
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>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
function centerOnPosition(lat, lon) {
|
||||||
if (map.value && map.value.loaded()) {
|
if (map.value && map.value.loaded()) {
|
||||||
map.value.flyTo({
|
map.value.flyTo({
|
||||||
|
|
@ -323,6 +330,7 @@ export default {
|
||||||
mapContainer,
|
mapContainer,
|
||||||
loading,
|
loading,
|
||||||
getCurrentCenter,
|
getCurrentCenter,
|
||||||
|
getCurrentZoom,
|
||||||
centerOnPosition
|
centerOnPosition
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue