UNPKG

@grafana/ui

Version:
263 lines (258 loc) • 9.31 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var jsxRuntime = require('react/jsx-runtime'); var css = require('@emotion/css'); var React = require('react'); var reactHookForm = require('react-hook-form'); var data = require('@grafana/data'); var e2eSelectors = require('@grafana/e2e-selectors'); var i18n = require('@grafana/i18n'); var ThemeContext = require('../../../themes/ThemeContext.cjs'); var Button = require('../../Button/Button.cjs'); var Field = require('../../Forms/Field.cjs'); var Icon = require('../../Icon/Icon.cjs'); var Input = require('../../Input/Input.cjs'); var Tooltip = require('../../Tooltip/Tooltip.cjs'); var utils = require('../utils.cjs'); var TimePickerCalendar = require('./TimePickerCalendar.cjs'); "use strict"; const ERROR_MESSAGES = { default: () => i18n.t( "time-picker.range-content.default-error", "Enter a date ({{dateExample}}) or relative time ({{relativeTimeExample1}}, {{relativeTimeExample2}})", { dateExample: "YYYY-MM-DD HH:mm:ss", relativeTimeExample1: "now", relativeTimeExample2: "now-1h" } ), range: () => i18n.t("time-picker.range-content.range-error", '"From" date must be before "To" date') }; const TimeRangeContent = (props) => { var _a, _b; const { value, isFullscreen = false, timeZone, onApply: onApplyFromProps, isReversed, fiscalYearStartMonth, onError, weekStart } = props; const style = ThemeContext.useStyles2(getStyles); const [isOpen, setOpen] = React.useState(false); const { handleSubmit, register, formState: { errors }, setValue, watch } = reactHookForm.useForm({ defaultValues: { from: valueAsString(value.raw.from, timeZone), to: valueAsString(value.raw.to, timeZone) } }); const fromFieldId = React.useId(); const toFieldId = React.useId(); React.useEffect(() => { setValue("from", valueAsString(value.raw.from, timeZone)); setValue("to", valueAsString(value.raw.to, timeZone)); }, [value.raw.from, value.raw.to, setValue, timeZone]); const onOpen = () => setOpen(true); const onApply = React.useCallback(() => { handleSubmit((data$1) => { const raw = { from: data$1.from, to: data$1.to }; const timeRange = data.rangeUtil.convertRawToRange(raw, timeZone, fiscalYearStartMonth); onApplyFromProps(timeRange); })(); }, [handleSubmit, timeZone, fiscalYearStartMonth, onApplyFromProps]); const onChange = React.useCallback( (from, to) => { setValue("from", valueAsString(from, timeZone)); setValue("to", valueAsString(to, timeZone)); }, [setValue, timeZone] ); const submitOnEnter = (event) => { if (event.key === "Enter") { onApply(); } }; const onCopy = () => { const rawSource = value.raw; const clipboardPayload = data.rangeUtil.formatRawTimeRange(rawSource); navigator.clipboard.writeText(JSON.stringify(clipboardPayload)); }; const onPaste = async () => { const raw = await navigator.clipboard.readText(); let range; try { range = JSON.parse(raw); } catch (error) { if (onError) { onError(raw); } return; } setValue("from", valueAsString(range.from, timeZone)); setValue("to", valueAsString(range.to, timeZone)); }; const fiscalYear = data.rangeUtil.convertRawToRange({ from: "now/fy", to: "now/fy" }, timeZone, fiscalYearStartMonth); const fyTooltip = /* @__PURE__ */ jsxRuntime.jsx("div", { className: style.tooltip, children: data.rangeUtil.isFiscal(value) ? /* @__PURE__ */ jsxRuntime.jsx( Tooltip.Tooltip, { content: i18n.t("time-picker.range-content.fiscal-year", "Fiscal year: {{from}} - {{to}}", { from: fiscalYear.from.format("MMM-DD"), to: fiscalYear.to.format("MMM-DD") }), children: /* @__PURE__ */ jsxRuntime.jsx(Icon.Icon, { name: "info-circle" }) } ) : null }); const icon = /* @__PURE__ */ jsxRuntime.jsx( Button.Button, { "aria-label": i18n.t("time-picker.range-content.open-input-calendar", "Open calendar"), "data-testid": e2eSelectors.selectors.components.TimePicker.calendar.openButton, icon: "calendar-alt", variant: "secondary", type: "button", onClick: onOpen } ); return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: style.fieldContainer, children: [ /* @__PURE__ */ jsxRuntime.jsx( Field.Field, { label: i18n.t("time-picker.range-content.from-input", "From"), invalid: !!errors.from, error: (_a = errors.from) == null ? void 0 : _a.message, children: /* @__PURE__ */ jsxRuntime.jsx( Input.Input, { ...register("from", { required: ERROR_MESSAGES.default(), validate: (value2, formValues) => { if (!utils.isValid(value2, false, timeZone)) { return ERROR_MESSAGES.default(); } if (!!formValues.to && utils.isValid(formValues.to, true, timeZone) && isRangeInvalid(value2, formValues.to, timeZone)) { return ERROR_MESSAGES.range(); } return true; } }), id: fromFieldId, onClick: (event) => event.stopPropagation(), onKeyDown: submitOnEnter, addonAfter: icon, "data-testid": e2eSelectors.selectors.components.TimePicker.fromField } ) } ), fyTooltip ] }), /* @__PURE__ */ jsxRuntime.jsxs("div", { className: style.fieldContainer, children: [ /* @__PURE__ */ jsxRuntime.jsx(Field.Field, { label: i18n.t("time-picker.range-content.to-input", "To"), invalid: !!errors.to, error: (_b = errors.to) == null ? void 0 : _b.message, children: /* @__PURE__ */ jsxRuntime.jsx( Input.Input, { ...register("to", { required: ERROR_MESSAGES.default(), validate: (value2, formValues) => { if (!utils.isValid(value2, true, timeZone)) { return ERROR_MESSAGES.default(); } if (!!formValues.from && utils.isValid(formValues.from, false, timeZone) && isRangeInvalid(formValues.from, value2, timeZone)) { return ERROR_MESSAGES.range(); } return true; } }), id: toFieldId, onClick: (event) => event.stopPropagation(), onKeyDown: submitOnEnter, addonAfter: icon, "data-testid": e2eSelectors.selectors.components.TimePicker.toField } ) }), fyTooltip ] }), /* @__PURE__ */ jsxRuntime.jsxs("div", { className: style.buttonsContainer, children: [ /* @__PURE__ */ jsxRuntime.jsx( Button.Button, { "data-testid": e2eSelectors.selectors.components.TimePicker.copyTimeRange, icon: "copy", variant: "secondary", tooltip: i18n.t("time-picker.copy-paste.tooltip-copy", "Copy time range to clipboard"), type: "button", onClick: onCopy } ), /* @__PURE__ */ jsxRuntime.jsx( Button.Button, { "data-testid": e2eSelectors.selectors.components.TimePicker.pasteTimeRange, icon: "clipboard-alt", variant: "secondary", tooltip: i18n.t("time-picker.copy-paste.tooltip-paste", "Paste time range"), type: "button", onClick: onPaste } ), /* @__PURE__ */ jsxRuntime.jsx(Button.Button, { "data-testid": e2eSelectors.selectors.components.TimePicker.applyTimeRange, type: "button", onClick: onApply, children: /* @__PURE__ */ jsxRuntime.jsx(i18n.Trans, { i18nKey: "time-picker.range-content.apply-button", children: "Apply time range" }) }) ] }), /* @__PURE__ */ jsxRuntime.jsx( TimePickerCalendar, { isFullscreen, isOpen, from: data.dateTimeParse(watch("from"), { timeZone }), to: data.dateTimeParse(watch("to"), { timeZone }), onApply, onClose: () => setOpen(false), onChange, timeZone, isReversed, weekStart } ) ] }); }; function isRangeInvalid(from, to, timezone) { const raw = { from, to }; const timeRange = data.rangeUtil.convertRawToRange(raw, timezone); const valid = timeRange.from.isSame(timeRange.to) || timeRange.from.isBefore(timeRange.to); return !valid; } function valueAsString(value, timeZone) { if (data.isDateTime(value)) { return data.dateTimeFormat(value, { timeZone }); } if (value.endsWith("Z")) { const dt = data.dateTimeParse(value); return data.dateTimeFormat(dt, { timeZone }); } return value; } function getStyles(theme) { return { fieldContainer: css.css({ display: "flex" }), buttonsContainer: css.css({ display: "flex", gap: theme.spacing(0.5), marginTop: theme.spacing(1) }), tooltip: css.css({ paddingLeft: theme.spacing(1), paddingTop: theme.spacing(3) }) }; } exports.TimeRangeContent = TimeRangeContent; //# sourceMappingURL=TimeRangeContent.cjs.map