aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStas Vilchik <stas.vilchik@sonarsource.com>2018-10-24 17:19:49 +0200
committerSonarTech <sonartech@sonarsource.com>2018-10-26 20:21:00 +0200
commit150f201ab694713194c18feb2abc7f75f0327c05 (patch)
treee5fc8286ddd8a953f12fa59915b5f68d5e5da426
parent3026740ee3e483b542aca2fad5f5e79a931faa87 (diff)
downloadsonarqube-150f201ab694713194c18feb2abc7f75f0327c05.tar.gz
sonarqube-150f201ab694713194c18feb2abc7f75f0327c05.zip
SONAR-11263 Add a confirmation modal when canceling background tasks
-rw-r--r--server/sonar-web/src/main/js/apps/background-tasks/__tests__/BackgroundTasks-test.tsx6
-rw-r--r--server/sonar-web/src/main/js/apps/background-tasks/components/BackgroundTasksApp.tsx6
-rw-r--r--server/sonar-web/src/main/js/apps/background-tasks/components/Stats.tsx36
-rw-r--r--server/sonar-web/src/main/js/apps/background-tasks/components/Task.tsx2
-rw-r--r--server/sonar-web/src/main/js/apps/background-tasks/components/TaskActions.tsx27
-rw-r--r--server/sonar-web/src/main/js/apps/background-tasks/components/Tasks.tsx2
-rw-r--r--server/sonar-web/src/main/js/components/controls/ConfirmButton.tsx2
-rw-r--r--server/sonar-web/src/main/js/components/controls/ConfirmModal.tsx4
-rw-r--r--sonar-core/src/main/resources/org/sonar/l10n/core.properties3
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>
- &nbsp;
- {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>
- &nbsp;
- {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