bible270 1.1.2 → 1.1.4

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: 5c5bfb6b7074375f7d7d3bbd69b10c9da92adf410f2a031fe1dea4dbb39f1eb2
4
- data.tar.gz: 89f755b1b9d853198b58ba8118a58f6c8780dc9321ea56e2c6216993419bbc6b
3
+ metadata.gz: a1d5f984616aed86326fe24bdb808b539bbd6cc8fe28e61f58838e6fba6573ca
4
+ data.tar.gz: 661d698c8eaacee191eb27eda7fa75bc83cf0df94ef5dfc85ae18974a26ead0d
5
5
  SHA512:
6
- metadata.gz: 3c28bd93672a533afa90873e5d7dc20e2fadd908338c2a29c86f093c19b68869dfae6b99032bdc1f514a03720bd64348c30bb21c80b81ae8d4244d750bdbcf31
7
- data.tar.gz: a1cb8d911339bbbef9aebcca715a42cad25035e82c424e044aa0fed9ca2c6d3db5cac6ec7a490cb576eea4895c235c302150c60c60d16582a2e3bb756757191d
6
+ metadata.gz: 60ccdd3d39fadb44e75c0eef05e18bc304032636e440f6d8d9b3b0a941b6c1a2a73bdc5231ae353de27d8b5aa8923f028e4dbd16d259ea9079bce20bf6b7bd9b
7
+ data.tar.gz: 0c41c6c130e93d42bc1d45dd1757c2f2216a378bf77cf5118dce25f28e72fceeb813f5064bb5ec93397afc077091f1a649b068b69f0616c964cfb2f700ab5cce
data/CHANGELOG.md CHANGED
@@ -4,27 +4,60 @@ All notable changes to bible270. Format follows [Keep a Changelog](https://keepa
4
4
 
5
5
  ## Unreleased Changes
6
6
 
7
- ### Removed
7
+ **[Full Changelog](https://github.com/avonderluft/bible270/compare/v1.1.3...main)**
8
8
 
9
- - remove the Compact reading preference so daily reading pages have one simple, predictable presentation
10
- - replace the homepage reader preview with one clear link to the Community page
11
- - remove the redundant schedule-restart shortcut from progress recovery choices
12
- - remove reader-facing start-date status, controls, and self-service endpoints while retaining automatic and admin-managed personal calendars
13
- - remove weekly progress, its unused schedule helper, milestones, and explanatory schedule-recovery copy from My Progress
14
- - replace the Reflections page’s separate day grid with the standard “View all 270 days” control
9
+ ## [1.1.3] - 2026-08-23
10
+
11
+ ### Changed
12
+
13
+ - align Profile reminder choices with the recommended 15-minute scheduler interval while preserving existing off-quarter preferences
14
+ - document concrete host cron and Docker Compose setup, output logging, verification, and one-scheduler-per-database guidance
15
+
16
+ **[Full Changelog](https://github.com/avonderluft/bible270/compare/v1.1.2...v1.1.3)**
17
+
18
+ ## [1.1.2] - 2026-08-22
19
+
20
+ ### Changed
21
+
22
+ - include complete 1.1.0 and 1.1.1 release history in the packaged changelog
23
+
24
+ ### Fixed
25
+
26
+ - make the mobile navigation menu toggle reliably on iOS Safari with an explicit accessible button, synchronized `aria-expanded` state, and controlled menu visibility
27
+
28
+ **[Full Changelog](https://github.com/avonderluft/bible270/compare/v1.1.1...v1.1.2)**
29
+
30
+ ## [1.1.1] - 2026-08-22
31
+
32
+ ### Changed
33
+
34
+ - replace the first custom mobile-menu handler with native `details` disclosure behavior
35
+
36
+ **[Full Changelog](https://github.com/avonderluft/bible270/compare/v1.1.0...v1.1.1)**
37
+
38
+ ## [1.1.0] - 2026-08-22
15
39
 
16
40
  ### Changed
17
41
 
18
42
  - notify reflection authors directly about replies, share one opt-out with explicit mentions, and stop inserting handles into reply text
19
43
  - consolidate duplicate visitor sign-in prompts on day pages into one invitation
20
44
  - show “Finish what you started” on My Progress only when partially read days need attention
21
- - clarify the global day-index control as “View all 270 days” and use that standard collapsed control on My Progress
45
+ - clarify the global day-index control as “View all 270 days” and use that standard collapsed control on My Progress and public reader pages
46
+ - redirect successful Profile updates back to Profile
47
+ - simplify Community listings to linked reader names and avatars with full joined dates instead of progress counts
48
+ - remove account-specific reflection messaging from the signed-out Progress page
49
+ - simplify header, Reflections, and empty day-page framing while retaining the primary actions and information
22
50
 
23
- ### Fixed
51
+ ### Removed
24
52
 
25
- - make the mobile navigation menu reliably open and close when its button is tapped
53
+ - remove the Compact reading preference so daily reading pages have one simple, predictable presentation
54
+ - replace the homepage reader preview with one clear link to the Community page
55
+ - remove the redundant schedule-restart shortcut from progress recovery choices
56
+ - remove reader-facing start-date status, controls, and self-service endpoints while retaining automatic and admin-managed personal calendars
57
+ - remove weekly progress, its unused schedule helper, milestones, and explanatory schedule-recovery copy from My Progress
58
+ - replace the Reflections page’s separate day grid with the standard “View all 270 days” control
26
59
 
27
- **[Full Changelog](https://github.com/avonderluft/bible270/compare/v1.0.0...main)**
60
+ **[Full Changelog](https://github.com/avonderluft/bible270/compare/v1.0.0...v1.1.0)**
28
61
 
29
62
  ## [1.0.0] - 2026-08-20
30
63
 
@@ -488,6 +521,10 @@ This is the initial public release.
488
521
 
489
522
  * Email sign-in requires working Action Mailer delivery in the host application. Set `config.mailer_from`; delivery is inline by default, or set `email_sign_in_deliver_later` when a queue backend is available.
490
523
 
524
+ [1.1.3]: https://github.com/avonderluft/bible270/releases/tag/v1.1.3
525
+ [1.1.2]: https://github.com/avonderluft/bible270/releases/tag/v1.1.2
526
+ [1.1.1]: https://github.com/avonderluft/bible270/releases/tag/v1.1.1
527
+ [1.1.0]: https://github.com/avonderluft/bible270/releases/tag/v1.1.0
491
528
  [1.0.0]: https://github.com/avonderluft/bible270/releases/tag/v1.0.0
492
529
  [0.19.0]: https://github.com/avonderluft/bible270/releases/tag/v0.19.0
493
530
  [0.18.2]: https://github.com/avonderluft/bible270/releases/tag/v0.18.2
data/README.md CHANGED
@@ -318,7 +318,7 @@ config.allow_reader_start_date = true # allow personal per-reader calendars
318
318
  | a date | false | Everyone is pinned to the community date; stored individual dates are ignored |
319
319
  | nil | false | Fully undated — no calendar anywhere |
320
320
 
321
- Dated plans show each day's date with a **Today** badge and a "Go to today" link. Administrators may re-map an individual reader's calendar from the admin panel; check-offs and reflections remain keyed to day numbers, so nothing in their history moves.
321
+ Dated plans show each day's date with a **Today** badge and a "Go to today" link. `config.start_date` is the deploy-time default; an administrator may override the current run's shared date from the Admin panel without a deploy, or reset it to the configured value. The shared-date change immediately re-maps calendar dates, **Today**, and reminders for readers following the shared calendar. Administrators may also re-map an individual reader's calendar. Check-offs and reflections remain keyed to day numbers, so nothing in their history moves.
322
322
 
323
323
  Date helpers are pure functions, usable anywhere:
324
324
 
@@ -334,7 +334,9 @@ Bible270::Plan.before_start?(date, start)
334
334
 
335
335
  Daily reminders are optional at both levels: the host enables the feature, then each reader chooses
336
336
  whether to receive it and at what local time from their profile. The feature and reader opt-in both
337
- default to off; each reader's time defaults to `08:00`.
337
+ default to off; each reader's time defaults to `08:00`. Profile times use quarter-hour choices so they
338
+ match the recommended 15-minute scheduler interval. An existing off-quarter preference remains
339
+ available until that reader chooses a new time.
338
340
 
339
341
  ```ruby
340
342
  # config/initializers/bible270.rb
@@ -354,9 +356,27 @@ recurring-job system:
354
356
  bin/rails bible270:reminders:send
355
357
  ```
356
358
 
357
- Each run converts `Time.now` through `Bible270.local_time`, waits until each reader's chosen `HH:MM`
358
- time, sends inline with `deliver_now`, and prints the number delivered. Set `config.time_zone` when the
359
- plan should not follow the server's local clock. Running periodically is safe because delivery is
359
+ For a host cron job, open the crontab with `crontab -e` under the same account that runs the application
360
+ and add a line like this, using the absolute application path:
361
+
362
+ ```cron
363
+ */15 * * * * cd /absolute/path/to/application && RAILS_ENV=production bin/rails bible270:reminders:send >> /absolute/path/to/application/log/bible270-reminders.log 2>&1
364
+ ```
365
+
366
+ For Docker Compose, run `pwd` in the directory containing the Compose file and `command -v docker` to
367
+ find the two absolute paths, then use the same host account that can run Docker:
368
+
369
+ ```cron
370
+ */15 * * * * cd /absolute/path/to/application && /usr/bin/docker compose exec -T rails bin/rails bible270:reminders:send >> /absolute/path/to/application/log/bible270-reminders.log 2>&1
371
+ ```
372
+
373
+ The `-T` is required because cron has no interactive terminal. Confirm the saved entry with `crontab -l`
374
+ and check `log/bible270-reminders.log` after the next interval. Run one scheduler per database; several
375
+ web containers sharing a database must not each run the task.
376
+
377
+ Each run converts `Time.now` through `Bible270.local_time`, waits until the first scheduler run at or
378
+ after each reader's chosen time, sends inline with `deliver_now`, and prints the number delivered. Set
379
+ `config.time_zone` when the plan should not follow the server's local clock. Running periodically is
360
380
  idempotent once per local date: readers already marked for that date are skipped. Undated readers,
361
381
  calendar dates before or after their plan, completed days, blank email addresses, and readers who have
362
382
  not opted in are also skipped. A failure for one reader is logged and does not stop the rest. The sent
data/Rakefile CHANGED
@@ -160,7 +160,7 @@ namespace :test do
160
160
  Rake::Task['test:serial'].enhance(['test:prepare_serial'])
161
161
 
162
162
  task :parallel do
163
- workers = ENV.fetch('PARALLEL_WORKERS', '2')
163
+ workers = ENV.fetch('PARALLEL_WORKERS', '6')
164
164
  FileUtils.rm_rf('coverage')
165
165
  env = {
166
166
  'PARALLEL_COVERAGE' => 'true',
@@ -28,10 +28,40 @@ module Bible270
28
28
  end
29
29
  end
30
30
 
31
+ def update_run_start
32
+ if Setting.set_run_start_date!(params[:start_date])
33
+ date = Setting.run_start_date
34
+ redirect_to admin_path, notice: "Current run start date changed to #{date.strftime('%B %-d, %Y')}."
35
+ else
36
+ redirect_to admin_path, alert: 'Choose a valid start date.'
37
+ end
38
+ end
39
+
40
+ def reset_run_start
41
+ Setting.clear_run_start_date!
42
+ date = Setting.run_start_date
43
+ notice = if date
44
+ "Current run now uses the configured start date, #{date.strftime('%B %-d, %Y')}."
45
+ else
46
+ 'Current run now uses the configured undated schedule.'
47
+ end
48
+ redirect_to admin_path, notice: notice
49
+ end
50
+
31
51
  def index
32
52
  @enrollment_closed = Setting.enrollment_closed?
33
53
  @enrollment_closed_at = Setting.enrollment_closed_at
34
54
  @readers = Reader.all.to_a.sort_by(&:sort_name)
55
+ @run_start_date = Setting.run_start_date
56
+ @configured_start_date = Bible270.config.start_date
57
+ @run_start_date_overridden = Setting.run_start_date_overridden?
58
+ if Bible270.config.allow_reader_start_date
59
+ @shared_calendar_readers = @readers.count { |reader| reader.started_on.nil? }
60
+ @personal_calendar_readers = @readers.size - @shared_calendar_readers
61
+ else
62
+ @shared_calendar_readers = @readers.size
63
+ @personal_calendar_readers = 0
64
+ end
35
65
  counts = Checkoff.group(:reader_id, :day).count
36
66
  @days_completed = Hash.new(0)
37
67
  counts.each { |(rid, day), n| @days_completed[rid] += 1 if n >= Plan.total_parts(day) }
@@ -8,7 +8,7 @@ module Bible270
8
8
  @start_day = current_reader&.current_day || 1
9
9
  # nil outside the plan's window, so no "Go to today" before it begins
10
10
  @today_day = current_reader&.today_day
11
- @community_start_date = Bible270.config.start_date
11
+ @community_start_date = Setting.run_start_date
12
12
  end
13
13
 
14
14
  def show
@@ -90,7 +90,7 @@ module Bible270
90
90
 
91
91
  # Every reflection is visible when written; these are the moderation actions.
92
92
  def hide! = update!(approved: false, moderated_at: Time.current)
93
- def unhide! = update!(approved: true, moderated_at: Time.current)
93
+ def unhide! = update!(approved: true, moderated_at: Time.current)
94
94
  def hidden? = !approved
95
95
  def reply? = parent_id.present?
96
96
 
@@ -28,6 +28,7 @@ module Bible270
28
28
  PASSAGE_SOURCES = %w[bible_gateway blue_letter_bible].freeze
29
29
  DEFAULT_PASSAGE_SOURCE = 'bible_gateway'
30
30
  DAILY_REMINDER_TIME_FORMAT = %r{\A(?:[01]\d|2[0-3]):[0-5]\d\z}
31
+ DAILY_REMINDER_MINUTES = %w[00 15 30 45].freeze
31
32
  DAILY_REMINDER_COLUMNS = %w[daily_reminders daily_reminder_time last_daily_reminder_sent_on].freeze
32
33
  REFLECTIONS_SEEN_COLUMN = 'reflections_seen_at'
33
34
 
@@ -514,14 +515,13 @@ module Bible270
514
515
 
515
516
  # The start date that actually governs this reader. A reader's own
516
517
  # started_on wins when per-reader dates are allowed; otherwise (or if they
517
- # haven't got one) the community-wide config.start_date applies. Nil means
518
- # the plan is undated for this reader and no calendar mapping exists.
518
+ # haven't got one) the current run's shared date applies. Nil means the plan
519
+ # is undated for this reader and no calendar mapping exists.
519
520
  def effective_start_date
520
- config = Bible270.config
521
- if config.allow_reader_start_date && started_on
521
+ if Bible270.config.allow_reader_start_date && started_on
522
522
  started_on
523
523
  else
524
- config.start_date
524
+ Setting.run_start_date
525
525
  end
526
526
  end
527
527
 
@@ -606,10 +606,9 @@ module Bible270
606
606
  # Called when a reader first participates. Only stamps a personal start date
607
607
  # when per-reader dates are enabled and a shared date isn't already in force.
608
608
  def ensure_started!
609
- config = Bible270.config
610
- return unless config.allow_reader_start_date
609
+ return unless Bible270.config.allow_reader_start_date
611
610
  return if started_on.present?
612
- return if config.start_date.present?
611
+ return if Setting.run_start_date.present?
613
612
 
614
613
  update!(started_on: Bible270.today)
615
614
  end
@@ -1,12 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bible270
4
- # Runtime state an admin can change without a deploy. Currently just whether
5
- # this run of the plan is open to new readers.
4
+ # Runtime state an admin can change without a deploy: enrollment and the
5
+ # current run's shared calendar date.
6
6
  class Setting < ApplicationRecord
7
7
  self.table_name = 'bible270_settings'
8
8
 
9
9
  ENROLLMENT_CLOSED_AT = 'enrollment_closed_at'
10
+ RUN_START_DATE = 'run_start_date'
10
11
 
11
12
  validates :key, presence: true, uniqueness: true
12
13
 
@@ -25,6 +26,35 @@ module Bible270
25
26
  where(key: key.to_s).delete_all
26
27
  end
27
28
 
29
+ # ---- current run ------------------------------------------------------
30
+
31
+ def self.run_start_date
32
+ run_start_date_override || Bible270.config.start_date
33
+ end
34
+
35
+ def self.run_start_date_override
36
+ Plan.to_date(read(RUN_START_DATE))
37
+ rescue ActiveRecord::StatementInvalid
38
+ nil
39
+ end
40
+
41
+ def self.run_start_date_overridden?
42
+ run_start_date_override.present?
43
+ end
44
+
45
+ def self.set_run_start_date!(value)
46
+ date = Plan.to_date(value)
47
+ return false if date.nil?
48
+
49
+ write(RUN_START_DATE, date.iso8601)
50
+ true
51
+ end
52
+
53
+ def self.clear_run_start_date!
54
+ delete_key(RUN_START_DATE)
55
+ true
56
+ end
57
+
28
58
  # ---- enrolment --------------------------------------------------------
29
59
 
30
60
  # Closed either because an admin closed it, or because the app was configured
@@ -7,11 +7,11 @@
7
7
  <div class="b270-panel">
8
8
  <h2 class="b270-subhead">This run of the plan is <%= @enrollment_closed ? 'closed' : 'open' %> to new readers.</h2>
9
9
  <% if @enrollment_closed %>
10
- <% if @enrollment_closed_at %>
11
- <p class="b270-startline">Enrollment closed
12
- on <%= b270_date(@enrollment_closed_at) %><% end %>.
10
+ <p class="b270-startline">
11
+ <% if @enrollment_closed_at %>Enrollment closed on <%= b270_date(@enrollment_closed_at) %>.<% end %>
13
12
  The <%= @readers.size %> reader<%= 's' unless @readers.size == 1 %> already taking part can
14
- still sign in and carry on.</p>
13
+ still sign in and carry on.
14
+ </p>
15
15
  <%= button_to 'Open to new readers', admin_enrollment_path, method: :patch,
16
16
  params: { state: 'open' }, class: 'b270-btn' %>
17
17
  <% else %>
@@ -22,11 +22,52 @@
22
22
  <% end %>
23
23
  </div>
24
24
 
25
+ <div class="b270-panel">
26
+ <h2 class="b270-subhead">Current run start date</h2>
27
+ <% if @run_start_date %>
28
+ <p class="b270-startline">
29
+ This run <%= @run_start_date > Bible270.today ? 'starts' : 'started' %>
30
+ <strong><%= @run_start_date.strftime('%B %-d, %Y') %></strong> and ends
31
+ <strong><%= Bible270::Plan.end_date_for(@run_start_date).strftime('%B %-d, %Y') %></strong>.
32
+ <% if @run_start_date_overridden %><span class="b270-badge">Admin override</span><% end %>
33
+ </p>
34
+ <% else %>
35
+ <p class="b270-startline">This run is undated.</p>
36
+ <% end %>
37
+
38
+ <%= form_with url: admin_run_start_path, method: :patch, class: "b270-startform",
39
+ data: { turbo_confirm: "Change the current run start date? Calendar dates, Today, and reminders will be re-mapped. Check-offs and reflections will not change." } do %>
40
+ <label class="b270-field">
41
+ <span>Start date</span>
42
+ <%= date_field_tag :start_date, @run_start_date, required: true %>
43
+ </label>
44
+ <%= submit_tag(@run_start_date ? 'Change start date' : 'Set start date', class: 'b270-btn') %>
45
+ <% end %>
46
+
47
+ <p class="b270-hint">
48
+ This affects <%= pluralize(@shared_calendar_readers, 'reader') %> following the shared calendar.
49
+ <% if @personal_calendar_readers.positive? %>
50
+ <%= pluralize(@personal_calendar_readers, 'reader') %> with a personal calendar will not move.
51
+ <% end %>
52
+ Check-offs and reflections remain attached to their existing day numbers.
53
+ </p>
54
+
55
+ <% if @run_start_date_overridden %>
56
+ <%= button_to 'Use configured date', admin_run_start_path, method: :delete, class: 'b270-linkbtn',
57
+ form: { data: { turbo_confirm: 'Remove the Admin override and use the configured start date?' } } %>
58
+ <p class="b270-hint">
59
+ Configured date:
60
+ <%= @configured_start_date ? @configured_start_date.strftime('%B %-d, %Y') : 'undated' %>.
61
+ </p>
62
+ <% end %>
63
+ </div>
64
+
25
65
  <% if @readers.any? %>
26
66
  <div class="b270-list">
27
67
  <% @readers.each do |reader| %>
28
68
  <div class="b270-li">
29
- <%= b270_avatar(reader, size: 72) %>
69
+ <%= link_to b270_avatar(reader, size: 72), admin_reader_path(reader),
70
+ "aria-label": reader.display_name %>
30
71
  <div>
31
72
  <div class="name"><%= link_to reader.display_name, admin_reader_path(reader), style: 'text-decoration:none' %>
32
73
  <% if Bible270.config.admin?(reader) %> <span class="sub"><strong>[admin]</strong></span> <% end %>
@@ -58,8 +99,7 @@
58
99
  <%= @reachable == 1 ? 'reader' : 'readers' %> individually, not as one message with
59
100
  everyone in bcc — so each is greeted by name.
60
101
  <% if @last_broadcast_at.present? %>
61
- <br>Last sent <%= b270_datetime(@last_broadcast_at) %><%
62
- %><% if @last_broadcast_subject.present? %>: <em><%= @last_broadcast_subject %></em><% end %>.
102
+ <br>Last sent <%= b270_datetime(@last_broadcast_at) %><% if @last_broadcast_subject.present? %>: <em><%= @last_broadcast_subject %></em><% end %>.
63
103
  <% end %>
64
104
  </p>
65
105
 
@@ -3,6 +3,6 @@
3
3
  <h1><%= Bible270.config.app_name %> <em>— read God's whole story</em></h1>
4
4
  <p class="lede">Daily passages from the Old Testament, New Testament, and Psalms or Proverbs — portions sized to take about the same time to read. Check off what you read; your place is saved for you, and you can share reflections and encourage one another along the way.</p>
5
5
 
6
- <%= render "bible270/shared/progress" %>
6
+ <%= render "bible270/shared/progress", show_start_date: true %>
7
7
 
8
8
  <p style="margin:12px 0 0"><%= link_to "Meet your fellow readers →", community_path %></p>
@@ -50,6 +50,7 @@
50
50
 
51
51
  <% if @daily_reminders_available %>
52
52
  <% reminder_hour, reminder_minute = @daily_reminder_time.to_s.split(":", 2) %>
53
+ <% reminder_minutes = (Bible270::Reader::DAILY_REMINDER_MINUTES + [reminder_minute]).compact.uniq.sort %>
53
54
  <div class="b270-field">
54
55
  <span>Daily reading reminder</span>
55
56
  <div class="b270-reminder-row">
@@ -70,7 +71,7 @@
70
71
  class: "b270-time-select", required: true, aria: { label: "Hour" } %>
71
72
  <span class="b270-time-separator" aria-hidden="true">:</span>
72
73
  <%= select_tag :daily_reminder_minute,
73
- options_for_select((0..59).map { |minute| format("%02d", minute) }, reminder_minute),
74
+ options_for_select(reminder_minutes, reminder_minute),
74
75
  class: "b270-time-select", required: true, aria: { label: "Minute" } %>
75
76
  <span class="b270-reminder-tooltip" id="daily-reminder-time-hint" role="tooltip">
76
77
  Uses the plan's configured time zone. You can turn reminders off here at any time.
@@ -1,4 +1,4 @@
1
- <%# locals: (reader: nil, start_day: nil, today_day: nil, community_start_date: :unset) %>
1
+ <%# locals: (reader: nil, start_day: nil, today_day: nil, community_start_date: :unset, show_start_date: false) %>
2
2
  <%#
3
3
  The progress panel.
4
4
 
@@ -21,7 +21,8 @@
21
21
  panel_reader = reader || current_reader
22
22
  panel_start_day = start_day || panel_reader&.current_day || 1
23
23
  panel_today_day = today_day || panel_reader&.today_day
24
- panel_community_date = community_start_date == :unset ? Bible270.config.start_date : community_start_date
24
+ panel_community_date = community_start_date == :unset ? Bible270::Setting.run_start_date : community_start_date
25
+ panel_start_date = panel_reader&.effective_start_date if show_start_date
25
26
  day_verb = panel_start_day == 1 ? 'Start' : 'Continue'
26
27
  panel_behind = panel_today_day.present? && panel_start_day < panel_today_day
27
28
  %>
@@ -29,7 +30,11 @@
29
30
  <% if panel_reader %>
30
31
  <div class="b270-bignum">
31
32
  <span class="n"><%= panel_reader.days_completed %></span>
32
- <span class="of">of <%= Bible270::Plan::DAYS %> days complete</span>
33
+ <span class="of">
34
+ of <%= Bible270::Plan::DAYS %> days complete<% if panel_start_date %>
35
+ · plan <% if panel_start_date == Bible270.today %>starts today<% elsif panel_start_date > Bible270.today %>starts on <%= panel_start_date.strftime("%b %-d, %Y") %><% else %>started on <%= panel_start_date.strftime("%b %-d, %Y") %><% end %>
36
+ <% end %>
37
+ </span>
33
38
  <span class="pct"><%= panel_reader.completion_percent %>%</span>
34
39
  </div>
35
40
 
@@ -112,7 +112,7 @@
112
112
 
113
113
  .b270-startline{margin:0;font-size:13.5px;color:var(--muted)}
114
114
  .b270-startline strong{color:var(--ink)}
115
- .b270-startform{display:flex;align-items:center;gap:10px;margin-top:10px;flex-wrap:wrap}
115
+ .b270-startform{display:flex;align-items:flex-end;gap:10px;margin-top:10px;flex-wrap:wrap}
116
116
  .b270-startform input[type=date]{font:inherit;font-size:14px;padding:8px 10px;border:1px solid var(--line);border-radius:8px;background:#fff;color:var(--ink)}
117
117
  .b270-linkbtn{background:none;border:none;padding:0;margin-top:8px;font:inherit;font-size:12.5px;color:var(--oxblood);cursor:pointer;text-decoration:underline}
118
118
  .b270-hint{margin:8px 0 0;font-size:12px;color:var(--faint);max-width:111ch}
data/config/routes.rb CHANGED
@@ -29,6 +29,8 @@ Bible270::Engine.routes.draw do
29
29
 
30
30
  post 'admin/broadcast', to: 'admin#broadcast', as: :admin_broadcast
31
31
  patch 'admin/enrollment', to: 'admin#update_enrollment', as: :admin_enrollment
32
+ patch 'admin/run-start', to: 'admin#update_run_start', as: :admin_run_start
33
+ delete 'admin/run-start', to: 'admin#reset_run_start'
32
34
  get 'admin/comments', to: 'admin#comments', as: :admin_comments
33
35
  patch 'admin/comments/:id/hide', to: 'admin#hide_comment', as: :admin_hide_comment
34
36
  patch 'admin/comments/:id/unhide', to: 'admin#unhide_comment', as: :admin_unhide_comment
data/lib/bible270/plan.rb CHANGED
@@ -493,14 +493,14 @@ module Bible270
493
493
  pinned.merge(pinned_from_breaks(chapters))
494
494
  end
495
495
 
496
- def psalm_parts = memo(:psalm_parts) { pp_parts.first(psalm_chapters.size) }
496
+ def psalm_parts = memo(:psalm_parts) { pp_parts.first(psalm_chapters.size) }
497
497
  def proverbs_parts = memo(:proverbs_parts) { pp_parts.last(proverbs_chapters.size) }
498
498
 
499
- def psalm_readings = memo(:psalm_readings) { expand_readings(psalm_chapters, psalm_parts) }
499
+ def psalm_readings = memo(:psalm_readings) { expand_readings(psalm_chapters, psalm_parts) }
500
500
  def proverbs_readings = memo(:proverbs_readings) { expand_readings(proverbs_chapters, proverbs_parts) }
501
501
 
502
502
  # Readings grouped by chapter, so a divided chapter stays together.
503
- def psalm_groups = memo(:psalm_groups) { group_by_chapter(psalm_readings) }
503
+ def psalm_groups = memo(:psalm_groups) { group_by_chapter(psalm_readings) }
504
504
  def proverbs_groups = memo(:proverbs_groups) { group_by_chapter(proverbs_readings) }
505
505
 
506
506
  def group_by_chapter(readings)
@@ -530,7 +530,7 @@ module Bible270
530
530
  end
531
531
  end
532
532
 
533
- def pp_plan = memo(:pp_plan) { pp_readings.map { |seg| format_segment(seg) } }
533
+ def pp_plan = memo(:pp_plan) { pp_readings.map { |seg| format_segment(seg) } }
534
534
  def pp_verse_loads = memo(:pp_verse_loads) { pp_readings.map { |seg| segment_length(seg) } }
535
535
 
536
536
  # 1-indexed days carrying a Proverbs reading.
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bible270
4
- VERSION = '1.1.2'
4
+ VERSION = '1.1.4'
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.1.2
4
+ version: 1.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew vonderLuft