mirror of
https://github.com/strapi/strapi.git
synced 2025-11-03 11:25:17 +00:00
fix(ee): logic for finding an entities target stage
This commit is contained in:
parent
f5279be28c
commit
d8da5b5214
@ -156,7 +156,7 @@ describe('Review workflows - Stages service', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('Should move entities in a deleted stage to the previous stage', async () => {
|
test('Should move entities in a deleted stage to the previous stage', async () => {
|
||||||
await stagesService.replaceWorkflowStages(1, workflowMock.stages.slice(0, 1));
|
await stagesService.replaceWorkflowStages(1, workflowMock.stages.slice(0, 2));
|
||||||
|
|
||||||
expect(servicesMock['admin::workflows'].findById).toBeCalled();
|
expect(servicesMock['admin::workflows'].findById).toBeCalled();
|
||||||
expect(entityServiceMock.create).not.toBeCalled();
|
expect(entityServiceMock.create).not.toBeCalled();
|
||||||
@ -173,7 +173,7 @@ describe('Review workflows - Stages service', () => {
|
|||||||
|
|
||||||
expect(servicesMock['admin::workflows'].update).toBeCalled();
|
expect(servicesMock['admin::workflows'].update).toBeCalled();
|
||||||
expect(servicesMock['admin::workflows'].update).toBeCalledWith(workflowMock.id, {
|
expect(servicesMock['admin::workflows'].update).toBeCalledWith(workflowMock.id, {
|
||||||
stages: [workflowMock.stages[0].id],
|
stages: [workflowMock.stages[0].id, workflowMock.stages[1].id],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -65,6 +65,8 @@ module.exports = ({ strapi }) => {
|
|||||||
const defaultWorkflow = await getDefaultWorkflow({ strapi });
|
const defaultWorkflow = await getDefaultWorkflow({ strapi });
|
||||||
|
|
||||||
await mapAsync(updated, (stage) => this.update(stage.id, stage));
|
await mapAsync(updated, (stage) => this.update(stage.id, stage));
|
||||||
|
|
||||||
|
const entitiesToMove = [];
|
||||||
await mapAsync(deleted, async (stage) => {
|
await mapAsync(deleted, async (stage) => {
|
||||||
// Find any entities related to this stage
|
// Find any entities related to this stage
|
||||||
const stageInfo = await this.findById(stage.id, {
|
const stageInfo = await this.findById(stage.id, {
|
||||||
@ -73,25 +75,39 @@ module.exports = ({ strapi }) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if ((stageInfo?.related?.length ?? 0) === 0) {
|
if ((stageInfo?.related?.length ?? 0) === 0) {
|
||||||
|
// If there are no related entities, just delete the stage
|
||||||
return this.delete(stage.id);
|
return this.delete(stage.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This stage has related entities that we need to move to the
|
// This stage has related entities that need to be moved to their
|
||||||
// previous stage
|
// target stage
|
||||||
const previousStage =
|
// Find the nearest stage in the workflow that is not deleted,
|
||||||
defaultWorkflow.stages[defaultWorkflow.stages.findIndex((s) => s.id === stage.id) - 1];
|
// prioritizing the previous stages
|
||||||
|
const targetStageId = findNearestMatchingStageID(
|
||||||
|
defaultWorkflow.stages,
|
||||||
|
defaultWorkflow.stages.findIndex((s) => s.id === stage.id),
|
||||||
|
(targetStage) => {
|
||||||
|
return !deleted.find((s) => s.id === targetStage.id);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
mapAsync(stageInfo.related, (entity) => {
|
// Keep track of the entities to move and their target stages
|
||||||
|
entitiesToMove.push(...stageInfo.related.map((entity) => ({ ...entity, targetStageId })));
|
||||||
|
|
||||||
|
return this.delete(stage.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Move all the entities whose stage was deleted to their target stage
|
||||||
|
mapAsync(entitiesToMove, (entity) => {
|
||||||
return this.updateEntity(
|
return this.updateEntity(
|
||||||
{
|
{
|
||||||
id: entity.id,
|
id: entity.id,
|
||||||
modelUID: entity.__type,
|
modelUID: entity.__type,
|
||||||
},
|
},
|
||||||
previousStage.id
|
entity.targetStageId
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
return this.delete(stage.id);
|
|
||||||
});
|
|
||||||
return workflowsService.update(workflowId, {
|
return workflowsService.update(workflowId, {
|
||||||
stages: stagesIds,
|
stages: stagesIds,
|
||||||
});
|
});
|
||||||
@ -174,3 +190,27 @@ function assertAtLeastOneStageRemain(workflowStages, diffStages) {
|
|||||||
throw new ApplicationError('At least one stage must remain in the workflow.');
|
throw new ApplicationError('At least one stage must remain in the workflow.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the nearest object in an array that matches a condition.
|
||||||
|
* Starts by searching the elements before the index, then the remaining elements in the array.
|
||||||
|
*
|
||||||
|
* @param {Array} array of stages
|
||||||
|
* @param {Number} index the index to start searching from
|
||||||
|
* @param {Function} condition must evaluate to true for the object to be considered a match
|
||||||
|
* @returns {Object}
|
||||||
|
*/
|
||||||
|
function findNearestMatchingStageID(array, index, condition) {
|
||||||
|
// Start by searching the elements before the index
|
||||||
|
for (let i = index; i >= 0; i -= 1) {
|
||||||
|
if (condition(array[i])) {
|
||||||
|
return array[i].id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no matching element is found before the index,
|
||||||
|
// search the remaining elements in the array
|
||||||
|
const remainingArray = array.slice(index + 1);
|
||||||
|
const nearestObject = remainingArray.filter(condition)[0];
|
||||||
|
return nearestObject.id;
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user