mirror of
https://github.com/Freika/dawarich.git
synced 2026-01-11 01:31:39 -05:00
Use user timezone to show dates on maps
This commit is contained in:
parent
1c9843dde7
commit
1970d78621
13 changed files with 37 additions and 23 deletions
|
|
@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||
## Fixed
|
||||
|
||||
- Cities visited during a trip are now being calculated correctly. #547
|
||||
- Points on the map are now show time in user's timezone. #580
|
||||
|
||||
|
||||
# [0.36.2] - 2025-12-06
|
||||
|
|
|
|||
|
|
@ -7,7 +7,8 @@ export default class extends Controller {
|
|||
|
||||
static values = {
|
||||
features: Object,
|
||||
userTheme: String
|
||||
userTheme: String,
|
||||
timezone: String
|
||||
}
|
||||
|
||||
connect() {
|
||||
|
|
@ -106,7 +107,8 @@ export default class extends Controller {
|
|||
});
|
||||
|
||||
// Format timestamp for display
|
||||
const lastSeen = new Date(location.updated_at).toLocaleString();
|
||||
const timezone = this.timezoneValue || 'UTC';
|
||||
const lastSeen = new Date(location.updated_at).toLocaleString('en-US', { timeZone: timezone });
|
||||
|
||||
// Create small tooltip that shows automatically
|
||||
const tooltipContent = this.createTooltipContent(lastSeen, location.battery);
|
||||
|
|
@ -176,7 +178,8 @@ export default class extends Controller {
|
|||
existingMarker.setIcon(newIcon);
|
||||
|
||||
// Update tooltip content
|
||||
const lastSeen = new Date(locationData.updated_at).toLocaleString();
|
||||
const timezone = this.timezoneValue || 'UTC';
|
||||
const lastSeen = new Date(locationData.updated_at).toLocaleString('en-US', { timeZone: timezone });
|
||||
const tooltipContent = this.createTooltipContent(lastSeen, locationData.battery);
|
||||
existingMarker.setTooltipContent(tooltipContent);
|
||||
|
||||
|
|
@ -214,7 +217,8 @@ export default class extends Controller {
|
|||
})
|
||||
});
|
||||
|
||||
const lastSeen = new Date(location.updated_at).toLocaleString();
|
||||
const timezone = this.timezoneValue || 'UTC';
|
||||
const lastSeen = new Date(location.updated_at).toLocaleString('en-US', { timeZone: timezone });
|
||||
|
||||
const tooltipContent = this.createTooltipContent(lastSeen, location.battery);
|
||||
familyMarker.bindTooltip(tooltipContent, {
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ export class EventHandlers {
|
|||
|
||||
const content = `
|
||||
<div class="space-y-2">
|
||||
<div><span class="font-semibold">Time:</span> ${formatTimestamp(properties.timestamp)}</div>
|
||||
<div><span class="font-semibold">Time:</span> ${formatTimestamp(properties.timestamp, this.controller.timezoneValue)}</div>
|
||||
${properties.battery ? `<div><span class="font-semibold">Battery:</span> ${properties.battery}%</div>` : ''}
|
||||
${properties.altitude ? `<div><span class="font-semibold">Altitude:</span> ${Math.round(properties.altitude)}m</div>` : ''}
|
||||
${properties.velocity ? `<div><span class="font-semibold">Speed:</span> ${Math.round(properties.velocity)} km/h</div>` : ''}
|
||||
|
|
@ -35,8 +35,8 @@ export class EventHandlers {
|
|||
const feature = e.features[0]
|
||||
const properties = feature.properties
|
||||
|
||||
const startTime = formatTimestamp(properties.started_at)
|
||||
const endTime = formatTimestamp(properties.ended_at)
|
||||
const startTime = formatTimestamp(properties.started_at, this.controller.timezoneValue)
|
||||
const endTime = formatTimestamp(properties.ended_at, this.controller.timezoneValue)
|
||||
const durationHours = Math.round(properties.duration / 3600)
|
||||
const durationDisplay = durationHours >= 1 ? `${durationHours}h` : `${Math.round(properties.duration / 60)}m`
|
||||
|
||||
|
|
@ -70,7 +70,7 @@ export class EventHandlers {
|
|||
const content = `
|
||||
<div class="space-y-2">
|
||||
${properties.photo_url ? `<img src="${properties.photo_url}" alt="Photo" class="w-full rounded-lg mb-2" />` : ''}
|
||||
${properties.taken_at ? `<div><span class="font-semibold">Taken:</span> ${formatTimestamp(properties.taken_at)}</div>` : ''}
|
||||
${properties.taken_at ? `<div><span class="font-semibold">Taken:</span> ${formatTimestamp(properties.taken_at, this.controller.timezoneValue)}</div>` : ''}
|
||||
</div>
|
||||
`
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,8 @@ export default class extends Controller {
|
|||
static values = {
|
||||
apiKey: String,
|
||||
startDate: String,
|
||||
endDate: String
|
||||
endDate: String,
|
||||
timezone: String
|
||||
}
|
||||
|
||||
static targets = [
|
||||
|
|
|
|||
|
|
@ -2220,6 +2220,7 @@ export default class extends BaseController {
|
|||
return;
|
||||
}
|
||||
|
||||
const timezone = this.timezone || 'UTC';
|
||||
const html = citiesData.map(country => `
|
||||
<div class="mb-4" style="min-width: min-content;">
|
||||
<h4 class="font-bold text-md">${country.country}</h4>
|
||||
|
|
@ -2228,7 +2229,7 @@ export default class extends BaseController {
|
|||
<li class="text-sm whitespace-nowrap">
|
||||
${city.city}
|
||||
<span class="text-gray-500">
|
||||
(${new Date(city.timestamp * 1000).toLocaleDateString()})
|
||||
(${new Date(city.timestamp * 1000).toLocaleDateString('en-US', { timeZone: timezone })})
|
||||
</span>
|
||||
</li>
|
||||
`).join('')}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@ export default class extends BaseController {
|
|||
uuid: String,
|
||||
dataBounds: Object,
|
||||
hexagonsAvailable: Boolean,
|
||||
selfHosted: String
|
||||
selfHosted: String,
|
||||
timezone: String
|
||||
};
|
||||
|
||||
connect() {
|
||||
|
|
@ -247,10 +248,11 @@ export default class extends BaseController {
|
|||
}
|
||||
|
||||
buildPopupContent(props) {
|
||||
const startDate = props.earliest_point ? new Date(props.earliest_point).toLocaleDateString() : 'N/A';
|
||||
const endDate = props.latest_point ? new Date(props.latest_point).toLocaleDateString() : 'N/A';
|
||||
const startTime = props.earliest_point ? new Date(props.earliest_point).toLocaleTimeString() : '';
|
||||
const endTime = props.latest_point ? new Date(props.latest_point).toLocaleTimeString() : '';
|
||||
const timezone = this.timezoneValue || 'UTC';
|
||||
const startDate = props.earliest_point ? new Date(props.earliest_point).toLocaleDateString('en-US', { timeZone: timezone }) : 'N/A';
|
||||
const endDate = props.latest_point ? new Date(props.latest_point).toLocaleDateString('en-US', { timeZone: timezone }) : 'N/A';
|
||||
const startTime = props.earliest_point ? new Date(props.earliest_point).toLocaleTimeString('en-US', { timeZone: timezone }) : '';
|
||||
const endTime = props.latest_point ? new Date(props.latest_point).toLocaleTimeString('en-US', { timeZone: timezone }) : '';
|
||||
|
||||
return `
|
||||
<div style="font-size: 12px; line-height: 1.6; max-width: 300px;">
|
||||
|
|
|
|||
|
|
@ -28,9 +28,10 @@ export function pointsToGeoJSON(points) {
|
|||
/**
|
||||
* Format timestamp for display
|
||||
* @param {number|string} timestamp - Unix timestamp (seconds) or ISO 8601 string
|
||||
* @param {string} timezone - IANA timezone string (e.g., 'Europe/Berlin')
|
||||
* @returns {string} Formatted date/time
|
||||
*/
|
||||
export function formatTimestamp(timestamp) {
|
||||
export function formatTimestamp(timestamp, timezone = 'UTC') {
|
||||
// Handle different timestamp formats
|
||||
let date
|
||||
if (typeof timestamp === 'string') {
|
||||
|
|
@ -49,6 +50,7 @@ export function formatTimestamp(timestamp) {
|
|||
month: 'short',
|
||||
day: 'numeric',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit'
|
||||
minute: '2-digit',
|
||||
timeZone: timezone
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,12 +17,13 @@
|
|||
data-tracks='<%= @tracks.to_json.html_safe %>'
|
||||
data-distance="<%= @distance %>"
|
||||
data-points_number="<%= @points_number %>"
|
||||
data-timezone="<%= Rails.configuration.time_zone %>"
|
||||
data-timezone="<%= current_user.timezone %>"
|
||||
data-features='<%= @features.to_json.html_safe %>'
|
||||
data-user_tags='<%= current_user.tags.ordered.select(:id, :name, :icon, :color).as_json.to_json.html_safe %>'
|
||||
data-home_coordinates='<%= @home_coordinates.to_json.html_safe %>'
|
||||
data-family-members-features-value='<%= @features.to_json.html_safe %>'
|
||||
data-family-members-user-theme-value="<%= current_user&.theme || 'dark' %>">
|
||||
data-family-members-user-theme-value="<%= current_user&.theme || 'dark' %>"
|
||||
data-family-members-timezone-value="<%= current_user.timezone %>">
|
||||
<div data-maps-target="container" class="w-full h-full">
|
||||
<div id="fog" class="fog"></div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
data-maps--maplibre-api-key-value="<%= current_user.api_key %>"
|
||||
data-maps--maplibre-start-date-value="<%= @start_at.to_s %>"
|
||||
data-maps--maplibre-end-date-value="<%= @end_at.to_s %>"
|
||||
data-maps--maplibre-timezone-value="<%= current_user.timezone %>"
|
||||
data-maps--maplibre-realtime-enabled-value="true"
|
||||
style="width: 100%; height: 100%; position: relative;">
|
||||
|
||||
|
|
|
|||
|
|
@ -63,7 +63,8 @@
|
|||
data-public-stat-map-uuid-value="<%= @stat.sharing_uuid %>"
|
||||
data-public-stat-map-data-bounds-value="<%= @data_bounds.to_json if @data_bounds %>"
|
||||
data-public-stat-map-hexagons-available-value="<%= @hexagons_available.to_s %>"
|
||||
data-public-stat-map-self-hosted-value="<%= @self_hosted %>"></div>
|
||||
data-public-stat-map-self-hosted-value="<%= @self_hosted %>"
|
||||
data-public-stat-map-timezone-value="<%= @user.timezone %>"></div>
|
||||
|
||||
<!-- Loading overlay -->
|
||||
<div id="map-loading" class="absolute inset-0 bg-base-200 bg-opacity-80 flex items-center justify-center z-50">
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
data-path="<%= trip.path.to_json %>"
|
||||
data-started_at="<%= trip.started_at %>"
|
||||
data-ended_at="<%= trip.ended_at %>"
|
||||
data-timezone="<%= Rails.configuration.time_zone %>">
|
||||
data-timezone="<%= current_user.timezone %>">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
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 %>">
|
||||
data-timezone="<%= trip.user.timezone %>">
|
||||
<div data-trips-target="container" class="h-[25rem] w-full min-h-screen md:h-64">
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
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.safe_settings.settings.to_json %>"
|
||||
data-trip-map-timezone-value="<%= Rails.configuration.time_zone %>">
|
||||
data-trip-map-timezone-value="<%= trip.user.timezone %>">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Reference in a new issue