foreman-tasks 1.1.3 → 1.2.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/app/controllers/foreman_tasks/api/tasks_controller.rb +29 -1
- data/app/controllers/foreman_tasks/tasks_controller.rb +3 -11
- data/app/models/foreman_tasks/task.rb +4 -0
- data/app/models/setting/foreman_tasks.rb +1 -1
- data/app/services/ui_notifications/tasks/task_bulk_stop.rb +36 -0
- data/app/views/foreman_tasks/api/tasks/details.json.rabl +0 -1
- data/config/routes.rb +1 -0
- data/db/migrate/20200517215015_rename_bookmarks_controller.rb +35 -0
- data/db/migrate/20200519093217_drop_dynflow_allow_dangerous_actions_setting.foreman_tasks.rb +5 -0
- data/db/seeds.d/30-notification_blueprints.rb +7 -0
- data/lib/foreman_tasks/engine.rb +1 -1
- data/lib/foreman_tasks/tasks/cleanup.rake +2 -2
- data/lib/foreman_tasks/tasks/export_tasks.rake +1 -1
- data/lib/foreman_tasks/version.rb +1 -1
- data/locale/action_names.rb +1 -1
- data/locale/en/foreman_tasks.po +227 -41
- data/locale/foreman_tasks.pot +579 -288
- data/webpack/ForemanTasks/Components/TaskActions/TaskAction.test.js +60 -0
- data/webpack/ForemanTasks/Components/{TasksTable/TasksTableActionHelpers.js → TaskActions/TaskActionHelpers.js} +21 -6
- data/webpack/ForemanTasks/Components/{TasksTable/__tests__/TasksTableActionHelpers.test.js → TaskActions/TaskActionHelpers.test.js} +2 -2
- data/webpack/ForemanTasks/Components/TaskActions/TaskActionsConstants.js +16 -0
- data/webpack/ForemanTasks/Components/TaskActions/UnlockModals.js +60 -0
- data/webpack/ForemanTasks/Components/TaskActions/UnlockModals.test.js +14 -0
- data/webpack/ForemanTasks/Components/TaskActions/__snapshots__/TaskAction.test.js.snap +233 -0
- data/webpack/ForemanTasks/Components/TaskActions/__snapshots__/UnlockModals.test.js.snap +25 -0
- data/webpack/ForemanTasks/Components/TaskActions/index.js +115 -0
- data/webpack/ForemanTasks/Components/TaskDetails/Components/Task.js +130 -152
- data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/Task.test.js +67 -3
- data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/TaskInfo.test.js +0 -1
- data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/Task.test.js.snap +101 -70
- data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsActions.js +0 -15
- data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsConstants.js +0 -5
- data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsReducer.js +0 -6
- data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsSelectors.js +0 -9
- data/webpack/ForemanTasks/Components/TaskDetails/TasksDetailsHelper.js +6 -1
- data/webpack/ForemanTasks/Components/TaskDetails/__tests__/TaskDetails.test.js +5 -0
- data/webpack/ForemanTasks/Components/TaskDetails/__tests__/__snapshots__/TaskDetails.test.js.snap +2 -7
- data/webpack/ForemanTasks/Components/TaskDetails/__tests__/integration.test.js +4 -0
- data/webpack/ForemanTasks/Components/TaskDetails/index.js +4 -8
- data/webpack/ForemanTasks/Components/TasksTable/Components/ActionSelectButton.js +14 -1
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/ConfirmModal.js +83 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/ConfirmModalActions.js +106 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/ConfirmModalReducer.js +38 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/ConfirmModalSelectors.js +45 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/ConfirmModal.test.js +36 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/ConfirmModalActions.test.js +205 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/ConfirmModalReducer.test.js +27 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/ConfirmModalSelectors.test.js +54 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/__snapshots__/ConfirmModal.test.js.snap +41 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/__snapshots__/ConfirmModalReducer.test.js.snap +19 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/__snapshots__/ConfirmModalSelectors.test.js.snap +30 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/index.js +29 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/ActionSelectButton.test.js +1 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/__snapshots__/ActionSelectButton.test.js.snap +11 -0
- data/webpack/ForemanTasks/Components/TasksTable/TasksBulkActions.js +113 -30
- data/webpack/ForemanTasks/Components/TasksTable/TasksTable.js +13 -9
- data/webpack/ForemanTasks/Components/TasksTable/TasksTableActions.js +23 -63
- data/webpack/ForemanTasks/Components/TasksTable/TasksTableConstants.js +10 -12
- data/webpack/ForemanTasks/Components/TasksTable/TasksTablePage.js +24 -94
- data/webpack/ForemanTasks/Components/TasksTable/TasksTableSchema.js +2 -2
- data/webpack/ForemanTasks/Components/TasksTable/TasksTableSelectors.js +7 -4
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksBulkActions.test.js +35 -0
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTable.fixtures.js +2 -12
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTableActions.test.js +22 -26
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/SubTasksPage.test.js.snap +2 -14
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksBulkActions.test.js.snap +107 -0
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksIndexPage.test.js.snap +2 -14
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTableActions.test.js.snap +17 -124
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTablePage.test.js.snap +24 -128
- data/webpack/ForemanTasks/Components/TasksTable/index.js +2 -2
- data/webpack/ForemanTasks/Components/common/ActionButtons/ActionButton.js +47 -19
- data/webpack/ForemanTasks/Components/common/ActionButtons/ActionButton.test.js +61 -14
- data/webpack/ForemanTasks/Components/common/ActionButtons/__snapshots__/ActionButton.test.js.snap +80 -21
- data/webpack/ForemanTasks/Components/common/ClickConfirmation/ClickConfirmation.scss +9 -0
- data/webpack/ForemanTasks/Components/common/ClickConfirmation/ClickConfirmation.test.js +44 -0
- data/webpack/ForemanTasks/Components/common/ClickConfirmation/__snapshots__/ClickConfirmation.test.js.snap +52 -0
- data/webpack/ForemanTasks/Components/common/ClickConfirmation/index.js +59 -66
- data/webpack/ForemanTasks/Components/common/{ToastTypesConstants.js → ToastsHelpers/ToastTypesConstants.js} +0 -0
- data/webpack/ForemanTasks/Components/common/ToastsHelpers/index.js +15 -0
- data/webpack/ForemanTasks/ForemanTasksReducers.js +2 -0
- data/webpack/ForemanTasks/Routes/ForemanTasksRoutes.test.js +2 -1
- data/webpack/__mocks__/foremanReact/components/ForemanModal/ForemanModalHooks.js +2 -2
- data/webpack/__mocks__/foremanReact/components/ForemanModal/index.js +17 -3
- data/webpack/__mocks__/foremanReact/components/common/ActionButtons/ActionButtons.js +3 -0
- metadata +32 -22
- data/db/migrate/20200611090846_add_task_lock_index_on_resource_type_and_task_id.rb +0 -9
- data/lib/foreman_tasks/tasks/dynflow.rake +0 -6
- data/webpack/ForemanTasks/Components/TasksTable/Components/CancelConfirm.js +0 -53
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmationModals.js +0 -56
- data/webpack/ForemanTasks/Components/TasksTable/Components/ResumeConfirm.js +0 -52
- data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/CancelConfirm.test.js +0 -26
- data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/ConfirmationModals.test.js +0 -24
- data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/ResumeConfirm.test.js +0 -26
- data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/__snapshots__/CancelConfirm.test.js.snap +0 -65
- data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/__snapshots__/ConfirmationModals.test.js.snap +0 -30
- data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/__snapshots__/ResumeConfirm.test.js.snap +0 -63
- data/webpack/ForemanTasks/Components/common/ActionButtons/CancelButton.js +0 -23
- data/webpack/ForemanTasks/Components/common/ActionButtons/CancelButton.test.js +0 -26
- data/webpack/ForemanTasks/Components/common/ActionButtons/ResumeButton.js +0 -23
- data/webpack/ForemanTasks/Components/common/ActionButtons/ResumeButton.test.js +0 -27
- data/webpack/ForemanTasks/Components/common/ActionButtons/__snapshots__/CancelButton.test.js.snap +0 -15
- data/webpack/ForemanTasks/Components/common/ActionButtons/__snapshots__/ResumeButton.test.js.snap +0 -15
|
@@ -8,6 +8,8 @@ import Pagination from 'foremanReact/components/Pagination/PaginationWrapper';
|
|
|
8
8
|
import { getURIQuery } from 'foremanReact/common/helpers';
|
|
9
9
|
import createTasksTableSchema from './TasksTableSchema';
|
|
10
10
|
import { updateURlQuery } from './TasksTableHelpers';
|
|
11
|
+
import { RESUME_MODAL, CANCEL_MODAL } from './TasksTableConstants';
|
|
12
|
+
import { FORCE_UNLOCK_MODAL } from '../TaskActions/TaskActionsConstants';
|
|
11
13
|
|
|
12
14
|
const TasksTable = ({
|
|
13
15
|
getTableItems,
|
|
@@ -23,7 +25,7 @@ const TasksTable = ({
|
|
|
23
25
|
selectRow,
|
|
24
26
|
unselectRow,
|
|
25
27
|
openClickedModal,
|
|
26
|
-
|
|
28
|
+
openModal,
|
|
27
29
|
allRowsSelected,
|
|
28
30
|
}) => {
|
|
29
31
|
const { search, pathname } = history.location;
|
|
@@ -97,14 +99,21 @@ const TasksTable = ({
|
|
|
97
99
|
openClickedModal({
|
|
98
100
|
taskId,
|
|
99
101
|
taskName,
|
|
100
|
-
setModalOpen:
|
|
102
|
+
setModalOpen: () => openModal(CANCEL_MODAL),
|
|
101
103
|
});
|
|
102
104
|
},
|
|
103
105
|
resumeTask: (taskId, taskName) => {
|
|
104
106
|
openClickedModal({
|
|
105
107
|
taskId,
|
|
106
108
|
taskName,
|
|
107
|
-
setModalOpen:
|
|
109
|
+
setModalOpen: () => openModal(RESUME_MODAL),
|
|
110
|
+
});
|
|
111
|
+
},
|
|
112
|
+
forceCancelTask: (taskId, taskName) => {
|
|
113
|
+
openClickedModal({
|
|
114
|
+
taskId,
|
|
115
|
+
taskName,
|
|
116
|
+
setModalOpen: () => openModal(FORCE_UNLOCK_MODAL),
|
|
108
117
|
});
|
|
109
118
|
},
|
|
110
119
|
};
|
|
@@ -151,12 +160,7 @@ TasksTable.propTypes = {
|
|
|
151
160
|
unselectAllRows: PropTypes.func.isRequired,
|
|
152
161
|
selectRow: PropTypes.func.isRequired,
|
|
153
162
|
unselectRow: PropTypes.func.isRequired,
|
|
154
|
-
|
|
155
|
-
cancelSelectedModal: PropTypes.object,
|
|
156
|
-
resumeSelectedModal: PropTypes.object,
|
|
157
|
-
cancelModal: PropTypes.object,
|
|
158
|
-
resumeModal: PropTypes.object,
|
|
159
|
-
}).isRequired,
|
|
163
|
+
openModal: PropTypes.func.isRequired,
|
|
160
164
|
allRowsSelected: PropTypes.bool,
|
|
161
165
|
};
|
|
162
166
|
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { getURIQuery } from 'foremanReact/common/helpers';
|
|
2
2
|
import { getTableItemsAction } from 'foremanReact/components/common/table';
|
|
3
|
-
|
|
4
|
-
import { addToast } from 'foremanReact/redux/actions/toasts';
|
|
5
|
-
import { sprintf } from 'foremanReact/common/I18n';
|
|
3
|
+
|
|
6
4
|
import {
|
|
7
5
|
TASKS_TABLE_ID,
|
|
8
6
|
SELECT_ROWS,
|
|
@@ -11,21 +9,15 @@ import {
|
|
|
11
9
|
UNSELECT_ROWS,
|
|
12
10
|
UPDATE_CLICKED,
|
|
13
11
|
OPEN_SELECT_ALL,
|
|
14
|
-
|
|
15
|
-
TASKS_RESUME_SUCCESS,
|
|
16
|
-
TASKS_RESUME_FAILURE,
|
|
17
|
-
TASKS_CANCEL_REQUEST,
|
|
18
|
-
TASKS_CANCEL_SUCCESS,
|
|
19
|
-
TASKS_CANCEL_FAILURE,
|
|
12
|
+
UPDATE_MODAL,
|
|
20
13
|
} from './TasksTableConstants';
|
|
21
|
-
import { TOAST_TYPES } from '../common/ToastTypesConstants';
|
|
22
14
|
import { getApiPathname } from './TasksTableHelpers';
|
|
23
15
|
import { fetchTasksSummary } from '../TasksDashboard/TasksDashboardActions';
|
|
24
16
|
import {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
} from '
|
|
17
|
+
cancelTaskRequest,
|
|
18
|
+
resumeTaskRequest,
|
|
19
|
+
forceCancelTaskRequest,
|
|
20
|
+
} from '../TaskActions';
|
|
29
21
|
|
|
30
22
|
export const getTableItems = url =>
|
|
31
23
|
getTableItemsAction(TASKS_TABLE_ID, getURIQuery(url), getApiPathname(url));
|
|
@@ -45,34 +37,6 @@ export const cancelTask = ({
|
|
|
45
37
|
reloadPage(url, parentTaskID, dispatch);
|
|
46
38
|
};
|
|
47
39
|
|
|
48
|
-
export const cancelTaskRequest = (id, name) => async dispatch => {
|
|
49
|
-
dispatch(
|
|
50
|
-
addToast({
|
|
51
|
-
type: TOAST_TYPES.INFO,
|
|
52
|
-
message: sprintf('Trying to cancel %s task', name),
|
|
53
|
-
})
|
|
54
|
-
);
|
|
55
|
-
dispatch({ type: TASKS_CANCEL_REQUEST });
|
|
56
|
-
try {
|
|
57
|
-
await API.post(`/foreman_tasks/tasks/${id}/cancel`);
|
|
58
|
-
dispatch({ type: TASKS_CANCEL_SUCCESS });
|
|
59
|
-
toastDispatch({
|
|
60
|
-
type: 'cancelled',
|
|
61
|
-
name,
|
|
62
|
-
toastInfo: cancelToastInfo,
|
|
63
|
-
dispatch,
|
|
64
|
-
});
|
|
65
|
-
} catch ({ response }) {
|
|
66
|
-
dispatch({ type: TASKS_CANCEL_FAILURE, payload: response });
|
|
67
|
-
toastDispatch({
|
|
68
|
-
type: 'skipped',
|
|
69
|
-
name,
|
|
70
|
-
toastInfo: cancelToastInfo,
|
|
71
|
-
dispatch,
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
};
|
|
75
|
-
|
|
76
40
|
export const resumeTask = ({
|
|
77
41
|
taskId,
|
|
78
42
|
taskName,
|
|
@@ -83,27 +47,15 @@ export const resumeTask = ({
|
|
|
83
47
|
reloadPage(url, parentTaskID, dispatch);
|
|
84
48
|
};
|
|
85
49
|
|
|
86
|
-
export const
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
toastInfo: resumeToastInfo,
|
|
96
|
-
dispatch,
|
|
97
|
-
});
|
|
98
|
-
} catch ({ response }) {
|
|
99
|
-
dispatch({ type: TASKS_RESUME_FAILURE, payload: response });
|
|
100
|
-
toastDispatch({
|
|
101
|
-
type: 'failed',
|
|
102
|
-
name,
|
|
103
|
-
toastInfo: resumeToastInfo,
|
|
104
|
-
dispatch,
|
|
105
|
-
});
|
|
106
|
-
}
|
|
50
|
+
export const forceCancelTask = ({
|
|
51
|
+
taskId,
|
|
52
|
+
taskName,
|
|
53
|
+
url,
|
|
54
|
+
parentTaskID,
|
|
55
|
+
}) => async dispatch => {
|
|
56
|
+
await dispatch(forceCancelTaskRequest(taskId, taskName));
|
|
57
|
+
dispatch(getTableItems(url));
|
|
58
|
+
dispatch(fetchTasksSummary(getURIQuery(url).time, parentTaskID));
|
|
107
59
|
};
|
|
108
60
|
|
|
109
61
|
export const selectPage = results => dispatch => {
|
|
@@ -141,3 +93,11 @@ export const openClickedModal = ({ taskId, taskName, setModalOpen }) => {
|
|
|
141
93
|
payload: { clicked: { taskId, taskName } },
|
|
142
94
|
};
|
|
143
95
|
};
|
|
96
|
+
|
|
97
|
+
export const openModalAction = (modalID, setModalOpen) => {
|
|
98
|
+
setModalOpen();
|
|
99
|
+
return {
|
|
100
|
+
type: UPDATE_MODAL,
|
|
101
|
+
payload: { modalID },
|
|
102
|
+
};
|
|
103
|
+
};
|
|
@@ -8,23 +8,21 @@ export const UNSELECT_ALL_ROWS = 'UNSELECT_ALL_ROWS';
|
|
|
8
8
|
export const SELECT_ALL_ROWS = 'SELECT_ALL_ROWS';
|
|
9
9
|
export const OPEN_SELECT_ALL = 'OPEN_SELECT_ALL';
|
|
10
10
|
|
|
11
|
-
export const TASKS_RESUME_REQUEST = 'TASKS_RESUME_REQUEST';
|
|
12
|
-
export const TASKS_RESUME_SUCCESS = 'TASKS_RESUME_SUCCESS';
|
|
13
|
-
export const TASKS_RESUME_FAILURE = 'TASKS_RESUME_FAILURE';
|
|
14
|
-
export const TASKS_CANCEL_REQUEST = 'TASKS_CANCEL_REQUEST';
|
|
15
|
-
export const TASKS_CANCEL_SUCCESS = 'TASKS_CANCEL_SUCCESS';
|
|
16
|
-
export const TASKS_CANCEL_FAILURE = 'TASKS_CANCEL_FAILURE';
|
|
17
|
-
|
|
18
11
|
export const BULK_CANCEL_PATH = 'bulk_cancel';
|
|
19
12
|
export const BULK_RESUME_PATH = 'bulk_resume';
|
|
13
|
+
export const BULK_FORCE_CANCEL_PATH = 'bulk_stop';
|
|
14
|
+
|
|
15
|
+
export const CANCEL_MODAL = 'cancelConfirmModal';
|
|
16
|
+
export const RESUME_MODAL = 'resumeConfirmModal';
|
|
17
|
+
export const CANCEL_SELECTED_MODAL = 'cancelSelectedConfirmModal';
|
|
18
|
+
export const RESUME_SELECTED_MODAL = 'resumeSelectedConfirmModal';
|
|
19
|
+
export const CONFIRM_MODAL = 'ConfirmModal';
|
|
20
|
+
export const FORCE_UNLOCK_SELECTED_MODAL = 'forceUnlockSelectedConfirmModal';
|
|
20
21
|
|
|
21
|
-
export const CANCEL_CONFIRM_MODAL_ID = 'cancelConfirmModal';
|
|
22
|
-
export const RESUME_CONFIRM_MODAL_ID = 'resumeConfirmModal';
|
|
23
|
-
export const CANCEL_SELECTED_CONFIRM_MODAL_ID = 'cancelSelectedConfirmModal';
|
|
24
|
-
export const RESUME_SELECTED_CONFIRM_MODAL_ID = 'resumeSelectedConfirmModal';
|
|
25
22
|
export const UPDATE_CLICKED = 'UPDATE_CLICKED';
|
|
23
|
+
export const UPDATE_MODAL = 'UPDATE_MODAL';
|
|
26
24
|
|
|
27
25
|
export const TASKS_SEARCH_PROPS = {
|
|
28
26
|
...getControllerSearchProps('tasks'),
|
|
29
|
-
controller: '
|
|
27
|
+
controller: 'foreman_tasks_tasks',
|
|
30
28
|
};
|
|
@@ -11,13 +11,13 @@ import { useForemanModal } from 'foremanReact/components/ForemanModal/ForemanMod
|
|
|
11
11
|
import TasksDashboard from '../TasksDashboard';
|
|
12
12
|
import TasksTable from './TasksTable';
|
|
13
13
|
import { resolveSearchQuery, getCSVurl } from './TasksTableHelpers';
|
|
14
|
-
import
|
|
14
|
+
import ConfirmModal from './Components/ConfirmModal/';
|
|
15
15
|
import {
|
|
16
16
|
TASKS_SEARCH_PROPS,
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
CANCEL_SELECTED_MODAL,
|
|
18
|
+
RESUME_SELECTED_MODAL,
|
|
19
|
+
FORCE_UNLOCK_SELECTED_MODAL,
|
|
20
|
+
CONFIRM_MODAL,
|
|
21
21
|
} from './TasksTableConstants';
|
|
22
22
|
import { ActionSelectButton } from './Components/ActionSelectButton';
|
|
23
23
|
import './TasksTablePage.scss';
|
|
@@ -26,10 +26,11 @@ import { SelectAllAlert } from './Components/SelectAllAlert';
|
|
|
26
26
|
const TasksTablePage = ({
|
|
27
27
|
getBreadcrumbs,
|
|
28
28
|
history,
|
|
29
|
-
clicked,
|
|
30
29
|
createHeader,
|
|
31
30
|
selectAllRows,
|
|
32
31
|
showSelectAll,
|
|
32
|
+
modalID,
|
|
33
|
+
openModalAction,
|
|
33
34
|
...props
|
|
34
35
|
}) => {
|
|
35
36
|
const url = history.location.pathname + history.location.search;
|
|
@@ -38,83 +39,20 @@ const TasksTablePage = ({
|
|
|
38
39
|
resolveSearchQuery(searchQuery, history);
|
|
39
40
|
};
|
|
40
41
|
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
);
|
|
45
|
-
return selectedIDs.map(item => ({
|
|
46
|
-
name: item.action,
|
|
47
|
-
id: item.id,
|
|
48
|
-
isCancellable: item.availableActions.cancellable,
|
|
49
|
-
isResumable: item.availableActions.resumable,
|
|
50
|
-
}));
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
const modalProps = {
|
|
54
|
-
cancelSelectedModal: useForemanModal({
|
|
55
|
-
id: CANCEL_SELECTED_CONFIRM_MODAL_ID,
|
|
56
|
-
}),
|
|
57
|
-
resumeSelectedModal: useForemanModal({
|
|
58
|
-
id: RESUME_SELECTED_CONFIRM_MODAL_ID,
|
|
59
|
-
}),
|
|
60
|
-
cancelModal: useForemanModal({ id: CANCEL_CONFIRM_MODAL_ID }),
|
|
61
|
-
resumeModal: useForemanModal({ id: RESUME_CONFIRM_MODAL_ID }),
|
|
62
|
-
};
|
|
42
|
+
const { setModalOpen, setModalClosed } = useForemanModal({
|
|
43
|
+
id: CONFIRM_MODAL,
|
|
44
|
+
});
|
|
63
45
|
|
|
64
|
-
const
|
|
65
|
-
bulkCancelById,
|
|
66
|
-
bulkCancelBySearch,
|
|
67
|
-
bulkResumeById,
|
|
68
|
-
bulkResumeBySearch,
|
|
69
|
-
cancelTask,
|
|
70
|
-
resumeTask,
|
|
71
|
-
parentTaskID,
|
|
72
|
-
} = props;
|
|
73
|
-
const tasksActions = {
|
|
74
|
-
cancelSelectedTasks: () => {
|
|
75
|
-
props.allRowsSelected
|
|
76
|
-
? bulkCancelBySearch({ query: uriQuery, parentTaskID })
|
|
77
|
-
: bulkCancelById({
|
|
78
|
-
selected: getSelectedTasks(),
|
|
79
|
-
url,
|
|
80
|
-
parentTaskID,
|
|
81
|
-
});
|
|
82
|
-
},
|
|
83
|
-
cancelTask: () => {
|
|
84
|
-
cancelTask({
|
|
85
|
-
taskId: clicked.taskId,
|
|
86
|
-
taskName: clicked.taskName,
|
|
87
|
-
url,
|
|
88
|
-
parentTaskID,
|
|
89
|
-
});
|
|
90
|
-
},
|
|
91
|
-
resumeSelectedTasks: () => {
|
|
92
|
-
props.allRowsSelected
|
|
93
|
-
? bulkResumeBySearch({ query: uriQuery, parentTaskID })
|
|
94
|
-
: bulkResumeById({
|
|
95
|
-
selected: getSelectedTasks(),
|
|
96
|
-
url,
|
|
97
|
-
parentTaskID,
|
|
98
|
-
});
|
|
99
|
-
},
|
|
100
|
-
resumeTask: () => {
|
|
101
|
-
resumeTask({
|
|
102
|
-
taskId: clicked.taskId,
|
|
103
|
-
taskName: clicked.taskName,
|
|
104
|
-
url,
|
|
105
|
-
parentTaskID,
|
|
106
|
-
});
|
|
107
|
-
},
|
|
108
|
-
};
|
|
46
|
+
const openModal = id => openModalAction(id, setModalOpen);
|
|
109
47
|
|
|
110
48
|
return (
|
|
111
49
|
<div className="tasks-table-wrapper">
|
|
112
|
-
<
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
}
|
|
117
|
-
|
|
50
|
+
<ConfirmModal
|
|
51
|
+
id={CONFIRM_MODAL}
|
|
52
|
+
url={url}
|
|
53
|
+
parentTaskID={props.parentTaskID}
|
|
54
|
+
uriQuery={uriQuery}
|
|
55
|
+
setModalClosed={setModalClosed}
|
|
118
56
|
/>
|
|
119
57
|
<PageLayout
|
|
120
58
|
searchable
|
|
@@ -132,8 +70,9 @@ const TasksTablePage = ({
|
|
|
132
70
|
/>
|
|
133
71
|
<ActionSelectButton
|
|
134
72
|
disabled={!(props.selectedRows.length || props.allRowsSelected)}
|
|
135
|
-
onCancel={
|
|
136
|
-
onResume={
|
|
73
|
+
onCancel={() => openModal(CANCEL_SELECTED_MODAL)}
|
|
74
|
+
onResume={() => openModal(RESUME_SELECTED_MODAL)}
|
|
75
|
+
onForceCancel={() => openModal(FORCE_UNLOCK_SELECTED_MODAL)}
|
|
137
76
|
/>
|
|
138
77
|
</React.Fragment>
|
|
139
78
|
}
|
|
@@ -152,7 +91,7 @@ const TasksTablePage = ({
|
|
|
152
91
|
allRowsSelected={props.allRowsSelected}
|
|
153
92
|
/>
|
|
154
93
|
)}
|
|
155
|
-
<TasksTable history={history} {...props}
|
|
94
|
+
<TasksTable history={history} {...props} openModal={openModal} />
|
|
156
95
|
</React.Fragment>
|
|
157
96
|
</PageLayout>
|
|
158
97
|
</div>
|
|
@@ -172,20 +111,11 @@ TasksTablePage.propTypes = {
|
|
|
172
111
|
actionName: PropTypes.string,
|
|
173
112
|
status: PropTypes.oneOf(Object.keys(STATUS)),
|
|
174
113
|
history: PropTypes.object.isRequired,
|
|
175
|
-
cancelTask: PropTypes.func.isRequired,
|
|
176
|
-
resumeTask: PropTypes.func.isRequired,
|
|
177
|
-
bulkCancelById: PropTypes.func.isRequired,
|
|
178
|
-
bulkCancelBySearch: PropTypes.func.isRequired,
|
|
179
|
-
bulkResumeById: PropTypes.func.isRequired,
|
|
180
|
-
bulkResumeBySearch: PropTypes.func.isRequired,
|
|
181
114
|
selectedRows: PropTypes.arrayOf(PropTypes.string),
|
|
182
115
|
parentTaskID: PropTypes.string,
|
|
183
116
|
createHeader: PropTypes.func,
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
taskName: PropTypes.string,
|
|
187
|
-
parentTaskID: PropTypes.string,
|
|
188
|
-
}),
|
|
117
|
+
modalID: PropTypes.string,
|
|
118
|
+
openModalAction: PropTypes.func.isRequired,
|
|
189
119
|
showSelectAll: PropTypes.bool,
|
|
190
120
|
unselectAllRows: PropTypes.func.isRequired,
|
|
191
121
|
};
|
|
@@ -200,9 +130,9 @@ TasksTablePage.defaultProps = {
|
|
|
200
130
|
status: STATUS.PENDING,
|
|
201
131
|
selectedRows: [],
|
|
202
132
|
parentTaskID: null,
|
|
203
|
-
clicked: {},
|
|
204
133
|
createHeader: () => __('Tasks'),
|
|
205
134
|
showSelectAll: false,
|
|
135
|
+
modalID: '',
|
|
206
136
|
};
|
|
207
137
|
|
|
208
138
|
export default TasksTablePage;
|
|
@@ -67,7 +67,7 @@ const createTasksTableSchema = (
|
|
|
67
67
|
sortableColumn('started_at', __('Started at'), 3, sortController, [
|
|
68
68
|
dateCellFormmatter,
|
|
69
69
|
]),
|
|
70
|
-
sortableColumn('duration', __('Duration'),
|
|
70
|
+
sortableColumn('duration', __('Duration'), 2, sortController, [
|
|
71
71
|
durationCellFormmatter,
|
|
72
72
|
]),
|
|
73
73
|
column(
|
|
@@ -76,7 +76,7 @@ const createTasksTableSchema = (
|
|
|
76
76
|
headFormat,
|
|
77
77
|
[actionCellFormatter(taskActions)],
|
|
78
78
|
{
|
|
79
|
-
className: 'col-md-
|
|
79
|
+
className: 'col-md-2',
|
|
80
80
|
}
|
|
81
81
|
),
|
|
82
82
|
];
|
|
@@ -24,9 +24,6 @@ export const selectActionName = state =>
|
|
|
24
24
|
export const selectSelectedRows = state =>
|
|
25
25
|
selectTasksTableQuery(state).selectedRows || [];
|
|
26
26
|
|
|
27
|
-
export const selectClicked = state =>
|
|
28
|
-
selectTasksTableQuery(state).clicked || {};
|
|
29
|
-
|
|
30
27
|
export const selectResults = createSelector(
|
|
31
28
|
selectTasksTableContent,
|
|
32
29
|
({ results }) =>
|
|
@@ -38,7 +35,10 @@ export const selectResults = createSelector(
|
|
|
38
35
|
username: result.username || '',
|
|
39
36
|
state: result.state + (result.frozen ? ` ${__('Disabled')}` : ''),
|
|
40
37
|
duration: getDuration(result.started_at, result.ended_at),
|
|
41
|
-
availableActions:
|
|
38
|
+
availableActions: {
|
|
39
|
+
...result.available_actions,
|
|
40
|
+
stoppable: result.state !== 'stopped',
|
|
41
|
+
},
|
|
42
42
|
}))
|
|
43
43
|
);
|
|
44
44
|
|
|
@@ -54,3 +54,6 @@ export const selectAllRowsSelected = state =>
|
|
|
54
54
|
|
|
55
55
|
export const selectShowSelectAll = state =>
|
|
56
56
|
selectTasksTableQuery(state).showSelectAll;
|
|
57
|
+
|
|
58
|
+
export const selectModalID = state =>
|
|
59
|
+
selectTasksTableQuery(state).modalID || '';
|
|
@@ -5,6 +5,8 @@ import {
|
|
|
5
5
|
bulkCancelBySearch,
|
|
6
6
|
bulkResumeById,
|
|
7
7
|
bulkResumeBySearch,
|
|
8
|
+
bulkForceCancelById,
|
|
9
|
+
bulkForceCancelBySearch,
|
|
8
10
|
} from '../TasksBulkActions';
|
|
9
11
|
|
|
10
12
|
jest.mock('foremanReact/components/common/table', () => ({
|
|
@@ -68,6 +70,28 @@ const fixtures = {
|
|
|
68
70
|
}));
|
|
69
71
|
return bulkCancelById({ selected, url: 'some-url' });
|
|
70
72
|
},
|
|
73
|
+
|
|
74
|
+
'handles bulkForceCancelById requests': () => {
|
|
75
|
+
const selected = [{ ...task, isCancellable: true }];
|
|
76
|
+
|
|
77
|
+
API.post.mockImplementation(() => ({
|
|
78
|
+
data: {
|
|
79
|
+
stopped_length: 2,
|
|
80
|
+
skipped_length: 4,
|
|
81
|
+
},
|
|
82
|
+
}));
|
|
83
|
+
return bulkForceCancelById({ selected, url: 'some-url' });
|
|
84
|
+
},
|
|
85
|
+
|
|
86
|
+
'handles bulkForceCancelById requests that fail': () => {
|
|
87
|
+
const selected = [{ ...task, isResumable: true }];
|
|
88
|
+
|
|
89
|
+
API.post.mockImplementation(() =>
|
|
90
|
+
Promise.reject(new Error('Network Error'))
|
|
91
|
+
);
|
|
92
|
+
return bulkForceCancelById({ selected, url: 'some-url' });
|
|
93
|
+
},
|
|
94
|
+
|
|
71
95
|
'handles bulkCancelById requests that are not cancellable': () => {
|
|
72
96
|
const selected = [{ ...task, isCancellable: false }];
|
|
73
97
|
return bulkCancelById({ selected, url: 'some-url' });
|
|
@@ -77,6 +101,11 @@ const fixtures = {
|
|
|
77
101
|
return bulkResumeById({ selected, url: 'some-url' });
|
|
78
102
|
},
|
|
79
103
|
|
|
104
|
+
'handles bulkForceCancelById requests that are stopped': () => {
|
|
105
|
+
const selected = [{ ...task, isResumable: false, state: 'stopped' }];
|
|
106
|
+
return bulkForceCancelById({ selected, url: 'some-url' });
|
|
107
|
+
},
|
|
108
|
+
|
|
80
109
|
'handles bulkCancelBySearch requests': () => {
|
|
81
110
|
API.post.mockImplementation(() => ({
|
|
82
111
|
data: {
|
|
@@ -105,6 +134,12 @@ const fixtures = {
|
|
|
105
134
|
parentTaskID: 'parent',
|
|
106
135
|
});
|
|
107
136
|
},
|
|
137
|
+
'handles bulkForceCancelBySearch requests': () =>
|
|
138
|
+
bulkForceCancelBySearch({
|
|
139
|
+
query: { search: {} },
|
|
140
|
+
url: 'some-url',
|
|
141
|
+
parentTaskID: 'parent',
|
|
142
|
+
}),
|
|
108
143
|
};
|
|
109
144
|
|
|
110
145
|
describe('TasksTable bulk actions', () => {
|