Fix sidebar content switching
This commit is contained in:
parent
12253a41b9
commit
83461b0748
@ -74,8 +74,9 @@ export default class MapComponent extends Component {
|
||||
this.loadBookmarks();
|
||||
});
|
||||
|
||||
this.storage.places.on('change', (event) => {
|
||||
// Ideally we would only update the changed one, but refreshing all is safer for now
|
||||
// Listen to changes in the /places/ scope
|
||||
this.storage.rs.scope('/places/').on('change', (event) => {
|
||||
console.log('RemoteStorage change detected:', event);
|
||||
this.loadBookmarks();
|
||||
});
|
||||
});
|
||||
@ -106,49 +107,56 @@ export default class MapComponent extends Component {
|
||||
}
|
||||
|
||||
handleMapClick = async (event) => {
|
||||
// 0. Handle closing sidebar if open and clicked on empty map area
|
||||
// Check if user clicked on a rendered feature (POI or Bookmark) FIRST
|
||||
const features = this.mapInstance.getFeaturesAtPixel(event.pixel);
|
||||
let clickedBookmark = null;
|
||||
let selectedFeatureName = null;
|
||||
let selectedFeatureType = null;
|
||||
|
||||
if (features && features.length > 0) {
|
||||
const bookmarkFeature = features.find(f => f.get('isBookmark'));
|
||||
if (bookmarkFeature) {
|
||||
clickedBookmark = bookmarkFeature.get('originalPlace');
|
||||
}
|
||||
// Also get visual props for standard map click logic later
|
||||
const props = features[0].getProperties();
|
||||
if (props.name) {
|
||||
selectedFeatureName = props.name;
|
||||
selectedFeatureType = props.class || props.subclass;
|
||||
}
|
||||
}
|
||||
|
||||
// Special handling when sidebar is OPEN
|
||||
if (this.args.isSidebarOpen) {
|
||||
// We can just trigger the outside click and return.
|
||||
// However, if the user clicked on a feature, maybe they want to switch selection?
|
||||
// The requirement says "when clicking on the map while the sidebar is open, it should close the sidebar instead of executing the normal map click logic"
|
||||
// This implies strict closing behavior.
|
||||
// If it's a bookmark, we allow "switching" to it even if sidebar is open
|
||||
if (clickedBookmark) {
|
||||
console.log("Clicked bookmark while sidebar open (switching):", clickedBookmark);
|
||||
if (this.args.onPlacesFound) {
|
||||
this.args.onPlacesFound([], clickedBookmark);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise (empty map or non-bookmark feature), close the sidebar
|
||||
if (this.args.onOutsideClick) {
|
||||
this.args.onOutsideClick();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Normal behavior (sidebar is closed)
|
||||
if (clickedBookmark) {
|
||||
console.log("Clicked bookmark:", clickedBookmark);
|
||||
if (this.args.onPlacesFound) {
|
||||
this.args.onPlacesFound([], clickedBookmark);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const coords = toLonLat(event.coordinate);
|
||||
const [lon, lat] = coords;
|
||||
|
||||
// 1. Check if user clicked on a rendered feature (POI or Bookmark)
|
||||
const features = this.mapInstance.getFeaturesAtPixel(event.pixel);
|
||||
let selectedFeatureName = null;
|
||||
let selectedFeatureType = null;
|
||||
let clickedBookmark = null;
|
||||
|
||||
if (features && features.length > 0) {
|
||||
// Prioritize bookmarks if clicked
|
||||
const bookmarkFeature = features.find(f => f.get('isBookmark'));
|
||||
if (bookmarkFeature) {
|
||||
clickedBookmark = bookmarkFeature.get('originalPlace');
|
||||
console.log("Clicked bookmark:", clickedBookmark);
|
||||
|
||||
// Notify parent to show bookmark details
|
||||
if (this.args.onPlacesFound) {
|
||||
// We pass it as a "selectedPlace" but with an empty list of nearby items since it's a specific bookmark
|
||||
this.args.onPlacesFound([], clickedBookmark);
|
||||
}
|
||||
return; // Stop processing to avoid fetching OSM data for a known bookmark
|
||||
}
|
||||
|
||||
const props = features[0].getProperties();
|
||||
if (props.name) {
|
||||
selectedFeatureName = props.name;
|
||||
selectedFeatureType = props.class || props.subclass; // e.g., 'cafe'
|
||||
console.log(`Clicked visual feature: "${selectedFeatureName}" (${selectedFeatureType})`);
|
||||
}
|
||||
}
|
||||
// ... continue with normal OSM fetch logic ...
|
||||
|
||||
// 2. Fetch authoritative data via Overpass
|
||||
try {
|
||||
|
||||
@ -8,31 +8,26 @@ import or from 'ember-truth-helpers/helpers/or';
|
||||
|
||||
export default class PlacesSidebar extends Component {
|
||||
@service storage;
|
||||
@tracked selectedPlace = null;
|
||||
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
// If a specific place was passed in (pre-selected by map), show it immediately
|
||||
if (this.args.initialPlace) {
|
||||
this.selectedPlace = this.args.initialPlace;
|
||||
@action
|
||||
selectPlace(place) {
|
||||
if (this.args.onSelect) {
|
||||
this.args.onSelect(place);
|
||||
}
|
||||
}
|
||||
|
||||
@action
|
||||
selectPlace(place) {
|
||||
this.selectedPlace = place;
|
||||
}
|
||||
|
||||
@action
|
||||
clearSelection() {
|
||||
this.selectedPlace = null;
|
||||
// If we were initialized with a single place (direct click),
|
||||
// going "back" might mean closing or showing the list if available.
|
||||
// Logic: if we have a list (@places), go back to list.
|
||||
// If we only had one place (@initialPlace) and no list, maybe close?
|
||||
// For now, assuming @places is always passed if we want a list fallback.
|
||||
// Going "back" clears the specific selection but keeps the sidebar open (showing list)
|
||||
if (this.args.onSelect) {
|
||||
this.args.onSelect(null);
|
||||
}
|
||||
|
||||
// Fallback logic: if no list available, close sidebar
|
||||
if (!this.args.places || this.args.places.length === 0) {
|
||||
this.args.onClose();
|
||||
if (this.args.onClose) {
|
||||
this.args.onClose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,16 +39,11 @@ export default class PlacesSidebar extends Component {
|
||||
// It's a saved bookmark -> Delete it
|
||||
if (confirm(`Delete "${place.title}"?`)) {
|
||||
try {
|
||||
// We need geohash to delete.
|
||||
// Existing bookmarks have it.
|
||||
// If for some reason it's missing (shouldn't happen for saved items), we can't delete easily.
|
||||
if (place.id && place.geohash) {
|
||||
await this.storage.places.remove(place.id, place.geohash);
|
||||
console.log('Place deleted:', place.title);
|
||||
|
||||
// Close sidebar after delete since the item is gone from "Saved" context
|
||||
// Or we could revert to "Save" state if we had the original POI data,
|
||||
// but usually we just close or show "Nearby".
|
||||
// Close sidebar after delete
|
||||
if (this.args.onClose) {
|
||||
this.args.onClose();
|
||||
}
|
||||
@ -67,8 +57,6 @@ export default class PlacesSidebar extends Component {
|
||||
}
|
||||
} else {
|
||||
// It's a fresh POI -> Save it
|
||||
|
||||
// Map Overpass POI to our Place schema
|
||||
const placeData = {
|
||||
title: place.tags.name || place.tags['name:en'] || 'Untitled Place',
|
||||
lat: place.lat,
|
||||
@ -76,23 +64,15 @@ export default class PlacesSidebar extends Component {
|
||||
tags: [],
|
||||
url: place.tags.website,
|
||||
osmId: String(place.id),
|
||||
// We rely on the module to generate ID and Geohash
|
||||
};
|
||||
|
||||
try {
|
||||
const savedPlace = await this.storage.places.store(placeData);
|
||||
console.log('Place saved:', placeData.title);
|
||||
|
||||
// Update the selected place in the UI to be the saved bookmark
|
||||
// (so the button turns to "Saved")
|
||||
// We can update the local tracked property if we are viewing a single item
|
||||
// or let the parent update.
|
||||
// Ideally, we switch `this.selectedPlace` to the `savedPlace` returned by the store.
|
||||
this.selectedPlace = savedPlace;
|
||||
|
||||
// Notify parent if needed (map will auto-update via events)
|
||||
if (this.args.onBookmarkSaved) {
|
||||
this.args.onBookmarkSaved();
|
||||
// Update selection to the new saved place object
|
||||
if (this.args.onSelect) {
|
||||
this.args.onSelect(savedPlace);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to save place:', error);
|
||||
@ -104,7 +84,7 @@ export default class PlacesSidebar extends Component {
|
||||
<template>
|
||||
<div class="sidebar">
|
||||
<div class="sidebar-header">
|
||||
{{#if this.selectedPlace}}
|
||||
{{#if @selectedPlace}}
|
||||
<button type="button" class="back-btn" {{on "click" this.clearSelection}}>←</button>
|
||||
<h2>Details</h2>
|
||||
{{else}}
|
||||
@ -114,35 +94,34 @@ export default class PlacesSidebar extends Component {
|
||||
</div>
|
||||
|
||||
<div class="sidebar-content">
|
||||
{{#if this.selectedPlace}}
|
||||
{{#if @selectedPlace}}
|
||||
<div class="place-details">
|
||||
<h3>{{or this.selectedPlace.title this.selectedPlace.tags.name this.selectedPlace.tags.name:en "Unnamed Place"}}</h3>
|
||||
<h3>{{or @selectedPlace.title @selectedPlace.tags.name @selectedPlace.tags.name:en "Unnamed Place"}}</h3>
|
||||
<p class="place-meta">
|
||||
{{#if this.selectedPlace.tags.amenity}}
|
||||
{{or this.selectedPlace.tags.amenity this.selectedPlace.tags.shop this.selectedPlace.tags.tourism}}
|
||||
{{#if @selectedPlace.tags.amenity}}
|
||||
{{or @selectedPlace.tags.amenity @selectedPlace.tags.shop @selectedPlace.tags.tourism}}
|
||||
{{else}}
|
||||
{{!-- If it is a bookmark, it might just have an array of tags or description --}}
|
||||
{{this.selectedPlace.description}}
|
||||
{{@selectedPlace.description}}
|
||||
{{/if}}
|
||||
</p>
|
||||
|
||||
{{#if (or this.selectedPlace.url this.selectedPlace.tags.website)}}
|
||||
<p><a href={{or this.selectedPlace.url this.selectedPlace.tags.website}} target="_blank" rel="noopener noreferrer">Website</a></p>
|
||||
{{#if (or @selectedPlace.url @selectedPlace.tags.website)}}
|
||||
<p><a href={{or @selectedPlace.url @selectedPlace.tags.website}} target="_blank" rel="noopener noreferrer">Website</a></p>
|
||||
{{/if}}
|
||||
|
||||
{{#if this.selectedPlace.tags.opening_hours}}
|
||||
<p><strong>Open:</strong> {{this.selectedPlace.tags.opening_hours}}</p>
|
||||
{{#if @selectedPlace.tags.opening_hours}}
|
||||
<p><strong>Open:</strong> {{@selectedPlace.tags.opening_hours}}</p>
|
||||
{{/if}}
|
||||
|
||||
<div class="actions">
|
||||
<button type="button" class={{if this.selectedPlace.createdAt "btn-secondary" "btn-primary"}} {{on "click" (fn this.toggleSave this.selectedPlace)}}>
|
||||
{{if this.selectedPlace.createdAt "Saved ✓" "Save"}}
|
||||
<button type="button" class={{if @selectedPlace.createdAt "btn-secondary" "btn-primary"}} {{on "click" (fn this.toggleSave @selectedPlace)}}>
|
||||
{{if @selectedPlace.createdAt "Saved ✓" "Save"}}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="meta-info">
|
||||
{{#if (or this.selectedPlace.osmId this.selectedPlace.id)}}
|
||||
<p><small>OSM ID: <a href="https://www.openstreetmap.org/{{if this.selectedPlace.type this.selectedPlace.type 'node'}}/{{or this.selectedPlace.osmId this.selectedPlace.id}}" target="_blank" rel="noopener noreferrer">{{or this.selectedPlace.osmId this.selectedPlace.id}}</a></small></p>
|
||||
{{#if (or @selectedPlace.osmId @selectedPlace.id)}}
|
||||
<p><small>OSM ID: <a href="https://www.openstreetmap.org/{{if @selectedPlace.type @selectedPlace.type 'node'}}/{{or @selectedPlace.osmId @selectedPlace.id}}" target="_blank" rel="noopener noreferrer">{{or @selectedPlace.osmId @selectedPlace.id}}</a></small></p>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -27,6 +27,11 @@ export default class ApplicationComponent extends Component {
|
||||
this.isSidebarOpen = true;
|
||||
}
|
||||
|
||||
@action
|
||||
selectPlace(place) {
|
||||
this.selectedPlace = place;
|
||||
}
|
||||
|
||||
@action
|
||||
closeSidebar() {
|
||||
this.isSidebarOpen = false;
|
||||
@ -46,7 +51,8 @@ export default class ApplicationComponent extends Component {
|
||||
{{#if this.isSidebarOpen}}
|
||||
<PlacesSidebar
|
||||
@places={{this.nearbyPlaces}}
|
||||
@initialPlace={{this.selectedPlace}}
|
||||
@selectedPlace={{this.selectedPlace}}
|
||||
@onSelect={{this.selectPlace}}
|
||||
@onClose={{this.closeSidebar}}
|
||||
/>
|
||||
{{/if}}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user