bible270 1.1.3 → 1.1.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: 45fdbb1df9bc7d830bbaf95bf41a49c0bb027faeb5a98da183b5baeda39c30fe
4
- data.tar.gz: 844cc4dfb784a197321910c5a606e092e57f0a0437890a8cbe1c4bcbe30c146a
3
+ metadata.gz: 1a655ad0a130cd6a4106374efb885fa76856b7f93c7fc05284062648a330125e
4
+ data.tar.gz: d23e6b7180c152f1b452e6eac5db9523f0e8cb7683ee50492fc8bbdc00d271cb
5
5
  SHA512:
6
- metadata.gz: b9c688571b688a9fd9cba621bd3bb816561751af80d59568ba7f54df5598bbd6543efbf28bac976c57deb1d390f7440aad08d9fc51ecc7e047563a85554cf266
7
- data.tar.gz: f5ffea7599e4526ea4f6184bafb0b7253a5c86ef24a0adf8781abccc410d8135b96781b3b079b856699272a02b6a6ce95c6f6a699fa3864e6ffd9331cc521fc6
6
+ metadata.gz: 791373f6597dde62c9a6ce8eaab3251868f4b19bbf24615fec46613ebab7e918e4f90e3eb8f318ed85502b1a769eb71c7290adb4973f17d3400eb411d2664202
7
+ data.tar.gz: 71b588c2a184a1939ee9c7c79dce661fcc017e2199ea732e334ebc2ba49412ec3bfcd029880e4cdffe64724c21d33a5e157c7f9dc886feda1d583f9b56e64db4
data/CHANGELOG.md CHANGED
@@ -4,7 +4,24 @@ All notable changes to bible270. Format follows [Keep a Changelog](https://keepa
4
4
 
5
5
  ## Unreleased Changes
6
6
 
7
- **[Full Changelog](https://github.com/avonderluft/bible270/compare/v1.1.2...main)**
7
+ ### Changed
8
+
9
+ - reuse one dedicated browser tab for Bible Gateway and Blue Letter Bible Scripture links instead of opening an unlimited series of tabs
10
+
11
+ ### Removed
12
+
13
+ - remove the unused `passage_url_builder` configuration hook; Bible Gateway and Blue Letter Bible are now the intentionally fixed passage providers
14
+
15
+ **[Full Changelog](https://github.com/avonderluft/bible270/compare/v1.1.3...main)**
16
+
17
+ ## [1.1.3] - 2026-08-23
18
+
19
+ ### Changed
20
+
21
+ - align Profile reminder choices with the recommended 15-minute scheduler interval while preserving existing off-quarter preferences
22
+ - document concrete host cron and Docker Compose setup, output logging, verification, and one-scheduler-per-database guidance
23
+
24
+ **[Full Changelog](https://github.com/avonderluft/bible270/compare/v1.1.2...v1.1.3)**
8
25
 
9
26
  ## [1.1.2] - 2026-08-22
10
27
 
@@ -12,13 +29,17 @@ All notable changes to bible270. Format follows [Keep a Changelog](https://keepa
12
29
 
13
30
  - include complete 1.1.0 and 1.1.1 release history in the packaged changelog
14
31
 
32
+ ### Fixed
33
+
34
+ - make the mobile navigation menu toggle reliably on iOS Safari with an explicit accessible button, synchronized `aria-expanded` state, and controlled menu visibility
35
+
15
36
  **[Full Changelog](https://github.com/avonderluft/bible270/compare/v1.1.1...v1.1.2)**
16
37
 
17
38
  ## [1.1.1] - 2026-08-22
18
39
 
19
- ### Fixed
40
+ ### Changed
20
41
 
21
- - make the mobile navigation menu toggle reliably on iOS Safari by relying on native `details` disclosure behavior instead of overriding it with JavaScript
42
+ - replace the first custom mobile-menu handler with native `details` disclosure behavior
22
43
 
23
44
  **[Full Changelog](https://github.com/avonderluft/bible270/compare/v1.1.0...v1.1.1)**
24
45
 
@@ -508,6 +529,7 @@ This is the initial public release.
508
529
 
509
530
  * 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.
510
531
 
532
+ [1.1.3]: https://github.com/avonderluft/bible270/releases/tag/v1.1.3
511
533
  [1.1.2]: https://github.com/avonderluft/bible270/releases/tag/v1.1.2
512
534
  [1.1.1]: https://github.com/avonderluft/bible270/releases/tag/v1.1.1
513
535
  [1.1.0]: https://github.com/avonderluft/bible270/releases/tag/v1.1.0
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
 
@@ -415,9 +415,6 @@ Bible270.configure do |config|
415
415
  config.after_sign_out_path = nil
416
416
 
417
417
  config.bible_version = "NKJV"
418
- config.passage_url_builder = ->(reference, version) {
419
- "https://www.biblegateway.com/passage/?search=#{URI.encode_www_form_component(reference)}&version=#{version}"
420
- }
421
418
  end
422
419
  ```
423
420
  ### Footer
@@ -460,7 +457,9 @@ It's emitted by the engine's layout, so if you point `config.layout` at your own
460
457
  References link to Bible Gateway by default. Readers choose Bible Gateway or Blue Letter Bible from
461
458
  their profile, and an admin can set the same source for any reader. The `HEB/GRK` option always uses
462
459
  Blue Letter Bible: WLC for Old Testament, Psalms, and Proverbs readings, and mGNT for New Testament
463
- readings. Set `passage_url_builder` to use another default reader, or a reader you host yourself.
460
+ readings. Scripture links share one dedicated browser tab so moving among the day's passages does not
461
+ leave a trail of open tabs; Ctrl-click, Cmd-click, middle-click, and the browser's context menu still
462
+ open additional tabs when a reader wants to compare passages.
464
463
 
465
464
  ## With ComfortableMediaSurfer
466
465
 
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
@@ -2,6 +2,8 @@
2
2
 
3
3
  module Bible270
4
4
  module PlanHelper
5
+ PASSAGE_LINK_TARGET = 'bible270_scripture'
6
+
5
7
  def b270_track(track)
6
8
  Plan::TRACKS.fetch(track.to_s)
7
9
  end
@@ -117,7 +119,18 @@ module Bible270
117
119
  return Translations.passage_url(reference, selected_version, blue_letter: true)
118
120
  end
119
121
 
120
- Bible270.config.passage_url_builder.call(reference, selected_version)
122
+ Translations.passage_url(reference, selected_version)
123
+ end
124
+
125
+ # The named target and noopener are the secure no-JavaScript fallback.
126
+ # Interaction UI retains one opener-backed tab handle on desktop. iOS Safari
127
+ # cannot foreground a reused background tab, so it closes and replaces that
128
+ # script-opened tab on each click. The two fixed providers are intentionally
129
+ # trusted for this enhanced path.
130
+ def b270_passage_link(reference, **options)
131
+ data = options.fetch(:data, {}).merge(b270_passage_link: true)
132
+ options.merge!(data: data, target: PASSAGE_LINK_TARGET, rel: 'noopener')
133
+ link_to reference, b270_passage_url(reference), options
121
134
  end
122
135
 
123
136
  # Small grey "(NKJV)" after a reading, so it's clear which translation the
@@ -224,8 +237,7 @@ module Bible270
224
237
  reference = readings[track]
225
238
  next if reference.blank?
226
239
 
227
- link_to reference, b270_passage_url(reference),
228
- class: 'b270-reflink', target: '_blank', rel: 'noopener'
240
+ b270_passage_link reference, class: 'b270-reflink'
229
241
  end
230
242
 
231
243
  safe_join(links, ' · ')
@@ -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
 
@@ -515,14 +515,13 @@ module Bible270
515
515
 
516
516
  # The start date that actually governs this reader. A reader's own
517
517
  # started_on wins when per-reader dates are allowed; otherwise (or if they
518
- # haven't got one) the community-wide config.start_date applies. Nil means
519
- # 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.
520
520
  def effective_start_date
521
- config = Bible270.config
522
- if config.allow_reader_start_date && started_on
521
+ if Bible270.config.allow_reader_start_date && started_on
523
522
  started_on
524
523
  else
525
- config.start_date
524
+ Setting.run_start_date
526
525
  end
527
526
  end
528
527
 
@@ -607,10 +606,9 @@ module Bible270
607
606
  # Called when a reader first participates. Only stamps a personal start date
608
607
  # when per-reader dates are enabled and a shared date isn't already in force.
609
608
  def ensure_started!
610
- config = Bible270.config
611
- return unless config.allow_reader_start_date
609
+ return unless Bible270.config.allow_reader_start_date
612
610
  return if started_on.present?
613
- return if config.start_date.present?
611
+ return if Setting.run_start_date.present?
614
612
 
615
613
  update!(started_on: Bible270.today)
616
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
 
@@ -27,13 +27,13 @@
27
27
  b270_success: (part_done ? "Reading marked unread." : "Reading marked read."),
28
28
  b270_failure: "Couldn’t update that reading. Try again." } },
29
29
  aria: { label: (part_done ? "Mark #{part_ref} unread" : "Mark #{part_ref} read") } do %>
30
- <span class="b270-check"><svg viewBox="0 0 24 24"><polyline points="20 6 9 17 4 12"/></svg></span>
30
+ <span class="b270-check"><svg viewBox="0 0 24 24"><polyline points="20 6 9 17 4 12" /></svg></span>
31
31
  <% end %>
32
32
  <% else %>
33
- <span class="b270-check"><svg viewBox="0 0 24 24"><polyline points="20 6 9 17 4 12"/></svg></span>
33
+ <span class="b270-check"><svg viewBox="0 0 24 24"><polyline points="20 6 9 17 4 12" /></svg></span>
34
34
  <% end %>
35
35
  <span class="b270-ref">
36
- <%= link_to part_ref, b270_passage_url(part_ref), target: "_blank", rel: "noopener" %>
36
+ <%= b270_passage_link part_ref %>
37
37
  </span>
38
38
  </li>
39
39
  <% end %>
@@ -51,14 +51,14 @@
51
51
  b270_success: (done ? "Reading marked unread." : "Reading marked read."),
52
52
  b270_failure: "Couldn’t update that reading. Try again." } },
53
53
  aria: { label: (done ? "Mark #{t[:label]} unread" : "Mark #{t[:label]} read") } do %>
54
- <span class="b270-check"><svg viewBox="0 0 24 24"><polyline points="20 6 9 17 4 12"/></svg></span>
54
+ <span class="b270-check"><svg viewBox="0 0 24 24"><polyline points="20 6 9 17 4 12" /></svg></span>
55
55
  <% end %>
56
56
  <% else %>
57
- <span class="b270-check"><svg viewBox="0 0 24 24"><polyline points="20 6 9 17 4 12"/></svg></span>
57
+ <span class="b270-check"><svg viewBox="0 0 24 24"><polyline points="20 6 9 17 4 12" /></svg></span>
58
58
  <% end %>
59
59
  <div class="b270-rbody">
60
60
  <div class="b270-cat"><%= t[:label] %></div>
61
- <div class="b270-ref"><%= link_to ref, b270_passage_url(ref), target: "_blank", rel: "noopener" %> <%= b270_version_tag(track: track) %></div>
61
+ <div class="b270-ref"><%= b270_passage_link ref %> <%= b270_version_tag(track: track) %></div>
62
62
  </div>
63
63
  <% end %>
64
64
  </div>
@@ -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>
@@ -30,6 +30,35 @@
30
30
  document.querySelectorAll("form[data-b270-submit='true']").forEach(resetForm);
31
31
  }
32
32
 
33
+ let scriptureWindow = null;
34
+ const replacesBackgroundTabs = /iPad|iPhone|iPod/.test(navigator.userAgent) ||
35
+ (navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1);
36
+
37
+ document.addEventListener("click", (event) => {
38
+ const target = event.target;
39
+ const link = target.closest && target.closest("a[data-b270-passage-link='true']");
40
+ if (!link || event.defaultPrevented || event.button !== 0) return;
41
+ if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return;
42
+
43
+ try {
44
+ if (replacesBackgroundTabs && scriptureWindow && !scriptureWindow.closed) {
45
+ scriptureWindow.close();
46
+ scriptureWindow = null;
47
+ }
48
+
49
+ if (!scriptureWindow || scriptureWindow.closed) {
50
+ scriptureWindow = window.open(link.href, "_blank");
51
+ if (!scriptureWindow) return;
52
+ } else {
53
+ scriptureWindow.location = link.href;
54
+ }
55
+ event.preventDefault();
56
+ scriptureWindow.focus();
57
+ } catch (_error) {
58
+ scriptureWindow = null;
59
+ }
60
+ });
61
+
33
62
  document.addEventListener("submit", (event) => {
34
63
  const form = event.target.closest("form[data-b270-submit='true']");
35
64
  if (!form) return;
@@ -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
@@ -271,7 +271,6 @@ module Bible270
271
271
  PROVIDER_LABELS[key.to_sym] || key.to_s.tr('_', ' ').split.map(&:capitalize).join(' ')
272
272
  end
273
273
 
274
- # Default Bible translation and a builder for external passage links.
275
274
  # Which translations readers may choose from. Defaults to all of
276
275
  # Bible270::Translations::VERSIONS; narrow it to offer fewer.
277
276
  attr_accessor :bible_versions
@@ -297,7 +296,7 @@ module Bible270
297
296
  # application owns scheduling the bible270:reminders:send task.
298
297
  attr_accessor :daily_reminders
299
298
 
300
- attr_accessor :after_sign_out_path, :email_sign_in_max_per_window, :passage_url_builder, :tagline, :footer_html, :footer, :favicon, :avatar_max_bytes, :chapter_breaks, :admin_emails, :admin_resolver, :bible_version, :header_mark, :remember_for, :require_sign_in_to_participate
299
+ attr_accessor :after_sign_out_path, :email_sign_in_max_per_window, :tagline, :footer_html, :footer, :favicon, :avatar_max_bytes, :chapter_breaks, :admin_emails, :admin_resolver, :bible_version, :header_mark, :remember_for, :require_sign_in_to_participate
301
300
 
302
301
  # Public labels.
303
302
  attr_accessor :app_name
@@ -355,7 +354,6 @@ module Bible270
355
354
  @after_sign_out_path = nil
356
355
  @bible_version = 'NKJV'
357
356
  @bible_versions = Translations::VERSIONS.keys
358
- @passage_url_builder = ->(reference, version) { Translations.passage_url(reference, version) }
359
357
  @app_name = 'Daily Bread'
360
358
  @tagline = 'Journeying through Scripture in 9 months'
361
359
  @time_zone = nil
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.3'
4
+ VERSION = '1.1.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.1.3
4
+ version: 1.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew vonderLuft