@smart-solutions-tech/smart-angular-calendar 0.0.3 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm2020/lib/components/calendar/calendar.component.mjs +10 -81
- package/esm2020/lib/components/day/day.component.mjs +92 -0
- package/esm2020/lib/components/duration-event/duration-event.component.mjs +56 -0
- package/esm2020/lib/components/smart-calendar/smart-calendar.component.mjs +180 -6
- package/esm2020/lib/smart-angular-calendar.module.mjs +9 -3
- package/esm2020/lib/translations.mjs +3 -1
- package/esm2020/lib/types.mjs +1 -1
- package/fesm2015/smart-solutions-tech-smart-angular-calendar.mjs +412 -168
- package/fesm2015/smart-solutions-tech-smart-angular-calendar.mjs.map +1 -1
- package/fesm2020/smart-solutions-tech-smart-angular-calendar.mjs +412 -168
- package/fesm2020/smart-solutions-tech-smart-angular-calendar.mjs.map +1 -1
- package/lib/components/calendar/calendar.component.d.ts +4 -25
- package/lib/components/day/day.component.d.ts +28 -0
- package/lib/components/duration-event/duration-event.component.d.ts +20 -0
- package/lib/components/smart-calendar/smart-calendar.component.d.ts +36 -2
- package/lib/smart-angular-calendar.module.d.ts +4 -2
- package/lib/types.d.ts +1 -0
- package/package.json +1 -1
|
@@ -55,6 +55,7 @@ const TRANSLATIONS = {
|
|
|
55
55
|
fri: 'Friday',
|
|
56
56
|
sat: 'Saturday',
|
|
57
57
|
today: 'Today',
|
|
58
|
+
allDayEvents: 'All-day events',
|
|
58
59
|
january: 'January',
|
|
59
60
|
february: 'February',
|
|
60
61
|
march: 'March',
|
|
@@ -79,6 +80,7 @@ const TRANSLATIONS = {
|
|
|
79
80
|
fri: 'Viernes',
|
|
80
81
|
sat: 'Sábado',
|
|
81
82
|
today: 'Hoy',
|
|
83
|
+
allDayEvents: 'Eventos de todo el día',
|
|
82
84
|
january: 'Enero',
|
|
83
85
|
february: 'Febrero',
|
|
84
86
|
march: 'Marzo',
|
|
@@ -186,6 +188,152 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
|
|
|
186
188
|
type: Output
|
|
187
189
|
}] } });
|
|
188
190
|
|
|
191
|
+
class CalendarComponent {
|
|
192
|
+
constructor() {
|
|
193
|
+
this.currentMonth = {
|
|
194
|
+
year: new Date().getFullYear(),
|
|
195
|
+
month: new Date().getMonth() + 1
|
|
196
|
+
};
|
|
197
|
+
this.events = [];
|
|
198
|
+
this.startAt = 'sunday';
|
|
199
|
+
this.dayCells = [];
|
|
200
|
+
this.weekDays = [
|
|
201
|
+
{ tag: 'sun' },
|
|
202
|
+
{ tag: 'mon' },
|
|
203
|
+
{ tag: 'tue' },
|
|
204
|
+
{ tag: 'wed' },
|
|
205
|
+
{ tag: 'thu' },
|
|
206
|
+
{ tag: 'fri' },
|
|
207
|
+
{ tag: 'sat' },
|
|
208
|
+
];
|
|
209
|
+
this.showMoreEventsModal = false;
|
|
210
|
+
this.moreEventsModalEvents = [];
|
|
211
|
+
this.resizeListener = () => {
|
|
212
|
+
this.setCalendarBodyHeight();
|
|
213
|
+
this.setMaxEventsInDayCell();
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
isToday(date) {
|
|
217
|
+
const today = new Date();
|
|
218
|
+
return date.getDate() === today.getDate() &&
|
|
219
|
+
date.getMonth() === today.getMonth() &&
|
|
220
|
+
date.getFullYear() === today.getFullYear();
|
|
221
|
+
}
|
|
222
|
+
getEventsForDay(date) {
|
|
223
|
+
return this.events.filter(event => {
|
|
224
|
+
const eventStart = new Date(event.start);
|
|
225
|
+
const eventEnd = event.end ? new Date(event.end) : eventStart;
|
|
226
|
+
return date >= new Date(eventStart.getFullYear(), eventStart.getMonth(), eventStart.getDate()) &&
|
|
227
|
+
date <= new Date(eventEnd.getFullYear(), eventEnd.getMonth(), eventEnd.getDate());
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
initDaysCells() {
|
|
231
|
+
const daysInMonth = new Date(this.currentMonth.year, this.currentMonth.month, 0).getDate();
|
|
232
|
+
const firstDayOfWeek = new Date(this.currentMonth.year, this.currentMonth.month - 1, 1).getDay();
|
|
233
|
+
const prevDaysCount = this.startAt === 'monday' ? (firstDayOfWeek === 0 ? 6 : firstDayOfWeek - 1) : firstDayOfWeek;
|
|
234
|
+
// const nextDaysCount = (7 - ((prevDaysCount + daysInMonth) % 7)) % 7;
|
|
235
|
+
const nextDaysCount = 42 - (prevDaysCount + daysInMonth); // Always show 6 weeks
|
|
236
|
+
this.dayCells = [];
|
|
237
|
+
for (let i = 0; i < prevDaysCount; i++) {
|
|
238
|
+
const date = new Date(this.currentMonth.year, this.currentMonth.month - 1, i - prevDaysCount + 1);
|
|
239
|
+
const _events = this.getEventsForDay(date);
|
|
240
|
+
this.dayCells.push({
|
|
241
|
+
date,
|
|
242
|
+
events: _events,
|
|
243
|
+
isOutsideMonth: true,
|
|
244
|
+
isToday: this.isToday(date)
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
for (let day = 1; day <= daysInMonth; day++) {
|
|
248
|
+
const date = new Date(this.currentMonth.year, this.currentMonth.month - 1, day);
|
|
249
|
+
const _events = this.getEventsForDay(date);
|
|
250
|
+
this.dayCells.push({
|
|
251
|
+
date,
|
|
252
|
+
events: _events,
|
|
253
|
+
isToday: this.isToday(date)
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
for (let i = 1; i <= nextDaysCount; i++) {
|
|
257
|
+
const date = new Date(this.currentMonth.year, this.currentMonth.month - 1, daysInMonth + i);
|
|
258
|
+
const _events = this.getEventsForDay(date);
|
|
259
|
+
this.dayCells.push({
|
|
260
|
+
date,
|
|
261
|
+
events: _events,
|
|
262
|
+
isOutsideMonth: true,
|
|
263
|
+
isToday: this.isToday(date)
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
setCalendarBodyHeight() {
|
|
268
|
+
this.calendarBodyHeight = this.calendarBodyRef.nativeElement.clientHeight;
|
|
269
|
+
}
|
|
270
|
+
setMaxEventsInDayCell() {
|
|
271
|
+
const element = document.getElementsByClassName('events-list')[0];
|
|
272
|
+
console.log(element);
|
|
273
|
+
if (element) {
|
|
274
|
+
const eventItemHeight = 22;
|
|
275
|
+
this.maxEventsInDayCell = Math.floor(element.clientHeight / eventItemHeight) - 1;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
openMoreEventsModal(date, events) {
|
|
279
|
+
this.moreEventsModalDate = date;
|
|
280
|
+
this.moreEventsModalEvents = events;
|
|
281
|
+
this.showMoreEventsModal = true;
|
|
282
|
+
}
|
|
283
|
+
closeMoreEventsModal() {
|
|
284
|
+
this.showMoreEventsModal = false;
|
|
285
|
+
this.moreEventsModalDate = undefined;
|
|
286
|
+
this.moreEventsModalEvents = [];
|
|
287
|
+
}
|
|
288
|
+
ngOnInit() {
|
|
289
|
+
if (this.startAt === 'monday') {
|
|
290
|
+
this.weekDays = [
|
|
291
|
+
{ tag: 'mon' },
|
|
292
|
+
{ tag: 'tue' },
|
|
293
|
+
{ tag: 'wed' },
|
|
294
|
+
{ tag: 'thu' },
|
|
295
|
+
{ tag: 'fri' },
|
|
296
|
+
{ tag: 'sat' },
|
|
297
|
+
{ tag: 'sun' },
|
|
298
|
+
];
|
|
299
|
+
}
|
|
300
|
+
this.initDaysCells();
|
|
301
|
+
}
|
|
302
|
+
ngAfterViewInit() {
|
|
303
|
+
window.addEventListener('resize', this.resizeListener);
|
|
304
|
+
setTimeout(() => {
|
|
305
|
+
this.setCalendarBodyHeight();
|
|
306
|
+
this.setMaxEventsInDayCell();
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
ngOnChanges(changes) {
|
|
310
|
+
if (changes['currentMonth']) {
|
|
311
|
+
this.initDaysCells();
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
onDestroy() {
|
|
315
|
+
window.removeEventListener('resize', this.resizeListener);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
CalendarComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: CalendarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
319
|
+
CalendarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: CalendarComponent, selector: "lib-calendar", inputs: { currentMonth: "currentMonth", events: "events", startAt: "startAt" }, viewQueries: [{ propertyName: "calendarRef", first: true, predicate: ["calendar"], descendants: true }, { propertyName: "calendarBodyRef", first: true, predicate: ["calendarBody"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"calendar-component\">\r\n <div class=\"body\" #calendarBody>\r\n <div class=\"week-days\">\r\n <div class=\"week-day\" *ngFor=\"let day of weekDays\">\r\n {{ day.tag | translate | slice:0:3 }}\r\n </div>\r\n </div>\r\n\r\n <div class=\"days-grid\">\r\n <div class=\"day-cell\" *ngFor=\"let day of dayCells; let i = index\"\r\n [ngClass]=\"{'outside-month': day.isOutsideMonth, 'is-today': day.isToday}\">\r\n <div class=\"day-number\">\r\n {{ day.date.getDate() }}\r\n </div>\r\n\r\n <div class=\"events-list\">\r\n <lib-calendar-event *ngFor=\"let event of day.events | slice:0:maxEventsInDayCell\"\r\n [event]=\"event\"></lib-calendar-event>\r\n\r\n <div class=\"more-events\" *ngIf=\"day.events.length > (maxEventsInDayCell || 0)\"\r\n (click)=\"openMoreEventsModal(day.date, day.events)\">\r\n {{'nMoreEvents' | translate: {n:(day.events.length - (maxEventsInDayCell || 0))} }}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"footer\">\r\n Footer\r\n </div>\r\n\r\n <lib-more-events-modal *ngIf=\"showMoreEventsModal && moreEventsModalDate\" [events]=\"moreEventsModalEvents\"\r\n [date]=\"moreEventsModalDate\" (close)=\"closeMoreEventsModal()\"\r\n (eventClick)=\"closeMoreEventsModal()\"></lib-more-events-modal>\r\n</div>", styles: ["*{box-sizing:border-box;margin:0;padding:0}.calendar-component{display:flex;flex-direction:column;width:100%;height:100%}.body{flex:1 1 0;display:flex;flex-direction:column;width:100%;min-height:0;height:100%}.week-days{flex-shrink:0;display:grid;grid-template-columns:repeat(7,1fr);width:100%;background-color:#f4f4f4}.week-day{display:flex;align-items:center;justify-content:center;padding:4px;background-color:#fff;font-size:14px;color:#00000080}.days-grid{flex:1 1 0;display:grid;grid-template-columns:repeat(7,1fr);gap:1px;grid-auto-rows:1fr;width:100%;padding:1px;background-color:#f4f4f4;min-height:0;height:100%}.day-cell{display:flex;flex-direction:column;gap:4px;padding:4px;background-color:#fff;overflow:hidden}.day-cell .day-number{display:flex;align-items:center;justify-content:center;width:fit-content;aspect-ratio:1;padding:2px;border-radius:50%;font-size:12px;line-height:16px;font-weight:600;-webkit-user-select:none;user-select:none}.day-cell.outside-month{background-color:#f8f8f8}.day-cell.is-today .day-number{background-color:#007bff;color:#fff}.day-cell .events-list{flex:1 1 auto;display:flex;flex-direction:column;gap:2px;overflow:hidden;min-height:0;max-height:100%}.day-cell .events-list .more-events{padding:2px 8px;border-radius:4px;font-size:12px;color:#555;cursor:pointer}.day-cell .events-list .more-events:hover{background-color:#eee}.footer{flex-shrink:0;background-color:#add8e6}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: CalendarEventComponent, selector: "lib-calendar-event", inputs: ["event"] }, { kind: "component", type: MoreEventsModalComponent, selector: "lib-more-events-modal", inputs: ["events", "date"], outputs: ["close", "eventClick"] }, { kind: "pipe", type: i1.SlicePipe, name: "slice" }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
|
|
320
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: CalendarComponent, decorators: [{
|
|
321
|
+
type: Component,
|
|
322
|
+
args: [{ selector: 'lib-calendar', template: "<div class=\"calendar-component\">\r\n <div class=\"body\" #calendarBody>\r\n <div class=\"week-days\">\r\n <div class=\"week-day\" *ngFor=\"let day of weekDays\">\r\n {{ day.tag | translate | slice:0:3 }}\r\n </div>\r\n </div>\r\n\r\n <div class=\"days-grid\">\r\n <div class=\"day-cell\" *ngFor=\"let day of dayCells; let i = index\"\r\n [ngClass]=\"{'outside-month': day.isOutsideMonth, 'is-today': day.isToday}\">\r\n <div class=\"day-number\">\r\n {{ day.date.getDate() }}\r\n </div>\r\n\r\n <div class=\"events-list\">\r\n <lib-calendar-event *ngFor=\"let event of day.events | slice:0:maxEventsInDayCell\"\r\n [event]=\"event\"></lib-calendar-event>\r\n\r\n <div class=\"more-events\" *ngIf=\"day.events.length > (maxEventsInDayCell || 0)\"\r\n (click)=\"openMoreEventsModal(day.date, day.events)\">\r\n {{'nMoreEvents' | translate: {n:(day.events.length - (maxEventsInDayCell || 0))} }}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"footer\">\r\n Footer\r\n </div>\r\n\r\n <lib-more-events-modal *ngIf=\"showMoreEventsModal && moreEventsModalDate\" [events]=\"moreEventsModalEvents\"\r\n [date]=\"moreEventsModalDate\" (close)=\"closeMoreEventsModal()\"\r\n (eventClick)=\"closeMoreEventsModal()\"></lib-more-events-modal>\r\n</div>", styles: ["*{box-sizing:border-box;margin:0;padding:0}.calendar-component{display:flex;flex-direction:column;width:100%;height:100%}.body{flex:1 1 0;display:flex;flex-direction:column;width:100%;min-height:0;height:100%}.week-days{flex-shrink:0;display:grid;grid-template-columns:repeat(7,1fr);width:100%;background-color:#f4f4f4}.week-day{display:flex;align-items:center;justify-content:center;padding:4px;background-color:#fff;font-size:14px;color:#00000080}.days-grid{flex:1 1 0;display:grid;grid-template-columns:repeat(7,1fr);gap:1px;grid-auto-rows:1fr;width:100%;padding:1px;background-color:#f4f4f4;min-height:0;height:100%}.day-cell{display:flex;flex-direction:column;gap:4px;padding:4px;background-color:#fff;overflow:hidden}.day-cell .day-number{display:flex;align-items:center;justify-content:center;width:fit-content;aspect-ratio:1;padding:2px;border-radius:50%;font-size:12px;line-height:16px;font-weight:600;-webkit-user-select:none;user-select:none}.day-cell.outside-month{background-color:#f8f8f8}.day-cell.is-today .day-number{background-color:#007bff;color:#fff}.day-cell .events-list{flex:1 1 auto;display:flex;flex-direction:column;gap:2px;overflow:hidden;min-height:0;max-height:100%}.day-cell .events-list .more-events{padding:2px 8px;border-radius:4px;font-size:12px;color:#555;cursor:pointer}.day-cell .events-list .more-events:hover{background-color:#eee}.footer{flex-shrink:0;background-color:#add8e6}\n"] }]
|
|
323
|
+
}], ctorParameters: function () { return []; }, propDecorators: { currentMonth: [{
|
|
324
|
+
type: Input
|
|
325
|
+
}], events: [{
|
|
326
|
+
type: Input
|
|
327
|
+
}], startAt: [{
|
|
328
|
+
type: Input
|
|
329
|
+
}], calendarRef: [{
|
|
330
|
+
type: ViewChild,
|
|
331
|
+
args: ['calendar']
|
|
332
|
+
}], calendarBodyRef: [{
|
|
333
|
+
type: ViewChild,
|
|
334
|
+
args: ['calendarBody']
|
|
335
|
+
}] } });
|
|
336
|
+
|
|
189
337
|
class TranslateMonthPipe {
|
|
190
338
|
constructor(translationService) {
|
|
191
339
|
this.translationService = translationService;
|
|
@@ -281,33 +429,157 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
|
|
|
281
429
|
type: Input
|
|
282
430
|
}] } });
|
|
283
431
|
|
|
284
|
-
class
|
|
432
|
+
class DurationEventComponent {
|
|
433
|
+
constructor() {
|
|
434
|
+
this.isDarkColor = false;
|
|
435
|
+
this.topPosition = 0;
|
|
436
|
+
this.height = 0;
|
|
437
|
+
this.isEventStartInThisDay = false;
|
|
438
|
+
this.isEventEndInThisDay = false;
|
|
439
|
+
}
|
|
440
|
+
ngOnInit() {
|
|
441
|
+
this.isDarkColor = isDarkColor(this.event.color || '#000000');
|
|
442
|
+
this.isEventStartInThisDay = this.getIsEventStartInThisDay();
|
|
443
|
+
this.isEventEndInThisDay = this.getIsEventEndInThisDay();
|
|
444
|
+
this.topPosition = this.getTopPosition();
|
|
445
|
+
this.height = this.getEventHeight();
|
|
446
|
+
}
|
|
447
|
+
getIsEventStartInThisDay() {
|
|
448
|
+
return this.event.start.getDate() === this.date.getDate() && this.event.start.getMonth() === this.date.getMonth() && this.event.start.getFullYear() === this.date.getFullYear();
|
|
449
|
+
}
|
|
450
|
+
getIsEventEndInThisDay() {
|
|
451
|
+
return this.event.end.getDate() === this.date.getDate() && this.event.end.getMonth() === this.date.getMonth() && this.event.end.getFullYear() === this.date.getFullYear();
|
|
452
|
+
}
|
|
453
|
+
getTopPosition() {
|
|
454
|
+
if (!this.isEventStartInThisDay)
|
|
455
|
+
return 0;
|
|
456
|
+
return this.event.start.getHours() * 60 + this.event.start.getMinutes();
|
|
457
|
+
}
|
|
458
|
+
getEventHeight() {
|
|
459
|
+
const max_minutes_in_day = 24 * 60;
|
|
460
|
+
if (!this.isEventStartInThisDay && !this.isEventEndInThisDay)
|
|
461
|
+
return max_minutes_in_day;
|
|
462
|
+
const result = (this.event.end.getTime() - this.event.start.getTime()) / (1000 * 60);
|
|
463
|
+
if (result < 20)
|
|
464
|
+
return 20;
|
|
465
|
+
if (!this.isEventStartInThisDay)
|
|
466
|
+
return (this.event.end.getTime() - new Date(this.date.getFullYear(), this.date.getMonth(), this.date.getDate(), 0, 0, 0).getTime()) / (1000 * 60);
|
|
467
|
+
const startPosition = this.getTopPosition();
|
|
468
|
+
if (startPosition + result > max_minutes_in_day)
|
|
469
|
+
return max_minutes_in_day - startPosition;
|
|
470
|
+
return result;
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
DurationEventComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: DurationEventComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
474
|
+
DurationEventComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: DurationEventComponent, selector: "lib-duration-event", inputs: { event: "event", date: "date" }, ngImport: i0, template: "<div class=\"duration-event-component\" style=\"--color: {{ event.color }};\" [style.top.px]=\"topPosition\"\n [style.height.px]=\"height\" [ngClass]=\"{'dark-color': isDarkColor}\" [title]=\"event.title\">\n <div class=\"event-title\">{{ event.title }}</div>\n</div>", styles: [".duration-event-component{position:absolute;left:0;z-index:1;width:100%;background-color:var(--color, rgba(0, 0, 0, .05));border-radius:4px;padding:2px 8px;cursor:pointer;-webkit-user-select:none;user-select:none;color:#212121}.duration-event-component.dark-color{color:#fafafa}.event-title{font-size:12px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
|
|
475
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: DurationEventComponent, decorators: [{
|
|
476
|
+
type: Component,
|
|
477
|
+
args: [{ selector: 'lib-duration-event', template: "<div class=\"duration-event-component\" style=\"--color: {{ event.color }};\" [style.top.px]=\"topPosition\"\n [style.height.px]=\"height\" [ngClass]=\"{'dark-color': isDarkColor}\" [title]=\"event.title\">\n <div class=\"event-title\">{{ event.title }}</div>\n</div>", styles: [".duration-event-component{position:absolute;left:0;z-index:1;width:100%;background-color:var(--color, rgba(0, 0, 0, .05));border-radius:4px;padding:2px 8px;cursor:pointer;-webkit-user-select:none;user-select:none;color:#212121}.duration-event-component.dark-color{color:#fafafa}.event-title{font-size:12px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n"] }]
|
|
478
|
+
}], ctorParameters: function () { return []; }, propDecorators: { event: [{
|
|
479
|
+
type: Input
|
|
480
|
+
}], date: [{
|
|
481
|
+
type: Input
|
|
482
|
+
}] } });
|
|
483
|
+
|
|
484
|
+
class DayComponent {
|
|
485
|
+
constructor() {
|
|
486
|
+
this.events = [];
|
|
487
|
+
this.hourBlocks = Array.from({ length: 24 }, (_, i) => i);
|
|
488
|
+
this.allDayEvents = [];
|
|
489
|
+
this.allDayHeight = 60;
|
|
490
|
+
this.eventCols = [];
|
|
491
|
+
this.resizing = false;
|
|
492
|
+
this.startY = 0;
|
|
493
|
+
this.startHeight = 0;
|
|
494
|
+
this.onResizeMouseMove = (event) => {
|
|
495
|
+
if (!this.resizing)
|
|
496
|
+
return;
|
|
497
|
+
const delta = event.clientY - this.startY;
|
|
498
|
+
const newHeight = this.startHeight + delta;
|
|
499
|
+
this.allDayHeight = Math.max(60, newHeight); // mínimo 80px
|
|
500
|
+
};
|
|
501
|
+
this.onResizeMouseUp = () => {
|
|
502
|
+
this.resizing = false;
|
|
503
|
+
document.removeEventListener('mousemove', this.onResizeMouseMove);
|
|
504
|
+
document.removeEventListener('mouseup', this.onResizeMouseUp);
|
|
505
|
+
};
|
|
506
|
+
}
|
|
507
|
+
ngOnInit() {
|
|
508
|
+
this.initEventCols();
|
|
509
|
+
}
|
|
510
|
+
findAvalailableColumn(event) {
|
|
511
|
+
for (let colIndex = 0; colIndex < this.eventCols.length; colIndex++) {
|
|
512
|
+
const col = this.eventCols[colIndex];
|
|
513
|
+
// conflict if event overlaps with any existing event in the column
|
|
514
|
+
const hasConflict = col.events.some(existingEvent => {
|
|
515
|
+
const startsDuringExisting = event.start < existingEvent.end && event.start >= existingEvent.start;
|
|
516
|
+
const endsDuringExisting = event.end > existingEvent.start && event.end <= existingEvent.end;
|
|
517
|
+
const spansExisting = event.start <= existingEvent.start && event.end >= existingEvent.end;
|
|
518
|
+
return startsDuringExisting || endsDuringExisting || spansExisting;
|
|
519
|
+
});
|
|
520
|
+
if (!hasConflict) {
|
|
521
|
+
return colIndex;
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
return this.eventCols.length;
|
|
525
|
+
}
|
|
526
|
+
addEventToEventCols(event) {
|
|
527
|
+
const colIndex = this.findAvalailableColumn(event);
|
|
528
|
+
if (colIndex === this.eventCols.length) {
|
|
529
|
+
this.eventCols.push({ events: [event] });
|
|
530
|
+
}
|
|
531
|
+
else {
|
|
532
|
+
this.eventCols[colIndex].events.push(event);
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
addEvent(event) {
|
|
536
|
+
if (event.allDay)
|
|
537
|
+
this.allDayEvents.push(event);
|
|
538
|
+
else
|
|
539
|
+
this.addEventToEventCols(event);
|
|
540
|
+
}
|
|
541
|
+
initEventCols() {
|
|
542
|
+
this.eventCols = [];
|
|
543
|
+
this.allDayEvents = [];
|
|
544
|
+
this.events.forEach(event => this.addEvent(event));
|
|
545
|
+
}
|
|
546
|
+
ngOnChanges(changes) {
|
|
547
|
+
if (changes['events']) {
|
|
548
|
+
this.initEventCols();
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
onResizeMouseDown(event) {
|
|
552
|
+
this.resizing = true;
|
|
553
|
+
this.startY = event.clientY;
|
|
554
|
+
this.startHeight = this.allDayHeight;
|
|
555
|
+
document.addEventListener('mousemove', this.onResizeMouseMove);
|
|
556
|
+
document.addEventListener('mouseup', this.onResizeMouseUp);
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
DayComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: DayComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
560
|
+
DayComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: DayComponent, selector: "lib-day", inputs: { events: "events", date: "date" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"day-view-component\">\n <section class=\"all-day-events\" [style.height.px]=\"allDayHeight\">\n <div class=\"header\">\n {{'allDayEvents' | translate}}\n </div>\n\n <div class=\"events-container\">\n <lib-calendar-event *ngFor=\"let event of allDayEvents\" [event]=\"event\"></lib-calendar-event>\n </div>\n </section>\n\n <div class=\"resize-divider\" (mousedown)=\"onResizeMouseDown($event)\"></div>\n\n <section class=\"duration-events\">\n <div class=\"hour-blocks\">\n <div class=\"hour-block\" *ngFor=\"let hour of hourBlocks\">\n <span>{{ hour }}:00</span>\n </div>\n </div>\n\n <div class=\"events-wrapper\">\n <div class=\"time-blocks\">\n <div class=\"time-block\" *ngFor=\"let hour of hourBlocks\">\n <div class=\"time-block-middle\"></div>\n </div>\n </div>\n\n <div class=\"events-container\" [style.gridTemplateColumns]=\"'repeat(' + eventCols.length + ', 1fr)'\">\n <div class=\"event-column\" *ngFor=\"let col of eventCols\">\n\n <lib-duration-event *ngFor=\"let event of col.events\" [event]=\"event\"\n [date]=\"date\"></lib-duration-event>\n\n </div>\n </div>\n </div>\n </section>\n</div>", styles: ["*{box-sizing:border-box;margin:0;padding:0}.day-view-component{display:flex;flex-direction:column;width:100%;height:100%;max-height:100%;overflow:hidden}section.all-day-events{position:relative;flex-shrink:0;display:flex;flex-direction:column;width:100%;min-height:60px;border-top:1px solid rgba(0,0,0,.12);overflow:auto}section.all-day-events .header{position:sticky;top:0;left:0;z-index:2;width:100%;flex-shrink:0;padding:2px 8px;background-color:#fff;font-size:12px;color:#000000b3;-webkit-user-select:none;user-select:none}section.all-day-events .events-container{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:4px;padding:4px}section.duration-events{flex-grow:1;display:flex;width:100%;overflow:auto}section.duration-events .hour-blocks{display:flex;flex-direction:column;width:45px;-webkit-user-select:none;user-select:none}section.duration-events .hour-blocks .hour-block{flex-shrink:0;height:60px;padding:4px;border:1px solid rgba(0,0,0,.12);border-top:none;font-size:12px;color:#00000080}section.duration-events .events-wrapper{position:relative;flex-grow:1;width:100%}section.duration-events .events-wrapper .time-blocks{position:absolute;top:0;left:0;width:100%;height:100%;z-index:0;display:flex;flex-direction:column}section.duration-events .events-wrapper .time-blocks .time-block{flex-shrink:0;height:60px;padding:4px;border-bottom:1px solid rgba(0,0,0,.12);border-top:none;font-size:12px;color:#00000080}section.duration-events .events-wrapper .time-blocks .time-block .time-block-middle{width:100%;height:50%;border-bottom:1px dashed rgba(0,0,0,.12)}section.duration-events .events-wrapper .events-container{display:grid;column-gap:1px}section.duration-events .events-wrapper .events-container .event-column{position:relative}.resize-divider{flex-shrink:0;width:100%;height:4px;background-color:#0000001f;cursor:row-resize;transition:transform .2s ease}.resize-divider:hover{z-index:5;background:repeating-linear-gradient(45deg,rgba(0,0,0,.12),rgba(0,0,0,.12) 4px,#ffffff 4px,#ffffff 8px);background-color:#fff;background-size:22px 8px;animation:stripe-move 1s linear infinite;transform:scaleY(2)}@keyframes stripe-move{0%{background-position:0 0}to{background-position:22px 0}}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: CalendarEventComponent, selector: "lib-calendar-event", inputs: ["event"] }, { kind: "component", type: DurationEventComponent, selector: "lib-duration-event", inputs: ["event", "date"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
|
|
561
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: DayComponent, decorators: [{
|
|
562
|
+
type: Component,
|
|
563
|
+
args: [{ selector: 'lib-day', template: "<div class=\"day-view-component\">\n <section class=\"all-day-events\" [style.height.px]=\"allDayHeight\">\n <div class=\"header\">\n {{'allDayEvents' | translate}}\n </div>\n\n <div class=\"events-container\">\n <lib-calendar-event *ngFor=\"let event of allDayEvents\" [event]=\"event\"></lib-calendar-event>\n </div>\n </section>\n\n <div class=\"resize-divider\" (mousedown)=\"onResizeMouseDown($event)\"></div>\n\n <section class=\"duration-events\">\n <div class=\"hour-blocks\">\n <div class=\"hour-block\" *ngFor=\"let hour of hourBlocks\">\n <span>{{ hour }}:00</span>\n </div>\n </div>\n\n <div class=\"events-wrapper\">\n <div class=\"time-blocks\">\n <div class=\"time-block\" *ngFor=\"let hour of hourBlocks\">\n <div class=\"time-block-middle\"></div>\n </div>\n </div>\n\n <div class=\"events-container\" [style.gridTemplateColumns]=\"'repeat(' + eventCols.length + ', 1fr)'\">\n <div class=\"event-column\" *ngFor=\"let col of eventCols\">\n\n <lib-duration-event *ngFor=\"let event of col.events\" [event]=\"event\"\n [date]=\"date\"></lib-duration-event>\n\n </div>\n </div>\n </div>\n </section>\n</div>", styles: ["*{box-sizing:border-box;margin:0;padding:0}.day-view-component{display:flex;flex-direction:column;width:100%;height:100%;max-height:100%;overflow:hidden}section.all-day-events{position:relative;flex-shrink:0;display:flex;flex-direction:column;width:100%;min-height:60px;border-top:1px solid rgba(0,0,0,.12);overflow:auto}section.all-day-events .header{position:sticky;top:0;left:0;z-index:2;width:100%;flex-shrink:0;padding:2px 8px;background-color:#fff;font-size:12px;color:#000000b3;-webkit-user-select:none;user-select:none}section.all-day-events .events-container{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:4px;padding:4px}section.duration-events{flex-grow:1;display:flex;width:100%;overflow:auto}section.duration-events .hour-blocks{display:flex;flex-direction:column;width:45px;-webkit-user-select:none;user-select:none}section.duration-events .hour-blocks .hour-block{flex-shrink:0;height:60px;padding:4px;border:1px solid rgba(0,0,0,.12);border-top:none;font-size:12px;color:#00000080}section.duration-events .events-wrapper{position:relative;flex-grow:1;width:100%}section.duration-events .events-wrapper .time-blocks{position:absolute;top:0;left:0;width:100%;height:100%;z-index:0;display:flex;flex-direction:column}section.duration-events .events-wrapper .time-blocks .time-block{flex-shrink:0;height:60px;padding:4px;border-bottom:1px solid rgba(0,0,0,.12);border-top:none;font-size:12px;color:#00000080}section.duration-events .events-wrapper .time-blocks .time-block .time-block-middle{width:100%;height:50%;border-bottom:1px dashed rgba(0,0,0,.12)}section.duration-events .events-wrapper .events-container{display:grid;column-gap:1px}section.duration-events .events-wrapper .events-container .event-column{position:relative}.resize-divider{flex-shrink:0;width:100%;height:4px;background-color:#0000001f;cursor:row-resize;transition:transform .2s ease}.resize-divider:hover{z-index:5;background:repeating-linear-gradient(45deg,rgba(0,0,0,.12),rgba(0,0,0,.12) 4px,#ffffff 4px,#ffffff 8px);background-color:#fff;background-size:22px 8px;animation:stripe-move 1s linear infinite;transform:scaleY(2)}@keyframes stripe-move{0%{background-position:0 0}to{background-position:22px 0}}\n"] }]
|
|
564
|
+
}], ctorParameters: function () { return []; }, propDecorators: { events: [{
|
|
565
|
+
type: Input
|
|
566
|
+
}], date: [{
|
|
567
|
+
type: Input
|
|
568
|
+
}] } });
|
|
569
|
+
|
|
570
|
+
class SmartCalendarComponent {
|
|
285
571
|
constructor() {
|
|
572
|
+
this.mode = 'month';
|
|
286
573
|
this.currentMonth = {
|
|
287
574
|
year: new Date().getFullYear(),
|
|
288
575
|
month: new Date().getMonth() + 1
|
|
289
576
|
};
|
|
290
577
|
this.events = [];
|
|
291
|
-
this.startAt = 'sunday';
|
|
292
578
|
this.monthChange = new EventEmitter();
|
|
293
|
-
this.
|
|
294
|
-
this.weekDays = [
|
|
295
|
-
{ tag: 'sun' },
|
|
296
|
-
{ tag: 'mon' },
|
|
297
|
-
{ tag: 'tue' },
|
|
298
|
-
{ tag: 'wed' },
|
|
299
|
-
{ tag: 'thu' },
|
|
300
|
-
{ tag: 'fri' },
|
|
301
|
-
{ tag: 'sat' },
|
|
302
|
-
];
|
|
303
|
-
this.showMoreEventsModal = false;
|
|
304
|
-
this.moreEventsModalEvents = [];
|
|
305
|
-
this.currentMonthTitle = ``;
|
|
579
|
+
this.dateChanged = new EventEmitter();
|
|
306
580
|
this.showDateSelector = false;
|
|
307
|
-
this.
|
|
308
|
-
|
|
309
|
-
this.setMaxEventsInDayCell();
|
|
310
|
-
};
|
|
581
|
+
this.selectedDate = new Date();
|
|
582
|
+
this.selectedDateEvents = [];
|
|
311
583
|
}
|
|
312
584
|
onDocumentClick(event) {
|
|
313
585
|
if (!this.showDateSelector)
|
|
@@ -318,176 +590,160 @@ class CalendarComponent {
|
|
|
318
590
|
this.showDateSelector = false;
|
|
319
591
|
}
|
|
320
592
|
}
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
return date.getDate() === today.getDate() &&
|
|
324
|
-
date.getMonth() === today.getMonth() &&
|
|
325
|
-
date.getFullYear() === today.getFullYear();
|
|
326
|
-
}
|
|
327
|
-
getEventsForDay(date) {
|
|
328
|
-
return this.events.filter(event => {
|
|
329
|
-
const eventStart = new Date(event.start);
|
|
330
|
-
const eventEnd = event.end ? new Date(event.end) : eventStart;
|
|
331
|
-
return date >= new Date(eventStart.getFullYear(), eventStart.getMonth(), eventStart.getDate()) &&
|
|
332
|
-
date <= new Date(eventEnd.getFullYear(), eventEnd.getMonth(), eventEnd.getDate());
|
|
333
|
-
});
|
|
334
|
-
}
|
|
335
|
-
initDaysCells() {
|
|
336
|
-
const daysInMonth = new Date(this.currentMonth.year, this.currentMonth.month, 0).getDate();
|
|
337
|
-
const firstDayOfWeek = new Date(this.currentMonth.year, this.currentMonth.month - 1, 1).getDay();
|
|
338
|
-
const prevDaysCount = this.startAt === 'monday' ? (firstDayOfWeek === 0 ? 6 : firstDayOfWeek - 1) : firstDayOfWeek;
|
|
339
|
-
// const nextDaysCount = (7 - ((prevDaysCount + daysInMonth) % 7)) % 7;
|
|
340
|
-
const nextDaysCount = 42 - (prevDaysCount + daysInMonth); // Always show 6 weeks
|
|
341
|
-
this.dayCells = [];
|
|
342
|
-
for (let i = 0; i < prevDaysCount; i++) {
|
|
343
|
-
const date = new Date(this.currentMonth.year, this.currentMonth.month - 1, i - prevDaysCount + 1);
|
|
344
|
-
const _events = this.getEventsForDay(date);
|
|
345
|
-
this.dayCells.push({
|
|
346
|
-
date,
|
|
347
|
-
events: _events,
|
|
348
|
-
isOutsideMonth: true,
|
|
349
|
-
isToday: this.isToday(date)
|
|
350
|
-
});
|
|
351
|
-
}
|
|
352
|
-
for (let day = 1; day <= daysInMonth; day++) {
|
|
353
|
-
const date = new Date(this.currentMonth.year, this.currentMonth.month - 1, day);
|
|
354
|
-
const _events = this.getEventsForDay(date);
|
|
355
|
-
this.dayCells.push({
|
|
356
|
-
date,
|
|
357
|
-
events: _events,
|
|
358
|
-
isToday: this.isToday(date)
|
|
359
|
-
});
|
|
360
|
-
}
|
|
361
|
-
for (let i = 1; i <= nextDaysCount; i++) {
|
|
362
|
-
const date = new Date(this.currentMonth.year, this.currentMonth.month - 1, daysInMonth + i);
|
|
363
|
-
const _events = this.getEventsForDay(date);
|
|
364
|
-
this.dayCells.push({
|
|
365
|
-
date,
|
|
366
|
-
events: _events,
|
|
367
|
-
isOutsideMonth: true,
|
|
368
|
-
isToday: this.isToday(date)
|
|
369
|
-
});
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
setCalendarBodyHeight() {
|
|
373
|
-
this.calendarBodyHeight = this.calendarBodyRef.nativeElement.clientHeight;
|
|
374
|
-
}
|
|
375
|
-
setMaxEventsInDayCell() {
|
|
376
|
-
const element = document.getElementsByClassName('events-list')[0];
|
|
377
|
-
console.log(element);
|
|
378
|
-
if (element) {
|
|
379
|
-
const eventItemHeight = 22;
|
|
380
|
-
this.maxEventsInDayCell = Math.floor(element.clientHeight / eventItemHeight) - 1;
|
|
381
|
-
}
|
|
593
|
+
ngOnInit() {
|
|
594
|
+
this.selectDate(new Date());
|
|
382
595
|
}
|
|
383
|
-
|
|
384
|
-
this.
|
|
385
|
-
this.moreEventsModalEvents = events;
|
|
386
|
-
this.showMoreEventsModal = true;
|
|
596
|
+
toggleDateSelector() {
|
|
597
|
+
this.showDateSelector = !this.showDateSelector;
|
|
387
598
|
}
|
|
388
|
-
|
|
389
|
-
this.
|
|
390
|
-
this.
|
|
391
|
-
this.
|
|
599
|
+
onMonthSelected(newMonth) {
|
|
600
|
+
const oldMonth = { ...this.currentMonth };
|
|
601
|
+
this.currentMonth = newMonth;
|
|
602
|
+
this.selectDate(new Date(this.currentMonth.year, this.currentMonth.month - 1, 1));
|
|
603
|
+
this.monthChange.emit({
|
|
604
|
+
newMonth: this.currentMonth,
|
|
605
|
+
oldMonth
|
|
606
|
+
});
|
|
607
|
+
this.showDateSelector = false;
|
|
392
608
|
}
|
|
393
609
|
nextMonth() {
|
|
394
610
|
const oldMonth = { ...this.currentMonth };
|
|
395
611
|
if (this.currentMonth.month === 12) {
|
|
396
|
-
this.currentMonth
|
|
397
|
-
|
|
612
|
+
this.currentMonth = {
|
|
613
|
+
year: this.currentMonth.year + 1,
|
|
614
|
+
month: 1
|
|
615
|
+
};
|
|
398
616
|
}
|
|
399
617
|
else {
|
|
400
|
-
this.currentMonth
|
|
618
|
+
this.currentMonth = {
|
|
619
|
+
year: this.currentMonth.year,
|
|
620
|
+
month: this.currentMonth.month + 1
|
|
621
|
+
};
|
|
401
622
|
}
|
|
402
|
-
this.
|
|
623
|
+
this.selectDate(new Date(this.currentMonth.year, this.currentMonth.month - 1, 1));
|
|
403
624
|
this.monthChange.emit({
|
|
404
|
-
newMonth:
|
|
625
|
+
newMonth: this.currentMonth,
|
|
405
626
|
oldMonth
|
|
406
627
|
});
|
|
407
628
|
}
|
|
408
629
|
prevMonth() {
|
|
409
630
|
const oldMonth = { ...this.currentMonth };
|
|
410
631
|
if (this.currentMonth.month === 1) {
|
|
411
|
-
this.currentMonth
|
|
412
|
-
|
|
632
|
+
this.currentMonth = {
|
|
633
|
+
year: this.currentMonth.year - 1,
|
|
634
|
+
month: 12
|
|
635
|
+
};
|
|
413
636
|
}
|
|
414
637
|
else {
|
|
415
|
-
this.currentMonth
|
|
638
|
+
this.currentMonth = {
|
|
639
|
+
year: this.currentMonth.year,
|
|
640
|
+
month: this.currentMonth.month - 1
|
|
641
|
+
};
|
|
416
642
|
}
|
|
417
|
-
this.
|
|
643
|
+
this.selectDate(new Date(this.currentMonth.year, this.currentMonth.month - 1, 1));
|
|
418
644
|
this.monthChange.emit({
|
|
419
|
-
newMonth:
|
|
645
|
+
newMonth: this.currentMonth,
|
|
420
646
|
oldMonth
|
|
421
647
|
});
|
|
422
648
|
}
|
|
423
649
|
goToToday() {
|
|
424
650
|
const today = new Date();
|
|
425
651
|
const oldMonth = { ...this.currentMonth };
|
|
426
|
-
this.currentMonth
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
652
|
+
this.currentMonth = {
|
|
653
|
+
year: today.getFullYear(),
|
|
654
|
+
month: today.getMonth() + 1
|
|
655
|
+
};
|
|
656
|
+
this.selectDate(today);
|
|
657
|
+
if (this.currentMonth.month !== oldMonth.month || this.currentMonth.year !== oldMonth.year)
|
|
658
|
+
this.monthChange.emit({
|
|
659
|
+
newMonth: this.currentMonth,
|
|
660
|
+
oldMonth
|
|
661
|
+
});
|
|
436
662
|
}
|
|
437
|
-
|
|
663
|
+
nextDay() {
|
|
438
664
|
const oldMonth = { ...this.currentMonth };
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
this.
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
665
|
+
const newDate = new Date(this.selectedDate);
|
|
666
|
+
newDate.setDate(newDate.getDate() + 1);
|
|
667
|
+
this.selectDate(newDate);
|
|
668
|
+
this.currentMonth = {
|
|
669
|
+
year: newDate.getFullYear(),
|
|
670
|
+
month: newDate.getMonth() + 1
|
|
671
|
+
};
|
|
672
|
+
if (this.currentMonth.month !== oldMonth.month || this.currentMonth.year !== oldMonth.year)
|
|
673
|
+
this.monthChange.emit({
|
|
674
|
+
newMonth: this.currentMonth,
|
|
675
|
+
oldMonth
|
|
676
|
+
});
|
|
446
677
|
}
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
678
|
+
prevDay() {
|
|
679
|
+
const oldMonth = { ...this.currentMonth };
|
|
680
|
+
const newDate = new Date(this.selectedDate);
|
|
681
|
+
newDate.setDate(newDate.getDate() - 1);
|
|
682
|
+
this.selectDate(newDate);
|
|
683
|
+
this.currentMonth = {
|
|
684
|
+
year: newDate.getFullYear(),
|
|
685
|
+
month: newDate.getMonth() + 1
|
|
686
|
+
};
|
|
687
|
+
if (this.currentMonth.month !== oldMonth.month || this.currentMonth.year !== oldMonth.year)
|
|
688
|
+
this.monthChange.emit({
|
|
689
|
+
newMonth: this.currentMonth,
|
|
690
|
+
oldMonth
|
|
691
|
+
});
|
|
460
692
|
}
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
this.
|
|
693
|
+
onNext() {
|
|
694
|
+
if (this.mode === 'month')
|
|
695
|
+
this.nextMonth();
|
|
696
|
+
else if (this.mode === 'day')
|
|
697
|
+
this.nextDay();
|
|
698
|
+
}
|
|
699
|
+
onPrev() {
|
|
700
|
+
if (this.mode === 'month')
|
|
701
|
+
this.prevMonth();
|
|
702
|
+
else if (this.mode === 'day')
|
|
703
|
+
this.prevDay();
|
|
704
|
+
}
|
|
705
|
+
selectDate(date) {
|
|
706
|
+
this.selectedDate = date;
|
|
707
|
+
this.selectedDateEvents = this.events.filter(event => {
|
|
708
|
+
const eventDate = new Date(event.start);
|
|
709
|
+
// return events that starts, ends or spans the selected date
|
|
710
|
+
return (eventDate.getDate() === date.getDate() &&
|
|
711
|
+
eventDate.getMonth() === date.getMonth() &&
|
|
712
|
+
eventDate.getFullYear() === date.getFullYear()) ||
|
|
713
|
+
(event.end &&
|
|
714
|
+
event.end.getDate() === date.getDate() &&
|
|
715
|
+
event.end.getMonth() === date.getMonth() &&
|
|
716
|
+
event.end.getFullYear() === date.getFullYear()) ||
|
|
717
|
+
(event.start < date && event.end && event.end > date);
|
|
466
718
|
});
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
719
|
+
const oldMonth = this.currentMonth;
|
|
720
|
+
this.currentMonth = {
|
|
721
|
+
year: date.getFullYear(),
|
|
722
|
+
month: date.getMonth() + 1
|
|
723
|
+
};
|
|
724
|
+
if (this.currentMonth.month !== oldMonth.month || this.currentMonth.year !== oldMonth.year)
|
|
725
|
+
this.monthChange.emit({
|
|
726
|
+
newMonth: this.currentMonth,
|
|
727
|
+
oldMonth
|
|
728
|
+
});
|
|
729
|
+
this.dateChanged.emit(this.selectedDate);
|
|
470
730
|
}
|
|
471
731
|
}
|
|
472
|
-
|
|
473
|
-
CalendarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: CalendarComponent, selector: "lib-calendar", inputs: { currentMonth: "currentMonth", events: "events", startAt: "startAt" }, outputs: { monthChange: "monthChange" }, host: { listeners: { "document:click": "onDocumentClick($event)" } }, viewQueries: [{ propertyName: "calendarRef", first: true, predicate: ["calendar"], descendants: true }, { propertyName: "calendarBodyRef", first: true, predicate: ["calendarBody"], descendants: true }, { propertyName: "dateSelectorDropdown", first: true, predicate: ["dateSelectorDropdown"], descendants: true }], ngImport: i0, template: "<div class=\"calendar-component\">\r\n <div class=\"header\">\r\n <div class=\"nav-controls\">\r\n <button class=\"btn-prev\" (click)=\"prevMonth()\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\" viewBox=\"0 -960 960 960\" width=\"24px\"\r\n fill=\"currentColor\">\r\n <path d=\"M560-240 320-480l240-240 56 56-184 184 184 184-56 56Z\" />\r\n </svg>\r\n </button>\r\n\r\n <button class=\"btn-today\" (click)=\"goToToday()\">{{'today' | translate}}</button>\r\n\r\n <button class=\"btn-next\" (click)=\"nextMonth()\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\" viewBox=\"0 -960 960 960\" width=\"24px\"\r\n fill=\"currentColor\">\r\n <path d=\"M504-480 320-664l56-56 240 240-240 240-56-56 184-184Z\" />\r\n </svg>\r\n </button>\r\n </div>\r\n\r\n <div class=\"spacer\"></div>\r\n\r\n <div class=\"date-selector-container\">\r\n <button class=\"btn-date-selector\" (click)=\"toggleDateSelector()\">\r\n <span>{{ currentMonth.month | translateMonth}} - {{ currentMonth.year }}</span>\r\n\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\" viewBox=\"0 -960 960 960\" width=\"24px\"\r\n fill=\"currentColor\">\r\n <path d=\"M480-360 280-560h400L480-360Z\" />\r\n </svg>\r\n </button>\r\n\r\n <div class=\"date-selector-dropdown\" *ngIf=\"showDateSelector\" #dateSelectorDropdown>\r\n <lib-month-selector [selectedMonth]=\"currentMonth\"\r\n (monthSelected)=\"onMonthSelected($event)\"></lib-month-selector>\r\n </div>\r\n </div>\r\n\r\n <div class=\"spacer\"></div>\r\n\r\n <div class=\"view-selector\">\r\n <button class=\"btn-view active\">\r\n <!-- month view -->\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\" viewBox=\"0 -960 960 960\" width=\"24px\"\r\n fill=\"currentColor\">\r\n <path\r\n d=\"M200-80q-33 0-56.5-23.5T120-160v-560q0-33 23.5-56.5T200-800h40v-80h80v80h320v-80h80v80h40q33 0 56.5 23.5T840-720v560q0 33-23.5 56.5T760-80H200Zm0-80h560v-400H200v400Zm0-480h560v-80H200v80Zm0 0v-80 80Zm280 240q-17 0-28.5-11.5T440-440q0-17 11.5-28.5T480-480q17 0 28.5 11.5T520-440q0 17-11.5 28.5T480-400Zm-160 0q-17 0-28.5-11.5T280-440q0-17 11.5-28.5T320-480q17 0 28.5 11.5T360-440q0 17-11.5 28.5T320-400Zm320 0q-17 0-28.5-11.5T600-440q0-17 11.5-28.5T640-480q17 0 28.5 11.5T680-440q0 17-11.5 28.5T640-400ZM480-240q-17 0-28.5-11.5T440-280q0-17 11.5-28.5T480-320q17 0 28.5 11.5T520-280q0 17-11.5 28.5T480-240Zm-160 0q-17 0-28.5-11.5T280-280q0-17 11.5-28.5T320-320q17 0 28.5 11.5T360-280q0 17-11.5 28.5T320-240Zm320 0q-17 0-28.5-11.5T600-280q0-17 11.5-28.5T640-320q17 0 28.5 11.5T680-280q0 17-11.5 28.5T640-240Z\" />\r\n </svg>\r\n </button>\r\n\r\n <button class=\"btn-view\">\r\n <!-- week view -->\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\" viewBox=\"0 -960 960 960\" width=\"24px\"\r\n fill=\"currentColor\">\r\n <path\r\n d=\"M160-160q-33 0-56.5-23.5T80-240v-480q0-33 23.5-56.5T160-800h640q33 0 56.5 23.5T880-720v480q0 33-23.5 56.5T800-160H160Zm360-80h100v-480H520v480Zm-180 0h100v-480H340v480Zm-180 0h100v-480H160v480Zm540 0h100v-480H700v480Z\" />\r\n </svg>\r\n </button>\r\n\r\n <button class=\"btn-view\">\r\n <!-- day view -->\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\" viewBox=\"0 -960 960 960\" width=\"24px\"\r\n fill=\"currentColor\">\r\n <path\r\n d=\"M120-160v-80h720v80H120Zm0-560v-80h720v80H120Zm80 400q-33 0-56.5-23.5T120-400v-160q0-33 23.5-56.5T200-640h560q33 0 56.5 23.5T840-560v160q0 33-23.5 56.5T760-320H200Zm0-80h560v-160H200v160Zm0-160v160-160Z\" />\r\n </svg>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div class=\"body\" #calendarBody>\r\n <div class=\"week-days\">\r\n <div class=\"week-day\" *ngFor=\"let day of weekDays\">\r\n {{ day.tag | translate | slice:0:3 }}\r\n </div>\r\n </div>\r\n\r\n <div class=\"days-grid\">\r\n <div class=\"day-cell\" *ngFor=\"let day of dayCells; let i = index\"\r\n [ngClass]=\"{'outside-month': day.isOutsideMonth, 'is-today': day.isToday}\">\r\n <div class=\"day-number\">\r\n {{ day.date.getDate() }}\r\n </div>\r\n\r\n <div class=\"events-list\">\r\n <lib-calendar-event *ngFor=\"let event of day.events | slice:0:maxEventsInDayCell\"\r\n [event]=\"event\"></lib-calendar-event>\r\n\r\n <div class=\"more-events\" *ngIf=\"day.events.length > (maxEventsInDayCell || 0)\"\r\n (click)=\"openMoreEventsModal(day.date, day.events)\">\r\n {{'nMoreEvents' | translate: {n:(day.events.length - (maxEventsInDayCell || 0))} }}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"footer\">\r\n Footer\r\n </div>\r\n\r\n <lib-more-events-modal *ngIf=\"showMoreEventsModal && moreEventsModalDate\" [events]=\"moreEventsModalEvents\"\r\n [date]=\"moreEventsModalDate\" (close)=\"closeMoreEventsModal()\"\r\n (eventClick)=\"closeMoreEventsModal()\"></lib-more-events-modal>\r\n</div>", styles: ["*{box-sizing:border-box;margin:0;padding:0}.calendar-component{display:flex;flex-direction:column;width:100%;height:100%}.header{flex-shrink:0;display:flex;align-items:center;gap:16px;padding:2px 16px}.header .spacer{flex:1 1 auto}.header .nav-controls{display:flex;align-items:center}.header .nav-controls .btn-prev,.header .nav-controls .btn-next{display:flex;align-items:center;justify-content:center;width:30px;height:30px;border:none;background:none;border-radius:50%;cursor:pointer;-webkit-user-select:none;user-select:none}.header .nav-controls .btn-prev:hover,.header .nav-controls .btn-next:hover{background-color:#eee}.header .nav-controls .btn-today{display:flex;align-items:center;height:30px;padding:0 12px;border:none;background:none;border-radius:50px;cursor:pointer;font-weight:600;-webkit-user-select:none;user-select:none}.header .nav-controls .btn-today:hover{background-color:#eee}.header .view-selector{display:flex;align-items:center}.header .view-selector .btn-view{display:flex;align-items:center;justify-content:center;width:30px;height:30px;border:1px solid #cccccc;background:none;cursor:pointer;-webkit-user-select:none;user-select:none}.header .view-selector .btn-view:first-child{border-top-left-radius:4px;border-bottom-left-radius:4px;border-right:none}.header .view-selector .btn-view:last-child{border-top-right-radius:4px;border-bottom-right-radius:4px;border-left:none}.header .view-selector .btn-view:hover{background-color:#eee}.header .view-selector .btn-view svg{width:22px;height:22px}.header .view-selector .btn-view.active{background-color:#0000001a}.header .date-selector-container{position:relative}.header .date-selector-container .date-selector-dropdown{position:absolute;top:100%;left:50%;transform:translate(-50%);background-color:#fff;border-radius:4px;box-shadow:0 2px 24px #0000004d;z-index:3}.header .date-selector-container .date-selector-dropdown:before{content:\"\";position:absolute;top:-6px;left:50%;transform:translate(-50%) rotate(45deg);width:12px;height:12px;background-color:#fff;border-radius:2px}.header .btn-date-selector{display:flex;align-items:center;gap:8px;height:30px;padding:0 8px 0 12px;border:none;background:none;border-radius:50px;cursor:pointer;font-weight:600;-webkit-user-select:none;user-select:none}.header .btn-date-selector:hover{background-color:#eee}.body{flex:1 1 0;display:flex;flex-direction:column;width:100%;min-height:0;height:100%}.week-days{flex-shrink:0;display:grid;grid-template-columns:repeat(7,1fr);width:100%;background-color:#f4f4f4}.week-day{display:flex;align-items:center;justify-content:center;padding:4px;background-color:#fff;font-size:14px;color:#00000080}.days-grid{flex:1 1 0;display:grid;grid-template-columns:repeat(7,1fr);gap:1px;grid-auto-rows:1fr;width:100%;padding:1px;background-color:#f4f4f4;min-height:0;height:100%}.day-cell{display:flex;flex-direction:column;gap:4px;padding:4px;background-color:#fff;overflow:hidden}.day-cell .day-number{display:flex;align-items:center;justify-content:center;width:fit-content;aspect-ratio:1;padding:2px;border-radius:50%;font-size:12px;line-height:16px;font-weight:600;-webkit-user-select:none;user-select:none}.day-cell.outside-month{background-color:#f8f8f8}.day-cell.is-today .day-number{background-color:#007bff;color:#fff}.day-cell .events-list{flex:1 1 auto;display:flex;flex-direction:column;gap:2px;overflow:hidden;min-height:0;max-height:100%}.day-cell .events-list .more-events{padding:2px 8px;border-radius:4px;font-size:12px;color:#555;cursor:pointer}.day-cell .events-list .more-events:hover{background-color:#eee}.footer{flex-shrink:0;background-color:#add8e6}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: CalendarEventComponent, selector: "lib-calendar-event", inputs: ["event"] }, { kind: "component", type: MoreEventsModalComponent, selector: "lib-more-events-modal", inputs: ["events", "date"], outputs: ["close", "eventClick"] }, { kind: "component", type: MonthSelectorComponent, selector: "lib-month-selector", inputs: ["selectedMonth"], outputs: ["monthSelected"] }, { kind: "pipe", type: i1.SlicePipe, name: "slice" }, { kind: "pipe", type: TranslatePipe, name: "translate" }, { kind: "pipe", type: TranslateMonthPipe, name: "translateMonth" }] });
|
|
474
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type:
|
|
732
|
+
SmartCalendarComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: SmartCalendarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
733
|
+
SmartCalendarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: SmartCalendarComponent, selector: "smart-calendar", inputs: { mode: "mode", currentMonth: "currentMonth", events: "events" }, outputs: { monthChange: "monthChange", dateChanged: "dateChanged" }, host: { listeners: { "document:click": "onDocumentClick($event)" } }, viewQueries: [{ propertyName: "dateSelectorDropdown", first: true, predicate: ["dateSelectorDropdown"], descendants: true }], ngImport: i0, template: "<div class=\"smart-calendar-component\">\n <div class=\"header\">\n <div class=\"nav-controls\">\n <button class=\"btn-prev\" (click)=\"onPrev()\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\" viewBox=\"0 -960 960 960\" width=\"24px\"\n fill=\"currentColor\">\n <path d=\"M560-240 320-480l240-240 56 56-184 184 184 184-56 56Z\" />\n </svg>\n </button>\n\n <button class=\"btn-today\" (click)=\"goToToday()\">{{'today' | translate}}</button>\n\n <button class=\"btn-next\" (click)=\"onNext()\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\" viewBox=\"0 -960 960 960\" width=\"24px\"\n fill=\"currentColor\">\n <path d=\"M504-480 320-664l56-56 240 240-240 240-56-56 184-184Z\" />\n </svg>\n </button>\n </div>\n\n <div class=\"spacer\"></div>\n\n <div class=\"date-selector-container\">\n <button class=\"btn-date-selector\" (click)=\"toggleDateSelector()\">\n <span *ngIf=\"mode === 'month'\">{{ currentMonth.month | translateMonth}} - {{ currentMonth.year }}</span>\n <span *ngIf=\"mode === 'day'\">{{ selectedDate.toDateString() }}</span>\n\n <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\" viewBox=\"0 -960 960 960\" width=\"24px\"\n fill=\"currentColor\">\n <path d=\"M480-360 280-560h400L480-360Z\" />\n </svg>\n </button>\n\n <div class=\"date-selector-dropdown\" *ngIf=\"showDateSelector\" #dateSelectorDropdown>\n <lib-month-selector [selectedMonth]=\"currentMonth\"\n (monthSelected)=\"onMonthSelected($event)\"></lib-month-selector>\n </div>\n </div>\n\n <div class=\"spacer\"></div>\n\n <div class=\"view-selector\">\n <button class=\"btn-view\" [ngClass]=\"{active: mode === 'month'}\" (click)=\"mode = 'month'\">\n <!-- month view -->\n <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\" viewBox=\"0 -960 960 960\" width=\"24px\"\n fill=\"currentColor\">\n <path\n d=\"M200-80q-33 0-56.5-23.5T120-160v-560q0-33 23.5-56.5T200-800h40v-80h80v80h320v-80h80v80h40q33 0 56.5 23.5T840-720v560q0 33-23.5 56.5T760-80H200Zm0-80h560v-400H200v400Zm0-480h560v-80H200v80Zm0 0v-80 80Zm280 240q-17 0-28.5-11.5T440-440q0-17 11.5-28.5T480-480q17 0 28.5 11.5T520-440q0 17-11.5 28.5T480-400Zm-160 0q-17 0-28.5-11.5T280-440q0-17 11.5-28.5T320-480q17 0 28.5 11.5T360-440q0 17-11.5 28.5T320-400Zm320 0q-17 0-28.5-11.5T600-440q0-17 11.5-28.5T640-480q17 0 28.5 11.5T680-440q0 17-11.5 28.5T640-400ZM480-240q-17 0-28.5-11.5T440-280q0-17 11.5-28.5T480-320q17 0 28.5 11.5T520-280q0 17-11.5 28.5T480-240Zm-160 0q-17 0-28.5-11.5T280-280q0-17 11.5-28.5T320-320q17 0 28.5 11.5T360-280q0 17-11.5 28.5T320-240Zm320 0q-17 0-28.5-11.5T600-280q0-17 11.5-28.5T640-320q17 0 28.5 11.5T680-280q0 17-11.5 28.5T640-240Z\" />\n </svg>\n </button>\n\n <button class=\"btn-view\" [ngClass]=\"{active: mode === 'week'}\" (click)=\"mode = 'week'\">\n <!-- week view -->\n <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\" viewBox=\"0 -960 960 960\" width=\"24px\"\n fill=\"currentColor\">\n <path\n d=\"M160-160q-33 0-56.5-23.5T80-240v-480q0-33 23.5-56.5T160-800h640q33 0 56.5 23.5T880-720v480q0 33-23.5 56.5T800-160H160Zm360-80h100v-480H520v480Zm-180 0h100v-480H340v480Zm-180 0h100v-480H160v480Zm540 0h100v-480H700v480Z\" />\n </svg>\n </button>\n\n <button class=\"btn-view\" [ngClass]=\"{active: mode === 'day'}\" (click)=\"mode = 'day'\">\n <!-- day view -->\n <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\" viewBox=\"0 -960 960 960\" width=\"24px\"\n fill=\"currentColor\">\n <path\n d=\"M120-160v-80h720v80H120Zm0-560v-80h720v80H120Zm80 400q-33 0-56.5-23.5T120-400v-160q0-33 23.5-56.5T200-640h560q33 0 56.5 23.5T840-560v160q0 33-23.5 56.5T760-320H200Zm0-80h560v-160H200v160Zm0-160v160-160Z\" />\n </svg>\n </button>\n </div>\n </div>\n\n <div class=\"view-container\">\n <lib-calendar [events]=\"events\" [currentMonth]=\"currentMonth\" *ngIf=\"mode === 'month'\"></lib-calendar>\n\n <lib-day *ngIf=\"mode === 'day'\" [date]=\"selectedDate\" [events]=\"selectedDateEvents\"></lib-day>\n </div>\n\n</div>", styles: ["*{box-sizing:border-box;margin:0;padding:0}.smart-calendar-component{display:flex;flex-direction:column;width:100%;height:100%;background-color:#fff}.header{flex-shrink:0;display:flex;align-items:center;gap:16px;padding:2px 16px}.header .spacer{flex:1 1 auto}.header .nav-controls{display:flex;align-items:center}.header .nav-controls .btn-prev,.header .nav-controls .btn-next{display:flex;align-items:center;justify-content:center;width:30px;height:30px;border:none;background:none;border-radius:50%;cursor:pointer;-webkit-user-select:none;user-select:none}.header .nav-controls .btn-prev:hover,.header .nav-controls .btn-next:hover{background-color:#eee}.header .nav-controls .btn-today{display:flex;align-items:center;height:30px;padding:0 12px;border:none;background:none;border-radius:50px;cursor:pointer;font-weight:600;-webkit-user-select:none;user-select:none}.header .nav-controls .btn-today:hover{background-color:#eee}.header .view-selector{display:flex;align-items:center}.header .view-selector .btn-view{display:flex;align-items:center;justify-content:center;width:30px;height:30px;border:1px solid #cccccc;background:none;cursor:pointer;-webkit-user-select:none;user-select:none}.header .view-selector .btn-view:first-child{border-top-left-radius:4px;border-bottom-left-radius:4px;border-right:none}.header .view-selector .btn-view:last-child{border-top-right-radius:4px;border-bottom-right-radius:4px;border-left:none}.header .view-selector .btn-view:hover{background-color:#eee}.header .view-selector .btn-view svg{width:22px;height:22px}.header .view-selector .btn-view.active{background-color:#0000001a}.header .date-selector-container{position:relative}.header .date-selector-container .date-selector-dropdown{position:absolute;top:100%;left:50%;transform:translate(-50%);background-color:#fff;border-radius:4px;box-shadow:0 2px 24px #0000004d;z-index:3}.header .date-selector-container .date-selector-dropdown:before{content:\"\";position:absolute;top:-6px;left:50%;transform:translate(-50%) rotate(45deg);width:12px;height:12px;background-color:#fff;border-radius:2px}.header .btn-date-selector{display:flex;align-items:center;gap:8px;height:30px;padding:0 8px 0 12px;border:none;background:none;border-radius:50px;cursor:pointer;font-weight:600;-webkit-user-select:none;user-select:none}.header .btn-date-selector:hover{background-color:#eee}.view-container{flex:1 1 auto;overflow:hidden}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: CalendarComponent, selector: "lib-calendar", inputs: ["currentMonth", "events", "startAt"] }, { kind: "component", type: MonthSelectorComponent, selector: "lib-month-selector", inputs: ["selectedMonth"], outputs: ["monthSelected"] }, { kind: "component", type: DayComponent, selector: "lib-day", inputs: ["events", "date"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }, { kind: "pipe", type: TranslateMonthPipe, name: "translateMonth" }] });
|
|
734
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: SmartCalendarComponent, decorators: [{
|
|
475
735
|
type: Component,
|
|
476
|
-
args: [{ selector: '
|
|
477
|
-
}], ctorParameters: function () { return []; }, propDecorators: {
|
|
736
|
+
args: [{ selector: 'smart-calendar', template: "<div class=\"smart-calendar-component\">\n <div class=\"header\">\n <div class=\"nav-controls\">\n <button class=\"btn-prev\" (click)=\"onPrev()\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\" viewBox=\"0 -960 960 960\" width=\"24px\"\n fill=\"currentColor\">\n <path d=\"M560-240 320-480l240-240 56 56-184 184 184 184-56 56Z\" />\n </svg>\n </button>\n\n <button class=\"btn-today\" (click)=\"goToToday()\">{{'today' | translate}}</button>\n\n <button class=\"btn-next\" (click)=\"onNext()\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\" viewBox=\"0 -960 960 960\" width=\"24px\"\n fill=\"currentColor\">\n <path d=\"M504-480 320-664l56-56 240 240-240 240-56-56 184-184Z\" />\n </svg>\n </button>\n </div>\n\n <div class=\"spacer\"></div>\n\n <div class=\"date-selector-container\">\n <button class=\"btn-date-selector\" (click)=\"toggleDateSelector()\">\n <span *ngIf=\"mode === 'month'\">{{ currentMonth.month | translateMonth}} - {{ currentMonth.year }}</span>\n <span *ngIf=\"mode === 'day'\">{{ selectedDate.toDateString() }}</span>\n\n <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\" viewBox=\"0 -960 960 960\" width=\"24px\"\n fill=\"currentColor\">\n <path d=\"M480-360 280-560h400L480-360Z\" />\n </svg>\n </button>\n\n <div class=\"date-selector-dropdown\" *ngIf=\"showDateSelector\" #dateSelectorDropdown>\n <lib-month-selector [selectedMonth]=\"currentMonth\"\n (monthSelected)=\"onMonthSelected($event)\"></lib-month-selector>\n </div>\n </div>\n\n <div class=\"spacer\"></div>\n\n <div class=\"view-selector\">\n <button class=\"btn-view\" [ngClass]=\"{active: mode === 'month'}\" (click)=\"mode = 'month'\">\n <!-- month view -->\n <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\" viewBox=\"0 -960 960 960\" width=\"24px\"\n fill=\"currentColor\">\n <path\n d=\"M200-80q-33 0-56.5-23.5T120-160v-560q0-33 23.5-56.5T200-800h40v-80h80v80h320v-80h80v80h40q33 0 56.5 23.5T840-720v560q0 33-23.5 56.5T760-80H200Zm0-80h560v-400H200v400Zm0-480h560v-80H200v80Zm0 0v-80 80Zm280 240q-17 0-28.5-11.5T440-440q0-17 11.5-28.5T480-480q17 0 28.5 11.5T520-440q0 17-11.5 28.5T480-400Zm-160 0q-17 0-28.5-11.5T280-440q0-17 11.5-28.5T320-480q17 0 28.5 11.5T360-440q0 17-11.5 28.5T320-400Zm320 0q-17 0-28.5-11.5T600-440q0-17 11.5-28.5T640-480q17 0 28.5 11.5T680-440q0 17-11.5 28.5T640-400ZM480-240q-17 0-28.5-11.5T440-280q0-17 11.5-28.5T480-320q17 0 28.5 11.5T520-280q0 17-11.5 28.5T480-240Zm-160 0q-17 0-28.5-11.5T280-280q0-17 11.5-28.5T320-320q17 0 28.5 11.5T360-280q0 17-11.5 28.5T320-240Zm320 0q-17 0-28.5-11.5T600-280q0-17 11.5-28.5T640-320q17 0 28.5 11.5T680-280q0 17-11.5 28.5T640-240Z\" />\n </svg>\n </button>\n\n <button class=\"btn-view\" [ngClass]=\"{active: mode === 'week'}\" (click)=\"mode = 'week'\">\n <!-- week view -->\n <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\" viewBox=\"0 -960 960 960\" width=\"24px\"\n fill=\"currentColor\">\n <path\n d=\"M160-160q-33 0-56.5-23.5T80-240v-480q0-33 23.5-56.5T160-800h640q33 0 56.5 23.5T880-720v480q0 33-23.5 56.5T800-160H160Zm360-80h100v-480H520v480Zm-180 0h100v-480H340v480Zm-180 0h100v-480H160v480Zm540 0h100v-480H700v480Z\" />\n </svg>\n </button>\n\n <button class=\"btn-view\" [ngClass]=\"{active: mode === 'day'}\" (click)=\"mode = 'day'\">\n <!-- day view -->\n <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\" viewBox=\"0 -960 960 960\" width=\"24px\"\n fill=\"currentColor\">\n <path\n d=\"M120-160v-80h720v80H120Zm0-560v-80h720v80H120Zm80 400q-33 0-56.5-23.5T120-400v-160q0-33 23.5-56.5T200-640h560q33 0 56.5 23.5T840-560v160q0 33-23.5 56.5T760-320H200Zm0-80h560v-160H200v160Zm0-160v160-160Z\" />\n </svg>\n </button>\n </div>\n </div>\n\n <div class=\"view-container\">\n <lib-calendar [events]=\"events\" [currentMonth]=\"currentMonth\" *ngIf=\"mode === 'month'\"></lib-calendar>\n\n <lib-day *ngIf=\"mode === 'day'\" [date]=\"selectedDate\" [events]=\"selectedDateEvents\"></lib-day>\n </div>\n\n</div>", styles: ["*{box-sizing:border-box;margin:0;padding:0}.smart-calendar-component{display:flex;flex-direction:column;width:100%;height:100%;background-color:#fff}.header{flex-shrink:0;display:flex;align-items:center;gap:16px;padding:2px 16px}.header .spacer{flex:1 1 auto}.header .nav-controls{display:flex;align-items:center}.header .nav-controls .btn-prev,.header .nav-controls .btn-next{display:flex;align-items:center;justify-content:center;width:30px;height:30px;border:none;background:none;border-radius:50%;cursor:pointer;-webkit-user-select:none;user-select:none}.header .nav-controls .btn-prev:hover,.header .nav-controls .btn-next:hover{background-color:#eee}.header .nav-controls .btn-today{display:flex;align-items:center;height:30px;padding:0 12px;border:none;background:none;border-radius:50px;cursor:pointer;font-weight:600;-webkit-user-select:none;user-select:none}.header .nav-controls .btn-today:hover{background-color:#eee}.header .view-selector{display:flex;align-items:center}.header .view-selector .btn-view{display:flex;align-items:center;justify-content:center;width:30px;height:30px;border:1px solid #cccccc;background:none;cursor:pointer;-webkit-user-select:none;user-select:none}.header .view-selector .btn-view:first-child{border-top-left-radius:4px;border-bottom-left-radius:4px;border-right:none}.header .view-selector .btn-view:last-child{border-top-right-radius:4px;border-bottom-right-radius:4px;border-left:none}.header .view-selector .btn-view:hover{background-color:#eee}.header .view-selector .btn-view svg{width:22px;height:22px}.header .view-selector .btn-view.active{background-color:#0000001a}.header .date-selector-container{position:relative}.header .date-selector-container .date-selector-dropdown{position:absolute;top:100%;left:50%;transform:translate(-50%);background-color:#fff;border-radius:4px;box-shadow:0 2px 24px #0000004d;z-index:3}.header .date-selector-container .date-selector-dropdown:before{content:\"\";position:absolute;top:-6px;left:50%;transform:translate(-50%) rotate(45deg);width:12px;height:12px;background-color:#fff;border-radius:2px}.header .btn-date-selector{display:flex;align-items:center;gap:8px;height:30px;padding:0 8px 0 12px;border:none;background:none;border-radius:50px;cursor:pointer;font-weight:600;-webkit-user-select:none;user-select:none}.header .btn-date-selector:hover{background-color:#eee}.view-container{flex:1 1 auto;overflow:hidden}\n"] }]
|
|
737
|
+
}], ctorParameters: function () { return []; }, propDecorators: { mode: [{
|
|
478
738
|
type: Input
|
|
479
|
-
}],
|
|
739
|
+
}], currentMonth: [{
|
|
480
740
|
type: Input
|
|
481
|
-
}],
|
|
741
|
+
}], events: [{
|
|
482
742
|
type: Input
|
|
483
743
|
}], monthChange: [{
|
|
484
744
|
type: Output
|
|
485
|
-
}],
|
|
486
|
-
type:
|
|
487
|
-
args: ['calendar']
|
|
488
|
-
}], calendarBodyRef: [{
|
|
489
|
-
type: ViewChild,
|
|
490
|
-
args: ['calendarBody']
|
|
745
|
+
}], dateChanged: [{
|
|
746
|
+
type: Output
|
|
491
747
|
}], dateSelectorDropdown: [{
|
|
492
748
|
type: ViewChild,
|
|
493
749
|
args: ['dateSelectorDropdown', { static: false }]
|
|
@@ -496,22 +752,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
|
|
|
496
752
|
args: ['document:click', ['$event']]
|
|
497
753
|
}] } });
|
|
498
754
|
|
|
499
|
-
class SmartCalendarComponent {
|
|
500
|
-
constructor() {
|
|
501
|
-
this.events = [];
|
|
502
|
-
}
|
|
503
|
-
ngOnInit() {
|
|
504
|
-
}
|
|
505
|
-
}
|
|
506
|
-
SmartCalendarComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: SmartCalendarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
507
|
-
SmartCalendarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: SmartCalendarComponent, selector: "smart-calendar", inputs: { events: "events" }, ngImport: i0, template: "<div class=\"smart-calendar-component\">\n <lib-calendar [events]=\"events\"></lib-calendar>\n</div>", styles: [".smart-calendar-component{width:100%;height:100%;background-color:#fff;border:1px solid #dddddd}\n"], dependencies: [{ kind: "component", type: CalendarComponent, selector: "lib-calendar", inputs: ["currentMonth", "events", "startAt"], outputs: ["monthChange"] }] });
|
|
508
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: SmartCalendarComponent, decorators: [{
|
|
509
|
-
type: Component,
|
|
510
|
-
args: [{ selector: 'smart-calendar', template: "<div class=\"smart-calendar-component\">\n <lib-calendar [events]=\"events\"></lib-calendar>\n</div>", styles: [".smart-calendar-component{width:100%;height:100%;background-color:#fff;border:1px solid #dddddd}\n"] }]
|
|
511
|
-
}], ctorParameters: function () { return []; }, propDecorators: { events: [{
|
|
512
|
-
type: Input
|
|
513
|
-
}] } });
|
|
514
|
-
|
|
515
755
|
class SmartAngularCalendarModule {
|
|
516
756
|
}
|
|
517
757
|
SmartAngularCalendarModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: SmartAngularCalendarModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
@@ -521,7 +761,9 @@ SmartAngularCalendarModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.
|
|
|
521
761
|
CalendarEventComponent,
|
|
522
762
|
MoreEventsModalComponent,
|
|
523
763
|
TranslateMonthPipe,
|
|
524
|
-
MonthSelectorComponent
|
|
764
|
+
MonthSelectorComponent,
|
|
765
|
+
DayComponent,
|
|
766
|
+
DurationEventComponent], imports: [CommonModule], exports: [SmartCalendarComponent] });
|
|
525
767
|
SmartAngularCalendarModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: SmartAngularCalendarModule, imports: [CommonModule] });
|
|
526
768
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: SmartAngularCalendarModule, decorators: [{
|
|
527
769
|
type: NgModule,
|
|
@@ -533,7 +775,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
|
|
|
533
775
|
CalendarEventComponent,
|
|
534
776
|
MoreEventsModalComponent,
|
|
535
777
|
TranslateMonthPipe,
|
|
536
|
-
MonthSelectorComponent
|
|
778
|
+
MonthSelectorComponent,
|
|
779
|
+
DayComponent,
|
|
780
|
+
DurationEventComponent
|
|
537
781
|
],
|
|
538
782
|
imports: [
|
|
539
783
|
CommonModule
|