marty 8.3.1 → 8.4.1

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: 6a089e78541222d60d9d84b7339c0fdefc8c87f445f0943a471732167e6946e2
4
- data.tar.gz: cde4b147a1f9d753327c09665df1aa2045f887c9a6d0cafd0236227ceff3c7f9
3
+ metadata.gz: 6d2b7a71540fdd0a796cc8bd62725ddfa80231af28875eff79b5cbf1e6b8d65a
4
+ data.tar.gz: de508c108b52dc8b89d9d873030173594952a5c48ee507c68438f2e01a21d136
5
5
  SHA512:
6
- metadata.gz: 42d06eccfc9294f7151ab41f12e6a8970c0c086fe8d6cf492c3520d82ed2c9694bc9f231f8fb6e3d6bb4f8f9c251085145a2c7f5d2d04884bc071a68b64dc4ee
7
- data.tar.gz: 32f0ce4bd5c4425ab855e4d606b50d117be8609c4cf23ba0968b2ced644fcdc29ca1f5ad7b8b345b6b6bf42a0cee374c973ec8d6ac191ab7c37623c6c729b2be
6
+ metadata.gz: efbcc2b834193e2525809e494d6e12936d75606b03f7c2fb9970008eb3adac30bb4a193c9bd64323691db0fdd983401aba0e73907df16f839bfb4675551094af
7
+ data.tar.gz: 1c2834966a5b98f4177a14a297eed967b88a94b7f56c6c3597445e6dcd25ab96cad08465bcbf31f4675a76cc2d977f0a198efae2b15f47e64f771159ae2dfdf6
@@ -0,0 +1,71 @@
1
+ module Marty
2
+ module BackgroundJob
3
+ class DelayedJobsGrid < Marty::Grid
4
+ ACCESSIBLE_BY = [:admin]
5
+
6
+ has_marty_permissions(
7
+ read: ACCESSIBLE_BY,
8
+ create: nil,
9
+ update: nil,
10
+ delete: nil,
11
+ destroy: ACCESSIBLE_BY,
12
+ job_run: ACCESSIBLE_BY,
13
+ edit_window__edit_form__submit: ACCESSIBLE_BY,
14
+ add_window__add_form__submit: ACCESSIBLE_BY
15
+ )
16
+
17
+ def configure(c)
18
+ super
19
+
20
+ c.title ||= I18n.t(
21
+ 'schedule_jobs_dashboard_view_title',
22
+ default: 'Delayed Jobs Dashboard'
23
+ )
24
+
25
+ c.model = 'Delayed::Job'
26
+ c.paging = :buffered
27
+ c.editing = :in_form
28
+ c.multi_select = false
29
+
30
+ c.attributes = [
31
+ :id,
32
+ :handler,
33
+ :run_at,
34
+ :locked_at,
35
+ :locked_by,
36
+ :created_at,
37
+ :cron,
38
+ :last_error
39
+ ]
40
+
41
+ c.store_config.merge!(
42
+ sorters: [
43
+ { property: :locked_at, direction: 'DESC' },
44
+ { property: :run_at, direction: 'DESC' }
45
+ ])
46
+
47
+ # c.scope = lambda do |r|
48
+ # r.order('locked_at DESC NULLS LAST')
49
+ # end
50
+ end
51
+
52
+ attribute :locked_at do |c|
53
+ c.sorting_scope = lambda do |relation, dir|
54
+ relation.order("locked_at #{dir} NULLS LAST")
55
+ end
56
+ end
57
+
58
+ def default_context_menu
59
+ []
60
+ end
61
+
62
+ def default_bbar
63
+ []
64
+ end
65
+
66
+ attribute :cron do |c|
67
+ c.width = 400
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,53 @@
1
+ require 'marty/background_job/schedule_jobs_grid'
2
+
3
+ module Marty
4
+ module BackgroundJob
5
+ class ScheduleJobsDashboard < Marty::Form
6
+ include Marty::Extras::Layout
7
+
8
+ def configure(c)
9
+ super
10
+ c.items = [
11
+ :schedule_jobs_grid,
12
+ :schedule_jobs_warnings
13
+ ]
14
+ end
15
+
16
+ def prepare_warnings
17
+ djs = ::Marty::BackgroundJob::FetchMissingInScheduleCronJobs.call
18
+
19
+ messages = djs.map do |dj|
20
+ handler_str = dj.handler[/job_class.*\n/]
21
+ job_class = handler_str.gsub('job_class:', '').strip
22
+
23
+ "#{job_class} with cron #{dj.cron} is present " \
24
+ 'in delayed_jobs table, but is missing in the Dashboard.'
25
+ end
26
+
27
+ messages.join('<br>')
28
+ end
29
+
30
+ client_class do |c|
31
+ c.header = false
32
+ c.defaults = { body_style: 'padding:0px' }
33
+ end
34
+
35
+ component :schedule_jobs_grid do |c|
36
+ c.klass = Marty::BackgroundJob::ScheduleJobsGrid
37
+ c.region = :north
38
+ c.min_height = 500
39
+ end
40
+
41
+ component :schedule_jobs_warnings do |c|
42
+ c.klass = Marty::Panel
43
+ c.title = I18n.t('jobs.schedule_dashboard.warnings')
44
+ c.html = prepare_warnings
45
+ c.min_height = 200
46
+ end
47
+
48
+ def default_bbar
49
+ []
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,136 @@
1
+ module Marty
2
+ module BackgroundJob
3
+ class ScheduleJobsGrid < Marty::Grid
4
+ ACCESSIBLE_BY = [:admin]
5
+
6
+ has_marty_permissions(
7
+ read: ACCESSIBLE_BY,
8
+ create: ACCESSIBLE_BY,
9
+ update: ACCESSIBLE_BY,
10
+ delete: ACCESSIBLE_BY,
11
+ destroy: ACCESSIBLE_BY,
12
+ job_run: ACCESSIBLE_BY,
13
+ edit_window__edit_form__submit: ACCESSIBLE_BY,
14
+ add_window__add_form__submit: ACCESSIBLE_BY
15
+ )
16
+
17
+ def configure(c)
18
+ super
19
+
20
+ c.title ||= I18n.t(
21
+ 'schedule_jobs_dashboard_view_title',
22
+ default: 'Schedule Jobs Dashboard'
23
+ )
24
+
25
+ c.model = 'Marty::BackgroundJob::Schedule'
26
+ c.paging = :buffered
27
+ c.editing = :in_form
28
+ c.multi_select = false
29
+
30
+ c.attributes = [
31
+ :job_class,
32
+ :cron,
33
+ :state
34
+ ]
35
+ end
36
+
37
+ def default_context_menu
38
+ []
39
+ end
40
+
41
+ def default_bbar
42
+ super + [:do_job_run]
43
+ end
44
+
45
+ attribute :job_class do |c|
46
+ c.width = 400
47
+ end
48
+
49
+ attribute :cron do |c|
50
+ c.width = 400
51
+ end
52
+
53
+ attribute :state do |c|
54
+ c.width = 150
55
+ editor_config = {
56
+ trigger_action: :all,
57
+ xtype: :combo,
58
+ store: Marty::BackgroundJob::Schedule::ALL_STATES,
59
+ forceSelection: true,
60
+ }
61
+
62
+ c.column_config = { editor: editor_config }
63
+ c.field_config = editor_config
64
+ end
65
+
66
+ action :do_job_run do |a|
67
+ a.text = 'Run'
68
+ a.tooltip = 'Run'
69
+ a.icon_cls = 'fa fa-play glyph'
70
+ a.disabled = true
71
+ end
72
+
73
+ endpoint :edit_window__edit_form__submit do |params|
74
+ result = super(params)
75
+ next result if result.empty?
76
+
77
+ obj_hash = result.first
78
+
79
+ Marty::BackgroundJob::UpdateSchedule.call(
80
+ id: obj_hash['id'],
81
+ job_class: obj_hash['job_class']
82
+ )
83
+
84
+ result
85
+ end
86
+
87
+ endpoint :add_window__add_form__submit do |params|
88
+ result = super(params)
89
+ next result if result.empty?
90
+
91
+ obj_hash = result.first
92
+
93
+ Marty::BackgroundJob::UpdateSchedule.call(
94
+ id: obj_hash['id'],
95
+ job_class: obj_hash['job_class']
96
+ )
97
+
98
+ result
99
+ end
100
+
101
+ endpoint :multiedit_window__multiedit_form__submit do |_params|
102
+ client.netzke_notify 'Multiediting is disabled for cron schedules'
103
+ end
104
+
105
+ endpoint :destroy do |params|
106
+ res = params.each_with_object({}) do |id, hash|
107
+ job_class = model.find_by(id: id)&.job_class
108
+ result = super([id])
109
+
110
+ # Do nothing If it wasn't destroyed
111
+ next hash.merge(result) unless result[id.to_i] == 'ok'
112
+
113
+ Marty::BackgroundJob::UpdateSchedule.call(
114
+ id: id,
115
+ job_class: job_class
116
+ )
117
+
118
+ hash.merge(result)
119
+ end
120
+
121
+ res
122
+ end
123
+
124
+ endpoint :job_run do
125
+ begin
126
+ s = Marty::BackgroundJob::Schedule.find(client_config['selected'])
127
+ klass = s.job_class
128
+ klass.constantize.new.perform
129
+ rescue StandardError => e
130
+ next client.netzke_notify(e.message)
131
+ end
132
+ client.netzke_notify("#{klass.demodulize} ran successfully.")
133
+ end
134
+ end
135
+ end
136
+ end
@@ -0,0 +1,87 @@
1
+ module Marty
2
+ module BackgroundJob
3
+ class ScheduleJobsLogs < Marty::Grid
4
+ ACCESSIBLE_BY = [:admin]
5
+
6
+ has_marty_permissions(
7
+ read: ACCESSIBLE_BY,
8
+ create: ACCESSIBLE_BY,
9
+ update: ACCESSIBLE_BY,
10
+ delete: ACCESSIBLE_BY,
11
+ destroy: ACCESSIBLE_BY,
12
+ destroy_all: ACCESSIBLE_BY,
13
+ ignore: ACCESSIBLE_BY,
14
+ edit_window__edit_form__submit: ACCESSIBLE_BY,
15
+ add_window__add_form__submit: ACCESSIBLE_BY
16
+ )
17
+
18
+ def configure(c)
19
+ super
20
+
21
+ c.title ||= I18n.t('schedule_jobs_dashboard_view_title', default: "Scheduled Job's Logs")
22
+ c.model = 'Marty::BackgroundJob::Log'
23
+ c.paging = :buffered
24
+ c.editing = :in_form
25
+ c.multi_select = true
26
+
27
+ c.attributes = [
28
+ :job_class,
29
+ :status,
30
+ :error,
31
+ :created_at
32
+ ]
33
+
34
+ c.store_config.merge!(sorters: [{ property: :id, direction: 'DESC' }])
35
+ end
36
+
37
+ def default_context_menu
38
+ []
39
+ end
40
+
41
+ def default_bbar
42
+ [:delete, :destroy_all, :ignore]
43
+ end
44
+
45
+ attribute :job_class do |c|
46
+ c.width = 400
47
+ c.read_only = true
48
+ end
49
+
50
+ attribute :status do |c|
51
+ c.read_only = true
52
+ end
53
+
54
+ attribute :error do |c|
55
+ c.width = 800
56
+ c.read_only = true
57
+ c.getter = ->(record) { record.error.to_json }
58
+ end
59
+
60
+ action :destroy_all do |a|
61
+ a.text = 'Delete all'
62
+ a.tooltip = 'Delete all logs'
63
+ a.icon_cls = 'fa fa-trash glyph'
64
+ end
65
+
66
+ action :ignore do |a|
67
+ a.text = 'Ignore in diag'
68
+ a.tooltip = 'Ignore in diag'
69
+ a.icon_cls = 'fa fa-trash glyph'
70
+ end
71
+
72
+ endpoint :destroy_all do
73
+ Marty::BackgroundJob::Log.delete_all
74
+ client.reload
75
+ end
76
+
77
+ endpoint :ignore do |ids|
78
+ Marty::BackgroundJob::Log.
79
+ where(id: ids).
80
+ where(status: :failure).
81
+ each { |record| record.update(status: :failure_ignore) }
82
+
83
+ client.reload
84
+ end
85
+ end
86
+ end
87
+ end
@@ -1,20 +1,21 @@
1
1
  require 'marty/api_auth_view'
2
2
  require 'marty/api_config_view'
3
3
  require 'marty/api_log_view'
4
+ require 'marty/background_job/delayed_jobs_grid'
5
+ require 'marty/background_job/schedule_jobs_dashboard'
6
+ require 'marty/background_job/schedule_jobs_logs'
4
7
  require 'marty/config_view'
5
8
  require 'marty/data_grid_view'
6
- require 'marty/schedule_jobs_dashboard'
7
- require 'marty/schedule_jobs_logs'
8
9
  require 'marty/data_grid_user_view'
9
10
  require 'marty/import_type_view'
10
11
  require 'marty/new_posting_window'
12
+ require 'marty/notifications/config_view'
13
+ require 'marty/notifications/deliveries_view'
11
14
  require 'marty/posting_window'
12
15
  require 'marty/promise_view'
13
16
  require 'marty/reporting'
14
17
  require 'marty/scripting'
15
18
  require 'marty/user_view'
16
- require 'marty/notifications/config_view'
17
- require 'marty/notifications/deliveries_view'
18
19
 
19
20
  class Marty::MainAuthApp < Marty::AuthApp
20
21
  extend ::Marty::Permissions
@@ -116,6 +117,7 @@ class Marty::MainAuthApp < Marty::AuthApp
116
117
  :bg_status,
117
118
  :bg_stop,
118
119
  :bg_restart,
120
+ :delayed_jobs_grid,
119
121
  :schedule_jobs_dashboard,
120
122
  :schedule_jobs_logs,
121
123
  ]
@@ -298,6 +300,14 @@ class Marty::MainAuthApp < Marty::AuthApp
298
300
  a.disabled = !self.class.has_perm?(:admin)
299
301
  end
300
302
 
303
+ action :delayed_jobs_grid do |a|
304
+ a.text = 'Delayed Jobs Dashboard'
305
+ a.tooltip = 'Show running delayed jobs'
306
+ a.icon_cls = 'fa fa-clock glyph'
307
+ a.disabled = !self.class.has_perm?(:admin)
308
+ a.handler = :netzke_load_component_by_action
309
+ end
310
+
301
311
  action :schedule_jobs_dashboard do |a|
302
312
  a.text = 'Schedule Jobs Dashboard'
303
313
  a.tooltip = 'Edit Delayed Jobs Cron schedules'
@@ -438,9 +448,9 @@ class Marty::MainAuthApp < Marty::AuthApp
438
448
 
439
449
  component :api_config_view
440
450
 
441
- component :schedule_jobs_dashboard
442
-
443
- component :schedule_jobs_logs
451
+ component :delayed_jobs_grid do |c|
452
+ c.klass = ::Marty::BackgroundJob::DelayedJobsGrid
453
+ end
444
454
 
445
455
  component :config_view
446
456
 
@@ -472,6 +482,14 @@ class Marty::MainAuthApp < Marty::AuthApp
472
482
 
473
483
  component :reporting
474
484
 
485
+ component :schedule_jobs_dashboard do |c|
486
+ c.klass = ::Marty::BackgroundJob::ScheduleJobsDashboard
487
+ end
488
+
489
+ component :schedule_jobs_logs do |c|
490
+ c.klass = ::Marty::BackgroundJob::ScheduleJobsLogs
491
+ end
492
+
475
493
  component :scripting do |c|
476
494
  c.allow_edit = self.class.has_scripting_perm?
477
495
  end
@@ -56,7 +56,7 @@ class Marty::DataConversion
56
56
  # Dates are kept as float in Google spreadsheets. Need to
57
57
  # convert them to dates.
58
58
  begin
59
- FLOAT_PAT.match?(v) ? EXCEL_START_DATE + v.to_f :
59
+ FLOAT_PAT.match?(v.to_s) ? EXCEL_START_DATE + v.to_f :
60
60
  Mcfly.is_infinity(v) ? 'infinity' : v.to_date
61
61
  rescue StandardError => e
62
62
  raise "date conversion failed for #{v.inspect}}"
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Marty
4
- VERSION = '8.3.1'
4
+ VERSION = '8.4.1'
5
5
  end
@@ -0,0 +1,80 @@
1
+ require 'spec_helper'
2
+
3
+ feature 'Delayed Jobs Dashboard', js: true do
4
+ before do
5
+ Delayed::Job.delete_all
6
+ populate_test_users
7
+ end
8
+
9
+ context 'as dev' do
10
+ before do
11
+ log_in_as('dev1')
12
+ wait_for_ajax
13
+ press('System')
14
+ press('Background Jobs')
15
+ press('Schedule Jobs Dashboard')
16
+ wait_for_ajax
17
+ end
18
+
19
+ it 'access denied' do
20
+ expect(page).to_not have_content 'Schedule Jobs Dashboard'
21
+ end
22
+ end
23
+
24
+ context 'as admin' do
25
+ let(:jobs_view) { netzke_find('delayed_jobs_grid') }
26
+
27
+ let!(:schedule) do
28
+ ['TestJob', 'Test2Job', 'TestFailingJob'].each do |klass_name|
29
+ Marty::BackgroundJob::Schedule.create(
30
+ job_class: klass_name,
31
+ cron: '0 0 * * *',
32
+ state: 'on'
33
+ ).tap do |job|
34
+ Marty::BackgroundJob::UpdateSchedule.call(
35
+ id: job.id,
36
+ job_class: job.job_class
37
+ )
38
+ end
39
+ end
40
+ end
41
+
42
+ let(:time1) { 10.hours.ago }
43
+
44
+ let(:time2) { 20.hours.ago }
45
+
46
+ before do
47
+ @djs = Delayed::Job.all
48
+ @djs.first.update!(locked_at: time1)
49
+ @djs.last.update!(locked_at: time2)
50
+
51
+ log_in_as('admin1')
52
+ wait_for_ajax
53
+ press('System')
54
+ press('Background Jobs')
55
+ press('Delayed Jobs Dashboard')
56
+
57
+ wait_for_ajax
58
+
59
+ expect(page).to have_content 'Delayed Jobs Dashboard'
60
+ end
61
+
62
+ it 'shows delayed jobs' do
63
+ expect(jobs_view.row_count).to eq @djs.size
64
+ expect(jobs_view.row_count).to eq 3
65
+ locked_at = jobs_view.get_col_vals('locked_at', 3, 0, false).map do |str|
66
+ next unless str
67
+
68
+ Time.zone.parse(str).to_s
69
+ end
70
+
71
+ expect(locked_at).to eq(
72
+ [
73
+ time1.to_s,
74
+ time2.to_s,
75
+ nil
76
+ ]
77
+ )
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,54 @@
1
+ require 'spec_helper'
2
+
3
+ module Marty
4
+ describe DataConversion do
5
+ describe '#convert' do
6
+ describe 'date' do
7
+ let(:date) { 1.day.ago.to_date }
8
+
9
+ it 'converts float strings to date' do
10
+ res = described_class.convert('40000.0', :date)
11
+ expect(res).to eq Date.new(2009, 7, 6)
12
+ end
13
+
14
+ it 'converts date to date' do
15
+ res = described_class.convert(date, :date)
16
+ expect(res).to eq date
17
+ end
18
+
19
+ it 'converts infinity' do
20
+ ['Infinity', 'infinity', ::Float::INFINITY].each do |value|
21
+ res = described_class.convert(value, :date)
22
+ expect(res).to eq 'infinity'
23
+ end
24
+ end
25
+
26
+ it 'raises error if the value is not valid' do
27
+ expect { described_class.convert(true, :date) }.
28
+ to raise_error(/date conversion failed for true/)
29
+ end
30
+ end
31
+
32
+ describe 'boolean' do
33
+ it 'converts true' do
34
+ ['true', '1', 'y', 't'].each do |value|
35
+ res = described_class.convert(value, :boolean)
36
+ expect(res).to eq true
37
+ end
38
+ end
39
+
40
+ it 'converts false' do
41
+ ['false', '0', 'n', 'f'].each do |value|
42
+ res = described_class.convert(value, :boolean)
43
+ expect(res).to eq false
44
+ end
45
+ end
46
+
47
+ it 'raises error if the value is not valid' do
48
+ expect { described_class.convert(1.day.ago, :boolean) }.
49
+ to raise_error(/unknown boolean/)
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: marty
3
3
  version: !ruby/object:Gem::Version
4
- version: 8.3.1
4
+ version: 8.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Arman Bostani
@@ -14,7 +14,7 @@ authors:
14
14
  autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
- date: 2019-12-03 00:00:00.000000000 Z
17
+ date: 2019-12-05 00:00:00.000000000 Z
18
18
  dependencies:
19
19
  - !ruby/object:Gem::Dependency
20
20
  name: actioncable
@@ -310,6 +310,12 @@ files:
310
310
  - app/components/marty/api_log_view.rb
311
311
  - app/components/marty/auth_app.rb
312
312
  - app/components/marty/auth_app/client/auth_app.js
313
+ - app/components/marty/background_job/delayed_jobs_grid.rb
314
+ - app/components/marty/background_job/schedule_jobs_dashboard.rb
315
+ - app/components/marty/background_job/schedule_jobs_grid.rb
316
+ - app/components/marty/background_job/schedule_jobs_grid/client/schedule_jobs_grid.js
317
+ - app/components/marty/background_job/schedule_jobs_logs.rb
318
+ - app/components/marty/background_job/schedule_jobs_logs/client/schedule_jobs_logs.js
313
319
  - app/components/marty/base_rule_view.rb
314
320
  - app/components/marty/base_rule_view/client/base_rule_view.js
315
321
  - app/components/marty/config_view.rb
@@ -356,11 +362,6 @@ files:
356
362
  - app/components/marty/report_select/client/report_select.js
357
363
  - app/components/marty/reporting.rb
358
364
  - app/components/marty/reporting/client/reporting.js
359
- - app/components/marty/schedule_jobs_dashboard.rb
360
- - app/components/marty/schedule_jobs_grid.rb
361
- - app/components/marty/schedule_jobs_grid/client/schedule_jobs_grid.js
362
- - app/components/marty/schedule_jobs_logs.rb
363
- - app/components/marty/schedule_jobs_logs/client/schedule_jobs_logs.js
364
365
  - app/components/marty/script_form.rb
365
366
  - app/components/marty/script_form/client/script_form.js
366
367
  - app/components/marty/script_grid.rb
@@ -1695,6 +1696,7 @@ files:
1695
1696
  - spec/features/data_blame_report_spec.rb
1696
1697
  - spec/features/data_grid_spec.rb
1697
1698
  - spec/features/data_import_spec.rb
1699
+ - spec/features/delayed_jobs_grid_spec.rb
1698
1700
  - spec/features/endpoint_access.rb
1699
1701
  - spec/features/enum_spec.rb
1700
1702
  - spec/features/enum_values_report_spec.rb
@@ -1737,6 +1739,7 @@ files:
1737
1739
  - spec/job_helper.rb
1738
1740
  - spec/jobs/cron_job_spec.rb
1739
1741
  - spec/lib/data_blame_spec.rb
1742
+ - spec/lib/data_conversion_spec.rb
1740
1743
  - spec/lib/data_exporter_spec.rb
1741
1744
  - spec/lib/data_importer_spec.rb
1742
1745
  - spec/lib/delorean_query_spec.rb
@@ -1,52 +0,0 @@
1
- require 'marty/schedule_jobs_grid'
2
-
3
- class Marty::ScheduleJobsDashboard < Marty::Form
4
- include Marty::Extras::Layout
5
-
6
- def configure(c)
7
- super
8
- c.items = [
9
- :schedule_jobs_grid,
10
- :schedule_jobs_warnings
11
- ]
12
- end
13
-
14
- def prepare_warnings
15
- djs = ::Marty::BackgroundJob::FetchMissingInScheduleCronJobs.call
16
-
17
- messages = djs.map do |dj|
18
- handler_str = dj.handler[/job_class.*\n/]
19
- job_class = handler_str.gsub('job_class:', '').strip
20
-
21
- "#{job_class} with cron #{dj.cron} is present in delayed_jobs table, " \
22
- 'but is missing in the Dashboard.'
23
- end
24
-
25
- messages.join('<br>')
26
- end
27
-
28
- client_class do |c|
29
- c.header = false
30
- # c.layout = :border
31
- c.defaults = { body_style: 'padding:0px' }
32
- end
33
-
34
- component :schedule_jobs_grid do |c|
35
- c.klass = Marty::ScheduleJobsGrid
36
- c.region = :north
37
- c.min_height = 500
38
- end
39
-
40
- component :schedule_jobs_warnings do |c|
41
- c.klass = Marty::Panel
42
- c.title = I18n.t('jobs.schedule_dashboard.warnings')
43
- c.html = prepare_warnings
44
- c.min_height = 200
45
- end
46
-
47
- def default_bbar
48
- []
49
- end
50
- end
51
-
52
- ScheduleJobsDashboard = Marty::ScheduleJobsDashboard
@@ -1,118 +0,0 @@
1
- class Marty::ScheduleJobsGrid < Marty::Grid
2
- ACCESSIBLE_BY = [:admin]
3
-
4
- has_marty_permissions(
5
- read: ACCESSIBLE_BY,
6
- create: ACCESSIBLE_BY,
7
- update: ACCESSIBLE_BY,
8
- delete: ACCESSIBLE_BY,
9
- destroy: ACCESSIBLE_BY,
10
- job_run: ACCESSIBLE_BY,
11
- edit_window__edit_form__submit: ACCESSIBLE_BY,
12
- add_window__add_form__submit: ACCESSIBLE_BY
13
- )
14
-
15
- def configure(c)
16
- super
17
-
18
- c.title ||= I18n.t('schedule_jobs_dashboard_view_title', default: 'Schedule Jobs Dashboard')
19
- c.model = 'Marty::BackgroundJob::Schedule'
20
- c.paging = :buffered
21
- c.editing = :in_form
22
- c.multi_select = false
23
-
24
- c.attributes = [
25
- :job_class,
26
- :cron,
27
- :state
28
- ]
29
- end
30
-
31
- def default_context_menu
32
- []
33
- end
34
-
35
- def default_bbar
36
- super + [:do_job_run]
37
- end
38
-
39
- attribute :job_class do |c|
40
- c.width = 400
41
- end
42
-
43
- attribute :cron do |c|
44
- c.width = 400
45
- end
46
-
47
- attribute :state do |c|
48
- c.width = 150
49
- editor_config = {
50
- trigger_action: :all,
51
- xtype: :combo,
52
- store: Marty::BackgroundJob::Schedule::ALL_STATES,
53
- forceSelection: true,
54
- }
55
-
56
- c.column_config = { editor: editor_config }
57
- c.field_config = editor_config
58
- end
59
-
60
- action :do_job_run do |a|
61
- a.text = 'Run'
62
- a.tooltip = 'Run'
63
- a.icon_cls = 'fa fa-play glyph'
64
- a.disabled = true
65
- end
66
-
67
- endpoint :edit_window__edit_form__submit do |params|
68
- result = super(params)
69
- next result if result.empty?
70
-
71
- obj_hash = result.first
72
- Marty::BackgroundJob::UpdateSchedule.call(id: obj_hash['id'], job_class: obj_hash['job_class'])
73
-
74
- result
75
- end
76
-
77
- endpoint :add_window__add_form__submit do |params|
78
- result = super(params)
79
- next result if result.empty?
80
-
81
- obj_hash = result.first
82
- Marty::BackgroundJob::UpdateSchedule.call(id: obj_hash['id'], job_class: obj_hash['job_class'])
83
-
84
- result
85
- end
86
-
87
- endpoint :multiedit_window__multiedit_form__submit do |_params|
88
- client.netzke_notify 'Multiediting is disabled for cron schedules'
89
- end
90
-
91
- endpoint :destroy do |params|
92
- res = params.each_with_object({}) do |id, hash|
93
- job_class = model.find_by(id: id)&.job_class
94
- result = super([id])
95
-
96
- # Do nothing If it wasn't destroyed
97
- next hash.merge(result) unless result[id.to_i] == 'ok'
98
-
99
- Marty::BackgroundJob::UpdateSchedule.call(id: id, job_class: job_class)
100
- hash.merge(result)
101
- end
102
-
103
- res
104
- end
105
-
106
- endpoint :job_run do
107
- begin
108
- s = Marty::BackgroundJob::Schedule.find(client_config['selected'])
109
- klass = s.job_class
110
- klass.constantize.new.perform
111
- rescue StandardError => e
112
- next client.netzke_notify(e.message)
113
- end
114
- client.netzke_notify("#{klass.demodulize} ran successfully.")
115
- end
116
- end
117
-
118
- ScheduleJobsGrid = Marty::ScheduleJobsGrid
@@ -1,85 +0,0 @@
1
- class Marty::ScheduleJobsLogs < Marty::Grid
2
- ACCESSIBLE_BY = [:admin]
3
-
4
- has_marty_permissions(
5
- read: ACCESSIBLE_BY,
6
- create: ACCESSIBLE_BY,
7
- update: ACCESSIBLE_BY,
8
- delete: ACCESSIBLE_BY,
9
- destroy: ACCESSIBLE_BY,
10
- destroy_all: ACCESSIBLE_BY,
11
- ignore: ACCESSIBLE_BY,
12
- edit_window__edit_form__submit: ACCESSIBLE_BY,
13
- add_window__add_form__submit: ACCESSIBLE_BY
14
- )
15
-
16
- def configure(c)
17
- super
18
-
19
- c.title ||= I18n.t('schedule_jobs_dashboard_view_title', default: "Scheduled Job's Logs")
20
- c.model = 'Marty::BackgroundJob::Log'
21
- c.paging = :buffered
22
- c.editing = :in_form
23
- c.multi_select = true
24
-
25
- c.attributes = [
26
- :job_class,
27
- :status,
28
- :error,
29
- :created_at
30
- ]
31
-
32
- c.store_config.merge!(sorters: [{ property: :id, direction: 'DESC' }])
33
- end
34
-
35
- def default_context_menu
36
- []
37
- end
38
-
39
- def default_bbar
40
- [:delete, :destroy_all, :ignore]
41
- end
42
-
43
- attribute :job_class do |c|
44
- c.width = 400
45
- c.read_only = true
46
- end
47
-
48
- attribute :status do |c|
49
- c.read_only = true
50
- end
51
-
52
- attribute :error do |c|
53
- c.width = 800
54
- c.read_only = true
55
- c.getter = ->(record) { record.error.to_json }
56
- end
57
-
58
- action :destroy_all do |a|
59
- a.text = 'Delete all'
60
- a.tooltip = 'Delete all logs'
61
- a.icon_cls = 'fa fa-trash glyph'
62
- end
63
-
64
- action :ignore do |a|
65
- a.text = 'Ignore in diag'
66
- a.tooltip = 'Ignore in diag'
67
- a.icon_cls = 'fa fa-trash glyph'
68
- end
69
-
70
- endpoint :destroy_all do
71
- Marty::BackgroundJob::Log.delete_all
72
- client.reload
73
- end
74
-
75
- endpoint :ignore do |ids|
76
- Marty::BackgroundJob::Log.
77
- where(id: ids).
78
- where(status: :failure).
79
- each { |record| record.update(status: :failure_ignore) }
80
-
81
- client.reload
82
- end
83
- end
84
-
85
- ScheduleJobsLogs = Marty::ScheduleJobsLogs