foreman-tasks 0.16.0 → 0.16.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. checksums.yaml +4 -4
  2. data/.babelrc +4 -1
  3. data/.eslintrc +4 -13
  4. data/app/assets/stylesheets/foreman_tasks/application.css.scss +0 -37
  5. data/app/controllers/foreman_tasks/api/tasks_controller.rb +9 -5
  6. data/app/controllers/foreman_tasks/tasks_controller.rb +23 -19
  7. data/app/helpers/foreman_tasks/foreman_tasks_helper.rb +28 -29
  8. data/app/lib/actions/bulk_action.rb +1 -1
  9. data/app/models/foreman_tasks/task.rb +1 -1
  10. data/app/models/foreman_tasks/task/dynflow_task.rb +30 -0
  11. data/app/services/foreman_tasks/troubleshooting_help_generator.rb +4 -0
  12. data/app/views/foreman_tasks/api/tasks/details.json.rabl +18 -0
  13. data/app/views/foreman_tasks/layouts/react.html.erb +1 -1
  14. data/app/views/foreman_tasks/tasks/index.html.erb +3 -0
  15. data/app/views/foreman_tasks/tasks/show.html.erb +10 -134
  16. data/config/routes.rb +3 -0
  17. data/lib/foreman_tasks/engine.rb +1 -1
  18. data/lib/foreman_tasks/tasks/export_tasks.rake +1 -2
  19. data/lib/foreman_tasks/version.rb +1 -1
  20. data/package.json +6 -20
  21. data/test/controllers/tasks_controller_test.rb +11 -0
  22. data/test/helpers/foreman_tasks/foreman_tasks_helper_test.rb +39 -0
  23. data/test/unit/actions/bulk_action_test.rb +2 -0
  24. data/test/unit/task_test.rb +4 -0
  25. data/webpack/ForemanTasks/Components/TaskDetails/Components/Errors.js +60 -0
  26. data/webpack/ForemanTasks/Components/TaskDetails/Components/Locks.js +46 -0
  27. data/webpack/ForemanTasks/Components/TaskDetails/Components/Raw.js +73 -0
  28. data/webpack/ForemanTasks/Components/TaskDetails/Components/RunningSteps.js +55 -0
  29. data/webpack/ForemanTasks/Components/TaskDetails/Components/Task.js +202 -0
  30. data/webpack/ForemanTasks/Components/TaskDetails/Components/TaskHelper.js +38 -0
  31. data/webpack/ForemanTasks/Components/TaskDetails/Components/TaskInfo.js +238 -0
  32. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/Errors.test.js +36 -0
  33. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/Locks.test.js +28 -0
  34. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/Raw.test.js +27 -0
  35. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/RunningSteps.test.js +29 -0
  36. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/Task.test.js +18 -0
  37. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/TaskHelper.test.js +77 -0
  38. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/TaskInfo.test.js +60 -0
  39. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/Errors.test.js.snap +77 -0
  40. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/Locks.test.js.snap +108 -0
  41. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/Raw.test.js.snap +174 -0
  42. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/RunningSteps.test.js.snap +62 -0
  43. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/Task.test.js.snap +282 -0
  44. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/TaskHelper.test.js.snap +37 -0
  45. data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/TaskInfo.test.js.snap +568 -0
  46. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetails.js +87 -0
  47. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetails.scss +63 -0
  48. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetails.stories.js +5 -0
  49. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsActions.js +109 -0
  50. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsConstants.js +18 -0
  51. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsReducer.js +44 -0
  52. data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsSelectors.js +83 -0
  53. data/webpack/ForemanTasks/Components/TaskDetails/TasksDetailsHelper.js +1 -0
  54. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/TaskDetails.test.js +12 -0
  55. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/TaskDetailsActions.test.js +20 -0
  56. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/TaskDetailsReducer.test.js +33 -0
  57. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/__snapshots__/TaskDetails.test.js.snap +97 -0
  58. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/__snapshots__/TaskDetailsActions.test.js.snap +43 -0
  59. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/__snapshots__/TaskDetailsReducer.test.js.snap +26 -0
  60. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/__snapshots__/integration.test.js.snap +122 -0
  61. data/webpack/ForemanTasks/Components/TaskDetails/__tests__/integration.test.js +63 -0
  62. data/webpack/ForemanTasks/Components/TaskDetails/index.js +77 -0
  63. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/PausedTasksCard/PausedTasksCard.js +6 -1
  64. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/PausedTasksCard/__snapshots__/PausedTasksCard.test.js.snap +2 -0
  65. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/RunningTasksCard/RunningTasksCard.js +6 -1
  66. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/RunningTasksCard/__snapshots__/RunningTasksCard.test.js.snap +2 -0
  67. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/ScheduledTasksCard/ScheduledTasksCard.js +3 -6
  68. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/ScheduledTasksCard/ScheduledTasksCard.scss +0 -3
  69. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/ScheduledTasksCard/__snapshots__/ScheduledTasksCard.test.js.snap +3 -0
  70. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCard.js +2 -0
  71. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCard.scss +0 -4
  72. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCardHelper.js +3 -3
  73. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/__snapshots__/StoppedTasksCard.test.js.snap +495 -54
  74. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutCard/TasksDonutCard.js +1 -0
  75. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutCard/TasksDonutCard.scss +6 -0
  76. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutChart/TasksDonutChart.scss +0 -3
  77. data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksLabelsRow/TasksLabelsRow.scss +1 -1
  78. data/webpack/ForemanTasks/Components/TasksDashboard/TasksDashboard.scss +2 -2
  79. data/webpack/ForemanTasks/Components/common/ClickConfirmation/index.js +83 -0
  80. data/webpack/ForemanTasks/ForemanTasksReducers.js +2 -0
  81. data/webpack/__mocks__/foremanReact/common/I18n.js +2 -0
  82. data/webpack/__mocks__/foremanReact/components/Layout/LayoutActions.js +2 -0
  83. data/webpack/index.js +5 -0
  84. metadata +46 -9
  85. data/app/views/foreman_tasks/tasks/_details.html.erb +0 -195
  86. data/app/views/foreman_tasks/tasks/_errors.html.erb +0 -42
  87. data/app/views/foreman_tasks/tasks/_locks.html.erb +0 -19
  88. data/app/views/foreman_tasks/tasks/_raw.html.erb +0 -28
  89. data/app/views/foreman_tasks/tasks/_running_steps.html.erb +0 -40
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a562e9a32057e45cbf20bcc2d511ee03580cee1181af686965683bccfc1d6f8e
4
- data.tar.gz: bcffaac1d9efb02ef8677394c7af554058aad577d5e1a7ce9b32c66ac21206f1
3
+ metadata.gz: 75231de648b74702c80ca64886f1d6c19caf3a7920d547807f892e130194cedb
4
+ data.tar.gz: bf5f7331818981dbf841c3a696e0e768bec3328b9e349df13532d1757bbe86a9
5
5
  SHA512:
6
- metadata.gz: e7acf7b281043c1ad3a3c0fcb45436258caf1f11a06295c5e4b69b43f8bbe5ea450d61e25346d638198c72596e1ac3e86fdad1eff2f092d4fc3254cb8e551d5f
7
- data.tar.gz: e5c9234ef7ccd241c17ef37892a79d04b6de918034d1e305093bea7b54ce125dce88cb1c9360f4a7dab1674eefbd00db20b3848a445ea297eeaab37c271cd855
6
+ metadata.gz: 8699acec8437f71f4fb52fb89a79dc96857cb08cd09375c7d33d9d4e72d67de8e95ee53352b14f1f80f1a62b880943df996d6fca16a666022ca030dcfdb4cd7d
7
+ data.tar.gz: fc3e36ab57cadf68fa033a4224890c2fdc71a76e18d782b0758cac2bef7748a2cc5e3f30b3f7a37641cb2b9f3ff8d1c79f3b2d2e90cfb0e2050381f04e2a7794
data/.babelrc CHANGED
@@ -13,11 +13,11 @@
13
13
  "transform-class-properties",
14
14
  "transform-object-rest-spread",
15
15
  "transform-object-assign",
16
- "lodash",
17
16
  "syntax-dynamic-import"
18
17
  ],
19
18
  "env": {
20
19
  "test": {
20
+ "presets": ["@theforeman/vendor-dev/babel.preset.js"],
21
21
  "plugins": [
22
22
  ["module-resolver", {
23
23
  "alias": {
@@ -27,6 +27,9 @@
27
27
  }],
28
28
  "dynamic-import-node"
29
29
  ]
30
+ },
31
+ "storybook": {
32
+ "presets": ["@theforeman/vendor-dev/babel.preset.js"]
30
33
  }
31
34
  }
32
35
  }
data/.eslintrc CHANGED
@@ -1,6 +1,9 @@
1
1
  {
2
2
  "plugins": ["patternfly-react"],
3
- "extends": ["plugin:patternfly-react/recommended"],
3
+ "extends": [
4
+ "plugin:patternfly-react/recommended",
5
+ "./node_modules/@theforeman/vendor-dev/eslint.extends.js"
6
+ ],
4
7
  "rules": {
5
8
  "prettier/prettier": ["error", {
6
9
  "singleQuote": true,
@@ -17,17 +20,5 @@
17
20
  "import/resolver": {
18
21
  "babel-module": {}
19
22
  }
20
- },
21
- "globals": {
22
- "document": false,
23
- "escape": false,
24
- "navigator": false,
25
- "unescape": false,
26
- "window": false,
27
- "$": true,
28
- "_": true,
29
- "__": true,
30
- "n__": true,
31
- "d3": true
32
23
  }
33
24
  }
@@ -12,43 +12,6 @@
12
12
  *= require_tree .
13
13
  */
14
14
 
15
- .spin {
16
- -webkit-animation: spin 1s infinite linear;
17
- -moz-animation: spin 1s infinite linear;
18
- -o-animation: spin 1s infinite linear;
19
- animation: spin 1s infinite linear;
20
- -webkit-transform-origin: 50% 50%;
21
- transform-origin: 50% 50%;
22
- -ms-transform-origin: 50% 50%; /* IE 9 */
23
- }
24
-
25
- @-moz-keyframes spin {
26
- from {
27
- -moz-transform: rotate(0deg);
28
- }
29
- to {
30
- -moz-transform: rotate(360deg);
31
- }
32
- }
33
-
34
- @-webkit-keyframes spin {
35
- from {
36
- -webkit-transform: rotate(0deg);
37
- }
38
- to {
39
- -webkit-transform: rotate(360deg);
40
- }
41
- }
42
-
43
- @keyframes spin {
44
- from {
45
- transform: rotate(0deg);
46
- }
47
- to {
48
- transform: rotate(360deg);
49
- }
50
- }
51
-
52
15
  div.form-group div.trigger_fields {
53
16
  margin-top: 15px;
54
17
  }
@@ -16,7 +16,7 @@ module ForemanTasks
16
16
  class BadRequest < Apipie::ParamError
17
17
  end
18
18
 
19
- before_action :find_task, :only => [:show]
19
+ before_action :find_task, :only => [:show, :details]
20
20
 
21
21
  api :GET, '/tasks/summary', 'Show task summary'
22
22
  def summary
@@ -27,6 +27,10 @@ module ForemanTasks
27
27
  param :id, :identifier, desc: 'UUID of the task'
28
28
  def show; end
29
29
 
30
+ api :GET, '/tasks/:id/details', 'Show task extended details'
31
+ param :id, :identifier, desc: 'UUID of the task'
32
+ def details; end
33
+
30
34
  api :POST, '/tasks/bulk_search', 'List dynflow tasks for uuids'
31
35
  param :searches, Array, :desc => 'List of uuids to fetch info about' do
32
36
  param :search_id, String, :desc => <<-DESC
@@ -117,10 +121,10 @@ module ForemanTasks
117
121
  param :order, String, :desc => N_('How to order the sorted results (e.g. ASC for ascending)')
118
122
  end
119
123
  def index
120
- scope = resource_scope.search_for(params[:search]).select('DISTINCT foreman_tasks_tasks.*')
121
-
122
124
  total = resource_scope.count
123
- subtotal = scope.count
125
+ subtotal = resource_scope.search_for(params[:search]).select('DISTINCT foreman_tasks_tasks.id').count
126
+
127
+ scope = resource_scope.search_for(params[:search]).select('DISTINCT foreman_tasks_tasks.*')
124
128
 
125
129
  ordering_params = {
126
130
  sort_by: params[:sort_by] || 'started_at',
@@ -276,7 +280,7 @@ module ForemanTasks
276
280
 
277
281
  def action_permission
278
282
  case params[:action]
279
- when 'bulk_search', 'summary'
283
+ when 'bulk_search', 'summary', 'details'
280
284
  :view
281
285
  when 'bulk_resume'
282
286
  :edit
@@ -12,16 +12,7 @@ module ForemanTasks
12
12
 
13
13
  def index
14
14
  params[:order] ||= 'started_at DESC'
15
- respond_to do |format|
16
- format.html do
17
- @tasks = filter(resource_base)
18
- render :index, layout: !request.xhr?
19
- end
20
- format.csv do
21
- @tasks = filter(resource_base, paginate: false)
22
- csv_response(@tasks, [:id, :action, :state, :result, 'started_at.in_time_zone', 'ended_at.in_time_zone', :username], ['Id', 'Action', 'State', 'Result', 'Started At', 'Ended At', 'User'])
23
- end
24
- end
15
+ respond_with_tasks resource_base
25
16
  end
26
17
 
27
18
  def summary
@@ -29,14 +20,14 @@ module ForemanTasks
29
20
  end
30
21
 
31
22
  def sub_tasks
32
- task = resource_base.find(params[:id])
33
- @tasks = filter(task.sub_tasks)
34
- render :index
23
+ # @task is used when rendering breadcrumbs
24
+ @task = resource_base.find(params[:id])
25
+ respond_with_tasks @task.sub_tasks
35
26
  end
36
27
 
37
28
  def cancel_step
38
29
  task = find_dynflow_task
39
- flash[:notice] = _('Trying to cancel step %s') % params[:step_id]
30
+ flash[:info] = _('Trying to cancel step %s') % params[:step_id]
40
31
  ForemanTasks.dynflow.world.event(task.external_id, params[:step_id].to_i, ::Dynflow::Action::Cancellable::Cancel).wait
41
32
  redirect_to foreman_tasks_task_path(task)
42
33
  end
@@ -44,7 +35,7 @@ module ForemanTasks
44
35
  def cancel
45
36
  task = find_dynflow_task
46
37
  if task.cancel
47
- flash[:notice] = _('Trying to cancel the task')
38
+ flash[:info] = _('Trying to cancel the task')
48
39
  else
49
40
  flash[:warning] = _('The task cannot be cancelled at the moment.')
50
41
  end
@@ -54,7 +45,7 @@ module ForemanTasks
54
45
  def abort
55
46
  task = find_dynflow_task
56
47
  if task.abort
57
- flash[:notice] = _('Trying to abort the task')
48
+ flash[:info] = _('Trying to abort the task')
58
49
  else
59
50
  flash[:warning] = _('The task cannot be aborted at the moment.')
60
51
  end
@@ -65,7 +56,7 @@ module ForemanTasks
65
56
  task = find_dynflow_task
66
57
  if task.resumable?
67
58
  ForemanTasks.dynflow.world.execute(task.execution_plan.id)
68
- flash[:notice] = _('The execution was resumed.')
59
+ flash[:info] = _('The execution was resumed.')
69
60
  else
70
61
  flash[:warning] = _('The execution has to be resumable.')
71
62
  end
@@ -77,7 +68,7 @@ module ForemanTasks
77
68
  if task.paused?
78
69
  task.state = :stopped
79
70
  task.save!
80
- flash[:notice] = _('The task resources were unlocked.')
71
+ flash[:info] = _('The task resources were unlocked.')
81
72
  else
82
73
  flash[:warning] = _('The execution has to be paused.')
83
74
  end
@@ -88,7 +79,7 @@ module ForemanTasks
88
79
  task = find_dynflow_task
89
80
  task.state = :stopped
90
81
  task.save!
91
- flash[:notice] = _('The task resources were unlocked with force.')
82
+ flash[:info] = _('The task resources were unlocked with force.')
92
83
  redirect_back(:fallback_location => foreman_tasks_task_path(task))
93
84
  end
94
85
 
@@ -103,6 +94,19 @@ module ForemanTasks
103
94
 
104
95
  private
105
96
 
97
+ def respond_with_tasks(scope)
98
+ respond_to do |format|
99
+ format.html do
100
+ @tasks = filter(scope)
101
+ render :index, layout: !request.xhr?
102
+ end
103
+ format.csv do
104
+ @tasks = filter(scope, paginate: false)
105
+ csv_response(@tasks, [:id, :action, :state, :result, 'started_at.in_time_zone', 'ended_at.in_time_zone', :username], ['Id', 'Action', 'State', 'Result', 'Started At', 'Ended At', 'User'])
106
+ end
107
+ end
108
+ end
109
+
106
110
  def restrict_dangerous_actions
107
111
  render_403 unless Setting['dynflow_allow_dangerous_actions']
108
112
  end
@@ -25,38 +25,17 @@ module ForemanTasks
25
25
  ret.html_safe
26
26
  end
27
27
 
28
- def task_result_icon_class(task)
29
- return 'task-status pficon-help' if task.state != 'stopped'
30
-
31
- icon_class = case task.result
32
- when 'success'
33
- 'pficon-ok'
34
- when 'error'
35
- 'pficon-error-circle-o'
36
- when 'warning'
37
- 'pficon-ok status-warn'
38
- else
39
- 'pficon-help'
40
- end
41
-
42
- "task-status #{icon_class}"
43
- end
44
-
45
- def time_in_words_span(time)
46
- if time.nil?
47
- _('N/A')
48
- else
49
- content_tag :span, (time > Time.now.utc ? _('in %s') : _('%s ago')) % time_ago_in_words(time),
50
- :'data-original-title' => time.try(:in_time_zone), :rel => 'twipsy'
51
- end
28
+ def troubleshooting_info_text
29
+ return if @task.state != 'paused' || @task.main_action.nil?
30
+ helper = TroubleshootingHelpGenerator.new(@task.main_action)
31
+ helper.generate_text
52
32
  end
53
33
 
54
- def duration_in_words_span(start, finish)
55
- if start.nil?
56
- _('N/A')
34
+ def username_link_task(owner, username)
35
+ if owner.present? && username != User::ANONYMOUS_API_ADMIN && username != User::ANONYMOUS_ADMIN
36
+ link_to_if_authorized(username, hash_for_edit_user_path(owner))
57
37
  else
58
- content_tag :span, distance_of_time_in_words(start, finish),
59
- :'data-original-title' => number_with_delimiter((finish - start).to_i) + _(' seconds'), :rel => 'twipsy'
38
+ username
60
39
  end
61
40
  end
62
41
 
@@ -122,6 +101,26 @@ module ForemanTasks
122
101
  render :partial => 'common/trigger_form', :locals => { :f => f, :triggering => triggering }
123
102
  end
124
103
 
104
+ def task_breadcrumb_item(task, active = false)
105
+ item = { :caption => format_task_input(task) }
106
+ item[:url] = url_for(foreman_tasks_task_path(task.id)) unless active
107
+ item
108
+ end
109
+
110
+ def index_breadcrumb_item
111
+ item = { :caption => _('Tasks') }
112
+ item[:url] = foreman_tasks_tasks_url if action_name != 'index'
113
+ item
114
+ end
115
+
116
+ def breadcrumb_items
117
+ items = [index_breadcrumb_item]
118
+ return items if action_name == 'index'
119
+ items << task_breadcrumb_item(@task, action_name == 'show')
120
+ items << { :caption => _('Sub tasks') } if action_name == 'sub_tasks'
121
+ items
122
+ end
123
+
125
124
  private
126
125
 
127
126
  def future_mode_fieldset(f, triggering)
@@ -46,7 +46,7 @@ module Actions
46
46
  def create_sub_plans
47
47
  action_class = input[:action_class].constantize
48
48
  target_class = input[:target_class].constantize
49
- targets = target_class.where(:id => current_batch)
49
+ targets = target_class.unscoped.where(:id => current_batch)
50
50
 
51
51
  missing = Array.new((current_batch - targets.map(&:id)).count) { nil }
52
52
 
@@ -77,7 +77,7 @@ module ForemanTasks
77
77
  end
78
78
 
79
79
  def username
80
- owner
80
+ owner.try(:login)
81
81
  end
82
82
 
83
83
  def execution_type
@@ -99,6 +99,36 @@ module ForemanTasks
99
99
  execution_plan.try(:steps_in_state, :running, :suspended) || []
100
100
  end
101
101
 
102
+ def input_output_failed_steps
103
+ failed_steps.map do |f|
104
+ begin
105
+ f_action = f.action(execution_plan)
106
+ {
107
+ error: ({ exception_class: f.error.exception_class, message: f.error.message, backtrace: f.error.backtrace } if f.error),
108
+ action_class: f.action_class.name,
109
+ state: f.state,
110
+ input: f_action.input.pretty_inspect,
111
+ output: f_action.output.pretty_inspect
112
+ }
113
+ end
114
+ end
115
+ end
116
+
117
+ def input_output_running_steps
118
+ running_steps.map do |f|
119
+ begin
120
+ f_action = f.action(execution_plan)
121
+ {
122
+ action_class: f.action_class.name,
123
+ state: f.state,
124
+ input: f_action.input.pretty_inspect,
125
+ output: f_action.output.pretty_inspect,
126
+ cancellable: cancellable_action?(f_action)
127
+ }
128
+ end
129
+ end
130
+ end
131
+
102
132
  def humanized
103
133
  { action: get_humanized(:humanized_name),
104
134
  input: get_humanized(:humanized_input),
@@ -44,6 +44,10 @@ module ForemanTasks
44
44
  # rubocop:enable Rails/OutputSafety
45
45
  end
46
46
 
47
+ def generate_text
48
+ (description + link_descriptions_html).join("\n")
49
+ end
50
+
47
51
  def link_descriptions_html
48
52
  links.map do |link|
49
53
  link.description % { link: %(<a href="%{href}">%{title}</a>) % link.to_h }
@@ -0,0 +1,18 @@
1
+ object @task if @task
2
+
3
+ extends 'foreman_tasks/api/tasks/show'
4
+
5
+ attributes :parent_task_id, :start_at, :start_before, :external_id
6
+ node(:action) { @task.action }
7
+ node(:execution_plan) { { state: @task.execution_plan.state, cancellable: @task.execution_plan.cancellable? } }
8
+ node(:failed_steps) { @task.input_output_failed_steps }
9
+ node(:running_steps) { @task.input_output_running_steps }
10
+ node(:help) { troubleshooting_info_text }
11
+ node(:has_sub_tasks) { @task.sub_tasks.any? }
12
+ node(:allowDangerousActions) { Setting['dynflow_allow_dangerous_actions'] }
13
+ node(:locks) do
14
+ @task.locks.map do |lock|
15
+ { name: lock.name, exclusive: lock.exclusive, resource_type: lock.resource_type, resource_id: lock.resource_id }
16
+ end
17
+ end
18
+ node(:username_path) { username_link_task(@task.owner, @task.username) }
@@ -9,4 +9,4 @@
9
9
  <div id="foremanTasksReactRoot"></div>
10
10
  <% end %>
11
11
  <%= render file: "layouts/base" %>
12
- <%= mount_react_component('ForemanTasks', '#foremanTasksReactRoot') %>
12
+ <%= mount_react_component('ForemanTasks', '#foremanTasksReactRoot',{ :flatten_data => true }) %>
@@ -10,6 +10,9 @@
10
10
  yo: 'ya'
11
11
  }.to_json) %>
12
12
  <% end %>
13
+ <% content_for(:breadcrumbs) do %>
14
+ <% breadcrumbs(:items => breadcrumb_items) %>
15
+ <% end %>
13
16
 
14
17
  <% title _("Tasks") %>
15
18
  <% title_actions csv_link, help_button %>
@@ -1,144 +1,20 @@
1
1
  <% stylesheet 'foreman_tasks/tasks' %>
2
-
2
+ <% content_for(:javascripts) do %>
3
+ <%= webpacked_plugins_js_for :'foreman-tasks' %>
4
+ <% end %>
5
+ <% content_for(:stylesheets) do %>
6
+ <%= webpacked_plugins_css_for :'foreman-tasks' %>
7
+ <% end %>
3
8
  <%= breadcrumbs(
4
- items: [
5
- {
6
- caption: _('Tasks'),
7
- url: url_for(foreman_tasks_tasks_path)
8
- },
9
- {
10
- caption: format_task_input(@task)
11
- }
12
- ],
9
+ items: breadcrumb_items,
13
10
  name_field: 'action',
14
11
  resource_url: foreman_tasks_api_tasks_path,
15
12
  switcher_item_url: foreman_tasks_task_path(:id => ':id')
16
13
  ) %>
17
14
 
18
15
 
19
- <div class="task-details">
20
- <script>
21
- if (typeof taskProgressReloader === 'undefined') {
22
- var taskProgressReloader = {
23
- timeoutId: null,
24
- formId: null,
25
- reload: function () {
26
- tfm.tools.showSpinner();
27
- taskProgressReloader.timeoutId = null;
28
- taskProgressReloader.formId = null;
29
-
30
- $.ajax({
31
- type:'GET',
32
- url: document.location.href,
33
- headers: {"X-Foreman-Layout": "two-pane"},
34
- success: function(response){
35
- $('#content .task-details').replaceWith($(response));
36
- },
37
- error: function(response){
38
- document.location.reload();
39
- },
40
- complete: function(){
41
- tfm.tools.hideSpinner();
42
- }
43
- });
44
- },
45
-
46
- start: function () {
47
- var button = $('.reload-button');
48
- if (!taskProgressReloader.timeoutId) {
49
- taskProgressReloader.timeoutId = setTimeout(this.reload, 5000);
50
- taskProgressReloader.formId = $(button).closest('form')[0].id;
51
- }
52
- button.html('<span class="glyphicon glyphicon-refresh spin"></span> <%= _('Stop auto-reloading') %>');
53
- button.show();
54
- },
55
-
56
- stop: function () {
57
- if (taskProgressReloader.timeoutId) {
58
- clearTimeout(taskProgressReloader.timeoutId);
59
- }
60
- taskProgressReloader.timeoutId = null;
61
- taskProgressReloader.formId = null;
62
- var button = $('.reload-button');
63
- button.html('<span class="glyphicon glyphicon-refresh"></span> <%= _('Start auto-reloading') %>');
64
- button.show();
65
- },
66
-
67
- toggle: function () {
68
- if (taskProgressReloader.timeoutId) {
69
- this.stop();
70
- } else {
71
- this.start();
72
- }
73
- }
74
- };
75
- }
76
-
77
- $(document).ready(function () {
78
- $('.modal-submit').click(function(e){
79
- if($(this).hasClass('disabled')){
80
- e.preventDefault();
81
- }
82
- });
83
- $('.disable-unlock').click(function() {
84
- var button = $(this).parents('.modal').find('.modal-submit');
85
-
86
- if($(this).is(':checked')){
87
- button.removeClass('disabled')
88
- }
89
- else{
90
- button.addClass('disabled')
91
- }
92
- });
93
-
94
- $('.reload-button').click(function (event) {
95
- taskProgressReloader.toggle();
96
- event.preventDefault();
97
- });
98
-
99
- $('.reload-button-stop').click(function (event) {
100
- taskProgressReloader.stop();
101
- });
102
-
103
- $('ul.nav-tabs a' ).click(function (event) {
104
- taskProgressReloader.stop();
105
- });
106
-
107
- <% if @task.state != 'stopped' %>
108
- taskProgressReloader.start();
109
- <% else %>
110
- taskProgressReloader.stop();
111
- <% end %>
112
- });
113
- </script>
114
-
115
-
116
- <%= form_for @task, :url => "#" do %>
117
-
118
- <ul class="nav nav-tabs" data-tabs="tabs">
119
- <li class="active"><a href="#primary" data-toggle="tab"><%= _("Task") %></a></li>
120
- <li><a href="#running-steps" data-toggle="tab"><%= _("Running Steps") %></a></li>
121
- <li><a href="#errors" data-toggle="tab"><%= _("Errors") %></a></li>
122
- <li><a href="#locks" data-toggle="tab"><%= _("Locks") %></a></li>
123
- <li><a href="#raw" data-toggle="tab"><%= _("Raw") %></a></li>
124
- </ul>
16
+ <div class="task-details" id="foremanTaskDetails">
17
+ </div>
125
18
 
126
- <div class="tab-content">
127
- <div class="tab-pane active" id="primary">
128
- <%= render :partial => 'details' %>
129
- </div>
130
- <div class="tab-pane" id="running-steps">
131
- <%= render :partial => 'running_steps' %>
132
- </div>
133
- <div class="tab-pane" id="errors">
134
- <%= render :partial => 'errors' %>
135
- </div>
136
- <div class="tab-pane" id="raw">
137
- <%= render :partial => 'raw' %>
138
- </div>
139
- <div class="tab-pane" id="locks">
140
- <%= render :partial => 'locks' %>
141
- </div>
142
19
 
143
- <% end %>
144
- </div>
20
+ <%= mount_react_component('TaskDetails', '#foremanTaskDetails') %>