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
This commit is contained in:
Alex Khomenko 2024-06-25 14:22:55 +03:00 committed by GitHub
parent 87b8da1719
commit a9aba2b42f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 34 additions and 4 deletions

View File

@ -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}
/>
</ClickOutsideWrapper>
)}

View File

@ -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}
/>
</section>
</FocusScope>

View File

@ -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<WeekStart, CalendarType> = {
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]}
/>
);
}

View File

@ -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<HTMLButtonElement>) => void;
onChange: (from: DateTime, to: DateTime) => void;
weekStart?: WeekStart;
/**
* When true, the calendar is rendered as a floating "tooltip" next to the input.

View File

@ -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}
/>
</div>
{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}
/>
</div>
{props.showHistory && (

View File

@ -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}
/>
</div>
);

View File

@ -15,7 +15,8 @@ export interface Props {
inputId?: string;
}
const weekStarts: Array<SelectableValue<string>> = [
export type WeekStart = 'saturday' | 'sunday' | 'monday';
const weekStarts: Array<SelectableValue<WeekStart | ''>> = [
{ value: '', label: 'Default' },
{ value: 'saturday', label: 'Saturday' },
{ value: 'sunday', label: 'Sunday' },