Skip to content

Commit

Permalink
filtering behaviour
Browse files Browse the repository at this point in the history
  • Loading branch information
BClark88 committed Dec 12, 2024
1 parent 98fcb00 commit e904339
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 3 deletions.
10 changes: 10 additions & 0 deletions app/filters/good_job/base_filter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,15 @@ def queues
.to_h
end

def labels
filtered_query(params.slice(:queue_name))
.joins("CROSS JOIN unnest(labels) AS label")
.group("label")
.order("label")
.count
.to_h
end

def job_classes
filtered_query(params.slice(:queue_name)).unscope(:select)
.group(GoodJob::Job.params_job_class).count
Expand All @@ -53,6 +62,7 @@ def to_params(override = {})
queue_name: params[:queue_name],
query: params[:query],
state: params[:state],
labels: params[:labels],
cron_key: params[:cron_key],
finished_since: params[:finished_since],
}.merge(override).delete_if { |_, v| v.blank? }
Expand Down
1 change: 1 addition & 0 deletions app/filters/good_job/jobs_filter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ def filtered_query(filter_params = params)
query = query.where(queue_name: filter_params[:queue_name]) if filter_params[:queue_name].present?
query = query.search_text(filter_params[:query]) if filter_params[:query].present?
query = query.where(cron_key: filter_params[:cron_key]) if filter_params[:cron_key].present?
query = query.where("labels && ARRAY[?]::text[]", filter_params[:labels]) if filter_params[:labels].present?
query = query.where(finished_at: finished_since(filter_params[:finished_since])..) if filter_params[:finished_since].present?

if filter_params[:state]
Expand Down
37 changes: 36 additions & 1 deletion app/views/good_job/shared/_filter.erb
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,23 @@
</select>
</div>

<div class="me-md-2 mb-2 mb-md-0">
<%= label_tag "label_filter", t(".job_name"), class: "visually-hidden" %>
<select name="labels[]" id="label_filter" class="form-select form-select-sm" size="2" multiple>
<option value="_all" <%= "selected='selected'" if params[:labels].blank? %>><%= t ".all_labels" %></option>

<% filter.labels.each do |name, count| %>
<option value="<%= name.to_param %>" <%= "selected='selected'" if params[:labels]&.include?(name.to_param) %>><%= name %> (<%= number_with_delimiter(count) %>)</option>
<% end %>
</select>
</div>

<div class="me-md-2 mb-2 mb-md-0 flex-fill">
<%= label_tag "query", t(".search"), class: "visually-hidden" %>
<%= search_field_tag "query", params[:query], class: "form-control form-control-sm", placeholder: t(".placeholder"), autocomplete: "off" %>
</div>

<div class="d-flex flex-col align-items-end">
<div class="d-flex flex-col align-items-start">
<div>
<%= form.submit t(".search"), name: nil, class: "btn btn-primary btn-sm" %>
<%= link_to filter.to_params(job_class: nil, state: nil, queue_name: nil, query: nil), class: "btn btn-secondary btn-sm" do %>
Expand Down Expand Up @@ -71,5 +82,29 @@
});
})
})

document.addEventListener("DOMContentLoaded", () => {
const labelFilter = document.getElementById('label_filter');

labelFilter.addEventListener('change', () => {
const selectedValues = Array.from(labelFilter.selectedOptions).map(option => option.value);
const allLabelsOption = labelFilter.querySelector('option[value="_all"]');

if (selectedValues.includes('_all')) {
// If "All labels" is selected, remove the name attribute so as not to pass params[:labels]
// & deselect other options
labelFilter.removeAttribute('name');

Array.from(labelFilter.options).forEach(option => {
if (option.value !== '_all') { option.selected = false; }
});
} else {
// Restore the name attribute & deselect "All labels" if other options are selected
labelFilter.setAttribute('name', 'labels[]');

if (allLabelsOption.selected) { allLabelsOption.selected = false; }
}
});
});
</script>
</div>
1 change: 1 addition & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ en:
filter:
all: All
all_jobs: All jobs
all_labels: All labels
all_queues: All queues
clear: Clear
job_name: Job name
Expand Down
1 change: 1 addition & 0 deletions demo/app/jobs/example_job.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
class ExampleJob < ApplicationJob
include GoodJob::ActiveJobExtensions::Labels
ExpectedError = Class.new(StandardError)
DeadError = Class.new(StandardError)

Expand Down
13 changes: 11 additions & 2 deletions spec/app/filters/good_job/jobs_filter_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
GoodJob::Job.order(created_at: :asc).last.update!(cron_key: "frequent_cron")

ActiveJob::Base.queue_adapter = GoodJob::Adapter.new(execution_mode: :inline)
ExampleJob.set(queue: 'default').perform_later(ExampleJob::SUCCESS_TYPE)
ExampleJob.set(queue: 'mice').perform_later(ExampleJob::ERROR_ONCE_TYPE)
ExampleJob.set(queue: 'default', good_job_labels: ["label1", "label 2"]).perform_later(ExampleJob::SUCCESS_TYPE)
ExampleJob.set(queue: 'mice', good_job_labels: ["label 2"]).perform_later(ExampleJob::ERROR_ONCE_TYPE)

Timecop.travel 1.hour.ago
ExampleJob.set(queue: 'elephants').perform_later(ExampleJob::DEAD_TYPE)
Expand Down Expand Up @@ -53,6 +53,15 @@
end
end

describe '#labels' do
it 'is a valid result' do
expect(filter.labels).to eq({
"label1" => 1,
"label 2" => 2,
})
end
end

describe '#state_names' do
it 'matches states' do
expect(filter.state_names).to match_array(filter.states.keys)
Expand Down

0 comments on commit e904339

Please sign in to comment.