canvas_sync 0.17.17.beta1 → 0.17.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 63d76061493c5aa510709d95f5d1e9828f47e675d0571c9a2afc76e2a2b92807
4
- data.tar.gz: 320ec24b43c5004c137287a11989dd6982436509f76c8745331ecb1ab6ad4702
3
+ metadata.gz: 30e1a16308bbc8795dc671c19f35d29577665213261829d3180a9efeefab4adf
4
+ data.tar.gz: bade0d8907b22bf252b85ba4067798ebd3b6582deed06adfccf7a8951a6164b4
5
5
  SHA512:
6
- metadata.gz: dd07a46eb04eeb95a069d516af6a361ca8051d1dce5254a41560ff072472e5090db1c049495b9f2a57a48cba456f127bd7e1df2e8510b205fc053e2398aceb3e
7
- data.tar.gz: 62767cc36c1cf7f6850072a9b7ea502e805da4218a4ae63f152f6453d1f02fbf144cca7f791f3ce848eb29c65af57832529f4b6a444e12342cd3aea4c4e77cf2
6
+ metadata.gz: 4a155b415154694a42c218bd5ef91f21ca7cdcc81967cc2f2c16a180eebfb32d1b279c72ea2eab58beaabb8e8a8905fe4ef4086ce758c9ee14b1583eccf06849
7
+ data.tar.gz: 3269c39188c086e7b3b03d6280414fbdc7a32c6780af5744da08f3f9432f4eb5ed993c3af4d22e2fe477d92ca8e4d705c62ba9e9005559a9e1145922f565aa4f
@@ -28,6 +28,7 @@ module CanvasSync
28
28
 
29
29
  BID_EXPIRE_TTL = 2_592_000
30
30
  SCHEDULE_CALLBACK = RedisScript.new(Pathname.new(__FILE__) + "../schedule_callback.lua")
31
+ BID_HIERARCHY = RedisScript.new(Pathname.new(__FILE__) + "../hier_batch_ids.lua")
31
32
 
32
33
  attr_reader :bid
33
34
 
@@ -423,6 +424,14 @@ module CanvasSync
423
424
  def push_callbacks(args, queue)
424
425
  Batch::Callback::worker_class.enqueue_all(args, queue)
425
426
  end
427
+
428
+ def bid_hierarchy(bid, depth: 4, per_depth: 5, slice: nil)
429
+ args = [bid, depth, per_depth]
430
+ args << slice if slice
431
+ redis do |r|
432
+ BID_HIERARCHY.call(r, [], args)
433
+ end
434
+ end
426
435
  end
427
436
  end
428
437
 
@@ -172,6 +172,14 @@ module CanvasSync
172
172
  mapper[key] ||= []
173
173
  end
174
174
 
175
+ # TODO: Add a Chain progress web View
176
+ # Augment Batch tree-view with Chain data
177
+ # > [DONE] Tree view w/o Chain will only show Parent/Current batches and Job Counts
178
+ # > If augmented with Chain data, the above will be annotated with Chain-related info and will be able to show Jobs defined in the Chain
179
+ # > Chain-jobs will be supplied chain_id and chain_step_id metadata
180
+ # > Using server-middleware, if a Chain-job (has chain_id and chain_step_id) creates a Batch, tag the Batch w/ the chain_id and chain_step_id
181
+ # > UI will map Batches to Chain-steps using the chain_step_id. UI will add entries for any Chain-steps that were not tied to a Batch
182
+ # > [DONE] Use a Lua script to find child batch IDs. Support max_depth, items_per_depth, top_depth_slice parameters
175
183
  def enqueue_job(job_def)
176
184
  job_class = job_def[:job].constantize
177
185
  job_options = job_def[:parameters] || []
@@ -0,0 +1,25 @@
1
+
2
+ local function add_bids(root, depth)
3
+ local result_data = {}
4
+
5
+ if depth > 0 then
6
+ local sbids
7
+ if depth == tonumber(ARGV[2]) and ARGV[4] then
8
+ local min, max = ARGV[4]:match('(%d+):(%d+)')
9
+ sbids = redis.call('ZRANGE', 'BID-' .. root .. '-bids', min, max)
10
+ else
11
+ sbids = redis.call('ZRANGE', 'BID-' .. root .. '-bids', 0, tonumber(ARGV[3]) - 1)
12
+ end
13
+
14
+ local sub_data = {}
15
+ for _,v in ipairs(sbids) do
16
+ table.insert(sub_data, add_bids(v, depth - 1))
17
+ end
18
+
19
+ return { root, sub_data }
20
+ end
21
+
22
+ return { root, result_data}
23
+ end
24
+
25
+ return add_bids(ARGV[1], tonumber(ARGV[2]))
@@ -9,11 +9,19 @@ require_relative "web/helpers"
9
9
 
10
10
  module CanvasSync::JobBatches::Sidekiq
11
11
  module Web
12
+ DEV_MODE = (defined?(Rails) && !Rails.env.production?) || !!ENV["SIDEKIQ_WEB_TESTING"]
13
+
12
14
  def self.registered(app) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
13
15
  app.helpers do
14
16
  include Web::Helpers
17
+
18
+ def dev_mode?
19
+ DEV_MODE
20
+ end
15
21
  end
16
22
 
23
+ # =============== BATCHES =============== #
24
+
17
25
  app.get "/batches" do
18
26
  @count = (params['count'] || 25).to_i
19
27
  @current_page, @total_size, @batches = page('batches', params['page'], @count)
@@ -26,6 +34,8 @@ module CanvasSync::JobBatches::Sidekiq
26
34
  @bid = params[:bid]
27
35
  @batch = CanvasSync::JobBatches::Batch.new(@bid)
28
36
 
37
+ @tree_data = tree_data(@bid)
38
+
29
39
  @count = (params['count'] || 25).to_i
30
40
  @current_batches_page, @total_batches_size, @sub_batches = page("BID-#{@batch.bid}-bids", params['batch_page'], @count)
31
41
  @sub_batches = @sub_batches.map {|b, score| CanvasSync::JobBatches::Batch.new(b) }
@@ -36,6 +46,81 @@ module CanvasSync::JobBatches::Sidekiq
36
46
  erb(get_template(:batch))
37
47
  end
38
48
 
49
+ app.get "/batches/:bid/tree" do
50
+ @bid = params[:bid]
51
+
52
+ json(tree_data(@bid, slice: params[:slice]))
53
+ end
54
+
55
+ app.helpers do
56
+ def tree_data(root_bid, slice: nil)
57
+ tree_bids = CanvasSync::JobBatches::Batch.bid_hierarchy(root_bid, slice: slice)
58
+
59
+ CanvasSync::JobBatches::Batch.redis do |r|
60
+ layer_data = ->(layer, parent = nil) {
61
+ bid = layer[0]
62
+ batch = CanvasSync::JobBatches::Batch.new(bid)
63
+
64
+ jobs_total = r.hget("BID-#{bid}", "job_count").to_i
65
+ jobs_pending = r.hget("BID-#{bid}", 'pending').to_i
66
+ jobs_failed = r.scard("BID-#{bid}-failed").to_i
67
+ jobs_success = jobs_total - jobs_pending
68
+
69
+ batches_total = r.hget("BID-#{bid}", 'children').to_i
70
+ batches_success = r.scard("BID-#{bid}-batches-success").to_i
71
+ batches_pending = batches_total - batches_success
72
+ batches_failed = r.scard("BID-#{bid}-batches-failed").to_i
73
+
74
+ status = 'in_progress'
75
+ status = 'complete' if batches_pending == batches_failed && jobs_pending == jobs_failed
76
+ status = 'success' if batches_pending == 0 && jobs_pending == 0
77
+ status = 'deleted' if bid != root_bid && !batch.parent_bid
78
+
79
+ {
80
+ bid: bid,
81
+ created_at: r.hget("BID-#{bid}", 'created_at'),
82
+ status: status,
83
+ parent_bid: parent ? parent.bid : batch.parent_bid,
84
+ description: batch.description,
85
+ jobs: {
86
+ pending_count: jobs_pending,
87
+ successful_count: jobs_success,
88
+ failed_count: jobs_failed,
89
+ total_count: jobs_total,
90
+ # items: batches.map{|b| layer_data[b] },
91
+ },
92
+ batches: {
93
+ pending_count: batches_pending,
94
+ successful_count: batches_success,
95
+ failed_count: batches_failed,
96
+ total_count: batches_total,
97
+ items: layer[1].map{|b| layer_data[b, batch] },
98
+ },
99
+ }
100
+ }
101
+
102
+ data = layer_data[tree_bids]
103
+ data[:batches][:slice] = slice if slice
104
+ data
105
+ end
106
+ end
107
+
108
+ def format_context(batch)
109
+ bits = []
110
+ own_keys = batch.context.own.keys
111
+ batch.context.flatten.each do |k,v|
112
+ added = own_keys.include? k
113
+ bits << " <span class=\"key #{added ? 'own' : 'inherited'}\">\"#{k}\": #{v.to_json},</span>"
114
+ end
115
+ bits = [
116
+ "{ // <span class=\"own\">Added</span> / <span class=\"inherited\">Inherited</span>",
117
+ *bits,
118
+ '}'
119
+ ]
120
+ bits.join("\n")
121
+ end
122
+ end
123
+
39
124
  app.post "/batches/all" do
40
125
  if params['delete']
41
126
  drain_zset('batches') do |batches|
@@ -107,6 +192,14 @@ module CanvasSync::JobBatches::Sidekiq
107
192
  end
108
193
 
109
194
  if defined?(::Sidekiq::Web)
195
+ rules = []
196
+ rules = [[:all, {"Cache-Control" => "public, max-age=86400"}]] unless CanvasSync::JobBatches::Sidekiq::Web::DEV_MODE
197
+
198
+ ::Sidekiq::Web.use Rack::Static, urls: ["/batches_assets"],
199
+ root: File.expand_path("#{File.dirname(__FILE__)}/web"),
200
+ cascade: true,
201
+ header_rules: rules
202
+
110
203
  ::Sidekiq::Web.register CanvasSync::JobBatches::Sidekiq::Web
111
204
  ::Sidekiq::Web.tabs["Batches"] = "batches"
112
205
  ::Sidekiq::Web.tabs["Pools"] = "pools"
@@ -0,0 +1,178 @@
1
+
2
+ @color-green: #25c766;
3
+ @color-red: #c7254e;
4
+ @color-yellow: #c4c725;
5
+
6
+ .code-wrap.batch-context .args-extended {
7
+ white-space: pre;
8
+
9
+ .key {
10
+ white-space: pre-wrap;
11
+ margin-left: 2em;
12
+ text-indent: -2em;
13
+ display: inline-block;
14
+ }
15
+
16
+ .own {
17
+ color: @color-green;
18
+ }
19
+ }
20
+
21
+
22
+ .batch-tree {
23
+ .status-block {
24
+ .tree-stat {
25
+ margin: 0 4px;
26
+
27
+ &.pending {
28
+ color: @color-yellow;
29
+ }
30
+ &.failed {
31
+ color: @color-red;
32
+ }
33
+ &.success {
34
+ color: @color-green;
35
+ }
36
+ &.total {
37
+
38
+ }
39
+ }
40
+ }
41
+
42
+ .text-inactive {
43
+ color: darken(#fff, 35%);
44
+ font-size: 80%;
45
+ }
46
+
47
+ .tree-header {
48
+ position: relative;
49
+
50
+ .status-block {
51
+ position: absolute;
52
+ bottom: 0;
53
+ width: 100%;
54
+
55
+ margin-right: 8px;
56
+ font-size: 90%;
57
+ text-align: right;
58
+
59
+ .tree-stat {
60
+ font-style: italic;
61
+ }
62
+ }
63
+ }
64
+
65
+ .tree-entry {
66
+ > .header {
67
+ display: flex;
68
+ align-items: center;
69
+
70
+ .header-inner {
71
+ padding: 4px 0;
72
+ border-bottom: 1px dashed white;
73
+ display: flex;
74
+ align-items: center;
75
+ flex: 1;
76
+ }
77
+
78
+ &:hover {
79
+ background-color: rgba(0,0,0,0.20);
80
+ border-radius: 3px;
81
+ }
82
+
83
+ .row-toggle {
84
+ width: 16px;
85
+ height: 16px;
86
+ text-align: center;
87
+ align-self: center;
88
+ border-radius: 50%;
89
+ border: 1px solid #999;
90
+ text-decoration: none;
91
+ margin: 0 4px;
92
+ font-size: 16px;
93
+ line-height: 15px;
94
+
95
+ &.not_applicable {
96
+ opacity: 0;
97
+ pointer-events: none;
98
+ }
99
+ }
100
+
101
+ .main {
102
+ flex: 1;
103
+ display: flex;
104
+ align-items: baseline;
105
+
106
+ .bid {
107
+ font-family: monospace;
108
+ padding: 3px 6px;
109
+ background: rgba(0,0,0,0.2);
110
+ border-radius: 3px;
111
+ font-size: 12px;
112
+ margin: 0 12px 0 0;
113
+
114
+ &:hover {
115
+ .bid-goto {
116
+ display: inline-block;
117
+ padding: 0 0 0 4px;
118
+ font-size: 200%;
119
+ line-height: 10px;
120
+ vertical-align: sub;
121
+ text-decoration: dotted;
122
+ }
123
+ }
124
+
125
+ .bid-goto {
126
+ display: none;
127
+ }
128
+ }
129
+ }
130
+
131
+ .goto-link {
132
+ margin: 0 8px;
133
+ display: inline-block;
134
+ height: 16px;
135
+ font-size: 90%;
136
+ border-bottom: 1px dotted white;
137
+ }
138
+
139
+ .status-label {
140
+ font-family: monospace;
141
+ padding: 3px 6px;
142
+ background: rgba(0,0,0,0.2);
143
+ border-radius: 3px;
144
+ font-size: 12px;
145
+ margin: 0 12px 0 0;
146
+
147
+ &.deleted {
148
+ background: #99999933;
149
+ }
150
+ &.failed, &.complete {
151
+ background: #99000033;
152
+ }
153
+ &.success {
154
+ background: #00990033;
155
+ }
156
+ }
157
+
158
+ .status-block {
159
+ width: 10em;
160
+ text-align: center;
161
+ }
162
+ }
163
+
164
+ > .subitems {
165
+ padding-left: 16px;
166
+
167
+ >.load-more {
168
+ padding: 4px 0;
169
+ text-align: center;
170
+ border-bottom: 1px dashed white;
171
+ a {
172
+ border-bottom: 1px dotted white;
173
+ text-decoration: none;
174
+ }
175
+ }
176
+ }
177
+ }
178
+ }
@@ -0,0 +1,106 @@
1
+ import { h, Component, render } from 'https://unpkg.com/preact?module';
2
+ import htm from 'https://unpkg.com/htm?module';
3
+ import { root_url } from './util.js';
4
+
5
+ // Initialize htm with Preact
6
+ const html = htm.bind(h);
7
+
8
+ const StatusBlock = (props) => html`
9
+ <div class="status-block ${props.class || ''}">
10
+ ${props.title && props.title + ':'}
11
+ <span class="tree-stat pending">${props.pending_count}</span>
12
+ |
13
+ <span class="tree-stat failed">${props.failed_count}</span>
14
+ |
15
+ <span class="tree-stat success">${props.successful_count}</span>
16
+ /
17
+ <span class="tree-stat total">${props.total_count}</span>
18
+ </div>
19
+ `
20
+
21
+ class TreeLevel extends Component {
22
+ get bid() {
23
+ return this.props.data.bid;
24
+ }
25
+
26
+ get batch() {
27
+ return this.props.data;
28
+ }
29
+
30
+ load_more = async (event) => {
31
+ event.preventDefault();
32
+ const l = this.batch.batches.items.length;
33
+ const resp = await fetch(`${root_url}batches/${this.bid}/tree?slice=${l}:${l + 5 - 1}`)
34
+ const result = await resp.json()
35
+ const newEntries = result.batches.items;
36
+ for (let ent of newEntries) {
37
+ this.batch.batches.items.push(ent)
38
+ }
39
+ this.forceUpdate()
40
+ }
41
+
42
+ toggle = (event) => {
43
+ event.preventDefault();
44
+ this.setState({ collapsed: !this.state.collapsed })
45
+ }
46
+
47
+ render() {
48
+ const { data: bd } = this.props;
49
+
50
+ let sub_entries = [];
51
+ let sub_batches = bd.batches.items;
52
+ for (let b of sub_batches) {
53
+ sub_entries.push(html`<${TreeLevel} data=${b} />`)
54
+ }
55
+
56
+ let fully_loaded = !(sub_batches.length < bd.batches.total_count);
57
+
58
+ const load_more_elem = html`<div class="load-more">
59
+ ${sub_entries.length} / ${bd.batches.total_count} Items Loaded - <a href="#" onClick=${this.load_more}>Load More</a>
60
+ </div>`
61
+
62
+ return html`<div class="tree-entry tree-batch">
63
+ <div class="header">
64
+ <a class="row-toggle ${!bd.batches.total_count && 'not_applicable'}" onClick=${this.toggle} href="#">
65
+ ${this.state.collapsed ? '+' : '-'}
66
+ </a>
67
+
68
+ <div class="header-inner">
69
+ <div class="main">
70
+ <span class="bid">
71
+ ${bd.bid}
72
+ <a class="bid-goto" href="${root_url}batches/${bd.bid}">⇢</a>
73
+ </span>
74
+ ${bd.description || (bd.status == 'deleted' && html`<i class="text-inactive">Deleted</i>`) || html`<i class="text-inactive">No Description</i>`}
75
+ </div>
76
+
77
+ <span class="status-label ${bd.status}">${bd.status}</span>
78
+
79
+ ${bd.status != 'deleted' && html`
80
+ <${StatusBlock} class="job-status" title="Jobs" ...${bd.jobs} />
81
+ <${StatusBlock} class="batch-status" title="Batches" ...${bd.batches} />
82
+ `}
83
+ </div>
84
+ </div>
85
+
86
+ <div class="subitems ${this.state.collapsed ? 'hidden' : ''}">
87
+ ${sub_entries}
88
+ ${!fully_loaded && load_more_elem}
89
+ </div>
90
+ </div>`
91
+ }
92
+ }
93
+
94
+ class TreeRoot extends Component {
95
+ render() {
96
+ const tree_data = JSON.parse(document.querySelector('#batch-tree #initial-data').innerHTML);
97
+ return html`
98
+ <div class="tree-header">
99
+ <${StatusBlock} pending_count="pending" failed_count="failed" successful_count="successful" total_count="total" />
100
+ </div>
101
+ <${TreeLevel} data=${tree_data} />
102
+ `;
103
+ }
104
+ }
105
+
106
+ render(html`<${TreeRoot} />`, document.querySelector('#batch-tree'));
@@ -0,0 +1,2 @@
1
+
2
+ export const root_url = (document.querySelector('meta[name="sidekiq-baseurl"]')).content;
@@ -0,0 +1,6 @@
1
+
2
+ <div id="batch-tree" class="batch-tree">
3
+ <script id="initial-data" type="application/json"><%= @tree_data.to_json %></script>
4
+ </div>
5
+
6
+ <script type="module" src="<%= root_path %>batches_assets/js/batch_tree.js"></script>
@@ -0,0 +1,13 @@
1
+
2
+ <% add_to_head do %>
3
+ <meta name="sidekiq-baseurl" content="<%= root_path %>" />
4
+ <% if dev_mode? %>
5
+ <link href="<%= root_path %>batches_assets/css/styles.less" media="screen" rel="stylesheet/less" type="text/css" />
6
+ <script async type="text/javascript" src="https://unpkg.com/less@4.1.1/dist/less.js" data-async="true"></script>
7
+ <% else %>
8
+ <link href="<%= root_path %>batches_assets/css/styles.less" media="screen" rel="stylesheet/less" type="text/css" />
9
+ <script async type="text/javascript" src="https://unpkg.com/less@4.1.1/dist/less.js" data-async="true"></script>
10
+ <%# TODO: Pre-compile LESS %>
11
+ <!-- <link href="<%= root_path %>batches_assets/css/styles.css" media="screen" rel="stylesheet" type="text/css" /> -->
12
+ <% end %>
13
+ <% end %>
@@ -1,3 +1,5 @@
1
+ <%= erb get_template(:_common) %>
2
+
1
3
  <h3><%= t('Batch') %></h3>
2
4
  <% status = CanvasSync::JobBatches::Batch::Status.new(@batch) %>
3
5
 
@@ -17,70 +19,13 @@
17
19
  <td><%= @batch.description %></td>
18
20
  </tr>
19
21
  <tr>
20
- <th colspan="2" scope=row><%= t('Added Context') %></td>
22
+ <th colspan="2" scope=row><%= t('Context') %></td>
21
23
  <td>
22
- <code class="code-wrap">
23
- <div class="args-extended"><%= @batch.context.own.to_json %></div>
24
+ <code class="code-wrap batch-context">
25
+ <div class="args-extended"><%= format_context(@batch) %></div>
24
26
  </code>
25
27
  </td>
26
28
  </tr>
27
- <tr>
28
- <th colspan="2" scope=row><%= t('Full Context') %></td>
29
- <td>
30
- <code class="code-wrap">
31
- <div class="args-extended"><%= @batch.context.flatten.to_json %></div>
32
- </code>
33
- </td>
34
- </tr>
35
-
36
- <tr>
37
- <th colspan="3">Jobs</th>
38
- </tr>
39
- <tr>
40
- <th></th>
41
- <th><%= t('Pending') %></th>
42
- <td><%= status.pending %></th>
43
- </tr>
44
- <tr>
45
- <th></th>
46
- <th><%= t('Failed') %></th>
47
- <td><%= status.failures %></th>
48
- </tr>
49
- <tr>
50
- <th></th>
51
- <th><%= t('Complete') %></th>
52
- <td><%= status.completed_count %></th>
53
- </tr>
54
- <tr>
55
- <th></th>
56
- <th><%= t('Total') %></th>
57
- <td><%= status.job_count %></th>
58
- </tr>
59
-
60
- <tr>
61
- <th colspan="3">Batches</th>
62
- </tr>
63
- <tr>
64
- <th></th>
65
- <th><%= t('Pending') %></th>
66
- <td><%= status.child_count - status.successful_children_count %></th>
67
- </tr>
68
- <tr>
69
- <th></th>
70
- <th><%= t('Failed') %></th>
71
- <td><%= status.failed_children_count %></th>
72
- </tr>
73
- <tr>
74
- <th></th>
75
- <th><%= t('Success') %></th>
76
- <td><%= status.successful_children_count %></th>
77
- </tr>
78
- <tr>
79
- <th></th>
80
- <th><%= t('Total') %></th>
81
- <td><%= status.child_count %></th>
82
- </tr>
83
-
84
29
  </tbody>
85
30
  </table>
86
31
  </div>
@@ -88,51 +33,33 @@
88
33
  <header class="row">
89
34
  <div class="col-sm-5">
90
35
  <h3>
91
- <%= t('Jobs') %>
36
+ <%= t('Child Batches') %>
92
37
  </h3>
93
38
  </div>
94
- <%
95
- @current_page = @current_jobs_page
96
- @total_size = @total_jobs_size
97
- %>
98
- <% if @jobs.any? && @total_size > @count.to_i %>
99
- <div class="col-sm-4">
100
- <%= erb get_template(:_pagination), locals: { url: "#{root_path}batches/#{@batch.bid}", page_key: :job_page } %>
101
- </div>
102
- <% end %>
103
39
  </header>
104
40
 
105
- <% if @jobs.any? %>
106
- <div class="table_container">
107
- <%= erb get_template(:_jobs_table), locals: { jobs: @jobs } %>
108
- </div>
109
- <% end %>
41
+ <%= erb get_template(:_batch_tree), locals: { } %>
110
42
 
111
43
  <header class="row">
112
44
  <div class="col-sm-5">
113
45
  <h3>
114
- <%= t('Child Batches') %>
46
+ <%= t('Jobs') %>
47
+ <i>(Queued and Current)</i>
115
48
  </h3>
116
49
  </div>
117
50
  <%
118
- @current_page = @current_batches_page
119
- @total_size = @total_batches_size
51
+ @current_page = @current_jobs_page
52
+ @total_size = @total_jobs_size
120
53
  %>
121
- <% if @sub_batches.any? && @total_size > @count.to_i %>
54
+ <% if @jobs.any? && @total_size > @count.to_i %>
122
55
  <div class="col-sm-4">
123
- <%= erb get_template(:_pagination), locals: { url: "#{root_path}batches/#{@batch.bid}", page_key: :batch_page } %>
56
+ <%= erb get_template(:_pagination), locals: { url: "#{root_path}batches/#{@batch.bid}", page_key: :job_page } %>
124
57
  </div>
125
58
  <% end %>
126
59
  </header>
127
60
 
128
- <% if @sub_batches.any? %>
61
+ <% if @jobs.any? %>
129
62
  <div class="table_container">
130
- <%= erb get_template(:_batches_table), locals: { batches: @sub_batches } %>
63
+ <%= erb get_template(:_jobs_table), locals: { jobs: @jobs } %>
131
64
  </div>
132
65
  <% end %>
133
-
134
- <form class="form-horizontal" action="<%= root_path %>batches/<%= @batch.bid %>" method="post">
135
- <%= csrf_tag %>
136
- <a class="btn btn-default" href="<%= root_path %>batches"><%= t('GoBack') %></a>
137
- <input class="btn btn-danger" type="submit" name="delete" value="<%= t('Delete') %>" data-confirm="<%= t('AreYouSure') %>" />
138
- </form>
@@ -1,3 +1,3 @@
1
1
  module CanvasSync
2
- VERSION = "0.17.17.beta1".freeze
2
+ VERSION = "0.17.18".freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: canvas_sync
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.17.17.beta1
4
+ version: 0.17.18
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nate Collings
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-07-13 00:00:00.000000000 Z
11
+ date: 2021-08-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -442,6 +442,7 @@ files:
442
442
  - lib/canvas_sync/job_batches/callback.rb
443
443
  - lib/canvas_sync/job_batches/chain_builder.rb
444
444
  - lib/canvas_sync/job_batches/context_hash.rb
445
+ - lib/canvas_sync/job_batches/hier_batch_ids.lua
445
446
  - lib/canvas_sync/job_batches/hincr_max.lua
446
447
  - lib/canvas_sync/job_batches/jobs/base_job.rb
447
448
  - lib/canvas_sync/job_batches/jobs/concurrent_batch_job.rb
@@ -453,8 +454,13 @@ files:
453
454
  - lib/canvas_sync/job_batches/schedule_callback.lua
454
455
  - lib/canvas_sync/job_batches/sidekiq.rb
455
456
  - lib/canvas_sync/job_batches/sidekiq/web.rb
457
+ - lib/canvas_sync/job_batches/sidekiq/web/batches_assets/css/styles.less
458
+ - lib/canvas_sync/job_batches/sidekiq/web/batches_assets/js/batch_tree.js
459
+ - lib/canvas_sync/job_batches/sidekiq/web/batches_assets/js/util.js
456
460
  - lib/canvas_sync/job_batches/sidekiq/web/helpers.rb
461
+ - lib/canvas_sync/job_batches/sidekiq/web/views/_batch_tree.erb
457
462
  - lib/canvas_sync/job_batches/sidekiq/web/views/_batches_table.erb
463
+ - lib/canvas_sync/job_batches/sidekiq/web/views/_common.erb
458
464
  - lib/canvas_sync/job_batches/sidekiq/web/views/_jobs_table.erb
459
465
  - lib/canvas_sync/job_batches/sidekiq/web/views/_pagination.erb
460
466
  - lib/canvas_sync/job_batches/sidekiq/web/views/batch.erb
@@ -673,11 +679,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
673
679
  version: '0'
674
680
  required_rubygems_version: !ruby/object:Gem::Requirement
675
681
  requirements:
676
- - - ">"
682
+ - - ">="
677
683
  - !ruby/object:Gem::Version
678
- version: 1.3.1
684
+ version: '0'
679
685
  requirements: []
680
- rubygems_version: 3.0.3.1
686
+ rubygems_version: 3.0.3
681
687
  signing_key:
682
688
  specification_version: 4
683
689
  summary: Gem for generating Canvas models and migrations and syncing data from Canvas