Skip to content

Commit

Permalink
Merge pull request #1657 from tactilenews/955_filter_contributors_by_tag
Browse files Browse the repository at this point in the history
  • Loading branch information
mattwr18 authored Jul 13, 2023
2 parents 1e20e07 + 217caab commit 4eecb9a
Show file tree
Hide file tree
Showing 21 changed files with 359 additions and 67 deletions.
6 changes: 6 additions & 0 deletions app/components/button/button.css
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,12 @@
padding: var(--input-padding);
}

.Button--warning {
--background-color: var(--color-orange-lightest);
--border-color: var(--color-orange);
--text-color: var(--color-orange-darkest);
}

.Button:disabled {
background-color: var(--color-gray);
pointer-events: none;
Expand Down
17 changes: 17 additions & 0 deletions app/components/contributors_index/contributors_index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
.ContributorsIndex-filterSection {
padding: 0;
}

.ContributorsIndex-filterSectionLabel {
font-size: 1.25rem;
line-height: 1.25;
font-weight: 700;
}

.ContributorsIndex-filterSection .TagsInput {
margin: var(--spacing-unit-s) 0;
}

.ContributorsIndex-filterSection .Button {
margin-right: var(--spacing-unit-s);
}
86 changes: 86 additions & 0 deletions app/components/contributors_index/contributors_index.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<%= c 'main', data: { controller: 'contributors-index' } do %>
<%= c 'page_header', styles: [:lightGrayBackground, :spaceBetween, :largeMarginBottom] do |header| %>
<div>
<%= c 'heading' do %>
<%= I18n.t 'contributor.contributor', count: :other %>
<% end %>
<p><%= t('contributor.subheading') %></p>
</div>

<%= c 'copy_button',
label: I18n.t('contributor.actions.copy_invite'),
styles: [:colorNavBar, :customIcon],
url: invites_url,
key: 'url',
custom_icon: 'onboarding-ticket'
%>

<% header.tab_bar do %>
<%= c('tab_bar', items: [
{
url: contributors_path(state: :active, tag_list: tag_list.present? ? @tag_list : nil),
label: "Aktiv",
active: state == :active,
count: active_contributors_count,
},
{
url: contributors_path(state: :inactive, tag_list: tag_list.present? ? @tag_list : nil),
label: "Inaktiv",
active: state == :inactive,
count: inactive_contributors_count,
},
{
label: I18n.t('contributor.filter_section.submit_button'),
icon: "filter-tool",
data: { action: 'contributors-index#toggleFilterSection' }
}
]) %>
<% end %>
<% end %>

<%= c('section',
class: 'ContributorsIndex-filterSection',
data: { contributors_index_target: 'filterSection' },
hidden: true
) do %>
<%= c('form',
url: contributors_path,
method: 'get',
multiple: true
) do %>
<%= hidden_field_tag :state, state %>

<label class="ContributorsIndex-filterSectionLabel">
<%= t('contributor.filter_section.heading') %>
<%= c 'tags_input',
id: 'ContributorsIndex-filterTagsInput',
available_tags: available_tags,
allow_new: false, name: 'tag_list[]',
value: tag_list
%>
</label>
<%= c 'submit_button',
styles: [:secondary],
label: t('contributor.filter_section.submit_button')
%>
<%= c 'button',
styles: [:secondary, :warning],
label: t('contributor.filter_section.clear_button'),
data: { action: 'contributors-index#clearTags' }
%>
<% end %>
<% end %>

<%= c 'section' do %>
<% if contributors.present? && tag_list.present? %>
<p><%= t('.filter_active_text', count: tag_list.size).html_safe %>
<strong>
<% tag_list.map do |tag| %>
<%= " (#{tag})" %>
<% end %>
</strong>
</p>
<% end %>
<%= c 'contributors_list', contributors: contributors, filter_active: tag_list.present? %>
<% end %>
<% end %>
20 changes: 20 additions & 0 deletions app/components/contributors_index/contributors_index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Controller } from '@hotwired/stimulus';

export default class extends Controller {
static targets = ['filterSection'];

connect() {
const searchParams = new URL(document.location).searchParams;
const tagList = searchParams.get('tag_list[]');
const showFilter = !(tagList && tagList.length > 0);
this.filterSectionTarget.hidden = showFilter;
}

toggleFilterSection() {
this.filterSectionTarget.hidden = !this.filterSectionTarget.hidden;
}

clearTags() {
this.dispatch('clearTags', { bubbles: true });
}
}
32 changes: 32 additions & 0 deletions app/components/contributors_index/contributors_index.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# frozen_string_literal: true

module ContributorsIndex
class ContributorsIndex < ApplicationComponent
def initialize(contributors:, state:, active_count:, inactive_count:, filter_count:, tag_list: nil)
super

@contributors = contributors
@tag_list = tag_list
@state = state
@active_count = active_count
@inactive_count = inactive_count
@filter_count = filter_count
end

private

attr_reader :contributors, :tag_list, :state, :active_count, :inactive_count, :filter_count

def available_tags
Contributor.all_tags_with_count.to_json
end

def active_contributors_count
tag_list.present? && state == :active ? filter_count : active_count
end

def inactive_contributors_count
tag_list.present? && state == :inactive ? filter_count : inactive_count
end
end
end
13 changes: 13 additions & 0 deletions app/components/contributors_list/contributors_list.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<% if contributors.empty? %>
<%= c 'empty_state', custom_icon: 'community' do %>
<% if filter_active %>
<p><%= t('.empty_state.filter_active') %></p>
<% else %>
<p><%= t('.empty_state.no_contributors') %></p>
<% end %>
<% end %>
<% else %>
<% contributors.each do |contributor| %>
<%= c 'contributor_row', contributor: contributor %>
<% end %>
<% end %>
16 changes: 16 additions & 0 deletions app/components/contributors_list/contributors_list.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# frozen_string_literal: true

module ContributorsList
class ContributorsList < ApplicationComponent
def initialize(contributors:, filter_active: false)
super

@contributors = contributors
@filter_active = filter_active
end

private

attr_reader :contributors, :filter_active
end
end
2 changes: 1 addition & 1 deletion app/components/empty_state/empty_state.html.erb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<div class="EmptyState">
<%= c 'box' do %>
<div class="EmptyState-icon">
<%= c 'icon', icon: 'a-chat' %>
<%= c 'icon', icon: custom_icon || 'a-chat', size: custom_icon ? 36 : 24 %>
</div>

<%= c 'heading', tag: :p, styles: [:beta] do %>
Expand Down
9 changes: 9 additions & 0 deletions app/components/empty_state/empty_state.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,14 @@

module EmptyState
class EmptyState < ApplicationComponent
def initialize(custom_icon: nil, **)
super

@custom_icon = custom_icon
end

private

attr_reader :custom_icon
end
end
13 changes: 11 additions & 2 deletions app/components/tab_bar/tab_bar.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,15 @@
margin-top: var(--spacing-unit-s);
}

.TabBar-list {
display: flex;
align-items: end;
}

.TabBar-item:nth-child(3) {
margin-left: calc(1.5 * var(--spacing-unit-xl));
}

.TabBar-item {
display: inline-block;
padding: var(--spacing-unit-xs) 0;
Expand All @@ -12,8 +21,8 @@
transition: 0.1s all ease-out;
}

.TabBar-item + .TabBar-item {
margin-left: var(--spacing-unit-s);
.TabBar-item:nth-child(even) {
margin-left: var(--spacing-unit);
}

.TabBar-item:not(.TabBar-item--active):hover {
Expand Down
25 changes: 17 additions & 8 deletions app/components/tab_bar/tab_bar.html.erb
Original file line number Diff line number Diff line change
@@ -1,17 +1,26 @@
<nav class="TabBar">
<ul>
<% items.each do |url, options| %>
<nav class="TabBar" data-controller="tab-bar">
<ul class="TabBar-list">
<% items.each do |options| %>
<li class="TabBar-item <%= 'TabBar-item--active' if options.dig(:active) %>">
<a href="<%= url %>">
<%= options.dig(:label) %>

<%= c('button',
link: options.dig(:url),
styles: [:inline],
data: options.dig(:data)
) do %>
<% if options.key?(:label) %>
<%= options.dig(:label) %>
<% end %>
<% if options.key?(:count) %>
<span class="TabBar-count">
<%= options[:count] %>
<%= options.dig(:count) %>
</span>
<% end %>
</a>
<% if options.key?(:icon) %>
<%= c 'icon', icon: options.dig(:icon), styles: [:inline] %>
<% end %>
<% end %>
</li>
<% end %>
</ul>
<%= content %>
</nav>
1 change: 1 addition & 0 deletions app/components/tags_input/tags_input.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
tags_input_allow_new_value: allow_new,
tags_input_available_tags_value: available_tags,
tags_input_members_label_value: I18n.t('contributor.contributor').to_json,
action: 'contributors-index:clearTags@window->tags-input#clearTags'
},
**attrs
%>
4 changes: 4 additions & 0 deletions app/components/tags_input/tags_input.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,4 +87,8 @@ export default class extends Controller {

this.element.dispatchEvent(event);
}

clearTags() {
this.tagify.removeAllTags();
}
}
25 changes: 21 additions & 4 deletions app/controllers/contributors_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
class ContributorsController < ApplicationController
before_action :set_contributor, only: %i[update destroy show edit message]
before_action :count_params, only: :count
before_action :contributors_params, only: :index

def message
request = contributor.active_request
Expand All @@ -14,11 +15,16 @@ def message
end

def index
@filter = filter_param
@state = state_params
@tag_list = tag_list_params

@active_count = Contributor.active.count
@inactive_count = Contributor.inactive.count
@available_tags = Contributor.all_tags_with_count.to_json

@contributors = @filter == :inactive ? Contributor.inactive : Contributor.active
@contributors = @state == :inactive ? Contributor.inactive : Contributor.active
@contributors = @contributors.with_tags(tag_list_params)
@filter_count = @contributors.size
@contributors = @contributors.with_attached_avatar.includes(:tags)
end

Expand Down Expand Up @@ -60,6 +66,10 @@ def set_contributor
@contributor = Contributor.find(params[:id])
end

def contributors_params
params.permit(:state, tag_list: [])
end

def contributor_params
params.require(:contributor).permit(:note, :first_name, :last_name, :avatar, :email, :threema_id, :phone, :zip_code, :city, :tag_list,
:active, :additional_email)
Expand All @@ -73,14 +83,21 @@ def count_params
params.permit(tag_list: [])
end

def filter_param
value = params.permit(:filter)[:filter]&.to_sym
def state_params
value = contributors_params[:state]&.to_sym

return :active unless %i[active inactive].include?(value)

value
end

def tag_list_params
value = contributors_params[:tag_list]
return [] if value.blank? || value.all?(&:blank?)

value.reject(&:empty?).first.split(',')
end

def handle_failed_update
flash.now[:error] = I18n.t('contributor.invalid', name: contributor.name)

Expand Down
Loading

0 comments on commit 4eecb9a

Please sign in to comment.