search envelope-o feed check
Home Unanswered Active Tags New Question
user comment-o

OnEventmoving and OnEventMoved drag acts crazy.

Asked by Anonymous
1 year ago.

Please check code and video.

Answer posted by Dan Letecky [DayPilot]
1 year ago.

It behaves as if the Calendar component were updated in the middle of the drag-and-drop movement.

You can see that the source event (which is marked with calendar_default_event_moving_source CSS class when moving starts) is sometimes not semi-transparent (that’s the style applied by calendar_default_event_moving_source). This class is only removed in mouseup event handler or when the Calendar is updated.

I recommend checking the dependency logic - some of the state updates might cause the Calendar to update (probably when some HTTP call or some other asynchronous operation is completed because there is a delay).

You can detect the Calendar updates by handling the onAfterRender event handler.

Comment posted by Anonymous
1 year ago.

How do you suggest to fix it?

Comment posted by Dan Letecky [DayPilot]
1 year ago.

First, add a console.log() message to onAfterRender to track the updates.

If this is indeed the problem, try to find what causes the Calendar update (most likely some state variable change).

  1. Then you can remove that dependency (probably the best solution).

  2. Another option would be to block the UI until everything is processed and updated (to prevent a new drag and drop operation from being started).

In the Scheduler, the loadingStart() and loadingStop() can be used to block the UI using an overlay div. Something like this could be added to the Calendar as well.

Comment posted by Anonymous
1 year ago.

Is there any way i can put a debouncer on event moved? i need those update

Comment posted by Dan Letecky [DayPilot]
1 year ago.

In the component, it’s not necessary to debounce the event because the UI gets updated immediately and a new drag-and-drop operation can only be started when it is complete.

However, if you perform additional asynchronous processing that results in an update, you will need to resolve that.

In the latest sandbox build (2023.4.5804), there are two new options:

  • Block the UI temporarily: You can call loadingStart({block: true}); when you start the asynchronous process and loadingStop() when it is complete. This will show an overlay on top of the Calendar and block access to it.

  • Detect an ongoing drag-and-drop operation: The dragInProgress() returns true if a user drag-and-drop operation is in progress. Do not perform the update in that case.

Blocking the UI temporarily will probably be easier to handle and more transparent to the user.

Comment posted by Anonymous
1 year ago.

Look at my code, how can i access to loading start and loading stop?

Comment posted by Dan Letecky [DayPilot]
1 year ago.

Using calendarRef.current?.control.loadingStart().

Just note that at this moment, it’s only available in the latest sandbox build (see npm.daypilot.org).

Comment posted by Anonymous
1 year ago.

Ok, one more issue. When i upgrade the version, the things i did with calendarREf.current.control.update() don’t work anymore. nothing happens in agenda. why?

Comment posted by Dan Letecky [DayPilot]
1 year ago.

There was no change in the update() logic recently.

The first thing to check would be the calendarRef.current value. If you use calendarRef.current?.control.update() it will fail silently if calendarRef.current is not set.

Otherwise, it depends on the exact code.

Comment posted by Anonymous
1 year ago.
useLayoutEffect(() => {
    if (pickedService.length > 0 && gender !== "") {
        pickedService.forEach((service) => {
            let event = calendarRef.current!.control.events.find(
                service.extra.appointment_id ?? service.service.id_service
            );

            if (service.extra.toDelete === false) {
                if (event !== null) {
                    let clientName = setIsEditingEventPosition(true);
                    calendarRef.current!.control.events.update({
                        id: service.extra.appointment_id ?? service.service.id_service,
                        text: service.service.id_service,
                        start: service.date!["start"],
                        end: service.date!["end"],
                        resource: service.resource?.id ?? 0,
                        cssClass: pickedService.some(
                            (service) => service.extra.appointment_id
                        ) ? "draft_selected_event" : "draft_selected_event",
                        barHidden: true,
                        tag: {
                            marker: service.service.ec_color_light,
                            client: (!name ? "" : name) + " " + (surname ?? (surname || (watchFields.id_cus === undefined ? { m: "Uomo", f: "Donna", b: "Bimbo" }[gender] || "" : extractGenderFromID(watchFields.id_cus!)))),
                            service: service.service.name,
                            writtenNote: note,
                            note: note,
                            heart: service.extra.worker_lock !== "0",
                            clock: service.extra.time_lock !== "0",
                        },
                    });
                } else {
                    setIsEditingEventPosition(true);
                    const event = new DayPilot.Event({
                        id: service.extra.appointment_id ?? service.service.id_service,
                        text: service.service.id_service,
                        start: service.date!["start"],
                        end: service.date!["end"],
                        resource: service.resource.id,
                        barHidden: true,
                        cssClass: "draft_selected_event",
                        tag: {
                            marker: service.service.ec_color_light,
                            service: service.service.name,
                            client: (!name ? "" : name) + " " + (surname ?? (surname || (watchFields.id_cus === undefined ? { m: "Uomo", f: "Donna", b: "Bimbo" }[gender] || "" : extractGenderFromID(watchFields.id_cus!)))),
                            writtenNote: note,
                            note: note,
                            heart: service.extra.worker_lock === "1",
                            clock: service.extra.time_lock === "1",
                        },
                    });

                    calendarRef.current?.control.events.add(event);
                }
            }
        });
    } else {
        // Handle the else condition here if needed
    }
}, [
    pickedService,
    gender,
    deferredQueryName,
    deferredQuerySurname,
    deferredNote,
    isEditListModalOpen,
]);

it works in previous version but not in this one, why?

Comment posted by Anonymous
1 year ago.

it doesn’t tdo any update on the agenda

Comment posted by Dan Letecky [DayPilot]
1 year ago.

Ok, that’s events.update() - let me check that.

Comment posted by Dan Letecky [DayPilot]
1 year ago.

That was a regression. It should be fixed now in build 2023.4.5805.

Comment posted by Anonymous
1 year ago.

oK, thank you. still, with loadingstart and stop i can’t seem to block ui. Event hte code doesn’t recognize block: true as parameter.

// scroll
onEventMoved: async (args: any) => {
    // dispatch(updateIsInEventMovingMode(false));

    calendarRef.current?.control.loadingStart();
    setIsMovingInAgenda(false);
    const eventId = args.e.data.id;
    calendarRef.current?.control.clearSelection();

    const start = args.newStart;
    const end = args.newEnd;
    const resource = args.newResource;

    const startDate = moment(start.toString());
    const endDate = moment(end.toString());
    const minutesDifference = endDate.diff(startDate, "minutes");

    dispatch(
        updateAppointmentDate({
            id: eventId,
            start: toMoment(start).add(1, 'hour').toISOString(),
            end: toMoment(end).add(1, 'hour').toISOString(),
            resource: resource,
            duration: minutesDifference,
            calendarDate: moment(calendarDate).format("YYYY-MM-DD"),
        })
    );

    // appuntamento anonimo
    if (isNaN(Number(eventId))) {
        await AppointmentsAPI.update(
            authProvider.storeId!,
            eventId,
            [{
                app_date: start,
                id_staff: resource,
            }],
            authProvider.email,
            authProvider.pin,
            authProvider.token
        );

        await ConfigAPI.refreshDays(
            authProvider.storeId!,
            authProvider.email,
            authProvider.token!,
            authProvider.pin!,
            moment(calendarDate).format("YYYY-MM-DD")
        ).then((response) => {
            setUpdatedEvent(response?.data!);
        });
    }

    const eventsFromCalendar = calendarRef
        .current!.control.events.list.filter((event) =>
            pickedService.some(
                (service) =>
                    (service.extra.appointment_id ?? service.service.id_service) === event.id
            )
        )
        .sort((a, b) => toMoment(a.start).isBefore(toMoment(b.start)) ? -1 : 1);

    for (let i = 0; i < eventsFromCalendar.length - 1; i++) {
        let poseDuration = toMoment(
            eventsFromCalendar[i + 1].id === eventId
                ? args.newStart
                : (eventsFromCalendar[i + 1].start as any)
        ).diff(
            toMoment(
                eventsFromCalendar[i].id === eventId
                    ? args.newEnd
                    : (eventsFromCalendar[i].end as any)
            ),
            "minutes"
        );

        if (poseDuration < 0) {
            poseDuration = 0;
        }

        eventsFromCalendar[i].poseDuration = poseDuration.toString();
    }

    const pickedServices = pickedService.sort((a, b) =>
        toMoment(a.date.start).isBefore(toMoment(b.date.start)) ? -1 : 1
    );

    pickedServices.forEach((pickedService) => {
        const event = eventsFromCalendar
            .find((e) => e.id === (pickedService.extra.appointment_id ?? pickedService.service.id_service));

        if (event) {
            pickedService.date.start = event.start;
            pickedService.date.end = event.end;
            pickedService.extra.poseDuration = parseInt(event.poseDuration ?? pickedService.extra.poseDuration);
            pickedService.extra.duration = toMoment(event.end).diff(toMoment(event.start), 'minutes');

            if (event.id === eventId) {
                const employees = settings.tableConfig?.employees || [];
                pickedService.resource = employees.find((e) => e.id === args.newResource)!

                pickedService.date.start = args.newStart;
                pickedService.date.end = args.newEnd;
            }
        }
    })

    setPickedServices([...pickedService]);
    calendarRef.current?.control.stop();
},

please check

Comment posted by Anonymous
1 year ago.

Plus, i can’t seem to install the build with .update fixed, it says not found. please help c:

Comment posted by Dan Letecky [DayPilot]
1 year ago.

To test both these things, you will need to install the latest trial version (2023.4.5805 or higher) from npm.daypilot.org. The sandbox build is only available as a trial.

Comment posted by Anonymous
1 year ago.

Yes, but i’ve paid for the pro version and i need the stuff

Comment posted by Anonymous
1 year ago.

Can we find a solutions? this is a commercial product to us

Comment posted by Dan Letecky [DayPilot]
1 year ago.

The next release is scheduled for December 1 (see also https://release.daypilot.org/changes/js/) and it will include these changes. The sandbox build is not production quality.

Comment posted by Anonymous
1 year ago.

Yes, but i need this things before, above all the blocking ui things. any further solutions?

Comment posted by Dan Letecky [DayPilot]
1 year ago.

You can also try disabling the event moving temporarily using eventMoveHandling:

calendarRef.current?.control.eventMoveHandling = "Disabled";

It must be set using calendarRef and not using the config state variable (that would cause an extra update).

Comment posted by Anonymous
1 year ago.

It’s ok as a solution. But i would like something more smooth (since it’s waiting for two network requests, it’s a lil bit slow). Maybe a debounce onEventMoved so that it acts only if the event is standinf for like x seconds?

This question is more than 1 months old and has been closed. Please create a new question if you have anything to add.