From fb04249209ec3991881f0adb779a2a365df4c03f Mon Sep 17 00:00:00 2001 From: Jose Farias Date: Thu, 14 Nov 2024 21:50:38 -0600 Subject: [PATCH] Make filters into a simple form --- app/assets/stylesheets/filters.css | 4 + app/controllers/filter_chips_controller.rb | 4 - app/helpers/filters_helper.rb | 19 ++-- .../controllers/filter_form_controller.js | 16 ++-- app/models/filter.rb | 2 +- app/models/filter/fields.rb | 10 +- app/views/bubbles/_filters.html.erb | 96 ++++++------------- app/views/bubbles/index.html.erb | 8 +- .../filter_chips/create.turbo_stream.erb | 7 -- config/routes.rb | 1 - .../filter_chips_controller_test.rb | 16 ---- 11 files changed, 63 insertions(+), 120 deletions(-) delete mode 100644 app/controllers/filter_chips_controller.rb delete mode 100644 app/views/filter_chips/create.turbo_stream.erb delete mode 100644 test/controllers/filter_chips_controller_test.rb diff --git a/app/assets/stylesheets/filters.css b/app/assets/stylesheets/filters.css index 95d988c49..f89c34039 100644 --- a/app/assets/stylesheets/filters.css +++ b/app/assets/stylesheets/filters.css @@ -15,6 +15,10 @@ text-overflow: ellipsis; white-space: nowrap; + input:checked + & { + background-color: var(--color-selected); + } + @media (hover: hover) { &:hover { background-color: var(--color-selected); diff --git a/app/controllers/filter_chips_controller.rb b/app/controllers/filter_chips_controller.rb deleted file mode 100644 index d08c906f3..000000000 --- a/app/controllers/filter_chips_controller.rb +++ /dev/null @@ -1,4 +0,0 @@ -class FilterChipsController < ApplicationController - def create - end -end diff --git a/app/helpers/filters_helper.rb b/app/helpers/filters_helper.rb index 1b763e665..407b2a998 100644 --- a/app/helpers/filters_helper.rb +++ b/app/helpers/filters_helper.rb @@ -1,22 +1,15 @@ module FiltersHelper - def filter_chip_id(name, value) - "#{name}__filter--#{value}" - end - - def filter_chip_tag(text, name:, value:, **options) - tag.button id: filter_chip_id(name, value), class: [ "btn txt-small btn--remove", options.delete(:class) ], - data: { action: "filter-form#removeFilter form#submit", filter_form_target: "button" } do + def filter_chip_tag(text, name:, value:) + tag.button class: "btn txt-small btn--remove", data: { action: "filter-form#removeFilter form#submit", filter_form_target: "chip" } do concat hidden_field_tag(name, value, id: nil) concat tag.span(text) concat image_tag("close.svg", aria: { hidden: true }, size: 24) end end - def button_to_chip(text, params: {}, data: {}) - if params.present? - button_to text, filter_chips_path, method: :post, class: "btn btn--plain filter__button", params: params, data: data - else - button_tag text, type: :button, class: "btn btn--plain filter__button", data: data - end + def filter_hidden_field_tag(key, value) + is_collection = ->(key) { !Filter::Params::PERMITTED_PARAMS.include?(key.to_sym) } + name = is_collection.(key) ? "#{key}[]".to_sym : key + hidden_field_tag name, value, id: nil end end diff --git a/app/javascript/controllers/filter_form_controller.js b/app/javascript/controllers/filter_form_controller.js index 65ac570a1..3e54f5837 100644 --- a/app/javascript/controllers/filter_form_controller.js +++ b/app/javascript/controllers/filter_form_controller.js @@ -1,27 +1,31 @@ import { Controller } from "@hotwired/stimulus" export default class extends Controller { - static targets = [ "button" ] + static targets = [ "chip" ] connect() { - this.buttonTargets.forEach(button => this.#showButton(button)) + this.chipTargets.forEach(button => this.#showChip(button)) } removeFilter(event) { event.preventDefault() - this.#hideButton(event.target.closest("button")) + this.#hideChip(event.target.closest("button")) } clearCategory({ params: { name } }) { - this.element.querySelectorAll(`input[name="${name}"]`).forEach(input => this.#hideButton(input.closest("button"))) + name.split(",").forEach(name => { + this.element.querySelectorAll(`input[name="${name}"]`).forEach(input => { + input.checked = false + }) + }) } - #showButton(button) { + #showChip(button) { button.querySelector("input").disabled = false button.hidden = false } - #hideButton(button) { + #hideChip(button) { button.querySelector("input").disabled = true button.hidden = true } diff --git a/app/models/filter.rb b/app/models/filter.rb index cfaadb8ed..b388b1d9d 100644 --- a/app/models/filter.rb +++ b/app/models/filter.rb @@ -12,7 +12,7 @@ class Filter < ApplicationRecord end def digest_params(params) - Digest::MD5.hexdigest params.sort.to_json + Digest::MD5.hexdigest params.to_h.sort.to_json end end diff --git a/app/models/filter/fields.rb b/app/models/filter/fields.rb index a1b385a06..93faed6c7 100644 --- a/app/models/filter/fields.rb +++ b/app/models/filter/fields.rb @@ -13,7 +13,7 @@ module Filter::Fields store_accessor :fields, :indexed_by, :assignments, :terms def indexed_by - (super || default_fields[:indexed_by]).inquiry + (super || default_indexed_by).inquiry end def assignments @@ -25,6 +25,14 @@ module Filter::Fields end end + def default_indexed_by + default_fields[:indexed_by] + end + + def default_indexed_by? + indexed_by == default_indexed_by + end + private delegate :default_fields, to: :class, private: true end diff --git a/app/views/bubbles/_filters.html.erb b/app/views/bubbles/_filters.html.erb index 49057a0b3..285f3a16a 100644 --- a/app/views/bubbles/_filters.html.erb +++ b/app/views/bubbles/_filters.html.erb @@ -10,7 +10,7 @@ <%= form_with url: bubbles_path, method: :get, class: "flex-inline center align-center gap-half", data: { controller: "form" } do %> - <%= filter_chip_tag filter.indexed_by.humanize, name: "indexed_by", value: filter.indexed_by %> + <%= filter_chip_tag filter.indexed_by.humanize, name: "indexed_by", value: filter.indexed_by unless filter.default_indexed_by? %> <% filter.tags.each do |tag| %> <%= filter_chip_tag tag.hashtag, name: "tag_ids[]", value: tag.id %> @@ -55,74 +55,25 @@ -
- - - <%= form_with url: bubbles_path, id: :filter_form, method: :get, class: "flex-inline center align-center gap-half" do %> - <%= turbo_frame_tag :indexed_by_chips do %> - <%= filter_chip_tag filter.indexed_by.humanize, name: "indexed_by", value: filter.indexed_by, class: "fill-selected" %> - <% end %> - - <%= turbo_frame_tag :tag_chips do %> - <% filter.tags.each do |tag| %> - <%= filter_chip_tag tag.hashtag, name: "tag_ids[]", value: tag.id, class: "fill-selected" %> - <% end %> - <% end %> - - <%= turbo_frame_tag :assignee_chips do %> - <% filter.assignees.each do |assignee| %> - <%= filter_chip_tag "for #{assignee.name}", name: "assignee_ids[]", value: assignee.id, class: "fill-selected" %> - <% end %> - - <% if filter.assignments.present? %> - <%= filter_chip_tag filter.assignments.humanize, name: "assignments", value: filter.assignments, class: "fill-selected" %> - <% end %> - <% end %> - - <%= turbo_frame_tag :assigner_chips do %> - <% filter.assigners.each do |assigner| %> - <%= filter_chip_tag "by #{assigner.name}", name: "assigner_ids[]", value: assigner.id, class: "fill-selected" %> - <% end %> - <% end %> - - <%= turbo_frame_tag :bucket_chips do %> - <% filter.buckets.each do |bucket| %> - <%= filter_chip_tag "in #{bucket.name}", name: "bucket_ids[]", value: bucket.id, class: "fill-selected" %> - <% end %> - <% end %> - - <%= turbo_frame_tag :terms_chips do %> - <% filter.terms.each do |term| %> - <%= filter_chip_tag %Q("#{term}"), name: "terms[]", value: term, class: "fill-selected" %> - <% end %> - <% end %> + <%= form_with url: bubbles_path, id: :filter_form, method: :get, class: "flex flex-column gap full-width", style: "--border-color: var(--color-subtle)" do %> + <% Array(params[:terms]).each do |term| %> + <%= hidden_field_tag "terms[]", term, id: nil %> <% end %> -
- <%= form_with url: filter_chips_path, method: :post, class: "flex gap flex-item-grow align-center justify-center full-width center margin-block" do %> - <%= hidden_field_tag :name, "terms[]" %> - <%= hidden_field_tag :frame, :terms_chips %> - - - - - <% end %> - -
  • Sort by
  • +
  • + <%= radio_button_tag "indexed_by", filter.default_indexed_by, filter.default_indexed_by?, hidden: true %> + <%= label_tag "indexed_by_#{filter.default_indexed_by}", "Default", class: "btn btn--plain filter__button" %> +
  • + <% Filter::INDEXES.each do |index| %>
  • - <%= button_to_chip index.humanize, params: { text: index.humanize, name: "indexed_by", value: index, frame: :indexed_by_chips }, data: { action: "filter-form#clearCategory", filter_form_name_param: "indexed_by" } %> + <%= radio_button_tag "indexed_by", index, filter.indexed_by == index, hidden: true %> + <%= label_tag "indexed_by_#{index}", index.humanize, class: "btn btn--plain filter__button" %>
  • <% end %>
    @@ -134,12 +85,13 @@
  • In Project
  • - <%= button_to_chip "All projects", data: { action: "filter-form#clearCategory", filter_form_name_param: "bucket_ids[]" } %> + <%= button_tag "All projects", type: :button, class: "btn btn--plain filter__button", data: { action: "filter-form#clearCategory", filter_form_name_param: "bucket_ids[]" } %>
  • <% Current.user.buckets.order(:name).each do |bucket| %>
  • - <%= button_to_chip bucket.name, params: { text: "in #{bucket.name}", name: "bucket_ids[]", value: bucket.id, frame: :bucket_chips } %> + <%= check_box_tag "bucket_ids[]", bucket.id, filter.buckets.include?(bucket), id: "bucket_ids_#{bucket.id}", hidden: true %> + <%= label_tag "bucket_ids_#{bucket.id}", bucket.name, class: "btn btn--plain filter__button" %>
  • <% end %> @@ -152,7 +104,8 @@ <% Current.account.tags.order(:title).each do |tag| %>
  • - <%= button_to_chip tag.title, params: { text: tag.hashtag, name: "tag_ids[]", value: tag.id, frame: :tag_chips } %> + <%= check_box_tag "tag_ids[]", tag.id, filter.tags.include?(tag), id: "tag_ids_#{tag.id}", hidden: true %> + <%= label_tag "tag_ids_#{tag.id}", tag.hashtag, class: "btn btn--plain filter__button" %>
  • <% end %> @@ -164,14 +117,17 @@
  • Assigned to…
  • - <%= button_to_chip "No one", params: { text: "Unassigned", name: "assignments", value: "unassigned", frame: :assignee_chips }, data: { action: "filter-form#clearCategory", filter_form_name_param: "assignee_ids[]" } %> + <%= check_box_tag "assignments", "unassigned", filter.assignments.unassigned?, id: "assignments_unassigned", hidden: true, data: { action: "filter-form#clearCategory", filter_form_name_param: "assignee_ids[],assigner_ids[]" } %> + <%= label_tag "assignments_unassigned", "No one", class: "btn btn--plain filter__button" %>
  • - <%= button_to_chip "Me", params: { text: "for #{Current.user.name}", name: "assignee_ids[]", value: Current.user.id, frame: :assignee_chips }, data: { action: "filter-form#clearCategory", filter_form_name_param: "assignments" } %> + <%= check_box_tag "assignee_ids[]", Current.user.id, filter.assignees.include?(Current.user), id: "assignee_ids_me", hidden: true, data: { action: "filter-form#clearCategory", filter_form_name_param: "assignments" } %> + <%= label_tag "assignee_ids_me", "Me", class: "btn btn--plain filter__button" %>
  • <% Current.account.users.active.without(Current.user).order(:name).each do |user| %>
  • - <%= button_to_chip user.name, params: { text: "for #{user.name}", name: "assignee_ids[]", value: user.id, frame: :assignee_chips }, data: { action: "filter-form#clearCategory", filter_form_name_param: "assignments" } %> + <%= check_box_tag "assignee_ids[]", user.id, filter.assignees.include?(user), id: "assignee_ids_#{user.id}", hidden: true, data: { action: "filter-form#clearCategory", filter_form_name_param: "assignments" } %> + <%= label_tag "assignee_ids_#{user.id}", user.name, class: "btn btn--plain filter__button" %>
  • <% end %> @@ -183,17 +139,19 @@
  • Assigned by…
  • - <%= button_to_chip "Me", params: { text: "by #{Current.user.name}", name: "assigner_ids[]", value: Current.user.id, frame: :assigner_chips }, data: { action: "filter-form#clearCategory", filter_form_name_param: "assignments" } %> + <%= check_box_tag "assigner_ids[]", Current.user.id, filter.assigners.include?(Current.user), id: "assigner_ids_me", hidden: true, data: { action: "filter-form#clearCategory", filter_form_name_param: "assignments" } %> + <%= label_tag "assigner_ids_me", "Me", class: "btn btn--plain filter__button" %>
  • <% Current.account.users.active.without(Current.user).order(:name).each do |user| %>
  • - <%= button_to_chip user.name, params: { text: "by #{user.name}", name: "assigner_ids[]", value: user.id, frame: :assigner_chips }, data: { action: "filter-form#clearCategory", filter_form_name_param: "assignments" } %> + <%= check_box_tag "assigner_ids[]", user.id, filter.assigners.include?(user), id: "assigner_ids_#{user.id}", hidden: true, data: { action: "filter-form#clearCategory", filter_form_name_param: "assignments" } %> + <%= label_tag "assigner_ids_#{user.id}", user.name, class: "btn btn--plain filter__button" %>
  • <% end %>
    -
    + <% end %>
    <%= tag.button class: "btn", form: :filter_form, formaction: filters_path, formmethod: :post do %> diff --git a/app/views/bubbles/index.html.erb b/app/views/bubbles/index.html.erb index 406a1960d..42e364159 100644 --- a/app/views/bubbles/index.html.erb +++ b/app/views/bubbles/index.html.erb @@ -34,8 +34,12 @@
    - <%= form_tag bubbles_path(@filter.to_params), method: :get do %> - <%= search_field_tag :term, params[:term], class: "input center flex-inline", placeholder: "Type to filter…" %> + <%= form_tag bubbles_path, method: :get do %> + <% @filter.to_params.each do |key, value| %> + <%= filter_hidden_field_tag key, value %> + <% end %> + + <%= search_field_tag "terms[]", nil, class: "input center flex-inline", placeholder: "Type to filter…", id: nil %> <% end %>
    diff --git a/app/views/filter_chips/create.turbo_stream.erb b/app/views/filter_chips/create.turbo_stream.erb deleted file mode 100644 index 17d0d268f..000000000 --- a/app/views/filter_chips/create.turbo_stream.erb +++ /dev/null @@ -1,7 +0,0 @@ -<% text = params[:text] || %Q("#{params[:value]}") %> - -<%= turbo_stream.remove filter_chip_id(params[:name], params[:value]) %> - -<%= turbo_stream.append params[:frame] do %> - <%= filter_chip_tag text, name: params[:name], value: params[:value], class: "fill-selected" %> -<% end %> diff --git a/config/routes.rb b/config/routes.rb index dffa263f2..0778fb130 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -33,7 +33,6 @@ Rails.application.routes.draw do end resources :filters - resources :filter_chips resource :first_run resource :session diff --git a/test/controllers/filter_chips_controller_test.rb b/test/controllers/filter_chips_controller_test.rb deleted file mode 100644 index 8be4c3b6c..000000000 --- a/test/controllers/filter_chips_controller_test.rb +++ /dev/null @@ -1,16 +0,0 @@ -require "test_helper" - -class FilterChipsControllerTest < ActionDispatch::IntegrationTest - setup do - sign_in_as :kevin - end - - test "create" do - post filter_chips_url(format: :turbo_stream), params: { text: "for David", name: "assignee_ids[]", value: users(:david).id, frame: "assignee_chips" } - assert_response :success - - assert_turbo_stream action: :remove, target: "assignee_ids[]__filter--#{users(:david).id}" - assert_turbo_stream action: :append, target: "assignee_chips" - assert_select "button", text: "for David" - end -end