diff --git a/packages/netlify-cms-core/src/actions/editorialWorkflow.ts b/packages/netlify-cms-core/src/actions/editorialWorkflow.ts index b19ca886..ea0ac630 100644 --- a/packages/netlify-cms-core/src/actions/editorialWorkflow.ts +++ b/packages/netlify-cms-core/src/actions/editorialWorkflow.ts @@ -558,7 +558,7 @@ export function unpublishPublishedEntry(collection: Collection, slug: string) { const entryDraft = (Map().set('entry', entry) as unknown) as EntryDraft; dispatch(unpublishedEntryPersisting(collection, entry, transactionID)); return backend - .deleteEntry(state.config, collection, slug) + .deleteEntry(state, collection, slug) .then(() => backend.persistEntry({ config: state.config, diff --git a/packages/netlify-cms-core/src/actions/entries.ts b/packages/netlify-cms-core/src/actions/entries.ts index f8eac767..c16c58d4 100644 --- a/packages/netlify-cms-core/src/actions/entries.ts +++ b/packages/netlify-cms-core/src/actions/entries.ts @@ -654,7 +654,7 @@ export function deleteEntry(collection: Collection, slug: string) { dispatch(entryDeleting(collection, slug)); return backend - .deleteEntry(state.config, collection, slug) + .deleteEntry(state, collection, slug) .then(() => { return dispatch(entryDeleted(collection, slug)); }) diff --git a/packages/netlify-cms-core/src/backend.ts b/packages/netlify-cms-core/src/backend.ts index 047640ef..1ea9facf 100644 --- a/packages/netlify-cms-core/src/backend.ts +++ b/packages/netlify-cms-core/src/backend.ts @@ -3,7 +3,7 @@ import { List, Map, fromJS } from 'immutable'; import * as fuzzy from 'fuzzy'; import { resolveFormat } from './formats/formats'; import { selectUseWorkflow } from './reducers/config'; -import { selectMediaFilePath, selectMediaFolder } from './reducers/entries'; +import { selectMediaFilePath, selectMediaFolder, selectEntry } from './reducers/entries'; import { selectIntegration } from './reducers/integrations'; import { selectEntrySlug, @@ -751,14 +751,25 @@ export class Backend { return entryObj.slug; } - async invokePrePublishEvent(entry: EntryMap) { + async invokeEventWithEntry(event: string, entry: EntryMap) { const { login, name } = (await this.currentUser()) as User; - await invokeEvent({ name: 'prePublish', data: { entry, author: { login, name } } }); + await invokeEvent({ name: event, data: { entry, author: { login, name } } }); + } + + async invokePrePublishEvent(entry: EntryMap) { + await this.invokeEventWithEntry('prePublish', entry); } async invokePostPublishEvent(entry: EntryMap) { - const { login, name } = (await this.currentUser()) as User; - await invokeEvent({ name: 'postPublish', data: { entry, author: { login, name } } }); + await this.invokeEventWithEntry('postPublish', entry); + } + + async invokePreUnpublishEvent(entry: EntryMap) { + await this.invokeEventWithEntry('preUnpublish', entry); + } + + async invokePostUnpublishEvent(entry: EntryMap) { + await this.invokeEventWithEntry('postUnpublish', entry); } async persistMedia(config: Config, file: AssetProxy) { @@ -778,13 +789,14 @@ export class Backend { return this.implementation.persistMedia(file, options); } - async deleteEntry(config: Config, collection: Collection, slug: string) { + async deleteEntry(state: State, collection: Collection, slug: string) { const path = selectEntryPath(collection, slug) as string; if (!selectAllowDeletion(collection)) { throw new Error('Not allowed to delete entries in this collection'); } + const config = state.config; const user = (await this.currentUser()) as User; const commitMessage = commitMessageFormatter( 'delete', @@ -798,7 +810,12 @@ export class Backend { }, user.useOpenAuthoring, ); - return this.implementation.deleteFile(path, commitMessage); + + const entry = selectEntry(state.entries, collection.get('name'), slug); + await this.invokePreUnpublishEvent(entry); + const result = await this.implementation.deleteFile(path, commitMessage); + await this.invokePostUnpublishEvent(entry); + return result; } async deleteMedia(config: Config, path: string) { diff --git a/packages/netlify-cms-core/src/lib/__tests__/registry.spec.js b/packages/netlify-cms-core/src/lib/__tests__/registry.spec.js index 171c38f1..92d8a83c 100644 --- a/packages/netlify-cms-core/src/lib/__tests__/registry.spec.js +++ b/packages/netlify-cms-core/src/lib/__tests__/registry.spec.js @@ -45,7 +45,7 @@ describe('registry', () => { }); describe('eventHandlers', () => { - const events = ['prePublish', 'postPublish']; + const events = ['prePublish', 'postPublish', 'preUnpublish', 'postUnpublish']; describe('registerEventListener', () => { it('should throw error on invalid event', () => { diff --git a/packages/netlify-cms-core/src/lib/registry.js b/packages/netlify-cms-core/src/lib/registry.js index ac5540c1..53ee4bb8 100644 --- a/packages/netlify-cms-core/src/lib/registry.js +++ b/packages/netlify-cms-core/src/lib/registry.js @@ -3,7 +3,7 @@ import produce from 'immer'; import { oneLine } from 'common-tags'; import EditorComponent from 'ValueObjects/EditorComponent'; -const allowedEvents = ['prePublish', 'postPublish']; +const allowedEvents = ['prePublish', 'postPublish', 'preUnpublish', 'postUnpublish']; const eventHandlers = {}; allowedEvents.forEach(e => { eventHandlers[e] = []; diff --git a/website/content/docs/beta-features.md b/website/content/docs/beta-features.md index bca85d89..f4a57e55 100644 --- a/website/content/docs/beta-features.md +++ b/website/content/docs/beta-features.md @@ -394,6 +394,16 @@ 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') })), +}); ``` -> Supported events are `prePublish` and `postPublish` +> Supported events are `prePublish`, `postPublish`, `preUnpublish` and `postUnpublish`