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" %>

-
- <%= u.input :phone %> - <%= u.input :phone2 %> - <%= u.input :phone3 %> - <%= u.input :best_time_to_call %> -
-
<%= f.input :pronouns %> <%= u.input :birthday, @@ -67,6 +62,18 @@
+
+

Phones

+
+
+ <%= u.input :phone %> + <%= u.input :phone2 %> + <%= u.input :phone3 %> + <%= u.input :best_time_to_call %> +
+
+
+
@@ -75,12 +82,14 @@
-

Work Address

-
- <%= f.input :street_address, label: 'Street', as: :text, input_html: { rows: 1 } %> - <%= f.input :city, as: :text, input_html: { rows: 1 } %> - <%= f.input :state %> - <%= f.input :zip %> +

Work address

+
+
+ <%= f.input :street_address, label: 'Street', as: :text, input_html: { rows: 1 } %> + <%= f.input :city, as: :text, input_html: { rows: 1 } %> + <%= f.input :state %> + <%= f.input :zip %> +
@@ -99,25 +108,35 @@
- Organization affiliations + Organizational affiliations (only editable by admins)
- <%= u.fields_for :project_users do |project_user_form| %> - <%= render "project_user_fields", - f: project_user_form, - projects: u.object.projects, - user: u.object %> - <% end %> + <% if false && current_user.super_user? %> +
+ <%= u.fields_for :project_users do |project_user_form| %> + <%= render "project_user_fields", + f: project_user_form, + projects: u.object.projects, + user: u.object %> + <% end %> - <% if current_user.super_user? %> -
- <%= link_to_add_association "âž• Add Role", - u, - :project_users, - html_options: { locals: { projects: u.object.projects } }, - class: "btn btn-secondary-outline" %> +
+ <%= link_to_add_association "âž• Add Role", + u, + :project_users, + html_options: { locals: { projects: u.object.projects } }, + class: "btn btn-secondary-outline" %> +
+ <% else %> + <% f.object.user && f.object.user.project_users.each do |pu| %> +
+
  • <%= pu.title || pu.position %> - <%= pu.persisted? ? (link_to pu.project&.name, + project_path(pu.project), + class: "underline") : pu.project&.name %>
  • +
    + <% end %> <% end %>
    @@ -159,41 +178,78 @@ hint: "Maximum 250 characters" %>
    -
    - <%= f.input :linked_in_url, as: :text, input_html: { rows: 1 } %> - <%= f.input :facebook_url, as: :text, input_html: { rows: 1 } %> - <%= f.input :instagram_url, as: :text, input_html: { rows: 1 } %> - <%= f.input :youtube_url, as: :text, input_html: { rows: 1 } %> - <%= f.input :twitter_url, as: :text, input_html: { rows: 1 } %> +
    +
    + Social media links: +
    +
    +
    + <%= f.input :linked_in_url, as: :text, input_html: { rows: 1 } %> + <%= f.input :facebook_url, as: :text, input_html: { rows: 1 } %> + <%= f.input :instagram_url, as: :text, input_html: { rows: 1 } %> + <%= f.input :youtube_url, as: :text, input_html: { rows: 1 } %> + <%= f.input :twitter_url, as: :text, input_html: { rows: 1 } %> +
    +
    - - Set your Profile preferences: - -
    - <%= f.input :profile_is_searchable, - hint: "Display in facilitators index" %> - <%= f.input :display_name_preference, - as: :select, - collection: [ - ["First and Last Name", "full_name"], - ["First Name and Last Initial", "first_name_last_initial"], - ["First Name Only", "first_name_only"], - ["Last Name Only", "last_name_only"] - ], - selected: f.object.display_name_preference || "full_name" %> - <%= f.input :profile_show_pronouns %> - <%= f.input :profile_show_member_since %> - <%= f.input :profile_show_bio %> -
    -
    - <%= f.input :profile_show_social_media %> - <%= f.input :profile_show_affiliations %> - <%= f.input :profile_show_sectors %> - <%= f.input :profile_show_email %> - <%= f.input :profile_show_phone %> +
    +
    + Profile display preferences: +
    + +
    +
    +
    + <%= f.input :profile_is_searchable, + hint: ("Findable on " + (link_to "facilitators index", + facilitators_path, + class: "underline")).html_safe %> + + <%= f.input :display_name_preference, + as: :select, + collection: [ + ["First and Last Name", "full_name"], + ["First Name and Last Initial", "first_name_last_initial"], + ["First Name Only", "first_name_only"], + ["Last Name Only", "last_name_only"] + ], + selected: f.object.display_name_preference || "full_name" %> + + <%= f.input :profile_show_pronouns, label: "Show pronouns" %> +
    + +
    + <%= f.input :profile_show_email, label: "Show email" %> + <%= f.input :profile_show_phone, label: "Show phone" %> + <%= f.input :profile_show_social_media, label: "Show social media" %> +
    + +
    + <%= f.input :profile_show_member_since, label: "Show facilitator since" %> + <%= f.input :profile_show_bio, label: "Show bio" %> + <%= f.input :profile_show_affiliations, label: "Show affiliations" %> + <%= f.input :profile_show_sectors, label: "Show sectors" %> +
    + +
    + <%= f.input :profile_show_workshops, label: "Show workshops" %> + <%= f.input :profile_show_workshop_variations, label: "Show workshop variations" %> + <%= f.input :profile_show_stories, label: "Show stories" %> + <%= f.input :profile_show_events_registered, label: "Show participation" %> +
    + + +
    + <%= f.input :profile_show_workshop_ideas, label: "Show workshop ideas" %> + <%= f.input :profile_show_story_ideas, label: "Show story ideas" %> + <%= f.input :profile_show_workshop_logs, label: "Show workshop logs" %> +
    +
    +
    +
    <% if @facilitator.persisted? && current_user.super_user? %> diff --git a/app/views/facilitators/_project_user_fields.html.erb b/app/views/facilitators/_project_user_fields.html.erb index 40ed3c69f..f9b50287d 100644 --- a/app/views/facilitators/_project_user_fields.html.erb +++ b/app/views/facilitators/_project_user_fields.html.erb @@ -41,4 +41,3 @@
  • <%= f.object.project&.name %> (<%= f.object.title || f.object.position %>)
  • <% end %> - 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 %> + <%= record_title.truncate(25) %> + <% 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") %> +
    +
    +
    +
    +
    diff --git a/app/views/facilitators/_social_media_buttons.html.erb b/app/views/facilitators/_social_media_buttons.html.erb index 88db2c5b8..bf7ec9740 100644 --- a/app/views/facilitators/_social_media_buttons.html.erb +++ b/app/views/facilitators/_social_media_buttons.html.erb @@ -1,7 +1,7 @@ <%# app/views/facilitators/_social_links.html.erb %> <% return if facilitator.blank? %> -
    +
    <% if facilitator.linked_in_url.present? %> <%= link_to facilitator.linked_in_url, target: "_blank", rel: "noopener", class: "group inline-flex items-center justify-center w-6 h-6 diff --git a/app/views/facilitators/edit.html.erb b/app/views/facilitators/edit.html.erb index 48593699e..9889d4f14 100644 --- a/app/views/facilitators/edit.html.erb +++ b/app/views/facilitators/edit.html.erb @@ -9,6 +9,15 @@ change_password_path, class: "btn btn-secondary-outline" %> <% end %> + <% if @facilitator.user %> + <%= link_to "User account", + edit_user_path(@facilitator.user), + class: "admin-only bg-blue-100 btn btn-secondary-outline" %> + <% else %> + <%= link_to "Create user account", + new_user_path(facilitator_id: @facilitator.id), + class: "admin-only bg-blue-100 btn btn-secondary-outline" %> + <% end %> <%= link_to "Profile", facilitator_path(@facilitator), class: "btn btn-secondary-outline" %> diff --git a/app/views/facilitators/index.html.erb b/app/views/facilitators/index.html.erb index 056fc974c..255f53834 100644 --- a/app/views/facilitators/index.html.erb +++ b/app/views/facilitators/index.html.erb @@ -23,7 +23,6 @@ - @@ -37,27 +36,8 @@ <% @facilitators.each do |facilitator| %> <% facilitator = facilitator.decorate %> - - - - - <% end %> diff --git a/app/views/facilitators/show.html.erb b/app/views/facilitators/show.html.erb index 95c377d5b..243d5369b 100644 --- a/app/views/facilitators/show.html.erb +++ b/app/views/facilitators/show.html.erb @@ -6,7 +6,7 @@ <%= link_to "Facilitators", facilitators_path, class: "btn btn-secondary-outline mr-2" %> <% if current_user.super_user? || current_user == @facilitator.user %> <%= link_to "Edit", edit_facilitator_path(@facilitator), - class: "admin-only bg-green-100 btn btn-primary-outline" %> + class: "admin-only bg-green-50 btn btn-primary-outline" %> <% end %> @@ -64,16 +64,16 @@ <% if @facilitator.profile_show_affiliations? %>
    -

    Organization affiliations

    +

    Organizational affiliations

    <% if @facilitator.user.project_users.active.any? %>
      <% @facilitator.user.project_users.active.each do |pu| %>
    • + <% if pu.title.present? || pu.position.present? %> + <%= pu.title.presence || pu.position.humanize %> - + <% end %> <%= link_to pu.project.name, authenticated_root_path(pu.project), class: "text-blue-600 hover:underline font-medium" %> - <% if pu.position.present? %> - – <%= pu.title.presence || pu.position.humanize %> - <% end %>
    • <% end %>
    @@ -128,113 +128,183 @@
    <% end %> - - <% if @facilitator.profile_show_workshops? %> -
    -

    Workshops authored

    - <% if @facilitator.user.workshops.any? %> - <% @facilitator.user.workshops.each do |workshop| %> - <%= link_to workshop.name, workshop_path(workshop), class: "btn btn-secondary-outline" %> - <% end %> - <% else %> -

    No workshops authored yet.

    - <% end %> + + + <% if @facilitator.profile_show_workshops? || + @facilitator.profile_show_workshop_variations? || + @facilitator.profile_show_stories? %> +
    + +
    +

    + Published content +

    - <% end %> - - <% if @facilitator.profile_show_workshop_variations? %> -
    -

    Workshop Variations authored

    - <% if @facilitator.user.workshop_variations_as_creator.any? %> - <% @facilitator.user.workshop_variations_as_creator.each do |workshop_variation| %> - <%= link_to workshop_variation.name, workshop_variation_path(workshop_variation), - class: "btn btn-secondary-outline" %> - <% end %> - <% else %> -

    No workshop variations submitted yet.

    + +
    + + <% if @facilitator.profile_show_workshops? %> +
    +

    Workshops authored

    + <% if @facilitator.user.workshops.any? %> +
    + <% @facilitator.user.workshops.order(created_at: :desc).each do |workshop| %> + <%= render "show_card", record: workshop.decorate, title_font_size: "text-sm" %> + <% end %> +
    + <% else %> +

    No workshops authored yet.

    + <% end %> +
    <% end %> -
    - <% end %> - - <% if @facilitator.profile_show_stories? %> -
    -

    Stories authored/featured

    - <% stories = @facilitator.user.stories_as_creator + @facilitator.stories_as_spotlighted_facilitator %> - <% if stories.any? %> - <% stories.each do |story| %> - <%= link_to story.title, story_path(story), class: "btn btn-secondary-outline" %> - <% end %> - <% else %> -

    No stories yet.

    + + <% if @facilitator.profile_show_workshop_variations? %> +
    +

    Workshop variations authored

    + <% if @facilitator.user.workshop_variations_as_creator.any? %> +
    + <% @facilitator.user.workshop_variations_as_creator.order(created_at: :desc).each do |workshop_variation| %> + <%= render "show_card", + record_title: "#{workshop_variation.name}
    " + + "WORKSHOP: #{workshop_variation.workshop.name}", + record: workshop_variation.decorate, title_font_size: "text-sm" %> + <% end %> +
    + <% else %> +

    No workshop variations submitted yet.

    + <% end %> +
    + <% end %> + + + <% if @facilitator.profile_show_stories? %> +
    +

    Stories authored/featured

    + <% stories = Story.where(id: @facilitator.user.stories_as_creator.pluck(:id) + + @facilitator.stories_as_spotlighted_facilitator.pluck(:id)) %> + <% if stories.any? %> +
    + <% stories.order(created_at: :desc).each do |story| %> + <%= render "show_card", record: story.decorate, title_font_size: "text-sm" %> + <% end %> +
    + <% else %> +

    No stories yet.

    + <% end %> +
    <% end %>
    +
    <% end %> - + <% if @facilitator.profile_show_events_registered? %> -
    -

    Events registered

    - <% if Event.all.any? %> - <% Event.all.each do |event| %> - <% event_name = "#{event.title} - #{event.start_date.strftime("%b %Y") rescue nil}" %> - <%= link_to event_name, event_path(event), class: "btn btn-secondary-outline" %> - <% end %> - <% else %> -

    No events recorded.

    +
    + +
    +

    + Participation history +

    +
    + + +
    + <% if @facilitator.profile_show_events_registered? %> +
    +

    Events registered

    + <% if @facilitator.event_registrations.any? %> +
    + <% @facilitator.event_registrations.includes(:event).order("events.start_date DESC").each do |event_registration| %> + <%= render "show_card", + bookmarkable: event_registration.event, + record_title: "#{event_registration.event.title}
    " + + "TIME: " + + "#{event_registration.event.decorate.times}", + record: event_registration.decorate, title_font_size: "text-sm" %> + <% end %> +
    + <% else %> +

    No events recorded.

    + <% end %> +
    <% end %>
    +
    <% end %> -
    + <% if current_user.super_user || current_user == @facilitator.user %> -
    - - <% if @facilitator.profile_show_workshop_ideas? %> -
    -

    Workshop Ideas submitted

    - <% if @facilitator.user.workshop_ideas_as_creator.any? %> - <% @facilitator.user.workshop_ideas_as_creator.each do |idea| %> - <%= link_to idea.title, workshop_idea_path(idea), class: "btn btn-secondary-outline" %> - <% end %> - <% else %> -

    No ideas submitted yet.

    - <% end %> +
    + +
    +

    + Submitted content +

    + + Only visible to you +
    - <% end %> - - <% if @facilitator.profile_show_story_ideas? %> -
    -

    Story Ideas submitted

    - <% if @facilitator.user.story_ideas_as_creator.any? %> - <% @facilitator.user.story_ideas_as_creator.each do |story_idea| %> - <%= link_to story_idea.full_name, story_idea_path(story_idea), - class: "btn btn-secondary-outline" %> - <% end %> - <% else %> -

    No story ideas yet.

    + +
    + + <% if @facilitator.profile_show_workshop_ideas? %> +
    +

    Workshop ideas submitted

    + <% if @facilitator.user.workshop_ideas_as_creator.any? %> +
    + <% @facilitator.user.workshop_ideas_as_creator.order(created_at: :desc).each do |idea| %> + <%= render "show_card", + record: idea.decorate, title_font_size: "text-sm" %> + <% end %> +
    + <% else %> +

    No ideas submitted yet.

    + <% end %> +
    <% end %> -
    - <% end %> - - <% if @facilitator.profile_show_workshop_logs? %> -
    -

    Workshop Logs submitted

    - <% if @facilitator.user.workshop_logs.any? %> - <% @facilitator.user.workshop_logs.order(date: :desc, created_at: :desc).each do |workshop_log| %> - <%= link_to workshop_log.full_name, - workshop_log_path(workshop_log), class: "btn btn-secondary-outline" %> - <% end %> - <% else %> -

    No workshops logged yet.

    + + <% if @facilitator.profile_show_story_ideas? %> +
    +

    Story ideas submitted

    + <% if @facilitator.user.story_ideas_as_creator.any? %> +
    + <% @facilitator.user.story_ideas_as_creator.order(created_at: :desc).each do |story_idea| %> + <%= render "show_card", + record_title: story_idea.workshop_title, + record: story_idea.decorate, title_font_size: "text-sm" %> + <% end %> +
    + <% else %> +

    No story ideas yet.

    + <% end %> +
    <% end %> + + + <% if @facilitator.profile_show_workshop_logs? %> +
    +

    Workshop logs submitted

    + <% if @facilitator.user.workshop_logs.any? %> +
    + <% @facilitator.user.workshop_logs.order(date: :desc, created_at: :desc).each do |workshop_log| %> + <%= render "show_card", + record_title: "#{workshop_log.workshop&.title || + "Workshop log #" + workshop_log.id.to_s} - #{workshop_log.windows_type_name}", + record: workshop_log.decorate, title_font_size: "text-sm" %> + <% end %> +
    + <% else %> +

    No workshops logged yet.

    + <% end %> +
    + <% end %>
    - <% end %> -
    +
    <% 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/users/_form.html.erb b/app/views/users/_form.html.erb index 5eea07a4d..9822eab18 100644 --- a/app/views/users/_form.html.erb +++ b/app/views/users/_form.html.erb @@ -5,58 +5,85 @@
    -
    +
    -
    - <%= f.input :first_name, input_html: { class: "w-full" }, wrapper_html: { class: "w-full" } %> - <%= f.input :last_name, input_html: { class: "w-full" }, wrapper_html: { class: "w-full" } %> -
    - -
    - <% if current_user.super_user? %> -
    - <%= f.input :email, - hint: "Only editable by admins", - input_html: { class: "w-full" }, - wrapper_html: { class: "w-full" } %> +
    + <% if @facilitator %> + <%= f.hidden_field :first_name, value: @facilitator.first_name %> + <%= f.hidden_field :last_name, value: @facilitator.last_name %> +
    +
    + +
    +
    + <%= @facilitator.first_name %> +
    +
    +

    + Edit on <%= link_to "facilitator profile", facilitator_path(@facilitator), class: "underline" %> +

    +
    - <% else %> -
    - -
    - - <%= f.object.email %> - + +
    +
    + +
    +
    + <%= @facilitator.last_name %> +
    +
    +

    + Edit on <%= link_to "facilitator profile", facilitator_path(@facilitator), class: "underline" %> +

    -

    - Only editable by admins -

    + <% else %> + <%= f.input :first_name, input_html: { value: @facilitator&.first_name || f.object.first_name } %> + <%= f.input :last_name, input_html: { value: @facilitator&.last_name || f.object.last_name } %> <% end %> -
    - <% if current_user.super_user? %> -
    -
    - <%= f.input :inactive, label: "Hidden?" %> - <%= f.input :super_user %> -
    +
    + <% if current_user.super_user? %> +
    + <%= f.input :email, + hint: "Only editable by admins", + input_html: { value: f.object.email.presence || @facilitator&.primary_email_address, + class: "w-full" }, + wrapper_html: { class: "w-full" } %> +
    + <% else %> +
    + +
    + + <%= f.object.email.presence || @facilitator&.primary_email_address %> + +
    +

    + Only editable by admins +

    +
    + <% end %> +
    +
    + <% if current_user.super_user? %> +
    +
    + <%= f.input :inactive, label: "No access?" %> + <%= f.input :super_user %> +
    +
    + <% end %>
    - <% end %> -
    -
    - - -
    - <% if f.object.facilitator&.avatar_image&.file %> -
    - workshop
    - <% end %> +
    @@ -67,27 +94,6 @@
    <% end %> -
    -

    Organization Connections

    - <%= f.fields_for :project_users do |project_user_form| %> - <%= render "project_user_fields", - f: project_user_form, - projects: @user.projects, - user: @user %> - <% end %> - -
    - <%= link_to_add_association "âž• Add Role", - f, - :project_users, - html_options: { - locals: { projects: @user.projects } - }, - class: "inline-flex items-center rounded-md bg-blue-600 text-white px-3 py-2 text-sm font-medium hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-1 transition" %> -
    -
    - -
    diff --git a/app/views/users/index.html.erb b/app/views/users/index.html.erb index 122459f43..3a8a8011c 100644 --- a/app/views/users/index.html.erb +++ b/app/views/users/index.html.erb @@ -23,13 +23,9 @@
    Avatar Name Facilitator since Sector(s)
    - <% 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 %>
    - - - + - - - + @@ -40,43 +36,18 @@ - - - - - - - - - - - -
    AvatarFirst NameLast NameName EmailOrganization(s)PhoneInactiveNo 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