bible270 0.11.2 → 0.12.0

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: 52e08240916fa78ed55408939d5ab6ecd297113f96b4f1cee646d471a9b289dd
4
- data.tar.gz: 5e078496dab3ca466eb2c1ef702a1ef4578cfa16566aa8194eb04022025ac05b
3
+ metadata.gz: 57c5245aba9c3d25d04ad67878802fc5d7ad712750dac55e85083e5d45080947
4
+ data.tar.gz: c9405dc4ac8ab2cb41d20d7c9a2f4ed4018fe814a7054f98494220da4468df47
5
5
  SHA512:
6
- metadata.gz: 07ab2d3720035d36f7dd9226455d2239db65fe0c623a682aea50ceec94cd74d4a0d13dd5c3cac0b06c8d66b2a08234d57f4cdb432ac647d905ff0f9116b5a2dd
7
- data.tar.gz: eb5082979de6f974634b2a6abdafab906f7bbd62d68b465f14b13d5a9ec73d461c82f203c79e1c48084e4e7fdc00c16ea7bf3390713f3c11447267ed980ab1c9
6
+ metadata.gz: b3a226ef874707b703845e48c496deb6b037b7714db29323241d337dcdd248e0c95fb2fe545171dd467790aa78b99bd8e304f010cca2b94e79dc659336445588
7
+ data.tar.gz: 8bcaf063952c4d82fff0d88ee06838bc599085eaaa37d69498aa3f7da0ce844ee81d05f7b4a08c7095d9835e013cfd2454057f88bb1d8bfc3fc8f2f2a7704533
@@ -14,6 +14,9 @@ module Bible270
14
14
  problems = []
15
15
  problems << 'both a first and last name' unless current_reader.update_names(params[:first_name],
16
16
  params[:last_name])
17
+ if params[:bible_version].present? && !current_reader.update_bible_version(params[:bible_version])
18
+ problems << 'a translation from the list'
19
+ end
17
20
  if params[:avatar].present? && !current_reader.attach_avatar(params[:avatar])
18
21
  problems << (current_reader.errors[:avatar].first || 'a valid image')
19
22
  end
@@ -18,14 +18,24 @@ module Bible270
18
18
  Bible270.config.label_for_provider(provider)
19
19
  end
20
20
 
21
- def b270_passage_url(reference)
21
+ # The signed-in reader's translation, falling back to the site default for
22
+ # visitors who aren't signed in.
23
+ def b270_bible_version
24
+ current_reader&.effective_bible_version || Translations.resolve(nil)
25
+ end
26
+
27
+ def b270_passage_url(reference, version = nil)
22
28
  return '#' if reference.blank?
23
29
 
24
- Bible270.config.passage_url_builder.call(reference, Bible270.config.bible_version)
30
+ Bible270.config.passage_url_builder.call(reference, version || b270_bible_version)
31
+ end
32
+
33
+ # Small grey "(NKJV)" after a reading, so it's clear which translation the
34
+ # link opens in.
35
+ def b270_version_tag(version = nil)
36
+ content_tag :span, "(#{version || b270_bible_version})", class: 'b270-version'
25
37
  end
26
38
 
27
- # An uploaded avatar wins over whatever the sign-in provider gave us.
28
- # Active Storage routes live in the host app, hence main_app.
29
39
  def b270_avatar_src(reader)
30
40
  return main_app.rails_blob_path(reader.avatar, only_path: true) if reader.avatar_uploaded?
31
41
 
@@ -114,6 +114,22 @@ module Bible270
114
114
  Names.first_with_last_initial(first_name, last_name).presence || display_name
115
115
  end
116
116
 
117
+ # The translation this reader reads in. Null means "whatever the site default
118
+ # is", so changing config.bible_version moves everyone who hasn't chosen.
119
+ def effective_bible_version
120
+ Translations.resolve(bible_version)
121
+ end
122
+
123
+ def bible_version_label
124
+ Translations.label(effective_bible_version)
125
+ end
126
+
127
+ def update_bible_version(code)
128
+ return false unless Translations.valid?(code)
129
+
130
+ update(bible_version: Translations.normalize(code))
131
+ end
132
+
117
133
  def sort_name
118
134
  [last_name, first_name].map { |n| n.to_s.strip.downcase }.join(' ').strip.presence || display_name.to_s.downcase
119
135
  end
@@ -209,7 +225,7 @@ module Bible270
209
225
  def suggested_names
210
226
  return { first_name: first_name, last_name: last_name } if full_name
211
227
 
212
- Names.split(display_name) || { first_name: display_name, last_name: nil }
228
+ Names.split_display_name(display_name) || { first_name: display_name, last_name: nil }
213
229
  end
214
230
 
215
231
  # ---- administrative adjustments --------------------------------------
@@ -1,4 +1,5 @@
1
1
  <% content_for :title, "#{@reader.display_name} — Admin" %>
2
+ <% content_for :hide_day_index, true %><%# this page has its own grid %>
2
3
  <p class="b270-eyebrow"><%= link_to 'Admin', admin_path %></p>
3
4
  <h1><%= @reader.display_name %></h1>
4
5
  <p class="lede">
@@ -11,7 +11,7 @@
11
11
  <% end %>
12
12
  <div class="b270-rbody">
13
13
  <div class="b270-cat"><%= t[:label] %></div>
14
- <div class="b270-ref"><%= link_to ref, b270_passage_url(ref), target: "_blank", rel: "noopener" %></div>
14
+ <div class="b270-ref"><%= link_to ref, b270_passage_url(ref), target: "_blank", rel: "noopener" %> <%= b270_version_tag %></div>
15
15
  </div>
16
16
  </div>
17
17
  <% else %>
@@ -27,6 +27,14 @@
27
27
  <span>Last name</span>
28
28
  <%= text_field_tag :last_name, @names[:last_name], required: true, autocomplete: "family-name" %>
29
29
  </label>
30
+ <label class="b270-field">
31
+ <span>Bible translation</span>
32
+ <%= select_tag :bible_version,
33
+ options_for_select(Bible270::Translations.options, current_reader.effective_bible_version),
34
+ class: "b270-select" %>
35
+ <span class="b270-hint" style="margin:0">Reading links open in this translation.</span>
36
+ </label>
37
+
30
38
  <%= submit_tag "Save", class: "b270-btn" %>
31
39
  <% end %>
32
40
 
@@ -1,8 +1,12 @@
1
1
  <% content_for :title, "#{@reader.display_name} — #{Bible270.config.app_name}" %>
2
+ <% content_for :hide_day_index, true %><%# this page has its own grid %>
2
3
  <div style="display:flex;align-items:center;gap:16px;margin-bottom:8px">
3
4
  <%= b270_avatar(@reader, size: 56) %>
4
5
  <div>
5
6
  <h1 style="margin:0"><%= @reader.display_name %></h1>
7
+ <% if signed_in? && current_reader.id == @reader.id %>
8
+ <p style="margin:2px 0 0"><%= link_to 'Edit your name', profile_path, class: 'b270-linkbtn' %></p>
9
+ <% end %>
6
10
  <p style="margin:2px 0 0;color:var(--faint);font-size:14px"><%= @days_completed %> of <%= Bible270::Plan::DAYS %> days complete · <%= @reader.completion_percent %>%</p>
7
11
  </div>
8
12
  </div>
@@ -107,6 +107,8 @@
107
107
  .b270-rbody{flex:1;min-width:0}
108
108
  .b270-cat{font-size:11px;letter-spacing:.13em;text-transform:uppercase;color:var(--faint);font-weight:600}
109
109
  .b270-ref{font-family:"Spectral",serif;font-size:19px;font-weight:500;margin-top:1px}
110
+ .b270-version{font-size:11.5px;color:var(--faint);font-weight:400;letter-spacing:.02em;white-space:nowrap}
111
+ .b270-select{font:inherit;font-size:14px;padding:10px 30px 10px 12px;border:1px solid var(--line);border-radius:9px;background:#fff;color:var(--ink);width:100%;max-width:100%;text-overflow:ellipsis}
110
112
  .b270-ref a{text-decoration:none;border-bottom:1px solid transparent}
111
113
  .b270-ref a:hover{border-bottom-color:var(--gold)}
112
114
  .b270-reading.done .b270-ref{color:var(--muted)}
@@ -18,9 +18,13 @@
18
18
  <% if flash[:alert] %><div class="b270-flash alert"><%= flash[:alert] %></div><% end %>
19
19
  <% if flash[:notice] %><div class="b270-flash notice"><%= flash[:notice] %></div><% end %>
20
20
  <%= yield %>
21
- <%= render 'bible270/shared/day_index' %>
21
+ <%# Pages with their own day grid opt out with content_for :hide_day_index %>
22
+ <%= render 'bible270/shared/day_index' unless content_for?(:hide_day_index) %>
22
23
  <footer class="b270-footer">
23
- <p>The Old Testament, New Testament and Psalms/Proverbs are each read once across the 270 days. Long chapters are divided so the readings fill each day evenly, e.g. Psalm 119 comes in eleven sections.</p>
24
+ <p>The Old Testament and New Testament are each read once across the 270 days, with a
25
+ reading from all three tracks every day. Alongside them the Psalms run once and
26
+ Proverbs twice; the longest chapters are divided so the readings fill each day
27
+ evenly, and Psalm 119 comes in eleven sections.</p>
24
28
  </footer>
25
29
  </div>
26
30
  </body>
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ class AddBibleVersionToBible270Readers < ActiveRecord::Migration[7.0]
4
+ def change
5
+ # Null means "use whatever the site default is", so changing
6
+ # config.bible_version moves everyone who hasn't chosen for themselves.
7
+ add_column :bible270_readers, :bible_version, :string
8
+ end
9
+ end
@@ -7,6 +7,7 @@
7
7
  require 'uri'
8
8
  require 'bible270/plan'
9
9
  require 'bible270/avatars'
10
+ require 'bible270/translations'
10
11
 
11
12
  module Bible270
12
13
  class Configuration
@@ -147,7 +148,6 @@ module Bible270
147
148
  # Psalm 35: []
148
149
  # Psalm 78: [20, 39, 55]
149
150
  attr_accessor :chapter_breaks_path
150
- attr_accessor :after_sign_out_path, :email_sign_in_max_per_window, :passage_url_builder, :tagline, :avatar_max_bytes, :chapter_breaks, :admin_emails, :admin_resolver
151
151
 
152
152
  def admin?(reader)
153
153
  return false if reader.nil?
@@ -202,7 +202,11 @@ module Bible270
202
202
  end
203
203
 
204
204
  # Default Bible translation and a builder for external passage links.
205
- attr_accessor :bible_version
205
+ # Which translations readers may choose from. Defaults to all of
206
+ # Bible270::Translations::VERSIONS; narrow it to offer fewer.
207
+ attr_accessor :bible_versions
208
+
209
+ attr_accessor :after_sign_out_path, :email_sign_in_max_per_window, :passage_url_builder, :tagline, :avatar_max_bytes, :chapter_breaks, :admin_emails, :admin_resolver, :bible_version
206
210
 
207
211
  # Public labels.
208
212
  attr_accessor :app_name
@@ -230,9 +234,11 @@ module Bible270
230
234
  @after_sign_in_path = nil
231
235
  @after_sign_out_path = nil
232
236
  @bible_version = 'NKJV'
237
+ @bible_versions = Translations::VERSIONS.keys
233
238
  @passage_url_builder = ->(reference, version) do
234
239
  search = URI.encode_www_form_component(reference)
235
- version = URI.encode_www_form_component(version)
240
+ # Translations.gateway_code maps 'NASB95' to Bible Gateway's 'NASB1995'.
241
+ version = URI.encode_www_form_component(Translations.gateway_code(version))
236
242
  "https://www.biblegateway.com/passage/?search=#{search}&version=#{version}"
237
243
  end
238
244
  @app_name = 'Daily Bread'
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bible270
4
+ # The translations a reader may choose between, and how each maps onto the
5
+ # external reader's own code. Kept free of Rails so it can be unit tested.
6
+ #
7
+ # The distinction matters: readers know the NASB 1995 as "NASB95", but Bible
8
+ # Gateway's parameter for it is "NASB1995". Sending the display code straight
9
+ # through would land every link on a search page instead of the passage.
10
+ module Translations
11
+ # `label` is the full name, for prose. `short` is what goes in the select,
12
+ # where "New American Standard Bible 1995" overflows the box.
13
+ VERSIONS = {
14
+ 'NKJV' => { label: 'New King James Version', short: 'New King James Version', gateway: 'NKJV' },
15
+ 'NASB95' => { label: 'New American Standard Bible 1995', short: 'New American Standard 1995', gateway: 'NASB1995' },
16
+ 'LSB' => { label: 'Legacy Standard Bible', short: 'Legacy Standard Version', gateway: 'LSB' },
17
+ 'ESV' => { label: 'English Standard Version', short: 'English Standard Version', gateway: 'ESV' },
18
+ 'KJV' => { label: 'King James Version', short: 'King James Version', gateway: 'KJV' }
19
+ }.freeze
20
+
21
+ DEFAULT = 'NKJV'
22
+
23
+ module_function
24
+
25
+ # The codes offered to readers, narrowed by config.bible_versions if the host
26
+ # only wants some of them.
27
+ def codes
28
+ allowed = Bible270.config.bible_versions if Bible270.config.respond_to?(:bible_versions)
29
+ requested = Array(allowed).map { |code| code.to_s.upcase }.select { |code| VERSIONS.key?(code) }
30
+ requested.any? ? requested : VERSIONS.keys
31
+ end
32
+
33
+ def valid?(code)
34
+ codes.include?(normalize(code))
35
+ end
36
+
37
+ def normalize(code)
38
+ code.to_s.strip.upcase
39
+ end
40
+
41
+ def label(code)
42
+ VERSIONS.dig(normalize(code), :label)
43
+ end
44
+
45
+ def short_label(code)
46
+ VERSIONS.dig(normalize(code), :short) || label(code)
47
+ end
48
+
49
+ # The code the external reader expects, which is not always the code readers
50
+ # recognise.
51
+ def gateway_code(code)
52
+ VERSIONS.dig(normalize(code), :gateway) || normalize(code)
53
+ end
54
+
55
+ # [[label, code], ...] for a select field.
56
+ def options
57
+ codes.map { |code| ["#{code} — #{short_label(code)}", code] }
58
+ end
59
+
60
+ # Falls back to the configured default, then to ESV, so a link is never built
61
+ # with a blank version.
62
+ def resolve(code)
63
+ return normalize(code) if valid?(code)
64
+
65
+ configured = Bible270.config.bible_version if Bible270.config.respond_to?(:bible_version)
66
+ return normalize(configured) if valid?(configured)
67
+
68
+ codes.include?(DEFAULT) ? DEFAULT : codes.first
69
+ end
70
+ end
71
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bible270
4
- VERSION = '0.11.2'
4
+ VERSION = '0.12.0'
5
5
  end
data/lib/bible270.rb CHANGED
@@ -5,6 +5,7 @@ require 'bible270/plan'
5
5
  require 'bible270/email_sign_in'
6
6
  require 'bible270/names'
7
7
  require 'bible270/avatars'
8
+ require 'bible270/translations'
8
9
  require 'bible270/configuration'
9
10
  require 'bible270/engine' if defined?(Rails::Engine)
10
11
 
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.11.2
4
+ version: 0.12.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew vonderLuft
@@ -113,6 +113,7 @@ files:
113
113
  - db/migrate/20260101000005_add_names_to_bible270_readers.rb
114
114
  - db/migrate/20260101000006_add_approval_to_bible270_comments.rb
115
115
  - db/migrate/20260101000007_create_bible270_settings.rb
116
+ - db/migrate/20260101000008_add_bible_version_to_bible270_readers.rb
116
117
  - lib/bible270.rb
117
118
  - lib/bible270/avatars.rb
118
119
  - lib/bible270/configuration.rb
@@ -120,6 +121,7 @@ files:
120
121
  - lib/bible270/engine.rb
121
122
  - lib/bible270/names.rb
122
123
  - lib/bible270/plan.rb
124
+ - lib/bible270/translations.rb
123
125
  - lib/bible270/versification.rb
124
126
  - lib/bible270/version.rb
125
127
  - lib/generators/bible270/install/install_generator.rb