good_job 2.14.1 → 2.14.2

Sign up to get free protection for your applications and to get access to all the features.
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 };