Skip to content

Commit 50bba1c

Browse files
authored
Merge pull request #3500 from AlchemyCMS/fix-attachments-filter
Fix filtering Attachments by only or except setting
2 parents 3160be9 + 7f71821 commit 50bba1c

File tree

29 files changed

+302
-61
lines changed

29 files changed

+302
-61
lines changed

app/assets/builds/alchemy/admin.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/assets/builds/alchemy/dark-theme.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/assets/builds/alchemy/light-theme.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/assets/builds/alchemy/theme.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/components/alchemy/admin/resource/select_filter.rb

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ module Alchemy
44
module Admin
55
module Resource
66
class SelectFilter < ViewComponent::Base
7-
attr_reader :name, :resource_name, :label, :include_blank, :options, :selected
7+
attr_reader :name, :resource_name, :label, :include_blank, :options, :selected, :multiple
88

99
erb_template <<~ERB
1010
<div class="filter-input">
@@ -14,17 +14,19 @@ class SelectFilter < ViewComponent::Base
1414
options_for_select(options, selected),
1515
include_blank: include_blank,
1616
form: "resource_search",
17+
multiple: multiple,
1718
is: 'alchemy-select'
1819
) %>
1920
</div>
2021
ERB
2122

22-
def initialize(name:, resource_name:, label:, include_blank:, options:, params:)
23+
def initialize(name:, resource_name:, label:, include_blank:, options:, params:, multiple: false)
2324
@name = name
2425
@options = options
2526
@label = label
2627
@include_blank = include_blank
2728
@resource_name = resource_name
29+
@multiple = multiple
2830
@selected = get_selected_value_from(params)
2931
end
3032

app/controllers/alchemy/admin/attachments_controller.rb

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,17 @@ class AttachmentsController < ResourcesController
66
include UploaderResponses
77
include ArchiveOverlay
88

9-
add_alchemy_filter :by_file_type, type: :select,
10-
options: -> { Alchemy::Attachment.file_types(_1.result) }
9+
add_alchemy_filter :by_file_type, type: :select, options: ->(_query, params) do
10+
case params&.to_h
11+
in {except:}
12+
Attachment.file_types - Attachment.file_types(from_extensions: except)
13+
in {only:}
14+
Attachment.file_types(from_extensions: only)
15+
else
16+
Attachment.file_types
17+
end
18+
end
19+
1120
add_alchemy_filter :recent, type: :checkbox
1221
add_alchemy_filter :last_upload, type: :checkbox
1322
add_alchemy_filter :without_tag, type: :checkbox
@@ -72,11 +81,37 @@ def default_sort_order
7281
end
7382

7483
def search_filter_params
75-
@_search_filter_params ||= params.except(*COMMON_SEARCH_FILTER_EXCLUDES + [:attachment]).permit(
76-
*common_search_filter_includes + [
77-
:form_field_id
78-
]
79-
)
84+
@_search_filter_params ||= begin
85+
params[:q] ||= ActionController::Parameters.new
86+
87+
if params[:only].present?
88+
params[:q][:by_file_type] ||= Array(params[:only]).map do |extension|
89+
Marcel::MimeType.for(extension:)
90+
end
91+
end
92+
93+
if params[:except].present?
94+
params[:q][:by_file_type] ||= Attachment.file_types - params[:except].map do |extension|
95+
Marcel::MimeType.for(extension:)
96+
end
97+
end
98+
99+
params.except(*COMMON_SEARCH_FILTER_EXCLUDES + [:attachment]).permit(
100+
*common_search_filter_includes + [
101+
:form_field_id,
102+
{only: []},
103+
{except: []}
104+
]
105+
)
106+
end
107+
end
108+
109+
def permitted_ransack_search_fields
110+
super + [
111+
{by_file_type: []},
112+
:not_file_type,
113+
{not_file_type: []}
114+
]
80115
end
81116

82117
def handle_uploader_response(status:)

app/javascript/alchemy_admin/components/select.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ class Select extends HTMLSelectElement {
5353
}
5454

5555
get allowClear() {
56-
return this.dataset.hasOwnProperty("allowClear")
56+
return this.dataset.hasOwnProperty("allowClear") || this.multiple
5757
}
5858
}
5959

app/models/alchemy/admin/filters/select.rb

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,25 @@ def input_component(params, query)
2424
name:,
2525
resource_name:,
2626
label: translated_name,
27-
include_blank:,
28-
options: get_options_for_select(query),
27+
include_blank: include_blank(params),
28+
options: get_options_for_select(query, params),
29+
multiple: multiple?(params),
2930
params:
3031
)
3132
end
3233

3334
private
3435

35-
def include_blank
36-
Alchemy.t(:all, scope: [:filters, resource_name, name])
36+
def multiple?(params)
37+
params[:only].presence&.many? || params[:except].present?
38+
end
39+
40+
def include_blank(params)
41+
if params[:only].present? || params[:except].present?
42+
false
43+
else
44+
Alchemy.t(:all, scope: [:filters, resource_name, name])
45+
end
3746
end
3847

3948
def options_to_proc(options)
@@ -44,8 +53,8 @@ def options_to_proc(options)
4453
end
4554
end
4655

47-
def get_options_for_select(query)
48-
options_for_select = options.call(query)
56+
def get_options_for_select(query, params = nil)
57+
options_for_select = (options.arity == 1) ? options.call(query) : options.call(query, params)
4958
# The result of the query is an Array of Arrays, where the first element is the translated name and the second element is the value.
5059
# If the first element is an Array, we assume that the options are already translated.
5160
if options_for_select.first.is_a? Array

app/models/alchemy/attachment.rb

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,14 @@ class Attachment < BaseRecord
2929

3030
stampable stamper_class_name: Alchemy.user_class_name
3131

32-
scope :by_file_type, ->(file_type) do
32+
scope :by_file_type, ->(*file_type) do
3333
Alchemy.storage_adapter.by_file_type_scope(file_type)
3434
end
3535

36+
scope :not_file_type, ->(*file_type) do
37+
Alchemy.storage_adapter.not_file_type_scope(file_type)
38+
end
39+
3640
scope :recent, -> { where("#{table_name}.created_at > ?", Time.current - 24.hours).order(:created_at) }
3741
scope :without_tag, -> { left_outer_joins(:taggings).where(gutentag_taggings: {id: nil}) }
3842

@@ -70,7 +74,12 @@ def ransackable_associations(_auth_object = nil)
7074
Alchemy.storage_adapter.ransackable_associations(name)
7175
end
7276

73-
def file_types(scope = all)
77+
def file_types(scope = all, from_extensions: nil)
78+
if from_extensions.present?
79+
scope = by_file_type(
80+
Array(from_extensions).map { |extension| Marcel::MimeType.for(extension:) }
81+
)
82+
end
7483
Alchemy.storage_adapter.file_formats(name, scope:)
7584
end
7685

@@ -79,7 +88,7 @@ def allowed_filetypes
7988
end
8089

8190
def ransackable_scopes(_auth_object = nil)
82-
%i[by_file_type recent last_upload without_tag deletable]
91+
%i[by_file_type not_file_type recent last_upload without_tag deletable]
8392
end
8493
end
8594

app/models/alchemy/storage_adapter.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ class UnknownAdapterError < StandardError; end
88
:attachment_url_class,
99
:by_file_format_scope,
1010
:by_file_type_scope,
11+
:not_file_type_scope,
1112
:file_extension,
1213
:file_formats,
1314
:file_mime_type,

0 commit comments

Comments
 (0)