import { css } from '@emotion/css'; import moment, { Moment } from 'moment/moment'; import { ChangeEvent, useState } from 'react'; import { dateTimeAsMoment, getTimeZoneInfo, GrafanaTheme2, isDateTime, SelectableValue } from '@grafana/data'; import { Button, Field, FieldSet, Input, Select, Stack, Switch, TimeOfDayPicker, TimeZonePicker, useStyles2, } from '@grafana/ui'; import { TimeZoneOffset } from '@grafana/ui/src/components/DateTimePickers/TimeZonePicker/TimeZoneOffset'; import { TimeZoneTitle } from '@grafana/ui/src/components/DateTimePickers/TimeZonePicker/TimeZoneTitle'; import { t } from 'app/core/internationalization'; import { TimeRegionConfig, TimeRegionMode } from 'app/core/utils/timeRegions'; import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv'; interface Props { value: TimeRegionConfig; onChange: (value?: TimeRegionConfig) => void; } const days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'].map((v, idx) => { return { label: v, value: idx + 1, }; }); export const TimeRegionEditor = ({ value, onChange }: Props) => { const styles = useStyles2(getStyles); const timestamp = Date.now(); const timezoneInfo = getTimeZoneInfo(value.timezone ?? 'utc', timestamp); const isDashboardTimezone = getDashboardSrv().getCurrent()?.getTimezone() === value.timezone; const [isEditing, setEditing] = useState(false); const onToggleChangeTimezone = () => { setEditing(!isEditing); }; const getTime = (time: string | undefined): Moment | undefined => { if (!time) { return undefined; } const date = moment(); if (time) { const match = time.split(':'); date.set('hour', parseInt(match[0], 10)); date.set('minute', parseInt(match[1], 10)); } return date; }; const getToPlaceholder = () => { let placeholder = 'Everyday'; if (value.fromDayOfWeek && !value.toDayOfWeek) { placeholder = days[value.fromDayOfWeek - 1].label; } return placeholder; }; const renderTimezonePicker = () => { const timezone = ( <> ); if (isDashboardTimezone) { return <>Dashboard timezone ({timezone}); } return timezone; }; const onTimeChange = (v: Moment | undefined, field: string) => { const time = v ? v.format('HH:mm') : undefined; if (field === 'from') { onChange({ ...value, from: time }); } else { onChange({ ...value, to: time }); } }; const onTimezoneChange = (v: string | undefined) => { onChange({ ...value, timezone: v }); }; const onModeChange = (v: TimeRegionMode) => { onChange({ ...value, mode: v }); }; const onCronExprChange = (v: string) => { onChange({ ...value, cronExpr: v }); }; const onDurationChange = (v: string) => { onChange({ ...value, duration: v }); }; const onFromDayOfWeekChange = (v: SelectableValue) => { const fromDayOfWeek = v ? v.value : undefined; const toDayOfWeek = v ? value.toDayOfWeek : undefined; // clear if everyday onChange({ ...value, fromDayOfWeek, toDayOfWeek }); }; const onToDayOfWeekChange = (v: SelectableValue) => { onChange({ ...value, toDayOfWeek: v ? v.value : undefined }); }; const renderTimezone = () => { if (isEditing) { return ( onTimezoneChange(v)} onBlur={() => setEditing(false)} openMenuOnFocus={false} width={100} autoFocus /> ); } return (
{renderTimezonePicker()}
); }; const from = getTime(value.from); const to = getTime(value.to); return (
{t('dashboard-settings.time-regions.advanced-description-use', 'Use ')} {t('dashboard-settings.time-regions.advanced-description-cron', 'Cron syntax')} {t( 'dashboard-settings.time-regions.advanced-description-rest', ' to define a recurrence schedule and duration' )} } > ) => onModeChange(e.currentTarget.checked ? 'cron' : null)} /> {value.mode == null && ( <> onToDayOfWeekChange(v)} width={20} /> )} onTimeChange(v ? dateTimeAsMoment(v) : v, 'to')} allowEmpty={true} placeholder="HH:mm" size="sm" /> )} {value.mode === 'cron' && ( <> ) => onCronExprChange(e.target.value)} value={value.cronExpr} placeholder="0 9 * * 1-5" width={40} /> ) => onDurationChange(e.target.value)} value={value.duration} placeholder="8h" width={40} /> )} {renderTimezone()}
); }; const getStyles = (theme: GrafanaTheme2) => { return { wrapper: css({ maxWidth: theme.spacing(60), marginBottom: theme.spacing(2), }), timezoneContainer: css({ padding: '5px', display: 'flex', flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', fontSize: '12px', }), timezone: css({ marginRight: '5px', }), }; };