|
1 | 1 | import { Component } from '@angular/core'; |
2 | | -import { ClickEvent } from 'devextreme/ui/button'; |
| 2 | +import notify from 'devextreme/ui/notify'; |
| 3 | +import { DxSchedulerTypes } from 'devextreme-angular/ui/scheduler'; |
| 4 | +import { |
| 5 | + AppointmentData, |
| 6 | + Holiday, |
| 7 | + DinnerTime, |
| 8 | + SchedulerView, |
| 9 | + DataCellTemplate, |
| 10 | +} from './app.types'; |
3 | 11 |
|
4 | 12 | @Component({ |
5 | 13 | selector: 'app-root', |
6 | 14 | templateUrl: './app.component.html', |
7 | 15 | styleUrls: ['./app.component.scss'], |
8 | 16 | }) |
9 | 17 | export class AppComponent { |
10 | | - title = 'Angular'; |
| 18 | + dataSource: AppointmentData[] = [ |
| 19 | + { |
| 20 | + text: 'Website Re-Design Plan', |
| 21 | + startDate: new Date(2021, 4, 5, 9, 30), |
| 22 | + endDate: new Date(2021, 4, 5, 11, 30), |
| 23 | + }, |
| 24 | + { |
| 25 | + text: 'Install New Router in Dev Room', |
| 26 | + startDate: new Date(2021, 4, 6, 13), |
| 27 | + endDate: new Date(2021, 4, 6, 14), |
| 28 | + }, |
| 29 | + { |
| 30 | + text: 'Approve Personal Computer Upgrade Plan', |
| 31 | + startDate: new Date(2021, 4, 3, 10), |
| 32 | + endDate: new Date(2021, 4, 3, 11), |
| 33 | + }, |
| 34 | + { |
| 35 | + text: 'Final Budget Review', |
| 36 | + startDate: new Date(2021, 4, 5, 13, 30), |
| 37 | + endDate: new Date(2021, 4, 5, 15), |
| 38 | + }, |
| 39 | + { |
| 40 | + text: 'New Brochures', |
| 41 | + startDate: new Date(2021, 4, 6, 15), |
| 42 | + endDate: new Date(2021, 4, 6, 16, 15), |
| 43 | + }, |
| 44 | + { |
| 45 | + text: 'Install New Database', |
| 46 | + startDate: new Date(2021, 4, 3, 9, 45), |
| 47 | + endDate: new Date(2021, 4, 3, 12), |
| 48 | + }, |
| 49 | + { |
| 50 | + text: 'Approve New Online Marketing Strategy', |
| 51 | + startDate: new Date(2021, 4, 3, 14, 30), |
| 52 | + endDate: new Date(2021, 4, 3, 16, 30), |
| 53 | + }, |
| 54 | + { |
| 55 | + text: 'Upgrade Personal Computers', |
| 56 | + startDate: new Date(2021, 4, 6, 15, 30), |
| 57 | + endDate: new Date(2021, 4, 6, 16, 45), |
| 58 | + }, |
| 59 | + { |
| 60 | + text: 'Prepare 2021 Marketing Plan', |
| 61 | + startDate: new Date(2021, 4, 3, 13), |
| 62 | + endDate: new Date(2021, 4, 3, 15), |
| 63 | + }, |
| 64 | + { |
| 65 | + text: 'Brochure Design Review', |
| 66 | + startDate: new Date(2021, 5, 1, 15, 30), |
| 67 | + endDate: new Date(2021, 5, 2), |
| 68 | + }, |
| 69 | + { |
| 70 | + text: 'Create Icons for Website', |
| 71 | + startDate: new Date(2021, 4, 5, 10), |
| 72 | + endDate: new Date(2021, 4, 5, 11), |
| 73 | + }, |
| 74 | + { |
| 75 | + text: 'Upgrade Server Hardware', |
| 76 | + startDate: new Date(2021, 4, 5, 16, 30), |
| 77 | + endDate: new Date(2021, 4, 5, 18), |
| 78 | + }, |
| 79 | + { |
| 80 | + text: 'Launch New Website', |
| 81 | + startDate: new Date(2021, 4, 5, 14, 30), |
| 82 | + endDate: new Date(2021, 4, 5, 16, 10), |
| 83 | + }, |
| 84 | + ]; |
11 | 85 |
|
12 | | - counter = 0; |
| 86 | + currentDate: Date = new Date(2021, 4, 3); |
13 | 87 |
|
14 | | - buttonText = 'Click count: 0'; |
| 88 | + views: SchedulerView[] = [ |
| 89 | + { |
| 90 | + type: 'timelineDay', |
| 91 | + intervalCount: 3, |
| 92 | + }, |
| 93 | + ]; |
15 | 94 |
|
16 | | - onClick(e: ClickEvent): void { |
17 | | - this.counter++; |
18 | | - this.buttonText = `Click count: ${this.counter}`; |
| 95 | + currentView = 'timelineDay'; |
| 96 | + |
| 97 | + startDayHour = 9; |
| 98 | + |
| 99 | + endDayHour = 19; |
| 100 | + |
| 101 | + cellDuration = 60; |
| 102 | + |
| 103 | + height = 600; |
| 104 | + |
| 105 | + private readonly dinnerTime: DinnerTime = { start: 12, end: 13 }; |
| 106 | + |
| 107 | + private readonly holiday: Holiday = { |
| 108 | + date: new Date(2021, 4, 4), |
| 109 | + name: 'Star Wars Day', |
| 110 | + }; |
| 111 | + |
| 112 | + isHoliday(startDate: Date, endDate: Date): boolean { |
| 113 | + return ( |
| 114 | + this.holiday.date.toLocaleDateString() === startDate.toLocaleDateString() |
| 115 | + && this.holiday.date.toLocaleDateString() === endDate.toLocaleDateString() |
| 116 | + ); |
| 117 | + } |
| 118 | + |
| 119 | + hasIntersection(startA: number, endA: number, startB: number, endB: number): boolean { |
| 120 | + if ( |
| 121 | + (startA <= startB && endB <= endA) |
| 122 | + || (startB <= startA && endA <= endB) |
| 123 | + ) { |
| 124 | + return true; |
| 125 | + } |
| 126 | + |
| 127 | + return ( |
| 128 | + (startA < startB && startB < endA) |
| 129 | + || (startA < endB && endB < endA) |
| 130 | + ); |
| 131 | + } |
| 132 | + |
| 133 | + isDinner(startDate: Date, endDate: Date): boolean { |
| 134 | + const todayDinnerStart = new Date(startDate).setHours(this.dinnerTime.start, 0, 0, 0); |
| 135 | + const todayDinnerEnd = new Date(endDate).setHours(this.dinnerTime.end, 0, 0, 0); |
| 136 | + |
| 137 | + return this.hasIntersection( |
| 138 | + todayDinnerStart, |
| 139 | + todayDinnerEnd, |
| 140 | + startDate.getTime(), |
| 141 | + endDate.getTime(), |
| 142 | + ); |
| 143 | + } |
| 144 | + |
| 145 | + onAppointmentChanging(e: any): void { |
| 146 | + const startDate = e.appointmentData |
| 147 | + ? new Date(e.appointmentData.startDate) |
| 148 | + : new Date(e.newData.startDate); |
| 149 | + |
| 150 | + const endDate = e.appointmentData |
| 151 | + ? new Date(e.appointmentData.endDate) |
| 152 | + : new Date(e.newData.endDate); |
| 153 | + |
| 154 | + if (!this.isValidAppointmentDate(startDate, endDate)) { |
| 155 | + e.cancel = true; |
| 156 | + this.notifyDisableDate(); |
| 157 | + } |
| 158 | + } |
| 159 | + |
| 160 | + onAppointmentFormOpening(e: any): void { |
| 161 | + const startDate = new Date(e.appointmentData.startDate); |
| 162 | + const endDate = new Date(e.appointmentData.endDate); |
| 163 | + |
| 164 | + if (!this.isValidAppointmentDate(startDate, endDate)) { |
| 165 | + e.cancel = true; |
| 166 | + this.notifyDisableDate(); |
| 167 | + } |
| 168 | + this.applyDisableDatesToDateEditors(e.form); |
| 169 | + } |
| 170 | + |
| 171 | + isValidAppointmentDate(startDate: Date, endDate: Date): boolean { |
| 172 | + return !this.isHoliday(startDate, endDate) && !this.isDinner(startDate, endDate); |
| 173 | + } |
| 174 | + |
| 175 | + applyDisableDatesToDateEditors(form: any): void { |
| 176 | + const holidayDate = this.holiday.date; |
| 177 | + |
| 178 | + const startDateEditor = form.getEditor('startDate'); |
| 179 | + startDateEditor.option('disabledDates', [holidayDate]); |
| 180 | + |
| 181 | + const endDateEditor = form.getEditor('endDate'); |
| 182 | + endDateEditor.option('disabledDates', [holidayDate]); |
| 183 | + } |
| 184 | + |
| 185 | + getCellText(cell: DataCellTemplate): string { |
| 186 | + const startDate = cell.startDate; |
| 187 | + const endDate = cell.endDate; |
| 188 | + |
| 189 | + const isHolidayCell = this.isHoliday(startDate, endDate); |
| 190 | + const isDinnerCell = this.isDinner(startDate, endDate); |
| 191 | + |
| 192 | + if (isHolidayCell) { |
| 193 | + return this.holiday.name; |
| 194 | + } |
| 195 | + if (isDinnerCell) { |
| 196 | + return 'Dinner Time'; |
| 197 | + } |
| 198 | + |
| 199 | + return cell.text; |
| 200 | + } |
| 201 | + |
| 202 | + notifyDisableDate(): void { |
| 203 | + notify( |
| 204 | + 'Cannot create or move an appointment/event to disabled time/date regions.', |
| 205 | + 'warning', |
| 206 | + 2000, |
| 207 | + ); |
19 | 208 | } |
20 | 209 | } |
0 commit comments