diff --git a/src/platform/packages/shared/response-ops/recurring-schedule-form/components/recurring_schedule_form_fields.tsx b/src/platform/packages/shared/response-ops/recurring-schedule-form/components/recurring_schedule_form_fields.tsx
index b51c337910d9b..85c70c454e138 100644
--- a/src/platform/packages/shared/response-ops/recurring-schedule-form/components/recurring_schedule_form_fields.tsx
+++ b/src/platform/packages/shared/response-ops/recurring-schedule-form/components/recurring_schedule_form_fields.tsx
@@ -41,13 +41,12 @@ import { getPresets } from '../utils/get_presets';
import { getWeekdayInfo } from '../utils/get_weekday_info';
import { RecurringSchedule } from '../types';
import * as i18n from '../translations';
+import { convertStringToMomentOptional, convertMomentToStringOptional } from '../converters/moment';
/**
* Using EuiForm in `div` mode since this is meant to be integrated in a larger form
*/
const UseField = getUseField({ component: Field });
-export const toMoment = (value?: string): Moment | undefined => (value ? moment(value) : undefined);
-export const toString = (value?: Moment): string => value?.toISOString() ?? '';
export interface RecurringScheduleFieldsProps {
startDate?: string;
@@ -211,8 +210,8 @@ export const RecurringScheduleFormFields = memo(
},
},
],
- serializer: toString,
- deserializer: toMoment,
+ serializer: convertMomentToStringOptional,
+ deserializer: convertStringToMomentOptional,
}}
componentProps={{
'data-test-subj': 'until-field',
diff --git a/src/platform/packages/shared/response-ops/recurring-schedule-form/converters/moment.test.ts b/src/platform/packages/shared/response-ops/recurring-schedule-form/converters/moment.test.ts
new file mode 100644
index 0000000000000..53db3256e0b59
--- /dev/null
+++ b/src/platform/packages/shared/response-ops/recurring-schedule-form/converters/moment.test.ts
@@ -0,0 +1,62 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the "Elastic License
+ * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
+ * Public License v 1"; you may not use this file except in compliance with, at
+ * your election, the "Elastic License 2.0", the "GNU Affero General Public
+ * License v3.0 only", or the "Server Side Public License, v 1".
+ */
+
+import {
+ convertStringToMoment,
+ convertStringToMomentOptional,
+ convertMomentToString,
+ convertMomentToStringOptional,
+} from './moment';
+import moment from 'moment';
+
+describe('Moment converters', () => {
+ describe('convertStringToMoment', () => {
+ it('should convert ISO string to Moment', () => {
+ const dateStr = '2025-06-26T12:34:56.789Z';
+ const result = convertStringToMoment(dateStr);
+ expect(moment.isMoment(result)).toBe(true);
+ expect(result.toISOString()).toBe(dateStr);
+ });
+ });
+
+ describe('convertStringToMomentOptional', () => {
+ it('should convert ISO string to Moment if value is provided', () => {
+ const dateStr = '2025-06-26T12:34:56.789Z';
+ const result = convertStringToMomentOptional(dateStr);
+ expect(moment.isMoment(result)).toBe(true);
+ expect(result?.toISOString()).toBe(dateStr);
+ });
+
+ it('should return undefined if value is not provided', () => {
+ const result = convertStringToMomentOptional(undefined);
+ expect(result).toBeUndefined();
+ });
+ });
+
+ describe('convertMomentToString', () => {
+ it('should convert Moment to ISO string', () => {
+ const m = moment('2025-06-26T12:34:56.789Z');
+ const result = convertMomentToString(m);
+ expect(result).toBe('2025-06-26T12:34:56.789Z');
+ });
+ });
+
+ describe('convertMomentToStringOptional', () => {
+ it('should convert Moment to ISO string if value is provided', () => {
+ const m = moment('2025-06-26T12:34:56.789Z');
+ const result = convertMomentToStringOptional(m);
+ expect(result).toBe('2025-06-26T12:34:56.789Z');
+ });
+
+ it('should return empty string if value is not provided', () => {
+ const result = convertMomentToStringOptional(undefined);
+ expect(result).toBe('');
+ });
+ });
+});
diff --git a/src/platform/packages/shared/response-ops/recurring-schedule-form/converters/moment.ts b/src/platform/packages/shared/response-ops/recurring-schedule-form/converters/moment.ts
new file mode 100644
index 0000000000000..b3d31feedd89a
--- /dev/null
+++ b/src/platform/packages/shared/response-ops/recurring-schedule-form/converters/moment.ts
@@ -0,0 +1,20 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the "Elastic License
+ * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
+ * Public License v 1"; you may not use this file except in compliance with, at
+ * your election, the "Elastic License 2.0", the "GNU Affero General Public
+ * License v3.0 only", or the "Server Side Public License, v 1".
+ */
+
+import type { Moment } from 'moment';
+import moment from 'moment';
+
+export const convertStringToMoment = (value: string): Moment => moment(value);
+
+export const convertStringToMomentOptional = (value?: string): Moment | undefined =>
+ value ? moment(value) : undefined;
+
+export const convertMomentToString = (value: Moment): string => value?.toISOString();
+
+export const convertMomentToStringOptional = (value?: Moment): string => value?.toISOString() ?? '';
diff --git a/src/platform/packages/shared/response-ops/recurring-schedule-form/utils/convert_to_rrule.test.ts b/src/platform/packages/shared/response-ops/recurring-schedule-form/utils/convert_to_rrule.test.ts
index 017645e8a933c..82e028783fe3a 100644
--- a/src/platform/packages/shared/response-ops/recurring-schedule-form/utils/convert_to_rrule.test.ts
+++ b/src/platform/packages/shared/response-ops/recurring-schedule-form/utils/convert_to_rrule.test.ts
@@ -14,13 +14,13 @@ import { convertToRRule } from './convert_to_rrule';
describe('convertToRRule', () => {
const timezone = 'UTC';
const today = '2023-03-22';
- const startDate = moment(today);
+ const startDate = moment(today).toISOString();
test('should convert a recurring schedule that is not recurring', () => {
const rRule = convertToRRule({ startDate, timezone });
expect(rRule).toEqual({
- dtstart: startDate.toISOString(),
+ dtstart: startDate,
tzid: 'UTC',
freq: Frequency.YEARLY,
count: 1,
@@ -39,7 +39,7 @@ describe('convertToRRule', () => {
});
expect(rRule).toEqual({
- dtstart: startDate.toISOString(),
+ dtstart: startDate,
tzid: 'UTC',
freq: Frequency.DAILY,
interval: 1,
@@ -61,7 +61,7 @@ describe('convertToRRule', () => {
});
expect(rRule).toEqual({
- dtstart: startDate.toISOString(),
+ dtstart: startDate,
tzid: 'UTC',
freq: Frequency.DAILY,
interval: 1,
@@ -83,7 +83,7 @@ describe('convertToRRule', () => {
});
expect(rRule).toEqual({
- dtstart: startDate.toISOString(),
+ dtstart: startDate,
tzid: 'UTC',
freq: Frequency.DAILY,
interval: 1,
@@ -103,7 +103,7 @@ describe('convertToRRule', () => {
});
expect(rRule).toEqual({
- dtstart: startDate.toISOString(),
+ dtstart: startDate,
tzid: 'UTC',
freq: Frequency.WEEKLY,
interval: 1,
@@ -122,7 +122,7 @@ describe('convertToRRule', () => {
});
expect(rRule).toEqual({
- dtstart: startDate.toISOString(),
+ dtstart: startDate,
tzid: 'UTC',
freq: Frequency.MONTHLY,
interval: 1,
@@ -141,7 +141,7 @@ describe('convertToRRule', () => {
});
expect(rRule).toEqual({
- dtstart: startDate.toISOString(),
+ dtstart: startDate,
tzid: 'UTC',
freq: Frequency.YEARLY,
interval: 1,
@@ -163,7 +163,7 @@ describe('convertToRRule', () => {
});
expect(rRule).toEqual({
- dtstart: startDate.toISOString(),
+ dtstart: startDate,
tzid: 'UTC',
freq: Frequency.DAILY,
interval: 1,
@@ -184,7 +184,7 @@ describe('convertToRRule', () => {
});
expect(rRule).toEqual({
- dtstart: startDate.toISOString(),
+ dtstart: startDate,
tzid: 'UTC',
freq: Frequency.WEEKLY,
interval: 1,
@@ -206,7 +206,7 @@ describe('convertToRRule', () => {
});
expect(rRule).toEqual({
- dtstart: startDate.toISOString(),
+ dtstart: startDate,
tzid: 'UTC',
freq: Frequency.MONTHLY,
interval: 1,
@@ -228,7 +228,7 @@ describe('convertToRRule', () => {
});
expect(rRule).toEqual({
- dtstart: startDate.toISOString(),
+ dtstart: startDate,
tzid: 'UTC',
freq: Frequency.MONTHLY,
interval: 1,
@@ -249,7 +249,7 @@ describe('convertToRRule', () => {
});
expect(rRule).toEqual({
- dtstart: startDate.toISOString(),
+ dtstart: startDate,
tzid: 'UTC',
freq: Frequency.YEARLY,
interval: 3,
diff --git a/src/platform/packages/shared/response-ops/recurring-schedule-form/utils/convert_to_rrule.ts b/src/platform/packages/shared/response-ops/recurring-schedule-form/utils/convert_to_rrule.ts
index 147d248d532ab..d0f40258a2b7c 100644
--- a/src/platform/packages/shared/response-ops/recurring-schedule-form/utils/convert_to_rrule.ts
+++ b/src/platform/packages/shared/response-ops/recurring-schedule-form/utils/convert_to_rrule.ts
@@ -7,7 +7,7 @@
* License v3.0 only", or the "Server Side Public License, v 1".
*/
-import type { Moment } from 'moment';
+import moment from 'moment';
import { Frequency } from '@kbn/rrule';
import { ISO_WEEKDAYS_TO_RRULE } from '../constants';
import { getPresets } from './get_presets';
@@ -21,20 +21,21 @@ export const convertToRRule = ({
recurringSchedule,
includeTime = false,
}: {
- startDate: Moment;
+ startDate: string;
timezone: string;
recurringSchedule?: RecurringSchedule;
includeTime?: boolean;
}): RRuleParams => {
- const presets = getPresets(startDate);
+ const startDateMoment = moment(startDate);
+ const presets = getPresets(startDateMoment);
const parsedSchedule = parseSchedule(recurringSchedule);
const rRule: RRuleParams = {
- dtstart: startDate.toISOString(),
+ dtstart: startDateMoment.toISOString(),
tzid: timezone,
...(Boolean(includeTime)
- ? { byhour: [startDate.get('hour')], byminute: [startDate.get('minute')] }
+ ? { byhour: [startDateMoment.get('hour')], byminute: [startDateMoment.get('minute')] }
: {}),
};
@@ -74,16 +75,16 @@ export const convertToRRule = ({
if (form.bymonth) {
if (form.bymonth === 'day') {
- rRule.bymonthday = [startDate.date()];
+ rRule.bymonthday = [startDateMoment.date()];
} else if (form.bymonth === 'weekday') {
- rRule.byweekday = [getNthByWeekday(startDate)];
+ rRule.byweekday = [getNthByWeekday(startDateMoment)];
}
}
if (frequency === Frequency.YEARLY) {
// rRule expects 1 based indexing for months
- rRule.bymonth = [startDate.month() + 1];
- rRule.bymonthday = [startDate.date()];
+ rRule.bymonth = [startDateMoment.month() + 1];
+ rRule.bymonthday = [startDateMoment.date()];
}
return rRule;
diff --git a/x-pack/platform/plugins/private/reporting/public/management/components/scheduled_report_flyout_content.test.tsx b/x-pack/platform/plugins/private/reporting/public/management/components/scheduled_report_flyout_content.test.tsx
index 82978314287b2..58e8364d5106a 100644
--- a/x-pack/platform/plugins/private/reporting/public/management/components/scheduled_report_flyout_content.test.tsx
+++ b/x-pack/platform/plugins/private/reporting/public/management/components/scheduled_report_flyout_content.test.tsx
@@ -6,17 +6,19 @@
*/
import React, { PropsWithChildren } from 'react';
+import moment from 'moment';
import { fireEvent, render, screen, waitFor, within } from '@testing-library/react';
+import userEvent from '@testing-library/user-event';
import { type ReportingAPIClient, useKibana } from '@kbn/reporting-public';
+import { coreMock } from '@kbn/core/public/mocks';
import { ReportTypeData, ScheduledReport } from '../../types';
import { getReportingHealth } from '../apis/get_reporting_health';
-import { coreMock } from '@kbn/core/public/mocks';
import { testQueryClient } from '../test_utils/test_query_client';
import { QueryClientProvider } from '@tanstack/react-query';
import { ScheduledReportFlyoutContent } from './scheduled_report_flyout_content';
import { scheduleReport } from '../apis/schedule_report';
import { ScheduledReportApiJSON } from '../../../server/types';
-import userEvent from '@testing-library/user-event';
+import * as useDefaultTimezoneModule from '../hooks/use_default_timezone';
// Mock Kibana hooks and context
jest.mock('@kbn/reporting-public', () => ({
@@ -139,6 +141,10 @@ const mockKibanaServices = {
getCurrent: jest.fn().mockResolvedValue({ user: { email: TEST_EMAIL } }),
},
};
+const defaultTimezone = moment.tz.guess();
+const timezoneSpy = jest
+ .spyOn(useDefaultTimezoneModule, 'useDefaultTimezone')
+ .mockReturnValue({ defaultTimezone, isBrowser: true });
describe('ScheduledReportFlyoutContent', () => {
beforeEach(() => {
@@ -379,4 +385,63 @@ describe('ScheduledReportFlyoutContent', () => {
expect(mockValidateEmailAddresses).toHaveBeenCalled();
expect(emailInput).not.toBeValid();
});
+
+ it('should use default values for startDate and timezone if not provided', async () => {
+ const systemTime = moment('2025-07-01');
+ jest.useFakeTimers().setSystemTime(systemTime.toDate());
+
+ render(
+
+
+
+ );
+
+ const timezoneField = await screen.findByTestId('timezoneCombobox');
+ expect(within(timezoneField).getByText(defaultTimezone)).toBeInTheDocument();
+
+ const startDatePicker = await screen.findByTestId('startDatePicker');
+ const startDateInput = within(startDatePicker).getByRole('textbox');
+ const startDateValue = startDateInput.getAttribute('value')!;
+ expect(startDateValue).toEqual(systemTime.format('MM/DD/YYYY hh:mm A'));
+
+ timezoneSpy.mockRestore();
+ jest.useRealTimers();
+ });
+
+ it('should show a validation error if startDate is in the past', async () => {
+ const systemTime = moment('2025-07-02');
+ jest.useFakeTimers().setSystemTime(systemTime.toDate());
+
+ render(
+
+
+
+ );
+
+ const startDatePicker = await screen.findByTestId('startDatePicker');
+ const startDateInput = within(startDatePicker).getByRole('textbox');
+ fireEvent.change(startDateInput, { target: { value: '07/01/2025 10:00 AM' } });
+ fireEvent.blur(startDateInput);
+
+ expect(await screen.findByText('Start date must be in the future')).toBeInTheDocument();
+
+ timezoneSpy.mockRestore();
+ jest.useRealTimers();
+ });
});
diff --git a/x-pack/platform/plugins/private/reporting/public/management/components/scheduled_report_flyout_content.tsx b/x-pack/platform/plugins/private/reporting/public/management/components/scheduled_report_flyout_content.tsx
index e7ab3a324a285..ac9ca25571b11 100644
--- a/x-pack/platform/plugins/private/reporting/public/management/components/scheduled_report_flyout_content.tsx
+++ b/x-pack/platform/plugins/private/reporting/public/management/components/scheduled_report_flyout_content.tsx
@@ -6,7 +6,7 @@
*/
import React, { useEffect, useMemo } from 'react';
-import moment from 'moment';
+import moment, { Moment } from 'moment';
import {
EuiBetaBadge,
EuiButton,
@@ -17,6 +17,7 @@ import {
EuiFlyoutBody,
EuiFlyoutFooter,
EuiFlyoutHeader,
+ EuiFormLabel,
EuiLink,
EuiLoadingSpinner,
EuiSpacer,
@@ -39,6 +40,12 @@ import { mountReactNode } from '@kbn/core-mount-utils-browser-internal';
import { RecurringScheduleFormFields } from '@kbn/response-ops-recurring-schedule-form/components/recurring_schedule_form_fields';
import { Field } from '@kbn/es-ui-shared-plugin/static/forms/components';
import { Frequency } from '@kbn/rrule';
+import { fieldValidators } from '@kbn/es-ui-shared-plugin/static/forms/helpers';
+import { TIMEZONE_OPTIONS as UI_TIMEZONE_OPTIONS } from '@kbn/core-ui-settings-common';
+import {
+ convertStringToMoment,
+ convertMomentToString,
+} from '@kbn/response-ops-recurring-schedule-form/converters/moment';
import { useGetUserProfileQuery } from '../hooks/use_get_user_profile_query';
import { ResponsiveFormGroup } from './responsive_form_group';
import { getReportParams } from '../report_params';
@@ -49,15 +56,25 @@ import { useGetReportingHealthQuery } from '../hooks/use_get_reporting_health_qu
import { ReportTypeData, ScheduledReport } from '../../types';
import * as i18n from '../translations';
import { SCHEDULED_REPORT_FORM_ID } from '../constants';
+import { getStartDateValidator } from '../validators/start_date_validator';
+
+const { emptyField } = fieldValidators;
const FormField = getUseField({
component: Field,
});
+const TIMEZONE_OPTIONS = UI_TIMEZONE_OPTIONS.map((tz) => ({
+ inputDisplay: tz,
+ value: tz,
+})) ?? [{ text: 'UTC', value: 'UTC' }];
+
export type FormData = Pick<
ScheduledReport,
| 'title'
| 'reportTypeId'
+ | 'startDate'
+ | 'timezone'
| 'recurringSchedule'
| 'sendByEmail'
| 'emailRecipients'
@@ -119,8 +136,6 @@ export const ScheduledReportFlyoutContent = ({
http,
});
const { defaultTimezone } = useDefaultTimezone();
- const now = useMemo(() => moment().tz(defaultTimezone), [defaultTimezone]);
- const defaultStartDateValue = useMemo(() => now.toISOString(), [now]);
const schema = useMemo(
() =>
getScheduledReportFormSchema(
@@ -130,8 +145,6 @@ export const ScheduledReportFlyoutContent = ({
[availableReportTypes, validateEmailAddresses]
);
const recurring = true;
- const startDate = defaultStartDateValue;
- const timezone = defaultTimezone;
const { form } = useForm({
defaultValue: scheduledReport,
options: { stripEmptyFields: true },
@@ -141,14 +154,15 @@ export const ScheduledReportFlyoutContent = ({
const {
title,
reportTypeId,
+ startDate,
+ timezone,
recurringSchedule,
optimizedForPrinting,
sendByEmail,
emailRecipients,
} = formData;
- // Remove start date since it's not supported for now
- const { dtstart, ...rrule } = convertToRRule({
- startDate: now,
+ const rrule = convertToRRule({
+ startDate,
timezone,
recurringSchedule,
includeTime: true,
@@ -187,10 +201,12 @@ export const ScheduledReportFlyoutContent = ({
}
},
});
- const [{ reportTypeId, sendByEmail }] = useFormData({
+ const [{ reportTypeId, startDate, timezone, sendByEmail }] = useFormData({
form,
- watch: ['reportTypeId', 'sendByEmail'],
+ watch: ['reportTypeId', 'startDate', 'timezone', 'sendByEmail'],
});
+ const now = useMemo(() => moment().set({ second: 0, millisecond: 0 }), []);
+ const defaultStartDateValue = useMemo(() => now.toISOString(), [now]);
useEffect(() => {
if (!readOnly && !hasManageReportingPrivilege && userProfile?.user.email) {
@@ -302,17 +318,79 @@ export const ScheduledReportFlyoutContent = ({
{i18n.SCHEDULED_REPORT_FORM_SCHEDULE_SECTION_TITLE}}
>
+
+ path="startDate"
+ config={{
+ type: FIELD_TYPES.DATE_PICKER,
+ label: i18n.SCHEDULED_REPORT_FORM_START_DATE_LABEL,
+ defaultValue: defaultStartDateValue,
+ serializer: convertMomentToString,
+ deserializer: convertStringToMoment,
+ validations: [
+ {
+ validator: emptyField(i18n.SCHEDULED_REPORT_FORM_START_DATE_REQUIRED_MESSAGE),
+ },
+ {
+ validator: getStartDateValidator(now, timezone ?? defaultTimezone),
+ },
+ ],
+ }}
+ componentProps={{
+ compressed: true,
+ fullWidth: true,
+ 'data-test-subj': 'startDatePicker',
+ euiFieldProps: {
+ compressed: true,
+ fullWidth: true,
+ showTimeSelect: true,
+ minDate: now,
+ readOnly,
+ },
+ }}
+ />
+
+ {i18n.SCHEDULED_REPORT_FORM_TIMEZONE_LABEL}
+
+ ),
+ readOnly,
+ },
+ }}
+ />
{isRecurring && (
-
+ <>
+
+
+ >
)}
{
+ const timezone = 'UTC';
+ const today = moment.tz('2025-07-11T00:00:00Z', timezone);
+ const validator = getStartDateValidator(today, timezone);
+
+ it('returns error if value is before today', () => {
+ const value = moment.tz('2025-07-10T23:59:59Z', timezone);
+ const result = validator({ value } as any);
+ expect(result).toEqual({ message: SCHEDULED_REPORT_FORM_START_DATE_TOO_EARLY_MESSAGE });
+ });
+
+ it('returns undefined if value is equal to today', () => {
+ const value = moment.tz('2025-07-11T00:00:00Z', timezone);
+ const result = validator({ value } as any);
+ expect(result).toBeUndefined();
+ });
+
+ it('returns undefined if value is after today', () => {
+ const value = moment.tz('2025-07-12T00:00:00Z', timezone);
+ const result = validator({ value } as any);
+ expect(result).toBeUndefined();
+ });
+
+ it('handles different timezones correctly', () => {
+ const tz = 'America/New_York';
+ const todayNY = moment.tz('2025-07-11T00:00:00', tz);
+ const validatorNY = getStartDateValidator(todayNY, tz);
+ const value = moment.tz('2025-07-10T23:59:59', tz);
+ const result = validatorNY({ value } as any);
+ expect(result).toEqual({ message: SCHEDULED_REPORT_FORM_START_DATE_TOO_EARLY_MESSAGE });
+ });
+});
diff --git a/x-pack/platform/plugins/private/reporting/public/management/validators/start_date_validator.ts b/x-pack/platform/plugins/private/reporting/public/management/validators/start_date_validator.ts
index 4555b4f1edf9e..121d1de901f41 100644
--- a/x-pack/platform/plugins/private/reporting/public/management/validators/start_date_validator.ts
+++ b/x-pack/platform/plugins/private/reporting/public/management/validators/start_date_validator.ts
@@ -11,9 +11,10 @@ import { SCHEDULED_REPORT_FORM_START_DATE_TOO_EARLY_MESSAGE } from '../translati
import { ScheduledReport } from '../../types';
export const getStartDateValidator =
- (today: Moment): ValidationFunc =>
+ (today: Moment, timezone: string): ValidationFunc, string, Moment> =>
({ value }) => {
- if (value.isBefore(today)) {
+ const valueInTimezone = value.clone().tz(timezone, true);
+ if (valueInTimezone.isBefore(today)) {
return {
message: SCHEDULED_REPORT_FORM_START_DATE_TOO_EARLY_MESSAGE,
};
diff --git a/x-pack/platform/plugins/private/reporting/public/types.ts b/x-pack/platform/plugins/private/reporting/public/types.ts
index af4b40e02a66e..9286ffa9e1fe6 100644
--- a/x-pack/platform/plugins/private/reporting/public/types.ts
+++ b/x-pack/platform/plugins/private/reporting/public/types.ts
@@ -54,21 +54,43 @@ export interface JobSummarySet {
export type ReportTypeId = 'pngV2' | 'printablePdfV2' | 'csv_searchsource' | 'csv_v2';
export interface ScheduledReport {
+ /**
+ * The title of the report, used for the filename and in the UI
+ */
title: string;
+ /**
+ * The type of report to generate, e.g. 'pngV2', 'printablePdfV2', 'csv_searchsource'
+ */
reportTypeId: ReportTypeId;
+ /**
+ * PDF-specific option
+ * TODO move this to a more specific interface
+ */
optimizedForPrinting?: boolean;
+ /**
+ * The date when the report should be first generated
+ */
+ startDate: string;
+ /**
+ * The timezone associated with the dates
+ */
+ timezone: string;
+ /**
+ * Whether the report should be generated on a recurring schedule
+ */
recurring: boolean;
+ /**
+ * If recurring, the schedule for generating the report
+ */
recurringSchedule: RecurringSchedule;
- sendByEmail: boolean;
- emailRecipients: string[];
/**
- * @internal Still unsupported by the schedule API
+ * Boolean indicating whether the report should be sent by email
*/
- startDate?: string;
+ sendByEmail: boolean;
/**
- * @internal Still unsupported by the schedule API
+ * List of email addresses to send the report to (`to` field in the email)
*/
- timezone?: string;
+ emailRecipients: string[];
}
export interface ReportTypeData {
diff --git a/x-pack/platform/plugins/private/reporting/tsconfig.json b/x-pack/platform/plugins/private/reporting/tsconfig.json
index 61c4266ab83ff..bd7bdca9d183f 100644
--- a/x-pack/platform/plugins/private/reporting/tsconfig.json
+++ b/x-pack/platform/plugins/private/reporting/tsconfig.json
@@ -65,7 +65,8 @@
"@kbn/core-http-browser",
"@kbn/response-ops-recurring-schedule-form",
"@kbn/core-mount-utils-browser-internal",
- "@kbn/core-user-profile-browser"
+ "@kbn/core-user-profile-browser",
+ "@kbn/core-ui-settings-common"
],
"exclude": ["target/**/*"]
}
diff --git a/x-pack/platform/plugins/shared/alerting/public/pages/maintenance_windows/components/create_maintenance_windows_form.tsx b/x-pack/platform/plugins/shared/alerting/public/pages/maintenance_windows/components/create_maintenance_windows_form.tsx
index 2670993aa2e2b..fc1ddfb52f81d 100644
--- a/x-pack/platform/plugins/shared/alerting/public/pages/maintenance_windows/components/create_maintenance_windows_form.tsx
+++ b/x-pack/platform/plugins/shared/alerting/public/pages/maintenance_windows/components/create_maintenance_windows_form.tsx
@@ -168,7 +168,7 @@ export const CreateMaintenanceWindowForm = React.memo