Wire up filter form sans search

This commit is contained in:
Jose Farias
2024-11-11 13:46:15 -06:00
parent d455b72906
commit 0baaf5d87f
7 changed files with 112 additions and 101 deletions
@@ -0,0 +1,4 @@
class FilterButtonsController < ApplicationController
def create
end
end
+45 -17
View File
@@ -1,27 +1,55 @@
module FiltersHelper
def buckets_filter_text(filter)
if filter.buckets.present?
filter.buckets.map(&:name).to_choice_sentence
else
"all projects"
def filter_button_id(value, name)
"#{name}_filter--#{value}"
end
def filter_buttons(filter, **)
filter.to_h.map do |kind, object|
filter_button_from kind, object, **
end.join.html_safe
end
def filter_button_tag(display:, value:, name:, **options)
tag.button id: filter_button_id(value, name), class: [ "btn txt-small btn--remove", options.delete(:class) ], data: { action: "filter-form#removeFilter form#submit" } do
concat hidden_field_tag(name, value, id: nil)
concat tag.span(display)
concat image_tag("close.svg", aria: { hidden: true }, size: 24)
end
end
def assignments_filter_text(filter)
if filter.assignees.present?
"assigned to #{filter.assignees.map(&:name).to_choice_sentence}"
elsif filter.assignments.unassigned?
"assigned to no one"
def button_to_filter(text, kind:, object:, data: {})
if object
button_to text, filter_buttons_path, method: :post, class: "btn btn--plain", params: filter_attrs(kind, object), data: data
else
"assigned to anyone"
button_tag text, type: :button, class: "btn btn--plain", data: data
end
end
def tags_filter_text(filter)
if filter.tags.present?
filter.tags.map(&:hashtag).to_choice_sentence
else
"any tag"
private
def filter_button_from(kind, object, **)
if object.respond_to? :map
safe_join object.map { |o| filter_button_tag(**filter_attrs(kind, o), **) }
else
filter_button_tag(**filter_attrs(kind, object), **)
end
end
def filter_attrs(kind, object)
case kind&.to_sym
when :tags
[ object.hashtag, object.id, "tag_ids[]" ]
when :buckets
[ "in #{object.name}", object.id, "bucket_ids[]" ]
when :assignees
[ "for #{object.name}", object.id, "assignee_ids[]" ]
when :assigners
[ "by #{object.name}", object.id, "assigner_ids[]" ]
when :indexed_by
[ object.humanize, object, "indexed_by" ]
when :assignments
[ object.humanize, object, "assignments" ]
end.then do |display, value, name|
{ display: display, value: value, name: name }
end
end
end
end
@@ -0,0 +1,17 @@
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
removeFilter(event) {
event.preventDefault()
this.#removeButton(event.target.closest("button"))
}
clearCategory({ params: { name } }) {
this.element.querySelectorAll(`input[name="${name}"]`).forEach(input => this.#removeButton(input.closest("button")))
}
#removeButton(button) {
button.querySelector("input").disabled = true
button.hidden = true
}
}
+16 -8
View File
@@ -8,15 +8,23 @@ module Filter::Params
end
def as_params
params = {}.tap do |h|
h["tag_ids"] = tags.ids
h["bucket_ids"] = buckets.ids
h["assignee_ids"] = assignees.ids
h["indexed_by"] = indexed_by
h["assignments"] = assignments
end
@as_params ||= to_h.dup.tap do |h|
h["tag_ids"] = h.delete("tags")&.ids
h["bucket_ids"] = h.delete("buckets")&.ids
h["assignee_ids"] = h.delete("assignees")&.ids
end.compact_blank
end
params.compact_blank.reject { |k, v| default_fields[k] == v }
def to_h
@to_h ||= {}.tap do |h|
h["indexed_by"] = indexed_by
h["assignments"] = assignments
h["assignees"] = assignees
h["tags"] = tags
h["buckets"] = buckets
end.reject do |k, v|
default_fields[k] == v
end.compact_blank
end
def to_params
+25 -76
View File
@@ -1,6 +1,6 @@
<div class="flex flex-column gap-half align-center" data-controller="dialog" data-action="keydown.esc->dialog#close click@document->dialog#closeOnClickOutside">
<div class="flex flex-column gap-half align-center" data-controller="dialog filter-form" data-action="keydown.esc->dialog#close click@document->dialog#closeOnClickOutside">
<h1 class="txt-large flex align-center gap-half">
Writebook
<%= filter.buckets.first&.name || "All projects" %>
</h1>
<div class="filters flex-inline align-center gap-half">
@@ -9,35 +9,9 @@
<span class="for-screen-reader">Filter</span>
</button>
<button class="btn txt-small btn--remove">
<span>"Basecamp"</span>
<%= image_tag "close.svg", aria: { hidden: true }, size: 24 %>
</button>
<button class="btn txt-small btn--remove">
<span>Newest</span>
<%= image_tag "close.svg", aria: { hidden: true }, size: 24 %>
</button>
<button class="btn txt-small btn--remove">
<span>Writebook</span>
<%= image_tag "close.svg", aria: { hidden: true }, size: 24 %>
</button>
<button class="btn txt-small btn--remove">
<span>Mobile</span>
<%= image_tag "close.svg", aria: { hidden: true }, size: 24 %>
</button>
<button class="btn txt-small btn--remove">
<span>for Kevin</span>
<%= image_tag "close.svg", aria: { hidden: true }, size: 24 %>
</button>
<button class="btn txt-small btn--remove">
<span>from David</span>
<%= image_tag "close.svg", aria: { hidden: true }, size: 24 %>
</button>
<%= form_with url: bubbles_path, method: :get, class: "flex-inline center align-center gap-half", data: { controller: "form" } do %>
<%= filter_buttons filter %>
<% end %>
</div>
<dialog class="panel fill-white shadow" style="--panel-padding: var(--block-space); --panel-size: 90ch;" data-dialog-target="dialog">
@@ -45,9 +19,9 @@
<div class="flex align-center gap-half justify-space-between">
<span class="btn btn--placeholder txt-small" aria-hidden="true"></span>
<h1 class="txt-large flex gap-half margin-none">
Writebook
</h1>
<h2 class="txt-large flex gap-half margin-none">
<%= filter.buckets.first&.name || "All projects" %>
</h2>
<form method="dialog">
<button class="btn panel__close txt-small" title="Close (esc)">
@@ -63,35 +37,9 @@
<span class="for-screen-reader">Filter</span>
</button>
<button class="btn txt-small btn--remove fill-selected">
<span>"Basecamp"</span>
<%= image_tag "close.svg", aria: { hidden: true }, size: 24 %>
</button>
<button class="btn txt-small btn--remove fill-selected">
<span>Newest</span>
<%= image_tag "close.svg", aria: { hidden: true }, size: 24 %>
</button>
<button class="btn txt-small btn--remove fill-selected">
<span>Writebook</span>
<%= image_tag "close.svg", aria: { hidden: true }, size: 24 %>
</button>
<button class="btn txt-small btn--remove fill-selected">
<span>Mobile</span>
<%= image_tag "close.svg", aria: { hidden: true }, size: 24 %>
</button>
<button class="btn txt-small btn--remove fill-selected">
<span>for Kevin</span>
<%= image_tag "close.svg", aria: { hidden: true }, size: 24 %>
</button>
<button class="btn txt-small btn--remove fill-selected">
<span>from David</span>
<%= image_tag "close.svg", aria: { hidden: true }, size: 24 %>
</button>
<%= form_with url: bubbles_path, id: :filter_form, method: :get, class: "flex-inline center align-center gap-half" do %>
<%= filter_buttons filter, class: "fill-selected" %>
<% end %>
</div>
<div class="flex gap flex-item-grow align-center justify-center full-width center margin-block">
@@ -109,7 +57,7 @@
<menu class="filter__menu unpad margin-none">
<li><strong class="filter__label">Sort by</strong></li>
<% Filter::INDEXES.each do |index| %>
<li><%= link_to index.humanize, bubbles_path(filter.to_params.merge(indexed_by: index)), class: "filter__button" %></li>
<li><%= button_to_filter index.humanize, kind: :indexed_by, object: index, data: { action: "filter-form#clearCategory", filter_form_name_param: "indexed_by" } %></li>
<% end %>
</menu>
</div>
@@ -118,9 +66,9 @@
<div class="flex gap flex-item-grow">
<menu class="filter__menu unpad margin-none">
<li><strong class="filter__label">In Project</strong></li>
<li><%= link_to "All projects", bubbles_path(filter.to_params.merge(bucket_ids: nil)), class: "filter__button" %></li>
<li><%= button_to_filter "All projects", kind: :buckets, object: nil, data: { action: "filter-form#clearCategory", filter_form_name_param: "bucket_ids[]" } %></li>
<% Current.user.buckets.order(:name).each do |bucket| %>
<li><%= link_to bucket.name, bubbles_path(filter.to_params.merge(bucket_ids: [ bucket.id ])), class: "filter__button" %></li>
<li><%= button_to_filter bucket.name, kind: :buckets, object: bucket %></li>
<% end %>
</menu>
</div>
@@ -130,7 +78,7 @@
<menu class="filter__menu unpad margin-none">
<li><strong class="filter__label">Tagged</strong></li>
<% Current.account.tags.order(:title).each do |tag| %>
<li><%= link_to tag.title, bubbles_path(filter.to_params.merge(tag_ids: [ tag.id ])) %></li>
<li><%= button_to_filter tag.title, kind: :tags, object: tag %></li>
<% end %>
</menu>
</div>
@@ -139,9 +87,10 @@
<div class="flex gap flex-item-grow">
<menu class="filter__menu unpad margin-none">
<li><strong class="filter__label">Assigned to…</strong></li>
<li><%= link_to "No one", bubbles_path(filter.to_params.merge(assignments: :unassigned, assignee_ids: [])), class: "filter__button" %></li>
<% Current.account.users.active.order(:name).each do |user| %>
<li><%= link_to user.name, bubbles_path(filter.to_params.merge(assignments: nil, assignee_ids: [ user.id ])) %></li>
<li><%= button_to_filter "No one", kind: :assignments, object: "unassigned", data: { action: "filter-form#clearCategory", filter_form_name_param: "assignee_ids[]" } %></li>
<li><%= button_to_filter "Me", kind: :assignees, object: Current.user, data: { action: "filter-form#clearCategory", filter_form_name_param: "assignments" } %></li>
<% Current.account.users.active.without(Current.user).order(:name).each do |user| %>
<li><%= button_to_filter user.name, kind: :assignees, object: user, data: { action: "filter-form#clearCategory", filter_form_name_param: "assignments" } %></li>
<% end %>
</menu>
</div>
@@ -150,9 +99,9 @@
<div class="flex gap flex-item-grow">
<menu class="filter__menu unpad margin-none">
<li><strong class="filter__label">Assigned by…</strong></li>
<li><a href="">Me</a></li>
<% Current.account.users.active.order(:name).each do |user| %>
<li><%= link_to user.name, bubbles_path(filter.to_params.merge(assignments: nil, assignee_ids: [ user.id ])) %></li>
<li><%= button_to_filter "Me", kind: :assigners, object: Current.user %></li>
<% Current.account.users.active.without(Current.user).order(:name).each do |user| %>
<li><%= button_to_filter user.name, kind: :assigners, object: user %></li>
<% end %>
</menu>
</div>
@@ -160,12 +109,12 @@
</div>
<div class="flex align-center txt-align-center justify-space-between gap-half margin-block-start">
<button class="btn">
<%= tag.button class: "btn", form: :filter_form, formaction: filters_path, formmethod: :post do %>
<%= image_tag "bubbles.svg", aria: { hidden: true }, size: 24 %>
<span>Save to home</span>
</button>
<% end %>
<button class="btn btn--reversed">
<button class="btn btn--reversed" form="filter_form">
<span>Apply</span>
<%= image_tag "arrow-right.svg", aria: { hidden: true }, size: 24 %>
</button>
@@ -0,0 +1,4 @@
<%= turbo_stream.remove filter_button_id(params[:value], params[:name]) %>
<%= turbo_stream.append :filter_form do %>
<%= filter_button_tag display: params[:display], value: params[:value], name: params[:name], class: "fill-selected" %>
<% end %>
+1
View File
@@ -33,6 +33,7 @@ Rails.application.routes.draw do
end
resources :filters
resources :filter_buttons
resource :first_run
resource :session