Skip to content
Merged
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
23 changes: 15 additions & 8 deletions src/components/HOCs/WithCurrentTask/WithCurrentTask.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -231,15 +231,20 @@ export const mapDispatchToProps = (dispatch, ownProps) => {
// Wait for all parallel tasks to complete
await Promise.all(parallelTasks);

// Handle next task loading - this needs to be sequential
// Handle next task loading - this needs to be sequential.
// challengeIdFromRoute falls back to props.challengeId, and ownProps
// carries one only when the route does (/challenge/:challengeId/task/
// :taskId). On the bare /task/:taskId route it doesn't, so seed it
// with the id the caller already handed us.
const nextTaskProps = { ...ownProps, challengeId };
if (taskLoadBy) {
// Start loading the next task from the challenge.
const loadNextTask = Number.isFinite(requestedNextTask)
? await nextRequestedTask(dispatch, ownProps, requestedNextTask)
: await nextRandomTask(dispatch, ownProps, taskId, taskLoadBy);
? await nextRequestedTask(dispatch, nextTaskProps, requestedNextTask)
: await nextRandomTask(dispatch, nextTaskProps, taskId, taskLoadBy);

try {
await visitNewTask(dispatch, ownProps, taskId, loadNextTask);
await visitNewTask(dispatch, nextTaskProps, taskId, loadNextTask);
} catch (error) {
ownProps.history.push(`/browse/challenges/${challengeId}`);
}
Expand Down Expand Up @@ -287,13 +292,15 @@ export const mapDispatchToProps = (dispatch, ownProps) => {
dispatch(addTaskComment(taskId, comment));
}

// See completeTask above for why challengeId has to be seeded here
const nextTaskProps = { ...ownProps, challengeId };
if (taskLoadBy === TaskLoadMethod.proximity && requestedNextTask) {
nextRequestedTask(dispatch, ownProps, requestedNextTask).then((newTask) =>
visitNewTask(dispatch, ownProps, taskId, newTask),
nextRequestedTask(dispatch, nextTaskProps, requestedNextTask).then((newTask) =>
visitNewTask(dispatch, nextTaskProps, taskId, newTask),
);
} else {
nextRandomTask(dispatch, ownProps, taskId, taskLoadBy).then((newTask) =>
visitNewTask(dispatch, ownProps, taskId, newTask),
nextRandomTask(dispatch, nextTaskProps, taskId, taskLoadBy).then((newTask) =>
visitNewTask(dispatch, nextTaskProps, taskId, newTask),
);
}
},
Expand Down
14 changes: 11 additions & 3 deletions src/components/TaskPane/TaskPane.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -605,9 +605,17 @@ export class TaskPane extends Component {
<Fragment>
<button
className="mr-button mr-button--white mr-mr-4"
onClick={() =>
this.props.history.push(`/task/${this.props.taskLockConflict.lockedTaskId}`)
}
onClick={() => {
// Route through the challenge whenever we know it: on the
// bare /task/:id route nothing supplies a challenge id,
// and loading the next task after completion needs one
const { lockedTaskId, parentId } = this.props.taskLockConflict;
this.props.history.push(
Number.isFinite(parentId)
? `/challenge/${parentId}/task/${lockedTaskId}`
: `/task/${lockedTaskId}`,
);
}}
>
<FormattedMessage {...messages.goToLockedTaskLabel} />
</button>
Expand Down
1 change: 1 addition & 0 deletions src/services/Task/LockConflict.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export const getLockConflict = (error) => {

return {
lockedTaskId: details.lockedTaskId,
parentId: typeof details.parentId === "number" ? details.parentId : null,
parentName: details.parentName ?? null,
bundledTasks: details.bundledTasks ?? [],
startedAt: details.startedAt ?? null,
Expand Down
5 changes: 4 additions & 1 deletion src/services/Task/LockConflict.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ describe("getLockConflict", () => {
details: {
message: "User 1 already holds a lock on item 123",
lockedTaskId: 123,
parentId: 42,
parentName: "Some Challenge",
bundledTasks: [124, 125],
startedAt: "2026-01-01T00:00:00Z",
Expand All @@ -30,21 +31,23 @@ describe("getLockConflict", () => {

expect(getLockConflict(error)).toEqual({
lockedTaskId: 123,
parentId: 42,
parentName: "Some Challenge",
bundledTasks: [124, 125],
startedAt: "2026-01-01T00:00:00Z",
message: "User 1 already holds a lock on item 123",
});
});

it("defaults parentName/bundledTasks/startedAt when absent", () => {
it("defaults parentId/parentName/bundledTasks/startedAt when absent", () => {
const error = {
response: { status: 409 },
details: { message: "conflict", lockedTaskId: 123 },
};

expect(getLockConflict(error)).toEqual({
lockedTaskId: 123,
parentId: null,
parentName: null,
bundledTasks: [],
startedAt: null,
Expand Down
Loading