bible270 1.8.3 → 1.8.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: be8007d9a8bdb9c797652387e0a4e8751e5fed2aa29d088d98287ca7d2b7e77a
4
- data.tar.gz: d71275e3b9097162a126c3129e635a09ad5ee8bd43a899e349c619cd9e633473
3
+ metadata.gz: 37c1e22aede65482ba3d194eb1d2e74efde387475c1f264c30496e6330d3666c
4
+ data.tar.gz: 298306a3422ce83b4f68b2a8e8acaa16b956c30475a7d9d36afd88a76f086450
5
5
  SHA512:
6
- metadata.gz: 59e2a645945d342632584219ac34231c458ccbe504b925009835144e4aa2b49c7fc9b6c61a169366c9a78e087d8e94648dea50a4a8c44906ca1ab77c3d40b08f
7
- data.tar.gz: 7e4947ed4bebe9581261d18e2851ca3afab2661f94ab682f1759d5ce5f301d7b0353de97df88303b17ff2a5788a9ddf4484247018082abf814e86602501677da
6
+ metadata.gz: 471fff64f3f002999a00c5785bdf975aa5c5ed4723c9c107e7e738161f4b4740b7f73c29067f0aa22a5bdb3d0c5cf818b5e3ebcb27b9b89898a7e1a1340b0abf
7
+ data.tar.gz: b68eddc3274715999dde7df1df9928f4b0899e45323f18b91ba9e7d17781c81ad02df129ac52fcb09427fce8e8466d87f3b51be211c37fbbf30ad4fef8f15b15
data/CHANGELOG.md CHANGED
@@ -7,6 +7,9 @@ All notable changes to bible270. Format follows [Keep a Changelog](https://keepa
7
7
  ### Changed
8
8
 
9
9
  - keep Proverbs 7 whole and divide Proverbs 10 and 16 into four readings
10
+ - show likes and replies on My Progress and reader pages, with admin edit links on reader pages
11
+ - show each reader's pace beside their completed-day count for admins on Community
12
+ - add edit, like, and reply controls to reflections on Admin reader pages
10
13
 
11
14
  **[Full Changelog](https://github.com/avonderluft/bible270/compare/v1.8.1...main)**
12
15
 
@@ -97,7 +97,7 @@ module Bible270
97
97
  @comment_notifications_available = comment_notifications_available_for?(@reader)
98
98
  @completion_dove_preference_available = completion_dove_available_for(@reader)
99
99
  @days_completed = @reader.days_completed
100
- @comments = @reader.comments.order(created_at: :desc).limit(50)
100
+ @comments = @reader.comments.includes(likes: :reader).order(created_at: :desc).limit(50)
101
101
  end
102
102
 
103
103
  # ---- reflections ------------------------------------------------------
@@ -17,7 +17,7 @@ module Bible270
17
17
  def progress
18
18
  @reader = current_reader
19
19
  # Defaults keep the open visitor page simple and make every view input explicit.
20
- @recent_comments = @reader ? @reader.comments.recent.limit(5) : Comment.none
20
+ @recent_comments = @reader ? recent_reflections(@reader, limit: 5) : []
21
21
  @partial_day_tasks = []
22
22
  @remaining_partial_days = 0
23
23
  return unless @reader
@@ -34,7 +34,7 @@ module Bible270
34
34
  redirect_to(community_path, alert: 'Reader not found.') and return unless @reader
35
35
 
36
36
  @days_completed = @reader.days_completed
37
- @recent_comments = @reader.comments.recent.limit(20)
37
+ @recent_comments = recent_reflections(@reader, limit: 20)
38
38
  end
39
39
 
40
40
  def mention_suggestions
@@ -43,5 +43,16 @@ module Bible270
43
43
  response.headers['Cache-Control'] = 'private, no-store'
44
44
  render json: { suggestions: Reader.mention_suggestions(params[:q], except: current_reader) }
45
45
  end
46
+
47
+ private
48
+
49
+ def recent_reflections(reader, limit:)
50
+ comments = reader.comments.recent
51
+ .includes(:reader, { likes: :reader }, { replies: [:reader, { likes: :reader }] })
52
+ .limit(limit).to_a
53
+ ids = comments.map(&:id)
54
+ # A reader's own replies already appear beneath any listed parent reflection.
55
+ comments.reject { |comment| ids.include?(comment.parent_id) }
56
+ end
46
57
  end
47
58
  end
@@ -150,7 +150,14 @@ module Bible270
150
150
  def edited? = updated_at - created_at > 1
151
151
 
152
152
  # Visible replies, oldest first: a conversation reads forwards.
153
- def visible_replies = replies.approved.order(created_at: :asc)
153
+ def visible_replies
154
+ if replies.loaded?
155
+ replies.select(&:approved?).sort_by { |reply| [reply.created_at, reply.id] }
156
+ else
157
+ replies.approved.order(created_at: :asc, id: :asc)
158
+ end
159
+ end
160
+
154
161
  def moderated? = moderated_at.present?
155
162
 
156
163
  private
@@ -643,6 +643,17 @@ module Bible270
643
643
  Plan.day_for(Bible270.today, effective_start_date)
644
644
  end
645
645
 
646
+ def progress_status(completed_days: days_completed)
647
+ today = calendar_day
648
+ return 'undated' unless today
649
+
650
+ difference = completed_days - today
651
+ return 'on track' if difference.zero?
652
+
653
+ amount = difference.abs
654
+ "#{amount} #{amount == 1 ? 'day' : 'days'} #{difference.positive? ? 'ahead' : 'behind'}"
655
+ end
656
+
646
657
  # Raw, unclamped — lets callers distinguish "not started yet" / "finished".
647
658
  # The plan day that today actually is, or nil when today falls outside the
648
659
  # plan's window. calendar_day clamps, so before the start date it reports day
@@ -90,8 +90,9 @@
90
90
  <% else %>
91
91
  <%= reader.provider %>
92
92
  <% end %>
93
- · <%= @days_completed[reader.id] %>/<%= Bible270::Plan::DAYS %> days
94
93
  <% if reader.dated? %>· started <%= reader.effective_start_date.strftime('%b %-d, %Y') %><% end %>
94
+ · <%= @days_completed[reader.id] %>/<%= Bible270::Plan::DAYS %> days
95
+ · <%= @reader_report.status_for(reader) %>
95
96
  </div>
96
97
  <div class="sub b270-reader-activity">
97
98
  <% if (activity = @recent_reader_activities[reader.id]) %>
@@ -115,7 +115,8 @@
115
115
 
116
116
 
117
117
  <div class="b270-panel">
118
- <%= render "bible270/shared/reflections", comments: @comments, moderate: true %>
118
+ <%= render "bible270/shared/interaction_status" %>
119
+ <%= render "bible270/shared/reflections", comments: @comments, moderate: true, editable: true, actions: true %>
119
120
  </div>
120
121
 
121
122
  <div class="b270-panel">
@@ -172,3 +173,4 @@
172
173
  </div>
173
174
 
174
175
  <p style="margin-top:18px"><%= link_to '← All readers', admin_path %></p>
176
+ <%= render "bible270/shared/interaction_ui" %>
@@ -14,6 +14,7 @@
14
14
  joined <%= Bible270.local_time(r.created_at).strftime("%b %-d %Y") %><% if @show_admin_progress %>
15
15
  · <%= link_to "#{@days_completed[r.id]} of #{Bible270::Plan::DAYS} days complete",
16
16
  admin_reader_path(r), class: "b270-admin-progress" %>
17
+ · <%= r.progress_status(completed_days: @days_completed[r.id].to_i) %>
17
18
  <% end %>
18
19
  </div>
19
20
  </div>
@@ -12,8 +12,10 @@
12
12
 
13
13
  <% if @reader %>
14
14
  <div class="b270-panel">
15
+ <%= render "bible270/shared/interaction_status" %>
15
16
  <%= render "bible270/shared/reflections", comments: @recent_comments,
16
- title: "Your recent reflections", editable: true,
17
+ title: "Your recent reflections", editable: true, conversations: true,
17
18
  empty_text: "You have not written any reflections yet." %>
18
19
  </div>
20
+ <%= render "bible270/shared/interaction_ui" %>
19
21
  <% end %>
@@ -16,8 +16,11 @@
16
16
  </div>
17
17
 
18
18
  <div class="b270-panel">
19
+ <%= render "bible270/shared/interaction_status" %>
19
20
  <%= render "bible270/shared/reflections", comments: @recent_comments,
20
- title: "Their reflections", empty_text: "No reflections yet." %>
21
+ title: "Their reflections", empty_text: "No reflections yet.",
22
+ conversations: true, editable: Bible270.config.admin?(current_reader) %>
21
23
  </div>
22
24
 
23
25
  <%= render "bible270/shared/day_index", reader: @reader, expanded: true %>
26
+ <%= render "bible270/shared/interaction_ui" %>
@@ -1,4 +1,4 @@
1
- <%# locals: (comments:, title: "Their reflections", moderate: false, editable: false, empty_text: "None yet.") %>
1
+ <%# locals: (comments:, title: "Their reflections", moderate: false, editable: false, actions: false, conversations: false, reply: false, empty_text: "None yet.") %>
2
2
  <%#
3
3
  A reader's reflections. Three views showed near-identical markup: the admin
4
4
  page, a reader's public page, and the progress page, differing only in whether
@@ -11,17 +11,21 @@
11
11
  No ERB tags in this comment: the first close-tag would end it and the rest
12
12
  would become live template code.
13
13
  %>
14
- <h2 class="b270-subhead"><%= title %></h2>
14
+ <% if title.present? %><h2 class="b270-subhead"><%= title %></h2><% end %>
15
15
 
16
16
  <% if comments.any? %>
17
17
  <% comments.each do |comment| %>
18
- <div class="b270-comment">
18
+ <div class="b270-comment <%= 'b270-reply' if reply %>" id="comment-<%= comment.id %>">
19
+ <% if reply %><%= b270_avatar(comment.reader, size: 36) %><% end %>
19
20
  <div style="flex:1">
20
21
  <div class="b270-cmeta">
22
+ <% if reply %>
23
+ <strong><%= link_to comment.reader.display_name, reader_path(comment.reader) %></strong> ·
24
+ <% end %>
21
25
  <%= link_to "Day #{comment.day}", day_path(comment.day) %>
22
26
  · <%= b270_date(comment.created_at) %>
23
27
  <% if moderate && comment.hidden? %><span class="b270-badge">Hidden</span><% end %>
24
- <% if editable && b270_can_edit?(comment) %>
28
+ <% if editable && !comment.hidden? && b270_can_edit?(comment) %>
25
29
  <%= link_to "edit", day_path(comment.day, edit: comment.id, anchor: "comment-#{comment.id}"),
26
30
  class: "b270-cedit" %>
27
31
  <% end %>
@@ -29,6 +33,27 @@
29
33
 
30
34
  <div class="b270-cbody"><%= b270_comment_body(comment) %></div>
31
35
 
36
+ <% if (actions || conversations) && !comment.hidden? %>
37
+ <div class="b270-cactions">
38
+ <%= render "bible270/likes/likes", comment: comment %>
39
+ <% if !comment.reply? && signed_in? && comment.reader_id != current_reader.id %>
40
+ <%= link_to "Reply", day_path(comment.day, reply_to: comment.id, anchor: "new_comment_form"),
41
+ class: "b270-linkbtn" %>
42
+ <% end %>
43
+ </div>
44
+ <% end %>
45
+ <% if conversations %>
46
+ <% unless comment.reply? %>
47
+ <div class="b270-replies" id="replies-<%= comment.id %>">
48
+ <% replies = comment.visible_replies %>
49
+ <% if replies.any? %>
50
+ <%= render "bible270/shared/reflections", comments: replies, title: nil,
51
+ conversations: true, reply: true, editable: editable %>
52
+ <% end %>
53
+ </div>
54
+ <% end %>
55
+ <% end %>
56
+
32
57
  <% if moderate %>
33
58
  <div style="display:flex;gap:10px;margin-top:6px">
34
59
  <% if comment.hidden? %>
@@ -239,6 +239,7 @@
239
239
  .b270-mention{color:var(--teal);font-weight:600;text-decoration:none}
240
240
  .b270-mention:hover{text-decoration:underline}
241
241
  .b270-cactions{display:flex;align-items:center;gap:12px;margin-top:6px;flex-wrap:wrap}
242
+ .b270-cactions .b270-linkbtn{margin:0}
242
243
  .b270-likes{display:inline-flex;align-items:center;gap:3px;position:relative}
243
244
  .b270-heart{font-size:13px;line-height:1;cursor:default}
244
245
  /* The single heart is also the toggle for signed-in readers. It stays red
@@ -28,12 +28,16 @@ module Bible270
28
28
  Row.new(
29
29
  name: reader.display_name,
30
30
  days_read: days_read,
31
- status: status(reader, days_read),
31
+ status: reader.progress_status(completed_days: days_read),
32
32
  last_activity: last_activity_date(reader)
33
33
  )
34
34
  end
35
35
  end
36
36
 
37
+ def status_for(reader)
38
+ reader.progress_status(completed_days: completed_days.fetch(reader.id, 0))
39
+ end
40
+
37
41
  def empty? = rows.empty?
38
42
 
39
43
  def to_table
@@ -79,16 +83,5 @@ module Bible270
79
83
  occurred_at = recent_activities[reader.id]&.occurred_at
80
84
  occurred_at ? Bible270.local_time(occurred_at).strftime('%b %-d, %Y') : '—'
81
85
  end
82
-
83
- def status(reader, days_read)
84
- calendar_day = reader.calendar_day
85
- return 'undated' unless calendar_day
86
-
87
- difference = days_read - calendar_day
88
- return 'on track' if difference.zero?
89
-
90
- amount = difference.abs
91
- "#{amount} #{amount == 1 ? 'day' : 'days'} #{difference.positive? ? 'ahead' : 'behind'}"
92
- end
93
86
  end
94
87
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bible270
4
- VERSION = '1.8.3'
4
+ VERSION = '1.8.5'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bible270
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.8.3
4
+ version: 1.8.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew vonderLuft