bible270 0.17.0 → 0.17.1
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 +4 -4
- data/app/controllers/bible270/comments_controller.rb +3 -1
- data/app/controllers/bible270/likes_controller.rb +22 -0
- data/app/helpers/bible270/plan_helper.rb +12 -0
- data/app/models/bible270/comment.rb +35 -2
- data/app/models/bible270/like.rb +14 -0
- data/app/models/bible270/reader.rb +1 -0
- data/app/views/bible270/admin/comments.html.erb +1 -1
- data/app/views/bible270/admin/index.html.erb +1 -1
- data/app/views/bible270/comments/_comment.html.erb +11 -8
- data/app/views/bible270/comments/index.html.erb +1 -1
- data/app/views/bible270/likes/_likes.html.erb +27 -0
- data/app/views/bible270/likes/toggle.turbo_stream.erb +3 -0
- data/app/views/bible270/notice_mailer/new_reader.html.erb +1 -1
- data/app/views/bible270/notice_mailer/new_reader.text.erb +1 -1
- data/app/views/bible270/readers/index.html.erb +1 -1
- data/app/views/bible270/shared/_header.html.erb +2 -2
- data/app/views/bible270/shared/_reflections.html.erb +1 -1
- data/app/views/bible270/shared/_styles.html.erb +11 -0
- data/config/routes.rb +1 -0
- data/db/migrate/20260101000013_create_bible270_likes.rb +21 -0
- data/lib/bible270/version.rb +1 -1
- data/lib/bible270.rb +18 -4
- metadata +6 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 70091a35da0211de345d0a946f8fe25aea94c7656d7f9fb7b305aa63c6a1b7e6
|
|
4
|
+
data.tar.gz: 98e6db18fb16bdb784b7b2ad095b05860a43a81cb3111279f33b7285345bcbd0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e03f11e9596c52e59413478a3c5c615ce5bc9f4289ecbed3a037906d51d70e515d56767d18324ba331dded40de502d0d6b7c741c603836d7e351d147375187df
|
|
7
|
+
data.tar.gz: f2496c1342b3be1625927fdbbecd333c1792d96c8c52742359bdfc9cb66e9de7ac0f3617b20b291ee081811e4d937a92e3dbbecc9c5ee29a3c3d0788db9f473a
|
|
@@ -92,7 +92,9 @@ module Bible270
|
|
|
92
92
|
end
|
|
93
93
|
|
|
94
94
|
ids = roots.sort_by { |_root, at| -at.to_i }.first(wanted).map(&:first)
|
|
95
|
-
threads = Comment.approved.where(id: ids)
|
|
95
|
+
threads = Comment.approved.where(id: ids)
|
|
96
|
+
.includes(:reader, { likes: :reader }, { replies: [:reader, { likes: :reader }] })
|
|
97
|
+
.index_by(&:id)
|
|
96
98
|
ids.filter_map { |id| threads[id] }
|
|
97
99
|
end
|
|
98
100
|
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Bible270
|
|
4
|
+
# A heart on someone's reflection. One route, because liking and unliking are
|
|
5
|
+
# the same gesture — tapping the heart again takes it back.
|
|
6
|
+
class LikesController < ApplicationController
|
|
7
|
+
def toggle
|
|
8
|
+
return unless require_reader!
|
|
9
|
+
|
|
10
|
+
@comment = Comment.approved.find_by(id: params[:id])
|
|
11
|
+
head :not_found and return unless @comment
|
|
12
|
+
|
|
13
|
+
@comment.toggle_like!(current_reader)
|
|
14
|
+
@comment.reload
|
|
15
|
+
|
|
16
|
+
respond_to do |format|
|
|
17
|
+
format.turbo_stream
|
|
18
|
+
format.html { redirect_to day_path(@comment.day, anchor: "comment-#{@comment.id}") }
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -137,6 +137,18 @@ module Bible270
|
|
|
137
137
|
end
|
|
138
138
|
end
|
|
139
139
|
|
|
140
|
+
# Timestamps in the plan's zone rather than UTC. Dates — started_on and the
|
|
141
|
+
# like — need no conversion and are formatted inline.
|
|
142
|
+
def b270_date(time)
|
|
143
|
+
local = Bible270.local_time(time)
|
|
144
|
+
local&.strftime('%b %-d, %Y')
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def b270_datetime(time)
|
|
148
|
+
local = Bible270.local_time(time)
|
|
149
|
+
local&.strftime('%b %-d, %Y at %-I:%M %p')
|
|
150
|
+
end
|
|
151
|
+
|
|
140
152
|
# Only the writer may change their own words. An admin can remove a reflection
|
|
141
153
|
# but not rewrite it: putting words in someone's mouth is worse than taking
|
|
142
154
|
# them away, and taking them away is already the moderator's job.
|
|
@@ -3,6 +3,15 @@
|
|
|
3
3
|
module Bible270
|
|
4
4
|
# A publicly visible reflection attached to a plan day (optionally a track).
|
|
5
5
|
class Comment < ApplicationRecord
|
|
6
|
+
# One heart for both states. An unliked one is the same emoji shown grey by
|
|
7
|
+
# CSS, so it cannot drift in size from a real like, and hovering it previews
|
|
8
|
+
# exactly what clicking will produce.
|
|
9
|
+
#
|
|
10
|
+
# The white heart this replaced was legible on white but nearly invisible on
|
|
11
|
+
# the paper background; an outline glyph like U+2661 is drawn by the font
|
|
12
|
+
# rather than the emoji set and needs hand-tuning to match.
|
|
13
|
+
HEART = '❤️'
|
|
14
|
+
|
|
6
15
|
self.table_name = 'bible270_comments'
|
|
7
16
|
|
|
8
17
|
belongs_to :reader, class_name: 'Bible270::Reader'
|
|
@@ -12,6 +21,7 @@ module Bible270
|
|
|
12
21
|
belongs_to :parent, class_name: 'Bible270::Comment', optional: true
|
|
13
22
|
has_many :replies, class_name: 'Bible270::Comment', foreign_key: :parent_id,
|
|
14
23
|
dependent: :destroy, inverse_of: :parent
|
|
24
|
+
has_many :likes, class_name: 'Bible270::Like', dependent: :destroy, inverse_of: :comment
|
|
15
25
|
|
|
16
26
|
validates :day, inclusion: { in: 1..Plan::DAYS }
|
|
17
27
|
validates :body, presence: true, length: { maximum: 4000 }
|
|
@@ -37,7 +47,9 @@ module Bible270
|
|
|
37
47
|
# Only the reflections themselves: replies are rendered under their parent, so
|
|
38
48
|
# listing them again at the top level would show each twice.
|
|
39
49
|
scope :for_day, ->(d) { approved.where(day: d, parent_id: nil).order(created_at: :asc) }
|
|
40
|
-
scope :threads_for_day, ->(d) {
|
|
50
|
+
scope :threads_for_day, ->(d) {
|
|
51
|
+
for_day(d).includes(:reader, { likes: :reader }, { replies: [:reader, { likes: :reader }] })
|
|
52
|
+
}
|
|
41
53
|
scope :recent, -> { approved.order(created_at: :desc) }
|
|
42
54
|
|
|
43
55
|
# Every reflection is visible when written; these are the moderation actions.
|
|
@@ -46,9 +58,30 @@ module Bible270
|
|
|
46
58
|
def hidden? = !approved
|
|
47
59
|
def reply? = parent_id.present?
|
|
48
60
|
|
|
61
|
+
def liked_by?(reader)
|
|
62
|
+
return false if reader.nil?
|
|
63
|
+
|
|
64
|
+
likes.any? { |like| like.reader_id == reader.id }
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Toggling returns the new state, so a caller can say what happened without
|
|
68
|
+
# asking again.
|
|
69
|
+
def toggle_like!(reader)
|
|
70
|
+
existing = likes.find { |like| like.reader_id == reader.id }
|
|
71
|
+
if existing
|
|
72
|
+
existing.destroy
|
|
73
|
+
likes.reload
|
|
74
|
+
false
|
|
75
|
+
else
|
|
76
|
+
likes.create(reader: reader)
|
|
77
|
+
likes.reload
|
|
78
|
+
true
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
49
82
|
# A second's grace: created_at and updated_at differ by microseconds on
|
|
50
83
|
# insert, which would mark every reflection as edited.
|
|
51
|
-
def edited?
|
|
84
|
+
def edited? = updated_at - created_at > 1
|
|
52
85
|
|
|
53
86
|
# Visible replies, oldest first: a conversation reads forwards.
|
|
54
87
|
def visible_replies = replies.approved.order(created_at: :asc)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Bible270
|
|
4
|
+
# A reader's heart on a reflection. There is nothing to a like but who gave it
|
|
5
|
+
# and when — the count is the number of rows, and the hover text is the name.
|
|
6
|
+
class Like < ApplicationRecord
|
|
7
|
+
self.table_name = 'bible270_likes'
|
|
8
|
+
|
|
9
|
+
belongs_to :reader, class_name: 'Bible270::Reader'
|
|
10
|
+
belongs_to :comment, class_name: 'Bible270::Comment'
|
|
11
|
+
|
|
12
|
+
validates :reader_id, uniqueness: { scope: :comment_id }
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -8,6 +8,7 @@ module Bible270
|
|
|
8
8
|
|
|
9
9
|
has_many :checkoffs, class_name: 'Bible270::Checkoff', dependent: :destroy
|
|
10
10
|
has_many :comments, class_name: 'Bible270::Comment', dependent: :destroy
|
|
11
|
+
has_many :likes, class_name: 'Bible270::Like', dependent: :destroy, inverse_of: :reader
|
|
11
12
|
belongs_to :owner, polymorphic: true, optional: true
|
|
12
13
|
|
|
13
14
|
# Active Storage is optional: an app may have it disabled, and the engine has
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
<div class="b270-cmeta">
|
|
19
19
|
<strong><%= comment.reader.display_name %></strong>
|
|
20
20
|
· <%= link_to "day #{comment.day}", day_path(comment.day) %>
|
|
21
|
-
· <%= comment.created_at
|
|
21
|
+
· <%= b270_date(comment.created_at) %>
|
|
22
22
|
<% if comment.reply? %>· reply to <strong><%= comment.parent&.reader&.display_name || 'a deleted reflection' %></strong><% end %>
|
|
23
23
|
<% if comment.hidden? %><span class="b270-badge">Hidden</span><% end %>
|
|
24
24
|
</div>
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
<% if @enrollment_closed %>
|
|
10
10
|
<% if @enrollment_closed_at %>
|
|
11
11
|
<p class="b270-startline">Enrollment closed
|
|
12
|
-
on <%= @enrollment_closed_at
|
|
12
|
+
on <%= b270_date(@enrollment_closed_at) %><% end %>.
|
|
13
13
|
The <%= @readers.size %> reader<%= 's' unless @readers.size == 1 %> already taking part can
|
|
14
14
|
still sign in and carry on.</p>
|
|
15
15
|
<%= button_to 'Open to new readers', admin_enrollment_path, method: :patch,
|
|
@@ -11,9 +11,9 @@
|
|
|
11
11
|
<div style="flex:1">
|
|
12
12
|
<div class="b270-cmeta">
|
|
13
13
|
<strong><%= link_to comment.reader.display_name, reader_path(comment.reader), style: "text-decoration:none" %></strong>
|
|
14
|
-
· <%= comment.created_at
|
|
14
|
+
· <%= b270_date(comment.created_at) %>
|
|
15
15
|
<% if comment.track.present? %>· <%= b270_track(comment.track)[:label] %><% end %>
|
|
16
|
-
<% if comment.edited? %>· <span class="b270-edited" title="<%= comment.updated_at
|
|
16
|
+
<% if comment.edited? %>· <span class="b270-edited" title="<%= b270_datetime(comment.updated_at) %>">edited</span><% end %>
|
|
17
17
|
<% if b270_can_edit?(comment) %>
|
|
18
18
|
<%= link_to "edit", day_path(comment.day, edit: comment.id, anchor: "comment-#{comment.id}"),
|
|
19
19
|
class: "b270-cedit" %>
|
|
@@ -37,13 +37,16 @@
|
|
|
37
37
|
|
|
38
38
|
<%# Only a top-level reflection can be replied to: one level deep, so a reply
|
|
39
39
|
offers no Reply of its own. %>
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
40
|
+
<div class="b270-cactions">
|
|
41
|
+
<%= render partial: "bible270/likes/likes", locals: { comment: comment } %>
|
|
42
|
+
<%# A reply may be liked but not replied to: one level deep. %>
|
|
43
|
+
<% if !reply && signed_in? && comment.reader_id != current_reader.id %>
|
|
44
|
+
<%= link_to "Reply", day_path(comment.day, reply_to: comment.id, anchor: "new_comment_form"),
|
|
45
|
+
class: "b270-linkbtn" %>
|
|
46
46
|
<% end %>
|
|
47
|
+
</div>
|
|
48
|
+
|
|
49
|
+
<% unless reply %>
|
|
47
50
|
|
|
48
51
|
<div class="b270-replies" id="replies-<%= comment.id %>">
|
|
49
52
|
<%= render partial: "bible270/comments/comment",
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<%# locals: (comment:) %>
|
|
2
|
+
<%#
|
|
3
|
+
One heart per like, each carrying its giver's name — so a row of hearts is both
|
|
4
|
+
the count and, on hover, the list of who.
|
|
5
|
+
|
|
6
|
+
Your own like is not drawn in the row: the button is your heart, filled, and
|
|
7
|
+
saying so. Drawing both gave a reader two hearts for one like.
|
|
8
|
+
%>
|
|
9
|
+
<%
|
|
10
|
+
liked = signed_in? && comment.liked_by?(current_reader)
|
|
11
|
+
others = signed_in? ? comment.likes.reject { |like| like.reader_id == current_reader.id } : comment.likes
|
|
12
|
+
%>
|
|
13
|
+
<span class="b270-likes" id="likes-<%= comment.id %>">
|
|
14
|
+
<% others.each do |like| %><span class="b270-heart"
|
|
15
|
+
title="<%= like.reader.display_name %>"><%= Bible270::Comment::HEART %></span><% end %>
|
|
16
|
+
|
|
17
|
+
<% if signed_in? %>
|
|
18
|
+
<%= button_to like_comment_path(comment), method: :post, class: "b270-likebtn#{' liked' if liked}",
|
|
19
|
+
form: { style: "display:inline", data: { turbo_stream: true } },
|
|
20
|
+
aria: { label: liked ? "Take back your like" : "Like this reflection" },
|
|
21
|
+
title: liked ? "You liked this — tap to take it back" : "Like this reflection" do %>
|
|
22
|
+
<%= Bible270::Comment::HEART %>
|
|
23
|
+
<% end %>
|
|
24
|
+
<% elsif comment.likes.any? %>
|
|
25
|
+
<span class="b270-likecount"><%= comment.likes.size %></span>
|
|
26
|
+
<% end %>
|
|
27
|
+
</span>
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
<tr><td style="padding:3px 12px 3px 0;color:#6d6558">Name</td><td><%= @reader.display_name %></td></tr>
|
|
12
12
|
<tr><td style="padding:3px 12px 3px 0;color:#6d6558">Email</td><td><%= @reader.email.presence || '(none given)' %></td></tr>
|
|
13
13
|
<tr><td style="padding:3px 12px 3px 0;color:#6d6558">Signed in with</td><td><%= @reader.provider.presence || 'the host application' %></td></tr>
|
|
14
|
-
<tr><td style="padding:3px 12px 3px 0;color:#6d6558">Joined</td><td><%= @reader.created_at.strftime('%B %-d, %Y at %-I:%M %p') %></td></tr>
|
|
14
|
+
<tr><td style="padding:3px 12px 3px 0;color:#6d6558">Joined</td><td><%= Bible270.local_time(@reader.created_at).strftime('%B %-d, %Y at %-I:%M %p') %></td></tr>
|
|
15
15
|
</table>
|
|
16
16
|
|
|
17
17
|
<p style="margin:18px 0 0;font-size:14px;color:#6d6558">
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Name: <%= @reader.display_name %>
|
|
4
4
|
Email: <%= @reader.email.presence || '(none given)' %>
|
|
5
5
|
Signed in with: <%= @reader.provider.presence || 'the host application' %>
|
|
6
|
-
Joined: <%= @reader.created_at.strftime('%B %-d, %Y at %-I:%M %p') %>
|
|
6
|
+
Joined: <%= Bible270.local_time(@reader.created_at).strftime('%B %-d, %Y at %-I:%M %p') %>
|
|
7
7
|
|
|
8
8
|
That makes <%= @total %> reader<%= 's' unless @total == 1 %> taking part.
|
|
9
9
|
<% if @admin_url %>
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
<%= b270_avatar(r, size: 40) %>
|
|
12
12
|
<div>
|
|
13
13
|
<div class="name"><%= link_to r.display_name, reader_path(r), style: "text-decoration:none" %></div>
|
|
14
|
-
<div class="sub"><%= @days_completed[r.id] %> of <%= Bible270::Plan::DAYS %> days · joined <%= r.created_at.strftime("%b %Y") %></div>
|
|
14
|
+
<div class="sub"><%= @days_completed[r.id] %> of <%= Bible270::Plan::DAYS %> days · joined <%= Bible270.local_time(r.created_at).strftime("%b %Y") %></div>
|
|
15
15
|
</div>
|
|
16
16
|
<div class="stat">
|
|
17
17
|
<span class="big"><%= (@days_completed[r.id].to_f / Bible270::Plan::DAYS * 100).round %>%</span>
|
|
@@ -12,11 +12,11 @@
|
|
|
12
12
|
<!--<%= link_to "Plan", root_path %>-->
|
|
13
13
|
<%= link_to "People", community_path %>
|
|
14
14
|
<%# Public, like the community page: anyone may read reflections. %>
|
|
15
|
-
<%= link_to "
|
|
15
|
+
<%= link_to "Posts", reflections_path %>
|
|
16
16
|
<% if signed_in? %>
|
|
17
|
-
<% if Bible270.config.admin?(current_reader) %><%= link_to "Admin", admin_path %><% end %>
|
|
18
17
|
<%= link_to "Progress", progress_path %>
|
|
19
18
|
<%= link_to "Profile", profile_path %>
|
|
19
|
+
<% if Bible270.config.admin?(current_reader) %><%= link_to "Admin", admin_path %><% end %>
|
|
20
20
|
<%= button_to "Sign out", sign_out_path, method: :delete, class: "b270-linkbtn",
|
|
21
21
|
form: { style: "display:inline" } %>
|
|
22
22
|
<% elsif Bible270.config.any_sign_in_method? %>
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
<div style="flex:1">
|
|
20
20
|
<div class="b270-cmeta">
|
|
21
21
|
<%= link_to "Day #{comment.day}", day_path(comment.day) %>
|
|
22
|
-
· <%= comment.created_at
|
|
22
|
+
· <%= b270_date(comment.created_at) %>
|
|
23
23
|
<% if moderate && comment.hidden? %><span class="b270-badge">Hidden</span><% end %>
|
|
24
24
|
</div>
|
|
25
25
|
|
|
@@ -161,6 +161,17 @@
|
|
|
161
161
|
.b270-replying strong{color:var(--ink)}
|
|
162
162
|
.b270-mention{color:var(--teal);font-weight:600;text-decoration:none}
|
|
163
163
|
.b270-mention:hover{text-decoration:underline}
|
|
164
|
+
.b270-cactions{display:flex;align-items:center;gap:12px;margin-top:6px;flex-wrap:wrap}
|
|
165
|
+
.b270-likes{display:inline-flex;align-items:center;gap:2px}
|
|
166
|
+
.b270-heart{font-size:13px;line-height:1;cursor:default}
|
|
167
|
+
/* Same size as a heart in the row: the button is one of the hearts, not a
|
|
168
|
+
control sitting beside them. Unliked, it is the same emoji desaturated —
|
|
169
|
+
visible against the paper, and hovering shows what clicking will give. */
|
|
170
|
+
.b270-likebtn{background:none;border:0;padding:0 2px;font-size:13px;line-height:1;cursor:pointer;
|
|
171
|
+
filter:grayscale(1);opacity:.5;transition:filter .12s,opacity .12s}
|
|
172
|
+
.b270-likebtn:hover{filter:none;opacity:1}
|
|
173
|
+
.b270-likebtn.liked{filter:none;opacity:1}
|
|
174
|
+
.b270-likecount{font-size:11.5px;color:var(--faint);margin-left:2px}
|
|
164
175
|
.b270-creply{margin-top:6px}
|
|
165
176
|
.b270-cbody{margin:3px 0 0;white-space:pre-wrap}
|
|
166
177
|
.b270-editform{margin-top:6px}
|
data/config/routes.rb
CHANGED
|
@@ -12,6 +12,7 @@ Bible270::Engine.routes.draw do
|
|
|
12
12
|
constraints: { day: %r{\d+} }
|
|
13
13
|
post 'day/:day/comments', to: 'comments#create', as: :day_comments,
|
|
14
14
|
constraints: { day: %r{\d+} }
|
|
15
|
+
post 'comments/:id/like', to: 'likes#toggle', as: :like_comment
|
|
15
16
|
patch 'comments/:id', to: 'comments#update'
|
|
16
17
|
delete 'comments/:id', to: 'comments#destroy', as: :comment
|
|
17
18
|
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class CreateBible270Likes < ActiveRecord::Migration[7.0]
|
|
4
|
+
def change
|
|
5
|
+
create_table :bible270_likes do |t|
|
|
6
|
+
t.references :reader, null: false, index: false,
|
|
7
|
+
foreign_key: { to_table: :bible270_readers }
|
|
8
|
+
t.references :comment, null: false, index: false,
|
|
9
|
+
foreign_key: { to_table: :bible270_comments }
|
|
10
|
+
t.timestamps
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# One like per reader per reflection, enforced by the database as well as the
|
|
14
|
+
# model: a double-tap should not become two hearts.
|
|
15
|
+
add_index :bible270_likes, %i[reader_id comment_id], unique: true,
|
|
16
|
+
name: 'idx_b270_likes_unique'
|
|
17
|
+
# Reading a thread asks for a comment's likes, so that is the index that earns
|
|
18
|
+
# its keep.
|
|
19
|
+
add_index :bible270_likes, :comment_id, name: 'idx_b270_likes_comment'
|
|
20
|
+
end
|
|
21
|
+
end
|
data/lib/bible270/version.rb
CHANGED
data/lib/bible270.rb
CHANGED
|
@@ -22,10 +22,24 @@ module_function
|
|
|
22
22
|
# it; Date.today follows the machine. A self-hosted reading plan wants the
|
|
23
23
|
# latter, so that is the default, with config.time_zone to override.
|
|
24
24
|
def today
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
local_time(Time.now).to_date
|
|
26
|
+
end
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
# A stored timestamp in the plan's own zone.
|
|
29
|
+
#
|
|
30
|
+
# created_at and friends come back in Rails' Time.zone, which is UTC unless the
|
|
31
|
+
# host app sets it — so a reflection written at 5pm in Los Angeles was being
|
|
32
|
+
# shown as the next day. This is the same rule Bible270.today follows: the
|
|
33
|
+
# machine's zone, or config.time_zone when one is given.
|
|
34
|
+
def local_time(time)
|
|
35
|
+
return nil if time.nil?
|
|
36
|
+
|
|
37
|
+
zone = config.time_zone
|
|
38
|
+
if zone.to_s.empty?
|
|
39
|
+
time.getlocal
|
|
40
|
+
else
|
|
41
|
+
found = Time.respond_to?(:find_zone) ? Time.find_zone(zone) : nil
|
|
42
|
+
found ? time.in_time_zone(found) : time.getlocal
|
|
43
|
+
end
|
|
30
44
|
end
|
|
31
45
|
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: 0.17.
|
|
4
|
+
version: 0.17.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Andrew vonderLuft
|
|
@@ -85,6 +85,7 @@ files:
|
|
|
85
85
|
- app/controllers/bible270/checkoffs_controller.rb
|
|
86
86
|
- app/controllers/bible270/comments_controller.rb
|
|
87
87
|
- app/controllers/bible270/days_controller.rb
|
|
88
|
+
- app/controllers/bible270/likes_controller.rb
|
|
88
89
|
- app/controllers/bible270/profiles_controller.rb
|
|
89
90
|
- app/controllers/bible270/readers_controller.rb
|
|
90
91
|
- app/controllers/bible270/sessions_controller.rb
|
|
@@ -95,6 +96,7 @@ files:
|
|
|
95
96
|
- app/models/bible270/application_record.rb
|
|
96
97
|
- app/models/bible270/checkoff.rb
|
|
97
98
|
- app/models/bible270/comment.rb
|
|
99
|
+
- app/models/bible270/like.rb
|
|
98
100
|
- app/models/bible270/reader.rb
|
|
99
101
|
- app/models/bible270/setting.rb
|
|
100
102
|
- app/models/bible270/sign_in_token.rb
|
|
@@ -115,6 +117,8 @@ files:
|
|
|
115
117
|
- app/views/bible270/days/_start_date.html.erb
|
|
116
118
|
- app/views/bible270/days/index.html.erb
|
|
117
119
|
- app/views/bible270/days/show.html.erb
|
|
120
|
+
- app/views/bible270/likes/_likes.html.erb
|
|
121
|
+
- app/views/bible270/likes/toggle.turbo_stream.erb
|
|
118
122
|
- app/views/bible270/notice_mailer/mentioned.html.erb
|
|
119
123
|
- app/views/bible270/notice_mailer/mentioned.text.erb
|
|
120
124
|
- app/views/bible270/notice_mailer/new_reader.html.erb
|
|
@@ -148,6 +152,7 @@ files:
|
|
|
148
152
|
- db/migrate/20260101000010_add_remember_token_to_bible270_readers.rb
|
|
149
153
|
- db/migrate/20260101000011_add_mention_notices_to_bible270_readers.rb
|
|
150
154
|
- db/migrate/20260101000012_add_parent_to_bible270_comments.rb
|
|
155
|
+
- db/migrate/20260101000013_create_bible270_likes.rb
|
|
151
156
|
- lib/bible270.rb
|
|
152
157
|
- lib/bible270/avatars.rb
|
|
153
158
|
- lib/bible270/configuration.rb
|