diff --git a/CHANGELOG.md b/CHANGELOG.md index dc1e9553..eb6dc107 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/app/helpers/tags_helper.rb b/app/helpers/tags_helper.rb new file mode 100644 index 00000000..de5150dd --- /dev/null +++ b/app/helpers/tags_helper.rb @@ -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 diff --git a/app/javascript/controllers/maps_controller.js b/app/javascript/controllers/maps_controller.js index 51449c8d..49a8652b 100644 --- a/app/javascript/controllers/maps_controller.js +++ b/app/javascript/controllers/maps_controller.js @@ -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) { diff --git a/app/javascript/maps/places.js b/app/javascript/maps/places.js index 2a221536..2496bc8f 100644 --- a/app/javascript/maps/places.js +++ b/app/javascript/maps/places.js @@ -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); } } }); diff --git a/app/views/tags/_form.html.erb b/app/views/tags/_form.html.erb index 8f35a923..ef71bdc5 100644 --- a/app/views/tags/_form.html.erb +++ b/app/views/tags/_form.html.erb @@ -19,6 +19,7 @@
+ <% default_emoji = tag.icon.presence || (tag.new_record? ? random_tag_emoji : '🏠') %>
<%= f.label :icon, class: "label" %>
@@ -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="🏠"> - <%= tag.icon.presence || '🏠' %> + data-default-icon="<%= default_emoji %>"> + <%= default_emoji %> @@ -36,7 +37,7 @@ class="hidden absolute z-50 mt-2 left-0">
- <%= f.hidden_field :icon, data: { emoji_picker_target: "input" } %> + <%= f.hidden_field :icon, value: default_emoji, data: { emoji_picker_target: "input" } %>
<%= f.hidden_field :privacy_radius_meters, - value: tag.privacy_radius_meters || 1000, + value: tag.privacy_radius_meters, data: { privacy_radius_target: "field" } %>