From dfc3afd4a909b408fc3065236360f2990c278f04 Mon Sep 17 00:00:00 2001 From: Roland Schneider Date: Fri, 21 Nov 2025 08:10:49 +0100 Subject: [PATCH] add fullcalendar example --- admin/package-lock.json | 78 +++++++++++++++++ admin/package.json | 6 ++ admin/src/app/app.routes.ts | 11 +++ admin/src/app/app.ts | 35 +++++--- .../calendar-view/calendar-view.css | 0 .../calendar-view/calendar-view.html | 8 ++ .../components/calendar-view/calendar-view.ts | 85 +++++++++++++++++++ 7 files changed, 209 insertions(+), 14 deletions(-) create mode 100644 admin/src/app/features/calendar/components/calendar-view/calendar-view.css create mode 100644 admin/src/app/features/calendar/components/calendar-view/calendar-view.html create mode 100644 admin/src/app/features/calendar/components/calendar-view/calendar-view.ts diff --git a/admin/package-lock.json b/admin/package-lock.json index 6baecc4..acb89f5 100644 --- a/admin/package-lock.json +++ b/admin/package-lock.json @@ -14,6 +14,12 @@ "@angular/forms": "^20.3.0", "@angular/platform-browser": "^20.3.0", "@angular/router": "^20.3.0", + "@fullcalendar/angular": "^6.1.19", + "@fullcalendar/core": "^6.1.19", + "@fullcalendar/daygrid": "^6.1.19", + "@fullcalendar/interaction": "^6.1.19", + "@fullcalendar/list": "^6.1.19", + "@fullcalendar/timegrid": "^6.1.19", "@tailwindcss/postcss": "^4.1.17", "daisyui": "^5.4.5", "jwt-decode": "^4.0.0", @@ -1358,6 +1364,68 @@ "node": ">=18" } }, + "node_modules/@fullcalendar/angular": { + "version": "6.1.19", + "resolved": "https://registry.npmjs.org/@fullcalendar/angular/-/angular-6.1.19.tgz", + "integrity": "sha512-a3TmjKnF8xprH1aNgFn9zYehEhM4GBAyh+91SJymno2j1cE8D8z0+W1HNwtDekKWwJt/5YoinCvDTHydmF/kKw==", + "license": "MIT", + "dependencies": { + "tslib": "^2.3.0" + }, + "peerDependencies": { + "@angular/common": "12 - 20", + "@angular/core": "12 - 20", + "@fullcalendar/core": "~6.1.19" + } + }, + "node_modules/@fullcalendar/core": { + "version": "6.1.19", + "resolved": "https://registry.npmjs.org/@fullcalendar/core/-/core-6.1.19.tgz", + "integrity": "sha512-z0aVlO5e4Wah6p6mouM0UEqtRf1MZZPt4mwzEyU6kusaNL+dlWQgAasF2cK23hwT4cmxkEmr4inULXgpyeExdQ==", + "license": "MIT", + "dependencies": { + "preact": "~10.12.1" + } + }, + "node_modules/@fullcalendar/daygrid": { + "version": "6.1.19", + "resolved": "https://registry.npmjs.org/@fullcalendar/daygrid/-/daygrid-6.1.19.tgz", + "integrity": "sha512-IAAfnMICnVWPjpT4zi87i3FEw0xxSza0avqY/HedKEz+l5MTBYvCDPOWDATpzXoLut3aACsjktIyw9thvIcRYQ==", + "license": "MIT", + "peerDependencies": { + "@fullcalendar/core": "~6.1.19" + } + }, + "node_modules/@fullcalendar/interaction": { + "version": "6.1.19", + "resolved": "https://registry.npmjs.org/@fullcalendar/interaction/-/interaction-6.1.19.tgz", + "integrity": "sha512-GOciy79xe8JMVp+1evAU3ytdwN/7tv35t5i1vFkifiuWcQMLC/JnLg/RA2s4sYmQwoYhTw/p4GLcP0gO5B3X5w==", + "license": "MIT", + "peerDependencies": { + "@fullcalendar/core": "~6.1.19" + } + }, + "node_modules/@fullcalendar/list": { + "version": "6.1.19", + "resolved": "https://registry.npmjs.org/@fullcalendar/list/-/list-6.1.19.tgz", + "integrity": "sha512-knZHpAVF0LbzZpSJSUmLUUzF0XlU/MRGK+Py2s0/mP93bCtno1k2L3XPs/kzh528hSjehwLm89RgKTSfW1P6cA==", + "license": "MIT", + "peerDependencies": { + "@fullcalendar/core": "~6.1.19" + } + }, + "node_modules/@fullcalendar/timegrid": { + "version": "6.1.19", + "resolved": "https://registry.npmjs.org/@fullcalendar/timegrid/-/timegrid-6.1.19.tgz", + "integrity": "sha512-OuzpUueyO9wB5OZ8rs7TWIoqvu4v3yEqdDxZ2VcsMldCpYJRiOe7yHWKr4ap5Tb0fs7Rjbserc/b6Nt7ol6BRg==", + "license": "MIT", + "dependencies": { + "@fullcalendar/daygrid": "~6.1.19" + }, + "peerDependencies": { + "@fullcalendar/core": "~6.1.19" + } + }, "node_modules/@inquirer/ansi": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@inquirer/ansi/-/ansi-1.0.1.tgz", @@ -8805,6 +8873,16 @@ "dev": true, "license": "MIT" }, + "node_modules/preact": { + "version": "10.12.1", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.12.1.tgz", + "integrity": "sha512-l8386ixSsBdbreOAkqtrwqHwdvR35ID8c3rKPa8lCWuO86dBi32QWHV4vfsZK1utLLFMvw+Z5Ad4XLkZzchscg==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } + }, "node_modules/proc-log": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-5.0.0.tgz", diff --git a/admin/package.json b/admin/package.json index 667bc1f..a7e5988 100644 --- a/admin/package.json +++ b/admin/package.json @@ -28,6 +28,12 @@ "@angular/forms": "^20.3.0", "@angular/platform-browser": "^20.3.0", "@angular/router": "^20.3.0", + "@fullcalendar/angular": "^6.1.19", + "@fullcalendar/core": "^6.1.19", + "@fullcalendar/daygrid": "^6.1.19", + "@fullcalendar/interaction": "^6.1.19", + "@fullcalendar/list": "^6.1.19", + "@fullcalendar/timegrid": "^6.1.19", "@tailwindcss/postcss": "^4.1.17", "daisyui": "^5.4.5", "jwt-decode": "^4.0.0", diff --git a/admin/src/app/app.routes.ts b/admin/src/app/app.routes.ts index 33aa054..5be2c47 100644 --- a/admin/src/app/app.routes.ts +++ b/admin/src/app/app.routes.ts @@ -37,8 +37,19 @@ import { BookingFormComponent } from "./features/bookings/components/booking-for import { BookingDetailsComponent } from "./features/bookings/components/booking-details/booking-details.component"; import { BookingTableComponent } from "./features/bookings/components/booking-table/booking-table.component"; import { BookingListComponent } from "./features/bookings/components/booking-list/booking-list.component"; +import { CalendarView } from './features/calendar/components/calendar-view/calendar-view'; export const routes: Routes = [ + + { + path: 'calendar', + component: CalendarView, + canActivate: [AuthGuard], + data: { + roles: ['admin'], + }, + }, + { path: 'bookings/new', component: BookingFormComponent, diff --git a/admin/src/app/app.ts b/admin/src/app/app.ts index 9a7bb70..b002de5 100644 --- a/admin/src/app/app.ts +++ b/admin/src/app/app.ts @@ -3,18 +3,17 @@ import { Router, RouterOutlet } from '@angular/router'; import { AuthService } from './auth/auth.service'; import { AdminLayoutRs1 } from '../../projects/rschneider/ng-daisyui/src/lib/layout'; import { Menu, MenuItem } from './components/menu/menu'; + @Component({ selector: 'app-root', - imports: [RouterOutlet, AdminLayoutRs1, Menu], + imports: [RouterOutlet, AdminLayoutRs1, Menu], templateUrl: './app.html', styleUrl: './app.css', }) export class App { protected readonly title = signal('admin'); - protected menuConfig: MenuItem[] = [ - - ]; + protected menuConfig: MenuItem[] = []; protected currentUserRoles: string[] = ['admin']; protected menuTitle: string | undefined = 'Menü'; @@ -27,7 +26,7 @@ export class App { svgIcon: ` -` +`, }, { menuText: 'Események', @@ -35,15 +34,23 @@ export class App { svgIcon: ` -` +`, }, - { + { + menuText: 'Naptár', + targetUrl: '/calendar', + svgIcon: ` + + +`, + }, + { menuText: 'Felhasználók', targetUrl: '/user/table', svgIcon: ` -` +`, }, { menuText: 'Felhasználó Csoport', @@ -51,19 +58,19 @@ export class App { svgIcon: ` -` +`, }, -{ + { menuText: 'Felhasználó Szerepek', targetUrl: '/user-role/table', svgIcon: ` -` +`, }, - ] + ]; } logout(): void { @@ -81,8 +88,8 @@ export class App { }); } - loggedIn(){ - return this.authService.isLoggedIn() + loggedIn() { + return this.authService.isLoggedIn(); } } diff --git a/admin/src/app/features/calendar/components/calendar-view/calendar-view.css b/admin/src/app/features/calendar/components/calendar-view/calendar-view.css new file mode 100644 index 0000000..e69de29 diff --git a/admin/src/app/features/calendar/components/calendar-view/calendar-view.html b/admin/src/app/features/calendar/components/calendar-view/calendar-view.html new file mode 100644 index 0000000..c4630dc --- /dev/null +++ b/admin/src/app/features/calendar/components/calendar-view/calendar-view.html @@ -0,0 +1,8 @@ +
+

Naptár

+
+ + add +
+ +
diff --git a/admin/src/app/features/calendar/components/calendar-view/calendar-view.ts b/admin/src/app/features/calendar/components/calendar-view/calendar-view.ts new file mode 100644 index 0000000..396bb93 --- /dev/null +++ b/admin/src/app/features/calendar/components/calendar-view/calendar-view.ts @@ -0,0 +1,85 @@ +import { Component, ElementRef, ViewChild } from '@angular/core'; +import { FullCalendarComponent, FullCalendarModule } from '@fullcalendar/angular'; +import { CalendarOptions } from '@fullcalendar/core'; + +import dayGridPlugin from '@fullcalendar/daygrid'; +import timeGridPlugin from '@fullcalendar/timegrid'; +import listPlugin from '@fullcalendar/list'; +import interactionPlugin from '@fullcalendar/interaction'; +import { appConfig } from '../../../../app.config'; + +@Component({ + selector: 'app-calendar-view', + imports: [FullCalendarModule], + templateUrl: './calendar-view.html', + styleUrl: './calendar-view.css', +}) +export class CalendarView { + + @ViewChild('startHour') startHour!: ElementRef; + @ViewChild('calendar') calendarComponent: FullCalendarComponent | undefined; + + calendarOptions: CalendarOptions; + + constructor() { + const start = new Date(); + start.setHours(10,0,0) + const end = new Date(); + end.setHours(11,0,0) + + this.calendarOptions = { + plugins: [dayGridPlugin, timeGridPlugin, listPlugin,interactionPlugin], + initialView: 'dayGridMonth', + weekends: true, + headerToolbar: { + left: 'prev,next,today', + center: 'title', + // right: 'dayGridMonth,dayGridWeek,dayGridDay' // user can switch between the two + right: 'dayGridMonth,dayGridWeek,dayGridDay,timeGridWeek,timeGridDay,listWeek', + + }, + events: [ + + + { title: 'Meeting1 until'+end.toString(), start, end }, + ], + + eventClick: function(info) { + console.info('Event info: ' , info); + + // change the border color just for fun + info.el.style.borderColor = 'red'; + }, + + dateClick: function(info) { + console.info('Date click on: ' , info); + const calendarApi = info.view.calendar; + const start = new Date(info.date.getTime()) + start.setHours(2,0,0) + const end = new Date(info.date.getTime()) + end.setHours(3,0,0) + calendarApi.addEvent({ + title: 'New Event', + start, + end, + }); + } + + }; + } + + protected addEvent($event: PointerEvent) { + let hourStr = this.startHour.nativeElement.value; + const hour = parseInt(hourStr,10); + const date = new Date() + const start = new Date(date.getTime()) + start.setHours(hour,0,0) + const end = new Date(date.getTime()) + // end.setHours(3,0,0) + + this.calendarComponent?.getApi().addEvent({ + title: 'Event at '+hour, + start + }) + } +}