Workshops authored
+ <% if @facilitator.user.workshops.any? %> +No workshops authored yet.
+ <% end %> +diff --git a/app/controllers/facilitators_controller.rb b/app/controllers/facilitators_controller.rb index a8d78163c..137434bc9 100644 --- a/app/controllers/facilitators_controller.rb +++ b/app/controllers/facilitators_controller.rb @@ -13,7 +13,7 @@ def index facilitators = Facilitator .searchable .search_by_params(params.to_unsafe_h) - .joins(:user) + .includes(:user).references(:user) .order(:first_name, :last_name) @facilitators_count = facilitators.size @facilitators = facilitators.paginate(page: params[:page], per_page: per_page) @@ -80,6 +80,7 @@ def set_form_variables end end @facilitator.build_user if @facilitator.user.blank? # Build a fresh one if missing + @facilitator.build_avatar_image if @facilitator.avatar_image.blank? @facilitator.user.project_users.first || @facilitator.user.project_users.build projects = if current_user.super_user? @@ -93,9 +94,13 @@ def set_form_variables # Only allow a list of trusted parameters through. def facilitator_params params.require(:facilitator).permit( - :first_name, :last_name, :primary_email_address, :primary_email_address_type, + :first_name, :last_name, + :primary_email_address, :primary_email_address_type, :street_address, :city, :state, :zip, :country, :mailing_address_type, - :phone_number, :phone_number_type,:bio, :created_by_id, :updated_by_id, + :phone_number, :phone_number_type, + :created_by_id, :updated_by_id, + :bio, + :display_name_preference, :pronouns, :profile_show_name_preference, :profile_is_searchable, @@ -142,7 +147,14 @@ def facilitator_params :state2, :zip2, :notes, - project_users_attributes: [:id, :project_id, :position, :inactive, :_destroy] + project_users_attributes: [ + :id, + :project_id, + :position, + :title, + :inactive, + :_destroy + ] ], ) end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 90ce32789..e5fef04f5 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -113,6 +113,8 @@ def set_user end def set_form_variables + @facilitator = @user.facilitator || + Facilitator.where(id: params[:facilitator_id]).first if params[:facilitator_id].present? @user.project_users.first || @user.project_users.build projects = if current_user.super_user? Project.active @@ -139,7 +141,7 @@ def user_params :agency_id, :facilitator_id, :created_by_id, :updated_by_id, :confirmed, :inactive, :super_user, :legacy, :legacy_id, avatar_image_attributes: [:id, :file, :_destroy], - project_users_attributes: [:id, :project_id, :position, :inactive, :_destroy] + project_users_attributes: [:id, :project_id, :position, :title, :inactive, :_destroy] ) end end 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/facilitator_decorator.rb b/app/decorators/facilitator_decorator.rb index f04ee9ca5..ced2dc5a9 100644 --- a/app/decorators/facilitator_decorator.rb +++ b/app/decorators/facilitator_decorator.rb @@ -44,7 +44,7 @@ def badges badges << ["Legacy Facilitator (10+ years)", "yellow"] if years >= 10 badges << ["Seasoned Facilitator (3-10 years)", "gray"] if member_since.present? && years >= 3 badges << ["New Facilitator (<3 years)", "green"] if member_since.present? && years < 3 - badges << ["Spotlighted Facilitator", "gray"] if true || stories_as_spotlighted_facilitator + badges << ["Spotlighted Facilitator", "gray"] if stories_as_spotlighted_facilitator badges << ["Events Attended", "blue"] if user.events.any? badges << ["Workshop Author", "indigo"] if user.workshops.any? # indigo badges << ["Story Author", "rose"] if user.stories_as_creator.any? # pink 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_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 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/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/helpers/facilitator_helper.rb b/app/helpers/facilitator_helper.rb new file mode 100644 index 000000000..dce10615b --- /dev/null +++ b/app/helpers/facilitator_helper.rb @@ -0,0 +1,27 @@ +module FacilitatorHelper + + def facilitator_profile_button(facilitator, size: 10) + link_to facilitator_path(facilitator), + class: "btn btn-secondary-outline flex items-center gap-3 px-4 py-2 rounded-lg" do + + facilitator = facilitator.decorate + avatar = if facilitator.avatar_image.present? + image_tag url_for(facilitator.avatar_image.file), + class: "w-10 h-10 rounded-full object-cover border border-gray-300 shadow-sm" + else + image_tag "missing.png", + class: "w-10 h-10 rounded-full object-cover border border-dashed border-gray-300" + end + + name = content_tag(:span, facilitator.name, class: "font-semibold text-gray-900") + + pronouns = if facilitator.pronouns_display.present? + content_tag(:span, facilitator.pronouns_display, + class: "text-xs text-gray-500 italic") + end + + avatar + content_tag(:div, name + (pronouns || "").html_safe, + class: "flex flex-col leading-tight text-left") + end + end +end diff --git a/app/models/facilitator.rb b/app/models/facilitator.rb index c0179d606..e2f69a48d 100644 --- a/app/models/facilitator.rb +++ b/app/models/facilitator.rb @@ -6,6 +6,9 @@ class Facilitator < ApplicationRecord has_many :sectors, through: :sectorable_items has_many :stories_as_spotlighted_facilitator, inverse_of: :spotlighted_facilitator, class_name: "Story", dependent: :restrict_with_error + # has_many through + has_many :event_registrations, through: :user + # Image associations has_one :avatar_image, -> { where(type: "Images::SquareImage") }, as: :owner, class_name: "Images::SquareImage", @@ -68,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 diff --git a/app/models/report.rb b/app/models/report.rb index 9a04f35ae..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 @@ -149,4 +150,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/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/user.rb b/app/models/user.rb index 9b66dad31..6c48aa08b 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -43,7 +43,7 @@ class User < ApplicationRecord # Nested attributes accepts_nested_attributes_for :user_forms accepts_nested_attributes_for :project_users, allow_destroy: true, - reject_if: proc { |attrs| attrs["organization_id"].blank? } + reject_if: proc { |attrs| attrs["project_id"].blank? || attrs["title"].blank? } # Validations validates :first_name, :last_name, presence: true 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}" 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_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 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/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/facilitators/_form.html.erb b/app/views/facilitators/_form.html.erb index 0f8243365..44238ef71 100644 --- a/app/views/facilitators/_form.html.erb +++ b/app/views/facilitators/_form.html.erb @@ -19,17 +19,12 @@ <%= u.object.email %>
Only - <%= current_user.super_user? && u.object.persisted? ? (link_to "editable by admins", edit_user_path(u.object)) : "editable by admins" %>
+ <%= current_user.super_user? && + u.object.persisted? ? (link_to "editable by admins", + edit_user_path(u.object)) : "editable by admins" %> -| Avatar | Name | Facilitator since | Sector(s) | @@ -37,27 +36,8 @@ <% @facilitators.each do |facilitator| %> <% facilitator = facilitator.decorate %>|||||||
|---|---|---|---|---|---|---|---|---|---|---|
| - <% if facilitator.user.avatar.present? %> - <%= link_to (image_tag url_for(facilitator.user.avatar), - class: "w-10 h-10 rounded-full object-cover - border border-gray-300 shadow-sm mx-auto").html_safe, - facilitator_path(facilitator) %> - <% else %> - <%= link_to (image_tag "missing.png", - class: "w-10 h-10 rounded-full object-cover - border border-dashed border-gray-300 mx-auto").html_safe, - facilitator_path(facilitator) %> - <% end %> - | - - -- <% facilitator_name = "#{ facilitator.name }" + - "#{ " (#{facilitator.pronouns_display})" if facilitator.pronouns_display.present? }" %> - <%= link_to facilitator_name.html_safe, - facilitator_path(facilitator) %> + | + <%= facilitator_profile_button(facilitator) %> | @@ -71,7 +51,7 @@ | - <% if facilitator.user.projects.any? %> + <% if facilitator.user&.projects&.any? %> <% user_project_names = facilitator.user.projects.map(&:name).join(", ") %> <%= truncate(user_project_names, length: 120) %> @@ -88,10 +68,12 @@ | - <%= link_to "Profile", facilitator_path(facilitator), - class: "btn btn-secondary-outline" %> - <%= link_to "Edit", edit_facilitator_path(facilitator), - class: "admin-only bg-blue-100 btn btn-secondary-outline" if current_user.super_user %> + <% if current_user.super_user? %> + <%= link_to "User", user_path(facilitator.user), + class: "admin-only bg-blue-100 btn btn-secondary-outline" if facilitator.user %> + <%= link_to "Edit", edit_facilitator_path(facilitator), + class: "admin-only bg-blue-100 btn btn-secondary-outline" %> + <% end %> |
| Avatar | -First Name | -Last Name | +Name | Organization(s) | -Phone | -Inactive | +No access? | Super User | Actions | |
|---|---|---|---|---|---|---|---|---|---|---|
| - <% 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? %> 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 %> 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 |