diff --git a/frontend/src/container/PlannedDowntime/PlannedDowntime.styles.scss b/frontend/src/container/PlannedDowntime/PlannedDowntime.styles.scss index 41949142fa..b81e4d1e51 100644 --- a/frontend/src/container/PlannedDowntime/PlannedDowntime.styles.scss +++ b/frontend/src/container/PlannedDowntime/PlannedDowntime.styles.scss @@ -77,6 +77,18 @@ color: var(--bg-vanilla-400); } } + + .formItemWithBullet { + margin-bottom: 0; + } + + .scheduleTimeInfoText { + margin-top: 8px; + margin-bottom: 20px; + font-size: 12px; + font-weight: 400; + color: var(--bg-vanilla-400); + } } .alert-rule-tags { @@ -543,5 +555,13 @@ background: var(--bg-vanilla-100); } } + + .scheduleTimeInfoText { + color: var(--bg-slate-300); + } + + .alert-rule-info { + color: var(--bg-slate-300); + } } } diff --git a/frontend/src/container/PlannedDowntime/PlannedDowntimeForm.tsx b/frontend/src/container/PlannedDowntime/PlannedDowntimeForm.tsx index 76b0507558..94d1a5d6eb 100644 --- a/frontend/src/container/PlannedDowntime/PlannedDowntimeForm.tsx +++ b/frontend/src/container/PlannedDowntime/PlannedDowntimeForm.tsx @@ -41,7 +41,7 @@ import { getAlertOptionsFromIds, getDurationInfo, getEndTime, - handleTimeConvertion, + handleTimeConversion, isScheduleRecurring, recurrenceOptions, recurrenceOptionWithSubmenu, @@ -52,6 +52,10 @@ dayjs.locale('en'); dayjs.extend(utc); dayjs.extend(timezone); +const TIME_FORMAT = 'HH:mm'; +const DATE_FORMAT = 'Do MMM YYYY'; +const ORDINAL_FORMAT = 'Do'; + interface PlannedDowntimeFormData { name: string; startTime: dayjs.Dayjs | string; @@ -105,6 +109,10 @@ export function PlannedDowntimeForm( ?.unit || 'm', ); + const [formData, setFormData] = useState( + initialValues?.schedule as PlannedDowntimeFormData, + ); + const [recurrenceType, setRecurrenceType] = useState( (initialValues.schedule?.recurrence?.repeatType as string) || recurrenceOptions.doesNotRepeat.value, @@ -131,7 +139,7 @@ export function PlannedDowntimeForm( .filter((alert) => alert !== undefined) as string[], name: values.name, schedule: { - startTime: handleTimeConvertion( + startTime: handleTimeConversion( values.startTime, timezoneInitialValue, values.timezone, @@ -139,7 +147,7 @@ export function PlannedDowntimeForm( ), timezone: values.timezone, endTime: values.endTime - ? handleTimeConvertion( + ? handleTimeConversion( values.endTime, timezoneInitialValue, values.timezone, @@ -196,14 +204,14 @@ export function PlannedDowntimeForm( ? `${values.recurrence?.duration}${durationUnit}` : undefined, endTime: !isEmpty(values.endTime) - ? handleTimeConvertion( + ? handleTimeConversion( values.endTime, timezoneInitialValue, values.timezone, !isEditMode, ) : undefined, - startTime: handleTimeConvertion( + startTime: handleTimeConversion( values.startTime, timezoneInitialValue, values.timezone, @@ -300,6 +308,116 @@ export function PlannedDowntimeForm( }), ); + const getTimezoneFormattedTime = ( + time: string | dayjs.Dayjs, + timeZone?: string, + isEditMode?: boolean, + format?: string, + ): string => { + if (!time) { + return ''; + } + if (!timeZone) { + return dayjs(time).format(format); + } + return dayjs(time).tz(timeZone, isEditMode).format(format); + }; + + const startTimeText = useMemo((): string => { + let startTime = formData?.startTime; + if (recurrenceType !== recurrenceOptions.doesNotRepeat.value) { + startTime = formData?.recurrence?.startTime || formData?.startTime || ''; + } + + if (!startTime) { + return ''; + } + + if (formData.timezone) { + startTime = handleTimeConversion( + startTime, + timezoneInitialValue, + formData?.timezone, + !isEditMode, + ); + } + const daysOfWeek = formData?.recurrence?.repeatOn; + + const formattedStartTime = getTimezoneFormattedTime( + startTime, + formData.timezone, + !isEditMode, + TIME_FORMAT, + ); + + const formattedStartDate = getTimezoneFormattedTime( + startTime, + formData.timezone, + !isEditMode, + DATE_FORMAT, + ); + + const ordinalFormat = getTimezoneFormattedTime( + startTime, + formData.timezone, + !isEditMode, + ORDINAL_FORMAT, + ); + + const formattedDaysOfWeek = daysOfWeek?.join(', '); + switch (recurrenceType) { + case 'daily': + return `Scheduled from ${formattedStartDate}, daily starting at ${formattedStartTime}.`; + case 'monthly': + return `Scheduled from ${formattedStartDate}, monthly on the ${ordinalFormat} starting at ${formattedStartTime}.`; + case 'weekly': + return `Scheduled from ${formattedStartDate}, weekly ${ + formattedDaysOfWeek ? `on [${formattedDaysOfWeek}]` : '' + } starting at ${formattedStartTime}`; + default: + return `Scheduled for ${formattedStartDate} starting at ${formattedStartTime}.`; + } + }, [formData, recurrenceType, isEditMode, timezoneInitialValue]); + + const endTimeText = useMemo((): string => { + let endTime = formData?.endTime; + if (recurrenceType !== recurrenceOptions.doesNotRepeat.value) { + endTime = formData?.recurrence?.endTime || ''; + + if (!isEditMode && !endTime) { + endTime = formData?.endTime || ''; + } + } + + if (!endTime) { + return ''; + } + + if (formData.timezone) { + endTime = handleTimeConversion( + endTime, + timezoneInitialValue, + formData?.timezone, + !isEditMode, + ); + } + + const formattedEndTime = getTimezoneFormattedTime( + endTime, + formData.timezone, + !isEditMode, + TIME_FORMAT, + ); + + const formattedEndDate = getTimezoneFormattedTime( + endTime, + formData.timezone, + !isEditMode, + DATE_FORMAT, + ); + return `Scheduled to end maintenance on ${formattedEndDate} at ${formattedEndTime}.`; + }, [formData, recurrenceType, isEditMode, timezoneInitialValue]); + return ( { setRecurrenceType(form.getFieldValue('recurrence')?.repeatType as string); + setFormData(form.getFieldsValue()); }} autoComplete="off" > @@ -333,7 +452,7 @@ export function PlannedDowntimeForm( label="Starts from" name="startTime" rules={formValidationRules} - className="formItemWithBullet" + className={!isEmpty(startTimeText) ? 'formItemWithBullet' : ''} getValueProps={(value): any => ({ value: value ? dayjs(value).tz(timezoneInitialValue) : undefined, })} @@ -348,6 +467,9 @@ export function PlannedDowntimeForm( popupClassName="datePicker" /> + {!isEmpty(startTimeText) && ( +
{startTimeText}
+ )} ({ value: value ? dayjs(value).tz(timezoneInitialValue) : undefined, })} @@ -426,6 +548,9 @@ export function PlannedDowntimeForm( popupClassName="datePicker" /> + {!isEmpty(endTimeText) && ( +
{endTimeText}
+ )}
Silence Alerts diff --git a/frontend/src/container/PlannedDowntime/PlannedDowntimeutils.ts b/frontend/src/container/PlannedDowntime/PlannedDowntimeutils.ts index 7d0745dc5e..feba0cb13e 100644 --- a/frontend/src/container/PlannedDowntime/PlannedDowntimeutils.ts +++ b/frontend/src/container/PlannedDowntime/PlannedDowntimeutils.ts @@ -262,7 +262,7 @@ export function formatWithTimezone( return `${parsedDate?.substring(0, 19)}${targetOffset}`; } -export function handleTimeConvertion( +export function handleTimeConversion( dateValue: string | dayjs.Dayjs, timezoneInit?: string, timezone?: string,