maintenance_tasks 1.0.0 → 1.2.1
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 +4 -4
- data/README.md +180 -22
- data/Rakefile +16 -16
- data/app/controllers/maintenance_tasks/application_controller.rb +3 -6
- data/app/controllers/maintenance_tasks/runs_controller.rb +1 -12
- data/app/controllers/maintenance_tasks/tasks_controller.rb +7 -4
- data/app/helpers/maintenance_tasks/application_helper.rb +2 -48
- data/app/helpers/maintenance_tasks/{task_helper.rb → tasks_helper.rb} +26 -18
- data/app/jobs/maintenance_tasks/task_job.rb +49 -6
- data/app/models/maintenance_tasks/application_record.rb +2 -2
- data/app/models/maintenance_tasks/csv_collection.rb +33 -0
- data/app/models/maintenance_tasks/progress.rb +19 -14
- data/app/models/maintenance_tasks/run.rb +39 -1
- data/app/models/maintenance_tasks/runner.rb +20 -5
- data/app/models/maintenance_tasks/runs_page.rb +55 -0
- data/app/models/maintenance_tasks/task_data.rb +9 -5
- data/app/models/maintenance_tasks/ticker.rb +0 -1
- data/app/tasks/maintenance_tasks/task.rb +43 -16
- data/app/validators/maintenance_tasks/run_status_validator.rb +15 -13
- data/app/views/layouts/maintenance_tasks/_navbar.html.erb +0 -6
- data/app/views/maintenance_tasks/runs/_info.html.erb +6 -0
- data/app/views/maintenance_tasks/runs/_run.html.erb +1 -9
- data/app/views/maintenance_tasks/runs/info/_running.html.erb +0 -2
- data/app/views/maintenance_tasks/tasks/show.html.erb +31 -4
- data/config/routes.rb +4 -6
- data/db/migrate/20210225152418_remove_index_on_task_name.rb +14 -0
- data/exe/maintenance_tasks +2 -2
- data/lib/generators/maintenance_tasks/install_generator.rb +4 -5
- data/lib/generators/maintenance_tasks/task_generator.rb +15 -9
- data/lib/generators/maintenance_tasks/templates/csv_task.rb.tt +13 -0
- data/lib/generators/maintenance_tasks/templates/task_spec.rb.tt +1 -1
- data/lib/generators/maintenance_tasks/templates/task_test.rb.tt +1 -1
- data/lib/maintenance_tasks.rb +34 -30
- data/lib/maintenance_tasks/cli.rb +18 -4
- data/lib/maintenance_tasks/engine.rb +6 -3
- metadata +9 -31
- data/app/views/maintenance_tasks/runs/index.html.erb +0 -15
- data/app/views/maintenance_tasks/tasks/actions/_cancelled.html.erb +0 -1
- data/app/views/maintenance_tasks/tasks/actions/_cancelling.html.erb +0 -4
- data/app/views/maintenance_tasks/tasks/actions/_enqueued.html.erb +0 -2
- data/app/views/maintenance_tasks/tasks/actions/_errored.html.erb +0 -1
- data/app/views/maintenance_tasks/tasks/actions/_interrupted.html.erb +0 -2
- data/app/views/maintenance_tasks/tasks/actions/_new.html.erb +0 -1
- data/app/views/maintenance_tasks/tasks/actions/_paused.html.erb +0 -2
- data/app/views/maintenance_tasks/tasks/actions/_pausing.html.erb +0 -2
- data/app/views/maintenance_tasks/tasks/actions/_running.html.erb +0 -2
- data/app/views/maintenance_tasks/tasks/actions/_succeeded.html.erb +0 -1
- data/lib/maintenance_tasks/integrations/bugsnag_handler.rb +0 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c673afea63371c8c8f69ccda520b66fb1391d17ff6f241eb5610e45c60493561
|
4
|
+
data.tar.gz: a1b914d6fdf7391bda0691444f8af2e263c71313c295bf2fd38e6e655f661a99
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d161e823b16c12abd127d725cccf985d0bca50253cb40937d265685d6078730beff127913eea7973ff23211576d5d143508ac61968ebb2460f1c12fc89ff5d82
|
7
|
+
data.tar.gz: 46de8ac9e6819829de191a0fcfaf40c48b2922f1cc3024df58a41a7e6763658149f3f32baa168045bae6c00790da1b789647d36bad880714bdf63e75d67aeb32
|
data/README.md
CHANGED
@@ -3,11 +3,16 @@
|
|
3
3
|
A Rails engine for queuing and managing maintenance tasks.
|
4
4
|
|
5
5
|
## Table of Contents
|
6
|
+
|
7
|
+
* [Demo](#demo)
|
6
8
|
* [Installation](#installation)
|
9
|
+
* [Active Job Dependency](#active-job-dependency)
|
7
10
|
* [Usage](#usage)
|
8
11
|
* [Creating a Task](#creating-a-task)
|
9
|
-
|
12
|
+
* [Creating a CSV Task](#creating-a-csv-task)
|
13
|
+
* [Considerations when writing Tasks](#considerations-when-writing-tasks)
|
10
14
|
* [Writing tests for a Task](#writing-tests-for-a-task)
|
15
|
+
* [Writing tests for a CSV Task](#writing-tests-for-a-csv-task)
|
11
16
|
* [Running a Task](#running-a-task)
|
12
17
|
* [Monitoring your Task's status](#monitoring-your-tasks-status)
|
13
18
|
* [How Maintenance Tasks runs a Task](#how-maintenance-tasks-runs-a-task)
|
@@ -17,22 +22,23 @@ A Rails engine for queuing and managing maintenance tasks.
|
|
17
22
|
* [Customizing the maintenance tasks module](#customizing-the-maintenance-tasks-module)
|
18
23
|
* [Customizing the underlying job class](#customizing-the-underlying-job-class)
|
19
24
|
* [Customizing the rate at which task progress gets updated](#customizing-the-rate-at-which-task-progress-gets-updated)
|
25
|
+
* [Customizing which Active Storage service to use](#customizing-which-active-storage-service-to-use)
|
20
26
|
* [Upgrading](#upgrading)
|
21
27
|
* [Contributing](#contributing)
|
22
28
|
* [Releasing new versions](#releasing-new-versions)
|
23
29
|
|
24
|
-
##
|
30
|
+
## Demo
|
25
31
|
|
26
|
-
|
32
|
+
Watch this demo video to see the gem in action:
|
27
33
|
|
28
|
-
|
29
|
-
gem 'maintenance_tasks'
|
30
|
-
```
|
34
|
+
[](https://www.youtube.com/watch?v=BTuvTQxlFzs)
|
31
35
|
|
32
|
-
|
36
|
+
## Installation
|
37
|
+
|
38
|
+
To install the gem and run the install generator, execute:
|
33
39
|
|
34
40
|
```bash
|
35
|
-
$ bundle
|
41
|
+
$ bundle add maintenance_tasks
|
36
42
|
$ rails generate maintenance_tasks:install
|
37
43
|
```
|
38
44
|
|
@@ -40,6 +46,22 @@ The generator creates and runs a migration to add the necessary table to your
|
|
40
46
|
database. It also mounts Maintenance Tasks in your `config/routes.rb`. By
|
41
47
|
default the web UI can be accessed in the new `/maintenance_tasks` path.
|
42
48
|
|
49
|
+
In case you use an exception reporting service (e.g. Bugsnag) you might want to
|
50
|
+
define an error handler. See [Customizing the error
|
51
|
+
handler](#customizing-the-error-handler) for more information.
|
52
|
+
|
53
|
+
### Active Job Dependency
|
54
|
+
|
55
|
+
The Maintenance Tasks framework relies on ActiveJob behind the scenes to run
|
56
|
+
Tasks. The default queuing backend for ActiveJob is
|
57
|
+
[asynchronous][async-adapter]. It is **strongly recommended** to change this to
|
58
|
+
a persistent backend so that Task progress is not lost during code or
|
59
|
+
infrastructure changes. For more information on configuring a queuing backend,
|
60
|
+
take a look at the [ActiveJob documentation][active-job-docs].
|
61
|
+
|
62
|
+
[async-adapter]: https://api.rubyonrails.org/classes/ActiveJob/QueueAdapters/AsyncAdapter.html
|
63
|
+
[active-job-docs]: https://guides.rubyonrails.org/active_job_basics.html#setting-the-backend
|
64
|
+
|
43
65
|
## Usage
|
44
66
|
|
45
67
|
### Creating a Task
|
@@ -81,7 +103,45 @@ module Maintenance
|
|
81
103
|
end
|
82
104
|
```
|
83
105
|
|
84
|
-
|
106
|
+
### Creating a CSV Task
|
107
|
+
|
108
|
+
You can also write a Task that iterates on a CSV file. Note that writing CSV
|
109
|
+
Tasks **requires ActiveStorage to be configured**. Ensure that the dependency
|
110
|
+
is specified in your application's Gemfile, and that you've followed the
|
111
|
+
[setup instuctions][setup].
|
112
|
+
|
113
|
+
[setup]: https://edgeguides.rubyonrails.org/active_storage_overview.html#setup
|
114
|
+
|
115
|
+
Generate a CSV Task by running:
|
116
|
+
|
117
|
+
```bash
|
118
|
+
$ rails generate maintenance_tasks:task import_posts --csv
|
119
|
+
```
|
120
|
+
|
121
|
+
The generated task is a subclass of `MaintenanceTasks::Task` that implements:
|
122
|
+
|
123
|
+
* `process`: do the work of your maintenance task on a `CSV::Row`
|
124
|
+
|
125
|
+
```ruby
|
126
|
+
# app/tasks/maintenance/import_posts_task.rb
|
127
|
+
module Maintenance
|
128
|
+
class ImportPostsTask < MaintenanceTasks::Task
|
129
|
+
csv_collection
|
130
|
+
|
131
|
+
def process(row)
|
132
|
+
Post.create!(title: row["title"], content: row["content"])
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
```
|
137
|
+
|
138
|
+
```csv
|
139
|
+
# posts.csv
|
140
|
+
title,content
|
141
|
+
My Title,Hello World!
|
142
|
+
```
|
143
|
+
|
144
|
+
### Considerations when writing Tasks
|
85
145
|
|
86
146
|
MaintenanceTasks relies on the queue adapter configured for your application to
|
87
147
|
run the job which is processing your Task. The guidelines for writing Task may
|
@@ -120,7 +180,7 @@ module Maintenance
|
|
120
180
|
test "#process performs a task iteration" do
|
121
181
|
post = Post.new
|
122
182
|
|
123
|
-
Maintenance::UpdatePostsTask.
|
183
|
+
Maintenance::UpdatePostsTask.process(post)
|
124
184
|
|
125
185
|
assert_equal 'New content!', post.content
|
126
186
|
end
|
@@ -128,6 +188,32 @@ module Maintenance
|
|
128
188
|
end
|
129
189
|
```
|
130
190
|
|
191
|
+
### Writing tests for a CSV Task
|
192
|
+
|
193
|
+
You should write tests for your `#process` method in a CSV Task as well. It
|
194
|
+
takes a `CSV::Row` as an argument. You can pass a row, or a hash with string
|
195
|
+
keys to `#process` from your test.
|
196
|
+
|
197
|
+
```ruby
|
198
|
+
# app/tasks/maintenance/import_posts_task_test.rb
|
199
|
+
module Maintenance
|
200
|
+
class ImportPostsTaskTest < ActiveSupport::TestCase
|
201
|
+
test "#process performs a task iteration" do
|
202
|
+
assert_difference -> { Post.count } do
|
203
|
+
Maintenance::UpdatePostsTask.process({
|
204
|
+
'title' => 'My Title',
|
205
|
+
'content' => 'Hello World!',
|
206
|
+
})
|
207
|
+
end
|
208
|
+
|
209
|
+
post = Post.last
|
210
|
+
assert_equal 'My Title', post.title
|
211
|
+
assert_equal 'Hello World!', post.content
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
```
|
216
|
+
|
131
217
|
### Running a Task
|
132
218
|
|
133
219
|
You can run your new Task by accessing the Web UI and clicking on "Run".
|
@@ -138,11 +224,26 @@ Alternatively, you can run your Task in the command line:
|
|
138
224
|
$ bundle exec maintenance_tasks perform Maintenance::UpdatePostsTask
|
139
225
|
```
|
140
226
|
|
141
|
-
|
142
|
-
|
227
|
+
To run a Task that processes CSVs from the command line, use the --csv option:
|
228
|
+
|
229
|
+
```bash
|
230
|
+
$ bundle exec maintenance_tasks perform Maintenance::ImportPostsTask --csv 'path/to/my_csv.csv'
|
231
|
+
```
|
232
|
+
|
233
|
+
You can also run a Task in Ruby by sending `run` with a Task name to Runner:
|
234
|
+
|
235
|
+
```ruby
|
236
|
+
MaintenanceTasks::Runner.run(name: 'Maintenance::UpdatePostsTask')
|
237
|
+
```
|
238
|
+
|
239
|
+
To run a Task that processes CSVs using the Runner, provide a Hash containing an
|
240
|
+
open IO object and a filename to `run`:
|
143
241
|
|
144
242
|
```ruby
|
145
|
-
MaintenanceTasks::Runner.
|
243
|
+
MaintenanceTasks::Runner.run(
|
244
|
+
name: 'Maintenance::ImportPostsTask'
|
245
|
+
csv_file: { io: File.open('path/to/my_csv.csv'), filename: 'my_csv.csv' }
|
246
|
+
)
|
146
247
|
```
|
147
248
|
|
148
249
|
### Monitoring your Task's status
|
@@ -224,17 +325,39 @@ be placed in a `maintenance_tasks.rb` initializer.
|
|
224
325
|
Exceptions raised while a Task is performing are rescued and information about
|
225
326
|
the error is persisted and visible in the UI.
|
226
327
|
|
227
|
-
If
|
228
|
-
|
229
|
-
|
230
|
-
If you want to integrate with another exception monitoring service or customize
|
231
|
-
error handling, a callback can be defined:
|
328
|
+
If you want to integrate with an exception monitoring service (e.g. Bugsnag),
|
329
|
+
you can define an error handler:
|
232
330
|
|
233
331
|
```ruby
|
234
332
|
# config/initializers/maintenance_tasks.rb
|
235
|
-
MaintenanceTasks.error_handler = ->(error
|
333
|
+
MaintenanceTasks.error_handler = ->(error, task_context, _errored_element) do
|
334
|
+
Bugsnag.notify(error) do |notification|
|
335
|
+
notification.add_tab(:task, task_context)
|
336
|
+
end
|
337
|
+
end
|
236
338
|
```
|
237
339
|
|
340
|
+
The error handler should be a lambda that accepts three arguments:
|
341
|
+
|
342
|
+
* `error`: The exception that was raised.
|
343
|
+
* `task_context`: A hash with additional information about the Task and the
|
344
|
+
error:
|
345
|
+
* `task_name`: The name of the Task that errored
|
346
|
+
* `started_at`: The time the Task started
|
347
|
+
* `ended_at`: The time the Task errored
|
348
|
+
Note that `task_context` may be empty if the Task produced an error before any
|
349
|
+
context could be gathered (for example, if deserializing the job to process
|
350
|
+
your Task failed).
|
351
|
+
* `errored_element`: The element, if any, that was being processed when the
|
352
|
+
Task raised an exception. If you would like to pass this object to your
|
353
|
+
exception monitoring service, make sure you **sanitize the object** to avoid
|
354
|
+
leaking sensitive data and **convert it to a format** that is compatible with
|
355
|
+
your bug tracker. For example, Bugsnag only sends the id and class name of
|
356
|
+
ActiveRecord objects in order to protect sensitive data. CSV rows, on the
|
357
|
+
other hand, are converted to strings and passed raw to Bugsnag, so make sure
|
358
|
+
to filter any personal data from these objects before adding them to a
|
359
|
+
report.
|
360
|
+
|
238
361
|
#### Customizing the maintenance tasks module
|
239
362
|
|
240
363
|
`MaintenanceTasks.tasks_module` can be configured to define the module in which
|
@@ -281,6 +404,36 @@ MaintenanceTasks.ticker_delay = 2.seconds
|
|
281
404
|
|
282
405
|
If no value is specified, it will default to 1 second.
|
283
406
|
|
407
|
+
#### Customizing which Active Storage service to use
|
408
|
+
|
409
|
+
The Active Storage framework in Rails 6.1 and up supports multiple storage
|
410
|
+
services per environment. To specify which service to use,
|
411
|
+
`MaintenanceTasks.active_storage_service` can be configured with the service's
|
412
|
+
key, as specified in your application's `config/storage.yml`:
|
413
|
+
|
414
|
+
```yaml
|
415
|
+
# config/storage.yml
|
416
|
+
user_data:
|
417
|
+
service: GCS
|
418
|
+
credentials: <%= Rails.root.join("path/to/user/data/keyfile.json") %>
|
419
|
+
project: "my-project"
|
420
|
+
bucket: "user-data-bucket"
|
421
|
+
|
422
|
+
internal:
|
423
|
+
service: GCS
|
424
|
+
credentials: <%= Rails.root.join("path/to/internal/keyfile.json") %>
|
425
|
+
project: "my-project"
|
426
|
+
bucket: "internal-bucket"
|
427
|
+
```
|
428
|
+
|
429
|
+
```ruby
|
430
|
+
# config/initializers/maintenance_tasks.rb
|
431
|
+
MaintenanceTasks.active_storage_service = :internal
|
432
|
+
```
|
433
|
+
|
434
|
+
There is no need to configure this option if your application uses only one
|
435
|
+
storage service per environment.
|
436
|
+
|
284
437
|
## Upgrading
|
285
438
|
|
286
439
|
Use bundler to check for and upgrade to newer versions. After installing a new
|
@@ -302,15 +455,20 @@ pull requests. You can find the contribution guidelines on
|
|
302
455
|
|
303
456
|
## Releasing new versions
|
304
457
|
|
305
|
-
|
458
|
+
Updates should be added to the latest draft release on GitHub as Pull Requests
|
459
|
+
are merged.
|
460
|
+
|
461
|
+
Once a release is ready, follow these steps:
|
306
462
|
|
307
463
|
* Update `spec.version` in `maintenance_tasks.gemspec`.
|
308
464
|
* Run `bundle install` to bump the `Gemfile.lock` version of the gem.
|
309
465
|
* Open a PR and merge on approval.
|
310
|
-
* Create a [release on GitHub][release] with a version number that matches the
|
311
|
-
version defined in the gemspec.
|
312
466
|
* Deploy via [Shipit][shipit] and see the new version on
|
313
467
|
<https://rubygems.org/gems/maintenance_tasks>.
|
468
|
+
* Ensure the release has documented all changes and publish it.
|
469
|
+
* Create a new [draft release on GitHub][release] with the title
|
470
|
+
'Upcoming Release'. The tag version can be left blank. This will be the
|
471
|
+
starting point for documenting changes related to the next release.
|
314
472
|
|
315
473
|
[release]: https://help.github.com/articles/creating-releases/
|
316
474
|
[shipit]: https://shipit.shopify.io/shopify/maintenance_tasks/rubygems
|
data/Rakefile
CHANGED
@@ -1,29 +1,29 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
begin
|
3
|
-
require
|
3
|
+
require "bundler/setup"
|
4
4
|
rescue LoadError
|
5
|
-
puts
|
5
|
+
puts "You must `gem install bundler` and `bundle install` to run rake tasks"
|
6
6
|
end
|
7
7
|
|
8
|
-
require
|
8
|
+
require "rdoc/task"
|
9
9
|
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
-
rdoc.rdoc_dir =
|
11
|
-
rdoc.title =
|
12
|
-
rdoc.options <<
|
13
|
-
rdoc.rdoc_files.include(
|
14
|
-
rdoc.rdoc_files.include(
|
10
|
+
rdoc.rdoc_dir = "rdoc"
|
11
|
+
rdoc.title = "MaintenanceTasks"
|
12
|
+
rdoc.options << "--line-numbers"
|
13
|
+
rdoc.rdoc_files.include("README.md")
|
14
|
+
rdoc.rdoc_files.include("lib/**/*.rb")
|
15
15
|
end
|
16
16
|
|
17
|
-
APP_RAKEFILE = File.expand_path(
|
18
|
-
load(
|
17
|
+
APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
|
18
|
+
load("rails/tasks/engine.rake")
|
19
19
|
|
20
|
-
load(
|
20
|
+
load("rails/tasks/statistics.rake")
|
21
21
|
|
22
|
-
require
|
22
|
+
require "bundler/gem_tasks"
|
23
23
|
|
24
|
-
require
|
24
|
+
require "rubocop/rake_task"
|
25
25
|
RuboCop::RakeTask.new
|
26
26
|
|
27
|
-
task(test:
|
28
|
-
task(
|
29
|
-
task(default: [
|
27
|
+
task(test: "app:test")
|
28
|
+
task("test:system" => "app:test:system")
|
29
|
+
task(default: ["db:test:prepare", "test", "test:system", "rubocop"])
|
@@ -3,11 +3,9 @@
|
|
3
3
|
module MaintenanceTasks
|
4
4
|
# Base class for all controllers used by this engine.
|
5
5
|
#
|
6
|
-
#
|
6
|
+
# Can be extended to add different authentication and authorization code.
|
7
7
|
class ApplicationController < ActionController::Base
|
8
|
-
|
9
|
-
|
10
|
-
BULMA_CDN = 'https://cdn.jsdelivr.net'
|
8
|
+
BULMA_CDN = "https://cdn.jsdelivr.net"
|
11
9
|
|
12
10
|
content_security_policy do |policy|
|
13
11
|
policy.style_src(BULMA_CDN)
|
@@ -17,10 +15,9 @@ module MaintenanceTasks
|
|
17
15
|
before_action do
|
18
16
|
request.content_security_policy_nonce_generator ||=
|
19
17
|
->(_request) { SecureRandom.base64(16) }
|
20
|
-
request.content_security_policy_nonce_directives = [
|
18
|
+
request.content_security_policy_nonce_directives = ["style-src"]
|
21
19
|
end
|
22
20
|
|
23
21
|
protect_from_forgery with: :exception
|
24
22
|
end
|
25
|
-
private_constant :ApplicationController
|
26
23
|
end
|
@@ -6,17 +6,7 @@ module MaintenanceTasks
|
|
6
6
|
#
|
7
7
|
# @api private
|
8
8
|
class RunsController < ApplicationController
|
9
|
-
before_action :set_run
|
10
|
-
|
11
|
-
# Shows a full list of Runs.
|
12
|
-
def index
|
13
|
-
query = Run.all.order(id: :desc)
|
14
|
-
if params[:task_name].present?
|
15
|
-
task_name = Run.sanitize_sql_like(params[:task_name])
|
16
|
-
query = query.where('task_name LIKE ?', "%#{task_name}%")
|
17
|
-
end
|
18
|
-
@pagy, @runs = pagy(query)
|
19
|
-
end
|
9
|
+
before_action :set_run
|
20
10
|
|
21
11
|
# Updates a Run status to paused.
|
22
12
|
def pause
|
@@ -40,5 +30,4 @@ module MaintenanceTasks
|
|
40
30
|
@run = Run.find(params.fetch(:id))
|
41
31
|
end
|
42
32
|
end
|
43
|
-
private_constant :RunsController
|
44
33
|
end
|
@@ -7,7 +7,7 @@ module MaintenanceTasks
|
|
7
7
|
#
|
8
8
|
# @api private
|
9
9
|
class TasksController < ApplicationController
|
10
|
-
before_action :set_refresh, only: [:index
|
10
|
+
before_action :set_refresh, only: [:index]
|
11
11
|
|
12
12
|
# Renders the maintenance_tasks/tasks page, displaying
|
13
13
|
# available tasks to users, grouped by category.
|
@@ -19,12 +19,16 @@ module MaintenanceTasks
|
|
19
19
|
# Shows running and completed instances of the Task.
|
20
20
|
def show
|
21
21
|
@task = TaskData.find(params.fetch(:id))
|
22
|
-
|
22
|
+
set_refresh if @task.last_run&.active?
|
23
|
+
@runs_page = RunsPage.new(@task.previous_runs, params[:cursor])
|
23
24
|
end
|
24
25
|
|
25
26
|
# Runs a given Task and redirects to the Task page.
|
26
27
|
def run
|
27
|
-
task = Runner.
|
28
|
+
task = Runner.run(
|
29
|
+
name: params.fetch(:id),
|
30
|
+
csv_file: params[:csv_file]
|
31
|
+
)
|
28
32
|
redirect_to(task_path(task))
|
29
33
|
rescue ActiveRecord::RecordInvalid => error
|
30
34
|
redirect_to(task_path(error.record.task_name), alert: error.message)
|
@@ -38,5 +42,4 @@ module MaintenanceTasks
|
|
38
42
|
@refresh = 3
|
39
43
|
end
|
40
44
|
end
|
41
|
-
private_constant :TasksController
|
42
45
|
end
|
@@ -4,17 +4,6 @@ module MaintenanceTasks
|
|
4
4
|
#
|
5
5
|
# @api private
|
6
6
|
module ApplicationHelper
|
7
|
-
include Pagy::Frontend
|
8
|
-
|
9
|
-
# Renders pagination for the page, if there is more than one page present.
|
10
|
-
#
|
11
|
-
# @param pagy [Pagy] the pagy instance containing pagination details,
|
12
|
-
# including the number of pages the results are spread across.
|
13
|
-
# @return [String] the HTML to render for pagination.
|
14
|
-
def pagination(pagy)
|
15
|
-
raw(pagy_bulma_nav(pagy)) if pagy.pages > 1
|
16
|
-
end
|
17
|
-
|
18
7
|
# Renders a time element with the given datetime, worded as relative to the
|
19
8
|
# current time.
|
20
9
|
#
|
@@ -24,44 +13,9 @@ module MaintenanceTasks
|
|
24
13
|
# @param datetime [ActiveSupport::TimeWithZone] the time to be presented.
|
25
14
|
# @return [String] the HTML to render with the relative datetime in words.
|
26
15
|
def time_ago(datetime)
|
27
|
-
time_tag(datetime, title: datetime.utc.iso8601, class:
|
28
|
-
time_ago_in_words(datetime) +
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
# Fix stylesheet_link_tag to handle integrity when preloading.
|
33
|
-
# To be reverted once fixed upstream in Rails.
|
34
|
-
def stylesheet_link_tag(*sources)
|
35
|
-
return super unless respond_to?(:send_preload_links_header, true)
|
36
|
-
options = sources.extract_options!.stringify_keys
|
37
|
-
path_options = options.extract!('protocol', 'host', 'skip_pipeline')
|
38
|
-
.symbolize_keys
|
39
|
-
preload_links = []
|
40
|
-
crossorigin = options.delete('crossorigin')
|
41
|
-
crossorigin = 'anonymous' if crossorigin == true
|
42
|
-
nopush = options['nopush'].nil? ? true : options.delete('nopush')
|
43
|
-
integrity = options['integrity']
|
44
|
-
|
45
|
-
sources_tags = sources.uniq.map do |source|
|
46
|
-
href = path_to_stylesheet(source, path_options)
|
47
|
-
preload_link = "<#{href}>; rel=preload; as=style"
|
48
|
-
preload_link += "; crossorigin=#{crossorigin}" unless crossorigin.nil?
|
49
|
-
preload_link += "; integrity=#{integrity}" unless integrity.nil?
|
50
|
-
preload_link += '; nopush' if nopush
|
51
|
-
preload_links << preload_link
|
52
|
-
tag_options = {
|
53
|
-
'rel' => 'stylesheet',
|
54
|
-
'media' => 'screen',
|
55
|
-
'crossorigin' => crossorigin,
|
56
|
-
'href' => href,
|
57
|
-
}.merge!(options)
|
58
|
-
tag(:link, tag_options)
|
16
|
+
time_tag(datetime, title: datetime.utc.iso8601, class: "is-clickable") do
|
17
|
+
time_ago_in_words(datetime) + " ago"
|
59
18
|
end
|
60
|
-
|
61
|
-
send_preload_links_header(preload_links)
|
62
|
-
|
63
|
-
safe_join(sources_tags)
|
64
19
|
end
|
65
20
|
end
|
66
|
-
private_constant :ApplicationHelper
|
67
21
|
end
|