angular-calendar-scheduler
Version:
[](https://travis-ci.org/michelebombardi/angular-calendar-scheduler) [](https://www.npm
1,118 lines (1,101 loc) • 190 kB
JavaScript
import * as i0 from '@angular/core';
import { Injectable, Inject, EventEmitter, Output, Input, Component, Pipe, LOCALE_ID, HostListener, ViewEncapsulation, inject, InjectionToken, NgModule } from '@angular/core';
import * as i1$1 from '@angular/common';
import { CommonModule } from '@angular/common';
import { adapterFactory } from 'angular-calendar/date-adapters/date-fns';
import * as i1 from 'angular-calendar';
import { MOMENT, CalendarEventTitleFormatter, CalendarEventTimesChangedEventType, CalendarDateFormatter, DateAdapter, CalendarModule } from 'angular-calendar';
import { isBefore } from 'date-fns';
import { validateEvents as validateEvents$1 } from 'calendar-utils';
import * as i4 from '@angular/cdk/layout';
import * as i6 from 'angular-draggable-droppable';
import * as i7 from 'angular-resizable-element';
// import * as momentNS from 'moment';
// const moment = momentNS;
// import moment from 'moment-timezone';
var DAYS_OF_WEEK;
(function (DAYS_OF_WEEK) {
DAYS_OF_WEEK[DAYS_OF_WEEK["SUNDAY"] = 0] = "SUNDAY";
DAYS_OF_WEEK[DAYS_OF_WEEK["MONDAY"] = 1] = "MONDAY";
DAYS_OF_WEEK[DAYS_OF_WEEK["TUESDAY"] = 2] = "TUESDAY";
DAYS_OF_WEEK[DAYS_OF_WEEK["WEDNESDAY"] = 3] = "WEDNESDAY";
DAYS_OF_WEEK[DAYS_OF_WEEK["THURSDAY"] = 4] = "THURSDAY";
DAYS_OF_WEEK[DAYS_OF_WEEK["FRIDAY"] = 5] = "FRIDAY";
DAYS_OF_WEEK[DAYS_OF_WEEK["SATURDAY"] = 6] = "SATURDAY";
})(DAYS_OF_WEEK || (DAYS_OF_WEEK = {}));
const DEFAULT_WEEKEND_DAYS = [
DAYS_OF_WEEK.SUNDAY,
DAYS_OF_WEEK.SATURDAY
];
const DAYS_IN_WEEK = 7;
const HOURS_IN_DAY = 24;
const MINUTES_IN_HOUR$1 = 60;
const SECONDS_IN_DAY = 60 * 60 * 24;
const DEFAULT_HOUR_SEGMENT_HEIGHT_PX = 40;
const DEFAULT_EVENT_WIDTH = 1;
const DEFAULT_HOUR_SEGMENTS = 2;
function getSchedulerViewHourGrid(dateAdapter, { viewDate, hourSegments, dayStart, dayEnd }) {
const { setMinutes, setHours, startOfDay, startOfMinute, endOfDay, addMinutes, addHours, addDays } = dateAdapter;
const hours = [];
let startOfView = setMinutes(setHours(startOfDay(viewDate), sanitiseHours(dayStart.hour)), sanitiseMinutes(dayStart.minute));
let endOfView = setMinutes(setHours(startOfMinute(endOfDay(viewDate)), sanitiseHours(dayEnd.hour)), sanitiseMinutes(dayEnd.minute));
const segmentDuration = MINUTES_IN_HOUR$1 / hourSegments;
let startOfViewDay = startOfDay(viewDate);
const endOfViewDay = endOfDay(viewDate);
let dateAdjustment = (d) => d;
// this means that we change from or to DST on this day and that's going to cause problems so we bump the date
if (startOfViewDay.getTimezoneOffset() !== endOfViewDay.getTimezoneOffset()) {
startOfViewDay = addDays(startOfViewDay, 1);
startOfView = addDays(startOfView, 1);
endOfView = addDays(endOfView, 1);
dateAdjustment = (d) => addDays(d, -1);
}
for (let i = 0; i < HOURS_IN_DAY; i++) {
}
for (let i = 0; i < HOURS_IN_DAY; i++) {
const segments = [];
for (let j = 0; j < hourSegments; j++) {
const date = addMinutes(addHours(startOfViewDay, i), j * segmentDuration);
if (date >= startOfView && date < endOfView) {
segments.push({
date: dateAdjustment(date),
displayDate: date,
isStart: j === 0
});
}
}
if (segments.length > 0) {
hours.push({ segments });
}
}
return hours;
}
function getSchedulerView(dateAdapter, moment, { events = [], viewDate, viewDays, weekStartsOn, startsWithToday, excluded = [], hourSegments = DEFAULT_HOUR_SEGMENTS, dayStart, dayEnd, weekendDays = DEFAULT_WEEKEND_DAYS, hourSegmentHeight = DEFAULT_HOUR_SEGMENT_HEIGHT_PX, eventWidth = DEFAULT_EVENT_WIDTH, logEnabled, }) {
if (!events) {
events = [];
}
const { addDays, startOfDay, endOfDay, startOfWeek, endOfWeek } = dateAdapter;
const startOfViewWeek = startsWithToday || viewDays < DAYS_IN_WEEK ? startOfDay(viewDate) : startOfWeek(viewDate, { weekStartsOn: weekStartsOn });
const endOfViewWeek = startsWithToday || viewDays < DAYS_IN_WEEK ? addDays(endOfDay(viewDate), viewDays - 1) : endOfWeek(viewDate, { weekStartsOn: weekStartsOn });
const eventsInWeek = getEventsInPeriod(dateAdapter, {
events: events,
periodStart: startOfViewWeek,
periodEnd: endOfViewWeek
});
const days = getSchedulerViewDays(dateAdapter, {
viewDate: viewDate,
viewDays: viewDays,
weekStartsOn: weekStartsOn,
startsWithToday: startsWithToday,
excluded: excluded,
weekendDays: weekendDays
});
days.forEach((day) => {
const startOfView = dateAdapter.setMinutes(dateAdapter.setHours(dateAdapter.startOfDay(day.date), dayStart.hour), dayStart.minute);
const endOfView = dateAdapter.setMinutes(dateAdapter.setHours(dateAdapter.startOfMinute(dateAdapter.endOfDay(day.date)), dayEnd.hour), dayEnd.minute);
const previousDayEvents = [];
const eventsInDay = getEventsInPeriod(dateAdapter, {
events: eventsInWeek,
periodStart: startOfView,
periodEnd: endOfView
});
const dayEvents = eventsInDay
.sort((eventA, eventB) => eventA.start.valueOf() - eventB.start.valueOf())
.map((ev) => {
const eventStart = ev.start;
const eventEnd = ev.end || eventStart;
const startsBeforeDay = eventStart < startOfView;
const endsAfterDay = dateAdapter.addMinutes(eventEnd, -1) > endOfView;
const hourHeightModifier = ((hourSegments * hourSegmentHeight) + 1) / MINUTES_IN_HOUR$1; // +1 for the 1px segment bottom border
let top = 0;
if (eventStart > startOfView) {
top += dateAdapter.differenceInMinutes(eventStart, startOfView);
}
top *= hourHeightModifier;
const startDate = startsBeforeDay ? startOfView : eventStart;
const endDate = endsAfterDay ? endOfView : eventEnd;
let height = dateAdapter.differenceInMinutes(endDate, startDate);
if (!ev.end) {
height = hourSegmentHeight;
}
else {
height *= hourHeightModifier;
}
const bottom = top + height;
const overlappingPreviousEvents = getOverLappingEvents(ev, previousDayEvents, top, bottom, logEnabled);
let left = 0;
while (overlappingPreviousEvents.some(previousEvent => previousEvent.left === left)) {
left += eventWidth;
}
const event = {
event: ev,
top: top,
height: height,
width: eventWidth,
left: left,
startsBeforeDay: startsBeforeDay,
endsAfterDay: endsAfterDay
};
previousDayEvents.push(event);
return event;
});
function getColumnCount(allEvents, prevOverlappingEvents) {
const columnCount = Math.max(...prevOverlappingEvents.map((ev) => ev.left + 1));
const nextOverlappingEvents = allEvents
.filter((ev) => ev.left >= columnCount)
.filter((ev) => {
return (getOverLappingEvents(ev, prevOverlappingEvents, ev.top, ev.top + ev.height, logEnabled).length > 0);
});
if (nextOverlappingEvents.length > 0) {
return getColumnCount(allEvents, nextOverlappingEvents);
}
else {
return columnCount;
}
}
const mappedEvents = dayEvents.map(event => {
const columnCount = getColumnCount(dayEvents, getOverLappingEvents(event, dayEvents, event.top, event.top + event.height, logEnabled));
const width = 100 / columnCount;
return { ...event, left: event.left * width, width };
});
day.events = mappedEvents.map(event => {
const overLappingEvents = getOverLappingEvents(event, mappedEvents.filter(otherEvent => otherEvent.left > event.left), event.top, event.top + event.height, logEnabled);
if (logEnabled) {
console.log(`DAY [${moment(day.date).format('dddd L')}] ` +
`- EVENT ${event.event.id} [${moment(event.event.start).format('dddd L, LTS')} ` +
`- ${moment(event.event.end).format('dddd L, LTS')}] overLappingEvents -> `, overLappingEvents);
}
if (overLappingEvents.length > 0) {
return {
...event,
width: Math.min(...overLappingEvents.map(otherEvent => otherEvent.left)) - event.left
};
}
return event;
});
day.hours = getSchedulerViewHourGrid(dateAdapter, {
viewDate: viewDate,
hourSegments: hourSegments,
dayStart: {
hour: dayStart.hour,
minute: dayStart.minute
},
dayEnd: {
hour: dayEnd.hour,
minute: dayEnd.minute
}
}).map((hour) => {
const date = new Date(day.date.getFullYear(), day.date.getMonth(), day.date.getDate(), hour.segments[0].date.getHours());
const startOfHour = new Date(day.date.getFullYear(), day.date.getMonth(), day.date.getDate(), hour.segments[0].date.getHours());
const endOfHour = dateAdapter.addSeconds(dateAdapter.addHours(startOfHour, 1), -1);
const eventsInHour = getSchedulerEventsInPeriod(dateAdapter, {
events: day.events,
periodStart: startOfHour,
periodEnd: endOfHour
});
const segments = hour.segments.map((segment) => {
segment.date = dateAdapter.setDate(dateAdapter.setMonth(dateAdapter.setYear(segment.date, day.date.getFullYear()), day.date.getMonth()), day.date.getDate());
const startOfSegment = segment.date;
const endOfSegment = dateAdapter.addSeconds(dateAdapter.addMinutes(startOfSegment, MINUTES_IN_HOUR$1 / hourSegments), -1);
const eventsInSegment = getSchedulerEventsInPeriod(dateAdapter, {
events: eventsInHour,
periodStart: startOfSegment,
periodEnd: endOfSegment
});
if (logEnabled) {
console.log(`SEGMENT [${moment(startOfSegment).format('dddd L, LTS')} - ${moment(endOfSegment).format('dddd L, LTS')}] EVENTS -> `, eventsInSegment);
}
return {
segment: segment,
date: new Date(segment.date),
events: eventsInSegment
};
});
return {
hour: hour,
date: date,
events: eventsInHour,
segments: segments
};
});
});
return {
days: days,
period: {
events: eventsInWeek,
start: startOfViewWeek,
end: endOfViewWeek
}
};
}
function getSchedulerViewDays(dateAdapter, { viewDate, viewDays, weekStartsOn, startsWithToday, excluded = [], weekendDays = DEFAULT_WEEKEND_DAYS }) {
const start = startsWithToday || viewDays < DAYS_IN_WEEK
? new Date(viewDate)
: dateAdapter.startOfWeek(viewDate, { weekStartsOn: weekStartsOn });
const days = [];
let currentDate = new Date(start);
while (days.length < viewDays) {
const dayOfWeek = currentDate.getDay();
if (!excluded.includes(dayOfWeek)) {
days.push(getSchedulerDay(dateAdapter, { date: currentDate, weekendDays }));
}
currentDate = dateAdapter.addDays(currentDate, 1);
}
return days;
}
function getSchedulerDay(dateAdapter, args) {
const date = args.date;
const today = dateAdapter.startOfDay(new Date());
return {
date: date,
isPast: date < today,
isToday: dateAdapter.isSameDay(date, today),
isFuture: date >= dateAdapter.addDays(today, 1),
isWeekend: args.weekendDays.indexOf(dateAdapter.getDay(date)) > -1,
inMonth: dateAdapter.isSameMonth(date, today),
hours: []
};
}
function getEventsInPeriod(dateAdapter, { events, periodStart, periodEnd }) {
return events.filter((event) => isEventInPeriod(dateAdapter, { event: event, periodStart: periodStart, periodEnd: periodEnd }));
}
function getSchedulerEventsInPeriod(dateAdapter, { events, periodStart, periodEnd }) {
return events.filter((event) => isEventInPeriod(dateAdapter, { event: event.event, periodStart: periodStart, periodEnd: periodEnd }));
}
function isEventInPeriod(dateAdapter, { event, periodStart, periodEnd }) {
const { isSameSecond, addSeconds } = dateAdapter;
const eventStart = event.start;
const eventEnd = event.end || event.start;
if (eventStart > periodStart && eventStart < periodEnd) {
return true;
}
if (eventEnd > periodStart && eventEnd < periodEnd) {
return true;
}
if (eventStart < periodStart && eventEnd > periodEnd) {
return true;
}
if (isSameSecond(eventStart, periodStart) || isSameSecond(eventStart, periodEnd)) {
return true;
}
if (isSameSecond(addSeconds(eventEnd, -1), periodStart) || isSameSecond(addSeconds(eventEnd, -1), periodEnd)) {
return true;
}
return false;
}
function getOverLappingEvents(event /*SchedulerViewEvent | CalendarSchedulerEvent*/, events, top, bottom, logEnabled = false) {
return events.filter((previousEvent) => {
top = Math.round(top);
bottom = Math.round(bottom);
const previousEventTop = Math.floor(previousEvent.top);
const previousEventBottom = Math.floor(previousEvent.top + previousEvent.height);
if (top < previousEventBottom && previousEventBottom < bottom) {
if (logEnabled) {
console.log('[getOverLappingEvents] - EVENT ' + (event.event?.id || event.id) + ' -> top: ' + top + ' - bottom: ' + bottom + ' | PREVIOUS EVENT ' + previousEvent.event.id
+ ' -> previousEventTop: ' + previousEventTop + ' - previousEventBottom: ' + previousEventBottom + ' -> top < previousEventBottom && previousEventBottom < bottom');
}
return true;
}
else if (top < previousEventTop && previousEventTop < bottom) {
if (logEnabled) {
console.log('[getOverLappingEvents] - EVENT ' + (event.event?.id || event.id) + ' -> top: ' + top + ' - bottom: ' + bottom + ' | PREVIOUS EVENT ' + previousEvent.event.id
+ ' -> previousEventTop: ' + previousEventTop + ' - previousEventBottom: ' + previousEventBottom + ' -> top < previousEventTop && previousEventTop < bottom');
}
return true;
}
else if (previousEventTop <= top && bottom <= previousEventBottom) {
if (logEnabled) {
console.log('[getOverLappingEvents] - EVENT ' + (event.event?.id || event.id) + ' -> top: ' + top + ' - bottom: ' + bottom + ' | PREVIOUS EVENT ' + previousEvent.event.id
+ ' -> previousEventTop: ' + previousEventTop + ' - previousEventBottom: ' + previousEventBottom + ' -> previousEventTop <= top && bottom <= previousEventBottom');
}
return true;
}
return false;
});
}
function sanitiseHours(hours) {
return Math.max(Math.min(23, hours), 0);
}
function sanitiseMinutes(minutes) {
return Math.max(Math.min(59, minutes), 0);
}
function addPeriod(dateAdapter, period, date, amount) {
return {
day: dateAdapter.addDays,
week: dateAdapter.addWeeks,
month: dateAdapter.addMonths
}[period](date, amount);
}
function subPeriod(dateAdapter, period, date, amount) {
return {
day: dateAdapter.subDays,
week: dateAdapter.subWeeks,
month: dateAdapter.subMonths
}[period](date, amount);
}
function startOfPeriod(dateAdapter, period, date) {
return {
day: dateAdapter.startOfDay,
week: dateAdapter.startOfWeek,
month: dateAdapter.startOfMonth
}[period](date);
}
function endOfPeriod(dateAdapter, period, date) {
return {
day: dateAdapter.endOfDay,
week: dateAdapter.endOfWeek,
month: dateAdapter.endOfMonth
}[period](date);
}
const trackByDayOrEvent = (index, event) => (event.event.id ? event.event.id : event.event);
const trackByHourColumn = (index, day) => day.hours[0] ? day.hours[0].segments[0].date.toISOString() : day;
const trackByHour$1 = (index, hour) => hour.segments[0].date.toISOString();
const trackByHourSegment$1 = (index, segment) => segment.date.toISOString();
function getMinimumEventHeightInMinutes(hourSegments, hourSegmentHeight) {
return (MINUTES_IN_HOUR$1 / (hourSegments * hourSegmentHeight)) * hourSegmentHeight;
}
function getDefaultEventEnd$1(dateAdapter, event, minimumMinutes) {
return event.end ? event.end : dateAdapter.addMinutes(event.start, minimumMinutes);
}
function roundToNearest$1(amount, precision) {
return Math.round(amount / precision) * precision;
}
function getMinutesMoved$1(movedY, hourSegments, hourSegmentHeight, eventSnapSize) {
const draggedInPixelsSnapSize = roundToNearest$1(movedY, eventSnapSize || hourSegmentHeight);
const pixelAmountInMinutes = MINUTES_IN_HOUR$1 / (hourSegments * hourSegmentHeight);
return draggedInPixelsSnapSize * pixelAmountInMinutes;
}
function isDraggedWithinPeriod$1(newStart, newEnd, period) {
const end = newEnd || newStart;
return ((period.start <= newStart && newStart <= period.end) ||
(period.start <= end && end <= period.end));
}
function shouldFireDroppedEvent$1(dropEvent, date, calendarId) {
return (dropEvent.dropData &&
dropEvent.dropData.event &&
dropEvent.dropData.calendarId !== calendarId);
}
const validateEvents = (events) => {
const warn = (...args) => console.warn('angular-calendar', ...args);
return validateEvents$1(events, warn);
};
function isInsideLeftAndRight(outer, inner) {
return (Math.floor(outer.left) <= Math.ceil(inner.left) &&
Math.floor(inner.left) <= Math.ceil(outer.right) &&
Math.floor(outer.left) <= Math.ceil(inner.right) &&
Math.floor(inner.right) <= Math.ceil(outer.right));
}
function isInsideTopAndBottom(outer, inner) {
return (Math.floor(outer.top) <= Math.ceil(inner.top) &&
Math.floor(inner.top) <= Math.ceil(outer.bottom) &&
Math.floor(outer.top) <= Math.ceil(inner.bottom) &&
Math.floor(inner.bottom) <= Math.ceil(outer.bottom));
}
function isInside(outer, inner) {
return (isInsideLeftAndRight(outer, inner) && isInsideTopAndBottom(outer, inner));
}
function roundToNearest(amount, precision) {
return Math.round(amount / precision) * precision;
}
const trackByEventId = (index, event) => event.id ? event.id : event;
const trackByWeekDayHeaderDate = (index, day) => day.date.toISOString();
const trackByHourSegment = (index, segment) => segment.date.toISOString();
const trackByHour = (index, hour) => hour.segments[0].date.toISOString();
const trackByWeekAllDayEvent = (index, weekEvent) => (weekEvent.event.id ? weekEvent.event.id : weekEvent.event);
const trackByWeekTimeEvent = (index, weekEvent) => (weekEvent.event.id ? weekEvent.event.id : weekEvent.event);
const MINUTES_IN_HOUR = 60;
function getPixelAmountInMinutes(hourSegments, hourSegmentHeight, hourDuration) {
return (hourDuration || MINUTES_IN_HOUR) / (hourSegments * hourSegmentHeight);
}
function getMinutesMoved(movedY, hourSegments, hourSegmentHeight, eventSnapSize, hourDuration) {
const draggedInPixelsSnapSize = roundToNearest(movedY, eventSnapSize || hourSegmentHeight);
const pixelAmountInMinutes = getPixelAmountInMinutes(hourSegments, hourSegmentHeight, hourDuration);
return draggedInPixelsSnapSize * pixelAmountInMinutes;
}
function getDefaultEventEnd(dateAdapter, event, minimumMinutes) {
if (event.end) {
return event.end;
}
else {
return dateAdapter.addMinutes(event.start, minimumMinutes);
}
}
function addDaysWithExclusions(dateAdapter, date, days, excluded) {
let daysCounter = 0;
let daysToAdd = 0;
const changeDays = days < 0 ? dateAdapter.subDays : dateAdapter.addDays;
let result = date;
while (daysToAdd <= Math.abs(days)) {
result = changeDays(date, daysCounter);
const day = dateAdapter.getDay(result);
if (excluded.indexOf(day) === -1) {
daysToAdd++;
}
daysCounter++;
}
return result;
}
function isDraggedWithinPeriod(newStart, newEnd, period) {
const end = newEnd || newStart;
return ((period.start <= newStart && newStart <= period.end) ||
(period.start <= end && end <= period.end));
}
function shouldFireDroppedEvent(dropEvent, date, allDay, calendarId) {
return (dropEvent.dropData &&
dropEvent.dropData.event &&
(dropEvent.dropData.calendarId !== calendarId ||
(dropEvent.dropData.event.allDay && !allDay) ||
(!dropEvent.dropData.event.allDay && allDay)));
}
function getWeekViewPeriod(dateAdapter, viewDate, weekStartsOn, excluded = [], daysInWeek) {
let viewStart = daysInWeek
? dateAdapter.startOfDay(viewDate)
: dateAdapter.startOfWeek(viewDate, { weekStartsOn });
const endOfWeek = dateAdapter.endOfWeek(viewDate, { weekStartsOn });
while (excluded.indexOf(dateAdapter.getDay(viewStart)) > -1 &&
viewStart < endOfWeek) {
viewStart = dateAdapter.addDays(viewStart, 1);
}
if (daysInWeek) {
const viewEnd = dateAdapter.endOfDay(addDaysWithExclusions(dateAdapter, viewStart, daysInWeek - 1, excluded));
return { viewStart, viewEnd };
}
else {
let viewEnd = endOfWeek;
while (excluded.indexOf(dateAdapter.getDay(viewEnd)) > -1 &&
viewEnd > viewStart) {
viewEnd = dateAdapter.subDays(viewEnd, 1);
}
return { viewStart, viewEnd };
}
}
function isWithinThreshold({ x, y }) {
const DRAG_THRESHOLD = 1;
return Math.abs(x) > DRAG_THRESHOLD || Math.abs(y) > DRAG_THRESHOLD;
}
class CalendarResizeHelper {
resizeContainerElement;
minWidth;
rtl;
constructor(resizeContainerElement, minWidth, rtl) {
this.resizeContainerElement = resizeContainerElement;
this.minWidth = minWidth;
this.rtl = rtl;
}
validateResize({ rectangle, edges }) {
if (this.rtl) {
// TODO - find a way of testing this, for some reason the tests always fail but it does actually work
/* istanbul ignore next */
if (typeof edges.left !== 'undefined') {
rectangle.left -= edges.left;
rectangle.right += edges.left;
}
else if (typeof edges.right !== 'undefined') {
rectangle.left += edges.right;
rectangle.right -= edges.right;
}
rectangle.width = rectangle.right - rectangle.left;
}
if (this.minWidth &&
Math.ceil(rectangle.width) < Math.ceil(this.minWidth)) {
return false;
}
return isInside(this.resizeContainerElement.getBoundingClientRect(), rectangle);
}
}
class CalendarDragHelper {
dragContainerElement;
startPosition;
constructor(dragContainerElement, draggableElement) {
this.dragContainerElement = dragContainerElement;
this.startPosition = draggableElement.getBoundingClientRect();
}
validateDrag({ x, y, snapDraggedEvents, dragAlreadyMoved, transform, }) {
const isDraggedWithinThreshold = isWithinThreshold({ x, y }) || dragAlreadyMoved;
if (snapDraggedEvents) {
const inner = Object.assign({}, this.startPosition, {
left: this.startPosition.left + transform.x,
right: this.startPosition.right + transform.x,
top: this.startPosition.top + transform.y,
bottom: this.startPosition.bottom + transform.y,
});
if (isDraggedWithinThreshold) {
const outer = this.dragContainerElement.getBoundingClientRect();
const isTopInside = outer.top < inner.top && inner.top < outer.bottom;
const isBottomInside = outer.top < inner.bottom && inner.bottom < outer.bottom;
return (
/*isInsideLeftAndRight(outer, inner) &&*/ (isTopInside || isBottomInside));
}
/* istanbul ignore next */
return false;
}
else {
return isDraggedWithinThreshold;
}
}
}
/**
* Auth configuration.
*/
class SchedulerConfig {
locale = 'en';
headerDateFormat = 'daysRange';
logEnabled = false;
constructor(config = {}) {
function use(source, defaultValue) {
return config && source !== undefined ? source : defaultValue;
}
this.locale = use(config.locale, this.locale);
this.headerDateFormat = use(config.headerDateFormat, this.headerDateFormat);
this.logEnabled = use(config.logEnabled, this.logEnabled);
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: SchedulerConfig, deps: [{ token: SchedulerConfig }], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: SchedulerConfig });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: SchedulerConfig, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: SchedulerConfig }] });
class CalendarSchedulerUtils {
dateAdapter;
moment;
constructor(dateAdapter, moment) {
this.dateAdapter = dateAdapter;
this.moment = moment;
}
getSchedulerViewHourGrid(args) {
return getSchedulerViewHourGrid(this.dateAdapter, args);
}
getSchedulerViewDays(args) {
return getSchedulerViewDays(this.dateAdapter, args);
}
getSchedulerView(args) {
return getSchedulerView(this.dateAdapter, this.moment, args);
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: CalendarSchedulerUtils, deps: [{ token: i1.DateAdapter }, { token: MOMENT }], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: CalendarSchedulerUtils });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: CalendarSchedulerUtils, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: i1.DateAdapter }, { type: undefined, decorators: [{
type: Inject,
args: [MOMENT]
}] }] });
// import * as momentNS from 'moment';
// const moment = momentNS;
// import moment from 'moment-timezone';
class CalendarSchedulerHourSegmentComponent {
moment;
title;
day;
segment;
locale;
customTemplate;
hourSegmentHeight = 58;
showHour = false;
segmentClicked = new EventEmitter();
constructor(moment) {
this.moment = moment;
}
ngOnInit() {
this.title = this.title || this.moment(this.segment.date).format('dddd L, LT');
}
/**
* @hidden
*/
onMouseEnter(mouseEvent, segment, event) {
if (!event.isDisabled && !segment.isDisabled) {
// Maybe do something
}
}
/**
* @hidden
*/
onMouseLeave(mouseEvent, segment, event) {
if (!event.isDisabled && !segment.isDisabled) {
// Maybe do something
}
}
/**
* @hidden
*/
onSegmentClick(mouseEvent, segment) {
if (mouseEvent.stopPropagation) {
mouseEvent.stopPropagation();
}
if (segment.events.length === 0 && !segment.isDisabled && !segment.isCancelled) {
this.segmentClicked.emit({ segment: segment });
}
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: CalendarSchedulerHourSegmentComponent, deps: [{ token: MOMENT }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: CalendarSchedulerHourSegmentComponent, isStandalone: false, selector: "calendar-scheduler-hour-segment", inputs: { title: "title", day: "day", segment: "segment", locale: "locale", customTemplate: "customTemplate", hourSegmentHeight: "hourSegmentHeight", showHour: "showHour" }, outputs: { segmentClicked: "segmentClicked" }, ngImport: i0, template: `
<ng-template #defaultTemplate>
<div class="cal-scheduler-hour-segment"
[title]="title"
[ngClass]="segment?.cssClass"
[class.has-events]="segment.events.length > 0"
[class.cal-cancelled]="segment.isCancelled"
[class.cal-disabled]="segment.isDisabled"
[style.backgroundColor]="segment.backgroundColor"
[style.height.px]="hourSegmentHeight"
(mwlClick)="onSegmentClick($event, segment)">
@if (showHour && segment.events.length === 0) {
<div class="cal-scheduler-time unselectable">
{{ segment.date | calendarDate:'dayViewHour':locale }}
</div>
}
</div>
</ng-template>
<ng-template
[ngTemplateOutlet]="customTemplate || defaultTemplate"
[ngTemplateOutletContext]="{
title: title,
day: day,
segment: segment,
locale: locale,
hourSegmentHeight: hourSegmentHeight,
showHour: showHour,
segmentClicked: segmentClicked
}">
</ng-template>
`, isInline: true, dependencies: [{ kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1.ClickDirective, selector: "[mwlClick]", inputs: ["clickListenerDisabled"], outputs: ["mwlClick"] }, { kind: "pipe", type: i1.CalendarDatePipe, name: "calendarDate" }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: CalendarSchedulerHourSegmentComponent, decorators: [{
type: Component,
args: [{
standalone: false,
selector: 'calendar-scheduler-hour-segment',
template: `
<ng-template #defaultTemplate>
<div class="cal-scheduler-hour-segment"
[title]="title"
[ngClass]="segment?.cssClass"
[class.has-events]="segment.events.length > 0"
[class.cal-cancelled]="segment.isCancelled"
[class.cal-disabled]="segment.isDisabled"
[style.backgroundColor]="segment.backgroundColor"
[style.height.px]="hourSegmentHeight"
(mwlClick)="onSegmentClick($event, segment)">
@if (showHour && segment.events.length === 0) {
<div class="cal-scheduler-time unselectable">
{{ segment.date | calendarDate:'dayViewHour':locale }}
</div>
}
</div>
</ng-template>
<ng-template
[ngTemplateOutlet]="customTemplate || defaultTemplate"
[ngTemplateOutletContext]="{
title: title,
day: day,
segment: segment,
locale: locale,
hourSegmentHeight: hourSegmentHeight,
showHour: showHour,
segmentClicked: segmentClicked
}">
</ng-template>
`
}]
}], ctorParameters: () => [{ type: undefined, decorators: [{
type: Inject,
args: [MOMENT]
}] }], propDecorators: { title: [{
type: Input
}], day: [{
type: Input
}], segment: [{
type: Input
}], locale: [{
type: Input
}], customTemplate: [{
type: Input
}], hourSegmentHeight: [{
type: Input
}], showHour: [{
type: Input
}], segmentClicked: [{
type: Output
}] } });
class CalendarSchedulerHeaderComponent {
days;
locale;
customTemplate;
dayHeaderClicked = new EventEmitter();
/**
* @hidden
*/
onDayHeaderClick(mouseEvent, day) {
if (mouseEvent.stopPropagation) {
mouseEvent.stopPropagation();
}
this.dayHeaderClicked.emit({ day: day });
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: CalendarSchedulerHeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: CalendarSchedulerHeaderComponent, isStandalone: false, selector: "calendar-scheduler-header", inputs: { days: "days", locale: "locale", customTemplate: "customTemplate" }, outputs: { dayHeaderClicked: "dayHeaderClicked" }, ngImport: i0, template: `
<ng-template #defaultTemplate>
<div class="cal-scheduler-headers">
<div class="cal-header aside cal-header-clock align-center">
<i class="material-icons md-32" style="margin:auto;">schedule</i>
</div>
<div class="cal-header-cols aside">
@for (day of days; track day) {
<div
class="cal-header"
[class.cal-past]="day.isPast"
[class.cal-today]="day.isToday"
[class.cal-future]="day.isFuture"
[class.cal-weekend]="day.isWeekend"
(mwlClick)="onDayHeaderClick($event, day)">
<b>{{ day.date | calendarDate:'weekViewColumnHeader':locale }}</b><br>
<span>{{ day.date | calendarDate:'weekViewColumnSubHeader':locale }}</span>
</div>
}
</div>
</div>
</ng-template>
<ng-template
[ngTemplateOutlet]="customTemplate || defaultTemplate"
[ngTemplateOutletContext]="{
days: days,
locale: locale,
dayHeaderClicked: dayHeaderClicked
}">
</ng-template>
`, isInline: true, dependencies: [{ kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1.ClickDirective, selector: "[mwlClick]", inputs: ["clickListenerDisabled"], outputs: ["mwlClick"] }, { kind: "pipe", type: i1.CalendarDatePipe, name: "calendarDate" }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: CalendarSchedulerHeaderComponent, decorators: [{
type: Component,
args: [{
standalone: false,
selector: 'calendar-scheduler-header',
template: `
<ng-template #defaultTemplate>
<div class="cal-scheduler-headers">
<div class="cal-header aside cal-header-clock align-center">
<i class="material-icons md-32" style="margin:auto;">schedule</i>
</div>
<div class="cal-header-cols aside">
@for (day of days; track day) {
<div
class="cal-header"
[class.cal-past]="day.isPast"
[class.cal-today]="day.isToday"
[class.cal-future]="day.isFuture"
[class.cal-weekend]="day.isWeekend"
(mwlClick)="onDayHeaderClick($event, day)">
<b>{{ day.date | calendarDate:'weekViewColumnHeader':locale }}</b><br>
<span>{{ day.date | calendarDate:'weekViewColumnSubHeader':locale }}</span>
</div>
}
</div>
</div>
</ng-template>
<ng-template
[ngTemplateOutlet]="customTemplate || defaultTemplate"
[ngTemplateOutletContext]="{
days: days,
locale: locale,
dayHeaderClicked: dayHeaderClicked
}">
</ng-template>
`
}]
}], propDecorators: { days: [{
type: Input
}], locale: [{
type: Input
}], customTemplate: [{
type: Input
}], dayHeaderClicked: [{
type: Output
}] } });
class CalendarSchedulerEventActionsComponent {
event;
actions = [];
ngOnInit() {
this.setupActions();
}
ngOnChanges(changes) {
if (changes.event) {
this.setupActions();
}
}
setupActions() {
if (this.event.actions) {
this.actions = this.event.isCancelled
? this.event.actions.filter((a) => !a.when || a.when === 'cancelled')
: this.event.isDisabled
? this.event.actions.filter((a) => !a.when || a.when === 'disabled')
: this.event.actions.filter((a) => !a.when || a.when === 'enabled');
}
}
/**
* @hidden
*/
onActionClick(mouseEvent, action, event) {
if (mouseEvent.stopPropagation) {
mouseEvent.stopPropagation();
}
action.onClick(event);
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: CalendarSchedulerEventActionsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: CalendarSchedulerEventActionsComponent, isStandalone: false, selector: "calendar-scheduler-event-actions", inputs: { event: "event" }, host: { classAttribute: "cal-scheduler-event-actions-container" }, usesOnChanges: true, ngImport: i0, template: `
@if (event.actions) {
<span
class="cal-scheduler-event-actions">
@for (action of actions; track action) {
<a
class="cal-scheduler-event-action"
href="javascript:;"
(mwlClick)="onActionClick($event, action, event)"
[ngClass]="action.cssClass"
[innerHtml]="action.label"
[title]="action.title">
</a>
}
</span>
}
`, isInline: true, dependencies: [{ kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.ClickDirective, selector: "[mwlClick]", inputs: ["clickListenerDisabled"], outputs: ["mwlClick"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: CalendarSchedulerEventActionsComponent, decorators: [{
type: Component,
args: [{
standalone: false,
selector: 'calendar-scheduler-event-actions',
template: `
@if (event.actions) {
<span
class="cal-scheduler-event-actions">
@for (action of actions; track action) {
<a
class="cal-scheduler-event-action"
href="javascript:;"
(mwlClick)="onActionClick($event, action, event)"
[ngClass]="action.cssClass"
[innerHtml]="action.label"
[title]="action.title">
</a>
}
</span>
}
`,
host: {
'class': 'cal-scheduler-event-actions-container'
}
}]
}], propDecorators: { event: [{
type: Input
}] } });
class SchedulerEventTitleFormatter extends CalendarEventTitleFormatter {
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: SchedulerEventTitleFormatter, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: SchedulerEventTitleFormatter });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: SchedulerEventTitleFormatter, decorators: [{
type: Injectable
}] });
class SchedulerEventTitlePipe {
schedulerEventTitle;
constructor(schedulerEventTitle) {
this.schedulerEventTitle = schedulerEventTitle;
}
transform(title, titleType, event) {
return this.schedulerEventTitle[titleType](event);
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: SchedulerEventTitlePipe, deps: [{ token: SchedulerEventTitleFormatter }], target: i0.ɵɵFactoryTarget.Pipe });
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.3", ngImport: i0, type: SchedulerEventTitlePipe, isStandalone: false, name: "schedulerEventTitle" });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: SchedulerEventTitlePipe, decorators: [{
type: Pipe,
args: [{
standalone: false,
name: 'schedulerEventTitle'
}]
}], ctorParameters: () => [{ type: SchedulerEventTitleFormatter }] });
class CalendarSchedulerEventTitleComponent {
view;
event;
showStatus = true;
showContent = true;
showActions = true;
customTemplate;
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: CalendarSchedulerEventTitleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: CalendarSchedulerEventTitleComponent, isStandalone: false, selector: "calendar-scheduler-event-title", inputs: { view: "view", event: "event", showStatus: "showStatus", showContent: "showContent", showActions: "showActions", customTemplate: "customTemplate" }, host: { classAttribute: "cal-scheduler-event-title-container" }, ngImport: i0, template: `
<ng-template #defaultTemplate>
<div
class="cal-scheduler-event-title"
[innerHTML]="event.title | schedulerEventTitle:view:event">
</div>
@if (showActions && !showContent && (event.isClickable || event.isDisabled)) {
<calendar-scheduler-event-actions
class="no-content-actions"
[event]="event">
</calendar-scheduler-event-actions>
}
@if (event.status && showStatus) {
<div
class="cal-scheduler-event-status"
[class.ok]="event.status === 'ok'"
[class.warning]="event.status === 'warning'"
[class.danger]="event.status === 'danger'">
</div>
}
</ng-template>
<ng-template
[ngTemplateOutlet]="customTemplate || defaultTemplate"
[ngTemplateOutletContext]="{
view: view,
event: event,
showStatus: showStatus,
showContent: showContent,
showActions: showActions
}">
</ng-template>
`, isInline: true, dependencies: [{ kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: CalendarSchedulerEventActionsComponent, selector: "calendar-scheduler-event-actions", inputs: ["event"] }, { kind: "pipe", type: SchedulerEventTitlePipe, name: "schedulerEventTitle" }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: CalendarSchedulerEventTitleComponent, decorators: [{
type: Component,
args: [{
standalone: false,
selector: 'calendar-scheduler-event-title',
template: `
<ng-template #defaultTemplate>
<div
class="cal-scheduler-event-title"
[innerHTML]="event.title | schedulerEventTitle:view:event">
</div>
@if (showActions && !showContent && (event.isClickable || event.isDisabled)) {
<calendar-scheduler-event-actions
class="no-content-actions"
[event]="event">
</calendar-scheduler-event-actions>
}
@if (event.status && showStatus) {
<div
class="cal-scheduler-event-status"
[class.ok]="event.status === 'ok'"
[class.warning]="event.status === 'warning'"
[class.danger]="event.status === 'danger'">
</div>
}
</ng-template>
<ng-template
[ngTemplateOutlet]="customTemplate || defaultTemplate"
[ngTemplateOutletContext]="{
view: view,
event: event,
showStatus: showStatus,
showContent: showContent,
showActions: showActions
}">
</ng-template>
`,
host: {
'class': 'cal-scheduler-event-title-container'
}
}]
}], propDecorators: { view: [{
type: Input
}], event: [{
type: Input
}], showStatus: [{
type: Input
}], showContent: [{
type: Input
}], showActions: [{
type: Input
}], customTemplate: [{
type: Input
}] } });
class CalendarSchedulerEventContentComponent {
hostElement;
event;
eventContainer;
maxHeight;
constructor(hostElement) {
this.hostElement = hostElement;
}
ngAfterViewInit() {
setTimeout(() => { this.maxHeight = Math.max(30, this.eventContainer.clientHeight - 70); }, 0);
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: CalendarSchedulerEventContentComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: CalendarSchedulerEventContentComponent, isStandalone: false, selector: "calendar-scheduler-event-content", inputs: { event: "event", eventContainer: "eventContainer" }, host: { classAttribute: "cal-scheduler-event-content-container" }, ngImport: i0, template: `
@if (event.content) {
<div
class="cal-scheduler-event-content"
[style.max-height.px]="maxHeight"
[style.white-space]="maxHeight && maxHeight > 30 ? 'normal' : 'nowrap'"
[innerHTML]="event.content">
</div>
}
`, isInline: true });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: CalendarSchedulerEventContentComponent, decorators: [{
type: Component,
args: [{
standalone: false,
selector: 'calendar-scheduler-event-content',
template: `
@if (event.content) {
<div
class="cal-scheduler-event-content"
[style.max-height.px]="maxHeight"
[style.white-space]="maxHeight && maxHeight > 30 ? 'normal' : 'nowrap'"
[innerHTML]="event.content">
</div>
}
`,
host: {
'class': 'cal-scheduler-event-content-container'
}
}]
}], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { event: [{
type: Input
}], eventContainer: [{
type: Input
}] } });
// import * as momentNS from 'moment';
// const moment = momentNS;
// import moment from 'moment-timezone';
class CalendarSchedulerEventComponent {
hostElement;
changeDetectorRef;
moment;
title;
day;
event;
container;
showContent = true;
showActions = true;
showStatus = true;
customTemplate;
eventTitleTemplate;
eventClicked = new EventEmitter();
constructor(hostElement, changeDetectorRef, moment) {
this.hostElement = hostElement;
this.changeDetectorRef = changeDetectorRef;
this.moment = moment;
}
ngOnInit() {
this.title = this.title || `${this.event.event.title}, ${this.event.event.content ? `${this.event.event.content},` : null} ${this.moment(this.event.event.start).format('dddd L, LT')}`;
}
ngAfterContentChecked() {
this.changeDetectorRef.detectChanges();
}
onMouseEnter() {
// Maybe do something
}
onMouseLeave() {
// Maybe do something
}
/**
* @hidden
*/
onEventClick(mouseEvent, event) {
if (mouseEvent.stopPropagation) {
mouseEvent.stopPropagation();
}
if (event.isClickable) {
this.eventClicked.emit({ event: event });
}
}
static ɵfac = i0.ɵɵn