Our powerful JS Calendar component


Post by smalchow »

Hi Bryntum Team,

we have the following issue:
After updating Bryntum to version 5.3.3 and applying the german Locale, the day cell header of the resources in our resource view is buggy. The presented week does not match the current week. Only after clicking below the header, it jumps to the current week. We did not change anything but adding a new Localization and applying it. Here is the code added to our calendar.js. I also checked if the L usage within the config has something to do with this issue by deleting all L usages. The issue was still present. Only after commenting out the applyLocale statement, the issue was solved. Do you have an idea?

import { Calendar, Combo, Model, Store, LocaleManager, ExternalEventSource, Toast } from "@bryntum/calendar"
import "@bryntum/calendar/locales/calendar.locale.De.js"

const newLocalization = {
    Object: {
        Yes: 'Ja',
        No: 'Nein',
        Cancel: 'Abbrechen',
        Ok: 'OK',
        Week: 'Woche',
        Month: 'Monat',
        newEvent: 'Neues Ereignis',
        'Reset length': 'Ereignisdauer zurücksetzen',
        'Repeat notification': eventName => `Inhalte für Event "${eventName}" werden wiederholt.`,
        'Cut notification': eventName => `Inhalte für Event "${eventName}" werden gekürzt.`,
        'Fit notification': eventName => `Dauer des Events "${eventName}" stimmt mit Inhalten überein.`,

},
EventEdit: {
    Title: 'Titel',
    Group: 'Gruppe',
    Description: 'Notiz',
    Repeat: 'Wiederholen',
},
Tooltip: {
    'Hide group': 'Gruppe ausblenden'
}
}
LocaleManager.applyLocale('De', newLocalization);
Bildschirmfoto 2023-05-09 um 22.20.20.png
Bildschirmfoto 2023-05-09 um 22.20.20.png (179.18 KiB) Viewed 901 times

Best regards


Post by Animal »

Is this the issue?

Screenshot 2023-05-10 at 07.26.54.png
Screenshot 2023-05-10 at 07.26.54.png (14.9 KiB) Viewed 884 times

And that goes away purely if you do not apply a locale?

That's extremely weird. I can't see from the outside how that could affect the layout of the view.

I would need at least the full config of the view (and any subclasses and overrides you apply), and the test data which creates that. If I can reproduce this issue, I can fix it, but I don't have the code.

I updated the examples/localization example to use ResourceView and added that code to it and it looks right.


Post by smalchow »

The problem is that the Calendar Date Picker within the Sidebar initially selects the current date when the calendar is accessed, which in this case is May 9th. Normally, the calendar itself should also display the week of May 9th in the resource view. However, the calendar displays the wrong week, although it is actually the current week in the background. This means that if I create an event in the wrong week and then click on it to edit it – For example, if I had dragged an event to May 4th – it shows May 11th in edit mode, while in the background, the calendar jumps to the correct week.

I have already removed our custom theme completely and used the classic theme, but the problem persists. Additionally, I have cleared the entire newLocalization variable. However, the problem persists as long as applyLocale is applied.

Here is our calendar configuration, which I have reduced to a minimum while retaining the problem:

import { Calendar, Combo, Model, Store, LocaleManager, ExternalEventSource, Toast } from "@bryntum/calendar"
import "@bryntum/calendar/locales/calendar.locale.De.js"

//import "@bryntum/calendar/calendar.material.css";

const newLocalization = {
    Object: {
        Yes: 'Ja',
        No: 'Nein',
        Cancel: 'Abbrechen',
        Ok: 'OK',
        Week: 'Woche',
        Month: 'Monat',
        newEvent: 'Neues Ereignis',
        'Reset length': 'Ereignisdauer zurücksetzen',
        'Repeat notification': eventName => `Inhalte für Event "${eventName}" werden wiederholt.`,
        'Cut notification': eventName => `Inhalte für Event "${eventName}" werden gekürzt.`,
        'Fit notification': eventName => `Dauer des Events "${eventName}" stimmt mit Inhalten überein.`,

},
EventEdit: {
    Title: 'Titel',
    Group: 'Gruppe',
    Description: 'Notiz',
    Repeat: 'Wiederholen',
},
Tooltip: {
    'Hide group': 'Gruppe ausblenden'
}
}
LocaleManager.applyLocale('De', newLocalization);


export default {

mounted() {
    const hook = this;
    const selector = '#' + this.el.id;

    const calendar = new Calendar({
        appendTo: this.el,
        features: {
            filterBar: false,
            drag: {
                creatable: false
            },
            externalEventSource: {
                dragRootElement: 'event-source',
                dragItemSelector: '.draggable-event',
                getRecordFromElement(element) {
                    // Return an object from which an EventModel can be created.
                    // Same format as loading an EventStore. { name : 'name', startDate: ''} etc
                    return createRecordFromElement(element);
                }
            },
            eventTooltip: {
                dateFormat: 'YYYY-MM-DD',
                timeFormat: 'LTS'
            },
        },
        sidebar: {
            items: {
                eventFilter: false,
            }
        },
        crudManager: {
            eventStore: {
                fields: [
                    { name: 'type', type: 'string' },
                    { name: 'initial_duration', dataSource: 'initial_duration', type: 'float' },
                    { name: 'durationUnit', dataSource: 'duration_unit' },
                    { name: 'playlist_id', dataSource: 'playlist_id' },
                    { name: 'asset_id', dataSource: 'asset_id' },
                ]
            },
            transport: {
                load: {
                    url: '/api/v1/calendar/load'
                },
                sync: {
                    url: '/api/v1/calendar/sync'
                }
            },
            autoLoad: true,
            autoSync: true,
            children: true
        },

        modes: {
            day: null,
            week: null,
            month: null,
            year: null,
            agenda: null,

            // Mode name can be anything if it contains a "type" property.
            weekResources: {
                // Type has the final say over which view type is created
                type: 'resource',
                title: 'L{Week}',

                // Specify how wide each resource panel should be
                resourceWidth: '20em',
                hideNonWorkingDays: true,

                // This is a config object for the subviews
                view: {
                    type: 'weekview',
                    visibleStartTime: '07:00',
                    increment: '5 minutes',
                    autoCreate: false,
                },

                // Info to diplay below a resource name
                meta: resource => resource.title
            },
            monthResources: {
                type: 'resource',
                title: 'L{Month}',
                resourceWidth: '30em',
                hideNonWorkingDays: true,

                view: {
                    type: 'monthview'
                },

                meta: resource => resource.title
            }
        }
    });

    function createRecordFromElement(element) {
        var eventRecord = Object.assign({}, element.dataset)
        return eventRecord;
    }
}
}

Here is our test data:



{
  "events": {
    "rows": [
      {
        "$PhantomId": null,
        "asset_id": null,
        "duration_unit": "second",
        "endDate": "2023-05-09T20:52:27Z",
        "exceptionDates": [],
        "id": 1,
        "initial_duration": null,
        "name": "Pre Defined Event",
        "playlist_id": 1,
        "recurrenceRule": null,
        "resourceId": 1,
        "startDate": "2023-05-09T19:52:27Z",
        "type": "playlist"
      },
      {
        "$PhantomId": null,
        "asset_id": 1,
        "duration_unit": "second",
        "endDate": "2023-05-09T00:55:00Z",
        "exceptionDates": [],
        "id": 2,
        "initial_duration": 1.3,
        "name": "Image Asset",
        "playlist_id": null,
        "recurrenceRule": null,
        "resourceId": 1,
        "startDate": "2023-05-08T22:50:00Z",
        "type": "asset"
      },
      {
        "$PhantomId": null,
        "asset_id": 5,
        "duration_unit": "second",
        "endDate": "2023-05-09T01:46:21Z",
        "exceptionDates": [],
        "id": 5,
        "initial_duration": 81,
        "name": "PPT",
        "playlist_id": null,
        "recurrenceRule": null,
        "resourceId": 1,
        "startDate": "2023-05-09T01:45:00Z",
        "type": "asset"
      },
      {
        "$PhantomId": null,
        "asset_id": 5,
        "duration_unit": "second",
        "endDate": "2023-05-11T01:35:00Z",
        "exceptionDates": [],
        "id": 6,
        "initial_duration": 81,
        "name": "PPT",
        "playlist_id": null,
        "recurrenceRule": null,
        "resourceId": 1,
        "startDate": "2023-05-10T01:00:00Z",
        "type": "asset"
      },
      {
        "$PhantomId": null,
        "asset_id": 5,
        "duration_unit": "second",
        "endDate": "2023-05-11T07:56:21Z",
        "exceptionDates": [],
        "id": 9,
        "initial_duration": 81,
        "name": "PPT",
        "playlist_id": null,
        "recurrenceRule": null,
        "resourceId": 1,
        "startDate": "2023-05-11T07:55:00Z",
        "type": "asset"
      },
      {
        "$PhantomId": null,
        "asset_id": 6,
        "duration_unit": "second",
        "endDate": "2023-05-11T11:46:24Z",
        "exceptionDates": [],
        "id": 10,
        "initial_duration": 84,
        "name": "PDF Asset",
        "playlist_id": null,
        "recurrenceRule": null,
        "resourceId": 1,
        "startDate": "2023-05-11T11:45:00Z",
        "type": "asset"
      },
      {
        "$PhantomId": null,
        "asset_id": 1,
        "duration_unit": "second",
        "endDate": "2023-05-09T04:00:00Z",
        "exceptionDates": [],
        "id": 4,
        "initial_duration": 1.3,
        "name": "Image Asset",
        "playlist_id": null,
        "recurrenceRule": null,
        "resourceId": 2,
        "startDate": "2023-05-09T02:05:00Z",
        "type": "asset"
      }
    ],
    "total": 7
  },
  "requestId": 16837122131320,
  "resources": {
    "rows": [
      {
        "eventColor": "#d02c4c",
        "id": 1,
        "name": "Pre Defined Group"
      },
      {
        "eventColor": "#0a7686",
        "id": 2,
        "name": "Kantine"
      }
    ],
    "total": 2
  },
  "success": true
}

Post by Animal »

When I run that locally, I get this:

Screenshot 2023-05-10 at 12.03.16.png
Screenshot 2023-05-10 at 12.03.16.png (432.05 KiB) Viewed 873 times

Post by Animal »

Is there any progress on this? It doesn't seem likely that a locale update could affect the view layout.


Post by smalchow »

We have unfortunately not made any progress and have temporarily removed the translation. It works perfectly fine without it. We cannot explain why this is the case. As mentioned before, only applyLocale triggers this bug. However, in the future, we will have to reintroduce the translation.


Post by Animal »

Best to try to figure it out. What does the DOM look like when you examine that strange looking "Image Asset" all day event block (I assume that is the bug you are referring to)


Post by smalchow »

This is not the bug I am referring to. That was the way I am showing, that an event's duration differs from its initial duration. In the eventRenderer I add a bottom border to the event. I removed the event renderer so that this border disappears but the bug is still present.

C9BD40E0-2C0E-4A8D-B991-4999F69E9371.jpeg
C9BD40E0-2C0E-4A8D-B991-4999F69E9371.jpeg (173.18 KiB) Viewed 796 times

Post by Animal »

What bug?


Post by smalchow »

Do you see that in my screenshot may 26 is selected but the calendar shows the week between may 15 and may 19. The calendar should show may 22 to may 26. After a click in the calendar it jumps to the correct. This is the bug and it's caused by this line:
LocaleManager.applyLocale('De', newLocalization);
not matter if there is data in the variable newLocalization or not and no matter if I use it in the config by calling the L() function or not.


Post Reply