Merge branch 'main' into logo-placeholder-update
* main: Need to return all collections so it's not blank Button to add a new filter Update test for new redirect Comparing params is fragile, use `id` for saved filters Update summary tests Improve summary display in menu Add keyboard navigation and filtering to quick filters Copy Keep stage when clearing Keep the current filter params after deleting a saved filter so you can change your mind Update test because we now drop all filters on destroy New UI for exposing filter options and saving/deleting them Unnecessary These aren't actually in the events namespace, use utility class
This commit is contained in:
@@ -122,10 +122,6 @@
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.events__popup {
|
||||
margin-block-start: var(--block-space-half);
|
||||
}
|
||||
|
||||
/* Event
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
@layer components {
|
||||
.filters {
|
||||
view-transition-name: "filters";
|
||||
z-index: var(--z-popup);
|
||||
|
||||
#header:has(&) {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
z-index: var(--z-popup);
|
||||
}
|
||||
|
||||
.btn {
|
||||
@@ -94,19 +97,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
.panel:is(.filter__popup) {
|
||||
--panel-size: 100ch;
|
||||
--panel-padding: var(--block-space);
|
||||
|
||||
inline-size: auto !important;
|
||||
min-inline-size: var(--panel-size);
|
||||
max-block-size: calc(90dvh - (2 * var(--block-space-double)));
|
||||
max-inline-size: calc(100dvw - (2 * var(--block-space-double)));
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.quick-filter {
|
||||
&:has(input:not(.default-value):checked) {
|
||||
&:not(.default-value):has(.checked) {
|
||||
.input--select {
|
||||
--input-background: var(--color-selected);
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@
|
||||
}
|
||||
|
||||
&:has(input:checked) {
|
||||
--btn-background: var(--color-ink-lightest);
|
||||
--btn-background: transparent;
|
||||
--btn-color: var(--color-ink);
|
||||
|
||||
.icon {
|
||||
|
||||
@@ -9,6 +9,11 @@ module FilterScoped
|
||||
DEFAULT_PARAMS = { indexed_by: "latest" }
|
||||
|
||||
def set_filter
|
||||
@filter = Current.user.filters.from_params params.reverse_merge(**DEFAULT_PARAMS).permit(*Filter::PERMITTED_PARAMS)
|
||||
@expand_all = params[:expand_all]
|
||||
if params[:filter_id].present?
|
||||
@filter = Current.user.filters.find(params[:filter_id])
|
||||
else
|
||||
@filter = Current.user.filters.from_params params.reverse_merge(**DEFAULT_PARAMS).permit(*Filter::PERMITTED_PARAMS)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -3,16 +3,17 @@ class FiltersController < ApplicationController
|
||||
|
||||
def create
|
||||
@filter = Current.user.filters.remember filter_params
|
||||
redirect_to cards_path(@filter.as_params)
|
||||
redirect_to cards_path(filter_id: @filter.id)
|
||||
end
|
||||
|
||||
def destroy
|
||||
filter_params = @filter.as_params
|
||||
@filter.destroy!
|
||||
|
||||
if request.referer == root_url
|
||||
redirect_to root_path
|
||||
else
|
||||
redirect_to cards_path(@filter.as_params)
|
||||
redirect_to cards_path(filter_params)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -21,6 +21,14 @@ module FiltersHelper
|
||||
hidden_field_tag name, value, id: nil
|
||||
end
|
||||
|
||||
def filter_selected_collections_sentence(filter)
|
||||
if filter.collections.any?
|
||||
filter.collections.collect { "<strong>#{it.name}</strong>" }.uniq.sort.to_sentence
|
||||
else
|
||||
tag.strong "All collections"
|
||||
end
|
||||
end
|
||||
|
||||
def filter_selected_collections_label(filter)
|
||||
selected_collections = if filter.collections.any?
|
||||
filter.collections.collect { "<strong>#{it.name}</strong>" }.uniq.sort.to_sentence
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
module Filter::Summarized
|
||||
def summary
|
||||
[ index_summary, tag_summary, assignee_summary, creator_summary, stage_summary, terms_summary ].compact.to_sentence + " #{collection_summary}"
|
||||
[ index_summary, tag_summary, assignee_summary, creator_summary, stage_summary, terms_summary ].compact.to_sentence
|
||||
end
|
||||
|
||||
private
|
||||
def index_summary
|
||||
indexed_by.humanize
|
||||
unless indexed_by.latest?
|
||||
indexed_by.humanize
|
||||
end
|
||||
end
|
||||
|
||||
def tag_summary
|
||||
if tags.any?
|
||||
"tagged #{tags.map(&:hashtag).to_choice_sentence}"
|
||||
"#{tags.map(&:hashtag).to_choice_sentence}"
|
||||
end
|
||||
end
|
||||
|
||||
@@ -28,12 +30,6 @@ module Filter::Summarized
|
||||
end
|
||||
end
|
||||
|
||||
def collection_summary
|
||||
if collections.any?
|
||||
"in #{collections.pluck(:name).to_choice_sentence}"
|
||||
end
|
||||
end
|
||||
|
||||
def terms_summary
|
||||
if terms.any?
|
||||
"matching #{terms.map { |term| %Q("#{term}") }.to_sentence}"
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
Recently closed
|
||||
</button>
|
||||
|
||||
<dialog class="events__popup popup panel flex-column align-start gap-half fill-white shadow"
|
||||
<dialog class="margin-block-start-half popup panel flex-column align-start gap-half fill-white shadow"
|
||||
aria-label="Closed with reason…" aria-description="Closed with reason…"
|
||||
data-dialog-target="dialog" data-action="turbo:before-cache@document->dialog#close">
|
||||
<strong class="popup__title margin-block-start-half pad-inline-half">Closed with reason…</strong>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<% end %>
|
||||
</button>
|
||||
|
||||
<dialog class="events__popup popup panel flex-column align-start gap-half fill-white shadow"
|
||||
<dialog class="margin-block-start-half popup panel flex-column align-start gap-half fill-white shadow"
|
||||
aria-label="In stage…" aria-description="In stage…"
|
||||
data-dialog-target="dialog" data-action="turbo:before-cache@document->dialog#close">
|
||||
<strong class="popup__title margin-block-start-half pad-inline-half">In stage(s)…</strong>
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<strong class="txt-medium overflow-ellipsis margin-none">Fizzy</strong>
|
||||
<% end %>
|
||||
|
||||
<%= tag.dialog class: "fizzy-dialog filter events__popup popup popup--animated panel flex-column align-start fill-white",
|
||||
<%= tag.dialog class: "fizzy-dialog filter margin-block-start-half popup popup--animated panel flex-column align-start fill-white",
|
||||
data: {
|
||||
action: "turbo:before-cache@document->dialog#close keydown->navigable-list#navigate filter:changed->navigable-list#reset toggle->filter#filter",
|
||||
controller: "filter navigable-list",
|
||||
@@ -32,12 +32,12 @@
|
||||
|
||||
<%= render "events/filter/header" %>
|
||||
|
||||
<strong class="popup__group-title">Collections</strong>
|
||||
<%= form_with url: events_path, method: :get, class: "popup__list",
|
||||
data: { controller: "form" } do |form| %>
|
||||
<% if Current.user.collections.many? %>
|
||||
<ul class="popup__list">
|
||||
<%= render "events/filter/custom_collections" %>
|
||||
<strong class="popup__group-title">Collections</strong>
|
||||
<%= render "events/filter/all_collections_option", form: form, filter: filter %>
|
||||
<%= render partial: "events/filter/collection_option", collection: Current.user.collections.ordered_by_recently_accessed, as: :collection, locals: { form: form, filter: filter } %>
|
||||
</ul>
|
||||
|
||||
@@ -1,11 +1,22 @@
|
||||
<div class="popup__list">
|
||||
<% @filters.each do |filter| %>
|
||||
<div class="popup__group flex align-center full-width gap-half overflow-ellipsis" data-filter-target="item" data-navigable-list-target="item">
|
||||
<%= link_to cards_path(**filter.as_params), class: "btn popup__new popup__item" do %>
|
||||
<%= icon_tag "filter" %>
|
||||
<span class="overflow-ellipsis"><%= filter.summary %></span>
|
||||
<span class="translucent flex-item-no-shrink flex-item-justify-end"> ›</span>
|
||||
<% end %>
|
||||
<strong class="popup__group-title">Saved filters</strong>
|
||||
<div class="popup__group flex align-center full-width gap-half overflow-ellipsis" data-navigable-list-target="item">
|
||||
<%= link_to cards_path(expand_all: true), class: "btn popup__new popup__item" do %>
|
||||
<%= icon_tag "bookmark" %>
|
||||
<div class="flex flex-column txt-tight-lines min-width txt-small">
|
||||
<strong class="overflow-ellipsis">Create a new filter</strong>
|
||||
</div>
|
||||
<span class="translucent flex-item-no-shrink flex-item-justify-end"> ›</span>
|
||||
<% end %>
|
||||
</div>
|
||||
<% @filters.each do |filter| %>
|
||||
<div class="popup__group flex align-center full-width gap-half overflow-ellipsis" data-navigable-list-target="item">
|
||||
<%= link_to cards_path(filter_id: filter.id), class: "btn popup__new popup__item" do %>
|
||||
<%= icon_tag "bookmark" %>
|
||||
<div class="flex flex-column txt-tight-lines min-width txt-small">
|
||||
<span class="overflow-ellipsis"><%= filter_selected_collections_sentence(filter).html_safe %></span>
|
||||
<span class="overflow-ellipsis"><%= filter.summary %></span>
|
||||
</div>
|
||||
<span class="translucent flex-item-no-shrink flex-item-justify-end"> ›</span>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
@@ -1,53 +1,85 @@
|
||||
<% if filter.assignees.any? %>
|
||||
<% if filter.assignees.any? || @expand_all %>
|
||||
<div class="quick-filter position-relative" data-controller="dialog" data-action="keydown.esc->dialog#close click@document->dialog#closeOnClickOutside">
|
||||
<button class="btn input input--select flex-inline txt-x-small" data-action="click->dialog#open:stop">
|
||||
<span class="overflow-ellipsis">
|
||||
<% if filter.assignment_status.unassigned? %>
|
||||
No one
|
||||
<% elsif filter.assignees.any? %>
|
||||
Assigned to <%= filter.assignees.map(&:familiar_name).to_sentence %>
|
||||
Assigned to <%= filter.assignees.map(&:familiar_name).to_sentence(two_words_connector: " or ", last_word_connector: ", or ") %>
|
||||
<% else %>
|
||||
Assigned to…
|
||||
<% end %>
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<dialog class="events__popup popup panel flex-column align-start gap-half fill-white shadow" data-dialog-target="dialog" data-action="turbo:before-cache@document->dialog#close">
|
||||
<strong class="popup__title margin-block-start-half pad-inline-half overflow-ellipsis">Assigned to…</strong>
|
||||
<%= form_with url: cards_path, method: :get, class: "popup__list",
|
||||
data: { controller: "form" } do |form| %>
|
||||
<% filter.as_params.except(:assignee_ids, :assignment_status).each do |key, value| %>
|
||||
<%= filter_hidden_field_tag key, value %>
|
||||
<% end %>
|
||||
<%= tag.dialog class: "margin-block-start-half popup panel flex-column align-start gap-half fill-white shadow txt-small", data: {
|
||||
action: "turbo:before-cache@document->dialog#close keydown->navigable-list#navigate filter:changed->navigable-list#reset toggle->filter#filter",
|
||||
aria: { label: "Assigned to…", aria_description: "Assigned to…" },
|
||||
controller: "filter navigable-list",
|
||||
dialog_target: "dialog",
|
||||
navigable_list_focus_on_selection_value: false,
|
||||
navigable_list_actionable_items_value: true } do %>
|
||||
<strong class="popup__title txt-nowrap">Assigned to…</strong>
|
||||
|
||||
<%= link_to cards_path(filter.as_params.except(:assignee_ids, :assignment_status)), class: "btn popup__item" do %>
|
||||
<span class="overflow-ellipsis">Clear all</span>
|
||||
<% end %>
|
||||
|
||||
<div class="btn popup__item">
|
||||
<%= form.check_box "assignment_status", {
|
||||
checked: filter.assignment_status.unassigned?,
|
||||
data: { action: "change->form#submit" },
|
||||
include_hidden: false,
|
||||
}, "unassigned" %>
|
||||
|
||||
<%= form.label :assignment_status, "No one", class: "overflow-ellipsis" %>
|
||||
<%= icon_tag "check", class: "checked flex-item-justify-end" %>
|
||||
</div>
|
||||
|
||||
<% User.active.order(:name).each do |user| %>
|
||||
<div class="btn popup__item">
|
||||
<%= form.check_box "assignee_ids[]", {
|
||||
checked: filter.assignees.include?(user),
|
||||
data: { action: "change->form#submit" },
|
||||
include_hidden: false,
|
||||
}, user.id %>
|
||||
|
||||
<%= form.label "assignee_ids[]", user.name, for: dom_id(user, :filter), class: "overflow-ellipsis" %>
|
||||
<%= icon_tag "check", class: "checked flex-item-justify-end" %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% if User.active.many? %>
|
||||
<%= text_field_tag :search, nil, placeholder: "Filter…", class: "input input--transparent txt-small", autofocus: true,
|
||||
type: "search", autocorrect: "off", autocomplete: "off", data: { "1p-ignore": "true", filter_target: "input", action: "input->filter#filter" } %>
|
||||
<% end %>
|
||||
</dialog>
|
||||
|
||||
<ul class="popup__list" data-filter-target="list">
|
||||
<li class="popup__group flex align-center" data-value="no one" data-filter-target="item" data-navigable-list-target="item">
|
||||
<%= form_with url: cards_path, method: :get, class: "full-width", data: { controller: "form" } do |form| %>
|
||||
<% filter.as_params.except(:assignee_ids, :assignment_status).each do |key, value| %>
|
||||
<%= filter_hidden_field_tag key, value %>
|
||||
<% end %>
|
||||
|
||||
<% unless filter.assignment_status.unassigned? %>
|
||||
<%= hidden_field_tag :assignment_status, "unassigned" %>
|
||||
<% end %>
|
||||
|
||||
<% if @expand_all %>
|
||||
<%= hidden_field_tag :expand_all, @expand_all %>
|
||||
<% end %>
|
||||
|
||||
<%= form.button type: "submit", class: "btn popup__item min-width full-width unpad-inline" do %>
|
||||
<span class="overflow-ellipsis flex-item-grow">No one</span>
|
||||
<% if filter.assignment_status.unassigned? %>
|
||||
<%= icon_tag "check", class: "checked flex-item-justify-end" %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</li>
|
||||
<% User.active.order(:name).each do |user| %>
|
||||
<li class="popup__group flex align-center" data-value="<%= user.name.downcase %>" data-filter-target="item" data-navigable-list-target="item">
|
||||
<%= form_with url: cards_path, method: :get, class: "full-width", data: { controller: "form" } do |form| %>
|
||||
<% filter.as_params.except(:assignee_ids, :assignment_status).each do |key, value| %>
|
||||
<%= filter_hidden_field_tag key, value %>
|
||||
<% end %>
|
||||
|
||||
<% filter.assignees.each do |existing_assignee| %>
|
||||
<% unless existing_assignee == user %>
|
||||
<%= hidden_field_tag "assignee_ids[]", existing_assignee.id %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<% unless filter.assignees.include?(user) %>
|
||||
<%= hidden_field_tag "assignee_ids[]", user.id %>
|
||||
<% end %>
|
||||
|
||||
<% if @expand_all %>
|
||||
<%= hidden_field_tag :expand_all, @expand_all %>
|
||||
<% end %>
|
||||
|
||||
<%= form.button type: "submit", class: "btn popup__item min-width full-width unpad-inline" do %>
|
||||
<span class="overflow-ellipsis flex-item-grow"><%= user.name %></span>
|
||||
<% if filter.assignees.include?(user) %>
|
||||
<%= icon_tag "check", class: "checked flex-item-justify-end" %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</li>
|
||||
<% end %>
|
||||
</ul>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
@@ -1,56 +1,62 @@
|
||||
<% if filter.creators.any? %>
|
||||
<% if filter.creators.any? || @expand_all %>
|
||||
<div class="quick-filter position-relative" data-controller="dialog"
|
||||
data-action="keydown.esc->dialog#close click@document->dialog#closeOnClickOutside">
|
||||
<button class="btn input input--select flex-inline txt-x-small" data-action="click->dialog#open:stop">
|
||||
<span class="overflow-ellipsis">
|
||||
<% if filter.creators.any? %>
|
||||
<%= "Added by #{filter.creators.map(&:familiar_name).to_sentence}" %>
|
||||
<%= "Added by #{filter.creators.map(&:familiar_name).to_sentence(two_words_connector: " or ", last_word_connector: ", or ")}" %>
|
||||
<% else %>
|
||||
Added by…
|
||||
<% end %>
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<dialog class="events__popup popup panel flex-column align-start gap-half fill-white shadow"
|
||||
aria-label="Added by…" aria-description="Added by…"
|
||||
data-dialog-target="dialog" data-action="turbo:before-cache@document->dialog#close">
|
||||
<strong class="popup__title margin-block-start-half pad-inline-half">Added by…</strong>
|
||||
<%= form_with url: cards_path, method: :get, class: "popup__list",
|
||||
data: { controller: "form" } do |form| %>
|
||||
<% filter.as_params.except(:creator_ids).each do |key, value| %>
|
||||
<%= filter_hidden_field_tag key, value %>
|
||||
<% end %>
|
||||
<%= tag.dialog class: "margin-block-start-half popup panel flex-column align-start gap-half fill-white shadow txt-small", data: {
|
||||
action: "turbo:before-cache@document->dialog#close keydown->navigable-list#navigate filter:changed->navigable-list#reset toggle->filter#filter",
|
||||
aria: { label: "Added by…", aria_description: "Added by…" },
|
||||
controller: "filter navigable-list",
|
||||
dialog_target: "dialog",
|
||||
navigable_list_focus_on_selection_value: false,
|
||||
navigable_list_actionable_items_value: true } do %>
|
||||
<strong class="popup__title txt-nowrap">Added by…</strong>
|
||||
|
||||
<%= link_to cards_path(filter.as_params.except(:creator_ids)), class: "btn popup__item" do %>
|
||||
<span class="overflow-ellipsis">Clear all</span>
|
||||
<% end %>
|
||||
|
||||
<div class="btn popup__item">
|
||||
<%= form.check_box :creator_ids, {
|
||||
multiple: true,
|
||||
checked: filter.creators.include?(Current.user),
|
||||
data: { action: "change->form#submit" },
|
||||
include_hidden: false,
|
||||
}, Current.user.id %>
|
||||
|
||||
<%= form.label :creator_ids, "Me", for: form.field_id(:creator_ids, Current.user.id), class: "overflow-ellipsis" %>
|
||||
<%= icon_tag "check", class: "checked flex-item-justify-end" %>
|
||||
</div>
|
||||
|
||||
<% User.active.without(Current.user).order(:name).each do |user| %>
|
||||
<div class="btn popup__item">
|
||||
<%= form.check_box :creator_ids, {
|
||||
multiple: true,
|
||||
checked: filter.creators.include?(user),
|
||||
data: { action: "change->form#submit" },
|
||||
include_hidden: false,
|
||||
}, user.id %>
|
||||
|
||||
<%= form.label :creator_ids, user.name, for: form.field_id(:creator_ids, user.id), class: "overflow-ellipsis" %>
|
||||
<%= icon_tag "check", class: "checked flex-item-justify-end" %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% if User.active.many? %>
|
||||
<%= text_field_tag :search, nil, placeholder: "Filter…", class: "input input--transparent txt-small", autofocus: true,
|
||||
type: "search", autocorrect: "off", autocomplete: "off", data: { "1p-ignore": "true", filter_target: "input", action: "input->filter#filter" } %>
|
||||
<% end %>
|
||||
</dialog>
|
||||
|
||||
<ul class="popup__list" data-filter-target="list">
|
||||
<% User.active.order(:name).each do |user| %>
|
||||
<li class="popup__group flex align-center" data-value="<%= user.name.downcase %>" data-filter-target="item" data-navigable-list-target="item">
|
||||
<%= form_with url: cards_path, method: :get, class: "full-width", data: { controller: "form" } do |form| %>
|
||||
<% filter.as_params.except(:creator_ids).each do |key, value| %>
|
||||
<%= filter_hidden_field_tag key, value %>
|
||||
<% end %>
|
||||
|
||||
<% filter.creators.each do |existing_creators| %>
|
||||
<% unless existing_creators == user %>
|
||||
<%= hidden_field_tag "creator_ids[]", existing_creators.id %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<% unless filter.creators.include?(user) %>
|
||||
<%= hidden_field_tag "creator_ids[]", user.id %>
|
||||
<% end %>
|
||||
|
||||
<% if @expand_all %>
|
||||
<%= hidden_field_tag :expand_all, @expand_all %>
|
||||
<% end %>
|
||||
|
||||
<%= form.button type: "submit", class: "btn popup__item min-width full-width unpad-inline" do %>
|
||||
<span class="overflow-ellipsis flex-item-grow"><%= user.name %></span>
|
||||
<% if filter.creators.include?(user) %>
|
||||
<%= icon_tag "check", class: "checked flex-item-justify-end" %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</li>
|
||||
<% end %>
|
||||
</ul>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<%# Don't delete this file just yet, it's coming back soon. %>
|
||||
<dialog class="filter__popup dialog panel fill-white shadow" aria-label="Filter" aria-description="Filter" data-dialog-target="dialog">
|
||||
<dialog class="dialog panel fill-white shadow" aria-label="Filter" aria-description="Filter" data-dialog-target="dialog">
|
||||
<div class="flex flex-column gap-half">
|
||||
<div class="flex align-center gap-half justify-space-between">
|
||||
<span class="btn btn--placeholder txt-small" aria-hidden="true"></span>
|
||||
|
||||
@@ -1,32 +1,44 @@
|
||||
<% if !filter.indexed_by.latest? %>
|
||||
<div class="quick-filter position-relative" data-controller="dialog" data-action="keydown.esc->dialog#close click@document->dialog#closeOnClickOutside">
|
||||
<button class="btn input input--select flex-inline txt-small" data-action="click->dialog#open:stop">
|
||||
<% if !filter.indexed_by.latest? || @expand_all %>
|
||||
<div class="quick-filter position-relative <%= "default-value" if filter.indexed_by.latest? %>" data-controller="dialog" data-action="keydown.esc->dialog#close click@document->dialog#closeOnClickOutside">
|
||||
<button class="btn input input--select flex-inline txt-x-small" data-action="click->dialog#open:stop">
|
||||
<span class="overflow-ellipsis">
|
||||
<%= filter.indexed_by.humanize %>
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<dialog class="events__popup popup panel flex-column align-start gap-half fill-white shadow"
|
||||
aria-label="Sort by…" aria-description="Sort by…"
|
||||
data-dialog-target="dialog" data-action="turbo:before-cache@document->dialog#close">
|
||||
<strong class="popup__title margin-block-start-half pad-inline-half">Sort by…</strong>
|
||||
<%= form_with url: cards_path, method: :get, class: "popup__list",
|
||||
data: { controller: "form" } do |form| %>
|
||||
<% filter.as_params.except(:indexed_by).each do |key, value| %>
|
||||
<%= filter_hidden_field_tag key, value %>
|
||||
<% end %>
|
||||
|
||||
<%= tag.dialog class: "margin-block-start-half popup panel flex-column align-start gap-half fill-white shadow txt-small", data: {
|
||||
action: "turbo:before-cache@document->dialog#close keydown->navigable-list#navigate",
|
||||
aria: { label: "Sort by…", aria_description: "Sort by…" },
|
||||
controller: "navigable-list",
|
||||
dialog_target: "dialog",
|
||||
navigable_list_focus_on_selection_value: false,
|
||||
navigable_list_actionable_items_value: true } do %>
|
||||
<strong class="popup__title txt-nowrap">Sort by…</strong>
|
||||
|
||||
<ul class="popup__list" data-filter-target="list">
|
||||
<% Filter::INDEXES.each do |index| %>
|
||||
<div class="btn popup__item">
|
||||
<%= form.radio_button :indexed_by, index,
|
||||
checked: filter.indexed_by == index,
|
||||
data: { action: "change->form#submit" } %>
|
||||
<li class="popup__group flex align-center" data-navigable-list-target="item">
|
||||
<%= form_with url: cards_path, method: :get, class: "full-width", data: { controller: "form" } do |form| %>
|
||||
<% filter.as_params.except(:indexed_by).each do |key, value| %>
|
||||
<%= filter_hidden_field_tag key, value %>
|
||||
<% end %>
|
||||
|
||||
<%= form.label :indexed_by, index.humanize, value: index, class: "overflow-ellipsis" %>
|
||||
<%= icon_tag "check", class: "checked flex-item-justify-end" %>
|
||||
</div>
|
||||
<%= hidden_field_tag :indexed_by, index %>
|
||||
|
||||
<% if @expand_all %>
|
||||
<%= hidden_field_tag :expand_all, @expand_all %>
|
||||
<% end %>
|
||||
|
||||
<%= form.button type: "submit", class: "btn popup__item min-width full-width unpad-inline" do %>
|
||||
<span class="overflow-ellipsis flex-item-grow"><%= index.humanize %></span>
|
||||
<% if filter.indexed_by == index %>
|
||||
<%= icon_tag "check", class: "checked flex-item-justify-end" %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</li>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</dialog>
|
||||
</ul>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
@@ -1,17 +1,46 @@
|
||||
<div class="filters flex align-center gap-half margin-none-block-end margin-block-start-half justify-center center">
|
||||
<div class="flex-inline center align-center gap-half">
|
||||
<% if any_filters?(filter) %>
|
||||
<% if @expand_all %>
|
||||
<%= link_to cards_path(filter.as_params), class: "btn txt-x-small btn--reversed", aria: { selected: true} do %>
|
||||
<%= icon_tag "filter" %>
|
||||
<span class="for-screen-reader">Edit filters</span>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<%= link_to cards_path(filter.as_params.merge(expand_all: true)), class: "btn txt-x-small" do %>
|
||||
<%= icon_tag "filter" %>
|
||||
<span class="for-screen-reader">Edit filters</span>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<%= render "filters/indexed_by", filter: filter %>
|
||||
<%= render "filters/tags", filter: filter %>
|
||||
<%= render "filters/assignees", filter: filter %>
|
||||
<%= render "filters/creators", filter: filter %>
|
||||
<%= render "filters/stages", filter: filter %>
|
||||
<%# FIXME LATER: this needs to be able to allow selection of unique stages across all active workflows %>
|
||||
<%#= render "filters/stages", filter: filter %>
|
||||
<%= render "filters/cards", filter: filter %>
|
||||
<%= render "filters/indexed_by", filter: filter %>
|
||||
|
||||
|
||||
<% filter.terms.each do |term| %>
|
||||
<%= filter_chip_tag %Q("#{term}"), filter.as_params_without(:terms, term) %>
|
||||
<% end %>
|
||||
|
||||
<% if any_filters?(filter) %>
|
||||
<% if filter.persisted? %>
|
||||
<%= button_to filter_path(filter), method: :delete, class: "btn txt-x-small btn--reversed", form_class: "inline" do %>
|
||||
<%= icon_tag "bookmark" %>
|
||||
<span class="for-screen-reader">Remove saved filter</span>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<% filter_params = filter.as_params.transform_values { |v| v.respond_to?(:to_str) ? v.to_str : v } %>
|
||||
<%= button_to filters_path, method: :post, params: filter_params, class: "btn txt-x-small", form_class: "inline" do %>
|
||||
<%= icon_tag "bookmark" %>
|
||||
<span class="for-screen-reader">Save filter</span>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<%= link_to cards_path(filter.as_params.except(:assignee_ids, :assignment_status, :card_ids, :creator_ids, :stage_ids, :tag_ids, :terms, :indexed_by)), class: "btn btn--remove txt-x-small" do %>
|
||||
<%= icon_tag "close" %>
|
||||
<span class="for-screen-reader">Clear all</span>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<% if filter.stages.any? %>
|
||||
<% if filter.stages.any? || @expand_all %>
|
||||
<div class="quick-filter position-relative" data-controller="dialog" data-action="keydown.esc->dialog#close click@document->dialog#closeOnClickOutside">
|
||||
<button class="btn input input--select flex-inline txt-x-small" data-action="click->dialog#open:stop">
|
||||
<span class="overflow-ellipsis">
|
||||
@@ -10,7 +10,7 @@
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<dialog class="events__popup popup panel flex-column align-start gap-half fill-white shadow"
|
||||
<dialog class="margin-block-start-half popup panel flex-column align-start gap-half fill-white shadow"
|
||||
aria-label="In stage…" aria-description="In stage…"
|
||||
data-dialog-target="dialog" data-action="turbo:before-cache@document->dialog#close">
|
||||
<strong class="popup__title margin-block-start-half pad-inline-half overflow-ellipsis">In stage…</strong>
|
||||
@@ -20,6 +20,10 @@
|
||||
<%= filter_hidden_field_tag key, value %>
|
||||
<% end %>
|
||||
|
||||
<% if @expand_all %>
|
||||
<%= hidden_field_tag :expand_all, @expand_all %>
|
||||
<% end %>
|
||||
|
||||
<% filter.stages.first.workflow.stages.each do |stage| %>
|
||||
<div class="btn popup__item">
|
||||
<%= form.check_box :stage_ids, {
|
||||
|
||||
@@ -1,40 +1,61 @@
|
||||
<% if filter.tags.any? %>
|
||||
<% if filter.tags.any?|| @expand_all %>
|
||||
<div class="quick-filter position-relative" data-controller="dialog" data-action="keydown.esc->dialog#close click@document->dialog#closeOnClickOutside">
|
||||
<button class="btn input input--select flex-inline txt-x-small" data-action="click->dialog#open:stop">
|
||||
<span class="overflow-ellipsis">
|
||||
<% if filter.tags.any? %>
|
||||
<%= filter.tags.map(&:hashtag).to_sentence %>
|
||||
<%= filter.tags.map(&:hashtag).to_sentence(two_words_connector: " or ", last_word_connector: ", or ") %>
|
||||
<% else %>
|
||||
Tagged…
|
||||
<% end %>
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<dialog class="events__popup popup panel flex-column align-start gap-half fill-white shadow" data-dialog-target="dialog" data-action="turbo:before-cache@document->dialog#close">
|
||||
<strong class="popup__title margin-block-start-half pad-inline-half overflow-ellipsis">Tagged…</strong>
|
||||
<%= form_with url: cards_path, method: :get, class: "popup__list",
|
||||
data: { controller: "form" } do |form| %>
|
||||
<% filter.as_params.except(:tag_ids).each do |key, value| %>
|
||||
<%= filter_hidden_field_tag key, value %>
|
||||
<% end %>
|
||||
<%= tag.dialog class: "margin-block-start-half popup panel flex-column align-start gap-half fill-white shadow txt-small", data: {
|
||||
action: "turbo:before-cache@document->dialog#close keydown->navigable-list#navigate filter:changed->navigable-list#reset toggle->filter#filter",
|
||||
aria: { label: "Tagged…", aria_description: "Tagged…" },
|
||||
controller: "filter navigable-list",
|
||||
dialog_target: "dialog",
|
||||
navigable_list_focus_on_selection_value: false,
|
||||
navigable_list_actionable_items_value: true } do %>
|
||||
<strong class="popup__title txt-nowrap">Tagged…</strong>
|
||||
|
||||
<%= link_to cards_path(filter.as_params.except(:tag_ids)), class: "btn popup__item" do %>
|
||||
<span class="overflow-ellipsis">Clear all</span>
|
||||
<% end %>
|
||||
|
||||
<% Tag.order(:title).each do |tag| %>
|
||||
<div class="btn popup__item">
|
||||
<%= form.check_box "tag_ids[]", {
|
||||
checked: filter.tags.include?(tag),
|
||||
data: { action: "change->form#submit" },
|
||||
include_hidden: false,
|
||||
}, tag.id %>
|
||||
|
||||
<%= form.label "tag_ids[]", tag.hashtag, for: dom_id(tag, :filter), class: "overflow-ellipsis" %>
|
||||
<%= icon_tag "check", class: "checked flex-item-justify-end" %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% if Tag.many? %>
|
||||
<%= text_field_tag :search, nil, placeholder: "Filter…", class: "input input--transparent txt-small", autofocus: true,
|
||||
type: "search", autocorrect: "off", autocomplete: "off", data: { "1p-ignore": "true", filter_target: "input", action: "input->filter#filter" } %>
|
||||
<% end %>
|
||||
</dialog>
|
||||
|
||||
<ul class="popup__list" data-filter-target="list">
|
||||
<% Tag.order(:title).each do |tag| %>
|
||||
<li class="popup__group flex align-center" data-value="<%= tag.title.downcase %>" data-filter-target="item" data-navigable-list-target="item">
|
||||
<%= form_with url: cards_path, method: :get, class: "full-width", data: { controller: "form" } do |form| %>
|
||||
<% filter.as_params.except(:tag_ids).each do |key, value| %>
|
||||
<%= filter_hidden_field_tag key, value %>
|
||||
<% end %>
|
||||
|
||||
<% filter.tags.each do |existing_tag| %>
|
||||
<% unless existing_tag == tag %>
|
||||
<%= hidden_field_tag "tag_ids[]", existing_tag.id %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<% unless filter.tags.include?(tag) %>
|
||||
<%= hidden_field_tag "tag_ids[]", tag.id %>
|
||||
<% end %>
|
||||
|
||||
<% if @expand_all %>
|
||||
<%= hidden_field_tag :expand_all, @expand_all %>
|
||||
<% end %>
|
||||
|
||||
<%= form.button type: "submit", class: "btn popup__item min-width full-width unpad-inline" do %>
|
||||
<span class="overflow-ellipsis flex-item-grow"><%= tag.hashtag %></span>
|
||||
<% if filter.tags.include?(tag) %>
|
||||
<%= icon_tag "check", class: "checked flex-item-justify-end" %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</li>
|
||||
<% end %>
|
||||
</ul>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
@@ -14,7 +14,7 @@ class FiltersControllerTest < ActionDispatch::IntegrationTest
|
||||
assignee_ids: [ users(:jz).id ],
|
||||
collection_ids: [ collections(:writebook).id ] }
|
||||
end
|
||||
assert_redirected_to cards_path(Filter.last.as_params)
|
||||
assert_redirected_to cards_path(filter_id: Filter.last.id)
|
||||
|
||||
filter = Filter.last
|
||||
assert_predicate filter.indexed_by, :closed?
|
||||
@@ -25,9 +25,12 @@ class FiltersControllerTest < ActionDispatch::IntegrationTest
|
||||
end
|
||||
|
||||
test "destroy" do
|
||||
filter = filters(:jz_assignments)
|
||||
expected_params = filter.as_params
|
||||
|
||||
assert_difference "users(:david).filters.count", -1 do
|
||||
delete filter_path(filters(:jz_assignments))
|
||||
delete filter_path(filter)
|
||||
end
|
||||
assert_redirected_to cards_path(filters(:jz_assignments).as_params)
|
||||
assert_redirected_to cards_path(expected_params)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -114,16 +114,16 @@ class FilterTest < ActiveSupport::TestCase
|
||||
end
|
||||
|
||||
test "summary" do
|
||||
assert_equal "Newest, tagged #mobile, and assigned to JZ ", filters(:jz_assignments).summary
|
||||
assert_equal "Newest, #mobile, and assigned to JZ", filters(:jz_assignments).summary
|
||||
|
||||
filters(:jz_assignments).update!(stages: workflow_stages(:qa_triage, :qa_in_progress))
|
||||
assert_equal "Newest, tagged #mobile, assigned to JZ, and staged in Triage or In progress ", filters(:jz_assignments).summary
|
||||
assert_equal "Newest, #mobile, assigned to JZ, and staged in Triage or In progress", filters(:jz_assignments).summary
|
||||
|
||||
filters(:jz_assignments).update!(stages: [], assignees: [], tags: [], collections: [ collections(:writebook) ])
|
||||
assert_equal "Newest in Writebook", filters(:jz_assignments).summary
|
||||
assert_equal "Newest", filters(:jz_assignments).summary
|
||||
|
||||
filters(:jz_assignments).update!(indexed_by: "stalled")
|
||||
assert_equal "Stalled in Writebook", filters(:jz_assignments).summary
|
||||
assert_equal "Stalled", filters(:jz_assignments).summary
|
||||
end
|
||||
|
||||
test "get a clone with some changed params" do
|
||||
|
||||
Reference in New Issue
Block a user