Commit 45d94807 authored by Eulyeon Ko's avatar Eulyeon Ko Committed by Olena Horal-Koretska

Add helpful comments to roadmap.scss

Whenever certain variables are modified in roadmap.scss,
the changes need to be reflected in roadmap/constants.js
parent 91b80533
import { s__ } from '~/locale';
/*
Update the counterparts in roadmap.scss when making changes.
*/
// Counterpart: $details-cell-width in roadmap.scss
export const EPIC_DETAILS_CELL_WIDTH = 320;
// Counterpart: $item-height in roadmap.scss
export const EPIC_ITEM_HEIGHT = 50;
// Counterpart: $timeline-cell-width in roadmap.scss
export const TIMELINE_CELL_MIN_WIDTH = 180;
export const SCROLL_BAR_SIZE = 16;
......
......@@ -41,7 +41,7 @@ export default {
* when startDate is out of range.
*/
getTimelineBarStartOffsetForMonths(roadmapItem) {
const daysInMonth = totalDaysInMonth(this.timeframeItem);
const daysInMonth = totalDaysInMonth(roadmapItem.startDate);
const startDate = this.startDateValues.date;
if (
......@@ -62,8 +62,9 @@ export default {
// Calculate proportional offset based on startDate and total days in
// current month.
const leftOffsetPercentage = Math.floor((startDate / daysInMonth) * 100);
/* eslint-disable-next-line @gitlab/require-i18n-strings */
return `left: ${(startDate / daysInMonth) * 100}%;`;
return `left: ${leftOffsetPercentage}%;`;
},
/**
* This method is externally only called when current timeframe cell has timeline
......
@import 'page_bundles/mixins_and_variables_and_functions';
/*
Update ee/app/assets/javascripts/roadmap/constants.js when making changes.
*/
$header-item-height: 60px;
$item-height: 50px;
$details-cell-width: px-to-rem(320px);
......
import Vue from 'vue';
import EpicItemTimelineComponent from 'ee/roadmap/components/epic_item_timeline.vue';
import { PRESET_TYPES } from 'ee/roadmap/constants';
import { getTimeframeForMonthsView } from 'ee/roadmap/utils/roadmap_utils';
import { mockTimeframeInitialDate, mockEpic } from 'ee_jest/roadmap/mock_data';
import mountComponent from 'helpers/vue_mount_component_helper';
import { shallowMount } from '@vue/test-utils';
const mockTimeframeMonths = getTimeframeForMonthsView(mockTimeframeInitialDate);
const createComponent = ({
describe('MonthsPresetMixin', () => {
let wrapper;
const createComponent = ({
presetType = PRESET_TYPES.MONTHS,
timeframe = mockTimeframeMonths,
timeframeItem = mockTimeframeMonths[0],
epic = mockEpic,
}) => {
const Component = Vue.extend(EpicItemTimelineComponent);
return mountComponent(Component, {
} = {}) => {
return shallowMount(EpicItemTimelineComponent, {
propsData: {
presetType,
timeframe,
timeframeItem,
epic,
},
});
};
describe('MonthsPresetMixin', () => {
let vm;
};
afterEach(() => {
vm.$destroy();
wrapper.destroy();
wrapper = null;
});
describe('methods', () => {
describe('hasStartDateForMonth', () => {
it('returns true when Epic.startDate falls within timeframeItem', () => {
vm = createComponent({
wrapper = createComponent({
epic: { ...mockEpic, startDate: mockTimeframeMonths[1] },
timeframeItem: mockTimeframeMonths[1],
});
expect(vm.hasStartDateForMonth()).toBe(true);
expect(wrapper.vm.hasStartDateForMonth()).toBe(true);
});
it('returns false when Epic.startDate does not fall within timeframeItem', () => {
vm = createComponent({
wrapper = createComponent({
epic: { ...mockEpic, startDate: mockTimeframeMonths[0] },
timeframeItem: mockTimeframeMonths[1],
});
expect(vm.hasStartDateForMonth()).toBe(false);
expect(wrapper.vm.hasStartDateForMonth()).toBe(false);
});
});
describe('isTimeframeUnderEndDateForMonth', () => {
const timeframeItem = new Date(2018, 0, 10); // Jan 10, 2018
beforeEach(() => {
vm = createComponent({});
});
it('returns true if provided timeframeItem is under epicEndDate', () => {
const epicEndDate = new Date(2018, 0, 26); // Jan 26, 2018
vm = createComponent({
wrapper = createComponent({
epic: { ...mockEpic, endDate: epicEndDate },
});
expect(vm.isTimeframeUnderEndDateForMonth(timeframeItem)).toBe(true);
expect(wrapper.vm.isTimeframeUnderEndDateForMonth(timeframeItem)).toBe(true);
});
it('returns false if provided timeframeItem is NOT under epicEndDate', () => {
const epicEndDate = new Date(2018, 1, 26); // Feb 26, 2018
vm = createComponent({
wrapper = createComponent({
epic: { ...mockEpic, endDate: epicEndDate },
});
expect(vm.isTimeframeUnderEndDateForMonth(timeframeItem)).toBe(false);
expect(wrapper.vm.isTimeframeUnderEndDateForMonth(timeframeItem)).toBe(false);
});
});
describe('getBarWidthForSingleMonth', () => {
it('returns calculated bar width based on provided cellWidth, daysInMonth and date', () => {
vm = createComponent({});
wrapper = createComponent();
expect(vm.getBarWidthForSingleMonth(300, 30, 1)).toBe(10); // 10% size
expect(vm.getBarWidthForSingleMonth(300, 30, 15)).toBe(150); // 50% size
expect(vm.getBarWidthForSingleMonth(300, 30, 30)).toBe(300); // Full size
expect(wrapper.vm.getBarWidthForSingleMonth(300, 30, 1)).toBe(10); // 10% size
expect(wrapper.vm.getBarWidthForSingleMonth(300, 30, 15)).toBe(150); // 50% size
expect(wrapper.vm.getBarWidthForSingleMonth(300, 30, 30)).toBe(300); // Full size
});
});
describe('getTimelineBarStartOffsetForMonths', () => {
it('returns empty string when Epic startDate is out of range', () => {
vm = createComponent({
wrapper = createComponent({
epic: { ...mockEpic, startDateOutOfRange: true },
});
expect(vm.getTimelineBarStartOffsetForMonths(vm.epic)).toBe('');
expect(wrapper.vm.getTimelineBarStartOffsetForMonths(wrapper.vm.epic)).toBe('');
});
it('returns empty string when Epic startDate is undefined and endDate is out of range', () => {
vm = createComponent({
wrapper = createComponent({
epic: { ...mockEpic, startDateUndefined: true, endDateOutOfRange: true },
});
expect(vm.getTimelineBarStartOffsetForMonths(vm.epic)).toBe('');
expect(wrapper.vm.getTimelineBarStartOffsetForMonths(wrapper.vm.epic)).toBe('');
});
it('return `left: 0;` when Epic startDate is first day of the month', () => {
vm = createComponent({
wrapper = createComponent({
epic: { ...mockEpic, startDate: new Date(2018, 0, 1) },
});
expect(vm.getTimelineBarStartOffsetForMonths(vm.epic)).toBe('left: 0;');
expect(wrapper.vm.getTimelineBarStartOffsetForMonths(wrapper.vm.epic)).toBe('left: 0;');
});
it('returns proportional `left` value based on Epic startDate and days in the month', () => {
vm = createComponent({
epic: { ...mockEpic, startDate: new Date(2018, 0, 15) },
wrapper = createComponent({
epic: { ...mockEpic, startDate: new Date(2018, 0, 15) }, // Jan 15, 2018
});
expect(vm.getTimelineBarStartOffsetForMonths(vm.epic)).toContain('left: 50%');
const startDateValue = 15;
const totalDaysInJanuary = 31;
const expectedLeftOffset = Math.floor((startDateValue / totalDaysInJanuary) * 100); // Approx. 48%
expect(wrapper.vm.getTimelineBarStartOffsetForMonths(wrapper.vm.epic)).toContain(
`left: ${expectedLeftOffset}%`,
);
});
});
describe('getTimelineBarWidthForMonths', () => {
it('returns calculated width value based on Epic.startDate and Epic.endDate', () => {
vm = createComponent({
timeframeItem: mockTimeframeMonths[0],
wrapper = createComponent({
timeframeItem: mockTimeframeMonths[1],
epic: {
...mockEpic,
startDate: new Date(2017, 11, 15), // Dec 15, 2017
endDate: new Date(2018, 1, 15), // Feb 15, 2017
endDate: new Date(2018, 1, 15), // Feb 15, 2018
},
});
expect(Math.floor(vm.getTimelineBarWidthForMonths())).toBe(546);
/*
The epic timeline bar width calculation:
- The width of the bar should account for 31 - 15 = 16 days from December.
- The width of the bar should fully account for all of January (31 days).
- The width of the bar should account for only 15 days
Dec: 16 days / 31 days * 180px ~= 92.9px
+ Jan: 31 days = 180px
+ Feb: 15 days / 28 days * 180px ~= 96.43px
---------------------------------------------------
Total ~= 369px
*/
const expectedTimelineBarWidth = 369; // in px.
expect(Math.floor(wrapper.vm.getTimelineBarWidthForMonths())).toBe(
expectedTimelineBarWidth,
);
});
});
});
......
import Vue from 'vue';
import EpicItemTimelineComponent from 'ee/roadmap/components/epic_item_timeline.vue';
import { PRESET_TYPES } from 'ee/roadmap/constants';
import { getTimeframeForQuartersView } from 'ee/roadmap/utils/roadmap_utils';
import { mockTimeframeInitialDate, mockEpic } from 'ee_jest/roadmap/mock_data';
import mountComponent from 'helpers/vue_mount_component_helper';
import { shallowMount } from '@vue/test-utils';
const mockTimeframeQuarters = getTimeframeForQuartersView(mockTimeframeInitialDate);
const createComponent = ({
describe('QuartersPresetMixin', () => {
let wrapper;
const createComponent = ({
presetType = PRESET_TYPES.QUARTERS,
timeframe = mockTimeframeQuarters,
timeframeItem = mockTimeframeQuarters[0],
epic = mockEpic,
}) => {
const Component = Vue.extend(EpicItemTimelineComponent);
return mountComponent(Component, {
} = {}) => {
return shallowMount(EpicItemTimelineComponent, {
propsData: {
presetType,
timeframe,
timeframeItem,
epic,
},
});
};
describe('QuartersPresetMixin', () => {
let vm;
};
afterEach(() => {
vm.$destroy();
wrapper.destroy();
wrapper = null;
});
describe('methods', () => {
describe('hasStartDateForQuarter', () => {
it('returns true when Epic.startDate falls within timeframeItem', () => {
vm = createComponent({
wrapper = createComponent({
epic: { ...mockEpic, startDate: mockTimeframeQuarters[1].range[0] },
timeframeItem: mockTimeframeQuarters[1],
});
expect(vm.hasStartDateForQuarter()).toBe(true);
expect(wrapper.vm.hasStartDateForQuarter()).toBe(true);
});
it('returns false when Epic.startDate does not fall within timeframeItem', () => {
vm = createComponent({
wrapper = createComponent({
epic: { ...mockEpic, startDate: mockTimeframeQuarters[0].range[0] },
timeframeItem: mockTimeframeQuarters[1],
});
expect(vm.hasStartDateForQuarter()).toBe(false);
expect(wrapper.vm.hasStartDateForQuarter()).toBe(false);
});
});
......@@ -57,77 +56,79 @@ describe('QuartersPresetMixin', () => {
const timeframeItem = mockTimeframeQuarters[1];
beforeEach(() => {
vm = createComponent({});
wrapper = createComponent({});
});
it('returns true if provided timeframeItem is under epicEndDate', () => {
const epicEndDate = mockTimeframeQuarters[1].range[2];
vm = createComponent({
wrapper = createComponent({
epic: { ...mockEpic, endDate: epicEndDate },
});
expect(vm.isTimeframeUnderEndDateForQuarter(timeframeItem)).toBe(true);
expect(wrapper.vm.isTimeframeUnderEndDateForQuarter(timeframeItem)).toBe(true);
});
it('returns false if provided timeframeItem is NOT under epicEndDate', () => {
const epicEndDate = mockTimeframeQuarters[2].range[1];
vm = createComponent({
wrapper = createComponent({
epic: { ...mockEpic, endDate: epicEndDate },
});
expect(vm.isTimeframeUnderEndDateForQuarter(timeframeItem)).toBe(false);
expect(wrapper.vm.isTimeframeUnderEndDateForQuarter(timeframeItem)).toBe(false);
});
});
describe('getBarWidthForSingleQuarter', () => {
it('returns calculated bar width based on provided cellWidth, daysInQuarter and day of quarter', () => {
vm = createComponent({});
wrapper = createComponent();
expect(Math.floor(vm.getBarWidthForSingleQuarter(300, 91, 1))).toBe(3); // 10% size
expect(Math.floor(vm.getBarWidthForSingleQuarter(300, 91, 45))).toBe(148); // 50% size
expect(vm.getBarWidthForSingleQuarter(300, 91, 91)).toBe(300); // Full size
expect(Math.floor(wrapper.vm.getBarWidthForSingleQuarter(300, 91, 1))).toBe(3); // 10% size
expect(Math.floor(wrapper.vm.getBarWidthForSingleQuarter(300, 91, 45))).toBe(148); // 50% size
expect(wrapper.vm.getBarWidthForSingleQuarter(300, 91, 91)).toBe(300); // Full size
});
});
describe('getTimelineBarStartOffsetForQuarters', () => {
it('returns empty string when Epic startDate is out of range', () => {
vm = createComponent({
wrapper = createComponent({
epic: { ...mockEpic, startDateOutOfRange: true },
});
expect(vm.getTimelineBarStartOffsetForQuarters(vm.epic)).toBe('');
expect(wrapper.vm.getTimelineBarStartOffsetForQuarters(wrapper.vm.epic)).toBe('');
});
it('returns empty string when Epic startDate is undefined and endDate is out of range', () => {
vm = createComponent({
wrapper = createComponent({
epic: { ...mockEpic, startDateUndefined: true, endDateOutOfRange: true },
});
expect(vm.getTimelineBarStartOffsetForQuarters(vm.epic)).toBe('');
expect(wrapper.vm.getTimelineBarStartOffsetForQuarters(wrapper.vm.epic)).toBe('');
});
it('return `left: 0;` when Epic startDate is first day of the quarter', () => {
vm = createComponent({
wrapper = createComponent({
epic: { ...mockEpic, startDate: mockTimeframeQuarters[0].range[0] },
});
expect(vm.getTimelineBarStartOffsetForQuarters(vm.epic)).toBe('left: 0;');
expect(wrapper.vm.getTimelineBarStartOffsetForQuarters(wrapper.vm.epic)).toBe('left: 0;');
});
it('returns proportional `left` value based on Epic startDate and days in the quarter', () => {
vm = createComponent({
wrapper = createComponent({
epic: { ...mockEpic, startDate: mockTimeframeQuarters[0].range[1] },
});
expect(vm.getTimelineBarStartOffsetForQuarters(vm.epic)).toContain('left: 34');
expect(wrapper.vm.getTimelineBarStartOffsetForQuarters(wrapper.vm.epic)).toContain(
'left: 34',
);
});
});
describe('getTimelineBarWidthForQuarters', () => {
it('returns calculated width value based on Epic.startDate and Epic.endDate', () => {
vm = createComponent({
wrapper = createComponent({
timeframeItem: mockTimeframeQuarters[0],
epic: {
...mockEpic,
......@@ -136,7 +137,7 @@ describe('QuartersPresetMixin', () => {
},
});
expect(Math.floor(vm.getTimelineBarWidthForQuarters(vm.epic))).toBe(180);
expect(Math.floor(wrapper.vm.getTimelineBarWidthForQuarters(wrapper.vm.epic))).toBe(180);
});
});
});
......
import Vue from 'vue';
import EpicItemTimelineComponent from 'ee/roadmap/components/epic_item_timeline.vue';
import { PRESET_TYPES } from 'ee/roadmap/constants';
import { getTimeframeForWeeksView } from 'ee/roadmap/utils/roadmap_utils';
import { mockTimeframeInitialDate, mockEpic } from 'ee_jest/roadmap/mock_data';
import mountComponent from 'helpers/vue_mount_component_helper';
import { shallowMount } from '@vue/test-utils';
const mockTimeframeWeeks = getTimeframeForWeeksView(mockTimeframeInitialDate);
const createComponent = ({
describe('WeeksPresetMixin', () => {
let wrapper;
const createComponent = ({
presetType = PRESET_TYPES.WEEKS,
timeframe = mockTimeframeWeeks,
timeframeItem = mockTimeframeWeeks[0],
epic = mockEpic,
}) => {
const Component = Vue.extend(EpicItemTimelineComponent);
return mountComponent(Component, {
} = {}) => {
return shallowMount(EpicItemTimelineComponent, {
propsData: {
presetType,
timeframe,
timeframeItem,
epic,
},
});
};
describe('WeeksPresetMixin', () => {
let vm;
};
afterEach(() => {
vm.$destroy();
wrapper.destroy();
wrapper = null;
});
describe('methods', () => {
describe('hasStartDateForWeek', () => {
it('returns true when Epic.startDate falls within timeframeItem', () => {
vm = createComponent({
wrapper = createComponent({
epic: { ...mockEpic, startDate: mockTimeframeWeeks[1] },
timeframeItem: mockTimeframeWeeks[1],
});
expect(vm.hasStartDateForWeek()).toBe(true);
expect(wrapper.vm.hasStartDateForWeek()).toBe(true);
});
it('returns false when Epic.startDate does not fall within timeframeItem', () => {
vm = createComponent({
wrapper = createComponent({
epic: { ...mockEpic, startDate: mockTimeframeWeeks[0] },
timeframeItem: mockTimeframeWeeks[1],
});
expect(vm.hasStartDateForWeek()).toBe(false);
expect(wrapper.vm.hasStartDateForWeek()).toBe(false);
});
});
describe('getLastDayOfWeek', () => {
it('returns date object set to last day of the week from provided timeframeItem', () => {
vm = createComponent({});
const lastDayOfWeek = vm.getLastDayOfWeek(mockTimeframeWeeks[0]);
wrapper = createComponent();
const lastDayOfWeek = wrapper.vm.getLastDayOfWeek(mockTimeframeWeeks[0]);
expect(lastDayOfWeek.getDate()).toBe(23);
expect(lastDayOfWeek.getMonth()).toBe(11);
......@@ -68,78 +67,107 @@ describe('WeeksPresetMixin', () => {
const timeframeItem = new Date(2018, 0, 7); // Jan 7, 2018
beforeEach(() => {
vm = createComponent({});
wrapper = createComponent();
});
it('returns true if provided timeframeItem is under epicEndDate', () => {
const epicEndDate = new Date(2018, 0, 3); // Jan 3, 2018
vm = createComponent({
/*
Visual illustration of the example spec:
- Each item in mockTimeframeWeeks represents a week.
For example, the item 2017-12-17 represents -
the timeframe representing the week starting on Dec 17, 2017
mockTimeframeWeeks =
[
2017-12-17, <- the epic starting on Jan 3, 2018 is in this timeframe
2017-12-24,
2017-12-31, <- the epic ending on Jan 15, 2018 is in this timeframe.
2018-01-07, <- the provided timeframeItem (Jan 7, 2018) points to this timeframe.
...
]
*/
wrapper = createComponent({
epic: { ...mockEpic, endDate: epicEndDate },
});
expect(vm.isTimeframeUnderEndDateForWeek(timeframeItem)).toBe(true);
expect(wrapper.vm.isTimeframeUnderEndDateForWeek(timeframeItem)).toBe(true);
});
it('returns false if provided timeframeItem is NOT under epicEndDate', () => {
const epicEndDate = new Date(2018, 0, 15); // Jan 15, 2018
vm = createComponent({
/*
Visual illustration of the example spec:
mockTimeframeWeeks =
[
2017-12-17, <- the epic starting on Jan 3, 2018 is in this timeframe
2017-12-24,
2017-12-31,
2018-01-07, <- the provided timeframeItem (Jan 7, 2018) points to this timeframe.
2018-01-14, <- the epic ending on Jan 15, 2018 is in this timeframe.
...
]
*/
wrapper = createComponent({
epic: { ...mockEpic, endDate: epicEndDate },
});
expect(vm.isTimeframeUnderEndDateForWeek(timeframeItem)).toBe(false);
expect(wrapper.vm.isTimeframeUnderEndDateForWeek(timeframeItem)).toBe(false);
});
});
describe('getBarWidthForSingleWeek', () => {
it('returns calculated bar width based on provided cellWidth and day of week', () => {
vm = createComponent({});
wrapper = createComponent();
expect(Math.floor(vm.getBarWidthForSingleWeek(300, 1))).toBe(42); // 10% size
expect(Math.floor(vm.getBarWidthForSingleWeek(300, 3))).toBe(128); // 50% size
expect(vm.getBarWidthForSingleWeek(300, 7)).toBe(300); // Full size
expect(Math.floor(wrapper.vm.getBarWidthForSingleWeek(300, 1))).toBe(42); // 10% size
expect(Math.floor(wrapper.vm.getBarWidthForSingleWeek(300, 3))).toBe(128); // 50% size
expect(wrapper.vm.getBarWidthForSingleWeek(300, 7)).toBe(300); // Full size
});
});
describe('getTimelineBarStartOffsetForWeeks', () => {
it('returns empty string when Epic startDate is out of range', () => {
vm = createComponent({
wrapper = createComponent({
epic: { ...mockEpic, startDateOutOfRange: true },
});
expect(vm.getTimelineBarStartOffsetForWeeks(vm.epic)).toBe('');
expect(wrapper.vm.getTimelineBarStartOffsetForWeeks(wrapper.vm.epic)).toBe('');
});
it('returns empty string when Epic startDate is undefined and endDate is out of range', () => {
vm = createComponent({
wrapper = createComponent({
epic: { ...mockEpic, startDateUndefined: true, endDateOutOfRange: true },
});
expect(vm.getTimelineBarStartOffsetForWeeks(vm.epic)).toBe('');
expect(wrapper.vm.getTimelineBarStartOffsetForWeeks(wrapper.vm.epic)).toBe('');
});
it('return `left: 0;` when Epic startDate is first day of the week', () => {
vm = createComponent({
wrapper = createComponent({
epic: { ...mockEpic, startDate: mockTimeframeWeeks[0] },
});
expect(vm.getTimelineBarStartOffsetForWeeks(vm.epic)).toBe('left: 0;');
expect(wrapper.vm.getTimelineBarStartOffsetForWeeks(wrapper.vm.epic)).toBe('left: 0;');
});
it('returns proportional `left` value based on Epic startDate and days in the week', () => {
vm = createComponent({
wrapper = createComponent({
epic: { ...mockEpic, startDate: new Date(2018, 0, 15) },
});
expect(vm.getTimelineBarStartOffsetForWeeks(vm.epic)).toContain('left: 38');
expect(wrapper.vm.getTimelineBarStartOffsetForWeeks(wrapper.vm.epic)).toContain('left: 38');
});
});
describe('getTimelineBarWidthForWeeks', () => {
it('returns calculated width value based on Epic.startDate and Epic.endDate', () => {
vm = createComponent({
timeframeItem: mockTimeframeWeeks[0],
wrapper = createComponent({
timeframeItem: mockTimeframeWeeks[2],
epic: {
...mockEpic,
startDate: new Date(2018, 0, 1), // Jan 1, 2018
......@@ -147,7 +175,29 @@ describe('WeeksPresetMixin', () => {
},
});
expect(Math.floor(vm.getTimelineBarWidthForWeeks())).toBe(1208);
/*
Visual illustration of the example spec:
- Each timeframe is 180px wide.
- The timebar width should be approximately 540px + 154.3px + 154.3px or 849px.
- In the below, [2017-12-31] is understood as a timeframe that covers -
the week starting on Dec 31, 2017 (ending on Jan 6, 2018).
mockTimeframeWeeks =
Epic start date Epic end date
Jan 1, 2018 Feb 2, 2018
. .
. .
[ [2017-12-31][2018-01-07][2018-01-14][2018-01-21][2018-01-28] ]
<--------------- timeline bar width ---------------->
<-- --><---- 180px * 3 frames = 540px ----><-- -->
^ ^
approximately 154px ^
~ approximately 154px
*/
const expectedTimelineBarWidth = 848; // in px;
expect(Math.floor(wrapper.vm.getTimelineBarWidthForWeeks())).toBe(expectedTimelineBarWidth);
});
});
});
......
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