Browse Source

SONAR-11263 Add a confirmation modal when canceling background tasks

tags/7.5
Stas Vilchik 5 years ago
parent
commit
150f201ab6

+ 3
- 3
server/sonar-web/src/main/js/apps/background-tasks/__tests__/BackgroundTasks-test.tsx View File

@@ -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();
});
});

+ 3
- 3
server/sonar-web/src/main/js/apps/background-tasks/components/BackgroundTasksApp.tsx View File

@@ -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;

+ 24
- 12
server/sonar-web/src/main/js/apps/background-tasks/components/Stats.tsx View File

@@ -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>
);
}

+ 1
- 1
server/sonar-web/src/main/js/apps/background-tasks/components/Task.tsx View File

@@ -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;

+ 25
- 2
server/sonar-web/src/main/js/apps/background-tasks/components/TaskActions.tsx View File

@@ -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} />
)}

+ 1
- 1
server/sonar-web/src/main/js/apps/background-tasks/components/Tasks.tsx View File

@@ -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;
}


+ 2
- 0
server/sonar-web/src/main/js/components/controls/ConfirmButton.tsx View File

@@ -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}

+ 3
- 1
server/sonar-web/src/main/js/components/controls/ConfirmModal.tsx View File

@@ -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>

+ 3
- 0
sonar-core/src/main/resources/org/sonar/l10n/core.properties View File

@@ -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

Loading…
Cancel
Save