command_proposal 1.0.12 → 1.0.13

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: ab0271a9e0e80bf0df78d8284cc8e13d292ef2254ab57180b1434f50b351dcb7
4
- data.tar.gz: 21b077ee6cfa9ede8ea83315523297ff9268bf5236de797c9f3acae9f1ef3910
3
+ metadata.gz: d57823efe2c4175b2786f8346a67ea68e96804bc980f06fc4afb0feb30a8dc9a
4
+ data.tar.gz: 212e7e868bf94fe559701ee696fc5487a9a17bcc3b549f35880843d8564f927d
5
5
  SHA512:
6
- metadata.gz: 52a46842e394c99d8dbb4527c222ab93e93dc437992996b3b9af3850a9bc6571bac4e472268c7f821d6b541c17074d21954d0b18e5e15d2109141a4f04179491
7
- data.tar.gz: eb670b929efd2d6c612997e569276fac67aa494325db38d357a5589496bdba19b0d5335d68696d715022b45e9ed13eae4e2245d4ddc12f53371ad3d611e4987b
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
- # in-sync
37
- runner.execute(@iteration)
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.where(session_type: params[:filter]) if params[:filter].present?
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(session_type: params[:session_type])
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
- <% primary_iteration = @task.primary_iteration %>
11
- <% @task.iterations.where.not(id: @iteration&.id).order(created_at: :desc).each do |iteration| %>
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
- <% if iteration.id == primary_iteration&.id %>
15
- <%= link_to iteration.created_at.strftime("%b %-d, %Y at %H:%M"), cmd_path(@task) %>
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
- <%= link_to "New #{params[:filter].presence&.capitalize || 'Command'}", cmd_path(:new, :task, session_type: params[:filter] || :task) %> <br>
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", cmd_path(:tasks, current_params.except(:filter)), class: "cmd-tab #{:active unless params.key?(:filter)}"
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
- @session.eval("#{bring_function};params = #{@iteration.args || {}}.with_indifferent_access")
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
@@ -1,3 +1,3 @@
1
1
  module CommandProposal
2
- VERSION = "1.0.12"
2
+ VERSION = "1.0.13"
3
3
  end
@@ -6,6 +6,8 @@ require "command_proposal/services/shut_down"
6
6
 
7
7
  module CommandProposal
8
8
  class Error < StandardError; end
9
+ PAGINATION_PER = 10
10
+
9
11
  def self.sessions
10
12
  @sessions ||= {}
11
13
  end
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.12
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: 2021-10-26 00:00:00.000000000 Z
11
+ date: 2022-01-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails