mirror of
https://github.com/Growstuff/growstuff.git
synced 2026-11-03 03:34:26 -05:00
Merge pull request #5010 from Growstuff/feat/timeline-jobs
add finished jobs to the timeline
This commit is contained in:
6 files changed
+55
-9
No files matched your search
@@ -28,7 +28,12 @@ module NeighboursHelper
|
||||
day == today - 1 ? t('neighbours.day.yesterday', date:) : date
|
||||
end
|
||||
|
||||
GROUP_ORDER = %w(planting seed seed_trade harvest transplant planted_out planting_finished seed_finished job garden_layout).freeze
|
||||
# Planned and finished jobs, which have a name of their own and no page.
|
||||
JOB_TYPES = %w(job job_finished).freeze
|
||||
NAMED_TYPES = (JOB_TYPES + %w(garden_layout)).freeze
|
||||
|
||||
GROUP_ORDER = %w(planting seed seed_trade harvest transplant planted_out planting_finished seed_finished
|
||||
job_finished job garden_layout).freeze
|
||||
|
||||
# The icon that goes with each kind of thing someone did.
|
||||
def group_icon(kind)
|
||||
@@ -37,7 +42,7 @@ module NeighboursHelper
|
||||
when 'seed', 'seed_trade' then seed_icon
|
||||
when 'harvest' then harvest_icon
|
||||
when 'transplant', 'planted_out' then growing_icon
|
||||
when 'planting_finished', 'seed_finished' then finished_icon
|
||||
when 'planting_finished', 'seed_finished', 'job_finished' then finished_icon
|
||||
when 'job' then icon('fas', 'calendar-days')
|
||||
when 'garden_layout' then garden_icon
|
||||
when 'photo' then photo_icon
|
||||
@@ -156,7 +161,7 @@ module NeighboursHelper
|
||||
|
||||
# Jobs have no page of their own, so they link to their owner's list.
|
||||
def thing_path(item)
|
||||
item.type == 'job' ? member_jobs_path(item.record.owner) : polymorphic_path(thing_record(item))
|
||||
JOB_TYPES.include?(item.type) ? member_jobs_path(item.record.owner) : polymorphic_path(thing_record(item))
|
||||
end
|
||||
|
||||
def thing_record(item)
|
||||
@@ -165,7 +170,7 @@ module NeighboursHelper
|
||||
|
||||
def thing_name(item)
|
||||
record = thing_record(item)
|
||||
%w(job garden_layout).include?(item.type) ? record.name : record.crop.name
|
||||
NAMED_TYPES.include?(item.type) ? record.name : record.crop.name
|
||||
end
|
||||
|
||||
def thing_details(item)
|
||||
|
||||
@@ -17,12 +17,12 @@ class Neighbours
|
||||
NEARBY_LIMIT = 100
|
||||
SUGGESTIONS_SHOWN = 4
|
||||
POSTS_SHOWN = 5
|
||||
FEED_KINDS = %i(planting harvest seed photo garden_layout transplant planned_job planting_finished seed_finished).freeze
|
||||
FEED_KINDS = %i(planting harvest seed photo garden_layout transplant planned_job job_finished planting_finished seed_finished).freeze
|
||||
FEED_EVENTS = 15
|
||||
MAX_OFFSET = 500
|
||||
PHOTO_SUBJECTS = %w(Planting Harvest Seed Garden).freeze
|
||||
EVENT_MODELS = { 'planting' => Planting, 'harvest' => Harvest, 'seed' => Seed, 'photo' => Photo, 'garden_layout' => Garden,
|
||||
'transplant' => PlantingHistory, 'job' => Job, 'planting_finished' => Planting,
|
||||
'transplant' => PlantingHistory, 'job' => Job, 'job_finished' => Job, 'planting_finished' => Planting,
|
||||
'seed_finished' => Seed }.freeze
|
||||
FEED_CACHE_FOR = 5.minutes
|
||||
|
||||
|
||||
@@ -18,8 +18,9 @@ class TimelineService
|
||||
comment: :comments_query,
|
||||
photo: :photos_query,
|
||||
seed: :seeds_query,
|
||||
job: :jobs_query,
|
||||
planned_job: :planned_jobs_query,
|
||||
job: :jobs_query,
|
||||
planned_job: :planned_jobs_query,
|
||||
job_finished: :jobs_finished_query,
|
||||
like: :likes_query,
|
||||
garden_layout: :garden_layouts_query,
|
||||
transplant: :transplants_query,
|
||||
@@ -30,7 +31,7 @@ class TimelineService
|
||||
|
||||
# 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, planned jobs and finished plantings and seeds.
|
||||
# for transplants, planned and finished jobs, 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) }
|
||||
@@ -68,6 +69,12 @@ class TimelineService
|
||||
"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
|
||||
|
||||
@@ -445,6 +445,9 @@ en:
|
||||
empty: Nothing to show yet.
|
||||
title: Latest from your friends and neighbours
|
||||
group:
|
||||
job_finished_html:
|
||||
one: Finished a job, %{things}
|
||||
other: Finished %{count} jobs, %{things}
|
||||
job_html:
|
||||
one: Planned a job, %{things}
|
||||
other: Planned %{count} jobs, %{things}
|
||||
|
||||
@@ -123,6 +123,15 @@ describe 'My friends and neighbours' do
|
||||
expect(page).to have_css('article', text: /friendly.*Planned a job, Weed the beans \(for #{due}\)/m)
|
||||
end
|
||||
|
||||
it 'shows a friend finishing a job' do
|
||||
friend = create(:member, login_name: 'friendly')
|
||||
member.follows.create!(followed: friend)
|
||||
create(:job, owner: friend, name: 'Net the berries', finished: true)
|
||||
|
||||
visit neighbours_path
|
||||
expect(page).to have_css('article', text: /friendly.*Finished a job, Net the berries/m)
|
||||
end
|
||||
|
||||
it 'shows only their own job under Me' do
|
||||
friend = create(:member, login_name: 'friendly')
|
||||
member.follows.create!(followed: friend)
|
||||
|
||||
@@ -229,6 +229,28 @@ describe Neighbours do
|
||||
expect(items.map { |item| [item.type, item.record] }).to include(['job', job])
|
||||
end
|
||||
|
||||
it 'has jobs people finished' do
|
||||
job = create(:job, owner: friend, finished: true)
|
||||
|
||||
items = neighbours.feed.flat_map(&:updates).flat_map(&:items)
|
||||
expect(items.map { |item| [item.type, item.record] }).to include(['job_finished', job])
|
||||
end
|
||||
|
||||
it 'leaves out a job that is not finished as a finished job' do
|
||||
create(:job, owner: friend, finished: false)
|
||||
|
||||
items = neighbours.feed.flat_map(&:updates).flat_map(&:items)
|
||||
expect(items.map(&:type)).not_to include('job_finished')
|
||||
end
|
||||
|
||||
it 'dates a finished job by when it was crossed off, not when it was due' do
|
||||
job = create(:job, owner: friend, due_date: Time.zone.today - 1.month, finished: true)
|
||||
job.update_column(:finished_at, Time.zone.now) # rubocop:disable Rails/SkipsModelValidations
|
||||
|
||||
days = neighbours.feed.select { |day| day.updates.flat_map(&:items).any? { |item| item.type == 'job_finished' } }
|
||||
expect(days.first.day).to eq Time.zone.today
|
||||
end
|
||||
|
||||
it 'dates a job by when it was planned, not when it is due' do
|
||||
create(:job, owner: friend, due_date: Time.zone.today + 1.month)
|
||||
|
||||
|
||||
Reference in new issue
Block a user