@@ -139,8 +139,60 @@ class StatsPeriodNavigation extends PureComponent {
139
139
this . handleArrowNavigation ( false ) ;
140
140
} ;
141
141
142
+ // TODO: refactor to extract logic with `dateForCustomRange` from `client/my-sites/stats/stats-date-picker/index.jsx`.
143
+ getFullPeriod = ( ) => {
144
+ const { moment, dateRange, momentSiteZone } = this . props ;
145
+ const localizedStartDate = moment ( dateRange . chartStart ) ;
146
+ const localizedEndDate = moment ( dateRange . chartEnd ) ;
147
+
148
+ // If it's a partial month but ends today.
149
+ if (
150
+ localizedStartDate . isSame ( localizedStartDate . clone ( ) . startOf ( 'month' ) , 'day' ) &&
151
+ localizedEndDate . isSame ( momentSiteZone , 'day' ) &&
152
+ localizedStartDate . isSame ( localizedEndDate , 'month' ) &&
153
+ ( ! dateRange . shortcutId || dateRange . shortcutId === 'month_to_date' )
154
+ ) {
155
+ return 'month' ;
156
+ }
157
+
158
+ // If it's a partial year but ends today.
159
+ if (
160
+ localizedStartDate . isSame ( localizedStartDate . clone ( ) . startOf ( 'year' ) , 'day' ) &&
161
+ localizedEndDate . isSame ( momentSiteZone , 'day' ) &&
162
+ localizedStartDate . isSame ( localizedEndDate , 'year' ) &&
163
+ ( ! dateRange . shortcutId || dateRange . shortcutId === 'year_to_date' )
164
+ ) {
165
+ return 'year' ;
166
+ }
167
+
168
+ // If it's the same day, show single date.
169
+ if ( localizedStartDate . isSame ( localizedEndDate , 'day' ) ) {
170
+ return 'day' ;
171
+ }
172
+
173
+ // If it's a full month.
174
+ if (
175
+ localizedStartDate . isSame ( localizedStartDate . clone ( ) . startOf ( 'month' ) , 'day' ) &&
176
+ localizedEndDate . isSame ( localizedEndDate . clone ( ) . endOf ( 'month' ) , 'day' ) &&
177
+ localizedStartDate . isSame ( localizedEndDate , 'month' )
178
+ ) {
179
+ return 'month' ;
180
+ }
181
+
182
+ // If it's a full year.
183
+ if (
184
+ localizedStartDate . isSame ( localizedStartDate . clone ( ) . startOf ( 'year' ) , 'day' ) &&
185
+ localizedEndDate . isSame ( localizedEndDate . clone ( ) . endOf ( 'year' ) , 'day' ) &&
186
+ localizedStartDate . isSame ( localizedEndDate , 'year' )
187
+ ) {
188
+ return 'year' ;
189
+ }
190
+
191
+ return null ;
192
+ } ;
193
+
142
194
handleArrowNavigation = ( previousOrNext = false ) => {
143
- const { moment, period, slug, dateRange } = this . props ;
195
+ const { moment, momentSiteZone , period, slug, dateRange } = this . props ;
144
196
145
197
const isWPAdmin = config . isEnabled ( 'is_odyssey' ) ;
146
198
const event_from = isWPAdmin ? 'jetpack_odyssey' : 'calypso' ;
@@ -150,16 +202,39 @@ class StatsPeriodNavigation extends PureComponent {
150
202
} ) ;
151
203
152
204
const navigationStart = moment ( dateRange . chartStart ) ;
153
- const navigationEnd = moment ( dateRange . chartEnd ) ;
154
-
155
- if ( previousOrNext ) {
156
- // Navigate to the previous date range.
157
- navigationStart . subtract ( dateRange . daysInRange , 'days' ) ;
158
- navigationEnd . subtract ( dateRange . daysInRange , 'days' ) ;
205
+ let navigationEnd = moment ( dateRange . chartEnd ) ;
206
+
207
+ // If it's a full month then we need to navigate to the previous/next month.
208
+ // If it's a full year then we need to navigate to the previous/next year.
209
+
210
+ const fullPeriod = this . getFullPeriod ( ) ;
211
+ if ( ! fullPeriod ) {
212
+ // Usual flow - only based on the days in range.
213
+ if ( previousOrNext ) {
214
+ // Navigate to the previous date range.
215
+ navigationStart . subtract ( dateRange . daysInRange , 'days' ) ;
216
+ navigationEnd . subtract ( dateRange . daysInRange , 'days' ) ;
217
+ } else {
218
+ // Navigate to the next date range.
219
+ navigationStart . add ( dateRange . daysInRange , 'days' ) ;
220
+ navigationEnd . add ( dateRange . daysInRange , 'days' ) ;
221
+ }
159
222
} else {
160
- // Navigate to the next date range.
161
- navigationStart . add ( dateRange . daysInRange , 'days' ) ;
162
- navigationEnd . add ( dateRange . daysInRange , 'days' ) ;
223
+ // Navigate range by full periods.
224
+ if ( previousOrNext ) {
225
+ // Navigate to the previous period.
226
+ navigationStart . subtract ( 1 , fullPeriod ) ;
227
+ navigationEnd . subtract ( 1 , fullPeriod ) ;
228
+ } else {
229
+ // Navigate to the next period.
230
+ navigationStart . add ( 1 , fullPeriod ) ;
231
+ navigationEnd . add ( 1 , fullPeriod ) ;
232
+ }
233
+ navigationStart . startOf ( fullPeriod ) ;
234
+ navigationEnd . endOf ( fullPeriod ) ;
235
+ if ( navigationEnd . isAfter ( momentSiteZone , 'day' ) ) {
236
+ navigationEnd = momentSiteZone ;
237
+ }
163
238
}
164
239
165
240
const chartStart = navigationStart . format ( 'YYYY-MM-DD' ) ;
@@ -246,7 +321,8 @@ class StatsPeriodNavigation extends PureComponent {
246
321
momentSiteZone ,
247
322
'day'
248
323
) ;
249
- const showArrowsForDateRange = showArrows && dateRange ?. daysInRange <= 31 ;
324
+ // Make sure we only show arrows for date ranges that are less than 3 years for performance reasons.
325
+ const showArrowsForDateRange = showArrows && dateRange ?. daysInRange <= 365 * 3 ;
250
326
251
327
return (
252
328
< div
0 commit comments