diff --git a/.app_version b/.app_version index c3d16c16..66333910 100644 --- a/.app_version +++ b/.app_version @@ -1 +1 @@ -0.17.2 +0.18.0 diff --git a/app/controllers/trips_controller.rb b/app/controllers/trips_controller.rb index c6e4b4a6..97492e74 100644 --- a/app/controllers/trips_controller.rb +++ b/app/controllers/trips_controller.rb @@ -6,7 +6,7 @@ class TripsController < ApplicationController before_action :set_coordinates, only: %i[show edit] def index - @trips = current_user.trips.order(created_at: :desc).page(params[:page]) + @trips = current_user.trips.order(started_at: :desc).page(params[:page]).per(6) end def show @@ -22,6 +22,7 @@ class TripsController < ApplicationController def new @trip = Trip.new + @coordinates = [] end def edit; end @@ -55,7 +56,6 @@ class TripsController < ApplicationController @trip = current_user.trips.find(params[:id]) end - def set_coordinates @coordinates = @trip.points.pluck( :latitude, :longitude, :battery, :altitude, :timestamp, :velocity, :id, @@ -64,6 +64,6 @@ class TripsController < ApplicationController end def trip_params - params.require(:trip).permit(:name, :started_at, :ended_at, :notes, :field_notes) + params.require(:trip).permit(:name, :started_at, :ended_at, :notes) end end diff --git a/app/javascript/controllers/maps_controller.js b/app/javascript/controllers/maps_controller.js index b3d62d8a..b00e6d16 100644 --- a/app/javascript/controllers/maps_controller.js +++ b/app/javascript/controllers/maps_controller.js @@ -788,88 +788,6 @@ export default class extends Controller { this.layerControl = L.control.layers(this.baseMaps(), layerControl).addTo(this.map); } - // async fetchAndDisplayPhotos(startDate, endDate, retryCount = 0) { - // const MAX_RETRIES = 3; - // const RETRY_DELAY = 3000; // 3 seconds - - // // Create loading control - // const LoadingControl = L.Control.extend({ - // onAdd: (map) => { - // const container = L.DomUtil.create('div', 'leaflet-loading-control'); - // container.innerHTML = '
'; - // return container; - // } - // }); - - // const loadingControl = new LoadingControl({ position: 'topleft' }); - // this.map.addControl(loadingControl); - - // try { - // const params = new URLSearchParams({ - // api_key: this.apiKey, - // start_date: startDate, - // end_date: endDate - // }); - - // const response = await fetch(`/api/v1/photos?${params}`); - // if (!response.ok) { - // throw new Error(`HTTP error! status: ${response.status}`); - // } - - // const photos = await response.json(); - // this.photoMarkers.clearLayers(); - - // // Create a promise for each photo to track when it's fully loaded - // const photoLoadPromises = photos.map(photo => { - // return new Promise((resolve) => { - // const img = new Image(); - // const thumbnailUrl = `/api/v1/photos/${photo.id}/thumbnail.jpg?api_key=${this.apiKey}`; - - // img.onload = () => { - // this.createPhotoMarker(photo); - // resolve(); - // }; - - // img.onerror = () => { - // console.error(`Failed to load photo ${photo.id}`); - // resolve(); // Resolve anyway to not block other photos - // }; - - // img.src = thumbnailUrl; - // }); - // }); - - // // Wait for all photos to be loaded and rendered - // await Promise.all(photoLoadPromises); - - // if (!this.map.hasLayer(this.photoMarkers)) { - // this.photoMarkers.addTo(this.map); - // } - - // // Show checkmark for 1 second before removing - // const loadingSpinner = document.querySelector('.loading-spinner'); - // loadingSpinner.classList.add('done'); - - // await new Promise(resolve => setTimeout(resolve, 1000)); - - // } catch (error) { - // console.error('Error fetching photos:', error); - // showFlashMessage('error', 'Failed to fetch photos'); - - // if (retryCount < MAX_RETRIES) { - // console.log(`Retrying in ${RETRY_DELAY/1000} seconds... (Attempt ${retryCount + 1}/${MAX_RETRIES})`); - // setTimeout(() => { - // this.fetchAndDisplayPhotos(startDate, endDate, retryCount + 1); - // }, RETRY_DELAY); - // } else { - // showFlashMessage('error', 'Failed to fetch photos after multiple attempts'); - // } - // } finally { - // // Remove loading control after the delay - // this.map.removeControl(loadingControl); - // } - // } - createPhotoMarker(photo) { if (!photo.exifInfo?.latitude || !photo.exifInfo?.longitude) return; diff --git a/app/javascript/controllers/trip_map_controller.js b/app/javascript/controllers/trip_map_controller.js new file mode 100644 index 00000000..b7df8943 --- /dev/null +++ b/app/javascript/controllers/trip_map_controller.js @@ -0,0 +1,60 @@ +import { Controller } from "@hotwired/stimulus" +import L from "leaflet" + +export default class extends Controller { + static values = { + tripId: Number, + coordinates: Array, + apiKey: String, + userSettings: Object, + timezone: String, + distanceUnit: String + } + + connect() { + setTimeout(() => { + this.initializeMap() + }, 100) + } + + initializeMap() { + // Initialize map with basic configuration + this.map = L.map(this.element, { + zoomControl: false, + dragging: false, + scrollWheelZoom: false, + attributionControl: true // Disable default attribution control + }) + + // Add the tile layer + L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { + maxZoom: 19, + attribution: "© OpenStreetMap" + }).addTo(this.map) + + // If we have coordinates, show the route + if (this.hasCoordinatesValue && this.coordinatesValue.length > 0) { + this.showRoute() + } + } + + showRoute() { + const points = this.coordinatesValue.map(coord => [coord[0], coord[1]]) + + const polyline = L.polyline(points, { + color: 'blue', + weight: 3, + opacity: 0.8 + }).addTo(this.map) + + this.map.fitBounds(polyline.getBounds(), { + padding: [20, 20] + }) + } + + disconnect() { + if (this.map) { + this.map.remove() + } + } +} diff --git a/app/javascript/controllers/trips_controller.js b/app/javascript/controllers/trips_controller.js index 5bb15e8c..76ab87ba 100644 --- a/app/javascript/controllers/trips_controller.js +++ b/app/javascript/controllers/trips_controller.js @@ -142,7 +142,7 @@ export default class extends Controller { const polyline = L.polyline(points, { color: 'blue', weight: 3, - opacity: 0.6 + opacity: 0.8 }) // Add to polylines layer instead of directly to map this.polylinesLayer.addTo(this.map) diff --git a/app/models/trip.rb b/app/models/trip.rb index a08e82ee..44f202ab 100644 --- a/app/models/trip.rb +++ b/app/models/trip.rb @@ -1,14 +1,16 @@ # frozen_string_literal: true class Trip < ApplicationRecord - has_rich_text :field_notes + has_rich_text :notes belongs_to :user validates :name, :started_at, :ended_at, presence: true + before_save :calculate_distance + def points - user.points.where(timestamp: started_at.to_i..ended_at.to_i).order(:timestamp) + user.tracked_points.where(timestamp: started_at.to_i..ended_at.to_i).order(:timestamp) end def countries @@ -34,4 +36,20 @@ class Trip < ApplicationRecord { url: "/api/v1/photos/#{asset['id']}/thumbnail.jpg?api_key=#{user.api_key}" } end end + + private + + def calculate_distance + distance = 0 + + points.each_cons(2) do |point1, point2| + distance_between = Geocoder::Calculations.distance_between( + point1.to_coordinates, point2.to_coordinates, units: ::DISTANCE_UNIT + ) + + distance += distance_between + end + + self.distance = distance.round + end end diff --git a/app/views/trips/_form.html.erb b/app/views/trips/_form.html.erb index 221e2ff6..cf5518ff 100644 --- a/app/views/trips/_form.html.erb +++ b/app/views/trips/_form.html.erb @@ -20,7 +20,7 @@ data-distance_unit="<%= DISTANCE_UNIT %>" data-api_key="<%= current_user.api_key %>" data-user_settings="<%= current_user.settings.to_json %>" - data-coordinates="<%= [].to_json %>" + data-coordinates="<%= @coordinates.to_json %>" data-timezone="<%= Rails.configuration.time_zone %>"> @@ -61,8 +61,8 @@| Name | -Started at | -Ended at | -
|---|---|---|
| <%= link_to trip.name, trip, class: 'underline hover:no-underline' %> | -<%= trip.started_at.strftime("%d.%m.%Y, %H:%M") %> | -<%= trip.ended_at.strftime("%d.%m.%Y, %H:%M") %> | -
+ <%= "#{human_date(trip.started_at)} – #{human_date(trip.ended_at)}, #{trip.distance} #{DISTANCE_UNIT}" %> +
+ +- <%= @trip.countries.join(', ') %> + <%= "#{@trip.countries.join(', ')} (#{@trip.distance} #{DISTANCE_UNIT})" %>
<% end %> @@ -34,7 +34,7 @@