Commit 41ebeaa7 authored by David O'Regan's avatar David O'Regan

Merge branch '322938-weekly-start-date-grid' into 'master'

Feat: Update schedule grid to start at beginning of current week

See merge request gitlab-org/gitlab!57004
parents 386687c9 eb571eb2
......@@ -3,6 +3,7 @@ import { GlCard, GlButtonGroup, GlButton, GlModalDirective, GlTooltipDirective }
import * as Sentry from '@sentry/browser';
import { capitalize } from 'lodash';
import {
getStartOfWeek,
formatDate,
nWeeksBefore,
nWeeksAfter,
......@@ -87,7 +88,7 @@ export default {
data() {
return {
presetType: this.$options.PRESET_TYPES.WEEKS,
timeframeStartDate: new Date(),
timeframeStartDate: getStartOfWeek(new Date()),
rotations: this.schedule.rotations.nodes,
rotationToUpdate: {},
};
......@@ -133,7 +134,8 @@ export default {
methods: {
switchPresetType(type) {
this.presetType = type;
this.timeframeStartDate = new Date();
this.timeframeStartDate =
type === PRESET_TYPES.WEEKS ? getStartOfWeek(new Date()) : new Date();
},
formatPresetType(type) {
return capitalize(type);
......
......@@ -32,7 +32,7 @@ export default {
<template>
<span
v-if="isVisible"
:style="getIndicatorStyles(presetType)"
:style="getIndicatorStyles(presetType, timeframeItem)"
data-testid="current-day-indicator"
class="current-day-indicator"
></span>
......
......@@ -48,7 +48,7 @@ export default {
currentDateTime >= this.timeframeItem.getTime() &&
currentDateTime <= lastDayOfCurrentWeekTime
) {
return 'label-dark label-bold';
return 'label-bold';
}
return '';
......@@ -66,7 +66,7 @@ export default {
<span class="timeline-header-item" :style="timelineHeaderStyles">
<div
:class="timelineHeaderClass"
class="item-label gl-pl-6 gl-py-4"
class="item-label label-dark gl-pl-5 gl-py-4"
data-testid="timeline-header-label"
>
{{ timelineHeaderLabel }}
......
......@@ -78,7 +78,7 @@ export default {
>
<span
v-if="hasToday"
:style="getIndicatorStyles($options.PRESET_TYPES.WEEKS)"
:style="getIndicatorStyles($options.PRESET_TYPES.WEEKS, timeframeItem)"
class="current-day-indicator-header preset-weeks"
></span>
</div>
......
......@@ -44,3 +44,7 @@ export const ASSIGNEE_SPACER_SMALL = 1;
export const TIMELINE_CELL_WIDTH = 180;
export const SHIFT_WIDTH_CALCULATION_DELAY = 250;
export const CURRENT_DAY_INDICATOR_OFFSET = 2.25;
export const oneHourOffsetDayView = 100 / HOURS_IN_DAY;
export const oneDayOffsetWeekView = 100 / DAYS_IN_WEEK;
export const oneHourOffsetWeekView = oneDayOffsetWeekView / HOURS_IN_DAY;
import { isToday } from '~/lib/utils/datetime_utility';
import { getDayDifference, isToday } from '~/lib/utils/datetime_utility';
import {
DAYS_IN_WEEK,
HOURS_IN_DAY,
PRESET_TYPES,
CURRENT_DAY_INDICATOR_OFFSET,
oneHourOffsetDayView,
oneDayOffsetWeekView,
oneHourOffsetWeekView,
} from '../constants';
export default {
......@@ -38,23 +38,30 @@ export default {
this.$options.currentDate = currentDate;
},
methods: {
getIndicatorStyles(presetType = PRESET_TYPES.WEEKS) {
const currentDate = new Date();
const base = 100 / HOURS_IN_DAY;
const hours = base * currentDate.getHours();
getIndicatorStyles(presetType = PRESET_TYPES.WEEKS, timeframeStartDate = new Date()) {
if (presetType === PRESET_TYPES.DAYS) {
const minutes = base * (currentDate.getMinutes() / 60) - CURRENT_DAY_INDICATOR_OFFSET;
return {
left: `${hours + minutes}%`,
};
return this.getDayViewIndicatorStyles();
}
const weeklyDayOffset = 100 / DAYS_IN_WEEK / 2;
const weeklyHourOffset = (weeklyDayOffset / HOURS_IN_DAY) * currentDate.getHours();
return this.getWeekViewIndicatorStyles(timeframeStartDate);
},
getDayViewIndicatorStyles() {
const currentDate = new Date();
const hours = oneHourOffsetDayView * currentDate.getHours();
const minutes = oneHourOffsetDayView * (currentDate.getMinutes() / 60);
return {
left: `${hours + minutes}%`,
};
},
getWeekViewIndicatorStyles(timeframeStartDate) {
const currentDate = new Date();
const hourOffset = oneHourOffsetWeekView * currentDate.getHours();
const daysSinceShiftStart = getDayDifference(timeframeStartDate, currentDate);
const leftOffset = oneDayOffsetWeekView * daysSinceShiftStart + hourOffset;
return {
left: `${weeklyDayOffset + weeklyHourOffset}%`,
left: `${Math.round(leftOffset)}%`,
};
},
},
......
---
title: Update schedule grid to start at beginning of current week
merge_request: 57004
author:
type: added
......@@ -74,7 +74,7 @@ exports[`RotationsListSectionComponent when the timeframe includes today renders
<span
class="current-day-indicator"
data-testid="current-day-indicator"
style="left: 7.142857142857143%;"
style="left: 29%;"
/>
<div>
......
import { shallowMount } from '@vue/test-utils';
import CurrentDayIndicator from 'ee/oncall_schedules/components/schedule/components/current_day_indicator.vue';
import { PRESET_TYPES, DAYS_IN_WEEK, HOURS_IN_DAY } from 'ee/oncall_schedules/constants';
import { PRESET_TYPES, HOURS_IN_DAY } from 'ee/oncall_schedules/constants';
import { useFakeDate } from 'helpers/fake_date';
describe('CurrentDayIndicator', () => {
......@@ -10,7 +10,8 @@ describe('CurrentDayIndicator', () => {
// January 1st, 2018 is the first day of the week-long timeframe
// so as long as current date (faked January 3rd, 2018) is within week timeframe
// current indicator will be rendered
const mockTimeframeInitialDate = new Date(2018, 0, 1);
const mockTimeframeInitialDate = new Date(2018, 0, 1); // Monday
const mockCurrentDate = new Date(2018, 0, 3); // Wednesday
function createComponent({
props = { presetType: PRESET_TYPES.WEEKS, timeframeItem: mockTimeframeInitialDate },
......@@ -36,19 +37,26 @@ describe('CurrentDayIndicator', () => {
expect(wrapper.classes('current-day-indicator')).toBe(true);
});
it('sets correct styles for a week', async () => {
const left = 100 / DAYS_IN_WEEK / 2;
expect(wrapper.attributes('style')).toBe(`left: ${left}%;`);
it('sets correct styles for a week that on a different day than the timeframe start date', () => {
/**
* Our start date for the timeframe in this spec is a Monday,
* and the current day is the following Wednesday.
* This creates a gap of two days so our generated offset should represent:
* DayDiffOffset + weeklyOffset + weeklyHourOffset
* 29 + 0
*/
const leftOffset = '29';
expect(wrapper.attributes('style')).toBe(`left: ${leftOffset}%;`);
});
it('sets correct styles for a day', async () => {
it('sets correct styles for a day', () => {
createComponent({
props: { presetType: PRESET_TYPES.DAYS, timeframeItem: new Date(2018, 0, 3) },
props: { presetType: PRESET_TYPES.DAYS, timeframeItem: mockCurrentDate },
});
const currentDate = new Date();
const base = 100 / HOURS_IN_DAY;
const hours = base * currentDate.getHours();
const minutes = base * (currentDate.getMinutes() / 60) - 2.25;
const minutes = base * (currentDate.getMinutes() / 60);
const left = hours + minutes;
expect(wrapper.attributes('style')).toBe(`left: ${left}%;`);
});
......
import { shallowMount } from '@vue/test-utils';
import { DAYS_IN_WEEK, HOURS_IN_DAY, PRESET_TYPES } from 'ee/oncall_schedules/constants';
import {
PRESET_TYPES,
oneHourOffsetDayView,
oneDayOffsetWeekView,
oneHourOffsetWeekView,
} from 'ee/oncall_schedules/constants';
import CommonMixin from 'ee/oncall_schedules/mixins/common_mixin';
import { useFakeDate } from 'helpers/fake_date';
import * as dateTimeUtility from '~/lib/utils/datetime_utility';
......@@ -81,20 +86,26 @@ describe('Schedule Common Mixins', () => {
});
describe('getIndicatorStyles', () => {
it('returns object containing `left` offset', () => {
const left = 100 / DAYS_IN_WEEK / 2;
expect(wrapper.vm.getIndicatorStyles()).toEqual(
it('returns object containing `left` offset for the weekly grid', () => {
const mockTimeframeInitialDate = new Date(2018, 0, 1);
const mockCurrentDate = new Date(2018, 0, 3);
const hourOffset = oneHourOffsetWeekView * mockCurrentDate.getHours();
const daysSinceShiftStart = dateTimeUtility.getDayDifference(
mockTimeframeInitialDate,
mockCurrentDate,
);
const leftOffset = oneDayOffsetWeekView * daysSinceShiftStart + hourOffset;
expect(wrapper.vm.getIndicatorStyles(PRESET_TYPES.WEEKS, mockTimeframeInitialDate)).toEqual(
expect.objectContaining({
left: `${left}%`,
left: `${Math.round(leftOffset)}%`,
}),
);
});
it('returns object containing `left` offset for a single day grid', () => {
const currentDate = new Date(2018, 0, 8);
const base = 100 / HOURS_IN_DAY;
const hours = base * currentDate.getHours();
const minutes = base * (currentDate.getMinutes() / 60) - 2.25;
const hours = oneHourOffsetDayView * currentDate.getHours();
const minutes = oneHourOffsetDayView * (currentDate.getMinutes() / 60);
expect(wrapper.vm.getIndicatorStyles(PRESET_TYPES.DAYS)).toEqual(
expect.objectContaining({
......
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