From 618624e1106662218eff6e74ba98de18be9b2fee Mon Sep 17 00:00:00 2001 From: Dan Ribbens Date: Wed, 19 Feb 2025 10:10:29 -0500 Subject: [PATCH] fix(ui): unsaved changes allows for scheduled publish missing changes (#11001) ### What? When you first edit a document and then open the Schedule publish drawer, you can schedule publish changes but the current changes made to the form won't be included. ### Why? The UX does not make it clear that the changes you have in the form are not actually going to be published. ### How? Instead of allowing that we just disable the Schedule Publish drawer toggler so that users are forced to save a draft first. In addition to the above, this change also passes a defaultType so that an already published document will default the radio type have "Unpublish" selected. --- packages/ui/src/elements/Button/index.tsx | 1 + .../ui/src/elements/DatePicker/DatePicker.tsx | 3 +- packages/ui/src/elements/DatePicker/types.ts | 1 + packages/ui/src/elements/Popup/index.tsx | 4 +- .../PublishButton/ScheduleDrawer/index.tsx | 16 +++++-- .../ui/src/elements/PublishButton/index.tsx | 17 ++++++-- test/versions/e2e.spec.ts | 43 +++++++++++++++++++ 7 files changed, 76 insertions(+), 9 deletions(-) diff --git a/packages/ui/src/elements/Button/index.tsx b/packages/ui/src/elements/Button/index.tsx index de1bc71ed1..2b130bea5a 100644 --- a/packages/ui/src/elements/Button/index.tsx +++ b/packages/ui/src/elements/Button/index.tsx @@ -185,6 +185,7 @@ export const Button: React.FC = (props) => { className={disabled && !enableSubMenu ? `${baseClass}--popup-disabled` : ''} disabled={disabled && !enableSubMenu} horizontalAlign="right" + id={`${id}-popup`} noBackground render={({ close }) => SubMenuPopupContent({ close: () => close() })} size="large" diff --git a/packages/ui/src/elements/DatePicker/DatePicker.tsx b/packages/ui/src/elements/DatePicker/DatePicker.tsx index 7fbb719701..714ec023d7 100644 --- a/packages/ui/src/elements/DatePicker/DatePicker.tsx +++ b/packages/ui/src/elements/DatePicker/DatePicker.tsx @@ -19,6 +19,7 @@ const baseClass = 'date-time-picker' const DatePicker: React.FC = (props) => { const { + id, displayFormat: customDisplayFormat, maxDate, maxTime, @@ -113,7 +114,7 @@ const DatePicker: React.FC = (props) => { }, [i18n.language, i18n.dateFNS]) return ( -
+
{dateTimePickerProps.selected && ( {processing ? {t('general:saving')} : null} diff --git a/packages/ui/src/elements/PublishButton/index.tsx b/packages/ui/src/elements/PublishButton/index.tsx index 66031e0051..64703e6981 100644 --- a/packages/ui/src/elements/PublishButton/index.tsx +++ b/packages/ui/src/elements/PublishButton/index.tsx @@ -73,7 +73,10 @@ export function PublishButton({ label: labelProp }: PublishButtonClientProps) { entityConfig?.versions?.drafts.schedulePublish const canSchedulePublish = Boolean( - scheduledPublishEnabled && hasPublishPermission && (globalSlug || (collectionSlug && id)), + scheduledPublishEnabled && + hasPublishPermission && + (globalSlug || (collectionSlug && id)) && + !modified, ) const operation = useOperation() @@ -209,7 +212,10 @@ export function PublishButton({ label: labelProp }: PublishButtonClientProps) { {canSchedulePublish && ( - [toggleModal(drawerSlug), close()]}> + [toggleModal(drawerSlug), close()]} + > {t('version:schedulePublish')} @@ -230,7 +236,12 @@ export function PublishButton({ label: labelProp }: PublishButtonClientProps) { > {localization ? defaultLabel : label} - {canSchedulePublish && isModalOpen(drawerSlug) && } + {canSchedulePublish && isModalOpen(drawerSlug) && ( + + )} ) } diff --git a/test/versions/e2e.spec.ts b/test/versions/e2e.spec.ts index f2bf61427e..0cd34eb850 100644 --- a/test/versions/e2e.spec.ts +++ b/test/versions/e2e.spec.ts @@ -743,6 +743,49 @@ describe('Versions', () => { expect(versionsTabUpdated).toBeTruthy() }) }) + + describe('Scheduled publish', () => { + beforeAll(() => { + url = new AdminUrlUtil(serverURL, draftCollectionSlug) + }) + + test('should schedule publish', async () => { + await page.goto(url.create) + await page.waitForURL(url.create) + await page.locator('#field-title').fill('scheduled publish') + await page.locator('#field-description').fill('scheduled publish description') + + // schedule publish should not be available before document has been saved + await page.locator('#action-save-popup').click() + await expect(page.locator('#schedule-publish')).not.toBeVisible() + + // save draft then try to schedule publish + await saveDocAndAssert(page) + await page.locator('#action-save-popup').click() + await page.locator('#schedule-publish').click() + + // drawer should open + await expect(page.locator('.schedule-publish__drawer-header')).toBeVisible() + // nothing in scheduled + await expect(page.locator('.drawer__content')).toContainText('No upcoming events scheduled.') + + // set date and time + await page.locator('.date-time-picker input').fill('Feb 21, 2050 12:00 AM') + await page.keyboard.press('Enter') + + // save the scheduled publish + await page.locator('#scheduled-publish-save').click() + + // delete the scheduled event after it was made + await page.locator('.cell-delete').locator('.btn').click() + + // see toast deleted successfully + await expect( + page.locator('.payload-toast-item:has-text("Deleted successfully.")'), + ).toBeVisible() + }) + }) + describe('Collections - publish specific locale', () => { beforeAll(() => { url = new AdminUrlUtil(serverURL, localizedCollectionSlug)