feat: add pre save/ post save hooks (#3812)

This commit is contained in:
Bartholomew 2020-05-27 14:14:35 +01:00 committed by GitHub
parent 946f7a0dc4
commit 812716e18b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 46 additions and 32 deletions

View File

@ -226,8 +226,6 @@ export default class TestBackend implements Implementation {
const unpubEntry = {
...unpubStore[existingEntryIndex],
data: raw,
title: options.parsedData && options.parsedData.title,
description: options.parsedData && options.parsedData.description,
mediaFiles: assetProxies.map(this.normalizeAsset),
};
@ -242,8 +240,6 @@ export default class TestBackend implements Implementation {
metaData: {
collection: options.collectionName as string,
status: (options.status || this.options.initialWorkflowStatus) as string,
title: options.parsedData && options.parsedData.title,
description: options.parsedData && options.parsedData.description,
},
slug,
mediaFiles: assetProxies.map(this.normalizeAsset),

View File

@ -702,18 +702,16 @@ export class Backend {
async persistEntry({
config,
collection,
entryDraft,
entryDraft: draft,
assetProxies,
usedSlugs,
unpublished = false,
status,
}: PersistArgs) {
const newEntry = entryDraft.getIn(['entry', 'newRecord']) || false;
const modifiedData = await this.invokePreSaveEvent(draft.get('entry'));
const entryDraft = (modifiedData && draft.setIn(['entry', 'data'], modifiedData)) || draft;
const parsedData = {
title: entryDraft.getIn(['entry', 'data', 'title'], 'No Title') as string,
description: entryDraft.getIn(['entry', 'data', 'description'], 'No Description!') as string,
};
const newEntry = entryDraft.getIn(['entry', 'newRecord']) || false;
let entryObj: {
path: string;
@ -782,7 +780,6 @@ export class Backend {
const updatedOptions = { unpublished, status };
const opts = {
newEntry,
parsedData,
commitMessage,
collectionName,
useWorkflow,
@ -795,6 +792,8 @@ export class Backend {
await this.implementation.persistEntry(entryObj, assetProxies, opts);
await this.invokePostSaveEvent(entryDraft.get('entry'));
if (!useWorkflow) {
await this.invokePostPublishEvent(entryDraft.get('entry'));
}
@ -804,7 +803,7 @@ export class Backend {
async invokeEventWithEntry(event: string, entry: EntryMap) {
const { login, name } = (await this.currentUser()) as User;
await invokeEvent({ name: event, data: { entry, author: { login, name } } });
return await invokeEvent({ name: event, data: { entry, author: { login, name } } });
}
async invokePrePublishEvent(entry: EntryMap) {
@ -823,6 +822,14 @@ export class Backend {
await this.invokeEventWithEntry('postUnpublish', entry);
}
async invokePreSaveEvent(entry: EntryMap) {
return await this.invokeEventWithEntry('preSave', entry);
}
async invokePostSaveEvent(entry: EntryMap) {
await this.invokeEventWithEntry('postSave', entry);
}
async persistMedia(config: Config, file: AssetProxy) {
const user = (await this.currentUser()) as User;
const options = {

View File

@ -45,7 +45,14 @@ describe('registry', () => {
});
describe('eventHandlers', () => {
const events = ['prePublish', 'postPublish', 'preUnpublish', 'postUnpublish'];
const events = [
'prePublish',
'postPublish',
'preUnpublish',
'postUnpublish',
'preSave',
'postSave',
];
describe('registerEventListener', () => {
it('should throw error on invalid event', () => {

View File

@ -3,7 +3,14 @@ import produce from 'immer';
import { oneLine } from 'common-tags';
import EditorComponent from 'ValueObjects/EditorComponent';
const allowedEvents = ['prePublish', 'postPublish', 'preUnpublish', 'postUnpublish'];
const allowedEvents = [
'prePublish',
'postPublish',
'preUnpublish',
'postUnpublish',
'preSave',
'postSave',
];
const eventHandlers = {};
allowedEvents.forEach(e => {
eventHandlers[e] = [];
@ -213,7 +220,7 @@ export async function invokeEvent({ name, data }) {
const handlers = registry.eventHandlers[name];
for (const { handler, options } of handlers) {
try {
await handler(data, options);
return await handler(data, options);
} catch (e) {
console.warn(`Failed running handler for event ${name} with message: ${e.message}`);
}

View File

@ -16,6 +16,10 @@ export interface StaticallyTypedRecord<T> {
keys: [K1, K2, K3],
defaultValue?: V,
): T[K1][K2][K3];
setIn<K1 extends keyof T, K2 extends keyof T[K1], V extends T[K1][K2]>(
keys: [K1, K2],
value: V,
): StaticallyTypedRecord<T>;
toJS(): T;
isEmpty(): boolean;
some<K extends keyof T>(predicate: (value: T[K], key: K, iter: this) => boolean): boolean;

View File

@ -52,7 +52,6 @@ export type Entry = { path: string; slug: string; raw: string };
export type PersistOptions = {
newEntry?: boolean;
parsedData?: { title: string; description: string };
commitMessage: string;
collectionName?: string;
useWorkflow?: boolean;

View File

@ -399,24 +399,18 @@ CMS.registerEventListener({
name: 'prePublish',
handler: ({ author, entry }) => console.log(JSON.stringify({ author, data: entry.get('data') })),
});
CMS.registerEventListener({
name: 'postPublish',
handler: ({ author, entry }) => console.log(JSON.stringify({ author, data: entry.get('data') })),
});
CMS.registerEventListener({
name: 'preUnpublish',
handler: ({ author, entry }) => console.log(JSON.stringify({ author, data: entry.get('data') })),
});
CMS.registerEventListener({
name: 'postUnpublish',
handler: ({ author, entry }) => console.log(JSON.stringify({ author, data: entry.get('data') })),
});
```
**Note:** Supported events are `prePublish`, `postPublish`, `preUnpublish` and `postUnpublish`.
Supported events are `prePublish`, `postPublish`, `preUnpublish`, `postUnpublish`, `preSave` and `postSave`. The `preSave` hook can be used to modify the entry data like so:
```javascript
CMS.registerEventListener({
name: 'preSave',
handler: ({ entry }) => {
return entry.get('data').set('title', 'new title');
},
});
```
## Dynamic Default Values