UNPKG

angular-calendar-scheduler

Version:

[![Build Status](https://travis-ci.org/michelebombardi/angular-calendar-scheduler.svg?branch=main)](https://travis-ci.org/michelebombardi/angular-calendar-scheduler) [![npm version](https://badge.fury.io/js/angular-calendar-scheduler.svg)](https://www.npm

1,118 lines (1,101 loc) 190 kB
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