foreman-tasks 2.0.3 → 3.0.0
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 +4 -4
- data/.github/workflows/js_tests.yml +27 -0
- data/.github/workflows/ruby_tests.yml +74 -0
- data/.rubocop.yml +12 -4
- data/.rubocop_todo.yml +32 -25
- data/Gemfile +5 -0
- data/app/controllers/foreman_tasks/api/tasks_controller.rb +31 -58
- data/app/controllers/foreman_tasks/concerns/parameters/triggering.rb +1 -1
- data/app/controllers/foreman_tasks/recurring_logics_controller.rb +7 -0
- data/app/helpers/foreman_tasks/foreman_tasks_helper.rb +3 -3
- data/app/models/foreman_tasks/recurring_logic.rb +4 -4
- data/app/models/foreman_tasks/task.rb +11 -0
- data/app/models/foreman_tasks/task/dynflow_task.rb +27 -33
- data/app/models/foreman_tasks/task/status_explicator.rb +1 -1
- data/app/models/foreman_tasks/triggering.rb +1 -1
- data/app/models/setting/foreman_tasks.rb +1 -1
- data/app/views/foreman_tasks/api/tasks/index.json.rabl +2 -0
- data/app/views/foreman_tasks/recurring_logics/index.html.erb +3 -1
- data/config/routes.rb +2 -1
- data/db/migrate/20200517215015_rename_bookmarks_controller.rb +2 -2
- data/db/seeds.d/30-notification_blueprints.rb +7 -7
- data/db/seeds.d/61-foreman_tasks_bookmarks.rb +1 -1
- data/lib/foreman_tasks/cleaner.rb +4 -6
- data/lib/foreman_tasks/dynflow/configuration.rb +1 -1
- data/lib/foreman_tasks/dynflow/persistence.rb +4 -6
- data/lib/foreman_tasks/engine.rb +2 -2
- data/lib/foreman_tasks/version.rb +1 -1
- data/package.json +0 -1
- data/test/controllers/api/recurring_logics_controller_test.rb +1 -1
- data/test/controllers/api/tasks_controller_test.rb +7 -7
- data/test/controllers/tasks_controller_test.rb +6 -6
- data/test/core/unit/runner_test.rb +20 -20
- data/test/core/unit/task_launcher_test.rb +8 -8
- data/test/helpers/foreman_tasks/foreman_tasks_helper_test.rb +7 -7
- data/test/helpers/foreman_tasks/tasks_helper_test.rb +3 -3
- data/test/lib/actions/middleware/keep_current_request_id_test.rb +3 -3
- data/test/support/history_tasks_builder.rb +1 -1
- data/test/tasks/generate_task_actions_test.rb +1 -1
- data/test/unit/actions/action_with_sub_plans_test.rb +2 -2
- data/test/unit/actions/bulk_action_test.rb +6 -6
- data/test/unit/actions/proxy_action_test.rb +20 -20
- data/test/unit/actions/recurring_action_test.rb +30 -32
- data/test/unit/cleaner_test.rb +24 -24
- data/test/unit/dashboard_table_filter_test.rb +5 -5
- data/test/unit/otp_manager_test.rb +2 -2
- data/test/unit/proxy_selector_test.rb +9 -9
- data/test/unit/recurring_logic_test.rb +32 -38
- data/test/unit/remote_task_test.rb +2 -2
- data/test/unit/task_groups_test.rb +4 -4
- data/test/unit/task_test.rb +18 -18
- data/test/unit/triggering_test.rb +8 -8
- data/test/unit/troubleshooting_help_generator_test.rb +6 -6
- data/test/unit/ui_notifications_test.rb +11 -11
- data/webpack/ForemanTasks/Components/TaskDetails/Components/RunningSteps.js +3 -3
- data/webpack/ForemanTasks/Components/TaskDetails/Components/Task.js +8 -157
- data/webpack/ForemanTasks/Components/TaskDetails/Components/TaskButtons.js +168 -0
- data/webpack/ForemanTasks/Components/TaskDetails/Components/TaskInfo.js +6 -7
- data/webpack/ForemanTasks/Components/TaskDetails/Components/TaskSkeleton.js +48 -0
- data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/RunningSteps.test.js +1 -1
- data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/Task.test.js +12 -70
- data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/TaskButtons.test.js +95 -0
- data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/Task.test.js.snap +78 -225
- data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/TaskButtons.test.js.snap +212 -0
- data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/TaskInfo.test.js.snap +8 -4
- data/webpack/ForemanTasks/Components/TaskDetails/TaskDetails.js +87 -70
- data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsActions.js +48 -125
- data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsConstants.js +3 -16
- data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsSelectors.js +55 -29
- data/webpack/ForemanTasks/Components/TaskDetails/__tests__/TaskDetails.fixtures.js +2 -2
- data/webpack/ForemanTasks/Components/TaskDetails/__tests__/TaskDetails.test.js +6 -0
- data/webpack/ForemanTasks/Components/TaskDetails/__tests__/TaskDetailsActions.test.js +2 -18
- data/webpack/ForemanTasks/Components/TaskDetails/__tests__/__snapshots__/TaskDetails.test.js.snap +77 -27
- data/webpack/ForemanTasks/Components/TaskDetails/__tests__/__snapshots__/TaskDetailsActions.test.js.snap +14 -101
- data/webpack/ForemanTasks/Components/TaskDetails/index.js +6 -3
- data/webpack/ForemanTasks/Components/common/urlHelpers.js +7 -0
- data/webpack/ForemanTasks/ForemanTasksReducers.js +0 -2
- data/webpack/__mocks__/foremanReact/common/helpers.js +2 -0
- data/webpack/__mocks__/foremanReact/redux/API/APISelectors.js +10 -0
- data/webpack/__mocks__/foremanReact/redux/API/index.js +10 -0
- data/webpack/__mocks__/foremanReact/redux/middlewares/IntervalMiddleware.js +5 -0
- metadata +17 -14
- data/.travis.yml +0 -7
- data/script/travis_run_js_tests.sh +0 -7
- data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsReducer.js +0 -38
- data/webpack/ForemanTasks/Components/TaskDetails/__tests__/TaskDetailsReducer.test.js +0 -33
- data/webpack/ForemanTasks/Components/TaskDetails/__tests__/__snapshots__/TaskDetailsReducer.test.js.snap +0 -26
- data/webpack/ForemanTasks/Components/TaskDetails/__tests__/__snapshots__/integration.test.js.snap +0 -122
- data/webpack/ForemanTasks/Components/TaskDetails/__tests__/integration.test.js +0 -72
- data/webpack/__mocks__/foremanReact/redux/API.js +0 -7
|
@@ -29,8 +29,8 @@ module ForemanTasks
|
|
|
29
29
|
|
|
30
30
|
it 'generates html from the main action troubleshooting_info' do
|
|
31
31
|
generated_html = subject.generate_html
|
|
32
|
-
generated_html.must_include "A paused task represents a process that has not finished properly"
|
|
33
|
-
generated_html.must_include %(See <a href="#{expected_troubleshooting_url}">troubleshooting documentation</a> for more details on how to resolve the issue)
|
|
32
|
+
_(generated_html).must_include "A paused task represents a process that has not finished properly"
|
|
33
|
+
_(generated_html).must_include %(See <a href="#{expected_troubleshooting_url}">troubleshooting documentation</a> for more details on how to resolve the issue)
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
it 'exposes link details' do
|
|
@@ -48,10 +48,10 @@ module ForemanTasks
|
|
|
48
48
|
|
|
49
49
|
it 'includes additional description in generated html' do
|
|
50
50
|
generated_html = subject.generate_html
|
|
51
|
-
generated_html.must_include 'A paused task represents a process that has not finished properly'
|
|
52
|
-
generated_html.must_match %r{See <a href=".*">troubleshooting documentation</a> for more details on how to resolve the issue}
|
|
53
|
-
generated_html.must_include 'This task requires special handling'
|
|
54
|
-
generated_html.must_include 'Investigate <a href="/additional_troubleshooting_page">custom link</a> on more details for this custom error'
|
|
51
|
+
_(generated_html).must_include 'A paused task represents a process that has not finished properly'
|
|
52
|
+
_(generated_html).must_match %r{See <a href=".*">troubleshooting documentation</a> for more details on how to resolve the issue}
|
|
53
|
+
_(generated_html).must_include 'This task requires special handling'
|
|
54
|
+
_(generated_html).must_include 'Investigate <a href="/additional_troubleshooting_page">custom link</a> on more details for this custom error'
|
|
55
55
|
end
|
|
56
56
|
|
|
57
57
|
it 'includes additional links' do
|
|
@@ -23,11 +23,11 @@ module ForemanTasks
|
|
|
23
23
|
it 'notifies all admins about current amount of paused tasks when some paused task occurs' do
|
|
24
24
|
trigger_task
|
|
25
25
|
notification = user_notifications(admin_user).first
|
|
26
|
-
notification.message.must_equal "There is 1 paused task in the system that need attention"
|
|
26
|
+
_(notification.message).must_equal "There is 1 paused task in the system that need attention"
|
|
27
27
|
links = notification.actions['links']
|
|
28
|
-
links.must_include('href' => '/foreman_tasks/tasks?search=state%3Dpaused',
|
|
28
|
+
_(links).must_include('href' => '/foreman_tasks/tasks?search=state%3Dpaused',
|
|
29
29
|
'title' => 'List of tasks')
|
|
30
|
-
links.must_include('name' => 'troubleshooting',
|
|
30
|
+
_(links).must_include('name' => 'troubleshooting',
|
|
31
31
|
'title' => 'Troubleshooting Documentation',
|
|
32
32
|
'description' => 'See %{link} for more details on how to resolve the issue',
|
|
33
33
|
'href' => "https://theforeman.org/manuals/#{SETTINGS[:version].short}/tasks_troubleshooting.html#",
|
|
@@ -37,19 +37,19 @@ module ForemanTasks
|
|
|
37
37
|
it 'aggregates the notification when multiple tasks get paused' do
|
|
38
38
|
trigger_task
|
|
39
39
|
recipient1 = NotificationRecipient.find_by(user_id: admin_user)
|
|
40
|
-
recipient1.notification.message.must_match(/1 paused task/)
|
|
40
|
+
_(recipient1.notification.message).must_match(/1 paused task/)
|
|
41
41
|
|
|
42
42
|
new_admin_user = FactoryBot.create(:user, :admin)
|
|
43
43
|
|
|
44
44
|
trigger_task
|
|
45
45
|
|
|
46
|
-
NotificationRecipient.find_by(id: recipient1.id).must_be_nil
|
|
47
|
-
Notification.find_by(id: recipient1.notification.id).must_be_nil
|
|
46
|
+
_(NotificationRecipient.find_by(id: recipient1.id)).must_be_nil
|
|
47
|
+
_(Notification.find_by(id: recipient1.notification.id)).must_be_nil
|
|
48
48
|
recipient2 = NotificationRecipient.find_by(user_id: admin_user)
|
|
49
|
-
recipient2.notification.message.must_match(/2 paused tasks/)
|
|
49
|
+
_(recipient2.notification.message).must_match(/2 paused tasks/)
|
|
50
50
|
|
|
51
51
|
new_recipient = NotificationRecipient.find_by(user_id: new_admin_user)
|
|
52
|
-
new_recipient.notification.must_equal recipient2.notification
|
|
52
|
+
_(new_recipient.notification).must_equal recipient2.notification
|
|
53
53
|
end
|
|
54
54
|
end
|
|
55
55
|
|
|
@@ -59,11 +59,11 @@ module ForemanTasks
|
|
|
59
59
|
notifications = user_notifications(task_owner)
|
|
60
60
|
assert_equal 1, notifications.size, 'Only notification for the main action should be triggered'
|
|
61
61
|
notification = notifications.first
|
|
62
|
-
notification.message.must_equal "The task 'Dummy pause action' got paused"
|
|
62
|
+
_(notification.message).must_equal "The task 'Dummy pause action' got paused"
|
|
63
63
|
links = notification.actions['links']
|
|
64
|
-
links.must_include("href" => "/foreman_tasks/tasks/#{task.id}",
|
|
64
|
+
_(links).must_include("href" => "/foreman_tasks/tasks/#{task.id}",
|
|
65
65
|
"title" => "Task Details")
|
|
66
|
-
links.must_include('name' => 'troubleshooting',
|
|
66
|
+
_(links).must_include('name' => 'troubleshooting',
|
|
67
67
|
'title' => 'Troubleshooting Documentation',
|
|
68
68
|
'description' => 'See %{link} for more details on how to resolve the issue',
|
|
69
69
|
'href' => "https://theforeman.org/manuals/#{SETTINGS[:version].short}/tasks_troubleshooting.html#Support::DummyPauseAction",
|
|
@@ -8,7 +8,7 @@ const RunningSteps = ({
|
|
|
8
8
|
id,
|
|
9
9
|
cancelStep,
|
|
10
10
|
taskReload,
|
|
11
|
-
|
|
11
|
+
taskReloadStart,
|
|
12
12
|
}) => {
|
|
13
13
|
if (!runningSteps.length) return <span>{__('No running steps')}</span>;
|
|
14
14
|
return (
|
|
@@ -21,7 +21,7 @@ const RunningSteps = ({
|
|
|
21
21
|
bsSize="small"
|
|
22
22
|
onClick={() => {
|
|
23
23
|
if (!taskReload) {
|
|
24
|
-
|
|
24
|
+
taskReloadStart(id);
|
|
25
25
|
}
|
|
26
26
|
cancelStep(id, step.id);
|
|
27
27
|
}}
|
|
@@ -59,7 +59,7 @@ RunningSteps.propTypes = {
|
|
|
59
59
|
id: PropTypes.string.isRequired,
|
|
60
60
|
cancelStep: PropTypes.func.isRequired,
|
|
61
61
|
taskReload: PropTypes.bool.isRequired,
|
|
62
|
-
|
|
62
|
+
taskReloadStart: PropTypes.func.isRequired,
|
|
63
63
|
};
|
|
64
64
|
|
|
65
65
|
RunningSteps.defaultProps = {
|
|
@@ -1,159 +1,37 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import
|
|
3
|
-
import { Grid, Row, Col, Button } from 'patternfly-react';
|
|
4
|
-
import { translate as __ } from 'foremanReact/common/I18n';
|
|
5
|
-
import { useForemanModal } from 'foremanReact/components/ForemanModal/ForemanModalHooks';
|
|
2
|
+
import { Grid, Row } from 'patternfly-react';
|
|
6
3
|
import TaskInfo from './TaskInfo';
|
|
7
|
-
import {
|
|
8
|
-
UNLOCK_MODAL,
|
|
9
|
-
FORCE_UNLOCK_MODAL,
|
|
10
|
-
} from '../../TaskActions/TaskActionsConstants';
|
|
11
4
|
import { ForceUnlockModal, UnlockModal } from '../../TaskActions/UnlockModals';
|
|
5
|
+
import { TaskButtons } from './TaskButtons';
|
|
12
6
|
|
|
13
7
|
const Task = props => {
|
|
14
|
-
const unlockModalActions = useForemanModal({
|
|
15
|
-
id: UNLOCK_MODAL,
|
|
16
|
-
});
|
|
17
|
-
const forceUnlockModalActions = useForemanModal({
|
|
18
|
-
id: FORCE_UNLOCK_MODAL,
|
|
19
|
-
});
|
|
20
|
-
|
|
21
8
|
const {
|
|
22
9
|
taskReload,
|
|
23
|
-
externalId,
|
|
24
10
|
id,
|
|
25
|
-
state,
|
|
26
|
-
resumable,
|
|
27
|
-
cancellable,
|
|
28
|
-
hasSubTasks,
|
|
29
|
-
parentTask,
|
|
30
|
-
cancelTaskRequest,
|
|
31
|
-
resumeTaskRequest,
|
|
32
11
|
forceCancelTaskRequest,
|
|
33
12
|
unlockTaskRequest,
|
|
34
13
|
action,
|
|
35
|
-
|
|
36
|
-
taskProgressToggle,
|
|
37
|
-
canEdit,
|
|
14
|
+
taskReloadStart,
|
|
38
15
|
} = props;
|
|
39
16
|
const forceUnlock = () => {
|
|
40
17
|
if (!taskReload) {
|
|
41
|
-
|
|
18
|
+
taskReloadStart(id);
|
|
42
19
|
}
|
|
43
20
|
forceCancelTaskRequest(id, action);
|
|
44
21
|
};
|
|
45
22
|
const unlock = () => {
|
|
46
23
|
if (!taskReload) {
|
|
47
|
-
|
|
24
|
+
taskReloadStart(id);
|
|
48
25
|
}
|
|
49
26
|
unlockTaskRequest(id, action);
|
|
50
27
|
};
|
|
51
|
-
const editActionsTitle = canEdit
|
|
52
|
-
? undefined
|
|
53
|
-
: __('You do not have permission');
|
|
54
|
-
const dynflowTitle = dynflowEnableConsole
|
|
55
|
-
? undefined
|
|
56
|
-
: `dynflow_enable_console ${__('Setting is off')}`;
|
|
57
28
|
return (
|
|
58
29
|
<React.Fragment>
|
|
59
30
|
<UnlockModal onClick={unlock} />
|
|
60
31
|
<ForceUnlockModal onClick={forceUnlock} />
|
|
61
32
|
<Grid>
|
|
62
33
|
<Row>
|
|
63
|
-
<
|
|
64
|
-
<Button
|
|
65
|
-
className="reload-button"
|
|
66
|
-
bsSize="small"
|
|
67
|
-
onClick={taskProgressToggle}
|
|
68
|
-
>
|
|
69
|
-
<span
|
|
70
|
-
className={`glyphicon glyphicon-refresh ${
|
|
71
|
-
taskReload ? 'spin' : ''
|
|
72
|
-
}`}
|
|
73
|
-
/>
|
|
74
|
-
{__(`${taskReload ? 'Stop' : 'Start'} auto-reloading`)}
|
|
75
|
-
</Button>
|
|
76
|
-
<Button
|
|
77
|
-
className="dynflow-button"
|
|
78
|
-
bsSize="small"
|
|
79
|
-
href={`/foreman_tasks/dynflow/${externalId}`}
|
|
80
|
-
disabled={!dynflowEnableConsole}
|
|
81
|
-
rel="noopener noreferrer"
|
|
82
|
-
target="_blank"
|
|
83
|
-
>
|
|
84
|
-
<span title={dynflowTitle} data-original-title={dynflowTitle}>
|
|
85
|
-
{__('Dynflow console')}
|
|
86
|
-
</span>
|
|
87
|
-
</Button>
|
|
88
|
-
<Button
|
|
89
|
-
className="resume-button"
|
|
90
|
-
bsSize="small"
|
|
91
|
-
title={editActionsTitle}
|
|
92
|
-
data-original-title={editActionsTitle}
|
|
93
|
-
disabled={!canEdit || !resumable}
|
|
94
|
-
onClick={() => {
|
|
95
|
-
if (!taskReload) {
|
|
96
|
-
taskProgressToggle();
|
|
97
|
-
}
|
|
98
|
-
resumeTaskRequest(id, action);
|
|
99
|
-
}}
|
|
100
|
-
>
|
|
101
|
-
{__('Resume')}
|
|
102
|
-
</Button>
|
|
103
|
-
<Button
|
|
104
|
-
className="cancel-button"
|
|
105
|
-
bsSize="small"
|
|
106
|
-
title={editActionsTitle}
|
|
107
|
-
data-original-title={editActionsTitle}
|
|
108
|
-
disabled={!canEdit || !cancellable}
|
|
109
|
-
onClick={() => {
|
|
110
|
-
if (!taskReload) {
|
|
111
|
-
taskProgressToggle();
|
|
112
|
-
}
|
|
113
|
-
cancelTaskRequest(id, action);
|
|
114
|
-
}}
|
|
115
|
-
>
|
|
116
|
-
{__('Cancel')}
|
|
117
|
-
</Button>
|
|
118
|
-
{parentTask && (
|
|
119
|
-
<Button
|
|
120
|
-
className="parent-button"
|
|
121
|
-
bsSize="small"
|
|
122
|
-
href={`/foreman_tasks/tasks/${parentTask}`}
|
|
123
|
-
>
|
|
124
|
-
{__('Parent task')}
|
|
125
|
-
</Button>
|
|
126
|
-
)}
|
|
127
|
-
{hasSubTasks && (
|
|
128
|
-
<Button
|
|
129
|
-
className="subtask-button"
|
|
130
|
-
bsSize="small"
|
|
131
|
-
href={`/foreman_tasks/tasks/${id}/sub_tasks`}
|
|
132
|
-
>
|
|
133
|
-
{__('Sub tasks')}
|
|
134
|
-
</Button>
|
|
135
|
-
)}
|
|
136
|
-
<Button
|
|
137
|
-
className="unlock-button"
|
|
138
|
-
bsSize="small"
|
|
139
|
-
disabled={!canEdit || state !== 'paused'}
|
|
140
|
-
onClick={unlockModalActions.setModalOpen}
|
|
141
|
-
title={editActionsTitle}
|
|
142
|
-
data-original-title={editActionsTitle}
|
|
143
|
-
>
|
|
144
|
-
{__('Unlock')}
|
|
145
|
-
</Button>
|
|
146
|
-
<Button
|
|
147
|
-
className="force-unlock-button"
|
|
148
|
-
bsSize="small"
|
|
149
|
-
disabled={!canEdit || state === 'stopped'}
|
|
150
|
-
onClick={forceUnlockModalActions.setModalOpen}
|
|
151
|
-
title={editActionsTitle}
|
|
152
|
-
data-original-title={editActionsTitle}
|
|
153
|
-
>
|
|
154
|
-
{__('Force Unlock')}
|
|
155
|
-
</Button>
|
|
156
|
-
</Col>
|
|
34
|
+
<TaskButtons taskReloadStart={taskReloadStart} {...props} />
|
|
157
35
|
</Row>
|
|
158
36
|
<TaskInfo {...props} />
|
|
159
37
|
</Grid>
|
|
@@ -163,39 +41,12 @@ const Task = props => {
|
|
|
163
41
|
|
|
164
42
|
Task.propTypes = {
|
|
165
43
|
...TaskInfo.PropTypes,
|
|
166
|
-
|
|
167
|
-
resumable: PropTypes.bool,
|
|
168
|
-
cancellable: PropTypes.bool,
|
|
169
|
-
refetchTaskDetails: PropTypes.func,
|
|
170
|
-
hasSubTasks: PropTypes.bool,
|
|
171
|
-
parentTask: PropTypes.string,
|
|
172
|
-
taskReload: PropTypes.bool,
|
|
173
|
-
taskReloadStop: PropTypes.func,
|
|
174
|
-
timeoutId: PropTypes.number,
|
|
175
|
-
externalId: PropTypes.string,
|
|
176
|
-
id: PropTypes.string.isRequired,
|
|
177
|
-
cancelTaskRequest: PropTypes.func,
|
|
178
|
-
resumeTaskRequest: PropTypes.func,
|
|
179
|
-
dynflowEnableConsole: PropTypes.bool,
|
|
180
|
-
canEdit: PropTypes.bool,
|
|
44
|
+
...TaskButtons.PropTypes,
|
|
181
45
|
};
|
|
182
46
|
|
|
183
47
|
Task.defaultProps = {
|
|
184
48
|
...TaskInfo.defaultProps,
|
|
185
|
-
|
|
186
|
-
resumable: false,
|
|
187
|
-
cancellable: false,
|
|
188
|
-
refetchTaskDetails: () => null,
|
|
189
|
-
hasSubTasks: false,
|
|
190
|
-
parentTask: '',
|
|
191
|
-
taskReload: false,
|
|
192
|
-
taskReloadStop: () => null,
|
|
193
|
-
timeoutId: null,
|
|
194
|
-
externalId: '',
|
|
195
|
-
cancelTaskRequest: () => null,
|
|
196
|
-
resumeTaskRequest: () => null,
|
|
197
|
-
dynflowEnableConsole: false,
|
|
198
|
-
canEdit: false,
|
|
49
|
+
...TaskButtons.defaultProps,
|
|
199
50
|
};
|
|
200
51
|
|
|
201
52
|
export default Task;
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import { Col, Button } from 'patternfly-react';
|
|
4
|
+
import { useForemanModal } from 'foremanReact/components/ForemanModal/ForemanModalHooks';
|
|
5
|
+
import { translate as __ } from 'foremanReact/common/I18n';
|
|
6
|
+
import {
|
|
7
|
+
UNLOCK_MODAL,
|
|
8
|
+
FORCE_UNLOCK_MODAL,
|
|
9
|
+
} from '../../TaskActions/TaskActionsConstants';
|
|
10
|
+
|
|
11
|
+
export const TaskButtons = ({
|
|
12
|
+
canEdit,
|
|
13
|
+
dynflowEnableConsole,
|
|
14
|
+
taskReloadStart,
|
|
15
|
+
taskProgressToggle,
|
|
16
|
+
taskReload,
|
|
17
|
+
externalId,
|
|
18
|
+
id,
|
|
19
|
+
action,
|
|
20
|
+
state,
|
|
21
|
+
resumable,
|
|
22
|
+
cancellable,
|
|
23
|
+
hasSubTasks,
|
|
24
|
+
parentTask,
|
|
25
|
+
cancelTaskRequest,
|
|
26
|
+
resumeTaskRequest,
|
|
27
|
+
}) => {
|
|
28
|
+
const unlockModalActions = useForemanModal({
|
|
29
|
+
id: UNLOCK_MODAL,
|
|
30
|
+
});
|
|
31
|
+
const forceUnlockModalActions = useForemanModal({
|
|
32
|
+
id: FORCE_UNLOCK_MODAL,
|
|
33
|
+
});
|
|
34
|
+
const editActionsTitle = canEdit
|
|
35
|
+
? undefined
|
|
36
|
+
: __('You do not have permission');
|
|
37
|
+
const dynflowTitle = dynflowEnableConsole
|
|
38
|
+
? undefined
|
|
39
|
+
: `dynflow_enable_console ${__('Setting is off')}`;
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<Col xs={12}>
|
|
43
|
+
<Button
|
|
44
|
+
className="reload-button"
|
|
45
|
+
bsSize="small"
|
|
46
|
+
onClick={taskProgressToggle}
|
|
47
|
+
>
|
|
48
|
+
<span
|
|
49
|
+
className={`glyphicon glyphicon-refresh ${taskReload ? 'spin' : ''}`}
|
|
50
|
+
/>
|
|
51
|
+
{__(`${taskReload ? 'Stop' : 'Start'} auto-reloading`)}
|
|
52
|
+
</Button>
|
|
53
|
+
<Button
|
|
54
|
+
className="dynflow-button"
|
|
55
|
+
bsSize="small"
|
|
56
|
+
href={`/foreman_tasks/dynflow/${externalId}`}
|
|
57
|
+
disabled={!dynflowEnableConsole}
|
|
58
|
+
rel="noopener noreferrer"
|
|
59
|
+
target="_blank"
|
|
60
|
+
>
|
|
61
|
+
<span title={dynflowTitle} data-original-title={dynflowTitle}>
|
|
62
|
+
{__('Dynflow console')}
|
|
63
|
+
</span>
|
|
64
|
+
</Button>
|
|
65
|
+
<Button
|
|
66
|
+
className="resume-button"
|
|
67
|
+
bsSize="small"
|
|
68
|
+
title={editActionsTitle}
|
|
69
|
+
data-original-title={editActionsTitle}
|
|
70
|
+
disabled={!canEdit || !resumable}
|
|
71
|
+
onClick={() => {
|
|
72
|
+
if (!taskReload) {
|
|
73
|
+
taskReloadStart(id);
|
|
74
|
+
}
|
|
75
|
+
resumeTaskRequest(id, action);
|
|
76
|
+
}}
|
|
77
|
+
>
|
|
78
|
+
{__('Resume')}
|
|
79
|
+
</Button>
|
|
80
|
+
<Button
|
|
81
|
+
className="cancel-button"
|
|
82
|
+
bsSize="small"
|
|
83
|
+
title={editActionsTitle}
|
|
84
|
+
data-original-title={editActionsTitle}
|
|
85
|
+
disabled={!canEdit || !cancellable}
|
|
86
|
+
onClick={() => {
|
|
87
|
+
if (!taskReload) {
|
|
88
|
+
taskReloadStart(id);
|
|
89
|
+
}
|
|
90
|
+
cancelTaskRequest(id, action);
|
|
91
|
+
}}
|
|
92
|
+
>
|
|
93
|
+
{__('Cancel')}
|
|
94
|
+
</Button>
|
|
95
|
+
{parentTask && (
|
|
96
|
+
<Button
|
|
97
|
+
className="parent-button"
|
|
98
|
+
bsSize="small"
|
|
99
|
+
href={`/foreman_tasks/tasks/${parentTask}`}
|
|
100
|
+
>
|
|
101
|
+
{__('Parent task')}
|
|
102
|
+
</Button>
|
|
103
|
+
)}
|
|
104
|
+
{hasSubTasks && (
|
|
105
|
+
<Button
|
|
106
|
+
className="subtask-button"
|
|
107
|
+
bsSize="small"
|
|
108
|
+
href={`/foreman_tasks/tasks/${id}/sub_tasks`}
|
|
109
|
+
>
|
|
110
|
+
{__('Sub tasks')}
|
|
111
|
+
</Button>
|
|
112
|
+
)}
|
|
113
|
+
<Button
|
|
114
|
+
className="unlock-button"
|
|
115
|
+
bsSize="small"
|
|
116
|
+
disabled={!canEdit || state !== 'paused'}
|
|
117
|
+
onClick={unlockModalActions.setModalOpen}
|
|
118
|
+
title={editActionsTitle}
|
|
119
|
+
data-original-title={editActionsTitle}
|
|
120
|
+
>
|
|
121
|
+
{__('Unlock')}
|
|
122
|
+
</Button>
|
|
123
|
+
<Button
|
|
124
|
+
className="force-unlock-button"
|
|
125
|
+
bsSize="small"
|
|
126
|
+
disabled={!canEdit || state === 'stopped'}
|
|
127
|
+
onClick={forceUnlockModalActions.setModalOpen}
|
|
128
|
+
title={editActionsTitle}
|
|
129
|
+
data-original-title={editActionsTitle}
|
|
130
|
+
>
|
|
131
|
+
{__('Force Unlock')}
|
|
132
|
+
</Button>
|
|
133
|
+
</Col>
|
|
134
|
+
);
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
TaskButtons.propTypes = {
|
|
138
|
+
canEdit: PropTypes.bool,
|
|
139
|
+
dynflowEnableConsole: PropTypes.bool,
|
|
140
|
+
taskReloadStart: PropTypes.func.isRequired,
|
|
141
|
+
taskProgressToggle: PropTypes.func.isRequired,
|
|
142
|
+
taskReload: PropTypes.bool,
|
|
143
|
+
externalId: PropTypes.string,
|
|
144
|
+
id: PropTypes.string.isRequired,
|
|
145
|
+
action: PropTypes.string,
|
|
146
|
+
state: PropTypes.string,
|
|
147
|
+
resumable: PropTypes.bool,
|
|
148
|
+
cancellable: PropTypes.bool,
|
|
149
|
+
hasSubTasks: PropTypes.bool,
|
|
150
|
+
parentTask: PropTypes.string,
|
|
151
|
+
cancelTaskRequest: PropTypes.func,
|
|
152
|
+
resumeTaskRequest: PropTypes.func,
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
TaskButtons.defaultProps = {
|
|
156
|
+
canEdit: false,
|
|
157
|
+
dynflowEnableConsole: false,
|
|
158
|
+
taskReload: false,
|
|
159
|
+
externalId: '',
|
|
160
|
+
action: '',
|
|
161
|
+
state: '',
|
|
162
|
+
resumable: false,
|
|
163
|
+
cancellable: false,
|
|
164
|
+
hasSubTasks: false,
|
|
165
|
+
parentTask: '',
|
|
166
|
+
cancelTaskRequest: () => null,
|
|
167
|
+
resumeTaskRequest: () => null,
|
|
168
|
+
};
|