Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 11 additions & 8 deletions app/controllers/events/callouts_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ class CalloutsController < ApplicationController
before_action :set_event_registration
before_action :authorize_callout
before_action :set_event
# These pages carry an editable intro (the built-in row's "Callout page text")
# above the app-controlled content, plus any resources linked to the row.
before_action :set_builtin_content, only: %i[ payment scholarship certificate videoconference ]
# Every built-in page carries an editable intro + title (the built-in row's
# "Callout page text" / title) above the app-controlled content, plus any
# resources linked to the row.
before_action :set_builtin_content, only: %i[ payment scholarship certificate ce videoconference handouts faq ]

# Hidden Resource (by title) backing the handout links, in display order.
# Missing ones (e.g. not seeded in an environment) are silently skipped.
Expand Down Expand Up @@ -175,14 +176,16 @@ def set_event
@event = @event_registration.event
end

# The editable intro and linked resources for a built-in page, from the
# The editable intro, title, and linked resources for a built-in page, from the
# materialized callout row for this action's magic_key. Nil/empty when the
# event hasn't materialized the card. Payment renders its own document list
# (W-9 + invoice/receipt) in its Documents section, so it skips the generic
# inline resource list here.
# event hasn't materialized the card. The CE action is `ce` but its row's key is
# `ce_hours`. Payment renders its own document list (W-9 + invoice/receipt) in
# its Documents section, so it skips the generic inline resource list here.
def set_builtin_content
callout = @event.registration_ticket_callouts.find_by(magic_key: action_name)
magic_key = action_name == "ce" ? "ce_hours" : action_name
callout = @event.registration_ticket_callouts.find_by(magic_key:)
@builtin_intro = callout&.description.presence
@builtin_title = callout&.title.presence
@builtin_resources = callout && action_name != "payment" ? callout.resources.to_a : []
end

Expand Down
31 changes: 2 additions & 29 deletions app/controllers/events_controller.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
class EventsController < ApplicationController
include AhoyTracking, TagAssignable
skip_before_action :authenticate_user!, only: [ :index, :show, :staff, :details, :ce_hours ]
skip_before_action :authenticate_user!, only: [ :index, :show, :staff ]
skip_before_action :verify_authenticity_token, only: [ :preview ]
before_action :set_event, only: %i[ show edit update destroy preview dashboard sample_ticket background registrants onboarding details ce_hours staff edit_staff update_staff recipients bulk_payments preview_reminder confirm_reminder send_reminder copy_registration_form allocate_bulk_payment create_bulk_payment ]
before_action :set_event, only: %i[ show edit update destroy preview dashboard sample_ticket background registrants onboarding staff edit_staff update_staff recipients bulk_payments preview_reminder confirm_reminder send_reminder copy_registration_form allocate_bulk_payment create_bulk_payment ]

def index
authorize!
Expand Down Expand Up @@ -188,34 +188,7 @@ def onboarding
# Public "Before you attend" page (materials, supplies, policies). Linked from
# the registration ticket. When no details are set there is nothing to show, so
# fall back to the event page.
def details
authorize! @event, to: :details?

callout = @event.registration_ticket_callouts.find_by(magic_key: "event_details")
@event_details_title = callout&.title.presence || @event.event_details_label
@event_details_body = callout&.description.presence || @event.event_details

if @event_details_body.blank?
redirect_to event_path(@event, reg: params[:reg].presence)
return
end

@event = @event.decorate
end

# Public CE hours page (continuing education requirements, payment, sign-in
# rules). Linked from the registration ticket. When no details are set there
# is nothing to show, so fall back to the event page.
def ce_hours
authorize! @event, to: :ce_hours?

unless @event.ce_eligible?
redirect_to event_path(@event, reg: params[:reg].presence)
return
end

@event = @event.decorate
end

def staff
authorize! @event, to: :staff?
Expand Down
6 changes: 3 additions & 3 deletions app/controllers/registration_ticket_callouts_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ class RegistrationTicketCalloutsController < ApplicationController
before_action :set_event

# Public detail page for a single registration ticket callout, linked from the
# call-out on the registration ticket (mirrors the events#details / #ce_hours
# pages). With no description and no linked resource there is nothing to show,
# so fall back to the event page.
# call-out on the registration ticket. Also the page for content built-ins like
# event_details. With no description and no linked resource there is nothing to
# show, so fall back to the event page.
def show
@callout = @event.registration_ticket_callouts.find(params[:id])
authorize! @callout, to: :show?
Expand Down
13 changes: 0 additions & 13 deletions app/models/event.rb
Original file line number Diff line number Diff line change
Expand Up @@ -210,19 +210,6 @@ def name
title
end

# Heading shown on the ticket call-out and the details page. Falls back to the
# default even when an admin clears it, so the section never renders unlabelled.
def event_details_label
super.presence || "Before you attend"
end

# Heading shown on the CE hours ticket call-out and its details page. Falls
# back to the default even when an admin clears it, so the section never
# renders unlabelled.
def ce_hours_details_label
super.presence || "CE hours"
end

# Virtual attributes for date/time inputs (Firefox datetime-local compat)
attr_writer :start_date_date, :start_date_time,
:end_date_date, :end_date_time,
Expand Down
13 changes: 7 additions & 6 deletions app/models/registration_ticket_callout.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,16 @@ class RegistrationTicketCallout < ApplicationRecord
# that key. Admin-authored callouts have a nil magic_key. Magic callouts are
# hidden rather than destroyed so they can be restored to their default.
MAGIC_KEYS = %w[
payment certificate scholarship ce_hours event_details
payment certificate scholarship ce_hours art_supplies
videoconference handouts faq
].freeze

# "Content" magic callouts render their own editable copy/resources (like custom
# callouts). "Behavioral" magic callouts (the rest) render live per-registration
# status through MagicTicketCallouts#card_for β€” the row still owns the editable
# title/subtitle/text, order, visibility, and resources.
CONTENT_MAGIC_KEYS = %w[ handouts faq ].freeze
# "Content" magic callouts render their own editable copy/resources on the
# generic callout page (like custom callouts). "Behavioral" magic callouts (the
# rest) render live per-registration status through MagicTicketCallouts#card_for
# β€” the row still owns the editable title/subtitle/text, order, visibility, and
# resources. art_supplies is content: its page is just its title + copy.
CONTENT_MAGIC_KEYS = %w[ handouts faq art_supplies ].freeze

# Behavioral built-ins that also carry event-level config edited inline in their
# row (CE hours offered / cost); their text lives on the row like everything else.
Expand Down
6 changes: 0 additions & 6 deletions app/policies/event_policy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,6 @@ def google_analytics?
:short_description,
:rhino_header,
:rhino_description,
:event_details,
:event_details_label,
:ce_hours_details,
:ce_hours_details_label,
:ce_hours_offered,
:ce_hours_cost,
:autoshow_cost,
Expand Down Expand Up @@ -169,8 +165,6 @@ def google_analytics?
end

alias_rule :preview?, to: :edit?
alias_rule :details?, to: :show?
alias_rule :ce_hours?, to: :show?

private

Expand Down
17 changes: 7 additions & 10 deletions app/services/default_ticket_callouts.rb
Original file line number Diff line number Diff line change
Expand Up @@ -174,23 +174,20 @@ def definitions
},
{
magic_key: "ce_hours",
# Title/text seed from the event's CE columns (migrating existing content);
# thereafter they live on the row like every other built-in. The row also
# carries the CE hours-offered/cost config.
title: ->(event) { event.ce_hours_details_label },
description: ->(event) { event.ce_hours_details },
# Text lives on the row like every other built-in (edit it as the callout's
# "Callout page text"). The row also carries the CE hours-offered/cost config.
title: "CE hours",
subtitle: "Continuing education β€” requirements & how to request",
callout_type: "action",
icon_class: "fa-solid fa-graduation-cap",
color_class: "teal",
hidden: ->(event) { !event.facilitator_training? }
},
{
magic_key: "event_details",
# Title/text seed from the event's details columns (migrating existing
# content); thereafter they live on the row.
title: ->(event) { event.event_details_label },
description: ->(event) { event.event_details },
magic_key: "art_supplies",
# Text lives on the row like every other built-in (edit it as the callout's
# "Callout page text"); its page is just that title + copy.
title: "Art supplies & what to bring",
subtitle: "Important info for this event β€” please read",
callout_type: "reference",
icon_class: "fa-solid fa-palette",
Expand Down
27 changes: 4 additions & 23 deletions app/services/magic_ticket_callouts.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,8 @@ def theme = DomainTheme.swatch(color)
end

# A registration-free description of one built-in card, for the event editor's
# callouts section. `key` is :ce_hours / :event_details for the two whose text
# admins edit via event columns; nil for the cards the app fully controls (shown
# greyed out). `magic_key` ties the card to its ticket behavior β€” once an event
# callouts section. `key` is nil for the app-controlled preview cards shown greyed
# out (all of them today). `magic_key` ties the card to its ticket behavior β€” once an event
# has materialized that key into an editable row, the preview is dropped here and
# the row is edited in the callout list instead. `subtitle` mirrors the card's
# ticket subtitle; `visibility` describes when the app shows it (rendered next to
Expand Down Expand Up @@ -58,7 +57,6 @@ def self.editor_cards(event)
"certificate" => :certificate_card,
"scholarship" => :scholarship_status_card,
"ce_hours" => :ce_hours_card,
"event_details" => :event_details_card,
"videoconference" => :videoconference_card,
"handouts" => :handouts_card,
"faq" => :faq_card
Expand All @@ -74,7 +72,7 @@ def initialize(event_registration)
# those from the row (calling #card_for for behavioral ones), so this is both the
# non-materialized set and the fallback for events not yet seeded.
def cards
CARD_BUILDERS.reject { |magic_key, _| materialized?(magic_key) || skip_in_fallback?(magic_key) }
CARD_BUILDERS.reject { |magic_key, _| materialized?(magic_key) }
.filter_map { |_, builder| send(builder) }
end

Expand All @@ -87,8 +85,6 @@ def card_for(callout)
builder = CARD_BUILDERS[callout.magic_key]
base = builder && send(builder)
return unless base
# Event details links to its page only when it has content to show.
return if callout.magic_key == "event_details" && callout.description.blank?

base.with(
title: callout.title,
Expand All @@ -111,12 +107,6 @@ def materialized?(magic_key)
@materialized_keys.include?(magic_key)
end

# In the unseeded fallback, event-details content lives on the event column, so
# hide the card when it's blank (the row path checks the row in #card_for).
def skip_in_fallback?(magic_key)
magic_key == "event_details" && event.event_details.blank?
end

# Top card: an action card while a balance is due, a reference card once paid
# in full. Its page lists every allocation with the running balance, plus the
# linked documents (the W-9, and the invoice/receipt) for paid events.
Expand Down Expand Up @@ -179,7 +169,7 @@ def ce_hours_card
# the payment card, rather than the resting teal.
due = registration.continuing_education_registrations.first&.remaining_cost.to_i.positive?
Card.new(icon_class: "fa-solid fa-graduation-cap", color: due ? "orange" : "teal",
title: event.ce_hours_details_label,
title: "CE hours",
subtitle: ce_hours_subtitle,
href: registration_ce_path(registration.slug),
target: nil, trailing_icon: "fa-solid fa-arrow-right",
Expand Down Expand Up @@ -221,15 +211,6 @@ def ce_missing_text
"License number needed"
end

# "Art supplies & what to bring" β€” the event's own details page.
def event_details_card
Card.new(icon_class: "fa-solid fa-palette", color: "blue",
title: event.event_details_label,
subtitle: "Important info for this event β€” please read",
href: details_event_path(event, reg: registration.slug),
target: nil, trailing_icon: "fa-solid fa-arrow-right")
end

# Shown only when the event has a videoconference URL set.
def videoconference_card
return if event.videoconference_url.blank?
Expand Down
28 changes: 0 additions & 28 deletions app/views/events/_builtin_callout_card.html.erb

This file was deleted.

15 changes: 0 additions & 15 deletions app/views/events/_form.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -580,20 +580,6 @@

<div class="space-y-3 mb-3">
<% MagicTicketCallouts.editor_cards(@event).each do |card| %>
<% case card.key %>
<% when :ce_hours %>
<%= render "events/builtin_callout_card", f: f, card: card,
label_field: :ce_hours_details_label, content_field: :ce_hours_details,
title_placeholder: "CE hours",
content_help: "CE requirements, payment, sign-in rules, and the post-training evaluation β€” shown on its own page linked from the ticket. Accepts basic HTML β€” bold, italics, links, lists, headings, and line breaks.",
content_placeholder: "e.g. <p>AWBW is approved by CAMFT…</p><h3>Before the training</h3><ul><li>Email your license number</li></ul>" %>
<% when :event_details %>
<%= render "events/builtin_callout_card", f: f, card: card,
label_field: :event_details_label, content_field: :event_details,
title_placeholder: "Before you attend",
content_help: "Materials, supplies, what to bring, and policies β€” shown on its own page linked from the ticket. Leave blank to hide it entirely. Accepts basic HTML β€” bold, italics, links, lists, headings, and line breaks.",
content_placeholder: "e.g. <h3>Workshop 1</h3><ul><li>Clear glass stones</li></ul>" %>
<% else %>
<div class="flex items-start gap-3 rounded-lg border border-gray-200 bg-gray-50 p-3 opacity-70">
<i class="<%= card.icon_class %> <%= card.theme[:icon] %> w-6 shrink-0 text-center text-xl pt-0.5" aria-hidden="true"></i>

Expand Down Expand Up @@ -639,7 +625,6 @@
<% end %>
</div>
</div>
<% end %>
<% end %>
</div>

Expand Down
12 changes: 3 additions & 9 deletions app/views/events/callouts/ce.html.erb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<% content_for(:page_bg_class, "public") %>
<% content_for(:page_title, "#{@event.ce_hours_details_label} β€” #{@event.title}") %>
<% ce_title = @builtin_title.presence || "CE hours" %>
<% content_for(:page_title, "#{ce_title} β€” #{@event.title}") %>
<% ce_registration = @event_registration.continuing_education_registrations.first %>

<%#
Expand All @@ -14,7 +15,7 @@
{}
end %>

<%= render layout: "events/callouts/callout_page", locals: { title: @event.ce_hours_details_label, **callout_eyebrow } do %>
<%= render layout: "events/callouts/callout_page", locals: { title: ce_title, **callout_eyebrow } do %>
<% if @event_registration.ce_registered? %>
<% license = ce_registration&.professional_license %>
<% license_kind = license&.kind %>
Expand Down Expand Up @@ -228,11 +229,4 @@
<%= form.submit "Request CE credit", class: "rounded-lg bg-teal-600 px-4 py-2 text-sm font-medium text-white shadow-sm hover:bg-teal-700 focus:outline-none focus:ring-2 focus:ring-teal-300 cursor-pointer" %>
<% end %>
<% end %>

<% if @event.ce_hours_details.present? %>
<section class="mt-7 border-t border-gray-100 pt-6">
<h2 class="text-xs font-semibold uppercase tracking-wider text-gray-500">Details</h2>
<div class="mt-3 rich-label prose max-w-none text-gray-700 leading-relaxed prose-headings:text-gray-800 prose-a:text-blue-700"><%= form_label_html(@event.ce_hours_details) %></div>
</section>
<% end %>
<% end %>
Loading