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