Overlapped Events issue for Buffered Renderer

Discuss issues related to v5.x
User avatar
jonathan
Premium Member
Premium Member
Posts: 77
Joined: Thu Apr 12, 2018 1:54 pm

Overlapped Events issue for Buffered Renderer

Post by jonathan » Sun Jan 27, 2019 4:24 pm

Dear Bryntum team,

We are using Bryntum ExtJS Scheduler 5.1.8, found an issue for overlapped events when big data set, i.e., Scrolling up/down will act weird when there are overlapped events(the overlapped events must be spreading randomly among the resources, e.g., 1 - 30 resources have no events, 30 - 40 resources each have 10 overlapped events, 41 - 70 resources have no events, 71 - 80 resources each have 10 overlapped events, 81 - 110 resources have no events, etc...). Please see attached screen recordings for detail.

1. Scroll down will scroll back to scrolled resources, and there's empty space at the top.
buffer_render_issue-version_5.mov.zip
Scroll down will scroll back to scrolled resources, and there's empty space at the top.
(3.09 MiB) Downloaded 33 times
2. Even using latest version - 6.0.8, still have resources hidden or empty space at the bottom issues.
buffer_render_issue-version_6.mov.zip
At first, resources are hidden, after re-generate, empty space appears at the bottom.
(3.71 MiB) Downloaded 34 times
To reproduce above issues, you can change the examples/bigdataset/app/view/Scheduler.js as below.

Code: Select all

Ext.define('Sch.examples.bigdataset.view.Scheduler', {
    extend : 'Sch.panel.SchedulerGrid',
    xtype  : 'bigdatasetscheduler',

    requires : [
        'Sch.examples.bigdataset.view.SchedulerViewController'
    ],

    controller : 'bigdatasetscheduler',
    barMargin  : 2,
    rowHeight  : 35,
    title      : 'Big Data Set',
    bodyBorder : false,
    split      : false,
    viewPreset : 'monthAndYear',
    startDate  : new Date(2017, 0, 1),
    endDate    : new Date(2019, 11, 31),

    eventRenderer : function (item, r, tplData, row, col, ds, index) {
        return item.get('Name');
    },

    // Setup static columns
    columns : [
        { header : 'Name', sortable : true, width : 160, dataIndex : 'Name' }
    ],

    header : {
        items: [
            {
                xtype: 'label',
                text : 'Resources',
                style: 'margin-right: 5px'
            },
            {
                xtype    : 'numberfield',
                emptyText: 'Persons',
                cls      : 'resources-field',
                itemId   : 'resources',
                step     : 100,
                value    : 100,
                minValue : 10,
                listeners : {
                    specialkey : 'onSpecialKey'
                }
            }, {
                xtype: 'label',
                text : 'x Events',
                style: 'margin: 0 10px 0 10px'
            }, {
                xtype    : 'numberfield',
                emptyText: 'Events',
                style    : 'margin-right: 10px',
                cls      : 'events-field',
                itemId   : 'events',
                step     : 10,
                minValue : 10,
                value    : 10,
                listeners : {
                    specialkey : 'onSpecialKey'
                }
            },
            {
                xtype : 'button',
                itemId: 'generateData',
                text  : 'Generate'
            }
        ]
    },

    onRender : function () {
        this.callParent();

        this.down('#generateData').on('click', this.loadDataIntoStores, this);
        this.loadDataIntoStores();
    },

    loadDataIntoStores : function () {
        var me        = this,
            resources = me.down('#resources').getValue(),
            events    = me.down('#events').getValue();

        me.getSchedulingView().scrollVerticallyTo(0);

        me.el.mask('Generating ' + (resources * events) + ' events');

        Ext.defer(function () {
            if (me.destroyed) {
                return;
            }
            // generate events based on user input
            var data = me.generateEvents(resources, events);

            // update stores with generated events
            me.suspendRefresh();
            me.getResourceStore().loadData(data.resources);
            me.getEventStore().loadData(data.events);
            me.resumeRefresh(true);
            me.el.unmask();

        }, 20);
    },

    generateEvents : function (numResources, eventsPerResource) {
        var k          = 0,
            firstNames = [
                'Mike', 'Linda', 'Don', 'Karen', 'Doug', 'Peter', 'Daniel', 'Jorge', 'John', 'Jane', 'Theo', 'Lisa',
                'Adam', 'Mary', 'Barbara', 'James', 'David'
            ],

            surNames   = [
                'McGregor', 'Ewans', 'Scott', 'Smith', 'Johnson', 'Adams', 'Williams', 'Brown', 'Jones', 'Miller',
                'Davis', 'More', 'Wilson', 'Taylor', 'Anderson', 'Thomas', 'Jackson'
            ],

            people     = [],
            events     = [];

        var iii = 0;
        var ttt = 0;

        // generate resources & events
        for (var i = 0; i < numResources; i++) {
            // resource
            var name   =
                    firstNames[ i % (firstNames.length - 1) ] +
                    ' ' +
                    String.fromCharCode(65 + (k % 25)) + // initial
                    ' ' +
                    surNames[ k % (surNames.length - 1) ],

                person = { Id : 'r' + (i + 1), Name : 'Resource-' + (i+1) };

            people.push(person);


            if (ttt <=0) {
              if (++iii > 30) {
                ttt = 10;
              } else {
                continue
              }
            } else if (--ttt <= 0) {
                iii = 0
                continue;
            }

            var startDate = new Date(2017 + (k % 3), k % 12, k % 28);
            // events
            for (var j = 0; j < eventsPerResource; j++) {

                events.push({
                    ResourceId : person.Id,
                    Name       : 'Event ' + (events.length + 1),
                    StartDate  : startDate,
                    EndDate    : Ext.Date.add(startDate, Ext.Date.MONTH, (k % 3) + 1)
                });

                k++;
            }
        }

        return {
            resources : people,
            events    : events
        };
    }
});
Please help advise.

Thanks in advance,
Jonathan

User avatar
mats
Premium Member
Premium Member
Posts: 15621
Joined: Sat Dec 19, 2009 11:41 pm
Location: Sweden
Contact:

Re: Overlapped Events issue for Buffered Renderer

Post by mats » Sun Jan 27, 2019 4:29 pm

Which browser? Which Ext JS version?

Could you please try using our latest version, and see if it's still reproducible?
Tired of debugging javascript errors in web applications? Try our new error logging service RootCause, or read more on the Sencha blog

@bryntum
Facebook
API documentation

User avatar
jonathan
Premium Member
Premium Member
Posts: 77
Joined: Thu Apr 12, 2018 1:54 pm

Re: Overlapped Events issue for Buffered Renderer

Post by jonathan » Sun Jan 27, 2019 5:09 pm

Hi Mats,

Thanks for the reply, we are using ExtJS 6.5.2, Chrome 71.0.3578.98. Tried 6.0.8 bigdataset example, scroll up/down looks not reproducible, but facing other issues - "resources hidden or empty space at the bottom issues". Pls see above attached buffer_render_issue-version_6.mov.zip for detail.

Thanks,
Jonathan

User avatar
pmiklashevich
Core Developer
Core Developer
Posts: 2579
Joined: Fri Apr 01, 2016 11:08 am

Re: Overlapped Events issue for Buffered Renderer

Post by pmiklashevich » Mon Jan 28, 2019 10:53 am

Hello Jonathan,

Thank you for the report. This issue has been reported to us recently, but I'm afraid we don't have a solution to fix it yet. Please see the original thread: viewtopic.php?f=49&t=10274

Best,
Pavel
Pavel Miklashevich - Core Developer

User avatar
pmiklashevich
Core Developer
Core Developer
Posts: 2579
Joined: Fri Apr 01, 2016 11:08 am

Re: Overlapped Events issue for Buffered Renderer

Post by pmiklashevich » Mon Apr 08, 2019 2:14 pm

Hello,

Could you please try to configure your scheduler with syncRowHeight enabled?

Code: Select all

new Sch.panel.SchedulerGrid({
    syncRowHeight : true,
});
Please let me know if this solution works for you.

Regards,
Pavel
Pavel Miklashevich - Core Developer

User avatar
jonathan
Premium Member
Premium Member
Posts: 77
Joined: Thu Apr 12, 2018 1:54 pm

Re: Overlapped Events issue for Buffered Renderer

Post by jonathan » Wed Jul 17, 2019 1:48 pm

Hello @Pavel,

We tried your suggestion, looks it works for the issue "resources hidden or empty space", but it introduced another jumping issue when updating the timespan, e.g., add next date to the current timeline.

Reproduce steps.
1. Update the examples/bigdataset/app/view/Scheduler.js as below

Code: Select all

Ext.define('Sch.examples.bigdataset.view.Scheduler', {
    extend : 'Sch.panel.SchedulerGrid',
    xtype  : 'bigdatasetscheduler',

    requires : [
        'Sch.examples.bigdataset.view.SchedulerViewController'
    ],

    syncRowHeight : true,

    controller : 'bigdatasetscheduler',
    barMargin  : 2,
    rowHeight  : 35,
    title      : 'Big Data Set',
    bodyBorder : false,
    split      : false,
    viewPreset : 'monthAndYear',
    startDate  : new Date(2017, 0, 1),
    endDate    : new Date(2019, 11, 31),

    eventRenderer : function (item, r, tplData, row, col, ds, index) {
        return item.get('Name');
    },

    // Setup static columns
    columns : [
        { header : 'Name', sortable : true, width : 160, dataIndex : 'Name' }
    ],

    header : {
        items: [
            {
                xtype: 'label',
                text : 'Resources',
                style: 'margin-right: 5px'
            },
            {
                xtype    : 'numberfield',
                emptyText: 'Persons',
                cls      : 'resources-field',
                itemId   : 'resources',
                step     : 100,
                value    : 100,
                minValue : 10,
                listeners : {
                    specialkey : 'onSpecialKey'
                }
            }, {
                xtype: 'label',
                text : 'x Events',
                style: 'margin: 0 10px 0 10px'
            }, {
                xtype    : 'numberfield',
                emptyText: 'Events',
                style    : 'margin-right: 10px',
                cls      : 'events-field',
                itemId   : 'events',
                step     : 10,
                minValue : 10,
                value    : 10,
                listeners : {
                    specialkey : 'onSpecialKey'
                }
            },
            {
                xtype : 'button',
                itemId: 'generateData',
                text  : 'Generate'
            },
            {
                xtype : 'button',
                itemId: 'addNextDate',
                text  : 'Add Next Date',
                handler: function() {
                    const scheduler = this.up('bigdatasetscheduler')
                    window.t = scheduler
                    scheduler.setEndDate(Sch.util.Date.add(scheduler.getEndDate(), 'd', 1))
                }
            }
        ]
    },

    onRender : function () {
        this.callParent();

        this.down('#generateData').on('click', this.loadDataIntoStores, this);
        this.loadDataIntoStores();
    },

    loadDataIntoStores : function () {
        var me        = this,
            resources = me.down('#resources').getValue(),
            events    = me.down('#events').getValue();

        me.getSchedulingView().scrollVerticallyTo(0);

        me.el.mask('Generating ' + (resources * events) + ' events');

        Ext.defer(function () {
            if (me.destroyed) {
                return;
            }
            // generate events based on user input
            var data = me.generateEvents(resources, events);

            // update stores with generated events
            me.suspendRefresh();
            me.getResourceStore().loadData(data.resources);
            me.getEventStore().loadData(data.events);
            me.resumeRefresh(true);
            me.el.unmask();

        }, 20);
    },

    generateEvents : function (numResources, eventsPerResource) {
        var k          = 0,
            firstNames = [
                'Mike', 'Linda', 'Don', 'Karen', 'Doug', 'Peter', 'Daniel', 'Jorge', 'John', 'Jane', 'Theo', 'Lisa',
                'Adam', 'Mary', 'Barbara', 'James', 'David'
            ],

            surNames   = [
                'McGregor', 'Ewans', 'Scott', 'Smith', 'Johnson', 'Adams', 'Williams', 'Brown', 'Jones', 'Miller',
                'Davis', 'More', 'Wilson', 'Taylor', 'Anderson', 'Thomas', 'Jackson'
            ],

            people     = [],
            events     = [];

        var iii = 0;
        var ttt = 0;

        // generate resources & events
        for (var i = 0; i < numResources; i++) {
            // resource
            var name   =
                    firstNames[ i % (firstNames.length - 1) ] +
                    ' ' +
                    String.fromCharCode(65 + (k % 25)) + // initial
                    ' ' +
                    surNames[ k % (surNames.length - 1) ],

                person = { Id : 'r' + (i + 1), Name : 'Resource-' + (i+1) };

            people.push(person);


            if (ttt <=0) {
              if (++iii > 30) {
                ttt = 10;
              } else {
                continue
              }
            } else if (--ttt <= 0) {
                iii = 0
                continue;
            }

            var startDate = new Date(2017 + (k % 3), k % 12, k % 28);
            // events
            for (var j = 0; j < eventsPerResource; j++) {

                events.push({
                    ResourceId : person.Id,
                    Name       : 'Event ' + (events.length + 1),
                    StartDate  : startDate,
                    EndDate    : Ext.Date.add(startDate, Ext.Date.MONTH, (k % 3) + 1)
                });

                k++;
            }
        }

        return {
            resources : people,
            events    : events
        };
    }
});
2. Open bigdataset sample, and scroll to Resource-74.
3. Click "Add Next Date" button, you'll see the Scheduler is jumping from Resource-74 to Resource-31.

Thanks,
Jonathan

User avatar
pmiklashevich
Core Developer
Core Developer
Posts: 2579
Joined: Fri Apr 01, 2016 11:08 am

Re: Overlapped Events issue for Buffered Renderer

Post by pmiklashevich » Thu Jul 18, 2019 7:58 pm

Thanks for your feedback Jonathan, I've updated https://app.assembla.com/spaces/bryntum/tickets/7417-missing-rows-in-scheduler-when-buffered-rendering-is-enabled/details with your findings. Also please keep in mind that there is another downside: after resizing or moving events the vertical scroll is reset.
Pavel Miklashevich - Core Developer

User avatar
jonathan
Premium Member
Premium Member
Posts: 77
Joined: Thu Apr 12, 2018 1:54 pm

Re: Overlapped Events issue for Buffered Renderer

Post by jonathan » Fri Jul 19, 2019 5:30 am

Thanks @pavel.

User avatar
mats
Premium Member
Premium Member
Posts: 15621
Joined: Sat Dec 19, 2009 11:41 pm
Location: Sweden
Contact:

Re: Overlapped Events issue for Buffered Renderer

Post by mats » Fri Dec 06, 2019 6:19 pm

Fixed in our sources, coming out in the next patch release!
Tired of debugging javascript errors in web applications? Try our new error logging service RootCause, or read more on the Sencha blog

@bryntum
Facebook
API documentation

User avatar
mats
Premium Member
Premium Member
Posts: 15621
Joined: Sat Dec 19, 2009 11:41 pm
Location: Sweden
Contact:

Re: Overlapped Events issue for Buffered Renderer

Post by mats » Thu Feb 27, 2020 10:41 am

@Jonathan All working ok?
Tired of debugging javascript errors in web applications? Try our new error logging service RootCause, or read more on the Sencha blog

@bryntum
Facebook
API documentation

Post Reply