mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
[ResponseOps][Maintenance Windows] Show dates in the selected timezone on the edit form (#158020)
Resolves https://github.com/elastic/kibana/issues/158013 ## Summary When a specific timezone has been set for a schedule, we will convert the time to local time when showing it in a list, table or overview. Updated the edit/create form so that when someone chooses to edit that schedule, we will then default to and show the specific timezone that was selected when it was created. ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios ### To verify Scenario 1: 1. Make sure your kibana timezone setting is set to `'Browser'` 2. Create a maintenance window and set the timezone to `America/Los_Angeles` or any timezone that is not your own 3. Verify that the times match the timezone set and save <img width="1002" alt="Screen Shot 2023-05-17 at 2 47 12 PM" src="4ea15e09
-3482-42a5-aa06-2dee7dd8c189"> 4. Verify on the table that the times match your current timezone <img width="829" alt="Screen Shot 2023-05-17 at 2 51 31 PM" src="29e6f52b
-8c40-4133-92fe-0674400a7368"> 5. Edit and verify that the times match the timezone you set when the mw was created <img width="991" alt="Screen Shot 2023-05-17 at 2 52 29 PM" src="9920d569
-0e7d-484a-8f08-d5f38a94616d"> Scenario 2: 1. Make sure your kibana timezone setting is set to timezone. I used `America/Denver` 2. Create a maintenance window and verify that the times reflect the timezone set in adv settings <img width="1000" alt="Screen Shot 2023-05-17 at 2 55 26 PM" src="31f3164e
-bb48-4ebe-98db-9bb24254fcd5"> 3. Verify on the table that the times match adv settings 4. Edit and verify that the times and the timezone match adv settings <img width="1001" alt="Screen Shot 2023-05-17 at 2 56 00 PM" src="350ad4bb
-9dbb-4265-bd7a-cf6a0cace7f7">
This commit is contained in:
parent
8cf6d034e3
commit
212e4df02d
6 changed files with 75 additions and 17 deletions
|
@ -94,8 +94,8 @@ describe('CreateMaintenanceWindowForm', () => {
|
|||
const timezoneInput = within(result.getByTestId('timezone-field')).getByTestId('input');
|
||||
|
||||
expect(titleInput).toHaveValue('test');
|
||||
expect(dateInputs[0]).toHaveValue('03/24/2023 12:00 AM');
|
||||
expect(dateInputs[1]).toHaveValue('03/26/2023 12:00 AM');
|
||||
expect(dateInputs[0]).toHaveValue('03/23/2023 09:00 PM');
|
||||
expect(dateInputs[1]).toHaveValue('03/25/2023 09:00 PM');
|
||||
expect(recurringInput).toBeChecked();
|
||||
expect(timezoneInput).toHaveTextContent('America/Los_Angeles');
|
||||
});
|
||||
|
|
|
@ -108,9 +108,9 @@ export const CreateMaintenanceWindowForm = React.memo<CreateMaintenanceWindowFor
|
|||
onSubmit: submitMaintenanceWindow,
|
||||
});
|
||||
|
||||
const [{ recurring }] = useFormData<FormProps>({
|
||||
const [{ recurring, timezone }] = useFormData<FormProps>({
|
||||
form,
|
||||
watch: ['recurring'],
|
||||
watch: ['recurring', 'timezone'],
|
||||
});
|
||||
const isRecurring = recurring || false;
|
||||
const showTimezone = isBrowser || initialValue?.timezone !== undefined;
|
||||
|
@ -181,7 +181,13 @@ export const CreateMaintenanceWindowForm = React.memo<CreateMaintenanceWindowFor
|
|||
},
|
||||
}}
|
||||
>
|
||||
{(fields) => <DatePickerRangeField fields={fields} data-test-subj="date-field" />}
|
||||
{(fields) => (
|
||||
<DatePickerRangeField
|
||||
fields={fields}
|
||||
timezone={timezone ?? [defaultTimezone]}
|
||||
data-test-subj="date-field"
|
||||
/>
|
||||
)}
|
||||
</UseMultiFields>
|
||||
</EuiFlexItem>
|
||||
{showTimezone ? (
|
||||
|
|
|
@ -28,7 +28,7 @@ export const DatePickerField: React.FC<DatePickerFieldProps> = React.memo(
|
|||
const { setFieldValue } = useFormContext();
|
||||
const [form] = useFormData({ watch: [field.path] });
|
||||
|
||||
const selected = getSelected(form, field.path);
|
||||
const { selected, utcOffset } = getSelected(form, field.path);
|
||||
|
||||
const onChange = useCallback(
|
||||
(currentDate: Moment | null) => {
|
||||
|
@ -45,6 +45,7 @@ export const DatePickerField: React.FC<DatePickerFieldProps> = React.memo(
|
|||
selected={selected}
|
||||
onChange={onChange}
|
||||
minDate={today}
|
||||
utcOffset={utcOffset}
|
||||
fullWidth
|
||||
/>
|
||||
</EuiFormRow>
|
||||
|
|
|
@ -18,19 +18,28 @@ import { getSelectedForDatePicker as getSelected } from '../../helpers/get_selec
|
|||
|
||||
interface DatePickerRangeFieldProps {
|
||||
fields: { startDate: FieldHook<string, string>; endDate: FieldHook<string, string> };
|
||||
timezone?: string[];
|
||||
showTimeSelect?: boolean;
|
||||
'data-test-subj'?: string;
|
||||
}
|
||||
|
||||
export const DatePickerRangeField: React.FC<DatePickerRangeFieldProps> = React.memo(
|
||||
({ fields, showTimeSelect = true, ...rest }) => {
|
||||
({ fields, timezone, showTimeSelect = true, ...rest }) => {
|
||||
const [today] = useState<Moment>(moment());
|
||||
|
||||
const { setFieldValue } = useFormContext();
|
||||
const [form] = useFormData({ watch: [fields.startDate.path, fields.endDate.path] });
|
||||
|
||||
const startDate = getSelected(form, fields.startDate.path);
|
||||
const endDate = getSelected(form, fields.endDate.path);
|
||||
const { selected: startDate, utcOffset: startOffset } = getSelected(
|
||||
form,
|
||||
fields.startDate.path,
|
||||
timezone
|
||||
);
|
||||
const { selected: endDate, utcOffset: endOffset } = getSelected(
|
||||
form,
|
||||
fields.endDate.path,
|
||||
timezone
|
||||
);
|
||||
|
||||
const onStartDateChange = useCallback(
|
||||
(currentDate: Moment | null) => {
|
||||
|
@ -69,6 +78,7 @@ export const DatePickerRangeField: React.FC<DatePickerRangeFieldProps> = React.m
|
|||
aria-label="Start date"
|
||||
showTimeSelect={showTimeSelect}
|
||||
minDate={today}
|
||||
utcOffset={startOffset}
|
||||
/>
|
||||
}
|
||||
endDateControl={
|
||||
|
@ -80,6 +90,7 @@ export const DatePickerRangeField: React.FC<DatePickerRangeFieldProps> = React.m
|
|||
aria-label="End date"
|
||||
showTimeSelect={showTimeSelect}
|
||||
minDate={today}
|
||||
utcOffset={endOffset}
|
||||
/>
|
||||
}
|
||||
fullWidth
|
||||
|
|
|
@ -15,22 +15,43 @@ describe('getSelectedForDatePicker', () => {
|
|||
test('should return the current date if the form is not initialized', () => {
|
||||
jest.useFakeTimers().setSystemTime(new Date('2023-03-30T00:00:00.000Z'));
|
||||
|
||||
expect(getSelectedForDatePicker({}, 'date').toISOString()).toEqual('2023-03-30T00:00:00.000Z');
|
||||
const { selected } = getSelectedForDatePicker({}, 'date');
|
||||
expect(selected.toISOString()).toEqual('2023-03-30T00:00:00.000Z');
|
||||
});
|
||||
|
||||
test('should return the form date if it is valid', () => {
|
||||
jest.useFakeTimers().setSystemTime(new Date('2023-03-30T00:00:00.000Z'));
|
||||
|
||||
expect(
|
||||
getSelectedForDatePicker({ date: '2023-01-30T00:00:00.000Z' }, 'date').toISOString()
|
||||
).toEqual('2023-01-30T00:00:00.000Z');
|
||||
const { selected } = getSelectedForDatePicker({ date: '2023-01-30T00:00:00.000Z' }, 'date');
|
||||
expect(selected.toISOString()).toEqual('2023-01-30T00:00:00.000Z');
|
||||
});
|
||||
|
||||
test('should return the current date if the form date is not valid', () => {
|
||||
jest.useFakeTimers().setSystemTime(new Date('2023-03-30T00:00:00.000Z'));
|
||||
|
||||
expect(getSelectedForDatePicker({ date: 'test' }, 'date').toISOString()).toEqual(
|
||||
'2023-03-30T00:00:00.000Z'
|
||||
const { selected } = getSelectedForDatePicker({ date: 'test' }, 'date');
|
||||
expect(selected.toISOString()).toEqual('2023-03-30T00:00:00.000Z');
|
||||
});
|
||||
|
||||
test('should return the current date if the form is not initialized and an offset that reflects the timezone', () => {
|
||||
jest.useFakeTimers().setSystemTime(new Date('2023-03-30T00:00:00.000Z'));
|
||||
|
||||
const { selected, utcOffset } = getSelectedForDatePicker({}, 'date', ['America/Denver']);
|
||||
expect(selected.toISOString()).toEqual('2023-03-30T00:00:00.000Z');
|
||||
expect(selected.toString()).toEqual('Wed Mar 29 2023 18:00:00 GMT-0600');
|
||||
expect(utcOffset).toEqual(-360);
|
||||
});
|
||||
|
||||
test('should return the form date if it is valid and an offset that reflects the timezone', () => {
|
||||
jest.useFakeTimers().setSystemTime(new Date('2023-03-30T00:00:00.000Z'));
|
||||
|
||||
const { selected, utcOffset } = getSelectedForDatePicker(
|
||||
{ date: '2023-05-01T00:00:00.000Z' },
|
||||
'date',
|
||||
['America/Denver']
|
||||
);
|
||||
expect(selected.toISOString()).toEqual('2023-05-01T00:00:00.000Z');
|
||||
expect(selected.toString()).toEqual('Sun Apr 30 2023 18:00:00 GMT-0600');
|
||||
expect(utcOffset).toEqual(-360);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -7,9 +7,15 @@
|
|||
|
||||
import { get } from 'lodash';
|
||||
import moment, { Moment } from 'moment';
|
||||
import 'moment-timezone';
|
||||
|
||||
import { FormData } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib';
|
||||
|
||||
export function getSelectedForDatePicker(form: FormData, path: string): Moment {
|
||||
export function getSelectedForDatePicker(
|
||||
form: FormData,
|
||||
path: string,
|
||||
timezone?: string[]
|
||||
): { selected: Moment; utcOffset: number } {
|
||||
// parse from a string date to moment() if there is an intitial value
|
||||
// otherwise just get the current date
|
||||
const initialValue = get(form, path);
|
||||
|
@ -17,5 +23,18 @@ export function getSelectedForDatePicker(form: FormData, path: string): Moment {
|
|||
if (initialValue && moment(initialValue).isValid()) {
|
||||
selected = moment(initialValue);
|
||||
}
|
||||
return selected;
|
||||
const utcOffset =
|
||||
timezone && timezone.length > 0
|
||||
? moment()
|
||||
.tz(timezone[0])
|
||||
.year(selected.year())
|
||||
.month(selected.month())
|
||||
.date(selected.date())
|
||||
.hour(selected.hour())
|
||||
.minute(selected.minute())
|
||||
.second(selected.second())
|
||||
.millisecond(selected.millisecond())
|
||||
.utcOffset()
|
||||
: selected.utcOffset();
|
||||
return { selected: selected.clone().utcOffset(utcOffset), utcOffset };
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue