Add new enum value and update description in

LayerPreview component
This commit is contained in:
Simon Larsen
2023-11-29 19:36:56 +00:00
parent ad4c98a492
commit ebc2f6f56e
4 changed files with 337 additions and 4 deletions

View File

@@ -23,6 +23,17 @@ export default class OneUptimeDate {
return moment();
}
public static keepTimeButMoveDay(keepTimeFor: Date, moveDayTo: Date){
keepTimeFor = this.fromString(keepTimeFor);
moveDayTo = this.fromString(moveDayTo);
return moment(moveDayTo).set({
hour: keepTimeFor.getHours(),
minute: keepTimeFor.getMinutes(),
second: keepTimeFor.getSeconds(),
millisecond: keepTimeFor.getMilliseconds()
}).toDate();
}
public static getOneMinAgo(): Date {
return this.getSomeMinutesAgo(new PositiveNumber(1));
}
@@ -42,6 +53,8 @@ export default class OneUptimeDate {
return Math.abs(Seconds_from_T1_to_T2);
}
public static getSomeMinutesAgo(minutes: PositiveNumber | number): Date {
if (!(minutes instanceof PositiveNumber)) {
minutes = new PositiveNumber(minutes);
@@ -87,6 +100,48 @@ export default class OneUptimeDate {
};
}
public static areOnTheSameDay(date1: Date, date2: Date): boolean {
date1 = this.fromString(date1);
date2 = this.fromString(date2);
return moment(date1).isSame(date2, 'day');
}
public static areOnTheSameMonth(date1: Date, date2: Date): boolean {
date1 = this.fromString(date1);
date2 = this.fromString(date2);
return moment(date1).isSame(date2, 'month');
}
public static areOnTheSameYear(date1: Date, date2: Date): boolean {
date1 = this.fromString(date1);
date2 = this.fromString(date2);
return moment(date1).isSame(date2, 'year');
}
public static areOnTheSameHour(date1: Date, date2: Date): boolean {
date1 = this.fromString(date1);
date2 = this.fromString(date2);
return moment(date1).isSame(date2, 'hour');
}
public static areOnTheSameMinute(date1: Date, date2: Date): boolean {
date1 = this.fromString(date1);
date2 = this.fromString(date2);
return moment(date1).isSame(date2, 'minute');
}
public static areOnTheSameSecond(date1: Date, date2: Date): boolean {
date1 = this.fromString(date1);
date2 = this.fromString(date2);
return moment(date1).isSame(date2, 'second');
}
public static areOnTheSameWeek(date1: Date, date2: Date): boolean {
date1 = this.fromString(date1);
date2 = this.fromString(date2);
return moment(date1).isSame(date2, 'week');
}
public static addRemoveMinutes(date: Date, minutes: number): Date {
date = this.fromString(date);
return moment(date).add(minutes, 'minutes').toDate();
@@ -97,6 +152,26 @@ export default class OneUptimeDate {
return moment(date).add(days, 'days').toDate();
}
public static addRemoveHours(date: Date, hours: number): Date {
date = this.fromString(date);
return moment(date).add(hours, 'hours').toDate();
}
public static addRemoveYears(date: Date, years: number): Date {
date = this.fromString(date);
return moment(date).add(years, 'years').toDate();
}
public static addRemoveMonths(date: Date, months: number): Date {
date = this.fromString(date);
return moment(date).add(months, 'months').toDate();
}
public static addRemoveWeeks(date: Date, weeks: number): Date {
date = this.fromString(date);
return moment(date).add(weeks, 'weeks').toDate();
}
public static addRemoveSeconds(date: Date, seconds: number): Date {
date = this.fromString(date);
return moment(date).add(seconds, 'seconds').toDate();
@@ -366,6 +441,18 @@ export default class OneUptimeDate {
return moment(date).isAfter(startDate);
}
public static isOnOrAfter(date: Date, startDate: Date): boolean {
date = this.fromString(date);
startDate = this.fromString(startDate);
return moment(date).isSameOrAfter(startDate);
}
public static isOnOrBefore(date: Date, endDate: Date): boolean {
date = this.fromString(date);
endDate = this.fromString(endDate);
return moment(date).isSameOrBefore(endDate);
}
public static isEqualBySeconds(date: Date, startDate: Date): boolean {
date = this.fromString(date);
startDate = this.fromString(startDate);

View File

@@ -1,4 +1,5 @@
enum EventInterval {
Hour = 'Hour',
Day = 'Day',
Week = 'Week',
Month = 'Month',

View File

@@ -1,10 +1,13 @@
import UserModel from '../../Models/UserModel';
import Recurring from '../Events/Recurring';
import CalendarEvent from '../Calendar/CalendarEvent';
import RestrictionTimes from './RestrictionTimes';
import RestrictionTimes, { RestrictionType } from './RestrictionTimes';
import OneUptimeDate from '../Date';
import EventInterval from '../Events/EventInterval';
import StartAndEndTime from '../Time/StartAndEndTime';
export default class Layer {
public static getEvents(_data: {
export default class LayerUtil {
public static getEvents(data: {
users: Array<UserModel>;
startDateTimeOfLayer: Date;
calendarStartDate: Date;
@@ -13,6 +16,247 @@ export default class Layer {
handOffTime: Date;
rotation: Recurring;
}): Array<CalendarEvent> {
const events: Array<CalendarEvent> = [];
let start: Date = data.calendarStartDate;
let end: Date = data.calendarEndDate;
// start time of the layer is after the start time of the calendar, so we need to update the start time of the calendar
if (OneUptimeDate.isAfter(data.startDateTimeOfLayer, start)) {
start = data.startDateTimeOfLayer;
}
// end time of the layer is before the end time of the calendar, so, we dont have any events and we can return empty array
if (OneUptimeDate.isAfter(data.startDateTimeOfLayer, end)) {
return [];
}
// if users are empty, we dont have any events and we can return empty array
if (data.users.length === 0) {
return [];
}
// split events by rotation.
const rotation: Recurring = data.rotation;
let hasReachedTheEndOfTheCalendar: boolean = false;
const handOffTime: Date = data.handOffTime;
// Looop vars
let currentEventStartTime: Date = start;
let currentEventEndTime: Date = OneUptimeDate.getCurrentDate(); // temporary set to current time to avoid typescript error
let currentUserIndex: number = 0;
while (!hasReachedTheEndOfTheCalendar) {
if (rotation.intervalType === EventInterval.Day) {
const daysToAdd = rotation.intervalCount.toNumber();
currentEventEndTime = OneUptimeDate.addRemoveDays(currentEventStartTime, daysToAdd);
} else if (rotation.intervalType === EventInterval.Week) {
let weeksToAdd = rotation.intervalCount.toNumber();
currentEventEndTime = OneUptimeDate.addRemoveWeeks(currentEventStartTime, weeksToAdd);
} else if (rotation.intervalType === EventInterval.Month) {
const monthsToAdd = rotation.intervalCount.toNumber();
currentEventEndTime = OneUptimeDate.addRemoveMonths(currentEventStartTime, monthsToAdd);
} else if (rotation.intervalType === EventInterval.Year) {
const yearsToAdd = rotation.intervalCount.toNumber();
currentEventEndTime = OneUptimeDate.addRemoveYears(currentEventStartTime, yearsToAdd);
} else if (rotation.intervalType === EventInterval.Hour) {
const hoursToAdd = rotation.intervalCount.toNumber();
currentEventEndTime = OneUptimeDate.addRemoveHours(currentEventStartTime, hoursToAdd);
}
// check calendar end time. if the end time of the event is after the end time of the calendar, we need to update the end time of the event
if (OneUptimeDate.isAfter(currentEventEndTime, end)) {
currentEventEndTime = end;
hasReachedTheEndOfTheCalendar = true;
}
// check restriction times. if the end time of the event is after the end time of the restriction times, we need to update the end time of the event.
const trimmedStartAndEndTimes: Array<StartAndEndTime>
= LayerUtil.trimStartAndEndTimesBasedOnRestrictionTimes({
eventStartTime: currentEventStartTime,
eventEndTime: currentEventEndTime,
restrictionTimes: data.restrictionTImes,
});
const userId = data.users[currentUserIndex]?.id?.toString() || '';
for (const trimmedStartAndEndTime of trimmedStartAndEndTimes) {
const event: CalendarEvent = {
id: 0,
title: userId, // This will be changed to username in the UI or will bve kept the same if used on the server.
allDay: false,
start: trimmedStartAndEndTime.startTime,
end: trimmedStartAndEndTime.endTime,
};
events.push(event);
}
// update the current event start time
currentEventStartTime = currentEventEndTime;
// update the current user index
currentUserIndex++;
// if the current user index is greater than the length of the users array, we need to reset the current user index to 0
if (currentUserIndex >= data.users.length) {
currentUserIndex = 0;
}
}
// increment ids of all the events and return them, to make sure they are unique
let id = 1;
for (const event of events) {
event.id = id;
id++;
}
return events;
}
public static trimStartAndEndTimesBasedOnRestrictionTimes(data: {
eventStartTime: Date;
eventEndTime: Date;
restrictionTimes: RestrictionTimes;
}): Array<StartAndEndTime> {
const restrictionTimes: RestrictionTimes = data.restrictionTimes;
if (restrictionTimes.restictionType === RestrictionType.None) {
return [{
startTime: data.eventStartTime,
endTime: data.eventEndTime,
}];
}
if (restrictionTimes.restictionType === RestrictionType.Daily) {
const dayRestrictionTimes = restrictionTimes.dayRestrictionTimes;
// if there are no day restriction times, we dont have any restrictions and we can return the event start and end times
if (!dayRestrictionTimes) {
return [{
startTime: data.eventStartTime,
endTime: data.eventEndTime,
}];
}
//
let restrictionStartTime: Date = dayRestrictionTimes.startTime;
let restrictionEndTime: Date = dayRestrictionTimes.endTime;
let currentStartTime = data.eventStartTime;
let currentEndTime = data.eventEndTime;
const trimmedStartAndEndTimes: Array<StartAndEndTime> = [];
let reachedTheEndOfTheCurrentEvent = false;
while (!reachedTheEndOfTheCurrentEvent) {
// if current end time is equalto or before than the current start time, we need to return the current event and exit the loop
if (OneUptimeDate.isBefore(currentEndTime, currentStartTime)) {
reachedTheEndOfTheCurrentEvent = true;
}
// before this we need to make sure restrciton times are moved to the day of the event.
restrictionStartTime = OneUptimeDate.keepTimeButMoveDay(restrictionStartTime, data.eventStartTime);
restrictionEndTime = OneUptimeDate.keepTimeButMoveDay(restrictionEndTime, data.eventStartTime);
// if the restriction end time is before the restriction start time, we need to add one day to the restriction end time
if (OneUptimeDate.isAfter(restrictionStartTime, restrictionEndTime)) {
restrictionEndTime = OneUptimeDate.addRemoveDays(restrictionEndTime, 1);
}
// 1 - if the current event falls within the restriction times, we need to return the current event.
if (OneUptimeDate.isOnOrAfter(currentStartTime, restrictionStartTime) && OneUptimeDate.isOnOrAfter(restrictionEndTime, currentEndTime)) {
trimmedStartAndEndTimes.push({
startTime: currentStartTime,
endTime: currentEndTime,
});
reachedTheEndOfTheCurrentEvent = true;
}
// 2 - Start Restriction: If the current event starts after the restriction start time and ends after the restriction end time, we need to return the current event with the start time of the current event and end time of the restriction
if (OneUptimeDate.isOnOrAfter(currentStartTime, restrictionStartTime) && OneUptimeDate.isOnOrAfter(currentEndTime, restrictionEndTime)) {
trimmedStartAndEndTimes.push({
startTime: currentStartTime,
endTime: restrictionEndTime,
});
reachedTheEndOfTheCurrentEvent = true;
}
// 3 - End Restriction - If the current event starts before the restriction start time and ends before the restriction end time, we need to return the current event with the start time of the restriction and end time of the current event.
if (OneUptimeDate.isBefore(currentStartTime, restrictionStartTime) && OneUptimeDate.isBefore(currentEndTime, restrictionEndTime)) {
trimmedStartAndEndTimes.push({
startTime: restrictionStartTime,
endTime: currentEndTime,
});
reachedTheEndOfTheCurrentEvent = true;
}
// 4 - If the current event starts before the restriction start time and ends after the restriction end time, we need to return the current event with the start time of the restriction and end time of the restriction.
if (OneUptimeDate.isBefore(currentStartTime, restrictionStartTime) && OneUptimeDate.isOnOrAfter(currentEndTime, restrictionEndTime)) {
trimmedStartAndEndTimes.push({
startTime: restrictionStartTime,
endTime: restrictionEndTime,
});
reachedTheEndOfTheCurrentEvent = true;
}
}
}
if (restrictionTimes.restictionType === RestrictionType.Weekly) {
const weeklyRestrictionTimes = restrictionTimes.weeklyRestrictionTimes;
// if there are no weekly restriction times, we dont have any restrictions and we can return the event start and end times
if (!weeklyRestrictionTimes || weeklyRestrictionTimes.length === 0) {
return [{
startTime: data.eventStartTime,
endTime: data.eventEndTime,
}];
}
}
return [];
}
}

View File

@@ -3,6 +3,7 @@ import OnCallDutyPolicyScheduleLayerUser from 'Model/Models/OnCallDutyPolicySche
import React, { FunctionComponent, ReactElement } from 'react';
import Calendar from 'CommonUI/src/Components/Calendar/Calendar';
import FieldLabelElement from 'CommonUI/src/Components/Forms/Fields/FieldLabel';
import OneUptimeDate from 'Common/Types/Date';
export interface ComponentProps {
layer: OnCallDutyPolicyScheduleLayer;
@@ -19,7 +20,7 @@ const LayerPreview: FunctionComponent<ComponentProps> = (
<FieldLabelElement
required={true}
title="Layer Preview"
description="Here is a preview of who is on call and when."
description={"Here is a preview of who is on call and when. This is based on your local timezone - "+OneUptimeDate.getCurrentTimezoneString()}
/>
<Calendar
events={[