good_job 2.14.1 → 2.14.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 06d4bc71856f5762f7adc99e3ce5227df56f17176a83be5b539df1bc0be71294
4
- data.tar.gz: 8cacdbd09e3938eb0ffdc549bf2e003fadb81d879ec1c3c552d0715d81907036
3
+ metadata.gz: 723ecfed33656e11fcabed4f807c7b9735e474cf15701d97faa0d95c84dd4280
4
+ data.tar.gz: 210f4f8c8d420d46630292212c015d245c2035e8e79dc1b3148fcb40e1b8dbd0
5
5
  SHA512:
6
- metadata.gz: b5d219e39b433103abab4b747ddc2b519cc77371ad409008c7df6954d546f6a72b6460b3a0d27a23cc14d4c09cc1ffbc9de74d26e6aad9eeeed8aee9d33aba95
7
- data.tar.gz: b20b54072e87ffc298b397a6fbe32fb0b6c02573ff1c94ac4dacca9ae4efe845aa4def15d7b9677c746d5e29d3a7bfa9280684416a2f88a12ac9f49780e685dc
6
+ metadata.gz: 20f4b5844debd83589f2dc4f9cebe7be963f9dd7ec6749227db7fad00aca4366cdb87003776194695db84f2bc23739b65f866460d92622dbad8923ff690b9799
7
+ data.tar.gz: 3528895af9ce6f1d4d2e33dab0b6a2fa60cb255d3211a0cfc5b0e97d0f2444e7270c696872c47562dd18d822a95a550345068073a50f80d7ebdd0c9eac782bf8
data/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # Changelog
2
2
 
3
+ ## [v2.14.2](https://github.com/bensheldon/good_job/tree/v2.14.2) (2022-05-01)
4
+
5
+ [Full Changelog](https://github.com/bensheldon/good_job/compare/v2.14.1...v2.14.2)
6
+
7
+ **Fixed bugs:**
8
+
9
+ - Reintroduce fixed "Apply to all" mass action [\#586](https://github.com/bensheldon/good_job/pull/586) ([bensheldon](https://github.com/bensheldon))
10
+
11
+ **Closed issues:**
12
+
13
+ - how to get the number of tasks in the queue and the size of the queue? [\#564](https://github.com/bensheldon/good_job/issues/564)
14
+ - GoodJob tells me to upgrade but migrations fail [\#544](https://github.com/bensheldon/good_job/issues/544)
15
+
16
+ **Merged pull requests:**
17
+
18
+ - Update development dependencies [\#584](https://github.com/bensheldon/good_job/pull/584) ([bensheldon](https://github.com/bensheldon))
19
+ - Refactor Dashboard Live Poll javascript [\#582](https://github.com/bensheldon/good_job/pull/582) ([bensheldon](https://github.com/bensheldon))
20
+
3
21
  ## [v2.14.1](https://github.com/bensheldon/good_job/tree/v2.14.1) (2022-04-26)
4
22
 
5
23
  [Full Changelog](https://github.com/bensheldon/good_job/compare/v2.14.0...v2.14.1)
@@ -4,11 +4,13 @@ import renderCharts from "charts";
4
4
  import checkboxToggle from "checkbox_toggle";
5
5
  import documentReady from "document_ready";
6
6
  import showToasts from "toasts";
7
- import Poller from "poller";
7
+ import LivePoll from "live_poll";
8
8
 
9
9
  documentReady(function() {
10
10
  renderCharts();
11
11
  showToasts();
12
12
  checkboxToggle();
13
- Poller.start();
13
+
14
+ const livePoll = new LivePoll
15
+ livePoll.start();
14
16
  });
@@ -0,0 +1,81 @@
1
+ /*jshint esversion: 6, strict: false */
2
+ import renderCharts from "charts";
3
+
4
+ const MINIMUM_POLL_INTERVAL = 1;
5
+ const STORAGE_KEY = "live_poll";
6
+
7
+ function getStorage(key) {
8
+ const value = localStorage.getItem('good_job-' + key);
9
+
10
+ if (value === 'true') {
11
+ return true;
12
+ } else if (value === 'false') {
13
+ return false;
14
+ } else {
15
+ return value;
16
+ }
17
+ }
18
+
19
+ function setStorage(key, value) {
20
+ localStorage.setItem('good_job-' + key, value);
21
+ }
22
+
23
+ function removeStorage(key) {
24
+ localStorage.removeItem('good_job-' + key);
25
+ }
26
+
27
+ export default class LivePoll {
28
+ start() {
29
+ const checkbox = document.querySelector('input[name="live_poll"]');
30
+
31
+ if (!checkbox.checked && getStorage(STORAGE_KEY)) {
32
+ checkbox.checked = true;
33
+ checkbox.value = getStorage(STORAGE_KEY)
34
+ }
35
+
36
+ checkbox.addEventListener('change', () => {
37
+ this.togglePolling();
38
+ });
39
+
40
+ this.togglePolling();
41
+ }
42
+
43
+ togglePolling = () => {
44
+ const checkbox = document.querySelector('input[name="live_poll"]');
45
+ const enabled = checkbox.checked;
46
+ const pollIntervalMilliseconds = Math.max(parseInt(checkbox.value), MINIMUM_POLL_INTERVAL) * 1000;
47
+
48
+ if (this.interval) {
49
+ clearInterval(this.interval);
50
+ this.interval = null;
51
+ }
52
+
53
+ if (enabled) {
54
+ setStorage(STORAGE_KEY, checkbox.value);
55
+ this.interval = setInterval(LivePoll.refreshPage, pollIntervalMilliseconds);
56
+ } else {
57
+ removeStorage(STORAGE_KEY);
58
+ }
59
+ }
60
+
61
+ static refreshPage() {
62
+ fetch(window.location.href)
63
+ .then(resp => resp.text())
64
+ .then(LivePoll.updatePageContent);
65
+ }
66
+
67
+ static updatePageContent(newContent) {
68
+ const domParser = new DOMParser();
69
+ const newDom = domParser.parseFromString(newContent, "text/html");
70
+
71
+ const newElements = newDom.querySelectorAll('[data-live-poll-region]');
72
+ newElements.forEach((newElement) => {
73
+ const regionName = newElement.getAttribute('data-live-poll-region');
74
+ const originalElement = document.querySelector(`[data-live-poll-region="${regionName}"]`);
75
+
76
+ originalElement.replaceWith(newElement);
77
+ });
78
+
79
+ renderCharts(false);
80
+ }
81
+ }
@@ -6,12 +6,12 @@ module GoodJob
6
6
  end
7
7
 
8
8
  def show
9
- @cron_entry = CronEntry.find(params[:id])
9
+ @cron_entry = CronEntry.find(params[:cron_key])
10
10
  @jobs_filter = JobsFilter.new(params, @cron_entry.jobs)
11
11
  end
12
12
 
13
13
  def enqueue
14
- @cron_entry = CronEntry.find(params[:id])
14
+ @cron_entry = CronEntry.find(params[:cron_key])
15
15
  @cron_entry.enqueue(Time.current)
16
16
  redirect_back(fallback_location: cron_entries_path, notice: "Cron entry has been enqueued.")
17
17
  end
@@ -22,7 +22,7 @@ module GoodJob
22
22
  raise ActionController::BadRequest, "#{mass_action} is not a valid mass action" unless mass_action.in?(ACTIONS.keys)
23
23
 
24
24
  jobs = if params[:all_job_ids]
25
- ActiveJobJob.all
25
+ JobsFilter.new(params).filtered_query
26
26
  else
27
27
  job_ids = params.fetch(:job_ids, [])
28
28
  ActiveJobJob.where(active_job_id: job_ids)
@@ -49,7 +49,7 @@ module GoodJob
49
49
  "No jobs were #{ACTIONS[mass_action]}"
50
50
  end
51
51
 
52
- redirect_to jobs_path, notice: notice
52
+ redirect_back(fallback_location: jobs_path, notice: notice)
53
53
  end
54
54
 
55
55
  def show
@@ -47,6 +47,7 @@ module GoodJob
47
47
  queue_name: params[:queue_name],
48
48
  query: params[:query],
49
49
  state: params[:state],
50
+ cron_key: params[:cron_key],
50
51
  }.merge(override).delete_if { |_, v| v.blank? }
51
52
  end
52
53
 
@@ -54,8 +55,9 @@ module GoodJob
54
55
  raise NotImplementedError
55
56
  end
56
57
 
57
- # def filtered_query_count
58
- delegate :count, to: :filtered_query, prefix: true
58
+ def filtered_count
59
+ filtered_query.count
60
+ end
59
61
 
60
62
  private
61
63
 
@@ -18,6 +18,7 @@ module GoodJob
18
18
  query = query.job_class(params[:job_class]) if params[:job_class].present?
19
19
  query = query.where(queue_name: params[:queue_name]) if params[:queue_name].present?
20
20
  query = query.search_text(params[:query]) if params[:query].present?
21
+ query = query.where(cron_key: params[:cron_key]) if params[:cron_key].present?
21
22
 
22
23
  if params[:state]
23
24
  case params[:state]
@@ -39,7 +40,7 @@ module GoodJob
39
40
  query
40
41
  end
41
42
 
42
- def filtered_query_count
43
+ def filtered_count
43
44
  filtered_query.unscope(:select).count
44
45
  end
45
46
 
@@ -3,4 +3,4 @@
3
3
  <% end %>
4
4
 
5
5
  <%= render 'good_job/shared/filter', title: title, filter: @jobs_filter %>
6
- <%= render 'good_job/jobs/table', jobs: @jobs_filter.records %>
6
+ <%= render 'good_job/jobs/table', jobs: @jobs_filter.records, filter: @jobs_filter %>
@@ -1,4 +1,4 @@
1
- <div class="my-3" data-gj-poll-replace id="executions-table">
1
+ <div class="my-3" data-live-poll-region="executions-table">
2
2
  <div class="table-responsive">
3
3
  <table class="table table-hover table-sm mb-0" id="executions_index_table">
4
4
  <thead>
@@ -1,7 +1,7 @@
1
- <div class="my-3" data-gj-poll-replace id="jobs-table">
1
+ <div class="my-3">
2
2
  <div class="table-responsive">
3
- <%= form_with(url: mass_update_jobs_path, method: :put, local: true, data: { "checkbox-toggle": "job_ids" }) do |form| %>
4
- <table class="table table-hover table-sm mb-0">
3
+ <%= form_with(url: mass_update_jobs_path(filter.to_params), method: :put, local: true, data: { "checkbox-toggle": "job_ids" }) do |form| %>
4
+ <table class="table table-hover table-sm mb-0 table-jobs">
5
5
  <thead>
6
6
  <tr>
7
7
  <th><%= check_box_tag('toggle_job_ids', "1", false, data: { "checkbox-toggle-all": "job_ids" }) %></th>
@@ -35,6 +35,15 @@
35
35
  <%= render_icon "arrow_clockwise" %> All
36
36
  <% end %>
37
37
  </div>
38
+ </th>
39
+ </tr>
40
+ <tr class="d-none" data-checkbox-toggle-show="job_ids">
41
+ <td class="text-center table-warning" colspan="10">
42
+ <label>
43
+ <%= check_box_tag "all_job_ids", 1, false, disabled: true, data: { "checkbox-toggle-show": "job_ids"} %>
44
+ Apply to all <%= filter.filtered_count %> <%= "job".pluralize(filter.filtered_count) %>.
45
+ </label>
46
+ </td>
38
47
  </tr>
39
48
  </thead>
40
49
  <tbody>
@@ -1,15 +1,17 @@
1
1
  <%= render 'good_job/shared/filter', title: "Jobs", filter: @filter %>
2
2
  <%= render 'good_job/shared/chart', chart_data: GoodJob::ScheduledByQueueChart.new(@filter).data %>
3
- <%= render 'good_job/jobs/table', jobs: @filter.records, all_jobs_count: @filter.filtered_query_count %>
4
3
 
5
- <% if @filter.records.present? %>
6
- <nav aria-label="Job pagination" class="mt-3" data-gj-poll-replace id="jobs-pagination">
7
- <ul class="pagination">
8
- <li class="page-item">
9
- <%= link_to(@filter.to_params(after_scheduled_at: (@filter.last.scheduled_at || @filter.last.created_at), after_id: @filter.last.id), class: "page-link") do %>
10
- Older jobs <span aria-hidden="true">&raquo;</span>
11
- <% end %>
12
- </li>
13
- </ul>
14
- </nav>
15
- <% end %>
4
+ <div data-live-poll-region="jobs-table">
5
+ <%= render 'good_job/jobs/table', jobs: @filter.records, filter: @filter %>
6
+ <% if @filter.records.present? %>
7
+ <nav aria-label="Job pagination" class="mt-3">
8
+ <ul class="pagination">
9
+ <li class="page-item">
10
+ <%= link_to(@filter.to_params(after_scheduled_at: (@filter.last.scheduled_at || @filter.last.created_at), after_id: @filter.last.id), class: "page-link") do %>
11
+ Older jobs <span aria-hidden="true">&raquo;</span>
12
+ <% end %>
13
+ </li>
14
+ </ul>
15
+ </nav>
16
+ <% end %>
17
+ </div>
@@ -2,7 +2,7 @@
2
2
  <h2>Processes</h2>
3
3
  </div>
4
4
 
5
- <div data-gj-poll-replace id="processes">
5
+ <div data-live-poll-region="processes">
6
6
  <% if !GoodJob::Process.migrated? %>
7
7
  <div class="card my-3">
8
8
  <div class="card-body">
@@ -1,4 +1,4 @@
1
- <div class="py-4" data-gj-poll-replace id="chart">
1
+ <div class="py-4" data-live-poll-region="chart">
2
2
  <div class="chart-wrapper container-fluid">
3
3
  <canvas class="chart" data-json="<%= chart_data.to_json %>"></canvas>
4
4
  </div>
@@ -1,4 +1,4 @@
1
- <div data-gj-poll-replace id="filter">
1
+ <div data-live-poll-region id="filter">
2
2
  <div class="bg-light break-out">
3
3
  <h2 class="container-fluid pt-3 pb-2"><%= title %></h2>
4
4
 
@@ -1,4 +1,4 @@
1
- <footer class="footer mt-auto py-3 bg-light border-top text-muted small" id="footer" data-gj-poll-replace>
1
+ <footer class="footer mt-auto py-3 bg-light border-top text-muted small" id="footer" data-live-poll-region="footer">
2
2
  <div class="container-fluid">
3
3
  <div class="row">
4
4
  <div class="col-6">
@@ -14,14 +14,14 @@
14
14
  <%= link_to t(".cron_schedules"), cron_entries_path, class: ["nav-link", ("active" if controller_name == 'cron_entries')] %>
15
15
  </li>
16
16
  <li class="nav-item">
17
- <%= link_to t(".processes"), processes_path, class: ["nav-link", ("active" if controller_name == 'processes')] %>
17
+ <%= link_to t(".processes"), processes_path, class: ["nav-link", ("active" if controller_name == 'processes')] %>
18
18
  </li>
19
19
  </ul>
20
20
  <div class="nav-item pe-2">
21
- <div class="form-check">
22
- <input type="checkbox" id="toggle-poll" name="toggle-poll" <%= 'checked' if params[:poll].present? %>>
23
- <label for="toggle-poll"><%= t(".live_poll") %></label>
24
- </div>
21
+ <label>
22
+ <%= check_box_tag "live_poll", params.fetch("poll", 30), params[:poll].present? %>
23
+ <%= t(".live_poll") %>
24
+ </label>
25
25
  </div>
26
26
  <ul class="navbar-nav">
27
27
  <li class="nav-item dropdown">
@@ -17,7 +17,7 @@ GoodJob::Engine.routes.draw do
17
17
  end
18
18
  end
19
19
 
20
- resources :cron_entries, only: %i[index show] do
20
+ resources :cron_entries, only: %i[index show], param: :cron_key do
21
21
  member do
22
22
  post :enqueue
23
23
  end
@@ -159,7 +159,7 @@ module GoodJob
159
159
  alias enable_cron? enable_cron
160
160
 
161
161
  def cron
162
- env_cron = JSON.parse(ENV['GOOD_JOB_CRON'], symbolize_names: true) if ENV['GOOD_JOB_CRON'].present?
162
+ env_cron = JSON.parse(ENV.fetch('GOOD_JOB_CRON'), symbolize_names: true) if ENV['GOOD_JOB_CRON'].present?
163
163
 
164
164
  options[:cron] ||
165
165
  rails_config[:cron] ||
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  module GoodJob
3
3
  # GoodJob gem version.
4
- VERSION = '2.14.1'
4
+ VERSION = '2.14.2'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: good_job
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.14.1
4
+ version: 2.14.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Sheldon
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-04-26 00:00:00.000000000 Z
11
+ date: 2022-05-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activejob
@@ -364,7 +364,7 @@ files:
364
364
  - engine/app/assets/good_job/modules/charts.js
365
365
  - engine/app/assets/good_job/modules/checkbox_toggle.js
366
366
  - engine/app/assets/good_job/modules/document_ready.js
367
- - engine/app/assets/good_job/modules/poller.js
367
+ - engine/app/assets/good_job/modules/live_poll.js
368
368
  - engine/app/assets/good_job/modules/toasts.js
369
369
  - engine/app/assets/good_job/scripts.js
370
370
  - engine/app/assets/good_job/style.css
@@ -1,93 +0,0 @@
1
- /*jshint esversion: 6, strict: false */
2
- import renderCharts from "charts";
3
-
4
- // NOTE: this file is a bit disorganized. Please do not use it as a template for how to organize a JS module.
5
-
6
- const DEFAULT_POLL_INTERVAL_SECONDS = 30;
7
- const MINIMUM_POLL_INTERVAL = 1000;
8
-
9
- function getStorage(key) {
10
- const value = localStorage.getItem('good_job-' + key);
11
-
12
- if (value === 'true') {
13
- return true;
14
- } else if (value === 'false') {
15
- return false;
16
- } else {
17
- return value;
18
- }
19
- }
20
-
21
- function setStorage(key, value) {
22
- localStorage.setItem('good_job-' + key, value);
23
- }
24
-
25
- function updatePageContent(newContent) {
26
- const domParser = new DOMParser();
27
- const parsedDOM = domParser.parseFromString(newContent, "text/html");
28
-
29
- const newElements = parsedDOM.querySelectorAll('[data-gj-poll-replace]');
30
-
31
- for (let i = 0; i < newElements.length; i++) {
32
- const newEl = newElements[i];
33
- const oldEl = document.getElementById(newEl.id);
34
-
35
- if (oldEl) {
36
- oldEl.replaceWith(newEl);
37
- }
38
- }
39
-
40
- renderCharts(false);
41
- }
42
-
43
- function refreshPage() {
44
- fetch(window.location.href)
45
- .then(resp => resp.text())
46
- .then(updatePageContent);
47
- }
48
-
49
- const Poller = {
50
- start: () => {
51
- Poller.updateSettings();
52
- Poller.pollUpdates();
53
-
54
- const checkbox = document.querySelector('input[name="toggle-poll"]');
55
- checkbox.addEventListener('change', Poller.togglePoll)
56
- },
57
-
58
- togglePoll: (event) => {
59
- Poller.pollEnabled = event.currentTarget.checked;
60
- setStorage('pollEnabled', Poller.pollEnabled);
61
- },
62
-
63
- updateSettings: () => {
64
- const queryString = window.location.search;
65
- const urlParams = new URLSearchParams(queryString);
66
-
67
- if (urlParams.has('poll')) {
68
- const parsedInterval = (parseInt(urlParams.get('poll')) || DEFAULT_POLL_INTERVAL_SECONDS) * 1000;
69
- Poller.pollInterval = Math.max(parsedInterval, MINIMUM_POLL_INTERVAL);
70
- setStorage('pollInterval', Poller.pollInterval);
71
-
72
- Poller.pollEnabled = true;
73
- } else {
74
- Poller.pollInterval = getStorage('pollInterval') || (DEFAULT_POLL_INTERVAL_SECONDS * 1000);
75
- Poller.pollEnabled = getStorage('pollEnabled') || false;
76
- }
77
-
78
- document.getElementById('toggle-poll').checked = Poller.pollEnabled;
79
- },
80
-
81
- pollUpdates: () => {
82
- setTimeout(() => {
83
- if (Poller.pollEnabled === true) {
84
- refreshPage();
85
- Poller.pollUpdates();
86
- } else {
87
- Poller.pollUpdates();
88
- }
89
- }, Poller.pollInterval);
90
- },
91
- };
92
-
93
- export { Poller as default };