Allow sharing digest for 1 week or 1 month

This commit is contained in:
Eugene Burmakin 2025-12-27 23:03:31 +01:00
parent 230e641808
commit df26984777
13 changed files with 56 additions and 51 deletions

View file

@ -68,12 +68,14 @@ class Stat < ApplicationRecord
def enable_sharing!(expiration: '1h')
# Default to 24h if an invalid expiration is provided
expiration = '24h' unless %w[1h 12h 24h].include?(expiration)
expiration = '24h' unless %w[1h 12h 24h 1w 1m].include?(expiration)
expires_at = case expiration
when '1h' then 1.hour.from_now
when '12h' then 12.hours.from_now
when '24h' then 24.hours.from_now
when '1w' then 1.week.from_now
when '1m' then 1.month.from_now
end
update!(

View file

@ -46,12 +46,14 @@ class Users::Digest < ApplicationRecord
end
def enable_sharing!(expiration: '24h')
expiration = '24h' unless %w[1h 12h 24h].include?(expiration)
expiration = '24h' unless %w[1h 12h 24h 1w 1m].include?(expiration)
expires_at = case expiration
when '1h' then 1.hour.from_now
when '12h' then 12.hours.from_now
when '24h' then 24.hours.from_now
when '1w' then 1.week.from_now
when '1m' then 1.month.from_now
end
update!(
@ -127,7 +129,7 @@ class Users::Digest < ApplicationRecord
end
def total_distance_all_time
all_time_stats['total_distance'] || 0
(all_time_stats['total_distance'] || 0).to_i
end
def distance_km

View file

@ -76,12 +76,12 @@ module Users
result = {}
monthly_stats.each do |stat|
result[stat.month.to_s] = stat.distance
result[stat.month.to_s] = stat.distance.to_s
end
# Fill in missing months with 0
(1..12).each do |month|
result[month.to_s] ||= 0
result[month.to_s] ||= '0'
end
result
@ -131,7 +131,7 @@ module Users
{
'total_countries' => user.countries_visited.count,
'total_cities' => user.cities_visited.count,
'total_distance' => user.stats.sum(:distance)
'total_distance' => user.stats.sum(:distance).to_s
}
end
end

View file

@ -43,7 +43,9 @@
<%= options_for_select([
['1 hour', '1h'],
['12 hours', '12h'],
['24 hours', '24h']
['24 hours', '24h'],
['1 week', '1w'],
['1 month', '1m']
], @stat&.sharing_settings&.dig('expiration') || '1h') %>
</select>
</div>

View file

@ -27,8 +27,9 @@
<% if @digests.empty? %>
<div class="card bg-base-200 shadow-xl">
<div class="card-body text-center py-12">
<div class="text-6xl mb-4"><%= icon 'earth' %></div>
<h2 class="text-xl font-semibold mb-2">No Year-End Digests Yet</h2>
<h2 class="text-xl font-semibold mb-2 flex items-center justify-center gap-2">
<%= icon 'earth' %>No Year-End Digests Yet
</h2>
<p class="text-gray-500 mb-4">
Year-end digests are automatically generated on January 1st each year.
<% if @available_years.any? && current_user.active? %>

View file

@ -80,7 +80,7 @@
<div class="w-full h-48 bg-base-200 rounded-lg p-4 relative">
<%= column_chart(
@digest.monthly_distances.sort.map { |month, distance_meters|
[Date::ABBR_MONTHNAMES[month.to_i], Users::Digest.convert_distance(distance_meters, @distance_unit).round]
[Date::ABBR_MONTHNAMES[month.to_i], Users::Digest.convert_distance(distance_meters.to_i, @distance_unit).round]
},
height: '200px',
suffix: " #{@distance_unit}",

View file

@ -102,7 +102,7 @@
<div class="w-full h-64 bg-base-100 rounded-lg p-4">
<%= column_chart(
@digest.monthly_distances.sort.map { |month, distance_meters|
[Date::ABBR_MONTHNAMES[month.to_i], Users::Digest.convert_distance(distance_meters, @distance_unit).round]
[Date::ABBR_MONTHNAMES[month.to_i], Users::Digest.convert_distance(distance_meters.to_i, @distance_unit).round]
},
height: '250px',
suffix: " #{@distance_unit}",
@ -262,8 +262,10 @@
<%= options_for_select([
['1 hour', '1h'],
['12 hours', '12h'],
['24 hours', '24h']
], @digest&.sharing_settings&.dig('expiration') || '1h') %>
['24 hours', '24h'],
['1 week', '1w'],
['1 month', '1m']
], @digest&.sharing_settings&.dig('expiration') || '24h') %>
</select>
</div>

View file

@ -166,6 +166,12 @@
<p>Your journey, by the numbers</p>
</div>
<div class="content">
<p>
Hi, this is Evgenii from Dawarich! Pretty wild journey last yeah, huh? Let's take a look back at all the places you explored in <strong><%= @digest.year %></strong>.
</p>
</div>
<div class="content">
<!-- Distance Traveled -->
<div class="stat-card">
@ -276,6 +282,12 @@
</div>
</div>
<div class="content">
<p>
You can open your digest for sharing on its page on Dawarich: <a href="<%= users_digest_url(year: @digest.year) %>"><%= users_digest_url(year: @digest.year) %></a>
</p>
</div>
<div class="footer">
<p>Powered by <a href="https://dawarich.app">Dawarich</a>, your personal location history.</p>
<p class="unsubscribe">

View file

@ -1,9 +1,7 @@
<%= @digest.year %> Year in Review
====================================
Hi <%= @user.email %>,
Here's your year in review!
Hi, this is Evgenii from Dawarich! Pretty wild journey last year, huh? Let's take a look back at all the places you explored in <%= @digest.year %>.
DISTANCE TRAVELED
<%= distance_with_unit(@digest.distance, @distance_unit) %>
@ -34,6 +32,8 @@ ALL-TIME STATS
- <%= @digest.total_cities_all_time %> cities explored
- <%= distance_with_unit(@digest.total_distance_all_time, @distance_unit) %> traveled
Keep exploring, keep discovering. Here's to even more adventures in <%= @digest.year + 1 %>!
--
Powered by Dawarich
https://dawarich.app

View file

@ -1,16 +0,0 @@
# frozen_string_literal: true
class ChangeDigestsDistanceToBigint < ActiveRecord::Migration[8.0]
# Safe: digests table is new with minimal data
disable_ddl_transaction!
def change
if respond_to?(:safety_assured)
safety_assured do
change_column :digests, :distance, :bigint, null: false, default: 0
end
else
change_column :digests, :distance, :bigint, null: false, default: 0
end
end
end

4
db/schema.rb generated
View file

@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[8.0].define(version: 2025_12_27_193242) do
ActiveRecord::Schema[8.0].define(version: 2025_12_27_000001) do
# These are extensions that must be enabled in order to support this database
enable_extension "pg_catalog.plpgsql"
enable_extension "postgis"
@ -84,7 +84,7 @@ ActiveRecord::Schema[8.0].define(version: 2025_12_27_193242) do
t.bigint "user_id", null: false
t.integer "year", null: false
t.integer "period_type", default: 0, null: false
t.bigint "distance", default: 0, null: false
t.integer "distance", default: 0, null: false
t.jsonb "toponyms", default: {}
t.jsonb "monthly_distances", default: {}
t.jsonb "time_spent_by_location", default: {}

View file

@ -28,18 +28,18 @@ FactoryBot.define do
monthly_distances do
{
'1' => 50_000,
'2' => 45_000,
'3' => 60_000,
'4' => 55_000,
'5' => 40_000,
'6' => 35_000,
'7' => 30_000,
'8' => 45_000,
'9' => 50_000,
'10' => 40_000,
'11' => 25_000,
'12' => 25_000
'1' => '50000',
'2' => '45000',
'3' => '60000',
'4' => '55000',
'5' => '40000',
'6' => '35000',
'7' => '30000',
'8' => '45000',
'9' => '50000',
'10' => '40000',
'11' => '25000',
'12' => '25000'
}
end
@ -78,7 +78,7 @@ FactoryBot.define do
{
'total_countries' => 10,
'total_cities' => 45,
'total_distance' => 2_500_000
'total_distance' => '2500000'
}
end

View file

@ -71,9 +71,9 @@ RSpec.describe Users::Digests::CalculateYear do
end
it 'builds monthly distances' do
expect(calculate_digest.monthly_distances['1']).to eq(50_000)
expect(calculate_digest.monthly_distances['2']).to eq(75_000)
expect(calculate_digest.monthly_distances['3']).to eq(0) # Missing month
expect(calculate_digest.monthly_distances['1']).to eq('50000')
expect(calculate_digest.monthly_distances['2']).to eq('75000')
expect(calculate_digest.monthly_distances['3']).to eq('0') # Missing month
end
it 'calculates time spent by location' do
@ -86,7 +86,7 @@ RSpec.describe Users::Digests::CalculateYear do
end
it 'calculates all time stats' do
expect(calculate_digest.all_time_stats['total_distance']).to eq(125_000)
expect(calculate_digest.all_time_stats['total_distance']).to eq('125000')
end
context 'when digest already exists' do