Merge pull request #16956 from strapi/feature/emit-review-workflow-webhooks

This commit is contained in:
Jamie Howard 2023-06-20 08:53:48 +01:00 committed by GitHub
commit 7427fb4845
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 92 additions and 15 deletions

View File

@ -2,22 +2,21 @@ import React from 'react';
import EventTable from '../../../../../../../../../admin/src/pages/SettingsPage/pages/Webhooks/EditView/components/Events';
// const events = {
// 'review-workflows': ['workflows.updateEntryStage'],
// };
const events = {
'review-workflows': ['review-workflows.updateEntryStage'],
};
// TODO: extend this to support review workflow events once the BE logic is ready
// const getHeaders = () => {
// return [{ id: 'review-workflows.updateEntryStage', defaultMessage: 'Stage Change' }];
// };
const getHeaders = () => {
return [{ id: 'review-workflows.updateEntryStage', defaultMessage: 'Stage Change' }];
};
export function EventTableEE() {
return (
<EventTable.Root>
<EventTable.Headers />
<EventTable.Body />
{/* <EventTable.Headers getHeaders={getHeaders} />
<EventTable.Body providedEvents={events} /> */}
<EventTable.Headers getHeaders={getHeaders} />
<EventTable.Body providedEvents={events} />
</EventTable.Root>
);
}

View File

@ -0,0 +1,5 @@
'use strict';
module.exports = {
WORKFLOW_UPDATE_STAGE: 'review-workflows.updateEntryStage',
};

View File

@ -1,6 +1,7 @@
'use strict';
const { omit } = require('lodash/fp');
const { WORKFLOW_UPDATE_STAGE } = require('../../../constants/webhookEvents');
const { decorator } = require('../entity-service-decorator')();
jest.mock('../../../utils');
@ -80,6 +81,8 @@ describe('Entity service decorator', () => {
});
describe('Update', () => {
const uid = 'test-model';
test('Calls original update for non review workflow content types', async () => {
const entry = {
id: 1,
@ -107,13 +110,38 @@ describe('Entity service decorator', () => {
update: jest.fn(() => Promise.resolve(entry)),
};
global.strapi = {
...global.strapi,
entityService: {
findOne: jest.fn(() => {
return { strapi_reviewWorkflows_stage: { id: 2, workflow: { id: 1 } } };
}),
emitEvent: jest.fn(),
},
};
const service = decorator(defaultService);
const id = 1;
const input = { data: { title: 'title ', strapi_reviewWorkflows_stage: 1 } };
await service.update('test-model', id, input);
await service.update(uid, id, input);
expect(defaultService.update).toHaveBeenCalledWith('test-model', id, {
expect(global.strapi.entityService.emitEvent).toHaveBeenCalledWith(
uid,
WORKFLOW_UPDATE_STAGE,
{
entityId: 1,
workflow: {
id: 1,
stages: {
from: 2,
to: 1,
},
},
}
);
expect(defaultService.update).toHaveBeenCalledWith(uid, id, {
...input,
data: {
...input.data,
@ -135,9 +163,9 @@ describe('Entity service decorator', () => {
const id = 1;
const input = { data: { title: 'title ', strapi_reviewWorkflows_stage: null } };
await service.update('test-model', id, input);
await service.update(uid, id, input);
expect(defaultService.update).toHaveBeenCalledWith('test-model', id, {
expect(defaultService.update).toHaveBeenCalledWith(uid, id, {
...input,
data: {
...omit('strapi_reviewWorkflows_stage', input.data),

View File

@ -2,6 +2,7 @@
const { isNil, isNull } = require('lodash/fp');
const { ENTITY_STAGE_ATTRIBUTE } = require('../../constants/workflows');
const { WORKFLOW_UPDATE_STAGE } = require('../../constants/webhookEvents');
const { hasReviewWorkflow, getDefaultWorkflow } = require('../../utils/review-workflows');
/**
@ -17,6 +18,25 @@ const getDataWithStage = async (data) => {
return data;
};
/**
* Get the stage information of an entity
* @param {String} uid
* @param {Number} id
* @returns {Object}
*/
const getEntityStage = async (uid, id) => {
const entity = await strapi.entityService.findOne(uid, id, {
populate: {
[ENTITY_STAGE_ATTRIBUTE]: {
populate: {
workflow: true,
},
},
},
});
return entity?.[ENTITY_STAGE_ATTRIBUTE] ?? {};
};
/**
* Decorates the entity service with RW business logic
* @param {object} service - entity service
@ -43,9 +63,31 @@ const decorator = (service) => ({
const data = { ...opts.data };
if (isNull(data[ENTITY_STAGE_ATTRIBUTE])) {
delete data[ENTITY_STAGE_ATTRIBUTE];
return service.update.call(this, uid, entityId, { ...opts, data });
}
return service.update.call(this, uid, entityId, { ...opts, data });
const previousStage = await getEntityStage(uid, entityId);
const updatedEntity = await service.update.call(this, uid, entityId, { ...opts, data });
if (
previousStage?.workflow?.id &&
previousStage?.id &&
previousStage.id !== data[ENTITY_STAGE_ATTRIBUTE]
) {
const webhookPayload = {
entityId,
workflow: {
id: previousStage.workflow.id,
stages: {
from: previousStage.id,
to: data[ENTITY_STAGE_ATTRIBUTE],
},
},
};
await strapi.entityService.emitEvent(uid, WORKFLOW_UPDATE_STAGE, webhookPayload);
}
return updatedEntity;
},
});

View File

@ -11,6 +11,7 @@ const { ENTITY_STAGE_ATTRIBUTE } = require('../../constants/workflows');
const { getDefaultWorkflow } = require('../../utils/review-workflows');
const { persistTables, removePersistedTablesWithSuffix } = require('../../utils/persisted-tables');
const webhookEvents = require('../../constants/webhookEvents');
async function initDefaultWorkflow({ workflowsService, stagesService, strapi }) {
const wfCount = await workflowsService.count();
@ -109,7 +110,9 @@ function persistStagesJoinTables({ strapi }) {
}
const registerWebhookEvents = async ({ strapi }) =>
strapi.webhookStore.addAllowedEvent('WORKFLOW_UPDATE_STAGE', 'workflow.updateEntryStage');
Object.entries(webhookEvents).forEach(([eventKey, event]) =>
strapi.webhookStore.addAllowedEvent(eventKey, event)
);
module.exports = ({ strapi }) => {
const workflowsService = getService('workflows', { strapi });