|
- <% if user.avatar.present? %>
- <%= image_tag url_for(user.avatar), class: "w-10 h-10 rounded-full object-cover border border-gray-300 shadow-sm mx-auto" %>
+ <% if user.facilitator %>
+ <%= facilitator_profile_button(user.facilitator) %>
<% else %>
- <%= image_tag "missing.png", class: "w-10 h-10 rounded-full object-cover border border-dashed border-gray-300 mx-auto" %>
+ <%= link_to "Create facilitator",
+ new_facilitator_path(user_id: user.id),
+ class: "btn btn-secondary-outline" %>
<% end %>
|
-
- <%= user.first_name %> |
-
-
- <%= user.last_name %> |
-
<%= user.email %> |
-
-
- <% if user.projects.any? %>
- <% user_project_names = user.projects.map(&:name).join(", ") %>
-
- <%= truncate(user_project_names, length: 60) %>
-
- <% else %>
- --
- <% end %>
- |
-
-
-
- <% if user.phone.present? %>
- <%= user.phone %>
- <% else %>
- --
- <% end %>
- |
-
<% if user.inactive? %>
From 7719a82de6940a53017126176ed6e5c02ca56d28 Mon Sep 17 00:00:00 2001
From: maebeale
Date: Tue, 2 Dec 2025 10:04:48 -0500
Subject: [PATCH 2/9] Move/add all main_image_url declarations out of models
and in to decorators
---
app/decorators/event_decorator.rb | 10 ++++++++++
app/decorators/event_registration_decorator.rb | 4 ++++
app/decorators/resource_decorator.rb | 11 +++++++++++
app/decorators/story_decorator.rb | 10 ++++++++++
app/decorators/story_idea_decorator.rb | 10 ++++++++++
app/decorators/workshop_decorator.rb | 10 ++++++++++
app/decorators/workshop_idea_decorator.rb | 17 +++++++++--------
app/decorators/workshop_variation_decorator.rb | 4 ++++
app/models/report.rb | 10 ++++++++++
app/models/resource.rb | 10 ----------
app/models/workshop.rb | 10 ----------
11 files changed, 78 insertions(+), 28 deletions(-)
diff --git a/app/decorators/event_decorator.rb b/app/decorators/event_decorator.rb
index 362a7f9a7..d50f70015 100644
--- a/app/decorators/event_decorator.rb
+++ b/app/decorators/event_decorator.rb
@@ -138,6 +138,16 @@ def times(display_day: false, display_date: false)
line
end
+ def main_image_url
+ if main_image&.file&.attached?
+ Rails.application.routes.url_helpers.url_for(main_image.file)
+ elsif gallery_images.first&.file&.attached?
+ Rails.application.routes.url_helpers.url_for(gallery_images.first.file)
+ else
+ ActionController::Base.helpers.asset_path("workshop_default_hands.png")
+ end
+ end
+
def breadcrumbs
"#{bookmarks_link} >> #{bookmarkable_link}".html_safe
end
diff --git a/app/decorators/event_registration_decorator.rb b/app/decorators/event_registration_decorator.rb
index f26854858..7574d5c84 100644
--- a/app/decorators/event_registration_decorator.rb
+++ b/app/decorators/event_registration_decorator.rb
@@ -8,4 +8,8 @@ def title
def description
end
+
+ def main_image_url
+ event.decorate.main_image_url
+ end
end
diff --git a/app/decorators/resource_decorator.rb b/app/decorators/resource_decorator.rb
index c1d1f88ed..e216d43ee 100644
--- a/app/decorators/resource_decorator.rb
+++ b/app/decorators/resource_decorator.rb
@@ -10,6 +10,17 @@ def featured_url
url.empty? ? h.resource_path(resource) : url
end
+
+ def main_image_url
+ if main_image&.file&.attached?
+ Rails.application.routes.url_helpers.url_for(main_image.file)
+ elsif gallery_images.first&.file&.attached?
+ Rails.application.routes.url_helpers.url_for(gallery_images.first.file)
+ else
+ ActionController::Base.helpers.asset_path("theme_default.png")
+ end
+ end
+
def truncated_author
h.truncate author, length: 20
end
diff --git a/app/decorators/story_decorator.rb b/app/decorators/story_decorator.rb
index 14caac61a..09ae6aac9 100644
--- a/app/decorators/story_decorator.rb
+++ b/app/decorators/story_decorator.rb
@@ -12,4 +12,14 @@ def inactive?
def workshop_title
workshop&.title || external_workshop_title
end
+
+ def main_image_url
+ if main_image&.file&.attached?
+ Rails.application.routes.url_helpers.url_for(main_image.file)
+ elsif gallery_images.first&.file&.attached?
+ Rails.application.routes.url_helpers.url_for(gallery_images.first.file)
+ else
+ ActionController::Base.helpers.asset_path("theme_default.png")
+ end
+ end
end
diff --git a/app/decorators/story_idea_decorator.rb b/app/decorators/story_idea_decorator.rb
index 06cc2ac39..a91463fb2 100644
--- a/app/decorators/story_idea_decorator.rb
+++ b/app/decorators/story_idea_decorator.rb
@@ -9,4 +9,14 @@ def title
def description
body.truncate(100)
end
+
+ def main_image_url
+ if main_image&.file&.attached?
+ Rails.application.routes.url_helpers.url_for(main_image.file)
+ elsif gallery_images.first&.file&.attached?
+ Rails.application.routes.url_helpers.url_for(gallery_images.first.file)
+ else
+ ActionController::Base.helpers.asset_path("theme_default.png")
+ end
+ end
end
diff --git a/app/decorators/workshop_decorator.rb b/app/decorators/workshop_decorator.rb
index 5cbb438e9..cfba5c735 100644
--- a/app/decorators/workshop_decorator.rb
+++ b/app/decorators/workshop_decorator.rb
@@ -26,6 +26,16 @@ def sector_has_name?(form)
form.object.name
end
+ def main_image_url
+ if main_image&.file&.attached?
+ Rails.application.routes.url_helpers.url_for(main_image.file)
+ elsif gallery_images.first&.file&.attached?
+ Rails.application.routes.url_helpers.url_for(gallery_images.first.file)
+ else
+ ActionController::Base.helpers.asset_path("workshop_default.jpg")
+ end
+ end
+
def breadcrumbs
if title
"#{breadcrumbs_title} >> #{breadcrumb_link} >> Workshop Log".html_safe
diff --git a/app/decorators/workshop_idea_decorator.rb b/app/decorators/workshop_idea_decorator.rb
index 3b1760489..4f230fbf7 100644
--- a/app/decorators/workshop_idea_decorator.rb
+++ b/app/decorators/workshop_idea_decorator.rb
@@ -1,14 +1,15 @@
class WorkshopIdeaDecorator < Draper::Decorator
delegate_all
- # Define presentation-specific methods here. Helpers are accessed through
- # `helpers` (aka `h`). You can override attributes, for example:
- #
- # def created_at
- # helpers.content_tag :span, class: 'time' do
- # object.created_at.strftime("%a %m/%d/%y")
- # end
- # end
+ def main_image_url
+ if main_image&.file&.attached?
+ Rails.application.routes.url_helpers.url_for(main_image.file)
+ elsif gallery_images.first&.file&.attached?
+ Rails.application.routes.url_helpers.url_for(gallery_images.first.file)
+ else
+ ActionController::Base.helpers.asset_path("workshop_default.jpg")
+ end
+ end
def display_spanish_fields
[
diff --git a/app/decorators/workshop_variation_decorator.rb b/app/decorators/workshop_variation_decorator.rb
index 9b7d1f78c..9862ca8a1 100644
--- a/app/decorators/workshop_variation_decorator.rb
+++ b/app/decorators/workshop_variation_decorator.rb
@@ -23,6 +23,10 @@ def display_code
end
end
+ def main_image_url
+ workshop.decorate.main_image_url
+ end
+
private
def method_name
diff --git a/app/models/report.rb b/app/models/report.rb
index 9a04f35ae..eedb6373f 100644
--- a/app/models/report.rb
+++ b/app/models/report.rb
@@ -149,4 +149,14 @@ def set_windows_type
def create_notification
notifications.create(notification_type: 0)
end
+
+ def main_image_url
+ if main_image&.file&.attached?
+ Rails.application.routes.url_helpers.url_for(main_image.file)
+ elsif gallery_images.first&.file&.attached?
+ Rails.application.routes.url_helpers.url_for(gallery_images.first.file)
+ else
+ ActionController::Base.helpers.asset_path("workshop_default.jpg")
+ end
+ end
end
diff --git a/app/models/resource.rb b/app/models/resource.rb
index fafa660e5..5802d20e6 100644
--- a/app/models/resource.rb
+++ b/app/models/resource.rb
@@ -83,16 +83,6 @@ def name
title || id
end
- def main_image_url
- if main_image&.file&.attached?
- Rails.application.routes.url_helpers.url_for(main_image.file)
- elsif gallery_images.first&.file&.attached?
- Rails.application.routes.url_helpers.url_for(gallery_images.first.file)
- else
- ActionController::Base.helpers.asset_path("theme_default.png")
- end
- end
-
def download_attachment
main_image || gallery_images.first || attachments.first
end
diff --git a/app/models/workshop.rb b/app/models/workshop.rb
index 754a03318..0b7464acd 100644
--- a/app/models/workshop.rb
+++ b/app/models/workshop.rb
@@ -151,16 +151,6 @@ def log_count
workshop_logs.size
end
- def main_image_url
- if main_image&.file&.attached?
- Rails.application.routes.url_helpers.url_for(main_image.file)
- elsif gallery_images.first&.file&.attached?
- Rails.application.routes.url_helpers.url_for(gallery_images.first.file)
- else
- ActionController::Base.helpers.asset_path("workshop_default.jpg")
- end
- end
-
def sector_hashtags
sectors.map do |sector|
"\#{sector.name.split(" ")[0].downcase}"
From 301fb13c9269437575228445833e705841556083 Mon Sep 17 00:00:00 2001
From: maebeale
Date: Tue, 2 Dec 2025 10:06:16 -0500
Subject: [PATCH 3/9] Add facilitator show_card partial, and associate
bookmarks to models without it so they'll all work with the card
---
app/models/report.rb | 1 +
app/models/story_idea.rb | 1 +
app/models/workshop_idea.rb | 1 +
app/models/workshop_variation.rb | 1 +
app/views/facilitators/_show_card.html.erb | 53 ++++++++++++++++++++++
5 files changed, 57 insertions(+)
create mode 100644 app/views/facilitators/_show_card.html.erb
diff --git a/app/models/report.rb b/app/models/report.rb
index eedb6373f..773a3e151 100644
--- a/app/models/report.rb
+++ b/app/models/report.rb
@@ -4,6 +4,7 @@ class Report < ApplicationRecord
belongs_to :project
belongs_to :windows_type
has_one :form, as: :owner
+ has_many :bookmarks, as: :bookmarkable, dependent: :destroy
has_many :notifications, as: :noticeable, dependent: :destroy
has_many :quotable_item_quotes, as: :quotable, dependent: :destroy
has_many :report_form_field_answers, dependent: :destroy
diff --git a/app/models/story_idea.rb b/app/models/story_idea.rb
index 6c68202ae..19109cde0 100644
--- a/app/models/story_idea.rb
+++ b/app/models/story_idea.rb
@@ -10,6 +10,7 @@ class StoryIdea < ApplicationRecord
belongs_to :project
belongs_to :windows_type
belongs_to :workshop, optional: true
+ has_many :bookmarks, as: :bookmarkable, dependent: :destroy
has_many :stories
# Image associations
has_one :main_image, -> { where(type: "Images::MainImage") },
diff --git a/app/models/workshop_idea.rb b/app/models/workshop_idea.rb
index bfd5b0537..47affcea0 100644
--- a/app/models/workshop_idea.rb
+++ b/app/models/workshop_idea.rb
@@ -2,6 +2,7 @@ class WorkshopIdea < ApplicationRecord
belongs_to :created_by, class_name: "User"
belongs_to :updated_by, class_name: "User"
belongs_to :windows_type
+ has_many :bookmarks, as: :bookmarkable, dependent: :destroy
has_many :workshops
has_many :workshop_series_children, # When this workshop is the parent in a series
-> { order(:series_order) },
diff --git a/app/models/workshop_variation.rb b/app/models/workshop_variation.rb
index 8bf6dbfe4..f9302bf1e 100644
--- a/app/models/workshop_variation.rb
+++ b/app/models/workshop_variation.rb
@@ -1,6 +1,7 @@
class WorkshopVariation < ApplicationRecord
belongs_to :workshop
belongs_to :created_by, class_name: 'User', optional: true
+ has_many :bookmarks, as: :bookmarkable, dependent: :destroy
# Image associations
has_many :images, as: :owner, dependent: :destroy
has_one :main_image, -> { where(type: "Images::MainImage") },
diff --git a/app/views/facilitators/_show_card.html.erb b/app/views/facilitators/_show_card.html.erb
new file mode 100644
index 000000000..93a3d238a
--- /dev/null
+++ b/app/views/facilitators/_show_card.html.erb
@@ -0,0 +1,53 @@
+<% bg_color ||= "bg-white" %>
+<% record_title ||= record.title %>
+<% title_font_size ||= nil %>
+<% bookmarkable ||= record.object %>
+
+
+
+
+ <%= render "bookmarks/editable_bookmark_icon", resource: bookmarkable %>
+
+
+
+
+
+
+
+
+
+ <%= link_to polymorphic_path(record.object), class: "block w-full h-full" do %>
+ 
+ <% end %>
+
+
+
+
+
+
+ <%= link_to polymorphic_path(record.object),
+ class: "inline-flex min-w-0 max-w-full text-lg font-semibold
+ text-gray-900 leading-tight hover:underline" do %>
+ <%= title_with_badges(record, font_size: title_font_size,
+ record_title: record_title,
+ show_hidden_badge: true).html_safe %>
+ <% end %>
+
+ <%= record.created_at.strftime("%b %d, %Y") %>
+
+
+
+
+
From 10949cf07598b12d64d524a9102714e18872b81b Mon Sep 17 00:00:00 2001
From: maebeale
Date: Tue, 2 Dec 2025 10:06:42 -0500
Subject: [PATCH 4/9] Add workshop_log_decorator (referenced by the
facilitators/_show_card
---
app/decorators/workshop_log_decorator.rb | 13 +++++++++++++
1 file changed, 13 insertions(+)
create mode 100644 app/decorators/workshop_log_decorator.rb
diff --git a/app/decorators/workshop_log_decorator.rb b/app/decorators/workshop_log_decorator.rb
new file mode 100644
index 000000000..5c9c5d488
--- /dev/null
+++ b/app/decorators/workshop_log_decorator.rb
@@ -0,0 +1,13 @@
+class WorkshopLogDecorator < Draper::Decorator
+ delegate_all
+
+ def main_image_url
+ if main_image&.file&.attached?
+ Rails.application.routes.url_helpers.url_for(main_image.file)
+ elsif gallery_images.first&.file&.attached?
+ Rails.application.routes.url_helpers.url_for(gallery_images.first.file)
+ else
+ ActionController::Base.helpers.asset_path("workshop_default.jpg")
+ end
+ end
+end
From 41d8a5d3efab318f609a1d72d3031d3b4c8e12f3 Mon Sep 17 00:00:00 2001
From: maebeale
Date: Tue, 2 Dec 2025 10:07:15 -0500
Subject: [PATCH 5/9] Change name display on facilitator to use its own name
rather than getting from the user
---
app/models/facilitator.rb | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/app/models/facilitator.rb b/app/models/facilitator.rb
index 7b3dbddd1..e2f69a48d 100644
--- a/app/models/facilitator.rb
+++ b/app/models/facilitator.rb
@@ -71,19 +71,19 @@ def sector_list
def name
case display_name_preference
when "full_name"
- user.full_name
+ full_name
when "first_name_last_initial"
- "#{user.first_name} #{user.last_name.first}"
+ "#{first_name} #{last_name.first}"
when "first_name_only"
- user.first_name
+ first_name
when "last_name_only"
- user.last_name
+ last_name
else
- user.full_name
+ full_name
end
end
def full_name
- user.full_name
+ "#{first_name} #{last_name}"
end
end
From 2995c333cc29b0458fe6ffeef12abdef118cb8c5 Mon Sep 17 00:00:00 2001
From: maebeale
Date: Tue, 2 Dec 2025 10:08:13 -0500
Subject: [PATCH 6/9] Add display name methods to workshop_log
---
app/models/workshop_log.rb | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/app/models/workshop_log.rb b/app/models/workshop_log.rb
index b7584add1..4003d489a 100644
--- a/app/models/workshop_log.rb
+++ b/app/models/workshop_log.rb
@@ -76,9 +76,17 @@ def workshop_title
title
end
+ def workshop_name
+ workshop&.title
+ end
+
+ def windows_type_name
+ windows_type&.short_name
+ end
+
def type_title
if windows_type
- "#{windows_type.short_name} #{type}"
+ "#{windows_type_name} #{type}"
else
"#{type}"
end
From df94fb4f5ca4e02f0227579e194c4e8e23ba356a Mon Sep 17 00:00:00 2001
From: maebeale
Date: Tue, 2 Dec 2025 10:10:43 -0500
Subject: [PATCH 7/9] Update title_with_badges signature to accept font_size
and show_hidden_badge instead of admin (since that's more descriptive)
---
app/helpers/application_helper.rb | 87 +++++++++++----------
app/views/community_news/index.html.erb | 2 +-
app/views/events/_card.html.erb | 2 +-
app/views/resources/_resource_card.html.erb | 2 +-
app/views/stories/index.html.erb | 2 +-
app/views/workshops/_index_row.html.erb | 3 +-
6 files changed, 50 insertions(+), 48 deletions(-)
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index bb890db58..de4846299 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -130,53 +130,54 @@ def sortable_field_display_name(name)
end
end
- def title_with_badges(record, admin: false, display_windows_type: false)
- content_tag :div, class: "flex flex-col" do
-
- # ---- BADGE ROW ---------------------------------------------------------
- badge_row = content_tag :div, class: "flex flex-wrap items-center gap-2 mb-1" do
- fragments = []
-
- # Hidden badge
- if admin && record.respond_to?(:inactive?) &&
- record.inactive? && controller_name != "dashboard"
- fragments << content_tag(
- :span,
- content_tag(:i, "", class: "fa-solid fa-eye-slash mr-1") + " Hidden",
- class: "inline-flex items-center px-2 py-0.5 rounded-full
- text-sm font-medium bg-blue-100 text-gray-600 whitespace-nowrap"
- )
- end
-
- # Featured badge
- if record.respond_to?(:featured?) &&
- record.featured? && controller_name != "dashboard"
- fragments << content_tag(
- :span,
- "🌟 Featured",
- class: "inline-flex items-center px-2 py-0.5 rounded-full
- text-sm font-medium bg-yellow-100 text-yellow-800 whitespace-nowrap"
- )
- end
-
- safe_join(fragments)
- end
-
- # ---- TITLE + WINDOWS TYPE ------------------------------------------------
- title_content = record.title.to_s
-
- if display_windows_type && record.respond_to?(:windows_type) && record.windows_type.present?
- title_content += " (#{record.windows_type.short_name})"
- end
+ def title_with_badges(record, font_size: "text-lg", record_title: nil,
+ show_hidden_badge: false, display_windows_type: false)
+ fragments = []
+
+ # --- Hidden badge ---
+ if show_hidden_badge && record.respond_to?(:inactive?) &&
+ record.inactive? && controller_name != "dashboard"
+ fragments << content_tag(
+ :span,
+ content_tag(:i, "", class: "fa-solid fa-eye-slash mr-1") + " Hidden",
+ class: "inline-flex items-center px-2 py-0.5 rounded-full
+ text-sm font-medium bg-blue-100 text-gray-600 whitespace-nowrap"
+ )
+ end
- title_row = content_tag(
+ # --- Featured badge ---
+ if record.respond_to?(:featured?) && record.featured? && controller_name != "dashboard"
+ fragments << content_tag(
:span,
- title_content.html_safe,
- class: "text-lg font-semibold text-gray-900 leading-tight"
+ "🌟 Dashboard Feature",
+ class: "inline-flex items-center px-2 py-0.5 rounded-full
+ text-sm font-medium bg-yellow-100 text-yellow-800 whitespace-nowrap"
)
+ end
+
+ title_content = record_title.presence || record.title.to_s
+
+ if display_windows_type && record.respond_to?(:windows_type) && record.windows_type.present?
+ title_content += " (#{record.windows_type.short_name})"
+ end
- # Combine badge row + title row
- safe_join([badge_row, title_row])
+ title_row = content_tag(
+ :span,
+ title_content.html_safe,
+ class: "#{font_size} font-semibold text-gray-900 leading-tight"
+ )
+
+ # ---- Combine rows intelligently ----
+ if fragments.any?
+ content_tag :div, class: "flex flex-col" do
+ safe_join([
+ content_tag(:div, safe_join(fragments), class: "flex flex-wrap items-center gap-2 mb-1"),
+ title_row
+ ])
+ end
+ else
+ # No badges: just return the title with no empty div wrapper
+ title_row
end
end
diff --git a/app/views/community_news/index.html.erb b/app/views/community_news/index.html.erb
index e15f06b3c..94295ea80 100644
--- a/app/views/community_news/index.html.erb
+++ b/app/views/community_news/index.html.erb
@@ -52,7 +52,7 @@
- <%= link_to title_with_badges(news, admin: current_user.super_user?).html_safe,
+ <%= link_to title_with_badges(news, show_hidden_badge: current_user.super_user?).html_safe,
community_news_path(news),
class: "font-bold hover:text-indigo-800 hover:underline" %>
diff --git a/app/views/events/_card.html.erb b/app/views/events/_card.html.erb
index e07347e30..99821b561 100644
--- a/app/views/events/_card.html.erb
+++ b/app/views/events/_card.html.erb
@@ -34,7 +34,7 @@
<%= link_to event_path(event),
class: "hover:underline block leading-tight",
data: { turbo: false } do %>
- <%= title_with_badges(event, admin: current_user.super_user?).html_safe %>
+ <%= title_with_badges(event, show_hidden_badge: current_user.super_user?).html_safe %>
<% end %>
diff --git a/app/views/resources/_resource_card.html.erb b/app/views/resources/_resource_card.html.erb
index eec4dca3d..94af3ca45 100644
--- a/app/views/resources/_resource_card.html.erb
+++ b/app/views/resources/_resource_card.html.erb
@@ -50,7 +50,7 @@
<%= link_to resource_path(resource.object),
class: "inline-flex min-w-0 max-w-full text-lg font-semibold
text-gray-900 leading-tight hover:underline" do %>
- <%= title_with_badges(resource, admin: current_user.super_user?).html_safe %>
+ <%= title_with_badges(resource, show_hidden_badge: current_user.super_user?).html_safe %>
<% end %>
diff --git a/app/views/stories/index.html.erb b/app/views/stories/index.html.erb
index 1b357cdbd..b0c64734d 100644
--- a/app/views/stories/index.html.erb
+++ b/app/views/stories/index.html.erb
@@ -54,7 +54,7 @@
- <%= link_to title_with_badges(story, admin: current_user.super_user?).html_safe,
+ <%= link_to title_with_badges(story, show_hidden_badge: current_user.super_user?).html_safe,
story_path(story),
class: "font-bold hover:text-indigo-800 hover:underline" %>
diff --git a/app/views/workshops/_index_row.html.erb b/app/views/workshops/_index_row.html.erb
index 0a797923a..5918cc5b0 100644
--- a/app/views/workshops/_index_row.html.erb
+++ b/app/views/workshops/_index_row.html.erb
@@ -46,7 +46,8 @@
<%= link_to link_route,
class: "hover:underline block",
data: { turbo: false } do %>
- <%= title_with_badges(workshop, admin: current_user.super_user?, display_windows_type: true).html_safe %>
+ <%= title_with_badges(workshop, show_hidden_badge: current_user.super_user?,
+ display_windows_type: true).html_safe %>
<% end %>
From edb010dc74d0847ea5e6d0c7d74b753db113a67d Mon Sep 17 00:00:00 2001
From: maebeale
Date: Tue, 2 Dec 2025 10:34:08 -0500
Subject: [PATCH 8/9] Change show section header from Authored content to
Published content
---
app/views/facilitators/show.html.erb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/views/facilitators/show.html.erb b/app/views/facilitators/show.html.erb
index 797974ba6..243d5369b 100644
--- a/app/views/facilitators/show.html.erb
+++ b/app/views/facilitators/show.html.erb
@@ -137,7 +137,7 @@
From bdc1df266a1251edf194b16c46cedcd936acd543 Mon Sep 17 00:00:00 2001
From: maebeale
Date: Tue, 2 Dec 2025 11:02:46 -0500
Subject: [PATCH 9/9] Update facilitator and user specs to correctly
cross-reference
---
spec/factories/users.rb | 4 +
spec/models/facilitator_spec.rb | 3 +-
.../views/facilitators/index.html.erb_spec.rb | 7 +-
spec/views/facilitators/show.html.erb_spec.rb | 7 +-
spec/views/users/index.html.erb_spec.rb | 86 ++++++++++++++++---
5 files changed, 85 insertions(+), 22 deletions(-)
diff --git a/spec/factories/users.rb b/spec/factories/users.rb
index a1c41add5..845a5134b 100644
--- a/spec/factories/users.rb
+++ b/spec/factories/users.rb
@@ -46,6 +46,10 @@
super_user { true }
end
+ trait :with_facilitator do
+ facilitator { association :facilitator, user: instance }
+ end
+
trait :orphaned_reports do
email { "orphaned_reports@awbw.org" }
super_user { true }
diff --git a/spec/models/facilitator_spec.rb b/spec/models/facilitator_spec.rb
index b75e35532..e8dde26d1 100644
--- a/spec/models/facilitator_spec.rb
+++ b/spec/models/facilitator_spec.rb
@@ -11,8 +11,7 @@
end
describe "#name" do
- let(:user) { build(:user, first_name: "Jane", last_name: "Doe") }
- let(:facilitator) { build(:facilitator, user: user) }
+ let(:facilitator) { build(:facilitator, first_name: "Jane", last_name: "Doe") }
context "when display_name_preference is full_name" do
it "returns the full name" do
diff --git a/spec/views/facilitators/index.html.erb_spec.rb b/spec/views/facilitators/index.html.erb_spec.rb
index f176ef114..be5cfa0d4 100644
--- a/spec/views/facilitators/index.html.erb_spec.rb
+++ b/spec/views/facilitators/index.html.erb_spec.rb
@@ -1,7 +1,6 @@
require 'rails_helper'
RSpec.describe "facilitators/index", type: :view do
- let(:user) { create(:user) }
let(:admin) { create(:user, :admin) }
let(:facilitator) { create(:facilitator)}
@@ -9,12 +8,12 @@
before(:each) do
assign(:facilitators, paginated([facilitator, facilitator_2]))
- allow(view).to receive(:current_user).and_return(user)
+ allow(view).to receive(:current_user).and_return(admin)
end
it "renders a list of facilitators" do
render
- expect(rendered).to match(facilitator.user.first_name)
- expect(rendered).to match(facilitator_2.user.first_name)
+ expect(rendered).to match(facilitator.first_name)
+ expect(rendered).to match(facilitator_2.first_name)
end
end
diff --git a/spec/views/facilitators/show.html.erb_spec.rb b/spec/views/facilitators/show.html.erb_spec.rb
index f97aeadcd..9a6270168 100644
--- a/spec/views/facilitators/show.html.erb_spec.rb
+++ b/spec/views/facilitators/show.html.erb_spec.rb
@@ -1,20 +1,19 @@
require 'rails_helper'
RSpec.describe "facilitators/show", type: :view do
- let(:user) { create(:user) }
let(:admin) { create(:user, :admin) }
let(:facilitator) { create(:facilitator)}
before do
assign(:facilitator, facilitator.decorate)
- allow(view).to receive(:current_user).and_return(user)
+ allow(view).to receive(:current_user).and_return(admin)
render
end
it "renders attributes" do
- expect(rendered).to match(facilitator.user.first_name)
- expect(rendered).to match(facilitator.user.last_name)
+ expect(rendered).to match(facilitator.first_name)
+ expect(rendered).to match(facilitator.last_name)
expect(rendered).to match(facilitator.user.email)
end
end
diff --git a/spec/views/users/index.html.erb_spec.rb b/spec/views/users/index.html.erb_spec.rb
index e2b2be735..f13bebf7a 100644
--- a/spec/views/users/index.html.erb_spec.rb
+++ b/spec/views/users/index.html.erb_spec.rb
@@ -1,21 +1,83 @@
-require 'rails_helper'
+require "rails_helper"
RSpec.describe "users/index", type: :view do
- let(:admin_user) { create(:user, :admin) } # or super_user trait
+ let(:admin_user) { create(:user, :admin) }
- before(:each) do
- allow(view).to receive(:current_user).and_return(admin_user) # Stub current_user for Devise
- users = create_list(:user, 3, first_name: "Alice")
- paginated_users = WillPaginate::Collection.create(1, 10, users.size) do |pager|
- pager.replace(users)
+ before do
+ allow(view).to receive(:current_user).and_return(admin_user)
+ end
+
+ context "when users have facilitators" do
+ before do
+ @users = create_list(:user, 2, :with_facilitator) # Factory should build facilitator + avatar if needed
+
+ paginated = WillPaginate::Collection.create(1, 10, @users.size) do |pager|
+ pager.replace(@users)
+ end
+
+ assign(:users, paginated)
+ assign(:users_count, @users.size)
+ end
+
+ it "renders facilitator profile buttons instead of 'Create facilitator'" do
+ render
+
+ # Two rows
+ expect(rendered).to have_selector("table tbody tr", count: 2)
+
+ @users.each do |user|
+ facilitator = user.facilitator
+
+ # The helper output (button) must appear
+ expect(rendered).to include(facilitator.name)
+
+ # Should NOT show "Create facilitator"
+ expect(rendered).not_to include("Create facilitator")
+ end
end
- assign(:users, paginated_users)
end
- it "renders a list of users" do
- render
+ context "when a user has NO facilitator" do
+ let!(:user_without_facilitator) { create(:user) }
+
+ before do
+ paginated = WillPaginate::Collection.create(1, 10, 1) do |pager|
+ pager.replace([user_without_facilitator])
+ end
- assert_select "table tbody tr", count: 3
- assert_select "table tbody tr td", text: /Alice/
+ assign(:users, paginated)
+ assign(:users_count, 1)
+ end
+
+ it "shows 'Create facilitator' button" do
+ render
+
+ expect(rendered).to include("Create facilitator")
+ expect(rendered).to have_link(
+ "Create facilitator",
+ href: new_facilitator_path(user_id: user_without_facilitator.id)
+ )
+ end
+ end
+
+ context "general index behavior" do
+ before do
+ users = create_list(:user, 3)
+
+ paginated = WillPaginate::Collection.create(1, 10, users.size) do |pager|
+ pager.replace(users)
+ end
+
+ assign(:users, paginated)
+ assign(:users_count, users.size)
+ end
+
+ it "renders correct table structure" do
+ render
+
+ expect(rendered).to have_selector("table thead tr th", text: "Name")
+ expect(rendered).to have_selector("table thead tr th", text: "Email")
+ expect(rendered).to have_selector("table tbody tr", count: 3)
+ end
end
end
|