solid_queue_tui 0.1.2 → 0.1.3

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.
@@ -4,62 +4,29 @@ module SolidQueueTui
4
4
  module Views
5
5
  class FailedView
6
6
  include Filterable
7
-
8
-
9
- LOAD_THRESHOLD = 10
7
+ include Confirmable
8
+ include Paginatable
9
+ include FormattingHelpers
10
10
 
11
11
  def initialize(tui)
12
12
  @tui = tui
13
- @table_state = RatatuiRuby::TableState.new(nil)
14
- @table_state.select(0)
15
- @selected_row = 0
16
- @failed_jobs = []
17
- @total_count = nil
18
- @all_loaded = false
19
- @confirm_action = nil
13
+ init_pagination
14
+ init_confirm
20
15
  init_filter
21
16
  end
22
17
 
23
18
  def update(failed_jobs:)
24
- @failed_jobs = failed_jobs
25
- @all_loaded = failed_jobs.size < SolidQueueTui.page_size
26
- @selected_row = @selected_row.clamp(0, [@failed_jobs.size - 1, 0].max)
27
- @table_state.select(@selected_row)
19
+ update_items(failed_jobs)
28
20
  end
29
21
 
30
22
  def append(failed_jobs:)
31
- @failed_jobs.concat(failed_jobs)
32
- @all_loaded = failed_jobs.size < SolidQueueTui.page_size
33
- end
34
-
35
- def total_count=(count)
36
- @total_count = count
37
- end
38
-
39
- def current_offset
40
- @failed_jobs.size
41
- end
42
-
43
- def reset_pagination!
44
- @failed_jobs = []
45
- @total_count = nil
46
- @all_loaded = false
47
- @selected_row = 0
48
- @table_state.select(0)
23
+ append_items(failed_jobs)
49
24
  end
50
25
 
51
26
  def render(frame, area)
52
- if @confirm_action
53
- confirm_area, content_area = @tui.layout_split(
54
- area,
55
- direction: :vertical,
56
- constraints: [
57
- @tui.constraint_length(3),
58
- @tui.constraint_fill(1)
59
- ]
60
- )
61
- render_confirm(frame, confirm_area)
62
- render_failed_table(frame, content_area)
27
+ if confirm_mode?
28
+ render_failed_table(frame, area)
29
+ render_confirm_popup(frame, area)
63
30
  elsif filter_mode?
64
31
  filter_area, content_area = @tui.layout_split(
65
32
  area,
@@ -77,7 +44,7 @@ module SolidQueueTui
77
44
  end
78
45
 
79
46
  def handle_input(event)
80
- if @confirm_action
47
+ if confirm_mode?
81
48
  handle_confirm_input(event)
82
49
  elsif filter_mode?
83
50
  handle_filter_input(event)
@@ -86,17 +53,9 @@ module SolidQueueTui
86
53
  end
87
54
  end
88
55
 
89
- def selected_item
90
- return nil if @failed_jobs.empty? || @selected_row >= @failed_jobs.size
91
- @failed_jobs[@selected_row]
92
- end
93
-
94
56
  def bindings
95
- if @confirm_action
96
- [
97
- { key: "y", action: "Confirm" },
98
- { key: "n/Esc", action: "Cancel" }
99
- ]
57
+ if confirm_mode?
58
+ confirm_bindings
100
59
  elsif filter_mode?
101
60
  filter_bindings
102
61
  else
@@ -112,7 +71,7 @@ module SolidQueueTui
112
71
  end
113
72
 
114
73
  def capturing_input?
115
- filter_mode? || @confirm_action
74
+ filter_mode? || confirm_mode?
116
75
  end
117
76
 
118
77
  def breadcrumb
@@ -121,10 +80,6 @@ module SolidQueueTui
121
80
 
122
81
  private
123
82
 
124
- def needs_more?
125
- !@all_loaded && @selected_row >= @failed_jobs.size - LOAD_THRESHOLD
126
- end
127
-
128
83
  def handle_normal_input(event)
129
84
  case event
130
85
  in { type: :key, code: "j" } | { type: :key, code: "up" }
@@ -144,7 +99,7 @@ module SolidQueueTui
144
99
  @confirm_action = :discard if selected_item
145
100
  nil
146
101
  in { type: :key, code: "A" }
147
- @confirm_action = :retry_all unless @failed_jobs.empty?
102
+ @confirm_action = :retry_all unless items.empty?
148
103
  nil
149
104
  in { type: :key, code: "/" }
150
105
  enter_filter_mode
@@ -156,52 +111,38 @@ module SolidQueueTui
156
111
  end
157
112
  end
158
113
 
159
- def handle_confirm_input(event)
160
- case event
161
- in { type: :key, code: "y" }
162
- action = @confirm_action
163
- @confirm_action = nil
164
- case action
165
- when :retry
166
- item = selected_item
167
- return nil unless item
168
- Actions::RetryJob.call(item.id)
169
- :refresh
170
- when :discard
171
- item = selected_item
172
- return nil unless item
173
- Actions::DiscardJob.call(item.id)
174
- :refresh
175
- when :retry_all
176
- f = filters
177
- Actions::RetryJob.retry_all(filter: f[:class_name], queue: f[:queue])
178
- :refresh
179
- end
180
- in { type: :key, code: "n" } | { type: :key, code: "esc" }
181
- @confirm_action = nil
182
- nil
183
- else
184
- nil
114
+ def confirm_message
115
+ case @confirm_action
116
+ when :retry
117
+ job = selected_item
118
+ "Retry job ##{job&.job_id} (#{job&.class_name})? [y/n]"
119
+ when :discard
120
+ job = selected_item
121
+ "Discard job ##{job&.job_id} (#{job&.class_name})? This cannot be undone. [y/n]"
122
+ when :retry_all
123
+ count = @total_count || items.size
124
+ label = @filters.empty? ? "failed jobs" : "filtered failed jobs"
125
+ "Retry ALL #{count} #{label}? [y/n]"
185
126
  end
186
127
  end
187
128
 
188
- def move_selection(delta)
189
- return if @failed_jobs.empty?
190
- @selected_row = (@selected_row + delta).clamp(0, @failed_jobs.size - 1)
191
- @table_state.select(@selected_row)
192
- :load_more if needs_more?
193
- end
194
-
195
- def jump_to_top
196
- @selected_row = 0
197
- @table_state.select(0)
198
- end
199
-
200
- def jump_to_bottom
201
- return if @failed_jobs.empty?
202
- @selected_row = @failed_jobs.size - 1
203
- @table_state.select(@selected_row)
204
- return :load_more if needs_more?
129
+ def execute_confirm_action(action)
130
+ case action
131
+ when :retry
132
+ item = selected_item
133
+ return nil unless item
134
+ Actions::RetryJob.call(item.id)
135
+ :refresh
136
+ when :discard
137
+ item = selected_item
138
+ return nil unless item
139
+ Actions::DiscardJob.call(item.id)
140
+ :refresh
141
+ when :retry_all
142
+ f = filters
143
+ Actions::RetryJob.retry_all(filter: f[:class_name], queue: f[:queue])
144
+ :refresh
145
+ end
205
146
  end
206
147
 
207
148
  def render_failed_table(frame, area)
@@ -214,7 +155,7 @@ module SolidQueueTui
214
155
  { key: :failed_at, label: "FAILED", width: 12 }
215
156
  ]
216
157
 
217
- rows = @failed_jobs.map do |job|
158
+ rows = items.map do |job|
218
159
  {
219
160
  id: job.job_id,
220
161
  class_name: job.class_name,
@@ -238,51 +179,6 @@ module SolidQueueTui
238
179
  table.render(frame, area, @table_state)
239
180
  end
240
181
 
241
- def render_confirm(frame, area)
242
- message = case @confirm_action
243
- when :retry
244
- job = selected_item
245
- "Retry job ##{job&.job_id} (#{job&.class_name})? [y/n]"
246
- when :discard
247
- job = selected_item
248
- "Discard job ##{job&.job_id} (#{job&.class_name})? This cannot be undone. [y/n]"
249
- when :retry_all
250
- count = @total_count || @failed_jobs.size
251
- label = @filters.empty? ? "failed jobs" : "filtered failed jobs"
252
- "Retry ALL #{count} #{label}? [y/n]"
253
- end
254
-
255
- frame.render_widget(
256
- @tui.paragraph(
257
- text: " #{message}",
258
- style: @tui.style(fg: :yellow, modifiers: [:bold]),
259
- block: @tui.block(
260
- title: " Confirm ",
261
- title_style: @tui.style(fg: :red, modifiers: [:bold]),
262
- borders: [:all],
263
- border_type: :rounded,
264
- border_style: @tui.style(fg: :red)
265
- )
266
- ),
267
- area
268
- )
269
- end
270
-
271
- def truncate(str, max)
272
- return "" unless str
273
- str.length > max ? "#{str[0...max - 3]}..." : str
274
- end
275
-
276
- def time_ago(time)
277
- return "n/a" unless time
278
- seconds = (Time.now.utc - time).to_i
279
- case seconds
280
- when 0..59 then "#{seconds}s ago"
281
- when 60..3599 then "#{seconds / 60}m ago"
282
- when 3600..86399 then "#{seconds / 3600}h ago"
283
- else "#{seconds / 86400}d ago"
284
- end
285
- end
286
182
  end
287
183
  end
288
184
  end
@@ -4,47 +4,21 @@ module SolidQueueTui
4
4
  module Views
5
5
  class FinishedView
6
6
  include Filterable
7
-
8
-
9
- LOAD_THRESHOLD = 10
7
+ include Paginatable
8
+ include FormattingHelpers
10
9
 
11
10
  def initialize(tui)
12
11
  @tui = tui
13
- @table_state = RatatuiRuby::TableState.new(nil)
14
- @table_state.select(0)
15
- @selected_row = 0
16
- @jobs = []
17
- @total_count = nil
18
- @all_loaded = false
12
+ init_pagination
19
13
  init_filter
20
14
  end
21
15
 
22
16
  def update(jobs:)
23
- @jobs = jobs
24
- @all_loaded = jobs.size < SolidQueueTui.page_size
25
- @selected_row = @selected_row.clamp(0, [@jobs.size - 1, 0].max)
26
- @table_state.select(@selected_row)
17
+ update_items(jobs)
27
18
  end
28
19
 
29
20
  def append(jobs:)
30
- @jobs.concat(jobs)
31
- @all_loaded = jobs.size < SolidQueueTui.page_size
32
- end
33
-
34
- def total_count=(count)
35
- @total_count = count
36
- end
37
-
38
- def current_offset
39
- @jobs.size
40
- end
41
-
42
- def reset_pagination!
43
- @jobs = []
44
- @total_count = nil
45
- @all_loaded = false
46
- @selected_row = 0
47
- @table_state.select(0)
21
+ append_items(jobs)
48
22
  end
49
23
 
50
24
  def render(frame, area)
@@ -72,11 +46,6 @@ module SolidQueueTui
72
46
  end
73
47
  end
74
48
 
75
- def selected_item
76
- return nil if @jobs.empty? || @selected_row >= @jobs.size
77
- @jobs[@selected_row]
78
- end
79
-
80
49
  def bindings
81
50
  if filter_mode?
82
51
  filter_bindings
@@ -101,10 +70,6 @@ module SolidQueueTui
101
70
 
102
71
  private
103
72
 
104
- def needs_more?
105
- !@all_loaded && @selected_row >= @jobs.size - LOAD_THRESHOLD
106
- end
107
-
108
73
  def handle_normal_input(event)
109
74
  case event
110
75
  in { type: :key, code: "j" } | { type: :key, code: "up" }
@@ -127,25 +92,6 @@ module SolidQueueTui
127
92
  end
128
93
  end
129
94
 
130
- def move_selection(delta)
131
- return if @jobs.empty?
132
- @selected_row = (@selected_row + delta).clamp(0, @jobs.size - 1)
133
- @table_state.select(@selected_row)
134
- :load_more if needs_more?
135
- end
136
-
137
- def jump_to_top
138
- @selected_row = 0
139
- @table_state.select(0)
140
- end
141
-
142
- def jump_to_bottom
143
- return if @jobs.empty?
144
- @selected_row = @jobs.size - 1
145
- @table_state.select(@selected_row)
146
- return :load_more if needs_more?
147
- end
148
-
149
95
  def render_table(frame, area)
150
96
  columns = [
151
97
  { key: :id, label: "ID", width: 8 },
@@ -156,14 +102,14 @@ module SolidQueueTui
156
102
  { key: :duration, label: "DURATION", width: 12 }
157
103
  ]
158
104
 
159
- rows = @jobs.map do |job|
105
+ rows = items.map do |job|
160
106
  {
161
107
  id: job.id,
162
108
  queue_name: job.queue_name,
163
109
  class_name: job.class_name,
164
110
  priority: job.priority,
165
111
  finished_at: format_time(job.finished_at),
166
- duration: format_duration(job.created_at, job.finished_at)
112
+ duration: job_duration(job.created_at, job.finished_at)
167
113
  }
168
114
  end
169
115
 
@@ -180,23 +126,9 @@ module SolidQueueTui
180
126
  table.render(frame, area, @table_state)
181
127
  end
182
128
 
183
- def format_time(time)
184
- return "n/a" unless time
185
- time.strftime("%Y-%m-%d %H:%M:%S")
186
- end
187
-
188
- def format_duration(created, finished)
129
+ def job_duration(created, finished)
189
130
  return "n/a" unless created && finished
190
- seconds = (finished - created).to_i
191
- if seconds < 1
192
- "<1s"
193
- elsif seconds < 60
194
- "#{seconds}s"
195
- elsif seconds < 3600
196
- "#{seconds / 60}m #{seconds % 60}s"
197
- else
198
- "#{seconds / 3600}h #{(seconds % 3600) / 60}m"
199
- end
131
+ format_duration((finished - created).to_i)
200
132
  end
201
133
  end
202
134
  end
@@ -4,47 +4,21 @@ module SolidQueueTui
4
4
  module Views
5
5
  class InProgressView
6
6
  include Filterable
7
-
8
-
9
- LOAD_THRESHOLD = 10
7
+ include Paginatable
8
+ include FormattingHelpers
10
9
 
11
10
  def initialize(tui)
12
11
  @tui = tui
13
- @table_state = RatatuiRuby::TableState.new(nil)
14
- @table_state.select(0)
15
- @selected_row = 0
16
- @jobs = []
17
- @total_count = nil
18
- @all_loaded = false
12
+ init_pagination
19
13
  init_filter
20
14
  end
21
15
 
22
16
  def update(jobs:)
23
- @jobs = jobs
24
- @all_loaded = jobs.size < SolidQueueTui.page_size
25
- @selected_row = @selected_row.clamp(0, [@jobs.size - 1, 0].max)
26
- @table_state.select(@selected_row)
17
+ update_items(jobs)
27
18
  end
28
19
 
29
20
  def append(jobs:)
30
- @jobs.concat(jobs)
31
- @all_loaded = jobs.size < SolidQueueTui.page_size
32
- end
33
-
34
- def total_count=(count)
35
- @total_count = count
36
- end
37
-
38
- def current_offset
39
- @jobs.size
40
- end
41
-
42
- def reset_pagination!
43
- @jobs = []
44
- @total_count = nil
45
- @all_loaded = false
46
- @selected_row = 0
47
- @table_state.select(0)
21
+ append_items(jobs)
48
22
  end
49
23
 
50
24
  def render(frame, area)
@@ -72,11 +46,6 @@ module SolidQueueTui
72
46
  end
73
47
  end
74
48
 
75
- def selected_item
76
- return nil if @jobs.empty? || @selected_row >= @jobs.size
77
- @jobs[@selected_row]
78
- end
79
-
80
49
  def bindings
81
50
  if filter_mode?
82
51
  filter_bindings
@@ -100,10 +69,6 @@ module SolidQueueTui
100
69
 
101
70
  private
102
71
 
103
- def needs_more?
104
- !@all_loaded && @selected_row >= @jobs.size - LOAD_THRESHOLD
105
- end
106
-
107
72
  def handle_normal_input(event)
108
73
  case event
109
74
  in { type: :key, code: "j" } | { type: :key, code: "up" }
@@ -126,25 +91,6 @@ module SolidQueueTui
126
91
  end
127
92
  end
128
93
 
129
- def move_selection(delta)
130
- return if @jobs.empty?
131
- @selected_row = (@selected_row + delta).clamp(0, @jobs.size - 1)
132
- @table_state.select(@selected_row)
133
- :load_more if needs_more?
134
- end
135
-
136
- def jump_to_top
137
- @selected_row = 0
138
- @table_state.select(0)
139
- end
140
-
141
- def jump_to_bottom
142
- return if @jobs.empty?
143
- @selected_row = @jobs.size - 1
144
- @table_state.select(@selected_row)
145
- return :load_more if needs_more?
146
- end
147
-
148
94
  def render_table(frame, area)
149
95
  columns = [
150
96
  { key: :id, label: "ID", width: 8 },
@@ -155,7 +101,7 @@ module SolidQueueTui
155
101
  { key: :started_at, label: "STARTED", width: 12 }
156
102
  ]
157
103
 
158
- rows = @jobs.map do |job|
104
+ rows = items.map do |job|
159
105
  {
160
106
  id: job.id,
161
107
  queue_name: job.queue_name,
@@ -179,16 +125,6 @@ module SolidQueueTui
179
125
  table.render(frame, area, @table_state)
180
126
  end
181
127
 
182
- def time_ago(time)
183
- return "n/a" unless time
184
- seconds = (Time.now.utc - time).to_i
185
- case seconds
186
- when 0..59 then "#{seconds}s ago"
187
- when 60..3599 then "#{seconds / 60}m ago"
188
- when 3600..86399 then "#{seconds / 3600}h ago"
189
- else "#{seconds / 86400}d ago"
190
- end
191
- end
192
128
  end
193
129
  end
194
130
  end