From 96360bc3a5f41199f21cb5dd5f399fa0a13bf237 Mon Sep 17 00:00:00 2001 From: Gustavo Saiani <gustavo@poe.ma> Date: Thu, 21 Jul 2022 23:50:01 +0200 Subject: [PATCH] Extract CurrentPicker date component (#24192) --- .../CurrentPicker/CurrentPicker.styled.tsx | 42 +++++++++ .../CurrentPicker/CurrentPicker.tsx | 83 +++++++++++++++++ .../pickers/DatePicker/CurrentPicker/index.ts | 1 + .../filters/pickers/DatePicker/DatePicker.tsx | 3 +- .../DatePicker/RelativeDatePicker.styled.tsx | 41 ++------- .../pickers/DatePicker/RelativeDatePicker.tsx | 90 ++----------------- 6 files changed, 141 insertions(+), 119 deletions(-) create mode 100644 frontend/src/metabase/query_builder/components/filters/pickers/DatePicker/CurrentPicker/CurrentPicker.styled.tsx create mode 100644 frontend/src/metabase/query_builder/components/filters/pickers/DatePicker/CurrentPicker/CurrentPicker.tsx create mode 100644 frontend/src/metabase/query_builder/components/filters/pickers/DatePicker/CurrentPicker/index.ts diff --git a/frontend/src/metabase/query_builder/components/filters/pickers/DatePicker/CurrentPicker/CurrentPicker.styled.tsx b/frontend/src/metabase/query_builder/components/filters/pickers/DatePicker/CurrentPicker/CurrentPicker.styled.tsx new file mode 100644 index 00000000000..1df7070cc31 --- /dev/null +++ b/frontend/src/metabase/query_builder/components/filters/pickers/DatePicker/CurrentPicker/CurrentPicker.styled.tsx @@ -0,0 +1,42 @@ +import styled from "@emotion/styled"; + +import { alpha, color } from "metabase/lib/colors"; +import { space } from "metabase/styled-components/theme"; + +import Button from "metabase/core/components/Button"; + +export const CurrentContainer = styled.div<{ first?: boolean }>` + display: flex; + flex-wrap: no-wrap; + grid-gap: ${space(2)}; + margin-bottom: ${({ first }) => (first ? space(2) : "")}; +`; + +export const CurrentPopover = styled.div` + color: ${color("white")}; + background-color: ${color("black")}; + padding: ${space(1)} ${space(2)}; +`; + +type ButtonProps = { + primaryColor?: string; + selected?: boolean; +}; + +export const CurrentButton = styled(Button)<ButtonProps>` + border: none; + border-radius: 99px; + + background-color: ${({ selected, primaryColor = color("brand") }) => + selected ? primaryColor : alpha(primaryColor, 0.1)}; + color: ${({ selected, primaryColor = color("brand") }) => + selected ? "white" : primaryColor}; + + padding-top: ${space(1)}; + padding-bottom: ${space(1)}; + + &:hover { + color: white; + background-color: ${props => props.primaryColor || color("brand")}; + } +`; diff --git a/frontend/src/metabase/query_builder/components/filters/pickers/DatePicker/CurrentPicker/CurrentPicker.tsx b/frontend/src/metabase/query_builder/components/filters/pickers/DatePicker/CurrentPicker/CurrentPicker.tsx new file mode 100644 index 00000000000..fda08eb6ae5 --- /dev/null +++ b/frontend/src/metabase/query_builder/components/filters/pickers/DatePicker/CurrentPicker/CurrentPicker.tsx @@ -0,0 +1,83 @@ +import React from "react"; +import { t } from "ttag"; +import moment from "moment"; + +import { formatBucketing } from "metabase/lib/query_time"; +import TippyPopover from "metabase/components/Popover/TippyPopover"; +import { DATE_PERIODS } from "../RelativeDatePicker"; +import { + CurrentButton, + CurrentContainer, + CurrentPopover, +} from "./CurrentPicker.styled"; +import Filter from "metabase-lib/lib/queries/structured/Filter"; + +type CurrentPickerProps = { + className?: string; + filter: Filter; + primaryColor?: string; + onCommit: (filter?: any[]) => void; +}; + +const periodPopoverText = (period: string) => { + const now = moment(); + let start: string, end: string; + switch (period) { + case "day": + return t`Right now, this is ${now.format("ddd, MMM D")}`; + case "week": + start = now.startOf("week").format("ddd, MMM D"); + end = now.endOf("week").format("ddd, MMM D"); + return t`Right now, this is ${start} - ${end}`; + case "month": + start = now.startOf("month").format("ddd, MMM D"); + end = now.endOf("month").format("ddd, MMM D"); + return t`Right now, this is ${start} - ${end}`; + case "quarter": + start = now.startOf("quarter").format("ddd, MMM D"); + end = now.endOf("quarter").format("ddd, MMM D"); + return t`Right now, this is ${start} - ${end}`; + case "year": + start = now.startOf("year").format("MMM D, YYYY"); + end = now.endOf("year").format("MMM D, YYYY"); + return t`Right now, this is ${start} - ${end}`; + } +}; + +export default function CurrentPicker(props: CurrentPickerProps) { + const { + className, + primaryColor, + onCommit, + filter: [operator, field, _intervals, unit], + } = props; + return ( + <div className={className}> + {DATE_PERIODS.map((periods, index) => ( + <CurrentContainer key={periods.length} first={index === 0}> + {periods.map(period => ( + <TippyPopover + key={period} + placement="bottom" + delay={[500, null]} + content={ + <CurrentPopover>{periodPopoverText(period)}</CurrentPopover> + } + > + <CurrentButton + key={period} + primaryColor={primaryColor} + selected={operator && unit === period.toLowerCase()} + onClick={() => { + onCommit([operator, field, "current", period]); + }} + > + {formatBucketing(period, 1)} + </CurrentButton> + </TippyPopover> + ))} + </CurrentContainer> + ))} + </div> + ); +} diff --git a/frontend/src/metabase/query_builder/components/filters/pickers/DatePicker/CurrentPicker/index.ts b/frontend/src/metabase/query_builder/components/filters/pickers/DatePicker/CurrentPicker/index.ts new file mode 100644 index 00000000000..67dd0a40043 --- /dev/null +++ b/frontend/src/metabase/query_builder/components/filters/pickers/DatePicker/CurrentPicker/index.ts @@ -0,0 +1 @@ +export { default } from "./CurrentPicker"; diff --git a/frontend/src/metabase/query_builder/components/filters/pickers/DatePicker/DatePicker.tsx b/frontend/src/metabase/query_builder/components/filters/pickers/DatePicker/DatePicker.tsx index c7568eca1c5..26ce2d0e0fb 100644 --- a/frontend/src/metabase/query_builder/components/filters/pickers/DatePicker/DatePicker.tsx +++ b/frontend/src/metabase/query_builder/components/filters/pickers/DatePicker/DatePicker.tsx @@ -22,7 +22,8 @@ import DatePickerHeader from "./DatePickerHeader"; import ExcludeDatePicker from "./ExcludeDatePicker"; import DatePickerShortcuts from "./DatePickerShortcuts"; import { DateShortcutOptions } from "./DatePickerShortcutOptions"; -import { CurrentPicker, NextPicker, PastPicker } from "./RelativeDatePicker"; +import CurrentPicker from "./CurrentPicker"; +import { NextPicker, PastPicker } from "./RelativeDatePicker"; import { AfterPicker, BeforePicker, BetweenPicker } from "./RangeDatePicker"; import SingleDatePicker from "./SingleDatePicker"; diff --git a/frontend/src/metabase/query_builder/components/filters/pickers/DatePicker/RelativeDatePicker.styled.tsx b/frontend/src/metabase/query_builder/components/filters/pickers/DatePicker/RelativeDatePicker.styled.tsx index 6feb7f5b9a6..189af49e966 100644 --- a/frontend/src/metabase/query_builder/components/filters/pickers/DatePicker/RelativeDatePicker.styled.tsx +++ b/frontend/src/metabase/query_builder/components/filters/pickers/DatePicker/RelativeDatePicker.styled.tsx @@ -22,47 +22,16 @@ export const NumericInput = styled(BaseNumericInput)<BaseProps>` } `; -type ButtonProps = { - primaryColor?: string; - selected?: boolean; -}; - -export const CurrentButton = styled(Button)<ButtonProps>` - border: none; - border-radius: 99px; - - background-color: ${({ selected, primaryColor = color("brand") }) => - selected ? primaryColor : alpha(primaryColor, 0.1)}; - color: ${({ selected, primaryColor = color("brand") }) => - selected ? "white" : primaryColor}; - - padding-top: ${space(1)}; - padding-bottom: ${space(1)}; - - &:hover { - color: white; - background-color: ${props => props.primaryColor || color("brand")}; - } -`; - -export const CurrentContainer = styled.div<{ first?: boolean }>` - display: flex; - flex-wrap: no-wrap; - grid-gap: ${space(2)}; - margin-bottom: ${({ first }) => (first ? space(2) : "")}; -`; - -export const CurrentPopover = styled.div` - color: ${color("white")}; - background-color: ${color("black")}; - padding: ${space(1)} ${space(2)}; -`; - export const OptionsContainer = styled.div` background-color: ${color("white")}; padding: ${space(2)} ${space(1)}; `; +type ButtonProps = { + primaryColor?: string; + selected?: boolean; +}; + type OptionButtonProps = ButtonProps & { reverseIconDirection?: boolean; }; diff --git a/frontend/src/metabase/query_builder/components/filters/pickers/DatePicker/RelativeDatePicker.tsx b/frontend/src/metabase/query_builder/components/filters/pickers/DatePicker/RelativeDatePicker.tsx index 9baf997826b..f73dedc554d 100644 --- a/frontend/src/metabase/query_builder/components/filters/pickers/DatePicker/RelativeDatePicker.tsx +++ b/frontend/src/metabase/query_builder/components/filters/pickers/DatePicker/RelativeDatePicker.tsx @@ -5,7 +5,6 @@ import moment from "moment"; import { assoc } from "icepick"; import { - formatBucketing, formatStartingFrom, getRelativeDatetimeInterval, getStartingFrom, @@ -18,9 +17,6 @@ import TippyPopover from "metabase/components/Popover/TippyPopover"; import Filter from "metabase-lib/lib/queries/structured/Filter"; import { - CurrentButton, - CurrentContainer, - CurrentPopover, GridContainer, GridText, MoreButton, @@ -42,76 +38,16 @@ export const NextPicker = (props: Props) => ( /> ); -const periodPopoverText = (period: string) => { - const now = moment(); - let start: string, end: string; - switch (period) { - case "day": - return t`Right now, this is ${now.format("ddd, MMM D")}`; - case "week": - start = now.startOf("week").format("ddd, MMM D"); - end = now.endOf("week").format("ddd, MMM D"); - return t`Right now, this is ${start} - ${end}`; - case "month": - start = now.startOf("month").format("ddd, MMM D"); - end = now.endOf("month").format("ddd, MMM D"); - return t`Right now, this is ${start} - ${end}`; - case "quarter": - start = now.startOf("quarter").format("ddd, MMM D"); - end = now.endOf("quarter").format("ddd, MMM D"); - return t`Right now, this is ${start} - ${end}`; - case "year": - start = now.startOf("year").format("MMM D, YYYY"); - end = now.endOf("year").format("MMM D, YYYY"); - return t`Right now, this is ${start} - ${end}`; - } -}; - -type CurrentPickerProps = { - className?: string; - filter: Filter; - primaryColor?: string; - onCommit: (filter?: any[]) => void; +const CURRENT_INTERVAL_NAME = { + day: t`today`, + week: t`this week`, + month: t`this month`, + year: t`this year`, + quarter: t`this quarter`, + minute: t`this minute`, + hour: t`this hour`, }; -export function CurrentPicker(props: CurrentPickerProps) { - const { - className, - primaryColor, - onCommit, - filter: [operator, field, _intervals, unit], - } = props; - return ( - <div className={className}> - {DATE_PERIODS.map((periods, index) => ( - <CurrentContainer key={periods.length} first={index === 0}> - {periods.map(period => ( - <TippyPopover - key={period} - placement="bottom" - delay={[500, null]} - content={ - <CurrentPopover>{periodPopoverText(period)}</CurrentPopover> - } - > - <CurrentButton - key={period} - primaryColor={primaryColor} - selected={operator && unit === period.toLowerCase()} - onClick={() => { - onCommit([operator, field, "current", period]); - }} - > - {formatBucketing(period, 1)} - </CurrentButton> - </TippyPopover> - ))} - </CurrentContainer> - ))} - </div> - ); -} - export const DATE_PERIODS = [ ["day", "week", "month"], ["quarter", "year"], @@ -144,16 +80,6 @@ const getStartingFromUnits = ( const getCurrentString = (filter: Filter) => t`Include ${getCurrentIntervalName(filter)}`; -const CURRENT_INTERVAL_NAME = { - day: t`today`, - week: t`this week`, - month: t`this month`, - year: t`this year`, - quarter: t`this quarter`, - minute: t`this minute`, - hour: t`this hour`, -}; - function getCurrentIntervalName(filter: Filter) { if (filter[0] === "time-interval") { return CURRENT_INTERVAL_NAME[ -- GitLab