From 0baaf5d87f0cce1d3afbb6e8688a68c00a6d1645 Mon Sep 17 00:00:00 2001 From: Jose Farias Date: Mon, 11 Nov 2024 13:46:15 -0600 Subject: [PATCH] Wire up filter form sans search --- app/controllers/filter_buttons_controller.rb | 4 + app/helpers/filters_helper.rb | 62 ++++++++--- .../controllers/filter_form_controller.js | 17 +++ app/models/filter/params.rb | 24 +++-- app/views/bubbles/_filters.html.erb | 101 +++++------------- .../filter_buttons/create.turbo_stream.erb | 4 + config/routes.rb | 1 + 7 files changed, 112 insertions(+), 101 deletions(-) create mode 100644 app/controllers/filter_buttons_controller.rb create mode 100644 app/javascript/controllers/filter_form_controller.js create mode 100644 app/views/filter_buttons/create.turbo_stream.erb diff --git a/app/controllers/filter_buttons_controller.rb b/app/controllers/filter_buttons_controller.rb new file mode 100644 index 000000000..20d316679 --- /dev/null +++ b/app/controllers/filter_buttons_controller.rb @@ -0,0 +1,4 @@ +class FilterButtonsController < ApplicationController + def create + end +end diff --git a/app/helpers/filters_helper.rb b/app/helpers/filters_helper.rb index 05caac3d0..80621407e 100644 --- a/app/helpers/filters_helper.rb +++ b/app/helpers/filters_helper.rb @@ -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 diff --git a/app/javascript/controllers/filter_form_controller.js b/app/javascript/controllers/filter_form_controller.js new file mode 100644 index 000000000..b55cc6069 --- /dev/null +++ b/app/javascript/controllers/filter_form_controller.js @@ -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 + } +} diff --git a/app/models/filter/params.rb b/app/models/filter/params.rb index 1077203ab..ee63c983e 100644 --- a/app/models/filter/params.rb +++ b/app/models/filter/params.rb @@ -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 diff --git a/app/views/bubbles/_filters.html.erb b/app/views/bubbles/_filters.html.erb index c8a511ac5..ebe553043 100644 --- a/app/views/bubbles/_filters.html.erb +++ b/app/views/bubbles/_filters.html.erb @@ -1,6 +1,6 @@ -
+

- Writebook + <%= filter.buckets.first&.name || "All projects" %>

@@ -9,35 +9,9 @@ Filter - - - - - - - - - - - + <%= form_with url: bubbles_path, method: :get, class: "flex-inline center align-center gap-half", data: { controller: "form" } do %> + <%= filter_buttons filter %> + <% end %>
@@ -45,9 +19,9 @@
-

- Writebook -

+

+ <%= filter.buckets.first&.name || "All projects" %> +

- - - - - - - - - - - + <%= 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 %>
@@ -109,7 +57,7 @@
  • Sort by
  • <% Filter::INDEXES.each do |index| %> -
  • <%= link_to index.humanize, bubbles_path(filter.to_params.merge(indexed_by: index)), class: "filter__button" %>
  • +
  • <%= button_to_filter index.humanize, kind: :indexed_by, object: index, data: { action: "filter-form#clearCategory", filter_form_name_param: "indexed_by" } %>
  • <% end %>
    @@ -118,9 +66,9 @@
  • In Project
  • -
  • <%= link_to "All projects", bubbles_path(filter.to_params.merge(bucket_ids: nil)), class: "filter__button" %>
  • +
  • <%= button_to_filter "All projects", kind: :buckets, object: nil, data: { action: "filter-form#clearCategory", filter_form_name_param: "bucket_ids[]" } %>
  • <% Current.user.buckets.order(:name).each do |bucket| %> -
  • <%= link_to bucket.name, bubbles_path(filter.to_params.merge(bucket_ids: [ bucket.id ])), class: "filter__button" %>
  • +
  • <%= button_to_filter bucket.name, kind: :buckets, object: bucket %>
  • <% end %>
    @@ -130,7 +78,7 @@
  • Tagged
  • <% Current.account.tags.order(:title).each do |tag| %> -
  • <%= link_to tag.title, bubbles_path(filter.to_params.merge(tag_ids: [ tag.id ])) %>
  • +
  • <%= button_to_filter tag.title, kind: :tags, object: tag %>
  • <% end %>
    @@ -139,9 +87,10 @@
  • Assigned to…
  • -
  • <%= link_to "No one", bubbles_path(filter.to_params.merge(assignments: :unassigned, assignee_ids: [])), class: "filter__button" %>
  • - <% Current.account.users.active.order(:name).each do |user| %> -
  • <%= link_to user.name, bubbles_path(filter.to_params.merge(assignments: nil, assignee_ids: [ user.id ])) %>
  • +
  • <%= button_to_filter "No one", kind: :assignments, object: "unassigned", data: { action: "filter-form#clearCategory", filter_form_name_param: "assignee_ids[]" } %>
  • +
  • <%= button_to_filter "Me", kind: :assignees, object: Current.user, data: { action: "filter-form#clearCategory", filter_form_name_param: "assignments" } %>
  • + <% Current.account.users.active.without(Current.user).order(:name).each do |user| %> +
  • <%= button_to_filter user.name, kind: :assignees, object: user, data: { action: "filter-form#clearCategory", filter_form_name_param: "assignments" } %>
  • <% end %>
    @@ -150,9 +99,9 @@
  • Assigned by…
  • -
  • Me
  • - <% Current.account.users.active.order(:name).each do |user| %> -
  • <%= link_to user.name, bubbles_path(filter.to_params.merge(assignments: nil, assignee_ids: [ user.id ])) %>
  • +
  • <%= button_to_filter "Me", kind: :assigners, object: Current.user %>
  • + <% Current.account.users.active.without(Current.user).order(:name).each do |user| %> +
  • <%= button_to_filter user.name, kind: :assigners, object: user %>
  • <% end %>
    @@ -160,12 +109,12 @@
    - + <% end %> - diff --git a/app/views/filter_buttons/create.turbo_stream.erb b/app/views/filter_buttons/create.turbo_stream.erb new file mode 100644 index 000000000..0a242797e --- /dev/null +++ b/app/views/filter_buttons/create.turbo_stream.erb @@ -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 %> diff --git a/config/routes.rb b/config/routes.rb index 0778fb130..c412efff6 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -33,6 +33,7 @@ Rails.application.routes.draw do end resources :filters + resources :filter_buttons resource :first_run resource :session