foreman-tasks 0.17.1 → 0.17.2
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/lib/foreman_tasks/version.rb +1 -1
- data/webpack/ForemanTasks/Components/TaskDetails/TaskDetailsSelectors.js +3 -1
- data/webpack/ForemanTasks/Components/TaskDetails/__tests__/__snapshots__/TaskDetails.test.js.snap +2 -2
- data/webpack/ForemanTasks/Components/TaskDetails/index.js +1 -4
- data/webpack/ForemanTasks/Components/TasksDashboard/index.js +1 -4
- data/webpack/ForemanTasks/Components/TasksTable/Components/ActionConfirmation.js +49 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/ActionSelectButton.js +37 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/CancelResumeConfirm.js +51 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/TableSelectionCell.js +32 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/TableSelectionHeaderCell.js +38 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/ActionConfirmation.test.js +18 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/ActionSelectButton.test.js +13 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/CancelResumeConfirm.test.js +28 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/TableSelectionCell.test.js +15 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/TableSelectionHeaderCell.test.js +15 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/__snapshots__/ActionConfirmation.test.js.snap +89 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/__snapshots__/ActionSelectButton.test.js.snap +32 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/__snapshots__/CancelResumeConfirm.test.js.snap +37 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/__snapshots__/TableSelectionCell.test.js.snap +14 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/__test__/__snapshots__/TableSelectionHeaderCell.test.js.snap +15 -0
- data/webpack/ForemanTasks/Components/TasksTable/TasksTable.js +29 -1
- data/webpack/ForemanTasks/Components/TasksTable/TasksTableActions.js +78 -3
- data/webpack/ForemanTasks/Components/TasksTable/TasksTableConstants.js +11 -0
- data/webpack/ForemanTasks/Components/TasksTable/TasksTablePage.js +47 -1
- data/webpack/ForemanTasks/Components/TasksTable/TasksTableReducer.js +30 -11
- data/webpack/ForemanTasks/Components/TasksTable/TasksTableSchema.js +23 -5
- data/webpack/ForemanTasks/Components/TasksTable/TasksTableSelectors.js +8 -0
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTable.fixtures.js +9 -1
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTableActions.test.js +46 -1
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/TasksTableReducer.test.js +29 -1
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/SubTasksPage.test.js.snap +9 -5
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksIndexPage.test.js.snap +9 -5
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTableActions.test.js.snap +77 -17
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTablePage.test.js.snap +46 -10
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTableReducer.test.js.snap +62 -7
- data/webpack/ForemanTasks/Components/TasksTable/formatters/__test__/__snapshots__/actionCellFormatter.test.js.snap +14 -0
- data/webpack/ForemanTasks/Components/TasksTable/formatters/__test__/__snapshots__/actionNameCellFormatter.test.js.snap +9 -0
- data/webpack/ForemanTasks/Components/TasksTable/formatters/__test__/__snapshots__/dateCellFormmatter.test.js.snap +9 -0
- data/webpack/ForemanTasks/Components/TasksTable/formatters/__test__/__snapshots__/durationCellFormmatter.test.js.snap +18 -0
- data/webpack/ForemanTasks/Components/TasksTable/formatters/__test__/__snapshots__/selectionCellFormatter.test.js.snap +10 -0
- data/webpack/ForemanTasks/Components/TasksTable/formatters/__test__/__snapshots__/selectionHeaderCellFormatter.test.js.snap +10 -0
- data/webpack/ForemanTasks/Components/TasksTable/formatters/__test__/actionCellFormatter.test.js +11 -0
- data/webpack/ForemanTasks/Components/TasksTable/formatters/__test__/actionNameCellFormatter.test.js +8 -0
- data/webpack/ForemanTasks/Components/TasksTable/formatters/__test__/dateCellFormmatter.test.js +7 -0
- data/webpack/ForemanTasks/Components/TasksTable/formatters/__test__/durationCellFormmatter.test.js +12 -0
- data/webpack/ForemanTasks/Components/TasksTable/formatters/__test__/selectionCellFormatter.test.js +12 -0
- data/webpack/ForemanTasks/Components/TasksTable/formatters/__test__/selectionHeaderCellFormatter.test.js +12 -0
- data/webpack/ForemanTasks/Components/TasksTable/formatters/actionCellFormatter.js +16 -0
- data/webpack/ForemanTasks/Components/TasksTable/formatters/actionNameCellFormatter.js +5 -0
- data/webpack/ForemanTasks/Components/TasksTable/formatters/dateCellFormmatter.js +7 -0
- data/webpack/ForemanTasks/Components/TasksTable/formatters/durationCellFormmatter.js +7 -0
- data/webpack/ForemanTasks/Components/TasksTable/formatters/index.js +7 -0
- data/webpack/ForemanTasks/Components/TasksTable/formatters/selectionCellFormatter.js +10 -0
- data/webpack/ForemanTasks/Components/TasksTable/formatters/selectionHeaderCellFormatter.js +10 -0
- data/webpack/ForemanTasks/Components/TasksTable/index.js +5 -4
- data/webpack/__mocks__/foremanReact/components/common/table.js +1 -0
- metadata +36 -3
- data/webpack/ForemanTasks/Components/TasksTable/TaskTableFormmatters.js +0 -53
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`ActionSelectButton renders with minimal props 1`] = `
|
|
4
|
+
<DropdownButton
|
|
5
|
+
disabled={false}
|
|
6
|
+
id="selcted-action-type"
|
|
7
|
+
title="Select Action"
|
|
8
|
+
>
|
|
9
|
+
<MenuItem
|
|
10
|
+
bsClass="dropdown"
|
|
11
|
+
disabled={false}
|
|
12
|
+
divider={false}
|
|
13
|
+
eventKey="1"
|
|
14
|
+
header={false}
|
|
15
|
+
onClick={[MockFunction]}
|
|
16
|
+
title="Cancel selected tasks"
|
|
17
|
+
>
|
|
18
|
+
Cancel Selected
|
|
19
|
+
</MenuItem>
|
|
20
|
+
<MenuItem
|
|
21
|
+
bsClass="dropdown"
|
|
22
|
+
disabled={false}
|
|
23
|
+
divider={false}
|
|
24
|
+
eventKey="2"
|
|
25
|
+
header={false}
|
|
26
|
+
onClick={[MockFunction]}
|
|
27
|
+
title="Resume selected tasks"
|
|
28
|
+
>
|
|
29
|
+
Resume Selected
|
|
30
|
+
</MenuItem>
|
|
31
|
+
</DropdownButton>
|
|
32
|
+
`;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`CancelResumeConfirm renders CANCEL modal 1`] = `
|
|
4
|
+
<ActionConfirmation
|
|
5
|
+
abortAction="No"
|
|
6
|
+
closeModal={[Function]}
|
|
7
|
+
confirmAction="Yes"
|
|
8
|
+
message="This will stop 3 tasks, putting them in the canceled state. Are you sure?"
|
|
9
|
+
onClick={[Function]}
|
|
10
|
+
showModal={true}
|
|
11
|
+
title="Cancel Selected Tasks"
|
|
12
|
+
/>
|
|
13
|
+
`;
|
|
14
|
+
|
|
15
|
+
exports[`CancelResumeConfirm renders CLOSED modal 1`] = `
|
|
16
|
+
<ActionConfirmation
|
|
17
|
+
abortAction="No"
|
|
18
|
+
closeModal={[Function]}
|
|
19
|
+
confirmAction="Yes"
|
|
20
|
+
message="This will resume 3 tasks, putting them in the running state. Are you sure?"
|
|
21
|
+
onClick={[Function]}
|
|
22
|
+
showModal={false}
|
|
23
|
+
title="Resume Selected Tasks"
|
|
24
|
+
/>
|
|
25
|
+
`;
|
|
26
|
+
|
|
27
|
+
exports[`CancelResumeConfirm renders RESUME modal 1`] = `
|
|
28
|
+
<ActionConfirmation
|
|
29
|
+
abortAction="No"
|
|
30
|
+
closeModal={[Function]}
|
|
31
|
+
confirmAction="Yes"
|
|
32
|
+
message="This will resume 3 tasks, putting them in the running state. Are you sure?"
|
|
33
|
+
onClick={[Function]}
|
|
34
|
+
showModal={true}
|
|
35
|
+
title="Resume Selected Tasks"
|
|
36
|
+
/>
|
|
37
|
+
`;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`TableSelectionCell renders TableSelectionCell 1`] = `
|
|
4
|
+
<TableSelectionCell
|
|
5
|
+
className=""
|
|
6
|
+
>
|
|
7
|
+
<TableCheckbox
|
|
8
|
+
checked={true}
|
|
9
|
+
id="some id"
|
|
10
|
+
label="some label"
|
|
11
|
+
onChange={[MockFunction]}
|
|
12
|
+
/>
|
|
13
|
+
</TableSelectionCell>
|
|
14
|
+
`;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`TableSelectionHeaderCell renders TableSelectionHeaderCell 1`] = `
|
|
4
|
+
<TableSelectionHeading
|
|
5
|
+
aria-label="some label"
|
|
6
|
+
className=""
|
|
7
|
+
>
|
|
8
|
+
<TableCheckbox
|
|
9
|
+
checked={true}
|
|
10
|
+
id="some id"
|
|
11
|
+
label="some label"
|
|
12
|
+
onChange={[MockFunction]}
|
|
13
|
+
/>
|
|
14
|
+
</TableSelectionHeading>
|
|
15
|
+
`;
|
|
@@ -19,6 +19,11 @@ const TasksTable = ({
|
|
|
19
19
|
pagination,
|
|
20
20
|
cancelTask,
|
|
21
21
|
resumeTask,
|
|
22
|
+
selectedRows,
|
|
23
|
+
selectAllRows,
|
|
24
|
+
unselectAllRows,
|
|
25
|
+
selectRow,
|
|
26
|
+
unselectRow,
|
|
22
27
|
}) => {
|
|
23
28
|
const url = history.location.pathname + history.location.search;
|
|
24
29
|
const uriQuery = getURIQuery(url);
|
|
@@ -27,6 +32,22 @@ const TasksTable = ({
|
|
|
27
32
|
getTableItems(url);
|
|
28
33
|
}, [history.location.search]);
|
|
29
34
|
|
|
35
|
+
const getSelectionController = () => {
|
|
36
|
+
const checkAllRowsSelected = () => results.length === selectedRows.length;
|
|
37
|
+
return {
|
|
38
|
+
allRowsSelected: () => checkAllRowsSelected(),
|
|
39
|
+
selectAllRows: () => {
|
|
40
|
+
if (checkAllRowsSelected()) unselectAllRows();
|
|
41
|
+
else selectAllRows(results);
|
|
42
|
+
},
|
|
43
|
+
selectRow: ({ rowData: { id } }) => {
|
|
44
|
+
if (selectedRows.includes(id)) unselectRow(id);
|
|
45
|
+
else selectRow(id);
|
|
46
|
+
},
|
|
47
|
+
isSelected: ({ rowData }) => selectedRows.includes(rowData.id),
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
|
|
30
51
|
if (status === STATUS.ERROR) {
|
|
31
52
|
return (
|
|
32
53
|
<MessageBox
|
|
@@ -76,7 +97,8 @@ const TasksTable = ({
|
|
|
76
97
|
setSortHistory,
|
|
77
98
|
uriQuery.sort_by,
|
|
78
99
|
uriQuery.sort_order,
|
|
79
|
-
taskActions
|
|
100
|
+
taskActions,
|
|
101
|
+
getSelectionController()
|
|
80
102
|
)}
|
|
81
103
|
rows={results}
|
|
82
104
|
/>
|
|
@@ -105,6 +127,11 @@ TasksTable.propTypes = {
|
|
|
105
127
|
history: PropTypes.object.isRequired,
|
|
106
128
|
cancelTask: PropTypes.func.isRequired,
|
|
107
129
|
resumeTask: PropTypes.func.isRequired,
|
|
130
|
+
selectedRows: PropTypes.array,
|
|
131
|
+
selectAllRows: PropTypes.func.isRequired,
|
|
132
|
+
unselectAllRows: PropTypes.func.isRequired,
|
|
133
|
+
selectRow: PropTypes.func.isRequired,
|
|
134
|
+
unselectRow: PropTypes.func.isRequired,
|
|
108
135
|
};
|
|
109
136
|
|
|
110
137
|
TasksTable.defaultProps = {
|
|
@@ -114,6 +141,7 @@ TasksTable.defaultProps = {
|
|
|
114
141
|
page: 1,
|
|
115
142
|
perPage: 20,
|
|
116
143
|
},
|
|
144
|
+
selectedRows: [],
|
|
117
145
|
};
|
|
118
146
|
|
|
119
147
|
export default TasksTable;
|
|
@@ -3,7 +3,16 @@ import { getTableItemsAction } from 'foremanReact/components/common/table';
|
|
|
3
3
|
import API from 'foremanReact/API';
|
|
4
4
|
import { addToast } from 'foremanReact/redux/actions/toasts';
|
|
5
5
|
import { translate as __ } from 'foremanReact/common/I18n';
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
TASKS_TABLE_ID,
|
|
8
|
+
SELECT_ROWS,
|
|
9
|
+
UNSELECT_ALL_ROWS,
|
|
10
|
+
UNSELECT_ROWS,
|
|
11
|
+
TASKS_TABLE_SELECTED_MODAL,
|
|
12
|
+
CLOSED,
|
|
13
|
+
RESUME,
|
|
14
|
+
CANCEL,
|
|
15
|
+
} from './TasksTableConstants';
|
|
7
16
|
import { getApiPathname } from './TasksTableHelpers';
|
|
8
17
|
import { fetchTasksSummary } from '../TasksDashboard/TasksDashboardActions';
|
|
9
18
|
|
|
@@ -28,14 +37,14 @@ export const cancelTaskRequest = (id, name) => async dispatch => {
|
|
|
28
37
|
dispatch(
|
|
29
38
|
addToast({
|
|
30
39
|
type: 'success',
|
|
31
|
-
message: `"${name}" ${__('
|
|
40
|
+
message: `"${name}" ${__('Task cancelled')}`,
|
|
32
41
|
})
|
|
33
42
|
);
|
|
34
43
|
} catch ({ response }) {
|
|
35
44
|
dispatch(
|
|
36
45
|
addToast({
|
|
37
46
|
type: 'error',
|
|
38
|
-
message: `"${name}" ${__('
|
|
47
|
+
message: `"${name}" ${__('Task cannot be cancelled at the moment.')}`,
|
|
39
48
|
})
|
|
40
49
|
);
|
|
41
50
|
}
|
|
@@ -65,3 +74,69 @@ export const resumeTaskRequest = (id, name) => async dispatch => {
|
|
|
65
74
|
);
|
|
66
75
|
}
|
|
67
76
|
};
|
|
77
|
+
|
|
78
|
+
export const selectAllRows = results => ({
|
|
79
|
+
type: SELECT_ROWS,
|
|
80
|
+
payload: results.map(row => row.id),
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
export const unselectAllRows = () => ({
|
|
84
|
+
type: UNSELECT_ALL_ROWS,
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
export const selectRow = id => ({
|
|
88
|
+
type: SELECT_ROWS,
|
|
89
|
+
payload: [id],
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
export const unselectRow = id => ({
|
|
93
|
+
type: UNSELECT_ROWS,
|
|
94
|
+
payload: id,
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
export const actionSelected = (actionType, selected, url) => async dispatch => {
|
|
98
|
+
let notAllActionable = false;
|
|
99
|
+
let someActionable = false;
|
|
100
|
+
const promises = selected.map(task => {
|
|
101
|
+
if (actionType === RESUME && task.isResumeble) {
|
|
102
|
+
someActionable = true;
|
|
103
|
+
return dispatch(resumeTaskRequest(task.id, task.name, url));
|
|
104
|
+
} else if (actionType === CANCEL && task.isCancelleble) {
|
|
105
|
+
someActionable = true;
|
|
106
|
+
return dispatch(cancelTaskRequest(task.id, task.name, url));
|
|
107
|
+
}
|
|
108
|
+
notAllActionable = true;
|
|
109
|
+
return null;
|
|
110
|
+
});
|
|
111
|
+
if (notAllActionable)
|
|
112
|
+
dispatch(
|
|
113
|
+
addToast({
|
|
114
|
+
type: 'warning',
|
|
115
|
+
message: __(
|
|
116
|
+
`Not all the selected tasks can be ${
|
|
117
|
+
actionType === RESUME ? 'resumed' : 'canceled'
|
|
118
|
+
}`
|
|
119
|
+
),
|
|
120
|
+
})
|
|
121
|
+
);
|
|
122
|
+
if (someActionable) {
|
|
123
|
+
await Promise.all(promises);
|
|
124
|
+
dispatch(getTableItems(url));
|
|
125
|
+
dispatch(fetchTasksSummary(getURIQuery(url).time));
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
export const showCancelSelcetedModal = () => ({
|
|
130
|
+
type: TASKS_TABLE_SELECTED_MODAL,
|
|
131
|
+
payload: CANCEL,
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
export const showResumeSelcetedModal = () => ({
|
|
135
|
+
type: TASKS_TABLE_SELECTED_MODAL,
|
|
136
|
+
payload: RESUME,
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
export const hideSelcetedModal = () => ({
|
|
140
|
+
type: TASKS_TABLE_SELECTED_MODAL,
|
|
141
|
+
payload: CLOSED,
|
|
142
|
+
});
|
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
import { getControllerSearchProps } from 'foremanReact/constants';
|
|
2
2
|
|
|
3
3
|
export const TASKS_TABLE_ID = 'TASKS_TABLE';
|
|
4
|
+
export const TASKS_CONTROLLER = 'tasks';
|
|
5
|
+
export const TASKS_SUCCESS = 'TASKS_SUCCESS';
|
|
6
|
+
export const TASKS_REQUEST = 'TASKS_REQUEST';
|
|
7
|
+
export const TASKS_FAILURE = 'TASKS_FAILURE';
|
|
8
|
+
export const SELECT_ROWS = 'SELECT_ROWS';
|
|
9
|
+
export const UNSELECT_ROWS = 'UNSELECT_ROWS';
|
|
10
|
+
export const UNSELECT_ALL_ROWS = 'UNSELECT_ALL_ROWS';
|
|
11
|
+
export const CANCEL = 'CANCEL';
|
|
12
|
+
export const RESUME = 'RESUME';
|
|
13
|
+
export const CLOSED = 'CLOSED';
|
|
4
14
|
|
|
15
|
+
export const TASKS_TABLE_SELECTED_MODAL = 'TASKS_TABLE_SELECTED_MODAL';
|
|
5
16
|
export const TASKS_SEARCH_PROPS = getControllerSearchProps('tasks');
|
|
@@ -3,13 +3,21 @@ import PropTypes from 'prop-types';
|
|
|
3
3
|
import { getURIsearch } from 'foremanReact/common/urlHelpers';
|
|
4
4
|
import { Spinner } from 'patternfly-react';
|
|
5
5
|
import PageLayout from 'foremanReact/routes/common/PageLayout/PageLayout';
|
|
6
|
+
import { translate as __ } from 'foremanReact/common/I18n';
|
|
6
7
|
import { getURIQuery } from 'foremanReact/common/helpers';
|
|
7
8
|
import ExportButton from 'foremanReact/routes/common/PageLayout/components/ExportButton/ExportButton';
|
|
8
9
|
import { STATUS } from 'foremanReact/constants';
|
|
9
10
|
import TasksDashboard from '../TasksDashboard';
|
|
10
11
|
import TasksTable from './TasksTable';
|
|
11
12
|
import { resolveSearchQuery, addSearchToURL } from './TasksTableHelpers';
|
|
12
|
-
import {
|
|
13
|
+
import { CancelResumeConfirm } from './Components/CancelResumeConfirm';
|
|
14
|
+
import {
|
|
15
|
+
TASKS_SEARCH_PROPS,
|
|
16
|
+
RESUME,
|
|
17
|
+
CANCEL,
|
|
18
|
+
CLOSED,
|
|
19
|
+
} from './TasksTableConstants';
|
|
20
|
+
import { ActionSelectButton } from './Components/ActionSelectButton';
|
|
13
21
|
import './TasksTablePage.scss';
|
|
14
22
|
|
|
15
23
|
const TasksTablePage = ({ getBreadcrumbs, history, ...props }) => {
|
|
@@ -20,8 +28,31 @@ const TasksTablePage = ({ getBreadcrumbs, history, ...props }) => {
|
|
|
20
28
|
props.getTableItems(url);
|
|
21
29
|
};
|
|
22
30
|
|
|
31
|
+
const getSelected = () => {
|
|
32
|
+
const selected = props.results.filter(item =>
|
|
33
|
+
props.selectedRows.includes(item.id)
|
|
34
|
+
);
|
|
35
|
+
return selected.map(item => ({
|
|
36
|
+
name: item.action,
|
|
37
|
+
id: item.id,
|
|
38
|
+
isCancelleble: item.availableActions.cancellable,
|
|
39
|
+
isResumeble: item.availableActions.resumable,
|
|
40
|
+
}));
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const TaskSelectedAction = (id, name) => {
|
|
44
|
+
props.actionSelected(id, name, url);
|
|
45
|
+
};
|
|
46
|
+
|
|
23
47
|
return (
|
|
24
48
|
<div className="tasks-table-wrapper">
|
|
49
|
+
<CancelResumeConfirm
|
|
50
|
+
closeModal={props.hideSelcetedModal}
|
|
51
|
+
action={TaskSelectedAction}
|
|
52
|
+
selected={getSelected()}
|
|
53
|
+
modalStatus={props.modalStatus}
|
|
54
|
+
selectedRowsLen={props.selectedRows.length}
|
|
55
|
+
/>
|
|
25
56
|
<PageLayout
|
|
26
57
|
searchable
|
|
27
58
|
searchProps={TASKS_SEARCH_PROPS}
|
|
@@ -33,6 +64,12 @@ const TasksTablePage = ({ getBreadcrumbs, history, ...props }) => {
|
|
|
33
64
|
{props.status === STATUS.PENDING && <Spinner size="lg" loading />}
|
|
34
65
|
<ExportButton
|
|
35
66
|
url={addSearchToURL('/foreman_tasks/tasks.csv', uriQuery)}
|
|
67
|
+
title={__('Export All')}
|
|
68
|
+
/>
|
|
69
|
+
<ActionSelectButton
|
|
70
|
+
disabled={props.selectedRows.length < 1}
|
|
71
|
+
onCancel={props.showCancelSelcetedModal}
|
|
72
|
+
onResume={props.showResumeSelcetedModal}
|
|
36
73
|
/>
|
|
37
74
|
</React.Fragment>
|
|
38
75
|
}
|
|
@@ -46,18 +83,27 @@ const TasksTablePage = ({ getBreadcrumbs, history, ...props }) => {
|
|
|
46
83
|
};
|
|
47
84
|
|
|
48
85
|
TasksTablePage.propTypes = {
|
|
86
|
+
results: PropTypes.array.isRequired,
|
|
49
87
|
getTableItems: PropTypes.func.isRequired,
|
|
50
88
|
getBreadcrumbs: PropTypes.func.isRequired,
|
|
51
89
|
actionName: PropTypes.string,
|
|
52
90
|
isSubTask: PropTypes.bool,
|
|
53
91
|
status: PropTypes.oneOf(Object.keys(STATUS)),
|
|
54
92
|
history: PropTypes.object.isRequired,
|
|
93
|
+
actionSelected: PropTypes.func.isRequired,
|
|
94
|
+
selectedRows: PropTypes.arrayOf(PropTypes.string),
|
|
95
|
+
showResumeSelcetedModal: PropTypes.func.isRequired,
|
|
96
|
+
showCancelSelcetedModal: PropTypes.func.isRequired,
|
|
97
|
+
hideSelcetedModal: PropTypes.func.isRequired,
|
|
98
|
+
modalStatus: PropTypes.oneOf([CANCEL, RESUME, CLOSED]),
|
|
55
99
|
};
|
|
56
100
|
|
|
57
101
|
TasksTablePage.defaultProps = {
|
|
58
102
|
actionName: '',
|
|
59
103
|
isSubTask: false,
|
|
60
104
|
status: STATUS.PENDING,
|
|
105
|
+
selectedRows: [],
|
|
106
|
+
modalStatus: CLOSED,
|
|
61
107
|
};
|
|
62
108
|
|
|
63
109
|
export default TasksTablePage;
|
|
@@ -1,19 +1,26 @@
|
|
|
1
1
|
import Immutable from 'seamless-immutable';
|
|
2
2
|
import { combineReducers } from 'redux';
|
|
3
|
+
import { union } from 'lodash';
|
|
3
4
|
import { createTableReducer } from 'foremanReact/components/common/table';
|
|
4
5
|
import createTableActionTypes from 'foremanReact/components/common/table/actionsHelpers/actionTypeCreator';
|
|
5
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
TASKS_TABLE_ID,
|
|
8
|
+
SELECT_ROWS,
|
|
9
|
+
UNSELECT_ROWS,
|
|
10
|
+
UNSELECT_ALL_ROWS,
|
|
11
|
+
TASKS_TABLE_SELECTED_MODAL,
|
|
12
|
+
CLOSED,
|
|
13
|
+
} from './TasksTableConstants';
|
|
6
14
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
} = action;
|
|
15
|
+
const initialState = Immutable({
|
|
16
|
+
selectedRows: [],
|
|
17
|
+
modalStatus: CLOSED,
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
export const TasksTableQueryReducer = (state = initialState, action) => {
|
|
21
|
+
const { type, payload } = action;
|
|
22
|
+
const { subtotal, page, per_page: perPageString, action_name: actionName } =
|
|
23
|
+
payload || {};
|
|
17
24
|
const ACTION_TYPES = createTableActionTypes(TASKS_TABLE_ID);
|
|
18
25
|
switch (type) {
|
|
19
26
|
case ACTION_TYPES.SUCCESS:
|
|
@@ -24,7 +31,19 @@ export const TasksTableQueryReducer = (state = {}, action) => {
|
|
|
24
31
|
page: Number(page),
|
|
25
32
|
perPage: Number(perPageString),
|
|
26
33
|
},
|
|
34
|
+
selectedRows: [],
|
|
27
35
|
});
|
|
36
|
+
case SELECT_ROWS:
|
|
37
|
+
return state.set('selectedRows', union(payload, state.selectedRows));
|
|
38
|
+
case UNSELECT_ROWS:
|
|
39
|
+
return state.set(
|
|
40
|
+
'selectedRows',
|
|
41
|
+
state.selectedRows.filter(row => row !== payload)
|
|
42
|
+
);
|
|
43
|
+
case UNSELECT_ALL_ROWS:
|
|
44
|
+
return state.set('selectedRows', []);
|
|
45
|
+
case TASKS_TABLE_SELECTED_MODAL:
|
|
46
|
+
return state.set('modalStatus', payload);
|
|
28
47
|
default:
|
|
29
48
|
return state;
|
|
30
49
|
}
|
|
@@ -6,11 +6,13 @@ import {
|
|
|
6
6
|
} from 'foremanReact/components/common/table';
|
|
7
7
|
import { translate as __ } from 'foremanReact/common/I18n';
|
|
8
8
|
import {
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
selectionHeaderCellFormatter,
|
|
10
|
+
selectionCellFormatter,
|
|
11
11
|
actionNameCellFormatter,
|
|
12
12
|
durationCellFormmatter,
|
|
13
|
-
|
|
13
|
+
actionCellFormatter,
|
|
14
|
+
dateCellFormmatter,
|
|
15
|
+
} from './formatters';
|
|
14
16
|
|
|
15
17
|
const headFormat = [headerFormatterWithProps];
|
|
16
18
|
const cellFormat = [cellFormatter];
|
|
@@ -25,7 +27,14 @@ const cellFormat = [cellFormatter];
|
|
|
25
27
|
* @param {function} cancelTask A function to run when the cancel cell is clicked
|
|
26
28
|
* @return {Array}
|
|
27
29
|
*/
|
|
28
|
-
|
|
30
|
+
|
|
31
|
+
const createTasksTableSchema = (
|
|
32
|
+
setSort,
|
|
33
|
+
by,
|
|
34
|
+
order,
|
|
35
|
+
taskActions,
|
|
36
|
+
selectionController
|
|
37
|
+
) => {
|
|
29
38
|
const sortController = {
|
|
30
39
|
apply: setSort,
|
|
31
40
|
property: by,
|
|
@@ -33,6 +42,15 @@ const createTasksTableSchema = (setSort, by, order, taskActions) => {
|
|
|
33
42
|
};
|
|
34
43
|
|
|
35
44
|
return [
|
|
45
|
+
column(
|
|
46
|
+
'select',
|
|
47
|
+
'Select all rows',
|
|
48
|
+
[label => selectionHeaderCellFormatter(selectionController, label)],
|
|
49
|
+
[
|
|
50
|
+
(value, additionalData) =>
|
|
51
|
+
selectionCellFormatter(selectionController, additionalData),
|
|
52
|
+
]
|
|
53
|
+
),
|
|
36
54
|
column(
|
|
37
55
|
'action',
|
|
38
56
|
__('Action'),
|
|
@@ -53,7 +71,7 @@ const createTasksTableSchema = (setSort, by, order, taskActions) => {
|
|
|
53
71
|
durationCellFormmatter,
|
|
54
72
|
]),
|
|
55
73
|
column(
|
|
56
|
-
'
|
|
74
|
+
'availableActions',
|
|
57
75
|
__('Operation'),
|
|
58
76
|
headFormat,
|
|
59
77
|
[actionCellFormatter(taskActions)],
|