UNPKG

@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
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();