mirror of
https://github.com/strapi/strapi.git
synced 2025-11-14 01:02:04 +00:00
feat(review-workflows): add update route on entity for stages
This commit is contained in:
parent
782009fded
commit
1cf3da856c
@ -1,7 +1,11 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
const { ApplicationError } = require('@strapi/utils/lib/errors');
|
||||||
const { getService } = require('../../../utils');
|
const { getService } = require('../../../utils');
|
||||||
const { validateUpdateStages } = require('../../../validation/review-workflows');
|
const {
|
||||||
|
validateUpdateStages,
|
||||||
|
validateUpdateStageOnEntity,
|
||||||
|
} = require('../../../validation/review-workflows');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
/**
|
/**
|
||||||
@ -54,4 +58,24 @@ module.exports = {
|
|||||||
|
|
||||||
ctx.body = { data };
|
ctx.body = { data };
|
||||||
},
|
},
|
||||||
|
|
||||||
|
async updateEntity(ctx) {
|
||||||
|
const stagesService = getService('stages');
|
||||||
|
const reviewWorkflowsService = getService('review-workflows');
|
||||||
|
const { model_uid: modelUID, id: entityId } = ctx.params;
|
||||||
|
|
||||||
|
const { id: stageId } = await validateUpdateStageOnEntity(
|
||||||
|
ctx.request?.body?.data,
|
||||||
|
'You shall pass an id to the body of the put request.'
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!reviewWorkflowsService.isReviewWorkflowEnabled({ strapi }, modelUID)) {
|
||||||
|
throw new ApplicationError(`Review workflows is not activated on ${modelUID}.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO When multiple workflows are possible, check if the stage is part of the right one
|
||||||
|
// Didn't need this today as their can only be one workflow
|
||||||
|
|
||||||
|
ctx.body = await stagesService.updateEntity({ id: entityId, modelUID }, stageId);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@ -209,4 +209,21 @@ module.exports = [
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
method: 'PUT',
|
||||||
|
path: '/content-manager/(collection|single)-types/:model_uid/:id/stage',
|
||||||
|
handler: 'stages.updateEntity',
|
||||||
|
config: {
|
||||||
|
middlewares: [enableFeatureMiddleware('review-workflows')],
|
||||||
|
policies: [
|
||||||
|
'admin::isAuthenticatedAdmin',
|
||||||
|
{
|
||||||
|
name: 'admin::hasPermissions',
|
||||||
|
config: {
|
||||||
|
actions: ['admin::review-workflows.read'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|||||||
@ -11,7 +11,7 @@ const { ENTITY_STAGE_ATTRIBUTE } = require('../../constants/workflows');
|
|||||||
const {
|
const {
|
||||||
disableOnContentTypes: disableReviewWorkflows,
|
disableOnContentTypes: disableReviewWorkflows,
|
||||||
} = require('../../migrations/review-workflows');
|
} = require('../../migrations/review-workflows');
|
||||||
const { getDefaultWorkflow } = require('../../utils/review-workflows');
|
const { getDefaultWorkflow, hasRWEnabled } = require('../../utils/review-workflows');
|
||||||
|
|
||||||
const getContentTypeUIDsWithActivatedReviewWorkflows = pipe([
|
const getContentTypeUIDsWithActivatedReviewWorkflows = pipe([
|
||||||
// Pick only content-types with reviewWorkflows options set to true
|
// Pick only content-types with reviewWorkflows options set to true
|
||||||
@ -170,5 +170,9 @@ module.exports = ({ strapi }) => {
|
|||||||
strapi.hook('strapi::content-types.afterSync').register(enableReviewWorkflow({ strapi }));
|
strapi.hook('strapi::content-types.afterSync').register(enableReviewWorkflow({ strapi }));
|
||||||
strapi.hook('strapi::content-types.afterSync').register(disableReviewWorkflows);
|
strapi.hook('strapi::content-types.afterSync').register(disableReviewWorkflows);
|
||||||
},
|
},
|
||||||
|
isReviewWorkflowEnabled({ strapi }, modelUID) {
|
||||||
|
const contentType = strapi.container.get('content-types').get(modelUID);
|
||||||
|
return hasRWEnabled(contentType);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@ -5,7 +5,7 @@ const {
|
|||||||
errors: { ApplicationError },
|
errors: { ApplicationError },
|
||||||
} = require('@strapi/utils');
|
} = require('@strapi/utils');
|
||||||
|
|
||||||
const { STAGE_MODEL_UID } = require('../../constants/workflows');
|
const { STAGE_MODEL_UID, ENTITY_STAGE_ATTRIBUTE } = require('../../constants/workflows');
|
||||||
const { getService } = require('../../utils');
|
const { getService } = require('../../utils');
|
||||||
|
|
||||||
module.exports = ({ strapi }) => {
|
module.exports = ({ strapi }) => {
|
||||||
@ -69,6 +69,21 @@ module.exports = ({ strapi }) => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the stage of an entity
|
||||||
|
*
|
||||||
|
* @param {object} entityInfo
|
||||||
|
* @param {string} entityInfo.id - Entity id
|
||||||
|
* @param {string} entityInfo.modelUID - the content-type of the entity
|
||||||
|
* @param {string} stageId - The id of the stage to assign to the entity
|
||||||
|
*/
|
||||||
|
updateEntity(entityInfo, stageId) {
|
||||||
|
return strapi.entityService.update(entityInfo.modelUID, entityInfo.id, {
|
||||||
|
data: { [ENTITY_STAGE_ATTRIBUTE]: Number(stageId) },
|
||||||
|
populate: [ENTITY_STAGE_ATTRIBUTE],
|
||||||
|
});
|
||||||
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -101,6 +101,20 @@ describeOnCondition(edition === 'EE')('Review workflows', () => {
|
|||||||
await builder.cleanup();
|
await builder.cleanup();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
testWorkflow = await strapi.query(WORKFLOW_MODEL_UID).update({
|
||||||
|
where: { id: testWorkflow.id },
|
||||||
|
data: {
|
||||||
|
uid: 'workflow',
|
||||||
|
stages: [defaultStage.id, secondStage.id],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await updateContentType(productUID, {
|
||||||
|
components: [],
|
||||||
|
contentType: model,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('Get workflows', () => {
|
describe('Get workflows', () => {
|
||||||
test("It shouldn't be available for public", async () => {
|
test("It shouldn't be available for public", async () => {
|
||||||
const res = await requests.public.get('/admin/review-workflows/workflows');
|
const res = await requests.public.get('/admin/review-workflows/workflows');
|
||||||
@ -328,8 +342,6 @@ describeOnCondition(edition === 'EE')('Review workflows', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('Enabling/Disabling review workflows on a content type', () => {
|
describe('Enabling/Disabling review workflows on a content type', () => {
|
||||||
let response;
|
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await createEntry(productUID, { name: 'Product' });
|
await createEntry(productUID, { name: 'Product' });
|
||||||
await createEntry(productUID, { name: 'Product 1' });
|
await createEntry(productUID, { name: 'Product 1' });
|
||||||
@ -343,18 +355,18 @@ describeOnCondition(edition === 'EE')('Review workflows', () => {
|
|||||||
});
|
});
|
||||||
await restart();
|
await restart();
|
||||||
|
|
||||||
response = await requests.admin({
|
const response = await requests.admin({
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
url: `/content-type-builder/content-types/api::product.product`,
|
url: `/content-type-builder/content-types/api::product.product`,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(response.body.data.schema.reviewWorkflows).toBeTruthy();
|
expect(response.body.data.schema.reviewWorkflows).toBeTruthy();
|
||||||
|
|
||||||
response = await getRWMorphTableResults(strapi.db.getConnection());
|
const morphTableResults = await getRWMorphTableResults(strapi.db.getConnection());
|
||||||
|
|
||||||
expect(response.length).toEqual(3);
|
expect(morphTableResults.length).toEqual(3);
|
||||||
for (let i = 0; i < response.length; i += 1) {
|
for (let i = 0; i < morphTableResults.length; i += 1) {
|
||||||
const entry = response[i];
|
const entry = morphTableResults[i];
|
||||||
expect(entry.related_id).toEqual(i + 1);
|
expect(entry.related_id).toEqual(i + 1);
|
||||||
expect(entry.order).toEqual(1);
|
expect(entry.order).toEqual(1);
|
||||||
}
|
}
|
||||||
@ -368,14 +380,66 @@ describeOnCondition(edition === 'EE')('Review workflows', () => {
|
|||||||
|
|
||||||
await restart();
|
await restart();
|
||||||
|
|
||||||
response = await requests.admin({
|
const response = await requests.admin({
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
url: `/content-type-builder/content-types/api::product.product`,
|
url: `/content-type-builder/content-types/api::product.product`,
|
||||||
});
|
});
|
||||||
expect(response.body.data.schema.reviewWorkflows).toBeFalsy();
|
expect(response.body.data.schema.reviewWorkflows).toBeFalsy();
|
||||||
|
|
||||||
response = await getRWMorphTableResults(strapi.db.getConnection());
|
const morphTableResults = await getRWMorphTableResults(strapi.db.getConnection());
|
||||||
expect(response.length).toEqual(0);
|
expect(morphTableResults.length).toEqual(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('update a stage on an entity', () => {
|
||||||
|
describe('Review Workflow is enabled', () => {
|
||||||
|
beforeAll(async () => {
|
||||||
|
await updateContentType(productUID, {
|
||||||
|
components: [],
|
||||||
|
contentType: { ...model, reviewWorkflows: true },
|
||||||
|
});
|
||||||
|
await restart();
|
||||||
|
});
|
||||||
|
test('Should update the accordingly on an entity', async () => {
|
||||||
|
const entry = await createEntry(productUID, { name: 'Product' });
|
||||||
|
|
||||||
|
const response = await requests.admin({
|
||||||
|
method: 'PUT',
|
||||||
|
url: `/admin/content-manager/collection-types/${productUID}/${entry.id}/stage`,
|
||||||
|
body: {
|
||||||
|
data: { id: secondStage.id },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(response.status).toEqual(200);
|
||||||
|
expect(response.body[ENTITY_STAGE_ATTRIBUTE]).toEqual(
|
||||||
|
expect.objectContaining({ id: secondStage.id })
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('Review Workflow is disabled', () => {
|
||||||
|
beforeAll(async () => {
|
||||||
|
await updateContentType(productUID, {
|
||||||
|
components: [],
|
||||||
|
contentType: { ...model, reviewWorkflows: false },
|
||||||
|
});
|
||||||
|
await restart();
|
||||||
|
});
|
||||||
|
test('Should not update the entity', async () => {
|
||||||
|
const entry = await createEntry(productUID, { name: 'Product' });
|
||||||
|
|
||||||
|
const response = await requests.admin({
|
||||||
|
method: 'PUT',
|
||||||
|
url: `/admin/content-manager/collection-types/${productUID}/${entry.id}/stage`,
|
||||||
|
body: {
|
||||||
|
data: { id: secondStage.id },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(response.status).toEqual(400);
|
||||||
|
expect(response.body.error).toBeDefined();
|
||||||
|
expect(response.body.error.name).toBe('ApplicationError');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -8,10 +8,17 @@ const stageObject = yup.object().shape({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const validateUpdateStagesSchema = yup.array().of(stageObject).required();
|
const validateUpdateStagesSchema = yup.array().of(stageObject).required();
|
||||||
|
const validateUpdateStageOnEntity = yup
|
||||||
|
.object()
|
||||||
|
.shape({
|
||||||
|
id: yup.number().integer().min(1).required(),
|
||||||
|
})
|
||||||
|
.required();
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
validateUpdateStages: validateYupSchema(validateUpdateStagesSchema, {
|
validateUpdateStages: validateYupSchema(validateUpdateStagesSchema, {
|
||||||
strict: false,
|
strict: false,
|
||||||
stripUnknown: true,
|
stripUnknown: true,
|
||||||
}),
|
}),
|
||||||
|
validateUpdateStageOnEntity: validateYupSchema(validateUpdateStageOnEntity),
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user