good_job 4.12.1 → 4.13.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.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +41 -0
  3. data/README.md +3 -2
  4. data/app/controllers/good_job/batches_controller.rb +1 -1
  5. data/app/controllers/good_job/cron_entries_controller.rb +3 -3
  6. data/app/controllers/good_job/frontends_controller.rb +15 -10
  7. data/app/controllers/good_job/jobs_controller.rb +7 -7
  8. data/app/controllers/good_job/pauses_controller.rb +2 -2
  9. data/app/frontend/good_job/application.js +23 -9
  10. data/app/frontend/good_job/modules/form_controller.js +11 -0
  11. data/app/frontend/good_job/vendor/turbo.js +34 -0
  12. data/app/models/good_job/batch.rb +2 -0
  13. data/app/models/good_job/batch_record.rb +2 -0
  14. data/app/models/good_job/discrete_execution.rb +1 -0
  15. data/app/models/good_job/job.rb +2 -2
  16. data/app/models/good_job/process.rb +2 -0
  17. data/app/models/good_job/setting.rb +2 -0
  18. data/app/views/good_job/_custom_head.html.erb +7 -0
  19. data/app/views/good_job/batches/_jobs.erb +4 -4
  20. data/app/views/good_job/batches/_table.erb +2 -2
  21. data/app/views/good_job/batches/show.html.erb +1 -1
  22. data/app/views/good_job/cron_entries/index.html.erb +2 -2
  23. data/app/views/good_job/jobs/_table.erb +12 -9
  24. data/app/views/good_job/jobs/show.html.erb +4 -4
  25. data/app/views/good_job/pauses/_group.html.erb +1 -1
  26. data/app/views/good_job/pauses/_pause.html.erb +1 -1
  27. data/app/views/good_job/shared/_filter.erb +4 -14
  28. data/app/views/good_job/shared/_navbar.erb +6 -6
  29. data/app/views/layouts/good_job/application.html.erb +12 -8
  30. data/config/brakeman.ignore +25 -25
  31. data/config/locales/de.yml +21 -21
  32. data/config/locales/zh-CN.yml +295 -0
  33. data/lib/generators/good_job/templates/install/migrations/create_good_jobs.rb.erb +1 -1
  34. data/lib/generators/good_job/templates/update/migrations/05_add_index_good_jobs_finished_at_for_cleanup.rb.erb +17 -0
  35. data/lib/generators/good_job/templates/update/migrations/06_remove_extraneous_finished_at_index.rb.erb +17 -0
  36. data/lib/good_job/active_job_extensions/labels.rb +1 -0
  37. data/lib/good_job/active_job_extensions/notify_options.rb +1 -0
  38. data/lib/good_job/notifier.rb +1 -0
  39. data/lib/good_job/version.rb +1 -1
  40. data/lib/good_job.rb +1 -1
  41. metadata +13 -9
  42. data/app/frontend/good_job/modules/document_ready.js +0 -7
  43. data/app/frontend/good_job/vendor/rails_ujs.js +0 -7
@@ -0,0 +1,295 @@
1
+ ---
2
+ zh-CN:
3
+ good_job:
4
+ actions:
5
+ destroy: 删除
6
+ discard: 丢弃
7
+ force_discard: 强制丢弃
8
+ inspect: 检查
9
+ reschedule: 重新调度
10
+ retry: 重试
11
+ batches:
12
+ actions:
13
+ confirm_retry: 您确定要重试此批处理吗?
14
+ retry: 重试
15
+ index:
16
+ older_batches: 更早的批处理
17
+ title: 批处理
18
+ jobs:
19
+ actions:
20
+ confirm_destroy: 您确定要删除此任务吗?
21
+ confirm_discard: 您确定要丢弃此任务吗?
22
+ confirm_reschedule: 您确定要重新调度此任务吗?
23
+ confirm_retry: 您确定要重试此任务吗?
24
+ destroy: 删除任务
25
+ discard: 丢弃任务
26
+ reschedule: 重新调度任务
27
+ retry: 重试任务
28
+ title: 操作
29
+ no_jobs_found: 未找到任务
30
+ retry:
31
+ notice: 批处理已重试
32
+ show:
33
+ attributes: 属性
34
+ batched_jobs: 批量任务
35
+ callback_jobs: 回调任务
36
+ table:
37
+ no_batches_found: 未找到批处理
38
+ cleaner:
39
+ index:
40
+ all: 全部
41
+ class: Class
42
+ exception: 异常
43
+ grouped_by_class: 按 Class 分组的丢弃任务
44
+ grouped_by_exception: 按异常分组的丢弃任务
45
+ last_1_hour: 最近 1 小时
46
+ last_24_hours: 最近 24 小时
47
+ last_3_days: 最近 3 天
48
+ last_3_hours: 最近 3 小时
49
+ last_7_days: 最近 7 天
50
+ title: 丢弃任务清理器
51
+ total: 总计
52
+ cron_entries:
53
+ actions:
54
+ confirm_disable: 您确定要禁用此定时任务吗?
55
+ confirm_enable: 您确定要启用此定时任务吗?
56
+ confirm_enqueue: 您确定要立即入队此定时任务吗?
57
+ disable: 禁用定时任务
58
+ enable: 启用定时任务
59
+ enqueue: 立即入队定时任务
60
+ disable:
61
+ notice: 定时任务已禁用
62
+ enable:
63
+ notice: 定时任务已启用
64
+ enqueue:
65
+ notice: 定时任务已入队
66
+ index:
67
+ no_cron_schedules_found: 未找到定时任务
68
+ title: 定时任务
69
+ show:
70
+ cron_entry_key: 定时任务 Key
71
+ datetime:
72
+ distance_in_words:
73
+ about_x_hours:
74
+ one: 大约 1 小时
75
+ other: 大约 %{count} 小时
76
+ about_x_months:
77
+ one: 大约 1 个月
78
+ other: 大约 %{count} 个月
79
+ about_x_years:
80
+ one: 大约 1 年
81
+ other: 大约 %{count} 年
82
+ almost_x_years:
83
+ one: 接近 1 年
84
+ other: 接近 %{count} 年
85
+ half_a_minute: 半分钟
86
+ less_than_x_minutes:
87
+ one: 少于 1 分钟
88
+ other: 少于 %{count} 分钟
89
+ less_than_x_seconds:
90
+ one: 少于 1 秒
91
+ other: 少于 %{count} 秒
92
+ over_x_years:
93
+ one: 超过 1 年
94
+ other: 超过 %{count} 年
95
+ x_days:
96
+ one: 1 天
97
+ other: "%{count} 天"
98
+ x_minutes:
99
+ one: 1 分钟
100
+ other: "%{count} 分钟"
101
+ x_months:
102
+ one: 1 个月
103
+ other: "%{count} 个月"
104
+ x_seconds:
105
+ one: 1 秒
106
+ other: "%{count} 秒"
107
+ x_years:
108
+ one: 1 年
109
+ other: "%{count} 年"
110
+ duration:
111
+ hours: "%{hour} 小时 %{min} 分"
112
+ less_than_10_seconds: "%{sec} 秒"
113
+ milliseconds: "%{ms} 毫秒"
114
+ minutes: "%{min} 分 %{sec} 秒"
115
+ seconds: "%{sec} 秒"
116
+ error_event:
117
+ discarded: 已丢弃
118
+ handled: 已处理
119
+ interrupted: 已中断
120
+ retried: 已重试
121
+ retry_stopped: 停止重试
122
+ unhandled: 未处理
123
+ helpers:
124
+ relative_time:
125
+ future: "%{time} 后"
126
+ past: "%{time} 前"
127
+ jobs:
128
+ actions:
129
+ confirm_destroy: 您确定要删除此任务吗?
130
+ confirm_discard: 您确定要丢弃此任务吗?
131
+ confirm_force_discard: 您确定要强制丢弃此任务吗?任务将被标记为丢弃,但正在运行的任务不会被停止 - 不过,失败时不会重试。
132
+ confirm_reschedule: 您确定要重新调度此任务吗?
133
+ confirm_retry: 您确定要重试此任务吗?
134
+ destroy: 删除任务
135
+ discard: 丢弃任务
136
+ force_discard: 强制丢弃任务
137
+ reschedule: 重新调度任务
138
+ retry: 重试任务
139
+ destroy:
140
+ notice: 任务已删除
141
+ discard:
142
+ notice: 任务已丢弃
143
+ executions:
144
+ application_trace: 应用跟踪
145
+ full_trace: 完整跟踪
146
+ in_queue: 队列中
147
+ runtime: 运行时间
148
+ title: 执行情况
149
+ force_discard:
150
+ notice: 任务已强制丢弃。它将继续运行但失败时不会重试
151
+ index:
152
+ job_pagination: 任务分页
153
+ older_jobs: 更早的任务
154
+ reschedule:
155
+ notice: 任务已重新调度
156
+ retry:
157
+ notice: 任务已重试
158
+ show:
159
+ jobs: 任务
160
+ table:
161
+ actions:
162
+ apply_to_all:
163
+ one: 应用于所有 1 个任务。
164
+ other: 应用于所有 %{count} 个任务。
165
+ confirm_destroy_all: 您确定要删除所选任务吗?
166
+ confirm_discard_all: 您确定要丢弃所选任务吗?
167
+ confirm_reschedule_all: 您确定要重新调度所选任务吗?
168
+ confirm_retry_all: 您确定要重试所选任务吗?
169
+ destroy_all: 全部删除
170
+ discard_all: 全部丢弃
171
+ reschedule_all: 全部重新调度
172
+ retry_all: 全部重试
173
+ title: 操作
174
+ no_jobs_found: 未找到任务
175
+ toggle_actions: 切换操作
176
+ toggle_all_jobs: 切换所有任务
177
+ models:
178
+ batch:
179
+ created: 已创建
180
+ created_at: 创建时间
181
+ discarded: 已丢弃
182
+ discarded_at: 丢弃时间
183
+ enqueued: 已入队
184
+ enqueued_at: 入队时间
185
+ finished: 已完成
186
+ finished_at: 完成时间
187
+ jobs: 任务
188
+ name: 名称
189
+ cron:
190
+ class: Class
191
+ last_run: 上次运行
192
+ next_scheduled: 下次计划
193
+ schedule: 计划
194
+ states:
195
+ active: 活跃
196
+ paused: 暂停
197
+ status: 状态
198
+ job:
199
+ arguments: 参数
200
+ attempts: 尝试次数
201
+ labels: 标签
202
+ priority: 优先级
203
+ queue: 队列
204
+ number:
205
+ format:
206
+ delimiter: ","
207
+ separator: "."
208
+ human:
209
+ decimal_units:
210
+ delimiter: ","
211
+ format: "%n%u"
212
+ precision: 3
213
+ separator: "."
214
+ units:
215
+ billion: 十亿
216
+ million: 百万
217
+ quadrillion: 千万亿
218
+ thousand: 千
219
+ trillion: 万亿
220
+ unit: ''
221
+ pauses:
222
+ index:
223
+ confirm_pause: 您确定要暂停%{value}吗?
224
+ confirm_unpause: 您确定要恢复%{value}吗?
225
+ disabled: 因会降低性能的可能性 GoodJob 实验性的暂停功能默认禁用,启用需要配置
226
+ job_class: 任务 Class
227
+ label: 标签
228
+ pause: 暂停
229
+ queue: 队列
230
+ title: 暂停
231
+ type: 暂停类型
232
+ unpause: 恢复
233
+ value: 值
234
+ performance:
235
+ index:
236
+ average_duration: 平均时长
237
+ chart_title: 任务总执行时间(秒)
238
+ executions: 执行次数
239
+ job_class: 任务 Class
240
+ maximum_duration: 最大时长
241
+ minimum_duration: 最小时长
242
+ queue_name: 队列名称
243
+ title: 性能
244
+ show:
245
+ slow: 慢
246
+ title: 性能
247
+ processes:
248
+ index:
249
+ cron_enabled: 定时任务已启用
250
+ no_good_job_processes_found: 未找到 GoodJob 进程
251
+ process: 进程
252
+ schedulers: 调度器
253
+ started: 已启动
254
+ title: 进程
255
+ updated: 已更新
256
+ shared:
257
+ boolean:
258
+ 'false': 否
259
+ 'true': 是
260
+ error: 错误
261
+ filter:
262
+ all: 全部
263
+ all_jobs: 所有任务
264
+ all_queues: 所有队列
265
+ clear: 清除
266
+ job_name: 任务名称
267
+ placeholder: 按类、任务 ID、任务参数和错误文本搜索。
268
+ queue_name: 队列名称
269
+ search: 搜索
270
+ navbar:
271
+ batches: 批处理
272
+ cleaner: 丢弃清理器
273
+ cron_schedules: 定时任务
274
+ jobs: 任务
275
+ live_poll: 实时轮询
276
+ name: "GoodJob 👍"
277
+ pauses: 暂停
278
+ performance: 性能
279
+ processes: 进程
280
+ theme:
281
+ auto: 自动
282
+ dark: 深色
283
+ light: 浅色
284
+ theme: 主题
285
+ pending_migrations: GoodJob 有待处理的数据库迁移
286
+ secondary_navbar:
287
+ inspiration: 记住,你也在做一份 Good Job!
288
+ last_updated: 最后更新
289
+ status:
290
+ discarded: 已丢弃
291
+ queued: 已入队
292
+ retried: 已重试
293
+ running: 运行中
294
+ scheduled: 已计划
295
+ succeeded: 已成功
@@ -85,7 +85,7 @@ class CreateGoodJobs < ActiveRecord::Migration<%= migration_version %>
85
85
  add_index :good_jobs, [:concurrency_key, :created_at], name: :index_good_jobs_on_concurrency_key_and_created_at
86
86
  add_index :good_jobs, [:cron_key, :created_at], where: "(cron_key IS NOT NULL)", name: :index_good_jobs_on_cron_key_and_created_at_cond
87
87
  add_index :good_jobs, [:cron_key, :cron_at], where: "(cron_key IS NOT NULL)", unique: true, name: :index_good_jobs_on_cron_key_and_cron_at_cond
88
- add_index :good_jobs, [:finished_at], where: "retried_good_job_id IS NULL AND finished_at IS NOT NULL", name: :index_good_jobs_jobs_on_finished_at
88
+ add_index :good_jobs, [:finished_at], where: "finished_at IS NOT NULL", name: :index_good_jobs_jobs_on_finished_at_only
89
89
  add_index :good_jobs, [:priority, :created_at], order: { priority: "DESC NULLS LAST", created_at: :asc },
90
90
  where: "finished_at IS NULL", name: :index_good_jobs_jobs_on_priority_created_at_when_unfinished
91
91
  add_index :good_jobs, [:priority, :created_at], order: { priority: "ASC NULLS LAST", created_at: :asc },
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ class AddIndexGoodJobsFinishedAtForCleanup < ActiveRecord::Migration<%= migration_version %>
4
+ disable_ddl_transaction!
5
+
6
+ def change
7
+ reversible do |dir|
8
+ dir.up do
9
+ # Ensure this incremental update migration is idempotent
10
+ # with monolithic install migration.
11
+ return if connection.index_exists? :good_jobs, [:finished_at], name: :index_good_jobs_jobs_on_finished_at_only
12
+ end
13
+ end
14
+
15
+ add_index :good_jobs, [:finished_at], where: "finished_at IS NOT NULL", name: :index_good_jobs_jobs_on_finished_at_only, algorithm: :concurrently
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ class RemoveExtraneousFinishedAtIndex < ActiveRecord::Migration<%= migration_version %>
4
+ disable_ddl_transaction!
5
+
6
+ def change
7
+ reversible do |dir|
8
+ dir.up do
9
+ # Ensure this incremental update migration is idempotent
10
+ # with monolithic install migration.
11
+ return unless connection.index_exists? :good_jobs, [:finished_at], name: :index_good_jobs_jobs_on_finished_at
12
+ end
13
+ end
14
+
15
+ remove_index :good_jobs, [:finished_at], where: "retried_good_job_id IS NULL AND finished_at IS NOT NULL", name: :index_good_jobs_jobs_on_finished_at, algorithm: :concurrently
16
+ end
17
+ end
@@ -24,6 +24,7 @@ module GoodJob
24
24
 
25
25
  included do
26
26
  prepend Prepends
27
+
27
28
  class_attribute :good_job_labels, instance_accessor: false, instance_predicate: false, default: []
28
29
  attr_accessor :good_job_labels
29
30
  end
@@ -40,6 +40,7 @@ module GoodJob
40
40
 
41
41
  included do
42
42
  prepend Prepends
43
+
43
44
  class_attribute :good_job_notify, instance_accessor: false, instance_predicate: false, default: nil
44
45
  attr_accessor :good_job_notify
45
46
  end
@@ -15,6 +15,7 @@ module GoodJob # :nodoc:
15
15
  #
16
16
  class Notifier
17
17
  include ActiveSupport::Callbacks
18
+
18
19
  define_callbacks :listen, :tick, :unlisten
19
20
 
20
21
  include ProcessHeartbeat
@@ -2,7 +2,7 @@
2
2
 
3
3
  module GoodJob
4
4
  # GoodJob gem version.
5
- VERSION = '4.12.1'
5
+ VERSION = '4.13.1'
6
6
 
7
7
  # GoodJob version as Gem::Version object
8
8
  GEM_VERSION = Gem::Version.new(VERSION)
data/lib/good_job.rb CHANGED
@@ -290,7 +290,7 @@ module GoodJob
290
290
  # For use in tests/CI to validate GoodJob is up-to-date.
291
291
  # @return [Boolean]
292
292
  def self.migrated?
293
- GoodJob::Job.job_class_index_migrated?
293
+ GoodJob::Job.historic_finished_at_index_migrated?
294
294
  end
295
295
 
296
296
  # Pause job execution for a given queue or job class.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: good_job
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.12.1
4
+ version: 4.13.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Sheldon
@@ -108,7 +108,7 @@ dependencies:
108
108
  - !ruby/object:Gem::Version
109
109
  version: '0'
110
110
  - !ruby/object:Gem::Dependency
111
- name: kramdown
111
+ name: cuprite
112
112
  requirement: !ruby/object:Gem::Requirement
113
113
  requirements:
114
114
  - - ">="
@@ -122,7 +122,7 @@ dependencies:
122
122
  - !ruby/object:Gem::Version
123
123
  version: '0'
124
124
  - !ruby/object:Gem::Dependency
125
- name: kramdown-parser-gfm
125
+ name: kramdown
126
126
  requirement: !ruby/object:Gem::Requirement
127
127
  requirements:
128
128
  - - ">="
@@ -136,7 +136,7 @@ dependencies:
136
136
  - !ruby/object:Gem::Version
137
137
  version: '0'
138
138
  - !ruby/object:Gem::Dependency
139
- name: puma
139
+ name: kramdown-parser-gfm
140
140
  requirement: !ruby/object:Gem::Requirement
141
141
  requirements:
142
142
  - - ">="
@@ -150,7 +150,7 @@ dependencies:
150
150
  - !ruby/object:Gem::Version
151
151
  version: '0'
152
152
  - !ruby/object:Gem::Dependency
153
- name: rspec-rails
153
+ name: puma
154
154
  requirement: !ruby/object:Gem::Requirement
155
155
  requirements:
156
156
  - - ">="
@@ -164,7 +164,7 @@ dependencies:
164
164
  - !ruby/object:Gem::Version
165
165
  version: '0'
166
166
  - !ruby/object:Gem::Dependency
167
- name: selenium-webdriver
167
+ name: rspec-rails
168
168
  requirement: !ruby/object:Gem::Requirement
169
169
  requirements:
170
170
  - - ">="
@@ -269,7 +269,7 @@ files:
269
269
  - app/frontend/good_job/modules/async_values_controller.js
270
270
  - app/frontend/good_job/modules/charts.js
271
271
  - app/frontend/good_job/modules/checkbox_toggle.js
272
- - app/frontend/good_job/modules/document_ready.js
272
+ - app/frontend/good_job/modules/form_controller.js
273
273
  - app/frontend/good_job/modules/html_legend_plugin.js
274
274
  - app/frontend/good_job/modules/live_poll.js
275
275
  - app/frontend/good_job/modules/popovers.js
@@ -280,8 +280,8 @@ files:
280
280
  - app/frontend/good_job/vendor/bootstrap/bootstrap.min.css
281
281
  - app/frontend/good_job/vendor/chartjs/chart.min.js
282
282
  - app/frontend/good_job/vendor/es_module_shims.js
283
- - app/frontend/good_job/vendor/rails_ujs.js
284
283
  - app/frontend/good_job/vendor/stimulus.js
284
+ - app/frontend/good_job/vendor/turbo.js
285
285
  - app/helpers/good_job/application_helper.rb
286
286
  - app/helpers/good_job/icons_helper.rb
287
287
  - app/models/concerns/good_job/advisory_lockable.rb
@@ -301,6 +301,7 @@ files:
301
301
  - app/models/good_job/process.rb
302
302
  - app/models/good_job/setting.rb
303
303
  - app/views/good_job/_custom_execution_details.html.erb
304
+ - app/views/good_job/_custom_head.html.erb
304
305
  - app/views/good_job/_custom_job_details.html.erb
305
306
  - app/views/good_job/batches/_jobs.erb
306
307
  - app/views/good_job/batches/_table.erb
@@ -341,6 +342,7 @@ files:
341
342
  - config/locales/ru.yml
342
343
  - config/locales/tr.yml
343
344
  - config/locales/uk.yml
345
+ - config/locales/zh-CN.yml
344
346
  - config/routes.rb
345
347
  - exe/good_job
346
348
  - lib/active_job/queue_adapters/good_job_adapter.rb
@@ -350,6 +352,8 @@ files:
350
352
  - lib/generators/good_job/templates/update/migrations/02_add_jobs_finished_at_to_good_job_batches.rb.erb
351
353
  - lib/generators/good_job/templates/update/migrations/03_add_index_good_jobs_concurrency_key_created_at.rb.erb
352
354
  - lib/generators/good_job/templates/update/migrations/04_add_index_good_jobs_job_class.rb.erb
355
+ - lib/generators/good_job/templates/update/migrations/05_add_index_good_jobs_finished_at_for_cleanup.rb.erb
356
+ - lib/generators/good_job/templates/update/migrations/06_remove_extraneous_finished_at_index.rb.erb
353
357
  - lib/generators/good_job/update_generator.rb
354
358
  - lib/good_job.rb
355
359
  - lib/good_job/active_job_extensions/batches.rb
@@ -422,7 +426,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
422
426
  - !ruby/object:Gem::Version
423
427
  version: '0'
424
428
  requirements: []
425
- rubygems_version: 3.7.2
429
+ rubygems_version: 3.6.9
426
430
  specification_version: 4
427
431
  summary: A multithreaded, Postgres-based ActiveJob backend for Ruby on Rails
428
432
  test_files: []
@@ -1,7 +0,0 @@
1
- export default function documentReady(callback) {
2
- if (document.readyState !== "loading") {
3
- callback();
4
- } else {
5
- document.addEventListener("DOMContentLoaded", callback);
6
- }
7
- }
@@ -1,7 +0,0 @@
1
- /**
2
- * Minified by jsDelivr using Terser v5.15.1.
3
- * Original file: /npm/@rails/ujs@7.0.4-2/lib/assets/compiled/rails-ujs.js
4
- *
5
- * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files
6
- */
7
- (function(){(function(){(function(){this.Rails={linkClickSelector:"a[data-confirm], a[data-method], a[data-remote]:not([disabled]), a[data-disable-with], a[data-disable]",buttonClickSelector:{selector:"button[data-remote]:not([form]), button[data-confirm]:not([form])",exclude:"form button"},inputChangeSelector:"select[data-remote], input[data-remote], textarea[data-remote]",formSubmitSelector:"form:not([data-turbo=true])",formInputClickSelector:"form:not([data-turbo=true]) input[type=submit], form:not([data-turbo=true]) input[type=image], form:not([data-turbo=true]) button[type=submit], form:not([data-turbo=true]) button:not([type]), input[type=submit][form], input[type=image][form], button[type=submit][form], button[form]:not([type])",formDisableSelector:"input[data-disable-with]:enabled, button[data-disable-with]:enabled, textarea[data-disable-with]:enabled, input[data-disable]:enabled, button[data-disable]:enabled, textarea[data-disable]:enabled",formEnableSelector:"input[data-disable-with]:disabled, button[data-disable-with]:disabled, textarea[data-disable-with]:disabled, input[data-disable]:disabled, button[data-disable]:disabled, textarea[data-disable]:disabled",fileInputSelector:"input[name][type=file]:not([disabled])",linkDisableSelector:"a[data-disable-with], a[data-disable]",buttonDisableSelector:"button[data-remote][data-disable-with], button[data-remote][data-disable]"}}).call(this)}).call(this);var t=this.Rails;(function(){(function(){var e;e=null,t.loadCSPNonce=function(){var t;return e=null!=(t=document.querySelector("meta[name=csp-nonce]"))?t.content:void 0},t.cspNonce=function(){return null!=e?e:t.loadCSPNonce()}}).call(this),function(){var e;e=Element.prototype.matches||Element.prototype.matchesSelector||Element.prototype.mozMatchesSelector||Element.prototype.msMatchesSelector||Element.prototype.oMatchesSelector||Element.prototype.webkitMatchesSelector,t.matches=function(t,n){return null!=n.exclude?e.call(t,n.selector)&&!e.call(t,n.exclude):e.call(t,n)},t.getData=function(t,e){var n;return null!=(n=t._ujsData)?n[e]:void 0},t.setData=function(t,e,n){return null==t._ujsData&&(t._ujsData={}),t._ujsData[e]=n},t.$=function(t){return Array.prototype.slice.call(document.querySelectorAll(t))}}.call(this),function(){var e,n,a;e=t.$,a=t.csrfToken=function(){var t;return(t=document.querySelector("meta[name=csrf-token]"))&&t.content},n=t.csrfParam=function(){var t;return(t=document.querySelector("meta[name=csrf-param]"))&&t.content},t.CSRFProtection=function(t){var e;if(null!=(e=a()))return t.setRequestHeader("X-CSRF-Token",e)},t.refreshCSRFTokens=function(){var t,r;if(r=a(),t=n(),null!=r&&null!=t)return e('form input[name="'+t+'"]').forEach((function(t){return t.value=r}))}}.call(this),function(){var e,n,a,r;a=t.matches,"function"!=typeof(e=window.CustomEvent)&&((e=function(t,e){var n;return(n=document.createEvent("CustomEvent")).initCustomEvent(t,e.bubbles,e.cancelable,e.detail),n}).prototype=window.Event.prototype,r=e.prototype.preventDefault,e.prototype.preventDefault=function(){var t;return t=r.call(this),this.cancelable&&!this.defaultPrevented&&Object.defineProperty(this,"defaultPrevented",{get:function(){return!0}}),t}),n=t.fire=function(t,n,a){var r;return r=new e(n,{bubbles:!0,cancelable:!0,detail:a}),t.dispatchEvent(r),!r.defaultPrevented},t.stopEverything=function(t){return n(t.target,"ujs:everythingStopped"),t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation()},t.delegate=function(t,e,n,r){return t.addEventListener(n,(function(t){var n;for(n=t.target;n instanceof Element&&!a(n,e);)n=n.parentNode;if(n instanceof Element&&!1===r.call(n,t))return t.preventDefault(),t.stopPropagation()}))}}.call(this),function(){var e,n,a,r,o,i;r=t.cspNonce,n=t.CSRFProtection,t.fire,e={"*":"*/*",text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript",script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},t.ajax=function(t){var e;return t=o(t),e=a(t,(function(){var n,a;return a=i(null!=(n=e.response)?n:e.responseText,e.getResponseHeader("Content-Type")),2===Math.floor(e.status/100)?"function"==typeof t.success&&t.success(a,e.statusText,e):"function"==typeof t.error&&t.error(a,e.statusText,e),"function"==typeof t.complete?t.complete(e,e.statusText):void 0})),!(null!=t.beforeSend&&!t.beforeSend(e,t))&&(e.readyState===XMLHttpRequest.OPENED?e.send(t.data):void 0)},o=function(t){return t.url=t.url||location.href,t.type=t.type.toUpperCase(),"GET"===t.type&&t.data&&(t.url.indexOf("?")<0?t.url+="?"+t.data:t.url+="&"+t.data),null==e[t.dataType]&&(t.dataType="*"),t.accept=e[t.dataType],"*"!==t.dataType&&(t.accept+=", */*; q=0.01"),t},a=function(t,e){var a;return(a=new XMLHttpRequest).open(t.type,t.url,!0),a.setRequestHeader("Accept",t.accept),"string"==typeof t.data&&a.setRequestHeader("Content-Type","application/x-www-form-urlencoded; charset=UTF-8"),t.crossDomain||(a.setRequestHeader("X-Requested-With","XMLHttpRequest"),n(a)),a.withCredentials=!!t.withCredentials,a.onreadystatechange=function(){if(a.readyState===XMLHttpRequest.DONE)return e(a)},a},i=function(t,e){var n,a;if("string"==typeof t&&"string"==typeof e)if(e.match(/\bjson\b/))try{t=JSON.parse(t)}catch(t){}else if(e.match(/\b(?:java|ecma)script\b/))(a=document.createElement("script")).setAttribute("nonce",r()),a.text=t,document.head.appendChild(a).parentNode.removeChild(a);else if(e.match(/\b(xml|html|svg)\b/)){n=new DOMParser,e=e.replace(/;.+/,"");try{t=n.parseFromString(t,e)}catch(t){}}return t},t.href=function(t){return t.href},t.isCrossDomain=function(t){var e,n;(e=document.createElement("a")).href=location.href,n=document.createElement("a");try{return n.href=t,!((!n.protocol||":"===n.protocol)&&!n.host||e.protocol+"//"+e.host==n.protocol+"//"+n.host)}catch(t){return t,!0}}}.call(this),function(){var e,n;e=t.matches,n=function(t){return Array.prototype.slice.call(t)},t.serializeElement=function(t,a){var r,o;return r=[t],e(t,"form")&&(r=n(t.elements)),o=[],r.forEach((function(t){if(t.name&&!t.disabled&&!e(t,"fieldset[disabled] *"))return e(t,"select")?n(t.options).forEach((function(e){if(e.selected)return o.push({name:t.name,value:e.value})})):t.checked||-1===["radio","checkbox","submit"].indexOf(t.type)?o.push({name:t.name,value:t.value}):void 0})),a&&o.push(a),o.map((function(t){return null!=t.name?encodeURIComponent(t.name)+"="+encodeURIComponent(t.value):t})).join("&")},t.formElements=function(t,a){return e(t,"form")?n(t.elements).filter((function(t){return e(t,a)})):n(t.querySelectorAll(a))}}.call(this),function(){var e,n,a;n=t.fire,a=t.stopEverything,t.handleConfirm=function(t){if(!e(this))return a(t)},t.confirm=function(t,e){return confirm(t)},e=function(e){var a,r,o;if(!(o=e.getAttribute("data-confirm")))return!0;if(a=!1,n(e,"confirm")){try{a=t.confirm(o,e)}catch(t){}r=n(e,"confirm:complete",[a])}return a&&r}}.call(this),function(){var e,n,a,r,o,i,l,u,c,s,d,m;s=t.matches,u=t.getData,d=t.setData,m=t.stopEverything,l=t.formElements,t.handleDisabledElement=function(t){if(this,this.disabled)return m(t)},t.enableElement=function(e){var n;if(e instanceof Event){if(c(e))return;n=e.target}else n=e;return s(n,t.linkDisableSelector)?i(n):s(n,t.buttonDisableSelector)||s(n,t.formEnableSelector)?r(n):s(n,t.formSubmitSelector)?o(n):void 0},t.disableElement=function(r){var o;return o=r instanceof Event?r.target:r,s(o,t.linkDisableSelector)?a(o):s(o,t.buttonDisableSelector)||s(o,t.formDisableSelector)?e(o):s(o,t.formSubmitSelector)?n(o):void 0},a=function(t){var e;if(!u(t,"ujs:disabled"))return null!=(e=t.getAttribute("data-disable-with"))&&(d(t,"ujs:enable-with",t.innerHTML),t.innerHTML=e),t.addEventListener("click",m),d(t,"ujs:disabled",!0)},i=function(t){var e;return null!=(e=u(t,"ujs:enable-with"))&&(t.innerHTML=e,d(t,"ujs:enable-with",null)),t.removeEventListener("click",m),d(t,"ujs:disabled",null)},n=function(n){return l(n,t.formDisableSelector).forEach(e)},e=function(t){var e;if(!u(t,"ujs:disabled"))return null!=(e=t.getAttribute("data-disable-with"))&&(s(t,"button")?(d(t,"ujs:enable-with",t.innerHTML),t.innerHTML=e):(d(t,"ujs:enable-with",t.value),t.value=e)),t.disabled=!0,d(t,"ujs:disabled",!0)},o=function(e){return l(e,t.formEnableSelector).forEach(r)},r=function(t){var e;return null!=(e=u(t,"ujs:enable-with"))&&(s(t,"button")?t.innerHTML=e:t.value=e,d(t,"ujs:enable-with",null)),t.disabled=!1,d(t,"ujs:disabled",null)},c=function(t){var e,n;return null!=(null!=(n=null!=(e=t.detail)?e[0]:void 0)?n.getResponseHeader("X-Xhr-Redirect"):void 0)}}.call(this),function(){var e;e=t.stopEverything,t.handleMethod=function(n){var a,r,o,i,l,u,c;if(c=(u=this).getAttribute("data-method"))return l=t.href(u),r=t.csrfToken(),a=t.csrfParam(),o=document.createElement("form"),i="<input name='_method' value='"+c+"' type='hidden' />",null==a||null==r||t.isCrossDomain(l)||(i+="<input name='"+a+"' value='"+r+"' type='hidden' />"),i+='<input type="submit" />',o.method="post",o.action=l,o.target=u.target,o.innerHTML=i,o.style.display="none",document.body.appendChild(o),o.querySelector('[type="submit"]').click(),e(n)}}.call(this),function(){var e,n,a,r,o,i,l,u,c,s=[].slice;i=t.matches,a=t.getData,u=t.setData,n=t.fire,c=t.stopEverything,e=t.ajax,r=t.isCrossDomain,l=t.serializeElement,o=function(t){var e;return null!=(e=t.getAttribute("data-remote"))&&"false"!==e},t.handleRemote=function(d){var m,f,p,b,h,v,S;return!o(b=this)||(n(b,"ajax:before")?(S=b.getAttribute("data-with-credentials"),p=b.getAttribute("data-type")||"script",i(b,t.formSubmitSelector)?(m=a(b,"ujs:submit-button"),h=a(b,"ujs:submit-button-formmethod")||b.method,v=a(b,"ujs:submit-button-formaction")||b.getAttribute("action")||location.href,"GET"===h.toUpperCase()&&(v=v.replace(/\?.*$/,"")),"multipart/form-data"===b.enctype?(f=new FormData(b),null!=m&&f.append(m.name,m.value)):f=l(b,m),u(b,"ujs:submit-button",null),u(b,"ujs:submit-button-formmethod",null),u(b,"ujs:submit-button-formaction",null)):i(b,t.buttonClickSelector)||i(b,t.inputChangeSelector)?(h=b.getAttribute("data-method"),v=b.getAttribute("data-url"),f=l(b,b.getAttribute("data-params"))):(h=b.getAttribute("data-method"),v=t.href(b),f=b.getAttribute("data-params")),e({type:h||"GET",url:v,data:f,dataType:p,beforeSend:function(t,e){return n(b,"ajax:beforeSend",[t,e])?n(b,"ajax:send",[t]):(n(b,"ajax:stopped"),!1)},success:function(){var t;return t=1<=arguments.length?s.call(arguments,0):[],n(b,"ajax:success",t)},error:function(){var t;return t=1<=arguments.length?s.call(arguments,0):[],n(b,"ajax:error",t)},complete:function(){var t;return t=1<=arguments.length?s.call(arguments,0):[],n(b,"ajax:complete",t)},crossDomain:r(v),withCredentials:null!=S&&"false"!==S}),c(d)):(n(b,"ajax:stopped"),!1))},t.formSubmitButtonClick=function(t){var e,n;if(n=(e=this).form)return e.name&&u(n,"ujs:submit-button",{name:e.name,value:e.value}),u(n,"ujs:formnovalidate-button",e.formNoValidate),u(n,"ujs:submit-button-formaction",e.getAttribute("formaction")),u(n,"ujs:submit-button-formmethod",e.getAttribute("formmethod"))},t.preventInsignificantClick=function(t){var e,n,a;if(this,a=(this.getAttribute("data-method")||"GET").toUpperCase(),e=this.getAttribute("data-params"),n=(t.metaKey||t.ctrlKey)&&"GET"===a&&!e,null!=t.button&&0!==t.button||n)return t.stopImmediatePropagation()}}.call(this),function(){var e,n,a,r,o,i,l,u,c,s,d,m,f,p,b;if(i=t.fire,a=t.delegate,u=t.getData,e=t.$,b=t.refreshCSRFTokens,n=t.CSRFProtection,f=t.loadCSPNonce,o=t.enableElement,r=t.disableElement,s=t.handleDisabledElement,c=t.handleConfirm,p=t.preventInsignificantClick,m=t.handleRemote,l=t.formSubmitButtonClick,d=t.handleMethod,"undefined"!=typeof jQuery&&null!==jQuery&&null!=jQuery.ajax){if(jQuery.rails)throw new Error("If you load both jquery_ujs and rails-ujs, use rails-ujs only.");jQuery.rails=t,jQuery.ajaxPrefilter((function(t,e,a){if(!t.crossDomain)return n(a)}))}t.start=function(){if(window._rails_loaded)throw new Error("rails-ujs has already been loaded!");return window.addEventListener("pageshow",(function(){return e(t.formEnableSelector).forEach((function(t){if(u(t,"ujs:disabled"))return o(t)})),e(t.linkDisableSelector).forEach((function(t){if(u(t,"ujs:disabled"))return o(t)}))})),a(document,t.linkDisableSelector,"ajax:complete",o),a(document,t.linkDisableSelector,"ajax:stopped",o),a(document,t.buttonDisableSelector,"ajax:complete",o),a(document,t.buttonDisableSelector,"ajax:stopped",o),a(document,t.linkClickSelector,"click",p),a(document,t.linkClickSelector,"click",s),a(document,t.linkClickSelector,"click",c),a(document,t.linkClickSelector,"click",r),a(document,t.linkClickSelector,"click",m),a(document,t.linkClickSelector,"click",d),a(document,t.buttonClickSelector,"click",p),a(document,t.buttonClickSelector,"click",s),a(document,t.buttonClickSelector,"click",c),a(document,t.buttonClickSelector,"click",r),a(document,t.buttonClickSelector,"click",m),a(document,t.inputChangeSelector,"change",s),a(document,t.inputChangeSelector,"change",c),a(document,t.inputChangeSelector,"change",m),a(document,t.formSubmitSelector,"submit",s),a(document,t.formSubmitSelector,"submit",c),a(document,t.formSubmitSelector,"submit",m),a(document,t.formSubmitSelector,"submit",(function(t){return setTimeout((function(){return r(t)}),13)})),a(document,t.formSubmitSelector,"ajax:send",r),a(document,t.formSubmitSelector,"ajax:complete",o),a(document,t.formInputClickSelector,"click",p),a(document,t.formInputClickSelector,"click",s),a(document,t.formInputClickSelector,"click",c),a(document,t.formInputClickSelector,"click",l),document.addEventListener("DOMContentLoaded",b),document.addEventListener("DOMContentLoaded",f),window._rails_loaded=!0},window.Rails===t&&i(document,"rails:attachBindings")&&t.start()}.call(this)}).call(this),"object"==typeof module&&module.exports?module.exports=t:"function"==typeof define&&define.amd&&define(t)}).call(this);