From a9aba2b42f79cf1095e971fbca81883d4cfc70e1 Mon Sep 17 00:00:00 2001 From: Alex Khomenko Date: Tue, 25 Jun 2024 14:22:55 +0300 Subject: [PATCH] TimeRangePicker: Add weekStart prop (#89650) * TimeRangePicker: Add weekStart prop * Set week start from config * Use week start from dashboard * Revert * Add comment * Tweak comment * Add WeekStart type --- .../src/components/DateTimePickers/TimeRangeInput.tsx | 5 +++++ .../components/DateTimePickers/TimeRangePicker.tsx | 5 +++++ .../DateTimePickers/TimeRangePicker/CalendarBody.tsx | 11 ++++++++++- .../TimeRangePicker/TimePickerCalendar.tsx | 2 ++ .../TimeRangePicker/TimePickerContent.tsx | 8 ++++++-- .../TimeRangePicker/TimeRangeContent.tsx | 4 ++++ .../components/DateTimePickers/WeekStartPicker.tsx | 3 ++- 7 files changed, 34 insertions(+), 4 deletions(-) diff --git a/packages/grafana-ui/src/components/DateTimePickers/TimeRangeInput.tsx b/packages/grafana-ui/src/components/DateTimePickers/TimeRangeInput.tsx index 03b48a4d7ff..1b0933bea19 100644 --- a/packages/grafana-ui/src/components/DateTimePickers/TimeRangeInput.tsx +++ b/packages/grafana-ui/src/components/DateTimePickers/TimeRangeInput.tsx @@ -11,6 +11,7 @@ import { getInputStyles } from '../Input/Input'; import { TimePickerContent } from './TimeRangePicker/TimePickerContent'; import { TimeRangeLabel } from './TimeRangePicker/TimeRangeLabel'; +import { WeekStart } from './WeekStartPicker'; import { quickOptions } from './options'; import { isValidTimeRange } from './utils'; @@ -28,6 +29,8 @@ export interface TimeRangeInputProps { hideQuickRanges?: boolean; disabled?: boolean; showIcon?: boolean; + /** Which day of the week the calendar should start on. Possible values: "saturday", "sunday" or "monday" */ + weekStart?: WeekStart; } const noop = () => {}; @@ -37,6 +40,7 @@ export const TimeRangeInput = ({ onChange, onChangeTimeZone = noop, clearable, + weekStart, hideTimeZone = true, timeZone = 'browser', placeholder = 'Select time range', @@ -106,6 +110,7 @@ export const TimeRangeInput = ({ hideTimeZone={hideTimeZone} isReversed={isReversed} hideQuickRanges={hideQuickRanges} + weekStart={weekStart} /> )} diff --git a/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker.tsx b/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker.tsx index d76cd7ac5fd..0619af37234 100644 --- a/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker.tsx +++ b/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker.tsx @@ -23,6 +23,7 @@ import { ToolbarButton } from '../ToolbarButton'; import { Tooltip } from '../Tooltip/Tooltip'; import { TimePickerContent } from './TimeRangePicker/TimePickerContent'; +import { WeekStart } from './WeekStartPicker'; import { quickOptions } from './options'; /** @public */ @@ -45,6 +46,8 @@ export interface TimeRangePickerProps { widthOverride?: number; isOnCanvas?: boolean; onToolbarTimePickerClick?: () => void; + /** Which day of the week the calendar should start on. Possible values: "saturday", "sunday" or "monday" */ + weekStart?: WeekStart; } export interface State { @@ -71,6 +74,7 @@ export function TimeRangePicker(props: TimeRangePickerProps) { widthOverride, isOnCanvas, onToolbarTimePickerClick, + weekStart, } = props; const onChange = (timeRange: TimeRange) => { @@ -168,6 +172,7 @@ export function TimeRangePicker(props: TimeRangePickerProps) { onChangeFiscalYearStartMonth={onChangeFiscalYearStartMonth} hideQuickRanges={hideQuickRanges} onError={onError} + weekStart={weekStart} /> diff --git a/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/CalendarBody.tsx b/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/CalendarBody.tsx index 652c223a0eb..b27d1b68d07 100644 --- a/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/CalendarBody.tsx +++ b/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/CalendarBody.tsx @@ -1,17 +1,25 @@ import { css } from '@emotion/css'; import React, { useCallback } from 'react'; import Calendar from 'react-calendar'; +import { CalendarType } from 'react-calendar/dist/cjs/shared/types'; import { GrafanaTheme2, dateTimeParse, DateTime, TimeZone } from '@grafana/data'; import { useStyles2 } from '../../../themes'; import { t } from '../../../utils/i18n'; import { Icon } from '../../Icon/Icon'; +import { WeekStart } from '../WeekStartPicker'; import { adjustDateForReactCalendar } from '../utils/adjustDateForReactCalendar'; import { TimePickerCalendarProps } from './TimePickerCalendar'; -export function Body({ onChange, from, to, timeZone }: TimePickerCalendarProps) { +const weekStartMap: Record = { + saturday: 'islamic', + sunday: 'gregory', + monday: 'iso8601', +}; + +export function Body({ onChange, from, to, timeZone, weekStart = 'monday' }: TimePickerCalendarProps) { const value = inputToValue(from, to, new Date(), timeZone); const onCalendarChange = useOnCalendarChange(onChange, timeZone); const styles = useStyles2(getBodyStyles); @@ -30,6 +38,7 @@ export function Body({ onChange, from, to, timeZone }: TimePickerCalendarProps) prevAriaLabel={t('time-picker.calendar.previous-month', 'Previous month')} onChange={onCalendarChange} locale="en" + calendarType={weekStartMap[weekStart]} /> ); } diff --git a/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/TimePickerCalendar.tsx b/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/TimePickerCalendar.tsx index 9b39f55f4af..692041f3030 100644 --- a/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/TimePickerCalendar.tsx +++ b/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/TimePickerCalendar.tsx @@ -9,6 +9,7 @@ import { selectors } from '@grafana/e2e-selectors'; import { useStyles2, useTheme2 } from '../../../themes'; import { getModalStyles } from '../../Modal/getModalStyles'; +import { WeekStart } from '../WeekStartPicker'; import { Body } from './CalendarBody'; import { Footer } from './CalendarFooter'; @@ -58,6 +59,7 @@ export interface TimePickerCalendarProps { onClose: () => void; onApply: (e: FormEvent) => void; onChange: (from: DateTime, to: DateTime) => void; + weekStart?: WeekStart; /** * When true, the calendar is rendered as a floating "tooltip" next to the input. diff --git a/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/TimePickerContent.tsx b/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/TimePickerContent.tsx index f8d9b847cf1..0a6a3b05b29 100644 --- a/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/TimePickerContent.tsx +++ b/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/TimePickerContent.tsx @@ -9,6 +9,7 @@ import { getFocusStyles } from '../../../themes/mixins'; import { t, Trans } from '../../../utils/i18n'; import { FilterInput } from '../../FilterInput/FilterInput'; import { Icon } from '../../Icon/Icon'; +import { WeekStart } from '../WeekStartPicker'; import { TimePickerFooter } from './TimePickerFooter'; import { TimePickerTitle } from './TimePickerTitle'; @@ -33,6 +34,7 @@ interface Props { isReversed?: boolean; hideQuickRanges?: boolean; widthOverride?: number; + weekStart?: WeekStart; } export interface PropsWithScreenSize extends Props { @@ -121,7 +123,7 @@ export const TimePickerContent = (props: Props) => { }; const NarrowScreenForm = (props: FormProps) => { - const { value, hideQuickRanges, onChange, timeZone, historyOptions = [], showHistory, onError } = props; + const { value, hideQuickRanges, onChange, timeZone, historyOptions = [], showHistory, onError, weekStart } = props; const styles = useStyles2(getNarrowScreenStyles); const isAbsolute = isDateTime(value.raw.from) || isDateTime(value.raw.to); const [collapsedFlag, setCollapsedFlag] = useState(!isAbsolute); @@ -161,6 +163,7 @@ const NarrowScreenForm = (props: FormProps) => { timeZone={timeZone} isFullscreen={false} onError={onError} + weekStart={weekStart} /> {showHistory && ( @@ -178,7 +181,7 @@ const NarrowScreenForm = (props: FormProps) => { }; const FullScreenForm = (props: FormProps) => { - const { onChange, value, timeZone, fiscalYearStartMonth, isReversed, historyOptions, onError } = props; + const { onChange, value, timeZone, fiscalYearStartMonth, isReversed, historyOptions, onError, weekStart } = props; const styles = useStyles2(getFullScreenStyles, props.hideQuickRanges); const onChangeTimeOption = (timeOption: TimeOption) => { return onChange(mapOptionToTimeRange(timeOption, timeZone)); @@ -200,6 +203,7 @@ const FullScreenForm = (props: FormProps) => { isFullscreen={true} isReversed={isReversed} onError={onError} + weekStart={weekStart} /> {props.showHistory && ( diff --git a/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/TimeRangeContent.tsx b/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/TimeRangeContent.tsx index d5a53aa10f3..ed2d5936146 100644 --- a/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/TimeRangeContent.tsx +++ b/packages/grafana-ui/src/components/DateTimePickers/TimeRangePicker/TimeRangeContent.tsx @@ -21,6 +21,7 @@ import { Field } from '../../Forms/Field'; import { Icon } from '../../Icon/Icon'; import { Input } from '../../Input/Input'; import { Tooltip } from '../../Tooltip/Tooltip'; +import { WeekStart } from '../WeekStartPicker'; import { isValid } from '../utils'; import TimePickerCalendar from './TimePickerCalendar'; @@ -34,6 +35,7 @@ interface Props { roundup?: boolean; isReversed?: boolean; onError?: (error?: string) => void; + weekStart?: WeekStart; } interface InputState { @@ -56,6 +58,7 @@ export const TimeRangeContent = (props: Props) => { isReversed, fiscalYearStartMonth, onError, + weekStart, } = props; const [fromValue, toValue] = valueToState(value.raw.from, value.raw.to, timeZone); const style = useStyles2(getStyles); @@ -223,6 +226,7 @@ export const TimeRangeContent = (props: Props) => { onChange={onChange} timeZone={timeZone} isReversed={isReversed} + weekStart={weekStart} /> ); diff --git a/packages/grafana-ui/src/components/DateTimePickers/WeekStartPicker.tsx b/packages/grafana-ui/src/components/DateTimePickers/WeekStartPicker.tsx index 59dd368280a..1a06c98fed9 100644 --- a/packages/grafana-ui/src/components/DateTimePickers/WeekStartPicker.tsx +++ b/packages/grafana-ui/src/components/DateTimePickers/WeekStartPicker.tsx @@ -15,7 +15,8 @@ export interface Props { inputId?: string; } -const weekStarts: Array> = [ +export type WeekStart = 'saturday' | 'sunday' | 'monday'; +const weekStarts: Array> = [ { value: '', label: 'Default' }, { value: 'saturday', label: 'Saturday' }, { value: 'sunday', label: 'Sunday' },