feat: delete scheduled published events (#10504)

### What?

Allows a user to delete a scheduled publish event after it has been
added:

![image](https://github.com/user-attachments/assets/79b1a206-c8a7-4ffa-a9bf-d0f84f86b8f9)

### Why?

Previously a user had no control over making changes once scheduled.

### How?

Extends the `scheduledPublishHandler` server action to accept a
`deleteID` for the event that should be removed and exposes this to the
user via the admin UI in a new column in the Upcoming Events table.
This commit is contained in:
Dan Ribbens
2025-01-13 14:41:38 -05:00
committed by GitHub
parent 6ada450531
commit f95d6ba94a
6 changed files with 195 additions and 12 deletions

View File

@@ -1,4 +1,5 @@
import type { Payload, PayloadRequest } from 'payload'
import { createLocalReq, Payload } from 'payload'
import { schedulePublishHandler } from '@payloadcms/ui/utilities/schedulePublishHandler'
import path from 'path'
import { ValidationError } from 'payload'
@@ -48,6 +49,7 @@ const formatGraphQLID = (id: number | string) =>
payload.db.defaultIDType === 'number' ? id : `"${id}"`
describe('Versions', () => {
let user
beforeAll(async () => {
process.env.SEED_IN_CONFIG_ONINIT = 'false' // Makes it so the payload config onInit seed is not run. Otherwise, the seed would be run unnecessarily twice for the initial test run - once for beforeEach and once for onInit
;({ payload, restClient } = await initPayloadInt(dirname))
@@ -69,12 +71,16 @@ describe('Versions', () => {
password: "${devUser.password}"
) {
token
user {
id
}
}
}`
const { data } = await restClient
.GRAPHQL_POST({ body: JSON.stringify({ query: login }) })
.then((res) => res.json())
user = { ...data.loginUser.user, collection: 'users' }
token = data.loginUser.token
// now: initialize
@@ -1862,10 +1868,6 @@ describe('Versions', () => {
const currentDate = new Date()
const user = (
await payload.find({ collection: 'users', where: { email: { equals: devUser.email } } })
).docs[0]
await payload.jobs.queue({
task: 'schedulePublish',
waitUntil: new Date(currentDate.getTime() + 3000),
@@ -1998,6 +2000,107 @@ describe('Versions', () => {
expect(retrieved._status).toStrictEqual('draft')
expect(retrieved.title).toStrictEqual('i will be a draft')
})
describe('server functions', () => {
let draftDoc
let event
beforeAll(async () => {
draftDoc = await payload.create({
collection: draftCollectionSlug,
data: {
title: 'my doc',
description: 'hello',
_status: 'draft',
},
})
})
it('should create using schedule-publish', async () => {
const currentDate = new Date()
const req = await createLocalReq({ user }, payload)
// use server action to create the event
await schedulePublishHandler({
req,
type: 'publish',
date: new Date(currentDate.getTime() + 3000),
doc: {
relationTo: draftCollectionSlug,
value: draftDoc.id,
},
user,
locale: 'all',
})
// fetch the job
;[event] = (
await payload.find({
collection: 'payload-jobs',
where: {
'input.doc.value': {
equals: draftDoc.id,
},
},
})
).docs
expect(event).toBeDefined()
})
it('should delete using schedule-publish', async () => {
const currentDate = new Date()
const req = await createLocalReq({ user }, payload)
// use server action to create the event
await schedulePublishHandler({
req,
type: 'publish',
date: new Date(currentDate.getTime() + 3000),
doc: {
relationTo: draftCollectionSlug,
value: draftDoc.id,
},
user,
locale: 'all',
})
// fetch the job
;[event] = (
await payload.find({
collection: 'payload-jobs',
where: {
'input.doc.value': {
equals: draftDoc.id,
},
},
})
).docs
// use server action to delete the event
await schedulePublishHandler({
req,
deleteID: event.id,
user,
})
// fetch the job
;[event] = (
await payload.find({
collection: 'payload-jobs',
where: {
'input.doc.value': {
equals: String(draftDoc.id),
},
},
})
).docs
expect(event).toBeUndefined()
})
})
})
describe('Publish Individual Locale', () => {