Commit 2979ac2e authored by Phil Hughes's avatar Phil Hughes

Merge branch 'mw-productivity-analytics-min-date-fix' into 'master'

Add getDefaultStartDate utility method

See merge request gitlab-org/gitlab!20040
parents c0864a0f 73ffa846
import Vue from 'vue'; import Vue from 'vue';
import { mapState, mapActions } from 'vuex'; import { mapState, mapActions } from 'vuex';
import { getDateInPast } from '~/lib/utils/datetime_utility';
import { defaultDaysInPast } from './constants'; import { defaultDaysInPast } from './constants';
import store from './store'; import store from './store';
import FilterDropdowns from './components/filter_dropdowns.vue'; import FilterDropdowns from './components/filter_dropdowns.vue';
import DateRange from '../shared/components/daterange.vue'; import DateRange from '../shared/components/daterange.vue';
import ProductivityAnalyticsApp from './components/app.vue'; import ProductivityAnalyticsApp from './components/app.vue';
import FilteredSearchProductivityAnalytics from './filtered_search_productivity_analytics'; import FilteredSearchProductivityAnalytics from './filtered_search_productivity_analytics';
import { getLabelsEndpoint, getMilestonesEndpoint } from './utils'; import { getLabelsEndpoint, getMilestonesEndpoint, getDefaultStartDate } from './utils';
export default () => { export default () => {
const container = document.getElementById('js-productivity-analytics'); const container = document.getElementById('js-productivity-analytics');
...@@ -20,11 +19,11 @@ export default () => { ...@@ -20,11 +19,11 @@ export default () => {
const appContainer = container.querySelector('.js-productivity-analytics-app-container'); const appContainer = container.querySelector('.js-productivity-analytics-app-container');
const { endpoint, emptyStateSvgPath, noAccessSvgPath } = appContainer.dataset; const { endpoint, emptyStateSvgPath, noAccessSvgPath } = appContainer.dataset;
const { startDate: minDate } = timeframeContainer.dataset; const { startDate: computedStartDate } = timeframeContainer.dataset;
const now = new Date(Date.now()); const minDate = computedStartDate ? new Date(computedStartDate) : null;
const defaultStartDate = getDateInPast(now, defaultDaysInPast); const defaultStartDate = getDefaultStartDate(minDate, defaultDaysInPast);
const defaultEndDate = now; const defaultEndDate = new Date(Date.now());
let filterManager; let filterManager;
...@@ -98,7 +97,7 @@ export default () => { ...@@ -98,7 +97,7 @@ export default () => {
show: this.groupNamespace !== null, show: this.groupNamespace !== null,
startDate: defaultStartDate, startDate: defaultStartDate,
endDate: defaultEndDate, endDate: defaultEndDate,
minDate: minDate ? new Date(minDate) : null, minDate,
}, },
on: { on: {
change: this.onDateRangeChange, change: this.onDateRangeChange,
......
...@@ -32,6 +32,24 @@ export const getMilestonesEndpoint = (namespacePath, projectPathWithNamespace) = ...@@ -32,6 +32,24 @@ export const getMilestonesEndpoint = (namespacePath, projectPathWithNamespace) =
return `/groups/${namespacePath}/-/milestones`; return `/groups/${namespacePath}/-/milestones`;
}; };
/**
* Determines the default min date for the productivity analytics date picker
* by taking the minDate (provided by the BE) into account.
* @param {Date} minDate - The min start date provided by the backend.
* @param {Number} defaultDaysInPast - The number of days in the past (used for computing the start date).
* @returns {Date} - The computed default start date.
*/
export const getDefaultStartDate = (minDate, defaultDaysInPast) => {
const now = new Date(Date.now());
const dateInPast = getDateInPast(now, defaultDaysInPast);
if (!minDate) {
return dateInPast;
}
return minDate > dateInPast ? minDate : dateInPast;
};
/** /**
* Computes the day difference 'days' between a given start and end date * Computes the day difference 'days' between a given start and end date
* and creates an array of length 'days'. * and creates an array of length 'days'.
...@@ -64,9 +82,9 @@ export const initDateArray = (startDate, endDate) => { ...@@ -64,9 +82,9 @@ export const initDateArray = (startDate, endDate) => {
* [{ merged_at: '2019-09-03T21:29:49.351Z', metric: 24 }, ... ] // 2019-09-03 * [{ merged_at: '2019-09-03T21:29:49.351Z', metric: 24 }, ... ] // 2019-09-03
* ] * ]
* *
* @param {*} data - The raw data received from the API. * @param {Object} data - The raw data received from the API.
* @param {*} startDate - The start date selected by the user minus an additional offset in days (e.g., 30 days). * @param {Date} startDate - The start date selected by the user minus an additional offset in days (e.g., 30 days).
* @param {*} endDate - The end date selected by the user. * @param {Date} endDate - The end date selected by the user.
* @returns {Array} The transformed data array (first item corresponds to start date, last item to end date) * @returns {Array} The transformed data array (first item corresponds to start date, last item to end date)
*/ */
export const transformScatterData = (data, startDate, endDate) => { export const transformScatterData = (data, startDate, endDate) => {
...@@ -108,9 +126,9 @@ export const transformScatterData = (data, startDate, endDate) => { ...@@ -108,9 +126,9 @@ export const transformScatterData = (data, startDate, endDate) => {
* i[1] = metric, displayed on y axis * i[1] = metric, displayed on y axis
* i[2] = datetime, used in the tooltip * i[2] = datetime, used in the tooltip
* *
* @param {*} data - The already transformed scatterplot data (which is computed by transformScatterData) * @param {Array} data - The already transformed scatterplot data (which is computed by transformScatterData)
* @param {*} startDate - The start date selected by the user * @param {Date} startDate - The start date selected by the user
* @param {*} endDate - The end date selected by the user * @param {Date} endDate - The end date selected by the user
* @returns {Array} An array with each item being another arry of two items (date, computed median) * @returns {Array} An array with each item being another arry of two items (date, computed median)
*/ */
export const getScatterPlotData = (data, startDate, endDate) => { export const getScatterPlotData = (data, startDate, endDate) => {
...@@ -139,9 +157,9 @@ export const getScatterPlotData = (data, startDate, endDate) => { ...@@ -139,9 +157,9 @@ export const getScatterPlotData = (data, startDate, endDate) => {
* Example: Rolling median for m days: * Example: Rolling median for m days:
* Calculate median for day i: median[i - m + 1 ... i] * Calculate median for day i: median[i - m + 1 ... i]
* *
* @param {*} data - The already transformed scatterplot data (which is computed by transformScatterData) * @param {Array} data - The already transformed scatterplot data (which is computed by transformScatterData)
* @param {*} startDate - The start date selected by the user * @param {Date} startDate - The start date selected by the user
* @param {*} endDate - The end date selected by the user * @param {Date} endDate - The end date selected by the user
* @param {Number} daysOffset The number of days that to look up data in the past (e.g. 30 days in the past for 30 day rolling median) * @param {Number} daysOffset The number of days that to look up data in the past (e.g. 30 days in the past for 30 day rolling median)
* @returns {Array} An array with each item being another arry of two items (date, computed median) * @returns {Array} An array with each item being another arry of two items (date, computed median)
*/ */
......
import { import {
getLabelsEndpoint, getLabelsEndpoint,
getMilestonesEndpoint, getMilestonesEndpoint,
getDefaultStartDate,
initDateArray, initDateArray,
transformScatterData, transformScatterData,
getScatterPlotData, getScatterPlotData,
...@@ -35,6 +36,32 @@ describe('Productivity Analytics utils', () => { ...@@ -35,6 +36,32 @@ describe('Productivity Analytics utils', () => {
}); });
}); });
describe('getDefaultStartDate', () => {
const realDateNow = Date.now;
const defaultDaysInPast = 10;
beforeAll(() => {
const today = jest.fn(() => new Date('2019-10-01'));
global.Date.now = today;
});
afterAll(() => {
global.Date.now = realDateNow;
});
it('returns the minDate when the computed date (today minus defaultDaysInPast) is before the minDate', () => {
const minDate = new Date('2019-09-30');
expect(getDefaultStartDate(minDate, defaultDaysInPast)).toEqual(minDate);
});
it('returns the computed date (today minus defaultDaysInPast) when this is after the minDate', () => {
const minDate = new Date('2019-09-01');
expect(getDefaultStartDate(minDate, defaultDaysInPast)).toEqual(new Date('2019-09-21'));
});
});
describe('initDateArray', () => { describe('initDateArray', () => {
it('creates a two-dimensional array with 3 empty arrays for startDate=2019-09-01 and endDate=2019-09-03', () => { it('creates a two-dimensional array with 3 empty arrays for startDate=2019-09-01 and endDate=2019-09-03', () => {
const startDate = new Date('2019-09-01'); const startDate = new Date('2019-09-01');
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment