Class: Bible270::AdminController
- Inherits:
-
ApplicationController
- Object
- ApplicationController
- Bible270::AdminController
- Defined in:
- app/controllers/bible270/admin_controller.rb
Overview
Small administrative panel: remove readers, adjust their completions, and move them to a given day of the plan.
Access is controlled by Bible270.config.admin_emails / admin_resolver. With neither set the panel is unreachable, and every action 404s rather than 403s so its existence isn't advertised.
Constant Summary collapse
- LAST_BROADCAST_AT =
'last_broadcast_at'- LAST_BROADCAST_SUBJECT =
'last_broadcast_subject'
Instance Method Summary collapse
-
#broadcast ⇒ Object
Put the reader on a given day as of today, or set an explicit start date.
-
#comments ⇒ Object
Everything is visible by default; this lists it all so anything unsuitable can be taken down.
- #complete_through ⇒ Object
- #deliver_broadcast(recipients, subject, body) ⇒ Object
- #destroy ⇒ Object
- #destroy_comment ⇒ Object
- #hide_comment ⇒ Object
- #index ⇒ Object
-
#parsed_time(value) ⇒ Object
Failures are counted rather than raised: one bad address must not stop the rest of the message going out, and the admin is told how many were sent.
- #remove_avatar ⇒ Object
- #show ⇒ Object
- #toggle_day ⇒ Object
- #unhide_comment ⇒ Object
- #update_bible_version ⇒ Object
-
#update_enrollment ⇒ Object
---- enrolment --------------------------------------------------------.
-
#update_profile ⇒ Object
Name and picture together, mirroring what a reader can change about themselves on their own profile.
- #update_start ⇒ Object
Instance Method Details
#broadcast ⇒ Object
Put the reader on a given day as of today, or set an explicit start date.
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
# File 'app/controllers/bible270/admin_controller.rb', line 84 def broadcast subject = params[:subject].to_s.strip body = params[:body].to_s.strip if subject.empty? || body.empty? return redirect_to(admin_path, alert: 'A message needs both a subject and something to say.') end recipients = Reader.where.not(email: [nil, '']).order(:id) return redirect_to(admin_path, alert: 'Nobody has an email address.') if recipients.empty? sent = deliver_broadcast(recipients, subject, body) Setting.write(LAST_BROADCAST_AT, Time.current.iso8601) Setting.write(LAST_BROADCAST_SUBJECT, subject) redirect_to admin_path, notice: "Sent to #{sent} #{'reader'.pluralize(sent)}." end |
#comments ⇒ Object
Everything is visible by default; this lists it all so anything unsuitable can be taken down.
52 53 54 55 56 57 58 59 |
# File 'app/controllers/bible270/admin_controller.rb', line 52 def comments scope = Comment.includes(:reader, parent: :reader).order(created_at: :desc) @filter = params[:filter].to_s scope = scope.hidden if @filter == 'hidden' scope = scope.approved if @filter == 'visible' @comments = scope.limit(200) @hidden_count = Comment.hidden.count end |
#complete_through ⇒ Object
175 176 177 178 179 180 181 182 183 |
# File 'app/controllers/bible270/admin_controller.rb', line 175 def complete_through day = params[:day].to_i if @reader.mark_through!(day) redirect_to admin_reader_path(@reader), notice: day.zero? ? 'All check-offs cleared.' : "Marked days 1-#{day} complete." else redirect_to admin_reader_path(@reader), alert: 'Give a day between 0 and 270.' end end |
#deliver_broadcast(recipients, subject, body) ⇒ Object
206 207 208 209 210 211 212 213 214 215 216 217 218 219 |
# File 'app/controllers/bible270/admin_controller.rb', line 206 def deliver_broadcast(recipients, subject, body) later = Bible270.config.registration_notice_deliver_later sent = 0 recipients.find_each do |reader| mail = NoticeMailer.broadcast(reader_id: reader.id, subject: subject, body: body) later ? mail.deliver_later : mail.deliver_now sent += 1 rescue StandardError => e Rails.logger.error("[bible270] broadcast to reader #{reader.id} failed: #{e.class}: #{e.}") end sent end |
#destroy ⇒ Object
77 78 79 80 81 |
# File 'app/controllers/bible270/admin_controller.rb', line 77 def destroy name = @reader.display_name @reader.destroy redirect_to admin_path, notice: "Removed #{name} and all their check-offs and reflections." end |
#destroy_comment ⇒ Object
71 72 73 74 75 |
# File 'app/controllers/bible270/admin_controller.rb', line 71 def destroy_comment day = @comment.day @comment.destroy redirect_back_to_comments "Deleted the reflection on day #{day}." end |
#hide_comment ⇒ Object
61 62 63 64 |
# File 'app/controllers/bible270/admin_controller.rb', line 61 def hide_comment @comment.hide! redirect_back_to_comments "Hidden #{@comment.reader.display_name}'s reflection on day #{@comment.day}." end |
#index ⇒ Object
31 32 33 34 35 36 37 38 39 40 41 |
# File 'app/controllers/bible270/admin_controller.rb', line 31 def index @enrollment_closed = Setting.enrollment_closed? @enrollment_closed_at = Setting.enrollment_closed_at @readers = Reader.all.to_a.sort_by(&:sort_name) counts = Checkoff.group(:reader_id, :day).count @days_completed = Hash.new(0) counts.each { |(rid, day), n| @days_completed[rid] += 1 if n >= Plan.total_parts(day) } @reachable = Reader.where.not(email: [nil, '']).count @last_broadcast_at = parsed_time(Setting.read(LAST_BROADCAST_AT)) @last_broadcast_subject = Setting.read(LAST_BROADCAST_SUBJECT) end |
#parsed_time(value) ⇒ Object
Failures are counted rather than raised: one bad address must not stop the rest of the message going out, and the admin is told how many were sent. A stored timestamp that cannot be read is treated as absent rather than blowing up the admin page.
198 199 200 201 202 203 204 |
# File 'app/controllers/bible270/admin_controller.rb', line 198 def parsed_time(value) return nil if value.blank? Time.parse(value.to_s) rescue ArgumentError, TypeError nil end |
#remove_avatar ⇒ Object
170 171 172 173 |
# File 'app/controllers/bible270/admin_controller.rb', line 170 def remove_avatar @reader.remove_avatar! redirect_to admin_reader_path(@reader), notice: "Removed #{@reader.display_name}'s picture." end |
#show ⇒ Object
43 44 45 46 |
# File 'app/controllers/bible270/admin_controller.rb', line 43 def show @days_completed = @reader.days_completed @comments = @reader.comments.order(created_at: :desc).limit(50) end |
#toggle_day ⇒ Object
185 186 187 188 189 190 191 192 |
# File 'app/controllers/bible270/admin_controller.rb', line 185 def toggle_day day = params[:day].to_i if @reader.toggle_day!(day) redirect_to admin_reader_path(@reader, anchor: "day-#{day}") else redirect_to admin_reader_path(@reader), alert: 'That day is outside the plan.' end end |
#unhide_comment ⇒ Object
66 67 68 69 |
# File 'app/controllers/bible270/admin_controller.rb', line 66 def unhide_comment @comment.unhide! redirect_back_to_comments "Restored #{@comment.reader.display_name}'s reflection on day #{@comment.day}." end |
#update_bible_version ⇒ Object
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
# File 'app/controllers/bible270/admin_controller.rb', line 103 def update_bible_version reader = Reader.find_by(id: params[:id]) return redirect_to(admin_path, alert: 'No such reader.') if reader.nil? code = params[:bible_version].to_s source = params[:passage_source].presence || Reader::DEFAULT_PASSAGE_SOURCE unless Reader::PASSAGE_SOURCES.include?(source) return redirect_to admin_reader_path(reader), alert: 'That is not a reading-link source on the list.' end # Blank means "no preference": the reader follows the site default, which is # not the same as choosing whichever translation the site happens to use now. if code.empty? reader.update(bible_version: nil, passage_source: source) return redirect_to admin_reader_path(reader), notice: "#{reader.display_name} now follows the site default " \ "(#{Bible270.config.bible_version})." end if reader.update_bible_version(code) reader.update_column(:passage_source, source) redirect_to admin_reader_path(reader), notice: "#{reader.display_name} now reads the #{reader.bible_version_label}." else redirect_to admin_reader_path(reader), alert: 'That is not a translation on the list.' end end |
#update_enrollment ⇒ Object
---- enrolment --------------------------------------------------------
21 22 23 24 25 26 27 28 29 |
# File 'app/controllers/bible270/admin_controller.rb', line 21 def update_enrollment if params[:state] == 'closed' Setting.close_enrollment! redirect_to admin_path, notice: 'Closed to new readers. Existing readers can still sign in.' else Setting.open_enrollment! redirect_to admin_path, notice: 'Open to new readers.' end end |
#update_profile ⇒ Object
Name and picture together, mirroring what a reader can change about themselves on their own profile.
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
# File 'app/controllers/bible270/admin_controller.rb', line 153 def update_profile problems = [] if (params[:first_name].present? || params[:last_name].present?) && !@reader.update_names(params[:first_name], params[:last_name]) problems << 'both a first and last name' end if params[:avatar].present? && !@reader.attach_avatar(params[:avatar]) problems << (@reader.errors[:avatar].first || 'a valid image') end if problems.empty? redirect_to admin_reader_path(@reader), notice: 'Updated.' else redirect_to admin_reader_path(@reader), alert: "Needs #{problems.to_sentence}." end end |
#update_start ⇒ Object
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
# File 'app/controllers/bible270/admin_controller.rb', line 131 def update_start if params[:start_date].present? # set_start_date!, not update_start_date!: an admin is not subject to # config.allow_reader_start_date, which governs what readers may do to # their own dates. if @reader.set_start_date!(params[:start_date]) redirect_to admin_reader_path(@reader), notice: "Start date set to #{@reader.started_on.strftime('%B %-d, %Y')}." else redirect_to admin_reader_path(@reader), alert: "Couldn't read #{params[:start_date].inspect} as a date." end elsif params[:day].present? && @reader.restart_on!(day: params[:day]) redirect_to admin_reader_path(@reader), notice: "#{@reader.display_name} is now on day #{params[:day]}." else redirect_to admin_reader_path(@reader), alert: 'Give a start date or a day between 1 and 270.' end end |