neiam
/apollos_crib
It's Apollo's Crib
public · Issues · Pulls 1 · Labels · Forks · Compare · Actions failure · Badges · Packages
⭐
Log in to mark this repository.
some big development in mapping
c32f492 · gmorell · 2025-09-15 16:07
Files changed
modified
apps/room_sanctum/assets/js/hooks/leaflet_map.js
+67
−3
@@ -405,6 +405,21 @@ const LeafletMap = {
| 405 | 405 | const popupContent = this.createFreeBikePopupContent(bike); |
| 406 | 406 | marker.bindPopup(popupContent); |
| 407 | 407 | |
| 408 | + // Add event listener for the add query button after popup opens | |
| 409 | + marker.on('popupopen', (e) => { | |
| 410 | + const popup = e.popup; | |
| 411 | + const addQueryBtn = popup.getElement().querySelector('.add-area-query-btn'); | |
| 412 | + if (addQueryBtn) { | |
| 413 | + addQueryBtn.addEventListener('click', () => { | |
| 414 | + this.pushEvent('add-query-from-map', { | |
| 415 | + station_id: bike.bike_id, | |
| 416 | + name: 'Free Bike Area Query', | |
| 417 | + type: 'area' | |
| 418 | + }); | |
| 419 | + }); | |
| 420 | + } | |
| 421 | + }); | |
| 422 | + | |
| 408 | 423 | return marker; |
| 409 | 424 | }, |
| 410 | 425 |
@@ -419,6 +434,21 @@ const LeafletMap = {
| 419 | 434 | const popupContent = this.createStationPopupContent(station); |
| 420 | 435 | marker.bindPopup(popupContent); |
| 421 | 436 | |
| 437 | + // Add event listener for the add query button after popup opens | |
| 438 | + marker.on('popupopen', (e) => { | |
| 439 | + const popup = e.popup; | |
| 440 | + const addQueryBtn = popup.getElement().querySelector('.add-query-btn'); | |
| 441 | + if (addQueryBtn) { | |
| 442 | + addQueryBtn.addEventListener('click', () => { | |
| 443 | + this.pushEvent('add-query-from-map', { | |
| 444 | + station_id: station.station_id, | |
| 445 | + name: station.name || 'Station', | |
| 446 | + type: 'station' | |
| 447 | + }); | |
| 448 | + }); | |
| 449 | + } | |
| 450 | + }); | |
| 451 | + | |
| 422 | 452 | return marker; |
| 423 | 453 | }, |
| 424 | 454 |
@@ -659,10 +689,22 @@ const LeafletMap = {
| 659 | 689 | </div> |
| 660 | 690 | ` : ''} |
| 661 | 691 | |
| 662 | − <div class="text-xs text-gray-500"> | |
| 692 | + <div class="text-xs text-gray-500 mb-2"> | |
| 663 | 693 | <i class="fa-solid fa-location-dot mr-1"></i> |
| 664 | 694 | ${bike.lat.toFixed(4)}, ${bike.lng.toFixed(4)} |
| 665 | 695 | </div> |
| 696 | + | |
| 697 | + <div class="flex justify-center mt-2"> | |
| 698 | + <button | |
| 699 | + class="add-area-query-btn btn btn-sm btn-secondary text-xs px-3 py-1 rounded-md bg-green-600 hover:bg-green-700 text-white transition-colors" | |
| 700 | + data-bike-id="${bike.bike_id}" | |
| 701 | + data-query-type="area" | |
| 702 | + title="Create an area query around this bike location" | |
| 703 | + > | |
| 704 | + <i class="fa-solid fa-plus mr-1"></i> | |
| 705 | + Add Area Query | |
| 706 | + </button> | |
| 707 | + </div> | |
| 666 | 708 | </div> |
| 667 | 709 | `; |
| 668 | 710 | }, |
@@ -751,10 +793,22 @@ const LeafletMap = {
| 751 | 793 | </div> |
| 752 | 794 | ` : ''} |
| 753 | 795 | |
| 754 | − <div class="text-xs text-gray-500"> | |
| 796 | + <div class="text-xs text-gray-500 mb-2"> | |
| 755 | 797 | <i class="fa-solid fa-location-dot mr-1"></i> |
| 756 | 798 | ${station.lat.toFixed(4)}, ${station.lng.toFixed(4)} |
| 757 | 799 | </div> |
| 800 | + | |
| 801 | + <div class="flex justify-center mt-2"> | |
| 802 | + <button | |
| 803 | + class="add-query-btn btn btn-sm btn-primary text-xs px-3 py-1 rounded-md bg-blue-600 hover:bg-blue-700 text-white transition-colors" | |
| 804 | + data-station-id="${station.station_id}" | |
| 805 | + data-station-name="${(station.name || 'Station').replace(/"/g, '"')}" | |
| 806 | + data-query-type="station" | |
| 807 | + > | |
| 808 | + <i class="fa-solid fa-plus mr-1"></i> | |
| 809 | + Add Query | |
| 810 | + </button> | |
| 811 | + </div> | |
| 758 | 812 | </div> |
| 759 | 813 | `; |
| 760 | 814 | }, |
@@ -789,10 +843,20 @@ const LeafletMap = {
| 789 | 843 | </div> |
| 790 | 844 | ` : ''} |
| 791 | 845 | |
| 792 | − <div class="text-xs text-gray-500"> | |
| 846 | + <div class="text-xs text-gray-500 mb-2"> | |
| 793 | 847 | <i class="fa-solid fa-location-dot mr-1"></i> |
| 794 | 848 | ${query.lat.toFixed(4)}, ${query.lng.toFixed(4)} |
| 795 | 849 | </div> |
| 850 | + | |
| 851 | + <div class="flex justify-center mt-2"> | |
| 852 | + <button | |
| 853 | + class="btn btn-sm btn-primary text-xs px-3 py-1 rounded-md bg-blue-600 hover:bg-blue-700 text-white transition-colors" | |
| 854 | + onclick="window.liveSocket.execJS(this, [['push', {event: 'add-query-from-map', value: {station_id: '${query.id}', name: '${query.name.replace(/'/g, "\\'")}', type: 'query'}}]])" | |
| 855 | + > | |
| 856 | + <i class="fa-solid fa-plus mr-1"></i> | |
| 857 | + Duplicate Query | |
| 858 | + </button> | |
| 859 | + </div> | |
| 796 | 860 | </div> |
| 797 | 861 | `; |
| 798 | 862 | }, |
modified
apps/room_sanctum/lib/room_sanctum_web/live/cfg_source_live/show.ex
+65
−0
@@ -235,6 +235,71 @@ defmodule RoomSanctumWeb.SourceLive.Show do
| 235 | 235 | {:noreply, socket |> assign(:tester_selected, nil) |> assign(:tester_selected_name, nil)} |
| 236 | 236 | end |
| 237 | 237 | |
| 238 | + @impl true | |
| 239 | + def handle_event("add-query-from-map", %{"station_id" => station_id, "name" => name, "type" => type}, socket) do | |
| 240 | + case {socket.assigns.source.type, type} do | |
| 241 | + {:gbfs, "station"} -> | |
| 242 | + Configuration.create_query( | |
| 243 | + %{ | |
| 244 | + user_id: socket.assigns.current_user.id, | |
| 245 | + source_id: socket.assigns.source.id, | |
| 246 | + name: "#{name} - Station Query", | |
| 247 | + query: %{"stop_id" => station_id, "__type__" => "gbfs"}, | |
| 248 | + public: true | |
| 249 | + }) |> IO.inspect | |
| 250 | + | |
| 251 | + {:gbfs, "area"} -> | |
| 252 | + # For free bike area queries, create a radius-based query around the bike location | |
| 253 | + # We'll use a default 500m radius, but this could be made configurable | |
| 254 | + bike = Enum.find(socket.assigns.free_bikes, &(&1.bike_id == station_id)) | |
| 255 | + if bike do | |
| 256 | + Configuration.create_query( | |
| 257 | + %{ | |
| 258 | + user_id: socket.assigns.current_user.id, | |
| 259 | + source_id: socket.assigns.source.id, | |
| 260 | + name: "Free Bikes around #{bike.lat}, #{bike.lon}", | |
| 261 | + query: %{ | |
| 262 | + "lat" => bike.lat, | |
| 263 | + "lng" => bike.lon, | |
| 264 | + "radius" => 500, # 500 meter radius | |
| 265 | + "__type__" => "gbfs" | |
| 266 | + }, | |
| 267 | + public: true | |
| 268 | + }) |> IO.inspect | |
| 269 | + end | |
| 270 | + | |
| 271 | + {:gtfs, "stop"} -> | |
| 272 | + Configuration.create_query( | |
| 273 | + %{ | |
| 274 | + user_id: socket.assigns.current_user.id, | |
| 275 | + source_id: socket.assigns.source.id, | |
| 276 | + name: "#{name} - Stop Query", | |
| 277 | + query: %{"stop" => station_id, "__type__" => "gtfs"}, | |
| 278 | + public: true | |
| 279 | + }) |> IO.inspect | |
| 280 | + | |
| 281 | + {_, "query"} -> | |
| 282 | + # For duplicating existing queries, find the original and copy it | |
| 283 | + original_query = Enum.find(socket.assigns.queries, &(&1.id == String.to_integer(station_id))) | |
| 284 | + if original_query do | |
| 285 | + Configuration.create_query( | |
| 286 | + %{ | |
| 287 | + user_id: socket.assigns.current_user.id, | |
| 288 | + source_id: socket.assigns.source.id, | |
| 289 | + name: "Copy of #{original_query.name}", | |
| 290 | + query: original_query.query, | |
| 291 | + public: true | |
| 292 | + }) |> IO.inspect | |
| 293 | + end | |
| 294 | + | |
| 295 | + _ -> | |
| 296 | + IO.inspect("Unhandled query creation for type: #{type}, source: #{socket.assigns.source.type}") | |
| 297 | + end | |
| 298 | + | |
| 299 | + # Show a temporary success message or update | |
| 300 | + {:noreply, socket |> put_flash(:info, "Query created successfully!")} | |
| 301 | + end | |
| 302 | + | |
| 238 | 303 | @impl true |
| 239 | 304 | def handle_event("select-foci", %{"foci" => foci, "distance" => distance} = data, socket) do |
| 240 | 305 | IO.inspect(data) |
Parents: 18ad607