foreman-tasks 11.0.5 → 11.0.7
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/assets/javascripts/foreman-tasks/locale/de/foreman_tasks.js +5 -2
- data/app/assets/javascripts/foreman-tasks/locale/en/foreman_tasks.js +4 -1
- data/app/assets/javascripts/foreman-tasks/locale/es/foreman_tasks.js +5 -2
- data/app/assets/javascripts/foreman-tasks/locale/fr/foreman_tasks.js +11 -8
- data/app/assets/javascripts/foreman-tasks/locale/ja/foreman_tasks.js +12 -9
- data/app/assets/javascripts/foreman-tasks/locale/ka/foreman_tasks.js +5 -2
- data/app/assets/javascripts/foreman-tasks/locale/ko/foreman_tasks.js +167 -165
- data/app/assets/javascripts/foreman-tasks/locale/pt_BR/foreman_tasks.js +5 -2
- data/app/assets/javascripts/foreman-tasks/locale/ru/foreman_tasks.js +5 -2
- data/app/assets/javascripts/foreman-tasks/locale/zh_CN/foreman_tasks.js +11 -8
- data/app/assets/javascripts/foreman-tasks/locale/zh_TW/foreman_tasks.js +5 -2
- data/lib/foreman_tasks/dynflow/console_authorizer.rb +1 -3
- data/lib/foreman_tasks/version.rb +1 -1
- data/locale/Makefile +18 -7
- data/locale/de/LC_MESSAGES/foreman_tasks.mo +0 -0
- data/locale/de/foreman_tasks.po +5 -2
- data/locale/en/LC_MESSAGES/foreman_tasks.mo +0 -0
- data/locale/en/foreman_tasks.po +4 -1
- data/locale/es/LC_MESSAGES/foreman_tasks.mo +0 -0
- data/locale/es/foreman_tasks.po +5 -2
- data/locale/foreman_tasks.pot +10 -6
- data/locale/fr/LC_MESSAGES/foreman_tasks.mo +0 -0
- data/locale/fr/foreman_tasks.po +11 -8
- data/locale/ja/LC_MESSAGES/foreman_tasks.mo +0 -0
- data/locale/ja/foreman_tasks.po +12 -9
- data/locale/ka/LC_MESSAGES/foreman_tasks.mo +0 -0
- data/locale/ka/foreman_tasks.po +5 -2
- data/locale/ko/LC_MESSAGES/foreman_tasks.mo +0 -0
- data/locale/ko/foreman_tasks.po +167 -165
- data/locale/pt_BR/LC_MESSAGES/foreman_tasks.mo +0 -0
- data/locale/pt_BR/foreman_tasks.po +5 -2
- data/locale/ru/LC_MESSAGES/foreman_tasks.mo +0 -0
- data/locale/ru/foreman_tasks.po +5 -2
- data/locale/zh_CN/LC_MESSAGES/foreman_tasks.mo +0 -0
- data/locale/zh_CN/foreman_tasks.po +11 -8
- data/locale/zh_TW/LC_MESSAGES/foreman_tasks.mo +0 -0
- data/locale/zh_TW/foreman_tasks.po +5 -2
- data/webpack/ForemanTasks/Components/TaskDetails/Components/Task.js +37 -9
- data/webpack/ForemanTasks/Components/TaskDetails/Components/TaskButtons.js +19 -16
- data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/TaskButtons.test.js +197 -71
- data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/Task.test.js.snap +24 -40
- data/webpack/ForemanTasks/Components/TaskDetails/__tests__/__snapshots__/TaskDetails.test.js.snap +2 -16
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/ConfirmModalSelectors.js +0 -16
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/GenericConfirmModal.js +70 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/ConfirmModalSelectors.test.js +25 -14
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/__snapshots__/ConfirmModalSelectors.test.js.snap +8 -7
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/index.test.js +409 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/createBulkTaskModal.js +67 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/createTaskModal.js +51 -0
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/index.js +73 -23
- data/webpack/ForemanTasks/Components/TasksTable/TasksTable.js +5 -2
- data/webpack/ForemanTasks/Components/TasksTable/TasksTableConstants.js +1 -1
- data/webpack/ForemanTasks/Components/TasksTable/TasksTablePage.js +67 -11
- data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTablePage.test.js.snap +86 -6
- data/webpack/ForemanTasks/Components/common/ClickConfirmation/ClickConfirmation.test.js +225 -39
- data/webpack/ForemanTasks/Components/common/ClickConfirmation/index.js +136 -37
- metadata +6 -19
- data/webpack/ForemanTasks/Components/TaskActions/UnlockModals.js +0 -60
- data/webpack/ForemanTasks/Components/TaskActions/UnlockModals.test.js +0 -14
- data/webpack/ForemanTasks/Components/TaskActions/__snapshots__/UnlockModals.test.js.snap +0 -25
- data/webpack/ForemanTasks/Components/TaskDetails/Components/__tests__/__snapshots__/TaskButtons.test.js.snap +0 -212
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/ConfirmModal.js +0 -83
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/ConfirmModalActions.js +0 -106
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/ConfirmModalReducer.js +0 -38
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/ConfirmModal.test.js +0 -36
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/ConfirmModalActions.test.js +0 -205
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/ConfirmModalReducer.test.js +0 -27
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/__snapshots__/ConfirmModal.test.js.snap +0 -41
- data/webpack/ForemanTasks/Components/TasksTable/Components/ConfirmModal/__test__/__snapshots__/ConfirmModalReducer.test.js.snap +0 -19
- data/webpack/ForemanTasks/Components/common/ClickConfirmation/ClickConfirmation.scss +0 -9
- data/webpack/ForemanTasks/Components/common/ClickConfirmation/__snapshots__/ClickConfirmation.test.js.snap +0 -52
- data/webpack/__mocks__/foremanReact/components/ForemanModal/ForemanModalActions.js +0 -2
- data/webpack/__mocks__/foremanReact/components/ForemanModal/ForemanModalHooks.js +0 -10
- data/webpack/__mocks__/foremanReact/components/ForemanModal/index.js +0 -18
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
import URI from 'urijs';
|
|
4
4
|
import { getURIsearch } from 'foremanReact/common/urlHelpers';
|
|
@@ -8,17 +8,25 @@ import { translate as __ } from 'foremanReact/common/I18n';
|
|
|
8
8
|
import { getURIQuery } from 'foremanReact/common/helpers';
|
|
9
9
|
import ExportButton from 'foremanReact/routes/common/PageLayout/components/ExportButton/ExportButton';
|
|
10
10
|
import { STATUS } from 'foremanReact/constants';
|
|
11
|
-
import { useForemanModal } from 'foremanReact/components/ForemanModal/ForemanModalHooks';
|
|
12
11
|
import TasksDashboard from '../TasksDashboard';
|
|
13
12
|
import TasksTable from './TasksTable';
|
|
14
13
|
import { getCSVurl, updateURlQuery } from './TasksTableHelpers';
|
|
15
|
-
import
|
|
14
|
+
import {
|
|
15
|
+
CancelModal,
|
|
16
|
+
ResumeModal,
|
|
17
|
+
CancelSelectedModal,
|
|
18
|
+
ResumeSelectedModal,
|
|
19
|
+
ForceUnlockModal,
|
|
20
|
+
ForceUnlockSelectedModal,
|
|
21
|
+
} from './Components/ConfirmModal';
|
|
16
22
|
import {
|
|
17
23
|
TASKS_SEARCH_PROPS,
|
|
18
24
|
CANCEL_SELECTED_MODAL,
|
|
19
25
|
RESUME_SELECTED_MODAL,
|
|
20
26
|
FORCE_UNLOCK_SELECTED_MODAL,
|
|
21
|
-
|
|
27
|
+
CANCEL_MODAL,
|
|
28
|
+
RESUME_MODAL,
|
|
29
|
+
FORCE_UNLOCK_MODAL,
|
|
22
30
|
} from './TasksTableConstants';
|
|
23
31
|
import { ActionSelectButton } from './Components/ActionSelectButton';
|
|
24
32
|
import './TasksTablePage.scss';
|
|
@@ -48,21 +56,69 @@ const TasksTablePage = ({
|
|
|
48
56
|
updateURlQuery(newUriQuery, history);
|
|
49
57
|
}
|
|
50
58
|
};
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
59
|
+
const [modalStates, setModalStates] = useState({
|
|
60
|
+
[CANCEL_MODAL]: false,
|
|
61
|
+
[RESUME_MODAL]: false,
|
|
62
|
+
[CANCEL_SELECTED_MODAL]: false,
|
|
63
|
+
[RESUME_SELECTED_MODAL]: false,
|
|
64
|
+
[FORCE_UNLOCK_MODAL]: false,
|
|
65
|
+
[FORCE_UNLOCK_SELECTED_MODAL]: false,
|
|
54
66
|
});
|
|
55
67
|
|
|
56
|
-
const openModal = id =>
|
|
68
|
+
const openModal = id => {
|
|
69
|
+
setModalStates(prev => ({
|
|
70
|
+
...prev,
|
|
71
|
+
[id]: true,
|
|
72
|
+
}));
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const closeModal = id => {
|
|
76
|
+
setModalStates(prev => ({
|
|
77
|
+
...prev,
|
|
78
|
+
[id]: false,
|
|
79
|
+
}));
|
|
80
|
+
};
|
|
57
81
|
|
|
58
82
|
return (
|
|
59
83
|
<div className="tasks-table-wrapper">
|
|
60
|
-
<
|
|
61
|
-
|
|
84
|
+
<CancelModal
|
|
85
|
+
isModalOpen={modalStates[CANCEL_MODAL]}
|
|
86
|
+
setIsModalOpen={() => closeModal(CANCEL_MODAL)}
|
|
87
|
+
url={url}
|
|
88
|
+
parentTaskID={props.parentTaskID}
|
|
89
|
+
/>
|
|
90
|
+
<ResumeModal
|
|
91
|
+
isModalOpen={modalStates[RESUME_MODAL]}
|
|
92
|
+
setIsModalOpen={() => closeModal(RESUME_MODAL)}
|
|
93
|
+
url={url}
|
|
94
|
+
parentTaskID={props.parentTaskID}
|
|
95
|
+
/>
|
|
96
|
+
<CancelSelectedModal
|
|
97
|
+
isModalOpen={modalStates[CANCEL_SELECTED_MODAL]}
|
|
98
|
+
setIsModalOpen={() => closeModal(CANCEL_SELECTED_MODAL)}
|
|
62
99
|
url={url}
|
|
100
|
+
uriQuery={uriQuery}
|
|
63
101
|
parentTaskID={props.parentTaskID}
|
|
102
|
+
/>
|
|
103
|
+
<ResumeSelectedModal
|
|
104
|
+
isModalOpen={modalStates[RESUME_SELECTED_MODAL]}
|
|
105
|
+
setIsModalOpen={() => closeModal(RESUME_SELECTED_MODAL)}
|
|
106
|
+
url={url}
|
|
64
107
|
uriQuery={uriQuery}
|
|
65
|
-
|
|
108
|
+
parentTaskID={props.parentTaskID}
|
|
109
|
+
/>
|
|
110
|
+
<ForceUnlockModal
|
|
111
|
+
isModalOpen={modalStates[FORCE_UNLOCK_MODAL]}
|
|
112
|
+
setIsModalOpen={() => closeModal(FORCE_UNLOCK_MODAL)}
|
|
113
|
+
url={url}
|
|
114
|
+
parentTaskID={props.parentTaskID}
|
|
115
|
+
/>
|
|
116
|
+
<ForceUnlockSelectedModal
|
|
117
|
+
isModalOpen={modalStates[FORCE_UNLOCK_SELECTED_MODAL]}
|
|
118
|
+
setIsModalOpen={() => closeModal(FORCE_UNLOCK_SELECTED_MODAL)}
|
|
119
|
+
url={url}
|
|
120
|
+
uriQuery={uriQuery}
|
|
121
|
+
parentTaskID={props.parentTaskID}
|
|
66
122
|
/>
|
|
67
123
|
<PageLayout
|
|
68
124
|
searchable
|
data/webpack/ForemanTasks/Components/TasksTable/__tests__/__snapshots__/TasksTablePage.test.js.snap
CHANGED
|
@@ -4,10 +4,50 @@ exports[`TasksTablePage rendering render with Breadcrubs and edit permissions 1`
|
|
|
4
4
|
<div
|
|
5
5
|
className="tasks-table-wrapper"
|
|
6
6
|
>
|
|
7
|
-
<
|
|
8
|
-
|
|
7
|
+
<TaskModal
|
|
8
|
+
isModalOpen={false}
|
|
9
9
|
parentTaskID={null}
|
|
10
|
-
|
|
10
|
+
setIsModalOpen={[Function]}
|
|
11
|
+
url="/foreman_tasks/tasks?action=\\"some-name\\""
|
|
12
|
+
/>
|
|
13
|
+
<TaskModal
|
|
14
|
+
isModalOpen={false}
|
|
15
|
+
parentTaskID={null}
|
|
16
|
+
setIsModalOpen={[Function]}
|
|
17
|
+
url="/foreman_tasks/tasks?action=\\"some-name\\""
|
|
18
|
+
/>
|
|
19
|
+
<BulkTaskModal
|
|
20
|
+
isModalOpen={false}
|
|
21
|
+
parentTaskID={null}
|
|
22
|
+
setIsModalOpen={[Function]}
|
|
23
|
+
uriQuery={
|
|
24
|
+
Object {
|
|
25
|
+
"state": "stopped",
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
url="/foreman_tasks/tasks?action=\\"some-name\\""
|
|
29
|
+
/>
|
|
30
|
+
<BulkTaskModal
|
|
31
|
+
isModalOpen={false}
|
|
32
|
+
parentTaskID={null}
|
|
33
|
+
setIsModalOpen={[Function]}
|
|
34
|
+
uriQuery={
|
|
35
|
+
Object {
|
|
36
|
+
"state": "stopped",
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
url="/foreman_tasks/tasks?action=\\"some-name\\""
|
|
40
|
+
/>
|
|
41
|
+
<TaskModal
|
|
42
|
+
isModalOpen={false}
|
|
43
|
+
parentTaskID={null}
|
|
44
|
+
setIsModalOpen={[Function]}
|
|
45
|
+
url="/foreman_tasks/tasks?action=\\"some-name\\""
|
|
46
|
+
/>
|
|
47
|
+
<BulkTaskModal
|
|
48
|
+
isModalOpen={false}
|
|
49
|
+
parentTaskID={null}
|
|
50
|
+
setIsModalOpen={[Function]}
|
|
11
51
|
uriQuery={
|
|
12
52
|
Object {
|
|
13
53
|
"state": "stopped",
|
|
@@ -156,10 +196,50 @@ exports[`TasksTablePage rendering render with minimal props 1`] = `
|
|
|
156
196
|
<div
|
|
157
197
|
className="tasks-table-wrapper"
|
|
158
198
|
>
|
|
159
|
-
<
|
|
160
|
-
|
|
199
|
+
<TaskModal
|
|
200
|
+
isModalOpen={false}
|
|
201
|
+
parentTaskID={null}
|
|
202
|
+
setIsModalOpen={[Function]}
|
|
203
|
+
url="/foreman_tasks/tasks?action=\\"some-name\\""
|
|
204
|
+
/>
|
|
205
|
+
<TaskModal
|
|
206
|
+
isModalOpen={false}
|
|
207
|
+
parentTaskID={null}
|
|
208
|
+
setIsModalOpen={[Function]}
|
|
209
|
+
url="/foreman_tasks/tasks?action=\\"some-name\\""
|
|
210
|
+
/>
|
|
211
|
+
<BulkTaskModal
|
|
212
|
+
isModalOpen={false}
|
|
213
|
+
parentTaskID={null}
|
|
214
|
+
setIsModalOpen={[Function]}
|
|
215
|
+
uriQuery={
|
|
216
|
+
Object {
|
|
217
|
+
"state": "stopped",
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
url="/foreman_tasks/tasks?action=\\"some-name\\""
|
|
221
|
+
/>
|
|
222
|
+
<BulkTaskModal
|
|
223
|
+
isModalOpen={false}
|
|
224
|
+
parentTaskID={null}
|
|
225
|
+
setIsModalOpen={[Function]}
|
|
226
|
+
uriQuery={
|
|
227
|
+
Object {
|
|
228
|
+
"state": "stopped",
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
url="/foreman_tasks/tasks?action=\\"some-name\\""
|
|
232
|
+
/>
|
|
233
|
+
<TaskModal
|
|
234
|
+
isModalOpen={false}
|
|
235
|
+
parentTaskID={null}
|
|
236
|
+
setIsModalOpen={[Function]}
|
|
237
|
+
url="/foreman_tasks/tasks?action=\\"some-name\\""
|
|
238
|
+
/>
|
|
239
|
+
<BulkTaskModal
|
|
240
|
+
isModalOpen={false}
|
|
161
241
|
parentTaskID={null}
|
|
162
|
-
|
|
242
|
+
setIsModalOpen={[Function]}
|
|
163
243
|
uriQuery={
|
|
164
244
|
Object {
|
|
165
245
|
"state": "stopped",
|
|
@@ -1,44 +1,230 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
confirmType: 'danger',
|
|
10
|
-
body: 'some-body',
|
|
11
|
-
confirmationMessage: 'some-message',
|
|
12
|
-
id: 'some-id',
|
|
13
|
-
confirmAction: 'some-confirm',
|
|
14
|
-
onClick: jest.fn(),
|
|
15
|
-
},
|
|
16
|
-
};
|
|
2
|
+
import { render, screen, fireEvent } from '@testing-library/react';
|
|
3
|
+
import '@testing-library/jest-dom';
|
|
4
|
+
import {
|
|
5
|
+
ClickConfirmation,
|
|
6
|
+
UnlockConfirmationModal,
|
|
7
|
+
ForceUnlockConfirmationModal,
|
|
8
|
+
} from './';
|
|
17
9
|
|
|
18
10
|
describe('ClickConfirmation', () => {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
11
|
+
const defaultProps = {
|
|
12
|
+
title: 'Test Modal',
|
|
13
|
+
body: 'This is a test modal body',
|
|
14
|
+
confirmationMessage: 'I understand the consequences',
|
|
15
|
+
confirmAction: 'Confirm',
|
|
16
|
+
onClick: jest.fn(),
|
|
17
|
+
id: 'test-modal',
|
|
18
|
+
isOpen: true,
|
|
19
|
+
setModalClosed: jest.fn(),
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
beforeEach(() => {
|
|
23
|
+
jest.clearAllMocks();
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
describe('Basic Rendering', () => {
|
|
27
|
+
it('renders modal with correct title and content when open', () => {
|
|
28
|
+
render(<ClickConfirmation {...defaultProps} />);
|
|
29
|
+
|
|
30
|
+
expect(screen.getByText('Test Modal')).toBeInTheDocument();
|
|
31
|
+
expect(screen.getByText('This is a test modal body')).toBeInTheDocument();
|
|
32
|
+
expect(
|
|
33
|
+
screen.getByText('I understand the consequences')
|
|
34
|
+
).toBeInTheDocument();
|
|
35
|
+
expect(screen.getByText('Confirm')).toBeInTheDocument();
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('does not render modal when isOpen is false', () => {
|
|
39
|
+
render(<ClickConfirmation {...defaultProps} isOpen={false} />);
|
|
40
|
+
|
|
41
|
+
expect(screen.queryByText('Test Modal')).not.toBeInTheDocument();
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('renders with warning variant by default', () => {
|
|
45
|
+
render(<ClickConfirmation {...defaultProps} />);
|
|
46
|
+
|
|
47
|
+
const modal = screen.getByRole('dialog');
|
|
48
|
+
expect(modal).toBeInTheDocument();
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('renders with danger variant when specified', () => {
|
|
52
|
+
render(<ClickConfirmation {...defaultProps} confirmType="danger" />);
|
|
53
|
+
|
|
54
|
+
const confirmButton = screen.getByRole('button', { name: 'Confirm' });
|
|
55
|
+
expect(confirmButton).toHaveClass('pf-m-danger');
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
describe('Checkbox Interaction', () => {
|
|
60
|
+
it('starts with checkbox unchecked and confirm button disabled', () => {
|
|
61
|
+
render(<ClickConfirmation {...defaultProps} />);
|
|
62
|
+
|
|
63
|
+
const checkbox = screen.getByRole('checkbox');
|
|
64
|
+
const confirmButton = screen.getByRole('button', { name: 'Confirm' });
|
|
65
|
+
|
|
66
|
+
expect(checkbox).not.toBeChecked();
|
|
67
|
+
expect(confirmButton).toBeDisabled();
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('enables confirm button when checkbox is checked', () => {
|
|
71
|
+
render(<ClickConfirmation {...defaultProps} />);
|
|
72
|
+
|
|
73
|
+
const checkbox = screen.getByRole('checkbox');
|
|
74
|
+
const confirmButton = screen.getByRole('button', { name: 'Confirm' });
|
|
75
|
+
|
|
76
|
+
fireEvent.click(checkbox);
|
|
77
|
+
|
|
78
|
+
expect(checkbox).toBeChecked();
|
|
79
|
+
expect(confirmButton).toBeEnabled();
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('disables confirm button when checkbox is unchecked', () => {
|
|
83
|
+
render(<ClickConfirmation {...defaultProps} />);
|
|
84
|
+
|
|
85
|
+
const checkbox = screen.getByRole('checkbox');
|
|
86
|
+
const confirmButton = screen.getByRole('button', { name: 'Confirm' });
|
|
87
|
+
|
|
88
|
+
// Check the checkbox first
|
|
89
|
+
fireEvent.click(checkbox);
|
|
90
|
+
expect(confirmButton).toBeEnabled();
|
|
91
|
+
|
|
92
|
+
// Uncheck the checkbox
|
|
93
|
+
fireEvent.click(checkbox);
|
|
94
|
+
expect(checkbox).not.toBeChecked();
|
|
95
|
+
expect(confirmButton).toBeDisabled();
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
describe('Button Actions', () => {
|
|
100
|
+
it('calls onClick and setModalClosed when confirm button is clicked', () => {
|
|
101
|
+
const onClick = jest.fn();
|
|
102
|
+
const setModalClosed = jest.fn();
|
|
103
|
+
|
|
104
|
+
render(
|
|
105
|
+
<ClickConfirmation
|
|
106
|
+
{...defaultProps}
|
|
107
|
+
onClick={onClick}
|
|
108
|
+
setModalClosed={setModalClosed}
|
|
109
|
+
/>
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
const checkbox = screen.getByRole('checkbox');
|
|
113
|
+
const confirmButton = screen.getByRole('button', { name: 'Confirm' });
|
|
114
|
+
|
|
115
|
+
// Enable the button by checking the checkbox
|
|
116
|
+
fireEvent.click(checkbox);
|
|
117
|
+
|
|
118
|
+
// Click the confirm button
|
|
119
|
+
fireEvent.click(confirmButton);
|
|
120
|
+
|
|
121
|
+
expect(onClick).toHaveBeenCalledTimes(1);
|
|
122
|
+
expect(setModalClosed).toHaveBeenCalledTimes(1);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it('calls setModalClosed when cancel button is clicked', () => {
|
|
126
|
+
const setModalClosed = jest.fn();
|
|
127
|
+
|
|
128
|
+
render(
|
|
129
|
+
<ClickConfirmation {...defaultProps} setModalClosed={setModalClosed} />
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
const cancelButton = screen.getByRole('button', { name: 'Cancel' });
|
|
133
|
+
fireEvent.click(cancelButton);
|
|
134
|
+
|
|
135
|
+
expect(setModalClosed).toHaveBeenCalledTimes(1);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it('does not call onClick when confirm button is clicked while disabled', () => {
|
|
139
|
+
const onClick = jest.fn();
|
|
140
|
+
|
|
141
|
+
render(<ClickConfirmation {...defaultProps} onClick={onClick} />);
|
|
142
|
+
|
|
143
|
+
const confirmButton = screen.getByRole('button', { name: 'Confirm' });
|
|
144
|
+
|
|
145
|
+
// Try to click the disabled button
|
|
146
|
+
fireEvent.click(confirmButton);
|
|
147
|
+
|
|
148
|
+
expect(onClick).not.toHaveBeenCalled();
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
describe('UnlockModal', () => {
|
|
154
|
+
const defaultProps = {
|
|
155
|
+
onClick: jest.fn(),
|
|
156
|
+
id: 'unlock-modal',
|
|
157
|
+
isOpen: true,
|
|
158
|
+
setModalClosed: jest.fn(),
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
beforeEach(() => {
|
|
162
|
+
jest.clearAllMocks();
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
it('renders with correct unlock-specific content and warning variant', () => {
|
|
166
|
+
render(<UnlockConfirmationModal {...defaultProps} />);
|
|
167
|
+
|
|
168
|
+
expect(
|
|
169
|
+
screen.getByRole('heading', { name: 'Warning alert: Unlock' })
|
|
170
|
+
).toBeInTheDocument();
|
|
171
|
+
expect(
|
|
172
|
+
screen.getByText(
|
|
173
|
+
/This will unlock the resources that the task is running against/
|
|
174
|
+
)
|
|
175
|
+
).toBeInTheDocument();
|
|
176
|
+
expect(
|
|
177
|
+
screen.getByText(
|
|
178
|
+
'I understand that this may cause harm and have working database backups of all backend services.'
|
|
179
|
+
)
|
|
180
|
+
).toBeInTheDocument();
|
|
181
|
+
|
|
182
|
+
const confirmButton = screen.getByRole('button', { name: 'Unlock' });
|
|
183
|
+
expect(confirmButton).toBeInTheDocument();
|
|
184
|
+
expect(confirmButton).toHaveClass('pf-m-primary');
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
describe('ForceUnlockModal', () => {
|
|
189
|
+
const defaultProps = {
|
|
190
|
+
onClick: jest.fn(),
|
|
191
|
+
id: 'force-unlock-modal',
|
|
192
|
+
selectedRowsLen: 3,
|
|
193
|
+
isOpen: true,
|
|
194
|
+
setModalClosed: jest.fn(),
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
beforeEach(() => {
|
|
198
|
+
jest.clearAllMocks();
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
it('renders with correct force unlock-specific content and danger variant', () => {
|
|
202
|
+
render(<ForceUnlockConfirmationModal {...defaultProps} />);
|
|
203
|
+
|
|
204
|
+
expect(
|
|
205
|
+
screen.getByRole('heading', { name: 'Danger alert: Force Unlock' })
|
|
206
|
+
).toBeInTheDocument();
|
|
207
|
+
expect(
|
|
208
|
+
screen.getByText(/Resources for 3 task\(s\) will be unlocked/)
|
|
209
|
+
).toBeInTheDocument();
|
|
210
|
+
expect(
|
|
211
|
+
screen.getByText(
|
|
212
|
+
'I understand that this may cause harm and have working database backups of all backend services.'
|
|
213
|
+
)
|
|
214
|
+
).toBeInTheDocument();
|
|
215
|
+
|
|
216
|
+
const confirmButton = screen.getByRole('button', { name: 'Force Unlock' });
|
|
217
|
+
expect(confirmButton).toBeInTheDocument();
|
|
218
|
+
expect(confirmButton).toHaveClass('pf-m-danger');
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
it('displays correct number of tasks in body', () => {
|
|
222
|
+
render(
|
|
223
|
+
<ForceUnlockConfirmationModal {...defaultProps} selectedRowsLen={5} />
|
|
224
|
+
);
|
|
225
|
+
|
|
226
|
+
expect(
|
|
227
|
+
screen.getByText(/Resources for 5 task\(s\) will be unlocked/)
|
|
228
|
+
).toBeInTheDocument();
|
|
43
229
|
});
|
|
44
230
|
});
|
|
@@ -1,10 +1,17 @@
|
|
|
1
|
-
import React, { useState
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
import {
|
|
4
|
+
Button,
|
|
5
|
+
Modal,
|
|
6
|
+
ModalVariant,
|
|
7
|
+
Checkbox,
|
|
8
|
+
TextContent,
|
|
9
|
+
} from '@patternfly/react-core';
|
|
10
|
+
import { translate as __, sprintf } from 'foremanReact/common/I18n';
|
|
11
|
+
import {
|
|
12
|
+
UNLOCK_MODAL,
|
|
13
|
+
FORCE_UNLOCK_MODAL,
|
|
14
|
+
} from '../../TaskActions/TaskActionsConstants';
|
|
8
15
|
|
|
9
16
|
export const ClickConfirmation = ({
|
|
10
17
|
title,
|
|
@@ -14,48 +21,57 @@ export const ClickConfirmation = ({
|
|
|
14
21
|
id,
|
|
15
22
|
confirmAction,
|
|
16
23
|
onClick,
|
|
24
|
+
isOpen,
|
|
25
|
+
setModalClosed,
|
|
17
26
|
}) => {
|
|
18
27
|
const [isConfirmed, setConfirm] = useState(false);
|
|
19
|
-
const
|
|
20
|
-
id,
|
|
21
|
-
});
|
|
22
|
-
useEffect(() => {
|
|
28
|
+
const onClose = () => {
|
|
23
29
|
setConfirm(false);
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
30
|
+
setModalClosed();
|
|
31
|
+
};
|
|
27
32
|
return (
|
|
28
|
-
<
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
onChange={e => {
|
|
37
|
-
setConfirm(e.target.checked);
|
|
38
|
-
}}
|
|
39
|
-
checked={isConfirmed}
|
|
40
|
-
type="checkbox"
|
|
41
|
-
/>
|
|
42
|
-
<span>{` ${confirmationMessage}`}</span>
|
|
43
|
-
</div>
|
|
44
|
-
<ForemanModal.Footer>
|
|
33
|
+
<Modal
|
|
34
|
+
title={title}
|
|
35
|
+
titleIconVariant={confirmType}
|
|
36
|
+
variant={ModalVariant.small}
|
|
37
|
+
isOpen={isOpen}
|
|
38
|
+
onClose={onClose}
|
|
39
|
+
ouiaId={`${id}-modal`}
|
|
40
|
+
actions={[
|
|
45
41
|
<Button
|
|
42
|
+
ouiaId={`${id}-cancel-button`}
|
|
43
|
+
key="cancel"
|
|
44
|
+
variant="secondary"
|
|
45
|
+
onClick={onClose}
|
|
46
|
+
>
|
|
47
|
+
{__('Cancel')}
|
|
48
|
+
</Button>,
|
|
49
|
+
<Button
|
|
50
|
+
ouiaId={`${id}-confirm-button`}
|
|
51
|
+
key="confirm"
|
|
46
52
|
className="confirm-button"
|
|
53
|
+
variant={confirmType === 'danger' ? 'danger' : 'primary'}
|
|
47
54
|
onClick={() => {
|
|
48
55
|
onClick();
|
|
49
|
-
|
|
56
|
+
onClose();
|
|
50
57
|
}}
|
|
51
|
-
|
|
52
|
-
disabled={!isConfirmed}
|
|
58
|
+
isDisabled={!isConfirmed}
|
|
53
59
|
>
|
|
54
60
|
{confirmAction}
|
|
55
|
-
</Button
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
61
|
+
</Button>,
|
|
62
|
+
]}
|
|
63
|
+
>
|
|
64
|
+
<TextContent>
|
|
65
|
+
{body}
|
|
66
|
+
<Checkbox
|
|
67
|
+
ouiaId={`${id}-confirmation-checkbox`}
|
|
68
|
+
id={`confirmation-checkbox-${id}`}
|
|
69
|
+
label={confirmationMessage}
|
|
70
|
+
isChecked={isConfirmed}
|
|
71
|
+
onChange={(_e, checked) => setConfirm(checked)}
|
|
72
|
+
/>
|
|
73
|
+
</TextContent>
|
|
74
|
+
</Modal>
|
|
59
75
|
);
|
|
60
76
|
};
|
|
61
77
|
|
|
@@ -67,10 +83,93 @@ ClickConfirmation.propTypes = {
|
|
|
67
83
|
onClick: PropTypes.func.isRequired,
|
|
68
84
|
confirmType: PropTypes.oneOf(['warning', 'danger']),
|
|
69
85
|
id: PropTypes.string.isRequired,
|
|
86
|
+
isOpen: PropTypes.bool,
|
|
87
|
+
setModalClosed: PropTypes.func,
|
|
70
88
|
};
|
|
71
89
|
|
|
72
90
|
ClickConfirmation.defaultProps = {
|
|
73
91
|
confirmType: 'warning',
|
|
92
|
+
isOpen: false,
|
|
93
|
+
setModalClosed: () => {},
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
// Unlock Modal Components
|
|
97
|
+
const confirmationMessage = __(
|
|
98
|
+
'I understand that this may cause harm and have working database backups of all backend services.'
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
export const UnlockConfirmationModal = ({
|
|
102
|
+
onClick,
|
|
103
|
+
id,
|
|
104
|
+
isOpen,
|
|
105
|
+
setModalClosed,
|
|
106
|
+
}) => (
|
|
107
|
+
<ClickConfirmation
|
|
108
|
+
id={id}
|
|
109
|
+
title={__('Unlock')}
|
|
110
|
+
body={__(
|
|
111
|
+
"This will unlock the resources that the task is running against. Please note that this might lead to inconsistent state and should be used with caution, after making sure that the task can't be resumed."
|
|
112
|
+
)}
|
|
113
|
+
confirmationMessage={confirmationMessage}
|
|
114
|
+
confirmAction={__('Unlock')}
|
|
115
|
+
onClick={onClick}
|
|
116
|
+
confirmType="warning"
|
|
117
|
+
isOpen={isOpen}
|
|
118
|
+
setModalClosed={setModalClosed}
|
|
119
|
+
/>
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
export const ForceUnlockConfirmationModal = ({
|
|
123
|
+
onClick,
|
|
124
|
+
id,
|
|
125
|
+
selectedRowsLen,
|
|
126
|
+
isOpen,
|
|
127
|
+
setModalClosed,
|
|
128
|
+
}) => (
|
|
129
|
+
<ClickConfirmation
|
|
130
|
+
id={id}
|
|
131
|
+
title={__('Force Unlock')}
|
|
132
|
+
body={sprintf(
|
|
133
|
+
__(
|
|
134
|
+
`Resources for %s task(s) will be unlocked and will not prevent other tasks from being run. As the task(s) might be still running, it should be avoided to use this unless you are really sure the task(s) got stuck.`
|
|
135
|
+
),
|
|
136
|
+
selectedRowsLen
|
|
137
|
+
)}
|
|
138
|
+
confirmationMessage={confirmationMessage}
|
|
139
|
+
confirmAction={__('Force Unlock')}
|
|
140
|
+
onClick={onClick}
|
|
141
|
+
confirmType="danger"
|
|
142
|
+
isOpen={isOpen}
|
|
143
|
+
setModalClosed={setModalClosed}
|
|
144
|
+
/>
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
UnlockConfirmationModal.propTypes = {
|
|
148
|
+
onClick: PropTypes.func.isRequired,
|
|
149
|
+
id: PropTypes.string,
|
|
150
|
+
isOpen: PropTypes.bool,
|
|
151
|
+
setModalClosed: PropTypes.func,
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
ForceUnlockConfirmationModal.propTypes = {
|
|
155
|
+
onClick: PropTypes.func.isRequired,
|
|
156
|
+
id: PropTypes.string,
|
|
157
|
+
selectedRowsLen: PropTypes.number,
|
|
158
|
+
isOpen: PropTypes.bool,
|
|
159
|
+
setModalClosed: PropTypes.func,
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
UnlockConfirmationModal.defaultProps = {
|
|
163
|
+
id: UNLOCK_MODAL,
|
|
164
|
+
isOpen: false,
|
|
165
|
+
setModalClosed: () => {},
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
ForceUnlockConfirmationModal.defaultProps = {
|
|
169
|
+
id: FORCE_UNLOCK_MODAL,
|
|
170
|
+
selectedRowsLen: 1,
|
|
171
|
+
isOpen: false,
|
|
172
|
+
setModalClosed: () => {},
|
|
74
173
|
};
|
|
75
174
|
|
|
76
175
|
export default ClickConfirmation;
|