From c19b2286b3431899c3bec510efb2bd7d631f7684 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Tue, 25 Feb 2025 12:55:26 +0100 Subject: [PATCH] feat: adds validation on date from/to inputs in the schedule modal (#18437) --- .../modal/document-schedule-modal.element.ts | 194 ++++++++++++------ 1 file changed, 135 insertions(+), 59 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/schedule-publish/modal/document-schedule-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/schedule-publish/modal/document-schedule-modal.element.ts index 2cf75e6f64..13d8b57ce7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/schedule-publish/modal/document-schedule-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/schedule-publish/modal/document-schedule-modal.element.ts @@ -6,12 +6,13 @@ import type { UmbDocumentScheduleModalValue, UmbDocumentScheduleSelectionModel, } from './document-schedule-modal.token.js'; -import { css, customElement, html, repeat, state, when } from '@umbraco-cms/backoffice/external/lit'; +import { css, customElement, html, ref, repeat, state, when } from '@umbraco-cms/backoffice/external/lit'; import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { UmbSelectionManager } from '@umbraco-cms/backoffice/utils'; +import { umbBindToValidation, UmbValidationContext } from '@umbraco-cms/backoffice/validation'; import type { UmbInputDateElement } from '@umbraco-cms/backoffice/components'; -import type { UUIBooleanInputElement } from '@umbraco-cms/backoffice/external/uui'; +import type { UUIBooleanInputElement, UUIButtonState } from '@umbraco-cms/backoffice/external/uui'; @customElement('umb-document-schedule-modal') export class UmbDocumentScheduleModalElement extends UmbModalBaseElement< @@ -35,6 +36,11 @@ export class UmbDocumentScheduleModalElement extends UmbModalBaseElement< @state() _internalValues: Array = []; + @state() + private _submitButtonState?: UUIButtonState; + + #validation = new UmbValidationContext(this); + #pickableFilter = (option: UmbDocumentVariantOptionModel) => { if (isNotPublishedMandatory(option)) { return true; @@ -91,11 +97,20 @@ export class UmbDocumentScheduleModalElement extends UmbModalBaseElement< this.#selectionManager.setSelection(selected); } - #submit() { - this.value = { - selection: this._internalValues, - }; - this.modalContext?.submit(); + async #submit() { + this._submitButtonState = 'waiting'; + try { + await this.#validation.validate(); + this._submitButtonState = 'success'; + this.value = { + selection: this._internalValues, + }; + this.modalContext?.submit(); + } catch { + this._submitButtonState = 'failed'; + } finally { + this._submitButtonState = undefined; + } } #close() { @@ -146,6 +161,7 @@ export class UmbDocumentScheduleModalElement extends UmbModalBaseElement<
this.localize.term('speechBubbles_scheduleErrReleaseDate1'), + () => { + const value = element.value.toString(); + if (!value) return false; + const date = new Date(value); + return date < new Date(); + }, + ); + } + + #attachValidatorsToUnpublish(element: UmbInputDateElement | null, unique: string) { + if (!element) return; + + element.addValidator( + 'badInput', + () => this.localize.term('speechBubbles_scheduleErrExpireDate1'), + () => { + const value = element.value.toString(); + if (!value) return false; + const date = new Date(value); + return date < new Date(); + }, + ); + + element.addValidator( + 'customError', + () => this.localize.term('speechBubbles_scheduleErrExpireDate2'), + () => { + const value = element.value.toString(); + if (!value) return false; + + // Check if the unpublish date is before the publish date + const variant = this._internalValues.find((s) => s.unique === unique); + if (!variant) return false; + const publishTime = variant.schedule?.publishTime; + if (!publishTime) return false; + + const date = new Date(value); + const publishDate = new Date(publishTime); + return date < publishDate; + }, + ); + } + #renderPublishDateInput(option: UmbDocumentVariantOptionModel, fromDate: string | null, toDate: string | null) { - return html`
- - Publish at -
- this.#onFromDateChange(e, option.unique)} - label=${this.localize.term('general_publishDate')}> -
- ${when( - fromDate, - () => html` - this.#removeFromDate(option.unique)}> - - - `, - )} -
-
-
-
- - Unpublish at -
- this.#onToDateChange(e, option.unique)} - label=${this.localize.term('general_publishDate')}> -
- ${when( - toDate, - () => html` - this.#removeToDate(option.unique)}> - - - `, - )} -
-
-
-
-
`; + return html` +
+ + Publish at +
+ this.#attachValidatorsToPublish(e as UmbInputDateElement))} + ${umbBindToValidation(this)} + type="datetime-local" + .value=${this.#formatDate(fromDate)} + @change=${(e: Event) => this.#onFromDateChange(e, option.unique)} + label=${this.localize.term('general_publishDate')}> +
+ ${when( + fromDate, + () => html` + this.#removeFromDate(option.unique)}> + + + `, + )} +
+
+
+
+ + + Unpublish at +
+ this.#attachValidatorsToUnpublish(e as UmbInputDateElement, option.unique))} + ${umbBindToValidation(this)} + type="datetime-local" + .value=${this.#formatDate(toDate)} + @change=${(e: Event) => this.#onToDateChange(e, option.unique)} + label=${this.localize.term('general_publishDate')}> +
+ ${when( + toDate, + () => html` + this.#removeToDate(option.unique)}> + + + `, + )} +
+
+
+
+
+ `; } #fromDate(unique: string): string | null { @@ -275,6 +347,7 @@ export class UmbDocumentScheduleModalElement extends UmbModalBaseElement< ...variant.schedule, publishTime: null, }; + this.#validation.validate(); this.requestUpdate('_internalValues'); } @@ -285,6 +358,7 @@ export class UmbDocumentScheduleModalElement extends UmbModalBaseElement< ...variant.schedule, unpublishTime: null, }; + this.#validation.validate(); this.requestUpdate('_internalValues'); } @@ -325,6 +399,7 @@ export class UmbDocumentScheduleModalElement extends UmbModalBaseElement< ...variant.schedule, publishTime: this.#getDateValue(e), }; + this.#validation.validate(); this.requestUpdate('_internalValues'); } @@ -335,6 +410,7 @@ export class UmbDocumentScheduleModalElement extends UmbModalBaseElement< ...variant.schedule, unpublishTime: this.#getDateValue(e), }; + this.#validation.validate(); this.requestUpdate('_internalValues'); }