Use protomaps in trips

This commit is contained in:
Eugene Burmakin 2025-05-15 22:25:47 +02:00
parent 088d8b14c2
commit 48e73b4f1d
6 changed files with 86 additions and 65 deletions

File diff suppressed because one or more lines are too long

View file

@ -3,6 +3,7 @@
import BaseController from "./base_controller"
import L from "leaflet"
import { createAllMapLayers } from "../maps/layers"
export default class extends BaseController {
static values = {
@ -31,11 +32,13 @@ export default class extends BaseController {
attributionControl: true
})
// Add the tile layer
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
attribution: "&copy; <a href='http://www.openstreetmap.org/copyright'>OpenStreetMap</a>"
}).addTo(this.map)
// Add base map layer
const selectedLayerName = this.hasUserSettingsValue ?
this.userSettingsValue.preferred_map_layer || "OpenStreetMap" :
"OpenStreetMap";
const maps = this.baseMaps();
const defaultLayer = maps[selectedLayerName] || Object.values(maps)[0];
defaultLayer.addTo(this.map);
// If we have coordinates, show the route
if (this.hasPathValue && this.pathValue) {
@ -45,8 +48,39 @@ export default class extends BaseController {
}
}
baseMaps() {
const selectedLayerName = this.hasUserSettingsValue ?
this.userSettingsValue.preferred_map_layer || "OpenStreetMap" :
"OpenStreetMap";
let maps = createAllMapLayers(this.map, selectedLayerName);
// Add custom map if it exists in settings
if (this.hasUserSettingsValue && this.userSettingsValue.maps && this.userSettingsValue.maps.url) {
const customLayer = L.tileLayer(this.userSettingsValue.maps.url, {
maxZoom: 19,
attribution: "&copy; OpenStreetMap contributors"
});
// If this is the preferred layer, add it to the map immediately
if (selectedLayerName === this.userSettingsValue.maps.name) {
customLayer.addTo(this.map);
// Remove any other base layers that might be active
Object.values(maps).forEach(layer => {
if (this.map.hasLayer(layer)) {
this.map.removeLayer(layer);
}
});
}
maps[this.userSettingsValue.maps.name] = customLayer;
}
return maps;
}
showRoute() {
const points = this.parseLineString(this.pathValue)
const points = this.getCoordinates(this.pathValue)
// Only create polyline if we have points
if (points.length > 0) {
@ -69,37 +103,34 @@ export default class extends BaseController {
}
}
parseLineString(linestring) {
getCoordinates(pathData) {
try {
// Remove 'LINESTRING (' from start and ')' from end
const coordsString = linestring
.replace(/LINESTRING\s*\(/, '') // Remove LINESTRING and opening parenthesis
.replace(/\)$/, '') // Remove closing parenthesis
.trim() // Remove any leading/trailing whitespace
// Parse the path data if it's a string
let coordinates = pathData;
if (typeof pathData === 'string') {
try {
coordinates = JSON.parse(pathData);
} catch (e) {
console.error("Error parsing path data as JSON:", e);
return [];
}
}
// Split into coordinate pairs and parse
const points = coordsString.split(',').map(pair => {
// Clean up any extra whitespace and remove any special characters
const cleanPair = pair.trim().replace(/[()"\s]+/g, ' ')
const [lng, lat] = cleanPair.split(' ').filter(Boolean).map(Number)
// Handle array format - convert from [lng, lat] to [lat, lng] for Leaflet
return coordinates.map(coord => {
const [lng, lat] = coord;
// Validate the coordinates
if (isNaN(lat) || isNaN(lng) || !lat || !lng) {
console.error("Invalid coordinates:", cleanPair)
return null
console.error("Invalid coordinates:", coord);
return null;
}
return [lat, lng] // Leaflet uses [lat, lng] order
}).filter(point => point !== null) // Remove any invalid points
// Validate we have points before returning
if (points.length === 0) {
return []
}
return points
return [lat, lng]; // Leaflet uses [lat, lng] order
}).filter(point => point !== null);
} catch (error) {
return []
console.error("Error processing coordinates:", error);
return [];
}
}

View file

@ -133,22 +133,31 @@ export default class extends BaseController {
// After map initialization, add the path if it exists
if (this.containerTarget.dataset.path) {
const pathData = this.containerTarget.dataset.path.replace(/^"|"$/g, ''); // Remove surrounding quotes
const coordinates = this.parseLineString(pathData);
try {
let coordinates;
const pathData = this.containerTarget.dataset.path.replace(/^"|"$/g, ''); // Remove surrounding quotes
const polyline = L.polyline(coordinates, {
color: 'blue',
opacity: 0.8,
weight: 3,
zIndexOffset: 400
});
// Try to parse as JSON first (new format)
coordinates = JSON.parse(pathData);
// Convert from [lng, lat] to [lat, lng] for Leaflet
coordinates = coordinates.map(coord => [coord[1], coord[0]]);
polyline.addTo(this.polylinesLayer);
this.polylinesLayer.addTo(this.map);
const polyline = L.polyline(coordinates, {
color: 'blue',
opacity: 0.8,
weight: 3,
zIndexOffset: 400
});
// Fit the map to the polyline bounds
if (coordinates.length > 0) {
this.map.fitBounds(polyline.getBounds(), { padding: [50, 50] });
polyline.addTo(this.polylinesLayer);
this.polylinesLayer.addTo(this.map);
// Fit the map to the polyline bounds
if (coordinates.length > 0) {
this.map.fitBounds(polyline.getBounds(), { padding: [50, 50] });
}
} catch (error) {
console.error("Error processing path data:", error);
}
}
}
@ -246,17 +255,4 @@ export default class extends BaseController {
this.fitMapToBounds()
}
}
// Add this method to parse the LineString format
parseLineString(lineString) {
// Remove LINESTRING and parentheses, then split into coordinate pairs
const coordsString = lineString.replace('LINESTRING (', '').replace(')', '');
const coords = coordsString.split(', ');
// Convert each coordinate pair to [lat, lng] format
return coords.map(coord => {
const [lng, lat] = coord.split(' ').map(Number);
return [lat, lng]; // Swap to lat, lng for Leaflet
});
}
}

View file

@ -10,12 +10,6 @@ class Trip < ApplicationRecord
after_create :enqueue_calculation_jobs
after_update :enqueue_calculation_jobs, if: -> { saved_change_to_started_at? || saved_change_to_ended_at? }
def calculate_trip_data
calculate_path
calculate_distance
calculate_countries
end
def enqueue_calculation_jobs
Trips::CalculateAllJob.perform_later(id)
end

View file

@ -7,7 +7,7 @@
data-distance_unit="<%= DISTANCE_UNIT %>"
data-api_key="<%= current_user.api_key %>"
data-user_settings="<%= current_user.settings.to_json %>"
data-path="<%= trip.path.to_json %>"
data-path="<%= trip.path.coordinates.to_json %>"
data-started_at="<%= trip.started_at %>"
data-ended_at="<%= trip.ended_at %>"
data-timezone="<%= Rails.configuration.time_zone %>">

View file

@ -13,7 +13,7 @@
class="rounded-lg z-0"
data-controller="trip-map"
data-trip-map-trip-id-value="<%= trip.id %>"
data-trip-map-path-value="<%= trip.path.to_json %>"
data-trip-map-path-value="<%= trip.path.coordinates.to_json %>"
data-trip-map-api-key-value="<%= current_user.api_key %>"
data-trip-map-user-settings-value="<%= current_user.settings.to_json %>"
data-trip-map-timezone-value="<%= Rails.configuration.time_zone %>"