mirror of
https://github.com/Freika/dawarich.git
synced 2026-01-10 17:21:38 -05:00
Some frontend fixes
This commit is contained in:
parent
5fbc1fb884
commit
a48cff098b
12 changed files with 76 additions and 72 deletions
32
CHANGELOG.md
32
CHANGELOG.md
|
|
@ -5,24 +5,32 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
|||
and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
|
||||
# 0.26.1 - 2025-05-12
|
||||
# 0.26.1 - 2025-05-15
|
||||
|
||||
Geodata on demand
|
||||
## Geodata on demand
|
||||
|
||||
- [x] Introduce a `STORE_GEODATA` environment variable to control whether to store geodata in the database.
|
||||
- [ ] When `STORE_GEODATA` is disabled, each feature that uses geodata will now make a direct request to the geocoding service to calculate required data.
|
||||
Geodata is being used:
|
||||
- [ ] Fetching places geodata
|
||||
- [x] Fetching countries for a trip
|
||||
- [x] Suggesting place name for a visit
|
||||
- [x] When `STORE_GEODATA` is disabled, points are not being reverse geocoded on creation.
|
||||
- [x] When `STORE_GEODATA` is disabled, countries for a trip are being pulled from the geocoding service.
|
||||
- [x] When `STORE_GEODATA` is enabled, points are being reverse geocoded upon creation and stored in the database.
|
||||
- [ ] Each feature that uses geodata will check if an entity (point, place, etc.) has geodata stored in the database and use it if available. If not, it will make a direct request to the geocoding service to calculate required data.
|
||||
This release introduces a new environment variable `STORE_GEODATA` to control whether to store geodata in the database.
|
||||
|
||||
When `STORE_GEODATA` is disabled, each feature that uses geodata will now make a direct request to the geocoding service to calculate required data.
|
||||
|
||||
Geodata is being used:
|
||||
|
||||
- Fetching places geodata
|
||||
- Fetching countries for a trip
|
||||
- Suggesting place name for a visit
|
||||
|
||||
If you prefer to keep the old behavior, you can set `STORE_GEODATA` to `true`. By default, starting this release, it's set to `false`.
|
||||
|
||||
If you're running your own Photon instance, you can safely set `STORE_GEODATA` to `false`, otherwise it'd be better to keep it enabled, because that way Dawarich will be using existing geodata for its calculations.
|
||||
|
||||
## Added
|
||||
|
||||
- Map page now has a button to go to the previous and next day. #296 #631 #904
|
||||
|
||||
## Changed
|
||||
|
||||
- Reverse geocoding is now working as on-demand job instead of storing the result in the database.
|
||||
- Stats cards now show the last update time. #733
|
||||
|
||||
## Fixed
|
||||
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -5,7 +5,7 @@ class StatsController < ApplicationController
|
|||
before_action :authenticate_active_user!, only: %i[update update_all]
|
||||
|
||||
def index
|
||||
@stats = current_user.stats.group_by(&:year).sort.reverse
|
||||
@stats = current_user.stats.group_by(&:year).transform_values { |stats| stats.sort_by(&:updated_at).reverse }.sort.reverse
|
||||
@points_total = current_user.tracked_points.count
|
||||
@points_reverse_geocoded = current_user.total_reverse_geocoded_points
|
||||
@points_reverse_geocoded_without_data = current_user.total_reverse_geocoded_points_without_data
|
||||
|
|
|
|||
|
|
@ -15,9 +15,9 @@ class Api::PlaceSerializer
|
|||
country: place.country,
|
||||
source: place.source,
|
||||
geodata: place.geodata,
|
||||
reverse_geocoded_at: place.reverse_geocoded_at,
|
||||
created_at: place.created_at,
|
||||
updated_at: place.updated_at
|
||||
updated_at: place.updated_at,
|
||||
reverse_geocoded_at: place.reverse_geocoded_at
|
||||
}
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -21,10 +21,8 @@ class Trips::Countries
|
|||
|
||||
batches = split_into_batches(all_points, @batch_count)
|
||||
threads_results = process_batches_in_threads(batches, total_points)
|
||||
country_counts = merge_thread_results(threads_results)
|
||||
|
||||
log_results(country_counts, total_points)
|
||||
country_counts.sort_by { |_country, count| -count }.to_h
|
||||
merge_thread_results(threads_results).uniq.compact
|
||||
end
|
||||
|
||||
private
|
||||
|
|
@ -39,10 +37,9 @@ class Trips::Countries
|
|||
threads_results = []
|
||||
threads = []
|
||||
|
||||
batches.each_with_index do |batch, batch_index|
|
||||
start_index = batch_index * batch.size + 1
|
||||
batches.each do |batch|
|
||||
threads << Thread.new do
|
||||
threads_results << process_batch(batch, start_index, total_points)
|
||||
threads_results << process_batch(batch)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -51,63 +48,32 @@ class Trips::Countries
|
|||
end
|
||||
|
||||
def merge_thread_results(threads_results)
|
||||
country_counts = {}
|
||||
countries = []
|
||||
|
||||
threads_results.each do |result|
|
||||
result.each do |country, count|
|
||||
country_counts[country] ||= 0
|
||||
country_counts[country] += count
|
||||
end
|
||||
countries.concat(result)
|
||||
end
|
||||
|
||||
country_counts
|
||||
countries
|
||||
end
|
||||
|
||||
def log_results(country_counts, total_points)
|
||||
total_counted = country_counts.values.sum
|
||||
Rails.logger.info("Processed #{total_points} points and found #{country_counts.size} countries")
|
||||
Rails.logger.info("Points counted: #{total_counted} out of #{total_points}")
|
||||
end
|
||||
|
||||
def process_batch(points, start_index, total_points)
|
||||
country_counts = {}
|
||||
|
||||
points.each_with_index do |point, idx|
|
||||
current_index = start_index + idx
|
||||
country_code = geocode_point(point, current_index, total_points)
|
||||
def process_batch(points)
|
||||
points.map do |point|
|
||||
country_code = geocode_point(point)
|
||||
next unless country_code
|
||||
|
||||
country_counts[country_code] ||= 0
|
||||
country_counts[country_code] += 1
|
||||
country_code
|
||||
end
|
||||
end
|
||||
|
||||
country_counts
|
||||
end
|
||||
|
||||
def geocode_point(point, current_index, total_points)
|
||||
def geocode_point(point)
|
||||
lonlat = point.lonlat
|
||||
return nil unless lonlat
|
||||
|
||||
latitude = lonlat.y
|
||||
longitude = lonlat.x
|
||||
|
||||
log_processing_point(current_index, total_points, latitude, longitude)
|
||||
country_code = fetch_country_code(latitude, longitude)
|
||||
log_found_country(country_code, latitude, longitude) if country_code
|
||||
|
||||
country_code
|
||||
end
|
||||
|
||||
def log_processing_point(current_index, total_points, latitude, longitude)
|
||||
thread_id = Thread.current.object_id
|
||||
Rails.logger.info(
|
||||
"Thread #{thread_id}: Processing point #{current_index} of #{total_points}: lat=#{latitude}, lon=#{longitude}"
|
||||
)
|
||||
end
|
||||
|
||||
def log_found_country(country_code, latitude, longitude)
|
||||
thread_id = Thread.current.object_id
|
||||
Rails.logger.info("Thread #{thread_id}: Found country: #{country_code} for point at #{latitude}, #{longitude}")
|
||||
fetch_country_code(latitude, longitude)
|
||||
end
|
||||
|
||||
def fetch_country_code(latitude, longitude)
|
||||
|
|
|
|||
|
|
@ -5,18 +5,36 @@
|
|||
<div class="flex flex-col space-y-4 mb-4 w-full">
|
||||
<%= form_with url: map_path(import_id: params[:import_id]), method: :get do |f| %>
|
||||
<div class="flex flex-col space-y-4 sm:flex-row sm:space-y-0 sm:space-x-4 sm:items-end">
|
||||
<div class="w-full sm:w-2/12 md:w-1/12 lg:w-3/12">
|
||||
<div class="w-full sm:w-1/12 md:w-1/12 lg:w-1/12">
|
||||
<div class="flex flex-col space-y-2">
|
||||
<span class="tooltip" data-tip="<%= human_date(@start_at - 1.day) %>">
|
||||
<%= link_to map_path(start_at: @start_at - 1.day, end_at: @end_at - 1.day, import_id: params[:import_id]), class: "btn btn-neutral hover:btn-ghost w-full" do %>
|
||||
◀️
|
||||
<% end %>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-full sm:w-2/12 md:w-1/12 lg:w-2/12">
|
||||
<div class="flex flex-col space-y-2">
|
||||
<%= f.label :start_at, class: "text-sm font-semibold" %>
|
||||
<%= f.datetime_local_field :start_at, include_seconds: false, class: "input input-bordered hover:cursor-pointer hover:input-primary", value: @start_at %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-full sm:w-2/12 md:w-1/12 lg:w-3/12">
|
||||
<div class="w-full sm:w-2/12 md:w-1/12 lg:w-2/12">
|
||||
<div class="flex flex-col space-y-2">
|
||||
<%= f.label :end_at, class: "text-sm font-semibold" %>
|
||||
<%= f.datetime_local_field :end_at, include_seconds: false, class: "input input-bordered hover:cursor-pointer hover:input-primary", value: @end_at %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-full sm:w-1/12 md:w-1/12 lg:w-1/12">
|
||||
<div class="flex flex-col space-y-2">
|
||||
<span class="tooltip" data-tip="<%= human_date(@start_at + 1.day) %>">
|
||||
<%= link_to map_path(start_at: @start_at + 1.day, end_at: @end_at + 1.day, import_id: params[:import_id]), class: "btn btn-neutral hover:btn-ghost w-full" do %>
|
||||
▶️
|
||||
<% end %>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-full sm:w-6/12 md:w-2/12 lg:w-1/12">
|
||||
<div class="flex flex-col space-y-2">
|
||||
<%= f.submit "Search", class: "btn btn-primary hover:btn-info" %>
|
||||
|
|
|
|||
|
|
@ -7,11 +7,12 @@
|
|||
<% end %>
|
||||
</h2>
|
||||
|
||||
<div class="flex items-center gap-2">
|
||||
<%= link_to '[Update]', update_year_month_stats_path(stat.year, stat.month), data: { turbo_method: :put }, class: 'text-sm text-gray-500 hover:underline' %>
|
||||
<div class="gap-2">
|
||||
<span class='text-xs text-gray-500'>Last update <%= human_date(stat.updated_at) %></span>
|
||||
<%= link_to '🔄', update_year_month_stats_path(stat.year, stat.month), data: { turbo_method: :put }, class: 'text-sm text-gray-500 hover:underline' %>
|
||||
</div>
|
||||
</div>
|
||||
<p><%= stat.distance %><%= DISTANCE_UNIT %></p>
|
||||
<p><%= number_with_delimiter stat.distance %><%= DISTANCE_UNIT %></p>
|
||||
<% if DawarichSettings.reverse_geocoding_enabled? %>
|
||||
<div class="card-actions justify-end">
|
||||
<%= countries_and_cities_stat_for_month(stat) %>
|
||||
|
|
|
|||
|
|
@ -32,7 +32,10 @@
|
|||
<%= link_to year, "/stats/#{year}", class: 'underline hover:no-underline' %>
|
||||
<%= link_to '[Map]', map_url(year_timespan(year)), class: 'underline hover:no-underline' %>
|
||||
</div>
|
||||
<%= link_to '[Update]', update_year_month_stats_path(year, :all), data: { turbo_method: :put }, class: 'text-sm text-gray-500 hover:underline' %>
|
||||
<div class="gap-2">
|
||||
<span class='text-xs text-gray-500'>Last updated: <%= human_date(stats.first.updated_at) %></span>
|
||||
<%= link_to '🔄', update_year_month_stats_path(year, :all), data: { turbo_method: :put }, class: 'text-sm text-gray-500 hover:underline' %>
|
||||
</div>
|
||||
</h2>
|
||||
<p>
|
||||
<% cache [current_user, 'year_distance_stat', year], skip_digest: true do %>
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ services:
|
|||
PROMETHEUS_EXPORTER_PORT: 9394
|
||||
SECRET_KEY_BASE: 1234567890
|
||||
RAILS_LOG_TO_STDOUT: "true"
|
||||
STORE_GEODATA: "false"
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
|
|
@ -124,6 +125,7 @@ services:
|
|||
PROMETHEUS_EXPORTER_PORT: 9394
|
||||
SECRET_KEY_BASE: 1234567890
|
||||
RAILS_LOG_TO_STDOUT: "true"
|
||||
STORE_GEODATA: "false"
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ services:
|
|||
PROMETHEUS_EXPORTER_HOST: 0.0.0.0
|
||||
PROMETHEUS_EXPORTER_PORT: 9394
|
||||
SELF_HOSTED: "true"
|
||||
STORE_GEODATA: "false"
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
|
|
@ -122,6 +123,7 @@ services:
|
|||
PROMETHEUS_EXPORTER_HOST: dawarich_app
|
||||
PROMETHEUS_EXPORTER_PORT: 9394
|
||||
SELF_HOSTED: "true"
|
||||
STORE_GEODATA: "false"
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ MIN_MINUTES_SPENT_IN_CITY=60
|
|||
APPLICATION_HOSTS=dawarich.example.synology.me
|
||||
TIME_ZONE=Europe/Berlin
|
||||
BACKGROUND_PROCESSING_CONCURRENCY=10
|
||||
STORE_GEODATA=false
|
||||
|
||||
###################################################################################
|
||||
# Database
|
||||
|
|
|
|||
|
|
@ -9,8 +9,11 @@ RSpec.describe ReverseGeocoding::Points::FetchData do
|
|||
|
||||
context 'when Geocoder returns city and country' do
|
||||
before do
|
||||
allow(Geocoder).to receive(:search).and_return([double(city: 'City', country: 'Country',
|
||||
data: { 'address' => 'Address' })])
|
||||
allow(Geocoder).to receive(:search).and_return(
|
||||
[
|
||||
double(city: 'City', country: 'Country',data: { 'address' => 'Address' })
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
context 'when point does not have city and country' do
|
||||
|
|
|
|||
Loading…
Reference in a new issue