Discuss anything related to web development but no technical support questions


Post by john.ubeeo »

I have a question. The moment I get calendars in my code I want to be able to when I change the calendar in the eventEdit section that it will automatically update the step in the eventEdit. But as soon as I console.log the calendars from the listener, I get an empty array. Any idea on what I am doing wrong?

import React, {useEffect, useRef, useState} from 'react';
import {BryntumCombo, BryntumComboProps} from "@bryntum/core-react-thin";
import {Calendar, CalendarConfig, EventEdit} from "@bryntum/calendar-thin";
import {useTranslation} from "react-i18next";
import {createRoot} from "react-dom/client";
import {UseVirtualCalendar} from "./hook/UseVirtualCalendar";
import {VirtualCalendar, VirtualCalendarEvent} from "./interfaces/VirtualCalendarModels";
import {Field, MessageDialog} from "@bryntum/core-thin";
import {BryntumCalendar} from "@bryntum/calendar-react-thin";

interface IProps {
    webPageId: number
}

interface BryntumChangeEvent {
    source: Field
    value: String
    oldValue: String
    valid: Boolean
    event: Event
}

const virtualCalendar = {

VirtualCalendarView: function ({webPageId}: IProps): React.ReactElement {
    const {t} = useTranslation();
    const [disabledCronofyTimeSlot, setDisabledCronofyTimeSlot] = useState(true)
    const [selectedTrackType, setSelectedTrackType] = useState<string | number | object | string[] | number[]>()
    const [selectedCronofyTimeSlotDuration, setSelectedCronofyTimeSlotDuration] = useState<number>(0)
    const [calendarKey, setCalendarKey] = useState<number>(0)

    const {
        calendars,
        setCalendars,
        events,
        durations,
        addEvent,
        editEvent,
        deleteEvent
    } = UseVirtualCalendar(webPageId);

    const calendarRef      = useRef<BryntumCalendar>(null);
    const calendarInstance = () => calendarRef.current?.instance as Calendar;

    const [eventEditStep, setEventEditStep] = useState<number>(0);

    function changeEventEditStep(){
        console.log(calendars)
    }

    function checkTimeSlot(trackType: BryntumComboProps) {
        if (!calendars) return;
        if (!trackType.value) return;
        const calendar = calendars.find((resource: VirtualCalendar) => resource.id === trackType.value)
        setSelectedTrackType(trackType.value)
        setSelectedCronofyTimeSlotDuration(calendar?.cronofyTimeSlot ?? 0);
        setDisabledCronofyTimeSlot(calendar?.cronofyTimeSlot !== null)
    }

    function setCronofyTimeSlot(timeSlot: BryntumComboProps) {
        if (+timeSlot.value! === 0) return;
        setDisabledCronofyTimeSlot(true)
        setCalendars((prevCalendars) => {
            return prevCalendars.map((calendar) => {
                if (calendar.id === selectedTrackType) {
                    return {
                        ...calendar,
                        cronofyTimeSlot: +timeSlot.value!,
                    };
                }
                return calendar;
            });
        });
    }

    useEffect(() => {
        setCalendarKey(prevKey => prevKey + 1);
    }, [calendars, durations, events]);


    const calendarConfig: Partial<CalendarConfig> = {
        eventEdit: {
            items: {
                allDay: null,
                nameField: null,
                resourceField: {
                    label: t("trackTypes"),
                    listeners: {
                        change(event: BryntumChangeEvent) {
                            changeEventEditStep()
                        },
                    },
                    type: "combo",
                    picker: {
                        allowGroupSelect: false
                    },
                    multiSelect: false,
                    editable: false,
                    weight: 0,
                    required: true
                },
                recurrenceCombo: null
            },
        }
    };
    
    return <div key={calendarKey} style={{width: '100%', height: '95%', position: 'absolute', top: 0}}>
        <p style={{margin: 10, marginBottom: 0}}>{t("duration.select")}</p>
        <div style={{display: 'flex'}}>
            <BryntumCombo margin={10} flex={1} onChange={checkTimeSlot} items={calendars} valueField={'id'}
                          displayField={'name'} placeholder={t("trackType.choose")}/>
            <BryntumCombo margin={10} value={selectedCronofyTimeSlotDuration} onChange={setCronofyTimeSlot}
                          valueField={'ID'} displayField={'VALUE'} disabled={disabledCronofyTimeSlot}
                          tooltip={t("duration.tooltip")}
                          items={durations} placeholder={t("duration.fill")}/>
        </div>
        <BryntumCalendar
            ref={ calendarRef }
            {...calendarConfig}
            masked={(!durations.length || !calendars || !events) ? {
                text: `${t('loading')}`,
                mode: "bright"
            } : undefined}
            height={'92%'}
            resources={calendars.filter(resource => resource.cronofyTimeSlot != null)}
            events={events!}
            config={calendarConfig}
            mode={"week"}
            weekStartDay={1}
            modes={{
                day: null,
                agenda: null,
            }}
            listeners={{
                beforeEventSave: async (event: VirtualCalendarEvent) => {
                    let calendarEvent = event.eventRecord.data;
                    calendarEvent.resourceId = event.values.resource.data.id
                    event.newStartDate = event.values.startDate
                    event.newEndDate = event.values.endDate
                    if (!calendarEvent.eventId) return addEvent(event)
                    const calendarName = calendars.find(calendar => calendar.id === calendarEvent.resourceId)?.name;
                    event.eventRecord.name = calendarName ?? calendarEvent.name
                    return editEvent(event);
                },
                beforeEventDelete: async (event: VirtualCalendarEvent) => {
                    return deleteEvent(event);
                },
                beforeDragMoveEnd: async (event: VirtualCalendarEvent) => {
                    if (event.newEndDate.getTime() < new Date().getTime()) {
                        MessageDialog.alert({
                            title: t('virtualCalendar.event.cantSave'),
                            message: t('virtualCalendar.error.eventInHistory')
                        });
                        return false;
                    }
                    return editEvent(event)
                },
                beforeDragResizeEnd: async (event: VirtualCalendarEvent) => {
                    if (event.newEndDate.getTime() < new Date().getTime()) {
                        MessageDialog.alert({
                            title: t('virtualCalendar.event.cantSave'),
                            message: t('virtualCalendar.error.eventInHistory')
                        });
                        return false;
                    }
                    return editEvent(event)
                },
                beforeEventEditShow({ eventEdit }: { eventEdit:  EventEdit }) {
                    console.log(eventEdit)
                    eventEdit.startTimeField.step = 30
                    // eventEdit.items.add({"startTimeField": {step: 30}})
                    // return {source, eventEdit, eventRecord, resourceRecord, eventElement, editor }
                }
            }}
        />
    </div>
},

createComponent: function (reactContainer: HTMLDivElement, {webPageId}: IProps): void {
    let virtualCalendarComponent = React.createElement(virtualCalendar.VirtualCalendarView, {webPageId: webPageId});
    createRoot(reactContainer).render(virtualCalendarComponent)
}
}

export default virtualCalendar

Post by marcio »

Hey john.ubeeo,

Thanks for reaching out.

resourceField is a Combo, so you need to check the combo events. Instead of change, you should use https://bryntum.com/products/calendar/docs/api/Core/widget/Combo#event-action

resourceField : {
                    listeners : {
                        action : ev => console.log(ev)
                    }
                }

You can test it here https://bryntum.com/products/calendar/examples/eventedit/

Best regards,
Márcio


Post by john.ubeeo »

Thanks for the response Marcio! I also have found another solution to the issue I had and that was through reference:

change(event: {source : Field, value: String, oldValue : String, valid : Boolean, event : Event, userAction: boolean}){
                            const find: VirtualCalendar | undefined = calendarRef.current?.instance.resources.find(resource => resource.id === calendarInstance().features.eventEdit.resourceField.value) as VirtualCalendar;
                            if (!find) return;
                            const
                                startTime = new Date(calendarInstance().features.eventEdit.startTimeField.value).getTime(),
                                endTime = new Date(calendarInstance().features.eventEdit.endTimeField.value).getTime();
                            let difference = 0
                            if (find.cronofyTimeSlot && (endTime - startTime) < find.cronofyTimeSlot){
                                difference = (startTime / 1000 / 60) + find.cronofyTimeSlot
                            }else{
                                difference = (((endTime - startTime) / 1000 / 60) % (find.cronofyTimeSlot? find.cronofyTimeSlot : 30))
                            }
                            calendarInstance().features.eventEdit.endTimeField.value = new Date(new Date(calendarInstance().features.eventEdit.endTimeField.value).getTime() - difference * 1000 * 60)
                        }

Post Reply