Skip to content

Commit

Permalink
[ENHC0010037] Member search component (#668)
Browse files Browse the repository at this point in the history
* starting to create a new member search component

* adding search component to project members table page

* adding member search component tests

* making the member search component usable for group links

* moving the search component out of the members folder

* adding a preview for search component

* resolving a warning with filters controller

* removing rendering the component within a turbo frame

* making tab optional

* adding the search component to the tabs component

* renaming turbo_frame_tag
  • Loading branch information
ksierks authored Jul 30, 2024
1 parent edfde24 commit 2cf91f7
Show file tree
Hide file tree
Showing 12 changed files with 115 additions and 60 deletions.
20 changes: 20 additions & 0 deletions app/components/search_component.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<%= search_form_for @q, url: @url, html: {"data-controller": "filters"} do |f| %>
<input type="hidden" name="format" value="turbo_stream"/>
<input type="hidden" name="tab" value="<%=@tab%>"/>
<%= f.label @search_attribute, @placeholder, class: "sr-only" %>
<div class="relative lg:w-72">
<div
class="
absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none
"
>
<%= viral_icon(name: "magnifying_glass", classes: "h-5 w-5") %>
</div>
<%= helpers.turbo_frame_tag "ransack_hidden_values" %>
<%= f.search_field @search_attribute,
"data-action": "filters#submit",
class:
"block w-full p-2.5 pl-10 text-sm text-slate-900 border border-slate-300 rounded-lg bg-slate-50 focus:ring-primary-500 focus:border-primary-500 dark:bg-slate-700 dark:border-slate-600 dark:placeholder-slate-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500",
placeholder: @placeholder %>
</div>
<% end %>
16 changes: 16 additions & 0 deletions app/components/search_component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# frozen_string_literal: true

# Component for rendering the search box
class SearchComponent < Component
include Ransack::Helpers::FormHelper

# rubocop:disable Naming/MethodParameterName
def initialize(q:, url:, search_attribute:, placeholder:, tab: '')
@q = q
@url = url
@search_attribute = search_attribute
@placeholder = placeholder
@tab = tab
end
# rubocop:enable Naming/MethodParameterName
end
17 changes: 8 additions & 9 deletions app/components/viral/tabs_component.html.erb
Original file line number Diff line number Diff line change
@@ -1,17 +1,11 @@
<div
class="
text-sm
font-medium
text-center
text-slate-500
border-b
border-slate-200
dark:text-slate-400
dark:border-slate-700
flex text-sm font-medium text-center text-slate-500 border-b border-slate-200
dark:text-slate-400 dark:border-slate-700
"
>
<ul
class="flex flex-wrap -mb-px text-sm font-medium text-center"
class="flex flex-wrap -mb-px"
role="tablist"
aria-orientation="horizontal"
aria-label="<%= label %>"
Expand All @@ -22,6 +16,11 @@
</li>
<% end %>
</ul>
<% if search_bar? %>
<div class="flex flex-row ml-auto">
<%= search_bar %>
</div>
<% end %>
</div>
<div role="region" id="<%= id %>" aria-live="polite">
<%= tab_content %>
Expand Down
1 change: 1 addition & 0 deletions app/components/viral/tabs_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ class TabsComponent < Viral::Component
attr_reader :id, :label

renders_many :tabs, Viral::Tabs::TabComponent
renders_one :search_bar, SearchComponent
renders_one :tab_content

def initialize(id:, label:)
Expand Down
4 changes: 3 additions & 1 deletion app/javascript/controllers/filters_controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ export default class extends Controller {

submit() {
this.element.requestSubmit();
this.selectionOutlet.clear();
if (this.hasSelectionOutlet) {
this.selectionOutlet.clear();
}
}
}
30 changes: 7 additions & 23 deletions app/views/groups/members/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -26,29 +26,6 @@
<% end %>
<% end %>

<div class="flex flex-row-reverse">
<%= search_form_for @q, url: group_members_url(**request.query_parameters), html: {"data-controller": "filters"} do |f| %>
<input type="hidden" name="format" value="turbo_stream"/>
<input type="hidden" name="tab" value="<%=@tab%>"/>
<%= f.label :user_email_cont, t(".search.placeholder"), class: "sr-only" %>
<div class="relative lg:w-72">
<div
class="
absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none
"
>
<%= viral_icon(name: "magnifying_glass", classes: "h-5 w-5") %>
</div>
<%= turbo_frame_tag "member_hidden_values" %>
<%= f.search_field :user_email_cont,
"data-action": "filters#submit",
class:
"block w-full p-2.5 pl-10 text-sm text-slate-900 border border-slate-300 rounded-lg bg-slate-50 focus:ring-primary-500 focus:border-primary-500 dark:bg-slate-700 dark:border-slate-600 dark:placeholder-slate-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500",
placeholder: t(".search.placeholder") %>
</div>
<% end %>
</div>

<div class="bg-white dark:bg-slate-800">
<%= viral_tabs(id: "members-tabs", label: t(:"groups.members.index.tabs.aria_label")) do |tabs| %>
<%= tabs.with_tab(url: group_members_path(), selected: @tab != "invited_groups", controls: "members-tabs") do %>
Expand All @@ -57,6 +34,13 @@
<%= tabs.with_tab(url: group_members_path(tab: "invited_groups"), selected: @tab == "invited_groups", controls: "members-tabs") do %>
<%= t(:"groups.members.index.tabs.groups") %>
<% end %>
<%= tabs.with_search_bar(
q: @q,
url: group_members_url(**request.query_parameters),
search_attribute: :user_email_cont,
placeholder: t(".search.placeholder"),
tab: @tab,
) %>
<%= tabs.with_tab_content do %>
<div class="flex flex-col">
<%= turbo_frame_tag "members", "data-turbo-temporary": true,
Expand Down
2 changes: 1 addition & 1 deletion app/views/groups/members/index.turbo_stream.erb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

<%= turbo_stream.update "members_pagination", partial: "pagination" %>

<%= turbo_stream.update "member_hidden_values" do %>
<%= turbo_stream.update "ransack_hidden_values" do %>
<%= render Ransack::HiddenSortFieldComponent.new(@q) %>
<% end %>

Expand Down
32 changes: 7 additions & 25 deletions app/views/projects/members/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -34,39 +34,21 @@
<% end %>
<% end %>

<div class="flex flex-row-reverse">
<%= search_form_for @q, url: namespace_project_members_url(**request.query_parameters), html: {"data-controller": "filters"} do |f| %>
<input type="hidden" name="format" value="turbo_stream"/>
<input type="hidden" name="tab" value="<%=@tab%>"/>
<%= f.label :user_email_cont, t(".search.placeholder"), class: "sr-only" %>
<div class="relative lg:w-72">
<div
class="
absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none
"
>
<%= viral_icon(name: "magnifying_glass", classes: "h-5 w-5") %>
</div>
<%= turbo_frame_tag "member_hidden_values" %>
<%= f.search_field :user_email_cont,
"data-action": "filters#submit",
class:
"block w-full p-2.5 pl-10 text-sm text-slate-900 border border-slate-300 rounded-lg bg-slate-50 focus:ring-primary-500 focus:border-primary-500 dark:bg-slate-700 dark:border-slate-600 dark:placeholder-slate-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500",
placeholder: t(".search.placeholder") %>
</div>
<% end %>
</div>

<div class="bg-white dark:bg-slate-800">
<%= viral_tabs(id: "project-members", label: t(:"projects.members.index.tabs.aria_label")) do |tabs| %>
<%= tabs.with_tab(url: namespace_project_members_path(), controls: "project-members", selected: @tab != "invited_groups") do %>
<%= t(:"projects.members.index.tabs.members") %>
<% end %>

<%= tabs.with_tab(url: namespace_project_members_path(tab: "invited_groups"), controls: "project-members", selected: @tab == "invited_groups") do %>
<%= t(:"projects.members.index.tabs.groups") %>
<% end %>

<%= tabs.with_search_bar(
q: @q,
url: namespace_project_members_url(**request.query_parameters),
search_attribute: :user_email_cont,
placeholder: t(".search.placeholder"),
tab: @tab,
) %>
<%= tabs.with_tab_content do %>
<div class="flex flex-col">
<%= turbo_frame_tag "members", "data-turbo-temporary": true,
Expand Down
2 changes: 1 addition & 1 deletion app/views/projects/members/index.turbo_stream.erb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

<%= turbo_stream.update "members_pagination", partial: "pagination" %>

<%= turbo_stream.update "member_hidden_values" do %>
<%= turbo_stream.update "ransack_hidden_values" do %>
<%= render Ransack::HiddenSortFieldComponent.new(@q) %>
<% end %>

Expand Down
36 changes: 36 additions & 0 deletions test/components/members/search_component_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# frozen_string_literal: true

require 'test_helper'

class SearchComponentTest < ViewComponent::TestCase
test 'Should render a searchbox' do
url = '/-/groups/group-1/-/members'
search_attribute = :user_email_cont
placeholder = 'a placeholder'

render_inline SearchComponent.new(q: Member.ransack, url:, search_attribute:,
placeholder:)

assert_selector "input[type='hidden'][name='tab'][value='']", visible: false, count: 1
assert_selector "form[action='#{url}']", count: 1
assert_selector "label[for='q_#{search_attribute}']", count: 1
assert_selector "input[id='q_#{search_attribute}']", count: 1
assert_text placeholder
end

test 'Should render a searchbox with a tab' do
url = '/-/groups/group-1/-/members'
search_attribute = :user_email_cont
placeholder = 'a placeholder'
tab = 'invited_groups'

render_inline SearchComponent.new(q: Member.ransack, url:, search_attribute:,
placeholder:, tab:)

assert_selector "input[type='hidden'][name='tab'][value='#{tab}']", visible: false, count: 1
assert_selector "form[action='#{url}']", count: 1
assert_selector "label[for='q_#{search_attribute}']", count: 1
assert_selector "input[id='q_#{search_attribute}']", count: 1
assert_text placeholder
end
end
9 changes: 9 additions & 0 deletions test/components/previews/search_component_preview.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# frozen_string_literal: true

class SearchComponentPreview < ViewComponent::Preview
def default
render_with_template(locals: {
url: group_members_url(Group.first)
})
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<%= render SearchComponent.new(
Member.ransack,
url,
:user_email_cont,
"a placeholder",
) %>

0 comments on commit 2cf91f7

Please sign in to comment.