@asadi/angular-date-components
Version:
`Angular Date Components` is a comprehensive angular library of date-related components designed to meet the needs of applications that require localization based on various calendar systems. While the package currently includes two powerful components (S
1,127 lines (1,117 loc) • 56.3 kB
JavaScript
import * as i0 from '@angular/core';
import { EventEmitter, Directive, Output, Input, inject, Component, NgModule, booleanAttribute, Inject, Optional } from '@angular/core';
import * as i3 from '@angular/common';
import { CommonModule } from '@angular/common';
import * as i2 from '@asadi/angular-date-components/core';
import { ADCDateTimeTools, DateChangeService, ADC_DATE_ADAPTER, ADC_DATE_FORMATTER, ADC_LABELS, ADC_OPTIONS, ADCStaticValues, ADCCommonService, TableSelection, FlatEventBuilder, ADCTableComponent, ADCBaseContainerComponent } from '@asadi/angular-date-components/core';
import { BehaviorSubject, Subject, takeUntil } from 'rxjs';
/**
* The `ADCResourceSchedulerSource` directive is used to manage and interact with the data source
* for the resource scheduler. It provides input properties for resources, events, holidays, and weekends,
* and emits output events for date range changes, event selection, and date range selection.
*/
class ADCResourceSchedulerSource {
constructor() {
this._events = new BehaviorSubject([]);
this._resources = new BehaviorSubject([]);
this._holidays = new BehaviorSubject([]);
this._weekends = new BehaviorSubject([]);
/**
* Event emitted when a date range is selected.
*/
this.dateRangeSelect = new EventEmitter();
/**
* Event emitted when an event is selected.
*/
this.eventSelect = new EventEmitter();
/**
* Event emitted when the date range changes.
*/
this.dateRangeChange = new EventEmitter();
this.startOf = null;
}
/**
* Input property for setting the list of events in the resource scheduler.
* @param value The events to be set in the scheduler.
*/
set events(value) {
if (value == null) {
this._events.next([]);
}
else {
this._events.next(value);
}
}
get events() {
return this._events.value;
}
/**
* Input property for setting the list of resources in the resource scheduler.
* @param value The resources to be set in the scheduler.
*/
set resources(value) {
if (value == null) {
this._resources.next([]);
}
else {
this._resources.next(value);
}
}
get resources() {
return this._resources.value;
}
/**
* Input property for setting the list of holidays in the resource scheduler.
* @param value The holidays to be set in the scheduler.
*/
set holidays(value) {
if (value == null) {
this._holidays.next([]);
}
else {
this._holidays.next(value);
}
}
get holidays() {
return this._holidays.value;
}
/**
* Input property for setting the list of weekends in the resource scheduler.
* @param value The weekends to be set in the scheduler.
*/
set weekends(value) {
if (value == null) {
this._weekends.next([]);
}
else {
this._weekends.next(value);
}
}
get weekends() {
return this._weekends.value;
}
resourceChanges() {
return this._resources.asObservable();
}
eventChanges() {
return this._events.asObservable();
}
holidayChanges() {
return this._holidays.asObservable();
}
weekendChanges() {
return this._weekends.asObservable();
}
onEventSelect(e) {
this.eventSelect.emit(e);
}
onDateRangeSelect(e) {
this.dateRangeSelect.next(e);
}
;
onDateRangeChange(e) {
this.dateRangeChange.emit(e);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.7", ngImport: i0, type: ADCResourceSchedulerSource, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.7", type: ADCResourceSchedulerSource, isStandalone: true, selector: "[ResourceSchedulerSource]", inputs: { events: "events", resources: "resources", holidays: "holidays", weekends: "weekends", startOf: "startOf" }, outputs: { dateRangeSelect: "dateRangeSelect", eventSelect: "eventSelect", dateRangeChange: "dateRangeChange" }, ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.7", ngImport: i0, type: ADCResourceSchedulerSource, decorators: [{
type: Directive,
args: [{
selector: '[ResourceSchedulerSource]',
standalone: true
}]
}], propDecorators: { dateRangeSelect: [{
type: Output,
args: ['dateRangeSelect']
}], eventSelect: [{
type: Output,
args: ['eventSelect']
}], dateRangeChange: [{
type: Output,
args: ['dateRangeChange']
}], events: [{
type: Input,
args: ['events']
}], resources: [{
type: Input,
args: ['resources']
}], holidays: [{
type: Input,
args: ["holidays"]
}], weekends: [{
type: Input,
args: ["weekends"]
}], startOf: [{
type: Input,
args: ['startOf']
}] } });
/**
* `ResourceSchedulerEventTools` provides utility methods to work with resource scheduler events, such as
* filtering events between a given date range.
*/
class ResourceSchedulerEventTools {
constructor() {
this.tools = new ADCDateTimeTools();
}
/**
* Filters and returns events that fall within the specified date range.
*
* The method checks each event's start and end dates against the provided range
* and returns events that overlap with the range, are contained within it,
* or completely span it.
*
* @param startDate The start date of the range in string format (e.g., 'YYYY-MM-DD').
* @param endDate The end date of the range in string format (e.g., 'YYYY-MM-DD').
* @param events The list of events to filter, or `null` if no events are provided.
*
* @returns An array of events that fall within the date range.
*/
getEventsBetweenDateRange(startDate, endDate, events) {
if (events == null)
return [];
const rangeStart = this.tools.dateOnly(startDate);
const rangeEnd = this.tools.dateOnly(endDate);
return events.filter((e) => {
const eventStart = this.tools.dateOnly(e.startDate);
const eventEnd = this.tools.dateOnly(e.endDate);
return eventStart >= rangeStart && eventStart <= rangeEnd ||
eventEnd >= rangeStart && eventEnd <= rangeEnd ||
eventStart < rangeStart && eventEnd > rangeEnd;
});
}
}
class ADCResourceSchedulerTools {
constructor() {
this.dateTime = new ADCDateTimeTools();
this.resourceScheduler = new ResourceSchedulerEventTools();
}
}
/**
* The `AdcResourceSchedulerBase` class provides the base functionality for resource schedulers.
* It manages date navigation, event changes, and resource updates. Derived classes are expected to
* implement specific handling for buttons, event changes, resource changes, and date range changes.
*/
class AdcResourceSchedulerBase {
constructor() {
this.destory$ = new Subject();
this.dateChangeService = inject(DateChangeService);
this.resourceSchedulerSource = inject(ADCResourceSchedulerSource);
this.isViewReady = false;
/**
* The date adapter used for formatting and managing date operations in the resouce scheduler.
*/
this.dateAdapter = inject(ADC_DATE_ADAPTER);
/**
* The date formatter used to format dates in the resource scheduler.
*/
this.dateFormatter = inject(ADC_DATE_FORMATTER);
/**
* Utility tools for working with resource scheduler data.
*/
this.tools = new ADCResourceSchedulerTools();
/**
* Optional labels used for localizing or customizing the text displayed in the resource scheduler.
*/
this.labels = inject(ADC_LABELS);
/**
* start of date provided in the scheduler component use it to set initial date range.
*/
this.startOf = this.resourceSchedulerSource.startOf;
this.options = inject(ADC_OPTIONS);
}
/**
* Initializes the resource scheduler by subscribing to date and resource changes, and setting up event handlers.
*/
init() {
this.initViewHanlder();
this.dateChangeService.onNext().pipe(takeUntil(this.destory$)).subscribe(() => {
this.isViewReady = false;
this.nextButtonHandler();
///this.dateChangesHandler();
//this.eventChangesHandler(undefined);
});
this.dateChangeService.onPrevious().pipe(takeUntil(this.destory$)).subscribe(() => {
this.isViewReady = false;
this.previousButtonHandler();
//this.dateChangesHandler();
//this.eventChangesHandler(undefined);
});
this.dateChangeService.onToday().pipe(takeUntil(this.destory$)).subscribe(() => {
this.isViewReady = false;
this.todayButtonHandler();
//this.dateChangesHandler();
//this.eventChangesHandler(undefined);
});
this.resourceSchedulerSource.resourceChanges().pipe(takeUntil(this.destory$)).subscribe((value) => {
this.isViewReady = false;
this.resourceChangesHandler(value);
//this.dateChangesHandler();
//this.eventChangesHandler(undefined);
});
this.resourceSchedulerSource.eventChanges().pipe(takeUntil(this.destory$)).subscribe((events) => {
if (!this.isViewReady)
return;
this.eventChangesHandler(events);
});
this.resourceSchedulerSource.holidayChanges().pipe(takeUntil(this.destory$)).subscribe((value) => {
this.holidaysChangesHandler(value);
//this.dateChangesHandler();
});
this.resourceSchedulerSource.weekendChanges().pipe(takeUntil(this.destory$)).subscribe((value) => {
this.weekendChangesHandler(value);
//this.dateChangesHandler();
});
}
/**
* Handles date range change events and forwards them to the resource scheduler source.
*
* @param e - The date range change event.
*/
dateRangeChange(e) {
this.resourceSchedulerSource.onDateRangeChange(e);
}
/**
* Handles date range select events and forwards them to the resource scheduler source.
*
* @param e - The date range select event.
*/
dateRangeSelect(e) {
this.resourceSchedulerSource.onDateRangeSelect(e);
}
/**
* Handles event select events and forwards them to the resource scheduler source.
*
* @param e - The event select event.
*/
eventClick(e) {
this.resourceSchedulerSource.onEventSelect(e);
}
/**
* Marks the view as ready to process events.
*
* Once this method is called:
* - The `eventChangesHandler` will be triggered immediately with the current list of events.
* - Subsequent updates to events will also be handled automatically until the view is marked as unready.
*
* @returns void
*/
markViewAsReady() {
this.isViewReady = true;
this.eventChangesHandler(this.resourceSchedulerSource.events);
}
/**
* Destroys the resource scheduler instance and cleans up any active subscriptions.
*/
destory() {
this.destory$.next();
}
}
class ADCWeekViewComponent extends AdcResourceSchedulerBase {
constructor() {
super();
this.week = 0;
this.year = 0;
this.daysOfWeek = ADCStaticValues.getDaysOfWeek();
this.title = '';
this.dateSplitter = this.dateFormatter.DateSplitter;
this.resources = [];
this.events = [];
this.rows = [];
this.startOfWeek = '';
this.endOfWeek = '';
this.weekends = [];
this.holidays = [];
this.commonService = new ADCCommonService(this.dateAdapter, this.labels);
this.today = this.dateAdapter.today();
this.selectionManager = new TableSelection(this.dateFilter);
this.eventBuilder = new FlatEventBuilder();
}
ngOnInit() {
super.init();
this.selectionManager.cellSelectionStream.subscribe(event => this.onDateRangeSelect(event.start, event.end));
this.eventBuilder.eventSelectionStream.subscribe(e => {
this.onEventClick(e.event, e.dom, e.jsEvent);
});
}
dateFilter(cell1, cell2) {
return cell1.rowValue == cell2.rowValue && cell2.columnValue >= cell1.columnValue;
}
initViewHanlder() {
if (this.startOf == null) {
this.todayButtonHandler();
}
else {
this.week = this.dateAdapter.getWeekOf(this.startOf);
this.year = this.dateAdapter.getYearOf(this.startOf);
this.calculateCurrentDate();
}
}
todayButtonHandler() {
this.week = this.dateAdapter.getCurrentWeek();
this.year = this.dateAdapter.getCurrentYear();
this.calculateCurrentDate();
}
previousButtonHandler() {
this.week--;
if (this.week < 1) {
this.year--;
this.week = this.dateAdapter.getWeeksOfYear(this.year) - 1;
}
this.calculateCurrentDate();
}
nextButtonHandler() {
this.week++;
const weeksOfYear = this.dateAdapter.getWeeksOfYear(this.year);
if (this.week >= weeksOfYear) {
this.year++;
this.week = 1;
}
this.calculateCurrentDate();
}
calculateCurrentDate() {
const start = this.dateAdapter.getDateOfDay(this.year, this.week, 0);
const end = this.dateAdapter.getDateOfDay(this.year, this.week, 6);
this.startOfWeek = this.dateAdapter.transformDate(+start.split(this.dateSplitter)[0], +start.split(this.dateSplitter)[1], +start.split(this.dateSplitter)[2]);
this.endOfWeek = this.dateAdapter.transformDate(+end.split(this.dateSplitter)[0], +end.split(this.dateSplitter)[1], +end.split(this.dateSplitter)[2]);
this.title = `${this.labels?.week || "Week"} ${this.week} ${this.labels?.year || "Year"} ${this.year}`;
this.dateChangesHandler();
super.dateRangeChange({ startDate: this.startOfWeek, endDate: this.endOfWeek });
}
eventChangesHandler(events) {
const tableEvents = [];
this.events = events;
const viewEvents = this.tools.resourceScheduler.getEventsBetweenDateRange(this.startOfWeek, this.endOfWeek, this.events);
viewEvents.forEach((e) => {
const rowIndex = this.rows.findIndex((r) => r.value == e.resourceId);
if (rowIndex == -1)
return;
const row = this.rows[rowIndex];
const startColumnIndex = row.columns.findIndex((c) => {
return this.tools.dateTime.dateOnly(c.value) == this.tools.dateTime.dateOnly(e.startDate);
});
const endColumnIndex = row.columns.findIndex((c) => {
return this.tools.dateTime.dateOnly(c.value) == this.tools.dateTime.dateOnly(e.endDate);
});
const startTime = +this.tools.dateTime.hourOrDefault(e.startTime, '00');
const endTime = +this.tools.dateTime.hourOrDefault(e.endTime, '24');
const cellEvent = {
columnStart: startColumnIndex != -1 ? startColumnIndex : null,
columnEnd: endColumnIndex != -1 ? endColumnIndex : null,
data: e,
rowStart: rowIndex,
rowEnd: rowIndex,
offsetX: startTime / 24,
fractionX: e.allDay == true ? 1 : (endTime / 24),
overlapTolerance: this.options.eventOverlapTolerance / 24
};
tableEvents.push(cellEvent);
});
this.eventBuilder.data = tableEvents;
}
resourceChangesHandler(resources) {
this.resources = resources;
this.dateChangesHandler();
}
dateChangesHandler() {
this.rows = this.getRowIntialValue();
if (this.resources.length == 0)
return;
this.resources.forEach((resource, rowIndex) => {
const row = {
classList: '',
label: resource.title,
prefix: '',
suffix: '',
value: resource.id.toString(),
verticalAlign: 'center',
horizontalAlign: 'center',
columns: []
};
this.daysOfWeek.forEach((day, dayIndex) => {
const date = this.getDate(dayIndex);
const column = {
label: '',
classList: '',
prefix: '',
suffix: '',
value: date.transformedDate.split('T')[0],
verticalAlign: 'center',
horizontalAlign: 'center',
selectable: true,
};
row.columns.push(column);
});
this.rows.push(row);
});
}
holidaysChangesHandler(holidays) {
this.holidays = holidays;
this.dateChangesHandler();
}
weekendChangesHandler(weekends) {
this.weekends = weekends;
this.dateChangesHandler();
}
onDateRangeSelect(start, end) {
const e = {
endDate: end.columnValue.toString(),
endTime: '00:00',
startDate: start.columnValue.toString(),
startTime: '00:00',
resourceId: start.rowValue
};
super.dateRangeSelect(e);
}
onEventClick(event, dom, jsEvent) {
const resourceSchedulerEvent = this.events.filter(item => item.id == event.data.id)[0];
super.eventClick({ dom: dom, jsEvent: jsEvent, event: resourceSchedulerEvent });
}
getDate(dayOfWeek) {
const date = this.dateAdapter.getDateOfDay(this.year, this.week, dayOfWeek);
const changedDate = this.dateAdapter.transformDate(+date.split(this.dateSplitter)[0], +date.split(this.dateSplitter)[1], +date.split(this.dateSplitter)[2]);
return { date: date, transformedDate: changedDate };
}
ngOnDestroy() {
super.destory();
}
getRowIntialValue() {
const row = {
verticalAlign: 'center',
horizontalAlign: 'center',
classList: '',
columns: [],
label: '',
prefix: '',
suffix: '',
value: ''
};
this.daysOfWeek.forEach((day, dayIndex) => {
const date = this.getDate(dayIndex);
const dIndex = this.commonService.getDayIndex(dayIndex);
const column = {
label: this.labels?.daysOfWeek[dIndex] || day,
classList: ''.concat(date.transformedDate.split('T')[0] == this.today ? ' today ' : ' ', this.weekends.includes(dayIndex) || this.holidays.includes(date.transformedDate.split('T')[0]) ? ' holiday ' : ' '),
prefix: '',
suffix: date.date.split(this.dateSplitter)[1] + this.dateSplitter + date.date.split(this.dateSplitter)[2],
value: dayIndex.toString(),
verticalAlign: 'center',
horizontalAlign: 'center',
selectable: false,
};
row.columns.push(column);
});
return [row];
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.7", ngImport: i0, type: ADCWeekViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.0.7", type: ADCWeekViewComponent, selector: "adc-week-view", usesInheritance: true, ngImport: i0, template: "<ng-container *ngIf=\"resources.length != 0\">\r\n <adc-table\r\n [rows]=\"rows\"\r\n [title]=\"title\" \r\n [selectionManager]=\"selectionManager\"\r\n [eventBuilder]=\"eventBuilder\"\r\n (viewReady)=\"markViewAsReady()\"\r\n ></adc-table>\r\n</ng-container>", styles: [".w-full{width:100%}.table-layout-fixed{table-layout:fixed}.border-collapse{border-collapse:collapse}.h-12{height:3rem}.text-center{text-align:center}.events{height:100%;width:100%;overflow:visible;padding:0;margin:0}.h-1152{height:1152px}.over-flow-hidden{overflow:hidden}table{border-spacing:0}\n"], dependencies: [{ kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2.ADCTableComponent, selector: "adc-table", inputs: ["rows", "showRowDetails", "title", "titleClass", "eventBuilder", "selectionManager"], outputs: ["viewReady"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.7", ngImport: i0, type: ADCWeekViewComponent, decorators: [{
type: Component,
args: [{ selector: 'adc-week-view', template: "<ng-container *ngIf=\"resources.length != 0\">\r\n <adc-table\r\n [rows]=\"rows\"\r\n [title]=\"title\" \r\n [selectionManager]=\"selectionManager\"\r\n [eventBuilder]=\"eventBuilder\"\r\n (viewReady)=\"markViewAsReady()\"\r\n ></adc-table>\r\n</ng-container>", styles: [".w-full{width:100%}.table-layout-fixed{table-layout:fixed}.border-collapse{border-collapse:collapse}.h-12{height:3rem}.text-center{text-align:center}.events{height:100%;width:100%;overflow:visible;padding:0;margin:0}.h-1152{height:1152px}.over-flow-hidden{overflow:hidden}table{border-spacing:0}\n"] }]
}], ctorParameters: () => [] });
class ADCMonthViewComponent extends AdcResourceSchedulerBase {
constructor() {
super();
this.month = 0;
this.year = 0;
this.daysOfWeek = ADCStaticValues.getDaysOfWeek();
this.monthsOfYear = this.dateAdapter.getMonthsOfYear();
this.weeksOfMonth = [];
this.title = '';
this.dateSplitter = this.dateFormatter.DateSplitter;
this.resources = [];
this.events = [];
this.rows = [];
this.startOfMonth = '';
this.endOfMonth = '';
this.weekends = [];
this.holidays = [];
this.commonService = new ADCCommonService(this.dateAdapter, this.labels);
this.today = this.dateAdapter.today();
this.selectionManager = new TableSelection(this.dateFilter);
this.eventBuilder = new FlatEventBuilder();
}
ngOnInit() {
super.init();
this.selectionManager.cellSelectionStream.subscribe(event => this.onDateRangeSelect(event.start, event.end));
this.eventBuilder.eventSelectionStream.subscribe(e => {
this.onEventClick(e.event, e.dom, e.jsEvent);
});
}
dateFilter(cell1, cell2) {
return cell1.rowValue == cell2.rowValue && cell2.columnValue >= cell1.columnValue;
}
initViewHanlder() {
if (this.startOf == null) {
this.todayButtonHandler();
}
else {
this.month = this.dateAdapter.getMonthOf(this.startOf);
this.year = this.dateAdapter.getYearOf(this.startOf);
this.calculateCurrentDate();
}
}
todayButtonHandler() {
this.month = this.dateAdapter.getCurrentMonth();
this.year = this.dateAdapter.getCurrentYear();
this.calculateCurrentDate();
}
previousButtonHandler() {
this.month--;
if (this.month < 1) {
this.month = 12;
this.year--;
}
this.calculateCurrentDate();
}
nextButtonHandler() {
this.month++;
if (this.month > 12) {
this.month = 1;
this.year++;
}
this.calculateCurrentDate();
}
calculateCurrentDate() {
this.weeksOfMonth = this.dateAdapter.getWeeksOfMonth(this.year, this.month);
this.startOfMonth = this.dateAdapter.transformDate(this.year, this.month, 1);
const daysOfMonth = this.dateAdapter.getDaysOfMonth(this.year, this.month);
this.endOfMonth = this.dateAdapter.transformDate(this.year, this.month, daysOfMonth);
const month = this.monthsOfYear[this.month - 1];
this.title = this.commonService.getMonthName(month) || month + ' ' + this.year;
this.dateChangesHandler();
super.dateRangeChange({ startDate: this.startOfMonth, endDate: this.endOfMonth });
}
eventChangesHandler(events) {
const tableEvents = [];
this.events = events;
const viewEvents = this.tools.resourceScheduler.getEventsBetweenDateRange(this.startOfMonth, this.endOfMonth, this.events);
viewEvents.forEach((e) => {
const rowIndex = this.rows.findIndex((r) => r.value == e.resourceId);
if (rowIndex == -1)
return;
const row = this.rows[rowIndex];
const startColumnIndex = row.columns.findIndex((c) => {
return this.tools.dateTime.dateOnly(c.value.toString()) == this.tools.dateTime.dateOnly(e.startDate);
});
const endColumnIndex = row.columns.findIndex((c) => {
return this.tools.dateTime.dateOnly(c.value.toString()) == this.tools.dateTime.dateOnly(e.endDate);
});
const startTime = +this.tools.dateTime.hourOrDefault(e.startTime, '00');
const endTime = +this.tools.dateTime.hourOrDefault(e.endTime, '24');
const cellEvent = {
columnStart: startColumnIndex != -1 ? startColumnIndex : null,
columnEnd: endColumnIndex != -1 ? endColumnIndex : null,
data: e,
rowStart: rowIndex,
rowEnd: rowIndex,
offsetX: startTime / 24,
fractionX: e.allDay == true ? 1 : (endTime / 24),
overlapTolerance: this.options.eventOverlapTolerance / 24
};
tableEvents.push(cellEvent);
});
this.eventBuilder.data = tableEvents;
}
resourceChangesHandler(resources) {
this.resources = resources;
this.dateChangesHandler();
}
dateChangesHandler() {
this.rows = this.getRowInitialValue();
if (this.resources.length == 0)
return;
this.resources.forEach((resource, rowIndex) => {
const row = {
label: resource.title,
classList: '',
prefix: '',
suffix: '',
value: resource.id.toString(),
verticalAlign: 'center',
horizontalAlign: 'center',
columns: [],
};
this.weeksOfMonth.forEach((week, weekIndex) => {
this.daysOfWeek.forEach((day, dayIndex) => {
const date = this.dateAdapter.getDateOfDay(this.year, +week, dayIndex);
const splittedDate = date.split(this.dateSplitter);
const transformedDate = this.dateAdapter.transformDate(+splittedDate[0], +splittedDate[1], +splittedDate[2]);
if (+splittedDate[1] != this.month)
return;
row.columns.push({
label: '',
classList: '',
prefix: '',
suffix: '',
value: transformedDate.split('T')[0],
verticalAlign: 'center',
horizontalAlign: 'center',
selectable: true
});
});
});
this.rows.push(row);
});
}
holidaysChangesHandler(holidays) {
this.holidays = holidays;
this.dateChangesHandler();
}
weekendChangesHandler(weekends) {
this.weekends = weekends;
this.dateChangesHandler();
}
onDateRangeSelect(start, end) {
const e = {
endDate: end.columnValue.split('T')[0],
endTime: '00:00',
startDate: start.columnValue.split('T')[0],
startTime: '00:00',
resourceId: start.rowValue
};
super.dateRangeSelect(e);
}
onEventClick(event, dom, jsEvent) {
const resourceSchedulerEvent = this.events.filter(item => item.id == event.data.id)[0];
super.eventClick({ dom: dom, jsEvent: jsEvent, event: resourceSchedulerEvent });
}
ngOnDestroy() {
super.destory();
}
getRowInitialValue() {
const row = {
verticalAlign: 'center',
horizontalAlign: 'center',
classList: '',
label: '',
prefix: '',
suffix: '',
value: '',
columns: [],
};
this.weeksOfMonth.forEach((week, weekIndex) => {
this.daysOfWeek.forEach((day, dayIndex) => {
const date = this.dateAdapter.getDateOfDay(this.year, +week, dayIndex);
const splittedDate = date.split(this.dateSplitter);
const transformedDate = this.dateAdapter.transformDate(+splittedDate[0], +splittedDate[1], +splittedDate[2]);
const dIndex = this.commonService.getDayIndex(dayIndex);
if (+splittedDate[1] != this.month)
return;
row.columns.push({
label: this.labels?.daysOfWeek[dIndex] || day,
classList: ''.concat(transformedDate.split('T')[0] == this.today ? ' today ' : ' ', this.weekends.includes(dayIndex) || this.holidays.includes(transformedDate.split('T')[0]) ? ' holiday ' : ' '),
prefix: '',
suffix: date.split(this.dateSplitter)[1] + this.dateSplitter + date.split(this.dateSplitter)[2],
value: dayIndex.toString(),
verticalAlign: 'center',
horizontalAlign: 'center',
selectable: false
});
});
});
return [row];
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.7", ngImport: i0, type: ADCMonthViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.0.7", type: ADCMonthViewComponent, selector: "adc-month-view", usesInheritance: true, ngImport: i0, template: "<ng-container *ngIf=\"resources.length != 0\">\r\n <adc-table\r\n [rows]=\"rows\"\r\n [title]=\"title\" \r\n [selectionManager]=\"selectionManager\"\r\n [eventBuilder]=\"eventBuilder\"\r\n (viewReady)=\"markViewAsReady()\"\r\n ></adc-table>\r\n</ng-container>\r\n\r\n\r\n\r\n\r\n\r\n", styles: [".w-full{width:100%}.table-layout-fixed{table-layout:fixed}.border-collapse{border-collapse:collapse}.h-12{height:3rem}.text-center{text-align:center}.events{height:100%;width:100%;overflow:visible;padding:0;margin:0}.h-1152{height:1152px}.over-flow-hidden{overflow:hidden}table{border-spacing:0}\n"], dependencies: [{ kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2.ADCTableComponent, selector: "adc-table", inputs: ["rows", "showRowDetails", "title", "titleClass", "eventBuilder", "selectionManager"], outputs: ["viewReady"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.7", ngImport: i0, type: ADCMonthViewComponent, decorators: [{
type: Component,
args: [{ selector: 'adc-month-view', template: "<ng-container *ngIf=\"resources.length != 0\">\r\n <adc-table\r\n [rows]=\"rows\"\r\n [title]=\"title\" \r\n [selectionManager]=\"selectionManager\"\r\n [eventBuilder]=\"eventBuilder\"\r\n (viewReady)=\"markViewAsReady()\"\r\n ></adc-table>\r\n</ng-container>\r\n\r\n\r\n\r\n\r\n\r\n", styles: [".w-full{width:100%}.table-layout-fixed{table-layout:fixed}.border-collapse{border-collapse:collapse}.h-12{height:3rem}.text-center{text-align:center}.events{height:100%;width:100%;overflow:visible;padding:0;margin:0}.h-1152{height:1152px}.over-flow-hidden{overflow:hidden}table{border-spacing:0}\n"] }]
}], ctorParameters: () => [] });
class ADCDayViewComponent extends AdcResourceSchedulerBase {
constructor() {
super();
this.year = 0;
this.week = 0;
this.day = 0;
this.currentDate = '';
this.title = '';
this.hoursOfDay = ADCStaticValues.getHoursOfDay();
this.daysOfweek = ADCStaticValues.getDaysOfWeek();
this.monthsOfYear = this.dateAdapter.getMonthsOfYear();
this.dateSplitter = this.dateFormatter.DateSplitter;
this.resources = [];
this.events = [];
this.rows = [];
this.weekends = [];
this.holidays = [];
this.commonService = new ADCCommonService(this.dateAdapter, this.labels);
this.today = this.dateAdapter.today();
this.selectionManager = new TableSelection(this.dateFilter);
this.eventBuilder = new FlatEventBuilder();
}
ngOnInit() {
super.init();
this.selectionManager.cellSelectionStream.subscribe(event => this.onDateRangeSelect(event.start, event.end));
this.eventBuilder.eventSelectionStream.subscribe(e => {
this.onEventClick(e.event, e.dom, e.jsEvent);
});
}
dateFilter(cell1, cell2) {
return cell1.rowValue == cell2.rowValue && cell2.columnValue >= cell1.columnValue;
}
initViewHanlder() {
if (this.startOf == null) {
this.todayButtonHandler();
}
else {
this.day = this.dateAdapter.getDayIndexOf(this.startOf);
this.week = this.dateAdapter.getWeekOf(this.startOf);
this.year = this.dateAdapter.getYearOf(this.startOf);
this.calculateCurrentDate();
}
}
todayButtonHandler() {
this.day = this.dateAdapter.getCurrentDay();
this.week = this.dateAdapter.getCurrentWeek();
this.year = this.dateAdapter.getCurrentYear();
this.calculateCurrentDate();
}
previousButtonHandler() {
this.day--;
if (this.day < 0) {
this.day = 6;
this.week--;
if (this.week < 1) {
this.year--;
this.week = this.dateAdapter.getWeeksOfYear(this.year);
}
}
this.calculateCurrentDate();
}
nextButtonHandler() {
this.day++;
if (this.day > 6) {
this.day = 0;
this.week++;
const weeksOfYear = this.dateAdapter.getWeeksOfYear(this.year);
if (this.week > weeksOfYear) {
this.week = 1;
this.year++;
}
}
this.calculateCurrentDate();
}
calculateCurrentDate() {
const date = this.dateAdapter.getDateOfDay(this.year, this.week, this.day);
this.currentDate = this.dateAdapter.transformDate(+date.split(this.dateSplitter)[0], +date.split(this.dateSplitter)[1], +date.split(this.dateSplitter)[2]);
const dayIndex = this.commonService.getDayIndex(this.day);
const month = this.monthsOfYear[+date.split(this.dateSplitter)[1] - 1];
this.title = `${this.labels?.daysOfWeek[dayIndex] || this.daysOfweek[dayIndex]}
${+date.split(this.dateSplitter)[2]}
${this.commonService.getMonthName(month) || month} ${this.labels?.year || "Year"}
${this.year}`;
this.dateChangesHandler();
super.dateRangeChange({ startDate: this.currentDate, endDate: this.currentDate });
}
eventChangesHandler(events) {
const tableEvents = [];
this.events = events;
const viewEvents = this.tools.resourceScheduler.getEventsBetweenDateRange(this.currentDate, this.currentDate, this.events);
viewEvents.forEach((e) => {
const rowIndex = this.rows.findIndex((r) => r.value == e.resourceId);
if (rowIndex == -1)
return;
const row = this.rows[rowIndex];
const startColumnIndex = row.columns.findIndex((c) => {
const time = this.tools.dateTime.timeOnly(c.value);
const date = this.tools.dateTime.dateOnly(c.value);
return date == this.tools.dateTime.dateOnly(e.startDate) &&
this.tools.dateTime.hour(time) == this.tools.dateTime.hourOrDefault(e.startTime, '00');
});
const endColumnIndex = row.columns.findIndex((c) => {
const time = this.tools.dateTime.timeOnly(c.value);
const date = this.tools.dateTime.dateOnly(c.value);
return date == this.tools.dateTime.dateOnly(e.endDate) &&
this.tools.dateTime.hour(time) == this.tools.dateTime.hourOrDefault(e.endTime, '23');
});
const startTime = +this.tools.dateTime.minutesOrDefault(e.startTime, '00');
const endTime = +this.tools.dateTime.minutesOrDefault(e.endTime, '60');
const currentDateOnly = this.tools.dateTime.dateOnly(this.currentDate);
const cellEvent = {
columnStart: startColumnIndex != -1 ? startColumnIndex : null,
columnEnd: endColumnIndex != -1 ? endColumnIndex : null,
data: e,
rowStart: rowIndex,
rowEnd: rowIndex,
offsetX: this.tools.dateTime.dateOnly(e.startDate) == currentDateOnly ? startTime / 60 : 0,
fractionX: endTime / 60,
overlapTolerance: this.options.eventOverlapTolerance / 60
};
if (e.allDay == true) {
const eventHourEnd = +this.tools.dateTime.hourOrDefault(e.endTime, '23');
const eventMinuteEnd = +this.tools.dateTime.minutesOrDefault(e.endTime, '00');
cellEvent.fractionX = 24 - eventHourEnd + (eventMinuteEnd / 60);
}
tableEvents.push(cellEvent);
});
this.eventBuilder.data = tableEvents;
}
resourceChangesHandler(resources) {
this.resources = resources;
this.dateChangesHandler();
}
dateChangesHandler() {
this.rows = this.getRowInitialValue();
if (this.resources.length == 0)
return;
const date = this.dateAdapter.getDateOfDay(this.year, this.week, this.day).split(this.dateSplitter);
const transformedDate = this.dateAdapter.transformDate(+date[0], +date[1], +date[2]).split('T')[0];
this.resources.forEach((resource, rowIndex) => {
const row = {
classList: '',
label: resource.title,
prefix: '',
suffix: '',
value: resource.id.toString(),
verticalAlign: 'center',
horizontalAlign: 'center',
columns: [],
};
this.hoursOfDay.forEach((hour) => {
const column = {
classList: '',
label: '',
prefix: '',
suffix: '',
value: `${transformedDate}T${hour}`,
verticalAlign: 'center',
horizontalAlign: 'center',
selectable: true,
};
row.columns.push(column);
});
this.rows.push(row);
});
}
holidaysChangesHandler(holidays) {
this.holidays = holidays;
this.dateChangesHandler();
}
weekendChangesHandler(weekends) {
this.weekends = weekends;
this.dateChangesHandler();
}
onDateRangeSelect(start, end) {
const e = {
endDate: end.columnValue.split('T')[0],
endTime: end.columnValue.split('T')[1],
startDate: start.columnValue.split('T')[0],
startTime: start.columnValue.split('T')[1],
resourceId: start.rowValue
};
super.dateRangeSelect(e);
}
onEventClick(event, dom, jsEvent) {
const resourceSchedulerEvent = this.events.filter(item => item.id == event.data.id)[0];
super.eventClick({ dom: dom, jsEvent: jsEvent, event: resourceSchedulerEvent });
}
ngOnDestroy() {
super.destory();
}
getRowInitialValue() {
const row = {
verticalAlign: 'center',
horizontalAlign: 'center',
classList: '',
columns: [],
label: '',
prefix: '',
suffix: '',
value: '',
};
this.hoursOfDay.forEach((hour) => {
const column = {
classList: '',
label: hour,
prefix: '',
suffix: '',
value: hour,
verticalAlign: 'center',
horizontalAlign: 'center',
selectable: false,
};
row.columns.push(column);
});
return [row];
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.7", ngImport: i0, type: ADCDayViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.0.7", type: ADCDayViewComponent, selector: "adc-day-view", usesInheritance: true, ngImport: i0, template: "<ng-container *ngIf=\"resources.length != 0\">\r\n <adc-table\r\n [rows]=\"rows\"\r\n [title]=\"title\"\r\n [titleClass]=\"''.concat(\r\n today == currentDate.split('T')[0] ? ' today ' : ' ',\r\n weekends.includes(day) || holidays.includes(currentDate.split('T')[0]) ? ' holiday ' : ' '\r\n )\"\r\n [selectionManager]=\"selectionManager\"\r\n [eventBuilder]=\"eventBuilder\"\r\n (viewReady)=\"markViewAsReady()\"\r\n ></adc-table>\r\n</ng-container>", styles: [".w-full{width:100%}.table-layout-fixed{table-layout:fixed}.border-collapse{border-collapse:collapse}.h-12{height:3rem}.text-center{text-align:center}.events{height:100%;width:100%;overflow:visible;padding:0;margin:0}.h-1152{height:1152px}.over-flow-hidden{overflow:hidden}table{border-spacing:0}\n"], dependencies: [{ kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2.ADCTableComponent, selector: "adc-table", inputs: ["rows", "showRowDetails", "title", "titleClass", "eventBuilder", "selectionManager"], outputs: ["viewReady"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.7", ngImport: i0, type: ADCDayViewComponent, decorators: [{
type: Component,
args: [{ selector: 'adc-day-view', template: "<ng-container *ngIf=\"resources.length != 0\">\r\n <adc-table\r\n [rows]=\"rows\"\r\n [title]=\"title\"\r\n [titleClass]=\"''.concat(\r\n today == currentDate.split('T')[0] ? ' today ' : ' ',\r\n weekends.includes(day) || holidays.includes(currentDate.split('T')[0]) ? ' holiday ' : ' '\r\n )\"\r\n [selectionManager]=\"selectionManager\"\r\n [eventBuilder]=\"eventBuilder\"\r\n (viewReady)=\"markViewAsReady()\"\r\n ></adc-table>\r\n</ng-container>", styles: [".w-full{width:100%}.table-layout-fixed{table-layout:fixed}.border-collapse{border-collapse:collapse}.h-12{height:3rem}.text-center{text-align:center}.events{height:100%;width:100%;overflow:visible;padding:0;margin:0}.h-1152{height:1152px}.over-flow-hidden{overflow:hidden}table{border-spacing:0}\n"] }]
}], ctorParameters: () => [] });
class AdcResourceSchedulerModule {
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.7", ngImport: i0, type: AdcResourceSchedulerModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "17.0.7", ngImport: i0, type: AdcResourceSchedulerModule, declarations: [ADCWeekViewComponent,
ADCMonthViewComponent,
ADCDayViewComponent], imports: [CommonModule,
ADCTableComponent], exports: [ADCWeekViewComponent,
ADCMonthViewComponent,
ADCDayViewComponent] }); }
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "17.0.7", ngImport: i0, type: AdcResourceSchedulerModule, imports: [CommonModule,
ADCTableComponent] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.7", ngImport: i0, type: AdcResourceSchedulerModule, decorators: [{
type: NgModule,
args: [{
declarations: [
ADCWeekViewComponent,
ADCMonthViewComponent,
ADCDayViewComponent
],
imports: [
CommonModule,
ADCTableComponent,
],
exports: [
ADCWeekViewComponent,
ADCMonthViewComponent,
ADCDayViewComponent
]
}]
}] });
const defaultViews = ['month', 'week', 'day'];
/**
* The ADCResourceSchedulerComponent is responsible for rendering a resource scheduler view.
* It supports different views (e.g., month, week, day) and handles navigation through date ranges.
* This component integrates with other services like date changes and event handling.
*
* ### Usage Example:
* ```html
* <adc-resource-scheduler
* [DefaultViews]="['month', 'week']"
* [CustomViews]="customViewsArray"
* (ViewChange)="handleViewChange($event)"
* (Next)="handleNext()"
* (Previous)="handlePrevious()">
* </adc-resource-scheduler>
* ```
*/
class ADCResourceSchedulerComponent {
/**
* The default views for the scheduler.
* This input accepts an array of view identifiers (e.g., 'month', 'week', 'day') to set the default views.
*
* @example
* ```html
* <adc-resource-scheduler [DefaultViews]="['month', 'week']"></adc-resource-scheduler>
* ```
*/
set defaultViews(value) {
this._defaultViews = value;
this.onViewSet();
}
get defaultViews() {
return this._defaultViews;
}
/**
* Custom views for the scheduler.
* This input allows you to provide custom views to display in the scheduler.
*
* @example
* ```html
* <adc-resource-scheduler [CustomViews]="customViewsArray"></adc-resource-scheduler>
* ```
*/
set customViews(value) {
this._customViews = value;
this.onViewSet();
}
get customViews() {
return this._customViews;
}
constructor(options, labels, dateChangeService) {
this.options = options;
this.labels = labels;
this.dateChangeService = dateChangeService;
this.currentView = this.options.initialView;
this.defaultViewComponents = [
{
id: 'month',
name: this.labels?.month || 'month',
component: ADCMonthViewComponent
},
{
id: 'week',
name: this.labels?.week || 'week',
component: ADCWeekViewComponent
},
{
id: 'day',
name: this.labels?.day || 'day',
component: ADCDayViewComponent
}
];
this.viewButtons = [];
this.resourceSchedulerViews = this.defaultViewComponents;
this._defaultViews = [];
this._customViews = [];
/**
* disables next button for resource scheduler component
*
* @example
* <adc-resource-scheduler disableNext></adc-resource-scheduler>
*/
this.disableNext = false;
/**
* disables previous button for resource scheduler component
*
* @example
* adc-resource-scheduler disablePrevious></adc-resource-scheduler>
*/
this.disablePrevious = false;
/**
* disables today button for resource scheduler component
*
* @example
* <adc-resource-scheduler disableToday></adc-resource-scheduler>
*/
this.disableToday = false;
/**
* Emitted when the view changes (e.g., month, week, or day).
* Use this output to capture the current view selection in the parent component.
*
* @event
* @example
* ```html
* <adc-resource-scheduler (viewChange)="onViewChange($event)"></adc-resource-scheduler>
* ```
*/
this.onViewChangeEvent = new EventEmitter();
/**
* Emitted when the "Next" button is clicked to navigate to the next date range.
*
* @event
* @example
* ```html
* <adc-resource-scheduler (next)="onNext()"></adc-resource-scheduler>
* ```
*/
this.onNextEvent = new EventEmitter();
/**
* Emitted when the "Previous" button is clicked to navigate to the previous date range.
*
* @event
* @example
* ```html
* <adc-resource-scheduler (previous)="onPrevious()"></adc-resource-scheduler>
* ```
*/
this.onPreviousEvent = new EventEmitter();
this.defaultViews = defaultViews;
}
onViewChange(view) {
this.currentView = view;
this.onViewChangeEvent.emit(view);
}
onPrevious() {
this.dateChangeService.previous();
this.onPreviousEvent.emit();
}
onNext() {
this.dateChangeService.next();
this.onNextEvent.emit();