foreman-tasks 0.16.0 → 0.16.1

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.
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') %>