From 9745dd17bc0ecd8254ff7ffd0eecdb0acd2f64cb Mon Sep 17 00:00:00 2001 From: rsmokeUM Date: Tue, 24 Feb 2026 14:21:49 -0500 Subject: [PATCH 1/3] Refactor contest descriptions display and eligibility rules rendering - Updated the rendering of eligibility rules in the ContainersHelper to display a preview of the first six words, enhancing user experience with a more concise view and a modal link for full details. - Introduced a new helper method in ContestDescriptionsHelper to encapsulate the logic for generating active contest entries links, improving code modularity and readability. - Refactored the contest descriptions table view to a card layout for better scannability and visual appeal, while maintaining all relevant information and actions. These changes enhance the UI and improve the clarity of contest descriptions, making it easier for users to interact with the information presented. --- app/helpers/containers_helper.rb | 30 +++-- app/helpers/contest_descriptions_helper.rb | 16 ++- .../_contest_descriptions_table.html.erb | 111 ++++++++---------- spec/helpers/containers_helper_spec.rb | 14 ++- 4 files changed, 89 insertions(+), 82 deletions(-) diff --git a/app/helpers/containers_helper.rb b/app/helpers/containers_helper.rb index 73e33691..9041c47d 100644 --- a/app/helpers/containers_helper.rb +++ b/app/helpers/containers_helper.rb @@ -15,17 +15,25 @@ def contest_description_action_links(container, description) end def render_eligibility_rules(description) - eligibility_plain = description.eligibility_rules.to_plain_text - if eligibility_plain.length > 60 - content_tag(:div) do - truncate(eligibility_plain, length: 60, omission: '') + - link_to(' ...more', '#', - data: { - action: 'click->modal#open', - url: eligibility_rules_container_contest_description_path(description.container, description), - modal_title: 'Eligibility Rules' - } - ) + eligibility_plain = description.eligibility_rules.to_plain_text.to_s.squish + preview_words = eligibility_plain.split + + if preview_words.length > 6 + preview_text = preview_words.first(6).join(' ') + + content_tag(:div, class: 'd-inline-flex align-items-center gap-1 border rounded px-1 py-0 bg-light small') do + safe_join([ + content_tag(:span, 'Rules:', class: 'fw-semibold text-muted'), + content_tag(:span, preview_text, class: 'text-muted'), + link_to('...more', '#', + data: { + action: 'click->modal#open', + url: eligibility_rules_container_contest_description_path(description.container, description), + modal_title: 'Eligibility Rules' + }, + aria: { label: 'View full eligibility rules' } + ) + ]) end else description.eligibility_rules diff --git a/app/helpers/contest_descriptions_helper.rb b/app/helpers/contest_descriptions_helper.rb index 5e53842d..bbf49b1c 100644 --- a/app/helpers/contest_descriptions_helper.rb +++ b/app/helpers/contest_descriptions_helper.rb @@ -1,13 +1,21 @@ module ContestDescriptionsHelper + def contest_description_entries_link(description) + active_instances = description.contest_instances.where(active: true) + return nil if active_instances.empty? + + first_active = active_instances.first + entry_count = first_active.entries.where(deleted: false).count + link_to("Active: #{pluralize(entry_count, 'entry')}", + container_contest_description_contest_instance_path(description.container, description, first_active), + class: 'btn btn-sm btn-primary small') + end + def contest_description_summary(description) total_instances = description.contest_instances.count active_instances = description.contest_instances.where(active: true) summary = '' if active_instances.any? - first_active = active_instances.first - entry_count = first_active.entries.where(deleted: false).count - summary += link_to("Active: #{pluralize(entry_count, 'entry')}", - container_contest_description_contest_instance_path(description.container, description, first_active), class: 'btn btn-sm btn-primary small') + summary += contest_description_entries_link(description).to_s summary += '
' end summary += "#{pluralize(total_instances, 'instance')}" diff --git a/app/views/containers/_contest_descriptions_table.html.erb b/app/views/containers/_contest_descriptions_table.html.erb index 2c8a6d84..4c1c06cc 100644 --- a/app/views/containers/_contest_descriptions_table.html.erb +++ b/app/views/containers/_contest_descriptions_table.html.erb @@ -1,63 +1,52 @@ -<%# app/views/containers/_contest_descriptions_table.html.erb %> -
- - - - - - - - - - - - - - <% descriptions.each do |description| %> - - - - - - - - - <% end %> - -
NameStatusShort NameEligibilityNotesActiveActions
- - <%= description.name %> - - - <%= contest_description_summary(description) %> - - - <%= description.short_name %> - - - - <%# - <% if description.notes.present? %> - <%= link_to "view", container_contest_description_contest_instances_path(container, description), class: "btn btn-link btn-sm p-0", title: "View notes", aria: { label: "View notes for #{description.name}" } %> +<%# app/views/containers/_contest_descriptions_table.html.erb - Card list for scannability and full names %> +<% descriptions.each do |description| %> +
+
+
+
+
+
+ <%= link_to description.name, + container_contest_description_contest_instances_path(container, description), + class: 'text-decoration-none fw-semibold fs-5 lh-1' %> +
+ <% if (entries_link = contest_description_entries_link(description)).present? %> +
+ <%= entries_link %> +
<% end %> -
- <%= boolean_to_yes_no(description.active) %> - -
- <% contest_description_action_links(container, description).each do |action, config| %> - <%= link_to config[:path], - class: 'btn btn-link btn-sm p-0', - data: config[:data]&.merge('bs-toggle': 'tooltip'), - title: config[:title], - aria: { label: config[:title] } do %> - - <%= config[:title] %> - <% end %> - <% end %> +
+
+
+ Short name: <%= description.short_name %> + <%= pluralize(description.contest_instances.count, 'instance') %>
-
-
+
<%= render_eligibility_rules(description) %>
+ + +
+ <% if description.notes.present? %> + <%= link_to "View notes", + container_contest_description_contest_instances_path(container, description), + class: "btn btn-link btn-sm p-0", + title: "View notes", + aria: { label: "View notes for #{description.name}" } %> + <% end %> + Active: <%= boolean_to_yes_no(description.active) %> +
+ <% contest_description_action_links(container, description).each do |_action, config| %> + <%= link_to config[:path], + class: 'btn btn-link btn-sm p-0', + data: config[:data]&.merge('bs-toggle': 'tooltip'), + title: config[:title], + aria: { label: config[:title] } do %> + + <%= config[:title] %> + <% end %> + <% end %> +
+
+ + + +<% end %> diff --git a/spec/helpers/containers_helper_spec.rb b/spec/helpers/containers_helper_spec.rb index cff1112a..aaf6fafe 100644 --- a/spec/helpers/containers_helper_spec.rb +++ b/spec/helpers/containers_helper_spec.rb @@ -48,8 +48,8 @@ end describe "#render_eligibility_rules" do - context "when eligibility rules are longer than 60 characters" do - let(:long_text) { "These are very long eligibility rules that will definitely exceed the 60 character limit and therefore trigger the modal functionality." } + context "when eligibility rules have more than 6 words" do + let(:long_text) { "These rules are intentionally long so they trigger modal preview behavior." } let(:rich_text) { instance_double(ActionText::RichText, to_plain_text: long_text) } before do @@ -61,19 +61,21 @@ result = helper.render_eligibility_rules(description) parsed_result = Nokogiri::HTML.fragment(result.to_s) link = parsed_result.at_css('a') + preview_chip = parsed_result.at_css('div') # Check link attributes expect(link['data-action']).to eq('click->modal#open') expect(link['data-modal-title']).to eq('Eligibility Rules') expect(link['href']).to eq('#') - expect(link.text).to eq(' ...more') + expect(link.text).to eq('...more') - # Check truncated text - expect(parsed_result.text).to include(long_text[0..59]) + # Check word-based truncation and visual treatment + expect(parsed_result.text).to match(/Rules:\s*These rules are intentionally long so/) + expect(preview_chip['class']).to include('border') end end - context "when eligibility rules are shorter than 100 characters" do + context "when eligibility rules have 6 or fewer words" do let(:short_text) { "Short rules" } let(:rich_text) { instance_double(ActionText::RichText, to_plain_text: short_text) } From 2e4cab9f7ebd43a62cd370a65fdfcf7074f04879 Mon Sep 17 00:00:00 2001 From: rsmokeUM Date: Tue, 24 Feb 2026 15:01:09 -0500 Subject: [PATCH 2/3] Refactor contest descriptions table for improved layout and functionality - Adjusted card layout styles in the contest descriptions table to enhance visual appeal and scannability, including modifications to padding and alignment. - Updated the rendering of eligibility rules and added a conditional link to view notes, improving user interaction and accessibility of information. - Enhanced the overall structure of the card components to ensure a more responsive design and better alignment of elements. These changes improve the user experience by providing a clearer and more organized display of contest descriptions. --- .../_contest_descriptions_table.html.erb | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/app/views/containers/_contest_descriptions_table.html.erb b/app/views/containers/_contest_descriptions_table.html.erb index 4c1c06cc..8bc1f7ef 100644 --- a/app/views/containers/_contest_descriptions_table.html.erb +++ b/app/views/containers/_contest_descriptions_table.html.erb @@ -1,7 +1,7 @@ <%# app/views/containers/_contest_descriptions_table.html.erb - Card list for scannability and full names %> <% descriptions.each do |description| %>
-
+
@@ -16,35 +16,36 @@
<% end %>
-
-
+
+
Short name: <%= description.short_name %> <%= pluralize(description.contest_instances.count, 'instance') %>
-
<%= render_eligibility_rules(description) %>
+
<%= render_eligibility_rules(description) %>
- <% if description.notes.present? %> - <%= link_to "View notes", - container_contest_description_contest_instances_path(container, description), - class: "btn btn-link btn-sm p-0", - title: "View notes", - aria: { label: "View notes for #{description.name}" } %> - <% end %> Active: <%= boolean_to_yes_no(description.active) %> -
+
<% contest_description_action_links(container, description).each do |_action, config| %> <%= link_to config[:path], - class: 'btn btn-link btn-sm p-0', + class: 'btn btn-link btn-sm p-0 d-inline-flex align-items-center justify-content-center', + style: 'width: 1.5rem; height: 1.5rem;', data: config[:data]&.merge('bs-toggle': 'tooltip'), title: config[:title], aria: { label: config[:title] } do %> - + <%= config[:title] %> <% end %> <% end %>
+ <% if description.notes.to_plain_text.squish.present? %> + <%= link_to "View notes", + container_contest_description_path(container, description), + class: "btn btn-link btn-sm p-0", + title: "View notes", + aria: { label: "View notes for #{description.name}" } %> + <% end %>
From d4ef537d60111b655ce917315b66e2bc29274f3e Mon Sep 17 00:00:00 2001 From: rsmokeUM Date: Tue, 24 Feb 2026 15:01:18 -0500 Subject: [PATCH 3/3] Update eligibility rules preview in ContainersHelper for improved display - Modified the preview of eligibility rules to display the first eight words instead of six, enhancing the amount of information presented to users. - Adjusted the CSS class for better alignment of elements within the preview, ensuring a more visually appealing layout. These changes improve the clarity and usability of eligibility rules in the contest descriptions. --- app/helpers/containers_helper.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/helpers/containers_helper.rb b/app/helpers/containers_helper.rb index 9041c47d..730f6731 100644 --- a/app/helpers/containers_helper.rb +++ b/app/helpers/containers_helper.rb @@ -18,10 +18,10 @@ def render_eligibility_rules(description) eligibility_plain = description.eligibility_rules.to_plain_text.to_s.squish preview_words = eligibility_plain.split - if preview_words.length > 6 - preview_text = preview_words.first(6).join(' ') + if preview_words.length > 8 + preview_text = preview_words.first(8).join(' ') - content_tag(:div, class: 'd-inline-flex align-items-center gap-1 border rounded px-1 py-0 bg-light small') do + content_tag(:div, class: 'd-inline-flex align-items-start gap-1 border rounded px-1 py-0 bg-light small') do safe_join([ content_tag(:span, 'Rules:', class: 'fw-semibold text-muted'), content_tag(:span, preview_text, class: 'text-muted'),