Commit e0fe0013 authored by Kushal Pandya's avatar Kushal Pandya

Roadmap Utils

parent 2447bcae
import { getTimeframeWindowFrom, totalDaysInMonth } from '~/lib/utils/datetime_utility';
import { PRESET_TYPES, PRESET_DEFAULTS } from '../constants';
/**
* This method returns array of Objects representing Quarters based on provided initialDate
*
* For eg; If initialDate is 15th Jan 2018
* Then as per Roadmap specs, we need to show
* 1 quarter before current quarter AND
* 4 quarters after current quarter
* thus, total of 6 quarters.
*
* So returned array from this method will be;
* [
* {
* quarterSequence: 4,
* year: 2017,
* range: [
* 1 Oct 2017,
* 1 Nov 2017,
* 31 Dec 2017,
* ],
* },
* {
* quarterSequence: 1,
* year: 2018,
* range: [
* 1 Jan 2018,
* 1 Feb 2018,
* 31 Mar 2018,
* ],
* },
* ....
* ....
* ....
* {
* quarterSequence: 1,
* year: 2019,
* range: [
* 1 Jan 2019,
* 1 Feb 2019,
* 31 Mar 2019,
* ],
* },
* ]
*
* @param {Date} initialDate
*/
export const getTimeframeForQuartersView = (initialDate = new Date()) => {
const startDate = initialDate;
startDate.setHours(0, 0, 0, 0);
const monthsForQuarters = {
1: [0, 1, 2],
2: [3, 4, 5],
3: [6, 7, 8],
4: [9, 10, 11],
};
// Get current quarter for current month
const currentQuarter = Math.floor((startDate.getMonth() + 3) / 3);
// Get index of current month in current quarter
// It could be 0, 1, 2 (i.e. first, second or third)
const currentMonthInCurrentQuarter = monthsForQuarters[currentQuarter].indexOf(
startDate.getMonth(),
);
// To move start back to first month of previous quarter
// Adding quarter size (3) to month order will give us
// exact number of months we need to go back in time
const startMonth = currentMonthInCurrentQuarter + 3;
const quartersTimeframe = [];
// Move startDate to first month of previous quarter
startDate.setMonth(startDate.getMonth() - startMonth);
// Get timeframe for the length we determined for this preset
// start from the startDate
const timeframe = getTimeframeWindowFrom(startDate, PRESET_DEFAULTS.QUARTERS.TIMEFRAME_LENGTH);
// Iterate over the timeframe and break it down
// in chunks of quarters
for (let i = 0; i < timeframe.length; i += 3) {
const range = timeframe.slice(i, i + 3);
const lastMonthOfQuarter = range[range.length - 1];
const quarterSequence = Math.floor((range[0].getMonth() + 3) / 3);
const year = range[0].getFullYear();
// Ensure that `range` spans across duration of
// entire quarter
lastMonthOfQuarter.setDate(totalDaysInMonth(lastMonthOfQuarter));
quartersTimeframe.push({
quarterSequence,
range,
year,
});
}
return quartersTimeframe;
};
/**
* This method returns array of Dates respresenting Months based on provided initialDate
*
* For eg; If initialDate is 15th Jan 2018
* Then as per Roadmap specs, we need to show
* 1 month before current month AND
* 5 months after current month
* thus, total of 7 months.
*
* So returned array from this method will be;
* [
* 1 Dec 2017, 1 Jan 2018, 1 Feb 2018, 1 Mar 2018,
* 1 Apr 2018, 1 May 2018, 30 Jun 2018
* ]
*
* @param {Date} initialDate
*/
export const getTimeframeForMonthsView = (initialDate = new Date()) => {
const startDate = initialDate;
startDate.setHours(0, 0, 0, 0);
// Move startDate to a month prior to current month
startDate.setMonth(startDate.getMonth() - 1);
return getTimeframeWindowFrom(startDate, PRESET_DEFAULTS.MONTHS.TIMEFRAME_LENGTH);
};
/**
* This method returns array of Dates respresenting Months based on provided initialDate
*
* For eg; If initialDate is 15th Jan 2018
* Then as per Roadmap specs, we need to show
* 1 week before current week AND
* 4 weeks after current week
* thus, total of 6 weeks.
* Note that week starts on Sunday
*
* So returned array from this method will be;
* [
* 7 Jan 2018, 14 Jan 2018, 21 Jan 2018,
* 28 Jan 2018, 4 Mar 2018, 11 Mar 2018
* ]
*
* @param {Date} initialDate
*/
export const getTimeframeForWeeksView = (initialDate = new Date()) => {
const startDate = initialDate;
startDate.setHours(0, 0, 0, 0);
const dayOfWeek = startDate.getDay();
const daysToFirstDayOfPrevWeek = dayOfWeek + 7;
const timeframe = [];
// Move startDate to first day (Sunday) of previous week
startDate.setDate(startDate.getDate() - daysToFirstDayOfPrevWeek);
// Iterate for the length of this preset
for (let i = 0; i < PRESET_DEFAULTS.WEEKS.TIMEFRAME_LENGTH; i += 1) {
// Push date to timeframe only when day is
// first day (Sunday) of the week1
if (startDate.getDay() === 0) {
timeframe.push(new Date(startDate.getTime()));
}
// Move date one day further
startDate.setDate(startDate.getDate() + 1);
}
return timeframe;
};
export const getTimeframeForPreset = (presetType = PRESET_TYPES.MONTHS) => {
if (presetType === PRESET_TYPES.QUARTERS) {
return getTimeframeForQuartersView();
} else if (presetType === PRESET_TYPES.MONTHS) {
return getTimeframeForMonthsView();
}
return getTimeframeForWeeksView();
};
export const getEpicsPathForPreset = ({
basePath = '',
filterQueryString = '',
presetType = '',
timeframe = [],
}) => {
let start;
let end;
let epicsPath = basePath;
if (!basePath || !timeframe.length) {
return null;
}
// Construct Epic API path to include
// `start_date` & `end_date` query params to get list of
// epics only for timeframe.
if (presetType === PRESET_TYPES.QUARTERS) {
const firstTimeframe = timeframe[0];
const lastTimeframe = timeframe[timeframe.length - 1];
start = firstTimeframe.range[0];
end = lastTimeframe.range[lastTimeframe.range.length - 1];
} else if (presetType === PRESET_TYPES.MONTHS) {
start = timeframe[0];
end = timeframe[timeframe.length - 1];
} else if (presetType === PRESET_TYPES.WEEKS) {
start = timeframe[0];
end = new Date(timeframe[timeframe.length - 1].getTime());
end.setDate(end.getDate() + 6);
}
const startDate = `${start.getFullYear()}-${start.getMonth() + 1}-${start.getDate()}`;
const endDate = `${end.getFullYear()}-${end.getMonth() + 1}-${end.getDate()}`;
epicsPath += `?start_date=${startDate}&end_date=${endDate}`;
if (filterQueryString) {
epicsPath += `&${filterQueryString}`;
}
return epicsPath;
};
import {
getTimeframeForQuartersView,
getTimeframeForMonthsView,
getTimeframeForWeeksView,
getEpicsPathForPreset,
} from 'ee/roadmap/utils/roadmap_utils';
import { PRESET_TYPES } from 'ee//roadmap/constants';
describe('getTimeframeForQuartersView', () => {
let timeframe;
beforeEach(() => {
timeframe = getTimeframeForQuartersView(new Date(2018, 0, 1));
});
it('returns timeframe with total of 6 quarters', () => {
expect(timeframe.length).toBe(6);
});
it('each timeframe item has `quarterSequence`, `year` and `range` present', () => {
const timeframeItem = timeframe[0];
expect(timeframeItem.quarterSequence).toEqual(jasmine.any(Number));
expect(timeframeItem.year).toEqual(jasmine.any(Number));
expect(Array.isArray(timeframeItem.range)).toBe(true);
});
it('first timeframe item refers to quarter prior to current quarter', () => {
const timeframeItem = timeframe[0];
const expectedQuarter = {
0: { month: 9, date: 1 }, // 1 Oct 2017
1: { month: 10, date: 1 }, // 1 Nov 2017
2: { month: 11, date: 31 }, // 31 Dec 2017
};
expect(timeframeItem.quarterSequence).toEqual(4);
expect(timeframeItem.year).toEqual(2017);
timeframeItem.range.forEach((month, index) => {
expect(month.getFullYear()).toBe(2017);
expect(expectedQuarter[index].month).toBe(month.getMonth());
expect(expectedQuarter[index].date).toBe(month.getDate());
});
});
it('last timeframe item refers to 5th quarter from current quarter', () => {
const timeframeItem = timeframe[timeframe.length - 1];
const expectedQuarter = {
0: { month: 0, date: 1 }, // 1 Jan 2019
1: { month: 1, date: 1 }, // 1 Feb 2019
2: { month: 2, date: 31 }, // 31 Mar 2019
};
expect(timeframeItem.quarterSequence).toEqual(1);
expect(timeframeItem.year).toEqual(2019);
timeframeItem.range.forEach((month, index) => {
expect(month.getFullYear()).toBe(2019);
expect(expectedQuarter[index].month).toBe(month.getMonth());
expect(expectedQuarter[index].date).toBe(month.getDate());
});
});
});
describe('getTimeframeForMonthsView', () => {
let timeframe;
beforeEach(() => {
timeframe = getTimeframeForMonthsView(new Date(2018, 0, 1));
});
it('returns timeframe with total of 7 months', () => {
expect(timeframe.length).toBe(7);
});
it('first timeframe item refers to month prior to current month', () => {
const timeframeItem = timeframe[0];
const expectedMonth = {
year: 2017,
month: 11,
date: 1,
};
expect(timeframeItem.getFullYear()).toBe(expectedMonth.year);
expect(timeframeItem.getMonth()).toBe(expectedMonth.month);
expect(timeframeItem.getDate()).toBe(expectedMonth.date);
});
it('last timeframe item refers to 6th month from current month', () => {
const timeframeItem = timeframe[timeframe.length - 1];
const expectedMonth = {
year: 2018,
month: 5,
date: 30,
};
expect(timeframeItem.getFullYear()).toBe(expectedMonth.year);
expect(timeframeItem.getMonth()).toBe(expectedMonth.month);
expect(timeframeItem.getDate()).toBe(expectedMonth.date);
});
});
describe('getTimeframeForWeeksView', () => {
let timeframe;
beforeEach(() => {
timeframe = getTimeframeForWeeksView(new Date(2018, 0, 1));
});
it('returns timeframe with total of 6 weeks', () => {
expect(timeframe.length).toBe(6);
});
it('first timeframe item refers to week prior to current week', () => {
const timeframeItem = timeframe[0];
const expectedMonth = {
year: 2017,
month: 11,
date: 24,
};
expect(timeframeItem.getFullYear()).toBe(expectedMonth.year);
expect(timeframeItem.getMonth()).toBe(expectedMonth.month);
expect(timeframeItem.getDate()).toBe(expectedMonth.date);
});
it('last timeframe item refers to 5th week from current month', () => {
const timeframeItem = timeframe[timeframe.length - 1];
const expectedMonth = {
year: 2018,
month: 0,
date: 28,
};
expect(timeframeItem.getFullYear()).toBe(expectedMonth.year);
expect(timeframeItem.getMonth()).toBe(expectedMonth.month);
expect(timeframeItem.getDate()).toBe(expectedMonth.date);
});
});
describe('getEpicsPathForPreset', () => {
const basePath = '/groups/gitlab-org/-/epics.json';
const filterQueryString = 'scope=all&utf8=✓&state=opened&label_name[]=Bug';
it('returns epics path string based on provided basePath and timeframe for Quarters', () => {
const timeframeQuarters = getTimeframeForQuartersView(new Date(2018, 0, 1));
const epicsPath = getEpicsPathForPreset({
basePath,
timeframe: timeframeQuarters,
presetType: PRESET_TYPES.QUARTERS,
});
expect(epicsPath).toBe(`${basePath}?start_date=2017-10-1&end_date=2019-3-31`);
});
it('returns epics path string based on provided basePath and timeframe for Months', () => {
const timeframeMonths = getTimeframeForMonthsView(new Date(2018, 0, 1));
const epicsPath = getEpicsPathForPreset({
basePath,
timeframe: timeframeMonths,
presetType: PRESET_TYPES.MONTHS,
});
expect(epicsPath).toBe(`${basePath}?start_date=2017-12-1&end_date=2018-6-30`);
});
it('returns epics path string based on provided basePath and timeframe for Weeks', () => {
const timeframeWeeks = getTimeframeForWeeksView(new Date(2018, 0, 1));
const epicsPath = getEpicsPathForPreset({
basePath,
timeframe: timeframeWeeks,
presetType: PRESET_TYPES.WEEKS,
});
expect(epicsPath).toBe(`${basePath}?start_date=2017-12-24&end_date=2018-2-3`);
});
it('returns epics path string while preserving filterQueryString', () => {
const timeframeMonths = getTimeframeForMonthsView(new Date(2018, 0, 1));
const epicsPath = getEpicsPathForPreset({
basePath,
filterQueryString,
timeframe: timeframeMonths,
presetType: PRESET_TYPES.MONTHS,
});
expect(epicsPath).toBe(
`${basePath}?start_date=2017-12-1&end_date=2018-6-30&scope=all&utf8=✓&state=opened&label_name[]=Bug`,
);
});
});
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