que-view 0.2.3 → 0.3.0

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: c1ced9639e99e58168c4b6e6a43c95f25e7a8dc0e44da579cc3e5bff4260afac
4
- data.tar.gz: 035f401a2e5afe417100ecb908ca54e99d467a7af3822a698af734e27bfbee1c
3
+ metadata.gz: a54cde016dccd6207b38924f717a5aeb3ea9ccae0eef215f848c2621c8af4945
4
+ data.tar.gz: 0d44f6c8e723e8533c8f640b58996a2b25b7d444115c761e95879c6a91ca3331
5
5
  SHA512:
6
- metadata.gz: 38a0e562ee5553257cdddffceb963b87b659cc57fd04fc8c78c0a1b6e6c7863d4c86287f0fc03e6df30bbd8823c758b0b78607c56fd39a04fb345649aad72aee
7
- data.tar.gz: 7466ab6634be76c84a3587eb800f82fbe7cb355eba7914cae29cd4bcf66054ff519b14d11d3a9be3c5927eb9011486e0d78d287ff7b7ada6ca758a5d77943dc6
6
+ metadata.gz: 72bde7eb6e7d6a2ae64e380eedb7f8ce45eb609116a017e71dc1af0ea7acdb5df7293cfb5015474b6d0793570b9062ca735e95878ea1e65e570dd95f0ba4f3d3
7
+ data.tar.gz: 659f6cfb80c3bb746f2f0088638e3e6f8d7acd63cc47ab0584df44762a9b18266736fd80bb4820c0a91d0e1b12b3262f7209c7321c7cf867b3ca9f2ee7c7eae9
data/README.md CHANGED
@@ -1,7 +1,16 @@
1
1
  # Que::View
2
2
  Rails engine inspired by [Que::Web](https://github.com/statianzo/que-web) for [Que](https://github.com/que-rb/que) job queue.
3
3
  SQL queries came from Que::Web, some styling from there too.
4
- Benefits for using this one: independent from Sinatra (que-web based on Sinatra)
4
+
5
+ Benefits for using this one:
6
+ - no Sinatra (que-web based on Sinatra),
7
+ - no Foundation for styles,
8
+ - no jQuery,
9
+ - Que::Web was last updated 2 years ago.
10
+
11
+ <img width="1735" alt="Снимок экрана 2024-02-21 в 15 10 35" src="https://github.com/kortirso/que-view/assets/6195394/cd2812c7-abb0-48d9-92d5-4dbef93bcd9e">
12
+ <img width="1735" alt="Снимок экрана 2024-02-21 в 15 11 12" src="https://github.com/kortirso/que-view/assets/6195394/8af01e7f-a002-4ef1-aeff-f96fd27c639f">
13
+
5
14
 
6
15
  ## Installation
7
16
 
@@ -48,8 +57,10 @@ Add this line to assets/config/manifest.js
48
57
 
49
58
  - [X] rescheduling jobs
50
59
  - [X] deleting jobs
51
- - [ ] better styles for UI
52
- - [ ] rendering running jobs
60
+ - [X] better styles for UI
61
+ - [X] rendering running jobs
62
+ - [ ] searching/filtering through jobs by name, queue
63
+ - [X] pagination for jobs list page
53
64
  - [ ] tests
54
65
 
55
66
  ## License
@@ -20,6 +20,11 @@
20
20
  font-family: 'Source Sans Pro';
21
21
  }
22
22
 
23
+ html, body {
24
+ padding: 0;
25
+ margin: 0;
26
+ }
27
+
23
28
  .row {
24
29
  display: flex;
25
30
  flex-direction: row;
@@ -48,11 +53,11 @@ table th {
48
53
  }
49
54
 
50
55
  table tbody tr:nth-of-type(2n), table tbody tr:hover {
51
- background: #DDD;
56
+ background: #EEE;
52
57
  }
53
58
 
54
59
  table tbody tr:nth-of-type(2n):hover {
55
- background: #CCC;
60
+ background: #DDD;
56
61
  }
57
62
 
58
63
  table p {
@@ -114,3 +119,76 @@ table p {
114
119
  padding: .25rem .5rem;
115
120
  margin-right: .5rem;
116
121
  }
122
+
123
+ .pagination {
124
+ margin: 1rem auto;
125
+ }
126
+
127
+ .pagination .pagination-link {
128
+ margin: 0 .5rem 0 0;
129
+ padding: .25rem .5rem;
130
+ background: #fde68a;
131
+ border: 1px solid #fcd34d;
132
+ border-radius: .25rem;
133
+ text-decoration: none;
134
+ }
135
+
136
+ .pagination .pagination-link.disabled {
137
+ background: #fef3c7;
138
+ }
139
+
140
+ .pagination .total-pages {
141
+ margin: 0 .5rem 0 0;
142
+ padding: .25rem .5rem;
143
+ }
144
+
145
+ .navigation {
146
+ display: flex;
147
+ padding: .5rem 1rem;
148
+ background: #52525b;
149
+ color: #fff;
150
+ }
151
+
152
+ .navigation h1 {
153
+ margin: 0 2rem 0 0;
154
+ }
155
+
156
+ .navigation h1 a {
157
+ text-decoration: none;
158
+ color: #fff;
159
+ }
160
+
161
+ .navigation .navigation-section {
162
+ flex: 1;
163
+ display: flex;
164
+ justify-content: space-between;
165
+ align-items: center;
166
+ }
167
+
168
+ .navigation .navigation-section ul {
169
+ margin: 0;
170
+ padding: 0;
171
+ list-style: none;
172
+ display: flex;
173
+ }
174
+
175
+ .navigation .navigation-section ul.version li {
176
+ margin-left: 1rem;
177
+ }
178
+
179
+ .navigation .navigation-section ul li a {
180
+ display: inline-block;
181
+ padding: .5rem;
182
+ text-decoration: none;
183
+ color: #fff;
184
+ }
185
+
186
+ .navigation .navigation-section ul li.active a {
187
+ text-decoration: underline;
188
+ }
189
+
190
+ @media screen and (max-width: 768px) {
191
+ .row {
192
+ flex-direction: column;
193
+ }
194
+ }
@@ -9,7 +9,7 @@ module Que
9
9
 
10
10
  def index
11
11
  @jobs = find_jobs(params[:status])
12
- @jobs_amount = find_jobs_amount(params[:status])
12
+ paginate
13
13
  end
14
14
 
15
15
  def show; end
@@ -48,6 +48,19 @@ module Que
48
48
 
49
49
  private
50
50
 
51
+ def paginate
52
+ return if %w[failing scheduled].exclude?(params[:status])
53
+ return unless @jobs.any?
54
+
55
+ @pagination = Que::View::Pagination.new(
56
+ params: {
57
+ page: page,
58
+ per_page: params[:per_page] || PER_PAGE,
59
+ count: find_jobs_total_amount(params[:status])
60
+ }
61
+ )
62
+ end
63
+
51
64
  def find_job
52
65
  @job = ::Que::View.fetch_job(params[:id])[0]
53
66
  return if @job
@@ -57,13 +70,14 @@ module Que
57
70
 
58
71
  def find_jobs(status)
59
72
  case status&.to_sym
73
+ when :running then ::Que::View.fetch_running_jobs(search)
60
74
  when :failing then ::Que::View.fetch_failing_jobs(PER_PAGE, offset, search)
61
75
  when :scheduled then ::Que::View.fetch_scheduled_jobs(PER_PAGE, offset, search)
62
76
  else []
63
77
  end
64
78
  end
65
79
 
66
- def find_jobs_amount(status)
80
+ def find_jobs_total_amount(status)
67
81
  ::Que::View.fetch_dashboard_stats(search)[0][status&.to_sym]
68
82
  end
69
83
 
@@ -96,13 +110,13 @@ module Que
96
110
  sanitised
97
111
  end
98
112
 
99
- def page
100
- (params[:page] || 1).to_i
101
- end
102
-
103
113
  def offset
104
114
  (page - 1) * PER_PAGE
105
115
  end
116
+
117
+ def page
118
+ (params[:page] || 1).to_i
119
+ end
106
120
  end
107
121
  end
108
122
  end
@@ -7,6 +7,27 @@
7
7
  <%= stylesheet_link_tag 'que/view/application', media: 'all' %>
8
8
  </head>
9
9
  <body>
10
+ <nav class="navigation" role="navigation">
11
+ <h1><%= link_to 'Que View', root_path %></h1>
12
+ <section class="navigation-section">
13
+ <ul>
14
+ <li class="<%= 'active' if params[:status] == 'running' %>">
15
+ <%= link_to 'Running', jobs_path(status: 'running') %>
16
+ </li>
17
+ <li class="<%= 'active' if params[:status] == 'scheduled' %>">
18
+ <%= link_to 'Scheduled', jobs_path(status: 'scheduled') %>
19
+ </li>
20
+ <li class="<%= 'active' if params[:status] == 'failing' %>">
21
+ <%= link_to 'Failing', jobs_path(status: 'failing') %>
22
+ </li>
23
+ </ul>
24
+ <ul class="version">
25
+ <li>Que <%= Que::VERSION %></li>
26
+ <li>Que View <%= Que::View::VERSION %></li>
27
+ <li><%= Time.now.utc.strftime("%Y-%m-%d %H:%M:%S") %></li>
28
+ </ul>
29
+ </section>
30
+ </nav>
10
31
  <%= yield %>
11
32
  </body>
12
33
  </html>
@@ -1,13 +1,32 @@
1
- <div class="row">
2
- <% if @jobs.size.positive? %>
1
+ <% if @jobs.any? %>
2
+ <% if @pagination %>
3
+ <div class="row pagination">
4
+ <% if @pagination.previous_page? %>
5
+ <%= link_to 'First', jobs_path(status: params[:status], page: 1), class: 'pagination-link' %>
6
+ <%= link_to '< Previous', jobs_path(status: params[:status], page: @pagination.previous_page), class: 'pagination-link' %>
7
+ <% else %>
8
+ <p class="pagination-link disabled">First</p>
9
+ <p class="pagination-link disabled">&#60; Previous</p>
10
+ <% end %>
11
+ <p class="total-pages"><%= "Page #{@pagination.page} of #{@pagination.total_pages}" %></p>
12
+ <% if @pagination.next_page? %>
13
+ <%= link_to 'Next >', jobs_path(status: params[:status], page: @pagination.next_page), class: 'pagination-link' %>
14
+ <%= link_to 'Last', jobs_path(status: params[:status], page: @pagination.total_pages), class: 'pagination-link' %>
15
+ <% else %>
16
+ <p class="pagination-link disabled">Next &#62;</p>
17
+ <p class="pagination-link disabled">Last </p>
18
+ <% end %>
19
+ </div>
20
+ <% end %>
21
+ <div class="row">
3
22
  <table cellspacing="0">
4
23
  <thead>
5
24
  <tr>
6
25
  <th>ID</th>
7
26
  <th>Run at</th>
8
27
  <th>Job</th>
9
- <th>Arguments</th>
10
28
  <th>Queue</th>
29
+ <th>Arguments</th>
11
30
  <% if params[:status] == 'failing' %>
12
31
  <th>Failures</th>
13
32
  <th>Error</th>
@@ -21,7 +40,7 @@
21
40
  <% @jobs.each do |job| %>
22
41
  <tr>
23
42
  <td><%= link_to job[:id], job_path(job[:id]) %></td>
24
- <td><%= job[:run_at].utc %></td>
43
+ <td><%= job[:run_at].strftime("%Y-%m-%d %H:%M:%S") %></td>
25
44
  <td><%= humanized_job_class(job) %></td>
26
45
  <td><%= job[:queue] %></td>
27
46
  <td>
@@ -34,20 +53,24 @@
34
53
  <td><%= format_error(job) %></td>
35
54
  <% end %>
36
55
  <% if %w[failing scheduled].include?(params[:status]) %>
37
- <td class="actions">
38
- <%= button_to 'Run', job_path(job[:id]), class: 'btn-danger', method: :patch, onclick: "return confirm('Are you sure you wish to reschedule job?')" %>
39
- <%= button_to 'Delete', job_path(job[:id]), class: 'btn-danger', method: :delete, onclick: "return confirm('Are you sure you wish to delete job?')" %>
56
+ <td>
57
+ <div class="actions">
58
+ <%= button_to 'Run', job_path(job[:id]), class: 'btn-danger', method: :patch, onclick: "return confirm('Are you sure you wish to reschedule job?')" %>
59
+ <%= button_to 'Delete', job_path(job[:id]), class: 'btn-danger', method: :delete, onclick: "return confirm('Are you sure you wish to delete job?')" %>
60
+ </div>
40
61
  </td>
41
62
  <% end %>
42
63
  </tr>
43
64
  <% end %>
44
65
  </tbody>
45
66
  </table>
46
- <% else %>
67
+ </div>
68
+ <% else %>
69
+ <div class="row">
47
70
  <p>No jobs found</p>
48
- <% end %>
49
- </div>
50
- <% if %w[failing scheduled].include?(params[:status]) && @jobs_amount.positive? %>
71
+ </div>
72
+ <% end %>
73
+ <% if @pagination&.count&.positive? %>
51
74
  <div class="row">
52
75
  <%= button_to 'Run All', reschedule_all_jobs_path(status: params[:status]), class: 'btn-danger', method: :post, onclick: "return confirm('Are you sure you wish to reschedule all jobs?')" %>
53
76
  <%= button_to 'Delete All', destroy_all_jobs_path(status: params[:status]), class: 'btn-danger', method: :delete, onclick: "return confirm('Are you sure you wish to delete all jobs?')" %>
@@ -20,7 +20,7 @@
20
20
  </tr>
21
21
  <tr>
22
22
  <th>Run at</th>
23
- <td><%= @job[:run_at].utc %></td>
23
+ <td><%= @job[:run_at].strftime("%Y-%m-%d %H:%M:%S") %></td>
24
24
  </tr>
25
25
  <tr>
26
26
  <th>Failures</th>
data/lib/que/view/dsl.rb CHANGED
@@ -8,6 +8,10 @@ module Que
8
8
  execute(fetch_dashboard_stats_sql(...))
9
9
  end
10
10
 
11
+ def fetch_running_jobs(...)
12
+ Que.job_states
13
+ end
14
+
11
15
  def fetch_failing_jobs(...)
12
16
  execute(fetch_failing_jobs_sql(...))
13
17
  end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Que
4
+ module View
5
+ class Pagination
6
+ attr_reader :page, :count, :per_page
7
+
8
+ def initialize(params: {})
9
+ @page = params[:page]
10
+ @count = params[:count]
11
+ @per_page = params[:per_page]
12
+ end
13
+
14
+ def offset
15
+ return 0 if page == 1
16
+
17
+ per_page * (page.to_i - 1)
18
+ end
19
+
20
+ def next_page
21
+ page + 1 unless last_page?
22
+ end
23
+
24
+ def next_page?
25
+ page < total_pages
26
+ end
27
+
28
+ def previous_page
29
+ page - 1 unless first_page?
30
+ end
31
+
32
+ def previous_page?
33
+ page > 1
34
+ end
35
+
36
+ def last_page?
37
+ page == total_pages
38
+ end
39
+
40
+ def first_page?
41
+ page == 1
42
+ end
43
+
44
+ def total_pages
45
+ (count / per_page.to_f).ceil
46
+ end
47
+ end
48
+ end
49
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Que
4
4
  module View
5
- VERSION = '0.2.3'
5
+ VERSION = '0.3.0'
6
6
  end
7
7
  end
data/lib/que/view.rb CHANGED
@@ -6,13 +6,14 @@ require 'que/view/version'
6
6
  require 'que/view/engine'
7
7
  require 'que/view/configuration'
8
8
  require 'que/view/dsl'
9
+ require 'que/view/pagination'
9
10
 
10
11
  module Que
11
12
  module View
12
13
  extend self
13
14
  extend Forwardable
14
15
 
15
- # Public: Configure emailbutler.
16
+ # Public: Configure que view.
16
17
  #
17
18
  # Que::View.configure do |config|
18
19
  # end
@@ -26,15 +27,15 @@ module Que
26
27
  @configuration ||= Configuration.new
27
28
  end
28
29
 
29
- # Public: Default per thread emailbutler instance if configured.
30
+ # Public: Default per thread que view instance if configured.
30
31
  # Returns Que::View::DSL instance.
31
32
  def instance
32
33
  Thread.current[:que_view_instance] ||= DSL.new
33
34
  end
34
35
 
35
36
  # Public: All the methods delegated to instance. These should match the interface of Que::View::DSL.
36
- def_delegators :instance,
37
- :fetch_dashboard_stats, :fetch_failing_jobs, :fetch_scheduled_jobs, :fetch_job,
37
+ def_delegators :instance, :fetch_dashboard_stats,
38
+ :fetch_running_jobs, :fetch_failing_jobs, :fetch_scheduled_jobs, :fetch_job,
38
39
  :delete_failing_jobs, :delete_scheduled_jobs, :delete_job,
39
40
  :reschedule_scheduled_jobs, :reschedule_failing_jobs, :reschedule_job
40
41
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: que-view
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bogdanov Anton
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-12-01 00:00:00.000000000 Z
11
+ date: 2024-02-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: que
@@ -175,6 +175,7 @@ files:
175
175
  - lib/que/view/configuration.rb
176
176
  - lib/que/view/dsl.rb
177
177
  - lib/que/view/engine.rb
178
+ - lib/que/view/pagination.rb
178
179
  - lib/que/view/version.rb
179
180
  homepage: https://github.com/kortirso/que-view
180
181
  licenses: