Files
growstuff/app/services/timeline_service.rb
T
Brenda Wallace 8e0825b1b0 Add job finished event handling and descriptions
- Implemented event description logic for finished jobs in EventHelper.
- Created a new partial for finished job descriptions.
- Updated TimelineService to include finished jobs in event queries.
- Enhanced specs for event descriptions and timeline service to cover finished jobs.
2026-10-24 17:48:57 +13:00

143 lines
4.0 KiB
Ruby

# frozen_string_literal: true
class TimelineService
def self.member_query(member)
query.where(owner_id: member.id)
end
# A timeline of events by people the member follows
def self.followed_query(member)
query.where(owner_id: [member.followed.pluck(:id)])
end
# What the timeline is made of, and the query for each kind of event.
EVENT_QUERIES = {
planting: :plantings_query,
harvest: :harvests_query,
post: :posts_query,
comment: :comments_query,
photo: :photos_query,
seed: :seeds_query,
planned_job: :planned_jobs_query,
job_finished: :jobs_finished_query,
like: :likes_query,
garden_layout: :garden_layouts_query,
transplant: :transplants_query,
planting_finished: :plantings_finished_query,
seed_finished: :seeds_finished_query
}.freeze
DEFAULT_EVENTS = %i(planting harvest post comment photo seed planned_job job_finished like).freeze
# Events of the given kinds, newest first. Garden layouts are only here when
# asked for, since the timeline page has nothing to say about them; the same goes
# for transplants, and finished plantings and seeds.
def self.query(kinds = DEFAULT_EVENTS)
kinds.map { |kind| public_send(EVENT_QUERIES.fetch(kind)) }
.reduce { |all, one| all.union_all(one) }
.where.not(event_at: nil)
.order(event_at: :desc)
end
def self.garden_layouts_query
Garden.where.not(layout_saved_at: nil)
.select(:id, "'garden_layout' as event_type", 'gardens.layout_saved_at as event_at', :owner_id, 'null as crop_id')
end
def self.plantings_finished_query
Planting.where(failed: [false, nil]).where(finished_at: ..Time.zone.today)
.select(:id, "'planting_finished' as event_type", 'finished_at as event_at', :owner_id, :crop_id)
end
def self.seeds_finished_query
Seed.where(finished_at: ..Time.zone.today)
.select(:id, "'seed_finished' as event_type", 'seeds.finished_at as event_at', :owner_id, :crop_id)
end
def self.transplants_query
PlantingHistory.joins(:planting)
.select('planting_histories.id', "'transplant' as event_type", 'planting_histories.ended_on as event_at',
'plantings.owner_id', 'plantings.crop_id')
end
def self.likes_query
Like
.select("likes.id",
"'like' as event_type",
"likes.created_at as event_at",
"likes.member_id as owner_id",
"null as crop_id")
end
# Jobs as the day they were crossed off.
def self.jobs_finished_query
Job.where(finished: true).where.not(finished_at: nil)
.select(:id, "'job_finished' as event_type", 'jobs.finished_at as event_at', :owner_id, 'null as crop_id')
end
# Jobs as the day they were planned rather than the day they are due,
# for a feed of what people have done.
def self.planned_jobs_query
Job.select(:id, "'job' as event_type", 'jobs.created_at as event_at', :owner_id, 'null as crop_id')
end
def self.plantings_query
Planting.select(
:id,
"'planting' as event_type",
'planted_at as event_at',
:owner_id,
:crop_id
)
end
def self.harvests_query
Harvest.select(
:id,
"'harvest' as event_type",
'harvested_at as event_at',
:owner_id,
:crop_id
)
end
def self.seeds_query
Seed.select(
:id,
"'seed' as event_type",
"seeds.created_at as event_at",
:owner_id,
:crop_id
)
end
def self.posts_query
Post.select(
:id,
"'post' as event_type",
'posts.created_at as event_at',
'author_id as owner_id',
'null as crop_id'
)
end
def self.comments_query
Comment.select(
:id,
"'comment' as event_type",
'comments.created_at as event_at',
'author_id as owner_id',
'null as crop_id'
)
end
def self.photos_query
Photo.select(
:id,
"'photo' as event_type",
"photos.created_at as event_at",
:owner_id,
'null as crop_id'
)
end
end