@grafana/ui
Version:
Grafana Components Library
295 lines (292 loc) • 11.2 kB
JavaScript
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
import { css, cx } from '@emotion/css';
import { useState, memo, useMemo } from 'react';
import { isDateTime, rangeUtil } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { t, Trans } from '@grafana/i18n';
import { useStyles2, useTheme2 } from '../../../themes/ThemeContext.mjs';
import { getFocusStyles } from '../../../themes/mixins.mjs';
import { FilterInput } from '../../FilterInput/FilterInput.mjs';
import { Icon } from '../../Icon/Icon.mjs';
import { TextLink } from '../../Link/TextLink.mjs';
import { TimePickerFooter } from './TimePickerFooter.mjs';
import { TimePickerTitle } from './TimePickerTitle.mjs';
import { TimeRangeContent } from './TimeRangeContent.mjs';
import { TimeRangeList } from './TimeRangeList.mjs';
import { mapOptionToTimeRange, mapRangeToTimeOption } from './mapper.mjs';
"use strict";
const TimePickerContentWithScreenSize = (props) => {
const {
quickOptions = [],
isReversed,
isFullscreen,
hideQuickRanges,
timeZone,
fiscalYearStartMonth,
value,
onChange,
history,
showHistory,
className,
hideTimeZone,
onChangeTimeZone,
onChangeFiscalYearStartMonth
} = props;
const isHistoryEmpty = !(history == null ? void 0 : history.length);
const isContainerTall = isFullscreen && showHistory || !isFullscreen && (showHistory && !isHistoryEmpty || !hideQuickRanges);
const styles = useStyles2(getStyles, isReversed, hideQuickRanges, isContainerTall, isFullscreen);
const historyOptions = mapToHistoryOptions(history, timeZone);
const timeOption = useTimeOption(value.raw, quickOptions);
const [searchTerm, setSearchQuery] = useState("");
const filteredQuickOptions = quickOptions.filter((o) => o.display.toLowerCase().includes(searchTerm.toLowerCase()));
const onChangeTimeOption = (timeOption2) => {
return onChange(mapOptionToTimeRange(timeOption2));
};
return /* @__PURE__ */ jsxs("div", { id: "TimePickerContent", className: cx(styles.container, className), children: [
/* @__PURE__ */ jsxs("div", { className: styles.body, children: [
(!isFullscreen || !hideQuickRanges) && /* @__PURE__ */ jsxs("div", { className: styles.rightSide, children: [
/* @__PURE__ */ jsx("div", { className: styles.timeRangeFilter, children: /* @__PURE__ */ jsx(
FilterInput,
{
width: 0,
value: searchTerm,
onChange: setSearchQuery,
placeholder: t("time-picker.content.filter-placeholder", "Search quick ranges")
}
) }),
/* @__PURE__ */ jsxs("div", { className: styles.scrollContent, children: [
!isFullscreen && /* @__PURE__ */ jsx(NarrowScreenForm, { ...props, historyOptions }),
!hideQuickRanges && /* @__PURE__ */ jsx(TimeRangeList, { options: filteredQuickOptions, onChange: onChangeTimeOption, value: timeOption })
] })
] }),
isFullscreen && /* @__PURE__ */ jsx("div", { className: styles.leftSide, children: /* @__PURE__ */ jsx(FullScreenForm, { ...props, historyOptions }) })
] }),
!hideTimeZone && isFullscreen && /* @__PURE__ */ jsx(
TimePickerFooter,
{
timeZone,
fiscalYearStartMonth,
onChangeTimeZone,
onChangeFiscalYearStartMonth
}
)
] });
};
const TimePickerContent = (props) => {
const { widthOverride } = props;
const theme = useTheme2();
const isFullscreen = (widthOverride || window.innerWidth) >= theme.breakpoints.values.lg;
return /* @__PURE__ */ jsx(TimePickerContentWithScreenSize, { ...props, isFullscreen });
};
const NarrowScreenForm = (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);
const collapsed = hideQuickRanges ? false : collapsedFlag;
const onChangeTimeOption = (timeOption) => {
return onChange(mapOptionToTimeRange(timeOption, timeZone));
};
return /* @__PURE__ */ jsxs("fieldset", { children: [
/* @__PURE__ */ jsx("div", { className: styles.header, children: /* @__PURE__ */ jsxs(
"button",
{
type: "button",
className: styles.expandButton,
onClick: () => {
if (!hideQuickRanges) {
setCollapsedFlag(!collapsed);
}
},
"data-testid": selectors.components.TimePicker.absoluteTimeRangeTitle,
"aria-expanded": !collapsed,
"aria-controls": "expanded-timerange",
children: [
/* @__PURE__ */ jsx(TimePickerTitle, { children: /* @__PURE__ */ jsx(Trans, { i18nKey: "time-picker.absolute.title", children: "Absolute time range" }) }),
!hideQuickRanges && /* @__PURE__ */ jsx(Icon, { name: !collapsed ? "angle-up" : "angle-down" })
]
}
) }),
!collapsed && /* @__PURE__ */ jsxs("div", { className: styles.body, id: "expanded-timerange", children: [
/* @__PURE__ */ jsx("div", { className: styles.form, children: /* @__PURE__ */ jsx(
TimeRangeContent,
{
value,
onApply: onChange,
timeZone,
isFullscreen: false,
onError,
weekStart
}
) }),
showHistory && /* @__PURE__ */ jsx(
TimeRangeList,
{
title: t("time-picker.absolute.recent-title", "Recently used absolute ranges"),
options: historyOptions,
onChange: onChangeTimeOption,
placeholderEmpty: null
}
)
] })
] });
};
const FullScreenForm = (props) => {
const { onChange, value, timeZone, fiscalYearStartMonth, isReversed, historyOptions, onError, weekStart } = props;
const styles = useStyles2(getFullScreenStyles, props.hideQuickRanges);
const onChangeTimeOption = (timeOption) => {
return onChange(mapOptionToTimeRange(timeOption, timeZone));
};
return /* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsxs("div", { className: styles.container, children: [
/* @__PURE__ */ jsx("div", { className: styles.title, "data-testid": selectors.components.TimePicker.absoluteTimeRangeTitle, children: /* @__PURE__ */ jsx(TimePickerTitle, { children: /* @__PURE__ */ jsx(Trans, { i18nKey: "time-picker.absolute.title", children: "Absolute time range" }) }) }),
/* @__PURE__ */ jsx(
TimeRangeContent,
{
value,
timeZone,
fiscalYearStartMonth,
onApply: onChange,
isFullscreen: true,
isReversed,
onError,
weekStart
}
)
] }),
props.showHistory && /* @__PURE__ */ jsx("div", { className: styles.recent, children: /* @__PURE__ */ jsx(
TimeRangeList,
{
title: t("time-picker.absolute.recent-title", "Recently used absolute ranges"),
options: historyOptions || [],
onChange: onChangeTimeOption,
placeholderEmpty: /* @__PURE__ */ jsx(EmptyRecentList, {})
}
) })
] });
};
const EmptyRecentList = memo(() => {
const styles = useStyles2(getEmptyListStyles);
const emptyRecentListText = t(
"time-picker.content.empty-recent-list-info",
"It looks like you haven't used this time picker before. As soon as you enter some time intervals, recently used intervals will appear here."
);
return /* @__PURE__ */ jsxs("div", { className: styles.container, children: [
/* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx("span", { children: emptyRecentListText }) }),
/* @__PURE__ */ jsx(Trans, { i18nKey: "time-picker.content.empty-recent-list-docs", children: /* @__PURE__ */ jsxs("div", { children: [
/* @__PURE__ */ jsx(TextLink, { href: "https://grafana.com/docs/grafana/latest/dashboards/time-range-controls", external: true, children: "Read the documentation" }),
/* @__PURE__ */ jsx("span", { children: " to find out more about how to enter custom time ranges." })
] }) })
] });
});
function mapToHistoryOptions(ranges, timeZone) {
if (!Array.isArray(ranges) || ranges.length === 0) {
return [];
}
return ranges.map((range) => mapRangeToTimeOption(range, timeZone));
}
EmptyRecentList.displayName = "EmptyRecentList";
const useTimeOption = (raw, quickOptions) => {
return useMemo(() => {
if (!rangeUtil.isRelativeTimeRange(raw)) {
return;
}
return quickOptions.find((option) => {
return option.from === raw.from && option.to === raw.to;
});
}, [raw, quickOptions]);
};
const getStyles = (theme, isReversed, hideQuickRanges, isContainerTall, isFullscreen) => ({
container: css({
background: theme.colors.background.elevated,
boxShadow: theme.shadows.z3,
width: `${isFullscreen ? "546px" : "262px"}`,
borderRadius: theme.shape.radius.default,
border: `1px solid ${theme.colors.border.weak}`,
[`${isReversed ? "left" : "right"}`]: 0,
display: "flex",
flexDirection: "column"
}),
body: css({
display: "flex",
flexDirection: "row-reverse",
height: `${isContainerTall ? "381px" : "217px"}`,
maxHeight: "100vh"
}),
leftSide: css({
display: "flex",
flexDirection: "column",
borderRight: `${isReversed ? "none" : `1px solid ${theme.colors.border.weak}`}`,
width: `${!hideQuickRanges ? "60%" : "100%"}`,
overflow: "auto",
scrollbarWidth: "thin",
order: isReversed ? 1 : 0
}),
rightSide: css({
width: `${isFullscreen ? "40%" : "100%"}; !important`,
borderRight: isReversed ? `1px solid ${theme.colors.border.weak}` : "none",
display: "flex",
flexDirection: "column"
}),
timeRangeFilter: css({
padding: theme.spacing(1)
}),
spacing: css({
marginTop: "16px"
}),
scrollContent: css({
overflowY: "auto",
scrollbarWidth: "thin"
})
});
const getNarrowScreenStyles = (theme) => ({
header: css({
display: "flex",
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
borderBottom: `1px solid ${theme.colors.border.weak}`,
padding: "7px 9px 7px 9px"
}),
expandButton: css({
backgroundColor: "transparent",
border: "none",
display: "flex",
width: "100%",
"&:focus-visible": getFocusStyles(theme)
}),
body: css({
borderBottom: `1px solid ${theme.colors.border.weak}`
}),
form: css({
padding: "7px 9px 7px 9px"
})
});
const getFullScreenStyles = (theme, hideQuickRanges) => ({
container: css({
paddingTop: "9px",
paddingLeft: "11px",
paddingRight: !hideQuickRanges ? "20%" : "11px"
}),
title: css({
marginBottom: "11px"
}),
recent: css({
flexGrow: 1,
display: "flex",
flexDirection: "column",
justifyContent: "flex-end",
paddingTop: theme.spacing(1)
})
});
const getEmptyListStyles = (theme) => ({
container: css({
padding: "12px",
margin: "12px",
"a, span": {
fontSize: "13px"
}
})
});
export { TimePickerContent, TimePickerContentWithScreenSize };
//# sourceMappingURL=TimePickerContent.mjs.map