mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
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:
parent
87b8da1719
commit
a9aba2b42f
@ -11,6 +11,7 @@ import { getInputStyles } from '../Input/Input';
|
|||||||
|
|
||||||
import { TimePickerContent } from './TimeRangePicker/TimePickerContent';
|
import { TimePickerContent } from './TimeRangePicker/TimePickerContent';
|
||||||
import { TimeRangeLabel } from './TimeRangePicker/TimeRangeLabel';
|
import { TimeRangeLabel } from './TimeRangePicker/TimeRangeLabel';
|
||||||
|
import { WeekStart } from './WeekStartPicker';
|
||||||
import { quickOptions } from './options';
|
import { quickOptions } from './options';
|
||||||
import { isValidTimeRange } from './utils';
|
import { isValidTimeRange } from './utils';
|
||||||
|
|
||||||
@ -28,6 +29,8 @@ export interface TimeRangeInputProps {
|
|||||||
hideQuickRanges?: boolean;
|
hideQuickRanges?: boolean;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
showIcon?: boolean;
|
showIcon?: boolean;
|
||||||
|
/** Which day of the week the calendar should start on. Possible values: "saturday", "sunday" or "monday" */
|
||||||
|
weekStart?: WeekStart;
|
||||||
}
|
}
|
||||||
|
|
||||||
const noop = () => {};
|
const noop = () => {};
|
||||||
@ -37,6 +40,7 @@ export const TimeRangeInput = ({
|
|||||||
onChange,
|
onChange,
|
||||||
onChangeTimeZone = noop,
|
onChangeTimeZone = noop,
|
||||||
clearable,
|
clearable,
|
||||||
|
weekStart,
|
||||||
hideTimeZone = true,
|
hideTimeZone = true,
|
||||||
timeZone = 'browser',
|
timeZone = 'browser',
|
||||||
placeholder = 'Select time range',
|
placeholder = 'Select time range',
|
||||||
@ -106,6 +110,7 @@ export const TimeRangeInput = ({
|
|||||||
hideTimeZone={hideTimeZone}
|
hideTimeZone={hideTimeZone}
|
||||||
isReversed={isReversed}
|
isReversed={isReversed}
|
||||||
hideQuickRanges={hideQuickRanges}
|
hideQuickRanges={hideQuickRanges}
|
||||||
|
weekStart={weekStart}
|
||||||
/>
|
/>
|
||||||
</ClickOutsideWrapper>
|
</ClickOutsideWrapper>
|
||||||
)}
|
)}
|
||||||
|
@ -23,6 +23,7 @@ import { ToolbarButton } from '../ToolbarButton';
|
|||||||
import { Tooltip } from '../Tooltip/Tooltip';
|
import { Tooltip } from '../Tooltip/Tooltip';
|
||||||
|
|
||||||
import { TimePickerContent } from './TimeRangePicker/TimePickerContent';
|
import { TimePickerContent } from './TimeRangePicker/TimePickerContent';
|
||||||
|
import { WeekStart } from './WeekStartPicker';
|
||||||
import { quickOptions } from './options';
|
import { quickOptions } from './options';
|
||||||
|
|
||||||
/** @public */
|
/** @public */
|
||||||
@ -45,6 +46,8 @@ export interface TimeRangePickerProps {
|
|||||||
widthOverride?: number;
|
widthOverride?: number;
|
||||||
isOnCanvas?: boolean;
|
isOnCanvas?: boolean;
|
||||||
onToolbarTimePickerClick?: () => void;
|
onToolbarTimePickerClick?: () => void;
|
||||||
|
/** Which day of the week the calendar should start on. Possible values: "saturday", "sunday" or "monday" */
|
||||||
|
weekStart?: WeekStart;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface State {
|
export interface State {
|
||||||
@ -71,6 +74,7 @@ export function TimeRangePicker(props: TimeRangePickerProps) {
|
|||||||
widthOverride,
|
widthOverride,
|
||||||
isOnCanvas,
|
isOnCanvas,
|
||||||
onToolbarTimePickerClick,
|
onToolbarTimePickerClick,
|
||||||
|
weekStart,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const onChange = (timeRange: TimeRange) => {
|
const onChange = (timeRange: TimeRange) => {
|
||||||
@ -168,6 +172,7 @@ export function TimeRangePicker(props: TimeRangePickerProps) {
|
|||||||
onChangeFiscalYearStartMonth={onChangeFiscalYearStartMonth}
|
onChangeFiscalYearStartMonth={onChangeFiscalYearStartMonth}
|
||||||
hideQuickRanges={hideQuickRanges}
|
hideQuickRanges={hideQuickRanges}
|
||||||
onError={onError}
|
onError={onError}
|
||||||
|
weekStart={weekStart}
|
||||||
/>
|
/>
|
||||||
</section>
|
</section>
|
||||||
</FocusScope>
|
</FocusScope>
|
||||||
|
@ -1,17 +1,25 @@
|
|||||||
import { css } from '@emotion/css';
|
import { css } from '@emotion/css';
|
||||||
import React, { useCallback } from 'react';
|
import React, { useCallback } from 'react';
|
||||||
import Calendar from 'react-calendar';
|
import Calendar from 'react-calendar';
|
||||||
|
import { CalendarType } from 'react-calendar/dist/cjs/shared/types';
|
||||||
|
|
||||||
import { GrafanaTheme2, dateTimeParse, DateTime, TimeZone } from '@grafana/data';
|
import { GrafanaTheme2, dateTimeParse, DateTime, TimeZone } from '@grafana/data';
|
||||||
|
|
||||||
import { useStyles2 } from '../../../themes';
|
import { useStyles2 } from '../../../themes';
|
||||||
import { t } from '../../../utils/i18n';
|
import { t } from '../../../utils/i18n';
|
||||||
import { Icon } from '../../Icon/Icon';
|
import { Icon } from '../../Icon/Icon';
|
||||||
|
import { WeekStart } from '../WeekStartPicker';
|
||||||
import { adjustDateForReactCalendar } from '../utils/adjustDateForReactCalendar';
|
import { adjustDateForReactCalendar } from '../utils/adjustDateForReactCalendar';
|
||||||
|
|
||||||
import { TimePickerCalendarProps } from './TimePickerCalendar';
|
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 value = inputToValue(from, to, new Date(), timeZone);
|
||||||
const onCalendarChange = useOnCalendarChange(onChange, timeZone);
|
const onCalendarChange = useOnCalendarChange(onChange, timeZone);
|
||||||
const styles = useStyles2(getBodyStyles);
|
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')}
|
prevAriaLabel={t('time-picker.calendar.previous-month', 'Previous month')}
|
||||||
onChange={onCalendarChange}
|
onChange={onCalendarChange}
|
||||||
locale="en"
|
locale="en"
|
||||||
|
calendarType={weekStartMap[weekStart]}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ import { selectors } from '@grafana/e2e-selectors';
|
|||||||
|
|
||||||
import { useStyles2, useTheme2 } from '../../../themes';
|
import { useStyles2, useTheme2 } from '../../../themes';
|
||||||
import { getModalStyles } from '../../Modal/getModalStyles';
|
import { getModalStyles } from '../../Modal/getModalStyles';
|
||||||
|
import { WeekStart } from '../WeekStartPicker';
|
||||||
|
|
||||||
import { Body } from './CalendarBody';
|
import { Body } from './CalendarBody';
|
||||||
import { Footer } from './CalendarFooter';
|
import { Footer } from './CalendarFooter';
|
||||||
@ -58,6 +59,7 @@ export interface TimePickerCalendarProps {
|
|||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
onApply: (e: FormEvent<HTMLButtonElement>) => void;
|
onApply: (e: FormEvent<HTMLButtonElement>) => void;
|
||||||
onChange: (from: DateTime, to: DateTime) => void;
|
onChange: (from: DateTime, to: DateTime) => void;
|
||||||
|
weekStart?: WeekStart;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When true, the calendar is rendered as a floating "tooltip" next to the input.
|
* When true, the calendar is rendered as a floating "tooltip" next to the input.
|
||||||
|
@ -9,6 +9,7 @@ import { getFocusStyles } from '../../../themes/mixins';
|
|||||||
import { t, Trans } from '../../../utils/i18n';
|
import { t, Trans } from '../../../utils/i18n';
|
||||||
import { FilterInput } from '../../FilterInput/FilterInput';
|
import { FilterInput } from '../../FilterInput/FilterInput';
|
||||||
import { Icon } from '../../Icon/Icon';
|
import { Icon } from '../../Icon/Icon';
|
||||||
|
import { WeekStart } from '../WeekStartPicker';
|
||||||
|
|
||||||
import { TimePickerFooter } from './TimePickerFooter';
|
import { TimePickerFooter } from './TimePickerFooter';
|
||||||
import { TimePickerTitle } from './TimePickerTitle';
|
import { TimePickerTitle } from './TimePickerTitle';
|
||||||
@ -33,6 +34,7 @@ interface Props {
|
|||||||
isReversed?: boolean;
|
isReversed?: boolean;
|
||||||
hideQuickRanges?: boolean;
|
hideQuickRanges?: boolean;
|
||||||
widthOverride?: number;
|
widthOverride?: number;
|
||||||
|
weekStart?: WeekStart;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PropsWithScreenSize extends Props {
|
export interface PropsWithScreenSize extends Props {
|
||||||
@ -121,7 +123,7 @@ export const TimePickerContent = (props: Props) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const NarrowScreenForm = (props: FormProps) => {
|
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 styles = useStyles2(getNarrowScreenStyles);
|
||||||
const isAbsolute = isDateTime(value.raw.from) || isDateTime(value.raw.to);
|
const isAbsolute = isDateTime(value.raw.from) || isDateTime(value.raw.to);
|
||||||
const [collapsedFlag, setCollapsedFlag] = useState(!isAbsolute);
|
const [collapsedFlag, setCollapsedFlag] = useState(!isAbsolute);
|
||||||
@ -161,6 +163,7 @@ const NarrowScreenForm = (props: FormProps) => {
|
|||||||
timeZone={timeZone}
|
timeZone={timeZone}
|
||||||
isFullscreen={false}
|
isFullscreen={false}
|
||||||
onError={onError}
|
onError={onError}
|
||||||
|
weekStart={weekStart}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{showHistory && (
|
{showHistory && (
|
||||||
@ -178,7 +181,7 @@ const NarrowScreenForm = (props: FormProps) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const FullScreenForm = (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 styles = useStyles2(getFullScreenStyles, props.hideQuickRanges);
|
||||||
const onChangeTimeOption = (timeOption: TimeOption) => {
|
const onChangeTimeOption = (timeOption: TimeOption) => {
|
||||||
return onChange(mapOptionToTimeRange(timeOption, timeZone));
|
return onChange(mapOptionToTimeRange(timeOption, timeZone));
|
||||||
@ -200,6 +203,7 @@ const FullScreenForm = (props: FormProps) => {
|
|||||||
isFullscreen={true}
|
isFullscreen={true}
|
||||||
isReversed={isReversed}
|
isReversed={isReversed}
|
||||||
onError={onError}
|
onError={onError}
|
||||||
|
weekStart={weekStart}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{props.showHistory && (
|
{props.showHistory && (
|
||||||
|
@ -21,6 +21,7 @@ import { Field } from '../../Forms/Field';
|
|||||||
import { Icon } from '../../Icon/Icon';
|
import { Icon } from '../../Icon/Icon';
|
||||||
import { Input } from '../../Input/Input';
|
import { Input } from '../../Input/Input';
|
||||||
import { Tooltip } from '../../Tooltip/Tooltip';
|
import { Tooltip } from '../../Tooltip/Tooltip';
|
||||||
|
import { WeekStart } from '../WeekStartPicker';
|
||||||
import { isValid } from '../utils';
|
import { isValid } from '../utils';
|
||||||
|
|
||||||
import TimePickerCalendar from './TimePickerCalendar';
|
import TimePickerCalendar from './TimePickerCalendar';
|
||||||
@ -34,6 +35,7 @@ interface Props {
|
|||||||
roundup?: boolean;
|
roundup?: boolean;
|
||||||
isReversed?: boolean;
|
isReversed?: boolean;
|
||||||
onError?: (error?: string) => void;
|
onError?: (error?: string) => void;
|
||||||
|
weekStart?: WeekStart;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface InputState {
|
interface InputState {
|
||||||
@ -56,6 +58,7 @@ export const TimeRangeContent = (props: Props) => {
|
|||||||
isReversed,
|
isReversed,
|
||||||
fiscalYearStartMonth,
|
fiscalYearStartMonth,
|
||||||
onError,
|
onError,
|
||||||
|
weekStart,
|
||||||
} = props;
|
} = props;
|
||||||
const [fromValue, toValue] = valueToState(value.raw.from, value.raw.to, timeZone);
|
const [fromValue, toValue] = valueToState(value.raw.from, value.raw.to, timeZone);
|
||||||
const style = useStyles2(getStyles);
|
const style = useStyles2(getStyles);
|
||||||
@ -223,6 +226,7 @@ export const TimeRangeContent = (props: Props) => {
|
|||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
timeZone={timeZone}
|
timeZone={timeZone}
|
||||||
isReversed={isReversed}
|
isReversed={isReversed}
|
||||||
|
weekStart={weekStart}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -15,7 +15,8 @@ export interface Props {
|
|||||||
inputId?: string;
|
inputId?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const weekStarts: Array<SelectableValue<string>> = [
|
export type WeekStart = 'saturday' | 'sunday' | 'monday';
|
||||||
|
const weekStarts: Array<SelectableValue<WeekStart | ''>> = [
|
||||||
{ value: '', label: 'Default' },
|
{ value: '', label: 'Default' },
|
||||||
{ value: 'saturday', label: 'Saturday' },
|
{ value: 'saturday', label: 'Saturday' },
|
||||||
{ value: 'sunday', label: 'Sunday' },
|
{ value: 'sunday', label: 'Sunday' },
|
||||||
|
Loading…
Reference in New Issue
Block a user