Fix bug where enabling place tag layers would trigger saving enabled layers, overwriting with incomplete data

This commit is contained in:
Eugene Burmakin 2025-11-23 01:12:38 +01:00
parent 78ac365c00
commit 6dfc0099e1
5 changed files with 65 additions and 16 deletions

View file

@ -11,12 +11,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- [ ] KML upload
- [ ] OIDC login with Authentik
- [ ] How does it work with existing settings to disable registrations?
- [ ] Place creation
- [ ] Tag creation + management
- [ ] Place privacy zones
- [ ] Settings panel is scrollable
- [x] Place creation
- [x] Tag creation + management
- [x] Place privacy zones
- [x] Settings panel is scrollable
- [ ] Family members can enable their location sharing and see each other on the map
- [ ] Home location
- [x] Home location
# OIDC and KML support release

View file

@ -0,0 +1,20 @@
# frozen_string_literal: true
module TagsHelper
COMMON_TAG_EMOJIS = %w[
🏠 🏢 🏫 🏥 🏪 🏨 🏦 🏛 🏟 🏖
🕌 🕍 🗼 🗽 🗿 💒 🏰 🏯
🍕 🍔 🍟 🍣 🍱 🍜 🍝 🍛 🥘 🍲
🍺 🍷 🥂 🍹 🍸 🥃 🍻 🥤 🧃
🏃 🏀 🏈 🎾 🏐 🏓 🏸 🏒
🚗 🚕 🚙 🚌 🚎 🏎 🚓 🚑 🚒 🚐
🚁 🚤 🛥 🚂 🚆 🚇 🚊
🎭 🎪 🎨 🎬 🎤 🎧 🎼 🎹 🎸 🎺
📚 📖 🖊 📝 📋 📌 📍 🗺 🧭
💼 👔 🎓 🏆 🎯 🎲 🎮 🎰 🛍 💍
].freeze
def random_tag_emoji
COMMON_TAG_EMOJIS.sample
end
end

View file

@ -766,6 +766,12 @@ export default class extends BaseController {
}
saveEnabledLayers() {
// Don't save if we're restoring layers from settings
if (this.isRestoringLayers) {
console.log('[saveEnabledLayers] Skipping save - currently restoring layers from settings');
return;
}
const enabledLayers = [];
// Iterate through all layers on the map to determine which are enabled
@ -798,6 +804,8 @@ export default class extends BaseController {
enabledLayers.push(`place_tag:${layer._placeTagId}`);
}
});
} else {
console.warn('[saveEnabledLayers] placesFilteredLayers is not initialized');
}
fetch('/api/v1/settings', {
@ -1777,8 +1785,12 @@ export default class extends BaseController {
});
// Handle place tag layers (format: "place_tag:ID" or "place_tag:untagged")
enabledLayers.forEach(layerKey => {
if (layerKey.startsWith('place_tag:')) {
const placeTagLayers = enabledLayers.filter(key => key.startsWith('place_tag:'));
if (placeTagLayers.length > 0) {
// Set flag once before restoring all place tag layers
this.isRestoringLayers = true;
placeTagLayers.forEach(layerKey => {
const tagId = layerKey.replace('place_tag:', '');
let layer;
@ -1792,19 +1804,23 @@ export default class extends BaseController {
}
if (layer && !this.map.hasLayer(layer)) {
this.isRestoringLayers = true;
layer.addTo(this.map);
console.log(`Enabled place tag layer: ${tagId}`);
setTimeout(() => { this.isRestoringLayers = false; }, 100);
}
}
});
});
// Reset flag after all layers have been added and events processed
setTimeout(() => {
this.isRestoringLayers = false;
console.log('[initializeLayersFromSettings] Finished restoring place tag layers');
}, 150);
}
// Update the tree control checkboxes to reflect the layer states
// Wait a bit for the tree control to be fully initialized
setTimeout(() => {
this.updateTreeControlCheckboxes(enabledLayers);
}, 100);
}, 200);
}
updateTreeControlCheckboxes(enabledLayers) {

View file

@ -349,9 +349,21 @@ export class PlacesManager {
const label = input.closest('label') || input.nextElementSibling;
if (label && label.textContent.trim() === 'Places') {
if (!input.checked) {
// Set a flag to prevent saving during programmatic layer addition
if (window.mapsController) {
window.mapsController.isRestoringLayers = true;
}
input.checked = true;
input.dispatchEvent(new Event('change', { bubbles: true }));
console.log('Enabled Places layer in tree control');
// Reset the flag after a short delay to allow the event to process
setTimeout(() => {
if (window.mapsController) {
window.mapsController.isRestoringLayers = false;
}
}, 50);
}
}
});

View file

@ -19,6 +19,7 @@
<div class="grid grid-cols-2 gap-4">
<!-- Emoji Picker -->
<% default_emoji = tag.icon.presence || (tag.new_record? ? random_tag_emoji : '🏠') %>
<div class="form-control" data-controller="emoji-picker" data-emoji-picker-auto-submit-value="false">
<%= f.label :icon, class: "label" %>
<div class="relative w-full">
@ -27,8 +28,8 @@
class="input input-bordered w-full flex items-center justify-center text-4xl cursor-pointer hover:bg-base-200 min-h-[4rem]"
data-action="click->emoji-picker#toggle"
data-emoji-picker-target="button"
data-default-icon="🏠">
<span data-emoji-picker-display><%= tag.icon.presence || '🏠' %></span>
data-default-icon="<%= default_emoji %>">
<span data-emoji-picker-display><%= default_emoji %></span>
</button>
<!-- Picker container -->
@ -36,7 +37,7 @@
class="hidden absolute z-50 mt-2 left-0"></div>
<!-- Hidden input for form submission -->
<%= f.hidden_field :icon, data: { emoji_picker_target: "input" } %>
<%= f.hidden_field :icon, value: default_emoji, data: { emoji_picker_target: "input" } %>
</div>
<label class="label">
<span class="label-text-alt">Click to select an emoji</span>
@ -134,7 +135,7 @@
<span>5000m</span>
</div>
<%= f.hidden_field :privacy_radius_meters,
value: tag.privacy_radius_meters || 1000,
value: tag.privacy_radius_meters,
data: { privacy_radius_target: "field" } %>
</div>
<label class="label">