Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions src/components/HOCs/WithTaskReview/WithTaskReview.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,41 @@ const mapDispatchToProps = (dispatch, ownProps) => {
}
},

/**
* Standalone task-completion-status update used by reviewers from the
* Completion widget in the Review pane. Preserves the current review
* status (so it doesn't double-count as a review action) and does not
* navigate away from the current task — the reviewer is expected to
* continue reviewing after correcting the status.
*/
updateTaskCompletionStatus: (task, newTaskStatus, comment, taskBundle) => {
const submitAsMetaReview = asMetaReview(ownProps);
const action = taskBundle
? completeBundleReview(
taskBundle.bundleId,
task.reviewStatus,
comment,
null,
newTaskStatus,
submitAsMetaReview,
undefined,
)
: completeReview(
task.id,
task.reviewStatus,
comment,
null,
newTaskStatus,
submitAsMetaReview,
undefined,
);

return dispatch(action).catch((error) => {
console.log(error);
dispatch(addError(AppErrors.task.updateFailure));
});
},

skipTaskReview: (task, loadBy, url) => {
dispatch(cancelReviewClaim(task.id));
loadNextTaskForReview(dispatch, url, task.id, asMetaReview(ownProps)).then((nextTask) =>
Expand Down
9 changes: 7 additions & 2 deletions src/components/ReviewTaskPane/ReviewTaskPane.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,17 @@ export const defaultWorkspaceSetup = function () {
widgetDescriptor("TaskHistoryWidget"),
widgetDescriptor("TaskInstructionsWidget"),
widgetDescriptor("TaskMapWidget"),
widgetDescriptor("TaskCompletionWidget"),
],
layout: [
{ i: generateWidgetId(), x: 0, y: 0, w: 4, h: 9 },
{ i: generateWidgetId(), x: 0, y: 0, w: 4, h: 8 },
{ i: generateWidgetId(), x: 0, y: 9, w: 4, h: 8 },
{ i: generateWidgetId(), x: 0, y: 17, w: 4, h: 4 },
{ i: generateWidgetId(), x: 4, y: 0, w: 8, h: 18 },
{ i: generateWidgetId(), x: 0, y: 21, w: 4, h: 8 },
],
excludeWidgets: ["TaskCompletionWidget", "TagDiffWidget"],
excludeWidgets: ["TagDiffWidget"],
};
};

Expand All @@ -59,15 +61,17 @@ export const defaultWorkspaceSetupAlt = function () {
widgetDescriptor("TasksWidget"),
widgetDescriptor("TaskHistoryWidget"),
widgetDescriptor("TaskInstructionsWidget"),
widgetDescriptor("TaskCompletionWidget"),
],
layout: [
{ i: generateWidgetId(), x: 0, y: 0, w: 4, h: 9 },
{ i: generateWidgetId(), x: 0, y: 0, w: 4, h: 8 },
{ i: generateWidgetId(), x: 0, y: 9, w: 4, h: 8 },
{ i: generateWidgetId(), x: 0, y: 17, w: 4, h: 4 },
{ i: generateWidgetId(), x: 4, y: 0, w: 4, h: 18 },
{ i: generateWidgetId(), x: 0, y: 21, w: 4, h: 8 },
],
excludeWidgets: ["TaskCompletionWidget", "TagDiffWidget", "TaskMapWidget"],
excludeWidgets: ["TagDiffWidget", "TaskMapWidget"],
};
};

Expand Down Expand Up @@ -188,6 +192,7 @@ export class ReviewTaskPane extends Component {
setCompletionResponse={this.setCompletionResponse}
completionResponses={completionResponses}
templateRevision={true}
asReviewer
/>
</MediaQuery>
<MediaQuery query="(max-width: 1023px)">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,7 @@ export class TaskConfirmationModal extends Component {
)}
{this.props.status !== TaskStatus.skipped &&
!reviewConfirmation &&
!this.props.asReviewer &&
this.props.user.settings.needsReview !== needsReviewType.mandatory && (
<div className="form mr-flex mr-items-baseline">
<input
Expand Down Expand Up @@ -445,7 +446,7 @@ export class TaskConfirmationModal extends Component {
</button>
</div>

{!reviewConfirmation && (
{!reviewConfirmation && !this.props.asReviewer && (
<div className="mr-mt-8">
<div className="form">
<span className="mr-mr-4">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,19 @@ export class ActiveTaskControls extends Component {
this.props.saveTaskTags(this.props.task, this.state.tags);
}

// Reviewer is correcting just the completion state from the Review
// pane: keep the existing review status, update only the task status,
// and stay on the current task so reviewing can continue.
if (this.props.asReviewer) {
await this.props.updateTaskCompletionStatus(
this.props.task,
taskStatus,
this.state.comment,
taskBundle,
);
return;
}

const revisionSubmission = this.props.task.reviewStatus === TaskReviewStatus.rejected;

if (this.state.submitRevision !== undefined) {
Expand Down Expand Up @@ -428,10 +441,14 @@ export class ActiveTaskControls extends Component {

const fromInbox = this.props.history?.location?.state?.fromInbox;

// Reviewers correcting completion state need a broad set of valid
// status transitions regardless of the current task status. Reuse the
// "for revision" progression set, which lists the final completion
// statuses (Fixed/AlreadyFixed/FalsePositive/TooHard) minus the current one.
const allowedProgressions = allowedStatusProgressions(
this.props.task.status,
false,
needsRevised,
needsRevised || this.props.asReviewer,
);
const isComplete = isCompletionStatus(this.props.task.status);
const isFinal = isFinalStatus(this.props.task.status);
Expand Down Expand Up @@ -491,6 +508,7 @@ export class ActiveTaskControls extends Component {
<Fragment>
{isTagFix &&
(!isFinal || needsRevised || this.state.completingTask) &&
!this.props.asReviewer &&
this.props.user.settings.seeTagFixSuggestions && (
<CooperativeWorkControls
{...this.props}
Expand All @@ -505,22 +523,25 @@ export class ActiveTaskControls extends Component {
)}

{(!isTagFix || !this.props.user.settings.seeTagFixSuggestions) &&
(!isFinal || needsRevised || this.state.completingTask) && (
(!isFinal ||
needsRevised ||
this.props.asReviewer ||
this.state.completingTask) && (
<TaskCompletionStep
{...this.props}
allowedEditors={this.allowedEditors()}
allowedProgressions={allowedProgressions}
pickEditor={this.pickEditor}
complete={this.initiateCompletion}
nextTask={this.next}
needsRevised={needsRevised}
needsRevised={needsRevised && !this.props.asReviewer}
editMode={editMode}
disabled={this.state.completingTask}
isCompleting={this.state.completingTask}
/>
)}

{!this.state.completingTask && isComplete && !needsRevised && (
{!this.state.completingTask && isComplete && !needsRevised && !this.props.asReviewer && (
<TaskNextControl
{...this.props}
className="mr-mt-1"
Expand Down
Loading