Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resize handle on event it's disappearing #1753

Open
ViktorDimitrievski opened this issue Nov 26, 2024 · 1 comment
Open

Resize handle on event it's disappearing #1753

ViktorDimitrievski opened this issue Nov 26, 2024 · 1 comment

Comments

@ViktorDimitrievski
Copy link

Hello mattlewis92,
Frist of all thank you for the angular-calendar library which is awesome work that you have done!

Describe the bug

After extensively using the Angular Calendar library, I encountered an issue that I believe might be a bug. However, it could also be an intended feature, and I couldn't find a definitive answer in the available examples or documentation.

To investigate further, I created an isolated project using the Angular Calendar library to reproduce the issue I faced in my main project.

Background:

  • The user can click on any segment to create an event.
  • Events can be resized
  • The calendar is set with specific hour limits ([dayStartHour]="9" [dayEndHour]="16").

Issue:
When a user resizes an event to the end limit of the day, the mwlResizeHandle disappears. This behavior makes it impossible to resize the event back to a shorter duration (e.g., reducing from 6 hours to 4 hours) by dragging from bottom to top, as the resize handle is no longer visible.

Supporting Information:

  • I have prepared two screenshots to illustrate the issue.
  • The code (TS and HTML files) used to reproduce this behavior is attached for your reference.

Please let me know if this is indeed a bug or expected behavior, and if there’s a workaround. Thank you for your time and assistance!

Minimal reproduction of the problem with instructions
ts file

import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ViewEncapsulation } from '@angular/core';
import {
	CalendarEvent,
	CalendarEventTimesChangedEvent,
	CalendarModule,
	CalendarView,
	CalendarWeekViewBeforeRenderEvent,
} from 'angular-calendar';
import { addHours, isBefore, isSameDay, setDay, setHours, setMinutes, startOfDay, subSeconds } from 'date-fns';
import { Subject } from 'rxjs';

export const colors: any = {
	red: {
		primary: '#ad2121',
		secondary: '#FAE3E3',
	},
	blue: {
		primary: '#1e90ff',
		secondary: '#D1E8FF',
	},
	yellow: {
		primary: '#e3bc08',
		secondary: '#FDF1BA',
	},
};

@Component({
	selector: 'app-preview',
	templateUrl: './preview.component.html',
	standalone: true,
	changeDetection: ChangeDetectionStrategy.OnPush,
	encapsulation: ViewEncapsulation.None,
	styles: [
		`
			.invalid-position .cal-event {
				background-color: #ad2121 !important;
				color: #fff;
			}

			.cal-disabled {
				background-color: #eee;
				pointer-events: none;
			}
		`,
	],
	imports: [CalendarModule],
})
export class PreviewComponent {
	dayStartHour = 9;
	dayEndHour = 16;
	todayDate = new Date();
	view: CalendarView = CalendarView.Week;

	viewDate = new Date();

	events: CalendarEvent[] = [
		{
			start: addHours(startOfDay(setDay(new Date(), 3)), 2),
			end: subSeconds(addHours(startOfDay(setDay(new Date(), 3)), 3), 1),
			title: 'An short event',
			color: colors.yellow,
			resizable: {
				beforeStart: true,
				afterEnd: true,
			},
			draggable: true,
		},
		{
			start: addHours(startOfDay(setDay(new Date(), 3)), 5),
			end: subSeconds(addHours(startOfDay(setDay(new Date(), 3)), 10), 1),
			title: 'A draggable and resizable event',
			color: colors.yellow,
			resizable: {
				beforeStart: true,
				afterEnd: true,
			},
			draggable: true,
		},
	];

	refresh = new Subject<void>();

	constructor(private cdr: ChangeDetectorRef) {}
	ngOnInit() {
		var event: CalendarEvent = {
			start: setHours(setMinutes(new Date(), 20), 16),
			end: setHours(setMinutes(new Date(), 40), 18),
			cssClass: 'invalid-position',
			title: 'After limit and red event',
			resizable: {
				beforeStart: false,
				afterEnd: false,
			},
			draggable: false,
		};
                 /**just for testing */
		setTimeout(() => {
			this.events = [...this.events, event];
			this.cdr.detectChanges();
		}, 5000);
	}

	validateEventTimesChanged = (
		{ event, newStart, newEnd, allDay }: CalendarEventTimesChangedEvent,
		addCssClass = true
	) => {
		if (event.allDay) {
			return true;
		}
		if (newEnd == undefined) {
			newEnd = setHours(newStart, 1);
		}
		delete event.cssClass;
		// don't allow dragging or resizing events to different days
		const sameDay = isSameDay(newStart, newEnd);

		if (!sameDay) {
			return false;
		}

		// don't allow dragging events to the same times as other events
		const overlappingEvent = this.events.find((otherEvent) => {
			return (
				otherEvent !== event &&
				!otherEvent.allDay &&
				((otherEvent.start < newStart && newStart < (otherEvent.end ?? new Date())) ||
					(otherEvent.start < newEnd && newStart < (otherEvent.end ?? new Date())))
			);
		});

		if (overlappingEvent) {
			if (addCssClass) {
				event.cssClass = 'invalid-position';
			} else {
				return false;
			}
		}

		return true;
	};

	eventTimesChanged(eventTimesChangedEvent: CalendarEventTimesChangedEvent): void {
		delete eventTimesChangedEvent.event.cssClass;
		if (this.validateEventTimesChanged(eventTimesChangedEvent, false)) {
			const { event, newStart, newEnd } = eventTimesChangedEvent;
			event.start = newStart;
			event.end = newEnd;
			this.refresh.next();
		}
	}

	beforeWeekViewRender(renderEvent: CalendarWeekViewBeforeRenderEvent) {
		renderEvent.hourColumns.forEach((hourColumn) => {
			const date = addHours(this.todayDate, 48);
			hourColumn.hours.forEach((hour) => {
				hour.segments.forEach((segment) => {
					delete segment.cssClass;
					debugger;
					if (isBefore(segment.date, date)) {
						segment.cssClass = 'cal-disabled';
					}
				});
			});
		});
	}
}

HTML file

  <mwl-calendar-week-view
    [viewDate]="viewDate"
    [events]="events"
    [refresh]="refresh"
    [dayStartHour]="dayStartHour"
	  [dayEndHour]="dayEndHour"
    (beforeViewRender)="beforeWeekViewRender($event)"
    [validateEventTimesChanged]="validateEventTimesChanged"
    (eventTimesChanged)="eventTimesChanged($event)"
  >
  </mwl-calendar-week-view>

Screenshots

before-limit
after=hitting-limit

Versions

  • package.json
  "dependencies": {
    "@angular/animations": "^18.2.0",
    "@angular/common": "^18.2.0",
    "@angular/compiler": "^18.2.0",
    "@angular/core": "^18.2.0",
    "@angular/forms": "^18.2.0",
    "@angular/platform-browser": "^18.2.0",
    "@angular/platform-browser-dynamic": "^18.2.0",
    "@angular/router": "^18.2.0",
    "angular-calendar": "^0.31.1",
    "date-fns": "^4.1.0",
    "rxjs": "~7.8.0",
    "tslib": "^2.3.0",
    "zone.js": "~0.14.10"
  },
  • Browser name and version:
    Chrome 131.0.6778.86 (Official Build) (64-bit)
@matts-bot
Copy link

matts-bot bot commented Nov 26, 2024

Thanks so much for opening an issue! If you'd like to support this project, then please consider sponsoring me

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant