1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 | import * as React from "react";
|
18 |
|
19 | import { Menu, MenuItem } from "@blueprintjs/core";
|
20 |
|
21 | import { Classes, type DateRange, type TimePrecision } from "../../common";
|
22 | import { clone, isDayRangeInRange } from "../../common/dateUtils";
|
23 |
|
24 | export interface DateShortcutBase {
|
25 |
|
26 | label: string;
|
27 |
|
28 | |
29 |
|
30 |
|
31 |
|
32 |
|
33 |
|
34 |
|
35 |
|
36 | includeTime?: boolean;
|
37 | }
|
38 |
|
39 | export interface DateRangeShortcut extends DateShortcutBase {
|
40 | |
41 |
|
42 |
|
43 |
|
44 | dateRange: DateRange;
|
45 | }
|
46 |
|
47 | export interface DatePickerShortcut extends DateShortcutBase {
|
48 | |
49 |
|
50 |
|
51 |
|
52 | date: Date;
|
53 | }
|
54 |
|
55 | export interface DatePickerShortcutMenuProps {
|
56 | allowSingleDayRange: boolean;
|
57 | minDate: Date;
|
58 | maxDate: Date;
|
59 | shortcuts: DateRangeShortcut[] | true;
|
60 | timePrecision: TimePrecision;
|
61 | selectedShortcutIndex?: number;
|
62 | onShortcutClick: (shortcut: DateRangeShortcut, index: number) => void;
|
63 | |
64 |
|
65 |
|
66 |
|
67 |
|
68 |
|
69 | useSingleDateShortcuts?: boolean;
|
70 | }
|
71 |
|
72 |
|
73 |
|
74 |
|
75 |
|
76 |
|
77 |
|
78 | export class DatePickerShortcutMenu extends React.PureComponent<DatePickerShortcutMenuProps> {
|
79 | public static defaultProps: Partial<DatePickerShortcutMenuProps> = {
|
80 | selectedShortcutIndex: -1,
|
81 | };
|
82 |
|
83 | public render() {
|
84 | const shortcuts =
|
85 | this.props.shortcuts === true
|
86 | ? createDefaultShortcuts(
|
87 | this.props.allowSingleDayRange,
|
88 | this.props.timePrecision !== undefined,
|
89 | this.props.useSingleDateShortcuts === true,
|
90 | )
|
91 | : this.props.shortcuts;
|
92 |
|
93 | const shortcutElements = shortcuts.map((shortcut, index) => (
|
94 | <MenuItem
|
95 | active={this.props.selectedShortcutIndex === index}
|
96 | disabled={!this.isShortcutInRange(shortcut.dateRange)}
|
97 | key={index}
|
98 | onClick={this.getShorcutClickHandler(shortcut, index)}
|
99 | shouldDismissPopover={false}
|
100 | text={shortcut.label}
|
101 | />
|
102 | ));
|
103 |
|
104 | return (
|
105 | <Menu aria-label="Date picker shortcuts" className={Classes.DATERANGEPICKER_SHORTCUTS} tabIndex={0}>
|
106 | {shortcutElements}
|
107 | </Menu>
|
108 | );
|
109 | }
|
110 |
|
111 | private getShorcutClickHandler = (shortcut: DateRangeShortcut, index: number) => () => {
|
112 | const { onShortcutClick } = this.props;
|
113 |
|
114 | onShortcutClick(shortcut, index);
|
115 | };
|
116 |
|
117 | private isShortcutInRange = (shortcutDateRange: DateRange) => {
|
118 | const { minDate, maxDate } = this.props;
|
119 |
|
120 | return isDayRangeInRange(shortcutDateRange, [minDate, maxDate]);
|
121 | };
|
122 | }
|
123 |
|
124 | function createShortcut(label: string, dateRange: DateRange): DateRangeShortcut {
|
125 | return { dateRange, label };
|
126 | }
|
127 |
|
128 | function createDefaultShortcuts(
|
129 | allowSingleDayRange: boolean,
|
130 | hasTimePrecision: boolean,
|
131 | useSingleDateShortcuts: boolean,
|
132 | ) {
|
133 | const today = new Date();
|
134 | const makeDate = (action: (d: Date) => void) => {
|
135 | const returnVal = clone(today);
|
136 | action(returnVal);
|
137 | returnVal.setDate(returnVal.getDate() + 1);
|
138 | return returnVal;
|
139 | };
|
140 |
|
141 | const tomorrow = makeDate(() => null);
|
142 | const yesterday = makeDate(d => d.setDate(d.getDate() - 2));
|
143 | const oneWeekAgo = makeDate(d => d.setDate(d.getDate() - 7));
|
144 | const oneMonthAgo = makeDate(d => d.setMonth(d.getMonth() - 1));
|
145 | const threeMonthsAgo = makeDate(d => d.setMonth(d.getMonth() - 3));
|
146 | const sixMonthsAgo = makeDate(d => d.setMonth(d.getMonth() - 6));
|
147 | const oneYearAgo = makeDate(d => d.setFullYear(d.getFullYear() - 1));
|
148 | const twoYearsAgo = makeDate(d => d.setFullYear(d.getFullYear() - 2));
|
149 |
|
150 | const singleDayShortcuts =
|
151 | allowSingleDayRange || useSingleDateShortcuts
|
152 | ? [
|
153 | createShortcut("Today", [today, hasTimePrecision ? tomorrow : today]),
|
154 | createShortcut("Yesterday", [yesterday, hasTimePrecision ? today : yesterday]),
|
155 | ]
|
156 | : [];
|
157 |
|
158 | return [
|
159 | ...singleDayShortcuts,
|
160 | createShortcut(useSingleDateShortcuts ? "1 week ago" : "Past week", [oneWeekAgo, today]),
|
161 | createShortcut(useSingleDateShortcuts ? "1 month ago" : "Past month", [oneMonthAgo, today]),
|
162 | createShortcut(useSingleDateShortcuts ? "3 months ago" : "Past 3 months", [threeMonthsAgo, today]),
|
163 |
|
164 | ...(useSingleDateShortcuts ? [] : [createShortcut("Past 6 months", [sixMonthsAgo, today])]),
|
165 | createShortcut(useSingleDateShortcuts ? "1 year ago" : "Past year", [oneYearAgo, today]),
|
166 | ...(useSingleDateShortcuts ? [] : [createShortcut("Past 2 years", [twoYearsAgo, today])]),
|
167 | ];
|
168 | }
|