command_proposal 1.0.12 → 1.0.13
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/stylesheets/command_proposal/components.scss +17 -0
- data/app/controllers/command_proposal/iterations_controller.rb +7 -2
- data/app/controllers/command_proposal/tasks_controller.rb +4 -2
- data/app/helpers/command_proposal/params_helper.rb +43 -0
- data/app/models/command_proposal/iteration.rb +11 -0
- data/app/models/command_proposal/task.rb +14 -2
- data/app/views/command_proposal/tasks/_past_iterations_list.html.erb +6 -7
- data/app/views/command_proposal/tasks/index.html.erb +7 -3
- data/lib/command_proposal/services/runner.rb +6 -2
- data/lib/command_proposal/version.rb +1 -1
- data/lib/command_proposal.rb +2 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d57823efe2c4175b2786f8346a67ea68e96804bc980f06fc4afb0feb30a8dc9a
|
4
|
+
data.tar.gz: 212e7e868bf94fe559701ee696fc5487a9a17bcc3b549f35880843d8564f927d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 96795b4fff0569ca5ed7c965cc1d27dcaa2fd753301a62cee0da1a0e7f684daa9489b5ca5f51f195bd58a8a86c3f9f77aea2b9e21017fc6c14c5ee61b73169e3
|
7
|
+
data.tar.gz: 6e15d7c2aeadeb488bfc35784cdeb2626a29cfa18f6a98264af30d35e45ecc7b8df8d8356d70ef4e7b07ca2228c78149dfd3a0bd7bc77e6ad00a3d17df2d63b1
|
@@ -35,3 +35,20 @@
|
|
35
35
|
background: lightgrey;
|
36
36
|
}
|
37
37
|
}
|
38
|
+
|
39
|
+
.cmd-pagination {
|
40
|
+
text-align: center;
|
41
|
+
margin-top: 10px;
|
42
|
+
|
43
|
+
.cmd-pagination-link {
|
44
|
+
text-decoration: none;
|
45
|
+
|
46
|
+
&:hover {
|
47
|
+
text-decoration: underline;
|
48
|
+
}
|
49
|
+
|
50
|
+
&.current-page {
|
51
|
+
font-weight: bold;
|
52
|
+
}
|
53
|
+
}
|
54
|
+
}
|
@@ -33,8 +33,13 @@ class ::CommandProposal::IterationsController < ::CommandProposal::EngineControl
|
|
33
33
|
@iteration = @task.current_iteration
|
34
34
|
@iteration.update(status: :approved) # Task was already approved, and this is line-by-line
|
35
35
|
|
36
|
-
#
|
37
|
-
|
36
|
+
# async, but wait for the job to finish
|
37
|
+
::CommandProposal::CommandRunnerJob.perform_later(@iteration.id)
|
38
|
+
loop do
|
39
|
+
sleep 0.2
|
40
|
+
|
41
|
+
break if @iteration.reload.complete?
|
42
|
+
end
|
38
43
|
|
39
44
|
render json: {
|
40
45
|
result: @iteration.result
|
@@ -17,7 +17,8 @@ class ::CommandProposal::TasksController < ::CommandProposal::EngineController
|
|
17
17
|
@tasks = ::CommandProposal::Task.includes(:iterations)
|
18
18
|
@tasks = @tasks.order(Arel.sql("COALESCE(command_proposal_tasks.last_executed_at, command_proposal_tasks.created_at) DESC"))
|
19
19
|
@tasks = @tasks.search(params[:search]) if params[:search].present?
|
20
|
-
@tasks = @tasks.
|
20
|
+
@tasks = @tasks.by_session(params[:filter])
|
21
|
+
@tasks = @tasks.cmd_page(params[:page])
|
21
22
|
end
|
22
23
|
|
23
24
|
def show
|
@@ -37,7 +38,8 @@ class ::CommandProposal::TasksController < ::CommandProposal::EngineController
|
|
37
38
|
end
|
38
39
|
|
39
40
|
def new
|
40
|
-
@task = ::CommandProposal::Task.new
|
41
|
+
@task = ::CommandProposal::Task.new
|
42
|
+
@task.session_type = params[:session_type] if params[:session_type].in?(::CommandProposal::Task.session_types)
|
41
43
|
|
42
44
|
render "form"
|
43
45
|
end
|
@@ -22,6 +22,15 @@ module ::CommandProposal::ParamsHelper
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
+
def current_path(new_params={})
|
26
|
+
if @task.present?
|
27
|
+
new_params.merge!(iteration: @iteration.id) if @iteration.present? && !@iteration.primary_iteration?
|
28
|
+
cmd_path(@task, new_params)
|
29
|
+
else
|
30
|
+
cmd_path(:tasks, current_params(new_params))
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
25
34
|
def truthy?(val)
|
26
35
|
val.to_s.downcase.in?(["true", "t", "1"])
|
27
36
|
end
|
@@ -60,4 +69,38 @@ module ::CommandProposal::ParamsHelper
|
|
60
69
|
return "< 1s" if str_parts.none?
|
61
70
|
str_parts.join(" ")
|
62
71
|
end
|
72
|
+
|
73
|
+
def div(opts={}, &block)
|
74
|
+
"<div #{opts.map { |k, v| "#{k}=\"#{v}\"" }.join(" ")}>#{yield}</div>".html_safe
|
75
|
+
end
|
76
|
+
|
77
|
+
def command_paginate(paged_collection)
|
78
|
+
collection = paged_collection.unscope(:limit, :offset)
|
79
|
+
|
80
|
+
per = ::CommandProposal::PAGINATION_PER
|
81
|
+
total_pages = (collection.count / per.to_f).ceil
|
82
|
+
current_page = params[:page].presence&.to_i || 1
|
83
|
+
|
84
|
+
return if total_pages <= 1
|
85
|
+
|
86
|
+
div(class: "cmd-pagination") do
|
87
|
+
links = []
|
88
|
+
links << ["<<", { page: 1 }] if current_page > 1
|
89
|
+
links << ["<", { page: current_page - 1 }] if current_page > 1
|
90
|
+
|
91
|
+
(current_page-2..current_page+2).each do |page_window|
|
92
|
+
next if page_window < 1
|
93
|
+
next if page_window > total_pages
|
94
|
+
|
95
|
+
links << [page_window, { page: page_window }]
|
96
|
+
end
|
97
|
+
|
98
|
+
links << [">", page: current_page + 1] if current_page < total_pages
|
99
|
+
links << [">>", page: total_pages] if current_page < total_pages
|
100
|
+
|
101
|
+
links.map do |link_text, link_params|
|
102
|
+
"<a class=\"cmd-pagination-link #{'current-page' if link_params[:page] == current_page}\" href=\"#{current_path(link_params)}\">#{link_text}</a>"
|
103
|
+
end.join("\n")
|
104
|
+
end
|
105
|
+
end
|
63
106
|
end
|
@@ -23,6 +23,7 @@ class ::CommandProposal::Iteration < ApplicationRecord
|
|
23
23
|
|
24
24
|
TRUNCATE_COUNT = 2000
|
25
25
|
# Also hardcoded in JS: app/assets/javascripts/command_proposal/console.js
|
26
|
+
PAGINATION_PER = 2
|
26
27
|
|
27
28
|
has_many :comments
|
28
29
|
belongs_to :task
|
@@ -40,6 +41,12 @@ class ::CommandProposal::Iteration < ApplicationRecord
|
|
40
41
|
terminated: 7, # Closed via server restart
|
41
42
|
}
|
42
43
|
|
44
|
+
scope :cmd_page, ->(page=nil) {
|
45
|
+
page = page.presence&.to_i || 1
|
46
|
+
per = ::CommandProposal::PAGINATION_PER
|
47
|
+
limit(per).offset(per * (page - 1))
|
48
|
+
}
|
49
|
+
|
43
50
|
delegate :name, to: :task
|
44
51
|
delegate :description, to: :task
|
45
52
|
delegate :session_type, to: :task
|
@@ -55,6 +62,10 @@ class ::CommandProposal::Iteration < ApplicationRecord
|
|
55
62
|
::CommandProposal::Task.module.where(friendly_id: bring_str.scan(/\s+\:(\w+),?/).flatten)
|
56
63
|
end
|
57
64
|
|
65
|
+
def primary_iteration?
|
66
|
+
task.primary_iteration == self
|
67
|
+
end
|
68
|
+
|
58
69
|
def complete?
|
59
70
|
success? || failed? || cancelled? || terminated?
|
60
71
|
end
|
@@ -15,12 +15,24 @@ class ::CommandProposal::Task < ApplicationRecord
|
|
15
15
|
scope :search, ->(text) {
|
16
16
|
where("name ILIKE :q OR description ILIKE :q", q: "%#{text}%")
|
17
17
|
}
|
18
|
+
scope :by_session, ->(filter) {
|
19
|
+
if filter.present?
|
20
|
+
where(session_type: filter) if filter.to_s.in?(session_types.keys)
|
21
|
+
else
|
22
|
+
where(session_type: :function)
|
23
|
+
end
|
24
|
+
}
|
25
|
+
scope :cmd_page, ->(page=nil) {
|
26
|
+
page = page.presence&.to_i || 1
|
27
|
+
per = ::CommandProposal::PAGINATION_PER
|
28
|
+
limit(per).offset(per * (page - 1))
|
29
|
+
}
|
18
30
|
|
19
31
|
enum session_type: {
|
20
|
-
# Task will have multiple iterations that are all essentially the same just with code changes
|
21
|
-
task: 0,
|
22
32
|
# Function iterations are much like tasks
|
23
33
|
function: 1,
|
34
|
+
# Task will have multiple iterations that are all essentially the same just with code changes
|
35
|
+
task: 0,
|
24
36
|
# Console iterations are actually line by line, so order matters
|
25
37
|
console: 2,
|
26
38
|
# Modules are included in tasks and not run independently
|
@@ -7,15 +7,12 @@
|
|
7
7
|
<!-- <th>Diff</th> -->
|
8
8
|
</thead>
|
9
9
|
<tbody>
|
10
|
-
<%
|
11
|
-
<%
|
10
|
+
<% paginated_iterations = @task.iterations.cmd_page(params[:page]) %>
|
11
|
+
<% paginated_iterations.order(created_at: :desc).each do |iteration| %>
|
12
12
|
<tr>
|
13
13
|
<td>
|
14
|
-
|
15
|
-
|
16
|
-
<% else %>
|
17
|
-
<%= link_to iteration.created_at.strftime("%b %-d, %Y at %H:%M"), cmd_path(@task, iteration: iteration.id) %>
|
18
|
-
<% end %>
|
14
|
+
<%= ">" if iteration == @iteration %>
|
15
|
+
<%= link_to iteration.created_at.strftime("%b %-d, %Y at %H:%M"), cmd_path(@task, iteration: iteration.id) %>
|
19
16
|
</td>
|
20
17
|
<td><%= iteration.status.capitalize %></td>
|
21
18
|
<!-- <td><%#= iteration.comments.count %></td> -->
|
@@ -24,4 +21,6 @@
|
|
24
21
|
<% end %>
|
25
22
|
</tbody>
|
26
23
|
</table>
|
24
|
+
|
25
|
+
<%= command_paginate paginated_iterations %>
|
27
26
|
<% end %>
|
@@ -1,9 +1,11 @@
|
|
1
1
|
<div class="cmd-wrapper">
|
2
|
-
|
2
|
+
<% filter_name = params[:filter].presence&.capitalize %>
|
3
|
+
<% filter_name = filter_name.blank? || filter_name == "All" ? "Command" : filter_name %>
|
4
|
+
<%= link_to "New #{filter_name}", cmd_path(:new, :task, session_type: params[:filter] || :task) %> <br>
|
3
5
|
<br>
|
4
|
-
<%= link_to "All",
|
6
|
+
<%= link_to "All", toggled_param(filter: :all), class: "cmd-tab #{:active if params[:filter] == "all"}"
|
5
7
|
%><% ::CommandProposal::Task.session_types.each_with_index do |(session_type, _session_enum), idx| %><%=
|
6
|
-
selected = params[:filter] == session_type.to_s
|
8
|
+
selected = params[:filter] == session_type.to_s || (!params.key?(:filter) && session_type == "function")
|
7
9
|
# Offset closing RB tags to fix spacing issues
|
8
10
|
link_to session_type.capitalize, toggled_param(filter: session_type), class: "cmd-tab #{:active if selected}"
|
9
11
|
%><% end %>
|
@@ -42,4 +44,6 @@
|
|
42
44
|
<% end %>
|
43
45
|
<% end %>
|
44
46
|
</div>
|
47
|
+
|
48
|
+
<%= command_paginate @tasks %>
|
45
49
|
</div>
|
@@ -76,7 +76,11 @@ module CommandProposal
|
|
76
76
|
|
77
77
|
def run
|
78
78
|
begin
|
79
|
-
|
79
|
+
params_str = ""
|
80
|
+
unless @iteration.task.console? # Don't bring params into the console
|
81
|
+
params_str = "params = #{@iteration.args || {}}.with_indifferent_access"
|
82
|
+
end
|
83
|
+
@session.eval("#{bring_function};#{params_str}")
|
80
84
|
rescue Exception => e # rubocop:disable Lint/RescueException - Yes, rescue full Exception so that we can catch typos in evals as well
|
81
85
|
return @iteration.result = results_from_exception(e)
|
82
86
|
end
|
@@ -88,7 +92,7 @@ module CommandProposal
|
|
88
92
|
|
89
93
|
running_thread = Thread.new do
|
90
94
|
begin
|
91
|
-
# Run bring functions in here so we can capture any string outputs
|
95
|
+
# Run `bring` functions in here so we can capture any string outputs
|
92
96
|
# OR! Run the full runner and instead of saving to an iteration, return the string for prepending here
|
93
97
|
result = @session.eval("_ = (#{@iteration.code})").inspect # rubocop:disable Security/Eval - Eval is scary, but in this case it's exactly what we need.
|
94
98
|
result = nil unless @iteration.task.console? # Only store final result for consoles
|
data/lib/command_proposal.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: command_proposal
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.13
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rocco Nicholls
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-01-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|