diff options
author | Stas Vilchik <stas.vilchik@sonarsource.com> | 2018-10-24 17:19:49 +0200 |
---|---|---|
committer | SonarTech <sonartech@sonarsource.com> | 2018-10-26 20:21:00 +0200 |
commit | 150f201ab694713194c18feb2abc7f75f0327c05 (patch) | |
tree | e5fc8286ddd8a953f12fa59915b5f68d5e5da426 | |
parent | 3026740ee3e483b542aca2fad5f5e79a931faa87 (diff) | |
download | sonarqube-150f201ab694713194c18feb2abc7f75f0327c05.tar.gz sonarqube-150f201ab694713194c18feb2abc7f75f0327c05.zip |
SONAR-11263 Add a confirmation modal when canceling background tasks
9 files changed, 65 insertions, 23 deletions
diff --git a/server/sonar-web/src/main/js/apps/background-tasks/__tests__/BackgroundTasks-test.tsx b/server/sonar-web/src/main/js/apps/background-tasks/__tests__/BackgroundTasks-test.tsx index 8dfe21635f4..f9ff5094c66 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/__tests__/BackgroundTasks-test.tsx +++ b/server/sonar-web/src/main/js/apps/background-tasks/__tests__/BackgroundTasks-test.tsx @@ -99,7 +99,7 @@ describe('Stats', () => { const result = shallow( <Stats onCancelAllPending={stub} onShowFailing={stub} pendingCount={0} /> ); - expect(result.find('.js-cancel-pending').length).toBe(0); + expect(result.find('[data-test="cancel-pending"]').length).toBe(0); }); it('should show cancel pending button', () => { @@ -111,7 +111,7 @@ describe('Stats', () => { pendingCount={5} /> ); - expect(result.find('.js-cancel-pending').length).toBe(1); + expect(result.find('[data-test="cancel-pending"]').length).toBe(1); }); it('should trigger cancelling pending', () => { @@ -125,7 +125,7 @@ describe('Stats', () => { /> ); expect(spy).not.toBeCalled(); - click(result.find('.js-cancel-pending')); + result.find('[data-test="cancel-pending"]').prop<Function>('onConfirm')(); expect(spy).toBeCalled(); }); }); diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/BackgroundTasksApp.tsx b/server/sonar-web/src/main/js/apps/background-tasks/components/BackgroundTasksApp.tsx index 9dcbfda40c0..4542c958b05 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/components/BackgroundTasksApp.tsx +++ b/server/sonar-web/src/main/js/apps/background-tasks/components/BackgroundTasksApp.tsx @@ -174,7 +174,7 @@ class BackgroundTasksApp extends React.PureComponent<Props, State> { handleCancelTask = (task: Task) => { this.setState({ loading: true }); - cancelTaskAPI(task.id).then(nextTask => { + return cancelTaskAPI(task.id).then(nextTask => { if (this.mounted) { this.setState(state => ({ tasks: updateTask(state.tasks, nextTask), @@ -196,7 +196,7 @@ class BackgroundTasksApp extends React.PureComponent<Props, State> { }); } - handleCancelAllPending() { + handleCancelAllPending = () => { this.setState({ loading: true }); cancelAllTasks().then(() => { @@ -204,7 +204,7 @@ class BackgroundTasksApp extends React.PureComponent<Props, State> { this.loadTasks(); } }, this.stopLoading); - } + }; render() { const { component } = this.props; diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/Stats.tsx b/server/sonar-web/src/main/js/apps/background-tasks/components/Stats.tsx index 31d9365d975..dd05ac309ef 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/components/Stats.tsx +++ b/server/sonar-web/src/main/js/apps/background-tasks/components/Stats.tsx @@ -21,6 +21,7 @@ import * as React from 'react'; import Tooltip from '../../../components/controls/Tooltip'; import { DeleteButton } from '../../../components/ui/buttons'; import { translate } from '../../../helpers/l10n'; +import ConfirmButton from '../../../components/controls/ConfirmButton'; interface Props { component?: unknown; @@ -46,16 +47,28 @@ export default class Stats extends React.PureComponent<Props> { return ( <span> <span className="js-pending-count emphasised-measure">{this.props.pendingCount}</span> - - {translate('background_tasks.pending')} - {this.props.isSystemAdmin && ( - <Tooltip overlay={translate('background_tasks.cancel_all_tasks')}> - <DeleteButton - className="js-cancel-pending spacer-left" - onClick={this.props.onCancelAllPending} - /> - </Tooltip> - )} + <span className="display-inline-flex-center little-spacer-left"> + {translate('background_tasks.pending')} + {this.props.isSystemAdmin && ( + <ConfirmButton + cancelButtonText={translate('close')} + confirmButtonText={translate('background_tasks.cancel_all_tasks.submit')} + data-test="cancel-pending" + isDestructive={true} + modalBody={translate('background_tasks.cancel_all_tasks.text')} + modalHeader={translate('background_tasks.cancel_all_tasks')} + onConfirm={this.props.onCancelAllPending}> + {({ onClick }) => ( + <Tooltip overlay={translate('background_tasks.cancel_all_tasks')}> + <DeleteButton + className="js-cancel-pending little-spacer-left" + onClick={onClick} + /> + </Tooltip> + )} + </ConfirmButton> + )} + </span> </span> ); } else { @@ -99,8 +112,7 @@ export default class Stats extends React.PureComponent<Props> { <Tooltip overlay={translate('background_tasks.failing_count')}> <span className="js-failures-count emphasised-measure">{this.props.failingCount}</span> </Tooltip> - - {translate('background_tasks.failures')} + <span className="little-spacer-left">{translate('background_tasks.failures')}</span> </span> ); } diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/Task.tsx b/server/sonar-web/src/main/js/apps/background-tasks/components/Task.tsx index 7dd532d3f98..903dad8de13 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/components/Task.tsx +++ b/server/sonar-web/src/main/js/apps/background-tasks/components/Task.tsx @@ -30,7 +30,7 @@ import { Task as TaskType } from '../../../app/types'; interface Props { component?: unknown; - onCancelTask: (task: TaskType) => void; + onCancelTask: (task: TaskType) => Promise<void>; onFilterTask: (task: TaskType) => void; task: TaskType; previousTask?: TaskType; diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/TaskActions.tsx b/server/sonar-web/src/main/js/apps/background-tasks/components/TaskActions.tsx index 814611067c7..fbabb073096 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/components/TaskActions.tsx +++ b/server/sonar-web/src/main/js/apps/background-tasks/components/TaskActions.tsx @@ -25,6 +25,7 @@ import { translate, translateWithParameters } from '../../../helpers/l10n'; import ActionsDropdown, { ActionsDropdownItem } from '../../../components/controls/ActionsDropdown'; import { Task } from '../../../app/types'; import { lazyLoad } from '../../../components/lazyLoad'; +import ConfirmModal from '../../../components/controls/ConfirmModal'; const AnalysisWarningsModal = lazyLoad( () => import('../../../components/common/AnalysisWarningsModal'), @@ -33,12 +34,13 @@ const AnalysisWarningsModal = lazyLoad( interface Props { component?: unknown; - onCancelTask: (task: Task) => void; + onCancelTask: (task: Task) => Promise<void>; onFilterTask: (task: Task) => void; task: Task; } interface State { + cancelTaskOpen: boolean; scannerContextOpen: boolean; stacktraceOpen: boolean; warningsOpen: boolean; @@ -46,6 +48,7 @@ interface State { export default class TaskActions extends React.PureComponent<Props, State> { state: State = { + cancelTaskOpen: false, scannerContextOpen: false, stacktraceOpen: false, warningsOpen: false @@ -55,14 +58,22 @@ export default class TaskActions extends React.PureComponent<Props, State> { this.props.onFilterTask(this.props.task); }; + handleCancelTask = () => { + return this.props.onCancelTask(this.props.task); + }; + handleCancelClick = () => { - this.props.onCancelTask(this.props.task); + this.setState({ cancelTaskOpen: true }); }; handleShowScannerContextClick = () => { this.setState({ scannerContextOpen: true }); }; + closeCancelTask = () => { + this.setState({ cancelTaskOpen: false }); + }; + closeScannerContext = () => { this.setState({ scannerContextOpen: false }); }; @@ -140,6 +151,18 @@ export default class TaskActions extends React.PureComponent<Props, State> { )} </ActionsDropdown> + {this.state.cancelTaskOpen && ( + <ConfirmModal + cancelButtonText={translate('close')} + confirmButtonText={translate('background_tasks.cancel_task')} + header={translate('background_tasks.cancel_task')} + isDestructive={true} + onClose={this.closeCancelTask} + onConfirm={this.handleCancelTask}> + {translate('background_tasks.cancel_task.text')} + </ConfirmModal> + )} + {this.state.scannerContextOpen && ( <ScannerContext onClose={this.closeScannerContext} task={task} /> )} diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/Tasks.tsx b/server/sonar-web/src/main/js/apps/background-tasks/components/Tasks.tsx index db104a80984..3f803849b55 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/components/Tasks.tsx +++ b/server/sonar-web/src/main/js/apps/background-tasks/components/Tasks.tsx @@ -27,7 +27,7 @@ interface Props { tasks: TaskType[]; component?: unknown; loading: boolean; - onCancelTask: (task: TaskType) => void; + onCancelTask: (task: TaskType) => Promise<void>; onFilterTask: (task: TaskType) => void; } diff --git a/server/sonar-web/src/main/js/components/controls/ConfirmButton.tsx b/server/sonar-web/src/main/js/components/controls/ConfirmButton.tsx index f9d609f9698..5a8a127df19 100644 --- a/server/sonar-web/src/main/js/components/controls/ConfirmButton.tsx +++ b/server/sonar-web/src/main/js/components/controls/ConfirmButton.tsx @@ -25,6 +25,7 @@ export { ChildrenProps } from './ModalButton'; interface Props { children: (props: ChildrenProps) => React.ReactNode; + cancelButtonText?: string; confirmButtonText: string; confirmData?: string; confirmDisable?: boolean; @@ -42,6 +43,7 @@ export default class ConfirmButton extends React.PureComponent<Props, State> { renderConfirmModal = ({ onClose }: ModalProps) => { return ( <ConfirmModal + cancelButtonText={this.props.cancelButtonText} confirmButtonText={this.props.confirmButtonText} confirmData={this.props.confirmData} confirmDisable={this.props.confirmDisable} diff --git a/server/sonar-web/src/main/js/components/controls/ConfirmModal.tsx b/server/sonar-web/src/main/js/components/controls/ConfirmModal.tsx index cd34fcafb0b..71256dd8ace 100644 --- a/server/sonar-web/src/main/js/components/controls/ConfirmModal.tsx +++ b/server/sonar-web/src/main/js/components/controls/ConfirmModal.tsx @@ -25,6 +25,7 @@ import { SubmitButton, ResetButtonLink } from '../ui/buttons'; interface Props<T> { children: React.ReactNode; + cancelButtonText?: string; confirmButtonText: string; confirmData?: T; confirmDisable?: boolean; @@ -57,6 +58,7 @@ export default class ConfirmModal<T = string> extends React.PureComponent<Props< renderModalContent = ({ onCloseClick, onFormSubmit, submitting }: ChildrenProps) => { const { children, confirmButtonText, confirmDisable, header, isDestructive } = this.props; + const { cancelButtonText = translate('cancel') } = this.props; return ( <form onSubmit={onFormSubmit}> <header className="modal-head"> @@ -72,7 +74,7 @@ export default class ConfirmModal<T = string> extends React.PureComponent<Props< {confirmButtonText} </SubmitButton> <ResetButtonLink disabled={submitting} onClick={onCloseClick}> - {translate('cancel')} + {cancelButtonText} </ResetButtonLink> </footer> </form> diff --git a/sonar-core/src/main/resources/org/sonar/l10n/core.properties b/sonar-core/src/main/resources/org/sonar/l10n/core.properties index aaeadbb45f8..04de8134d70 100644 --- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties +++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties @@ -2315,7 +2315,10 @@ background_tasks.table.duration=Duration background_tasks.filter_by_component_x=Filter by Component "{0}" background_tasks.cancel_task=Cancel Task +background_tasks.cancel_task.text=Are you sure you want to cancel this pending task? background_tasks.cancel_all_tasks=Cancel All Pending Tasks +background_tasks.cancel_all_tasks.text=Are you sure you want to cancel all pending tasks? +background_tasks.cancel_all_tasks.submit=Cancel All background_tasks.scanner_context=Scanner Context background_tasks.show_scanner_context=Show Scanner Context background_tasks.show_stacktrace=Show Error Details |