Premium support for our pure JavaScript UI components


Post by cubrilo »

Hi,

I am trying to use the toolbar checkbox to toggle between 24h and working hours, and trying to use this to update the configuration:

onAction(e) {
                        let workingTime = {};
                        if (e.checked) {
                            workingTime = {
                                fromDay: 1,
                                toDay: 6,
                                fromHour: 0,
                                toHour: 24
                            }
                        } else {
                            workingTime = {
                                fromDay: 1,
                                toDay: 6,
                                fromHour: 7,
                                toHour: 21
                            }
                        }
                        
const updatedConfig = {...scheduler.config, workingTime}; //1st attempt scheduler.setConfig(updatedConfig); // breaks with and error //2nd attempt scheduler.setConfig({workingTime}); // passes but doesn't do anything //3rd attempt scheduler.setConfig(workingTime); // same as previous (or breaks, can't remember //do I need to use any of these to refresh the the UI after config update? //scheduler.refreshWithTransition(); // scheduler.setTimeSpan(scheduler.startDate, scheduler.endDate); }

You can see the comments in the code what I have tried. Should it be done some other way?


Post by mats »

You can learn how to do this in our workingtime demo: https://bryntum.com/examples/scheduler/workingtime/

Just set it like so:

scheduler.workingTime = {
        fromDay  : 1,
        toDay    : 6,
        fromHour : 8,
        toHour   : 17
    };

Post by cubrilo »

Ah, ok, that's easier than I expected. I checked the example, but you are not changing the header of the scheduler, just basically compressing the time range available inside the fixed week period. I need to update the time axis to show me either 00-24 or 07-21 time in the header (my header shows the date and underneath hours, and this should be for both single or multiple days). Same thing with working days, I want to hide Saturday or Sunday, or both. So I need to rerender the complete scheduler (both grid and header) and update visible timespan for day(s) or hide days, depending of the change. workingTime property does it all but I can't find how to update the UI.


Post by mats »

That's easy to solve, you can learn how to customize the time axis from these demos: https://bryntum.com/examples/scheduler/timeaxis/


Post by cubrilo »

In your example you are rendering a few different schedulers and then switching inbetween them if I understand the example correctly. That is a bit too much of an overhead for what I need.
I actually managed to get the functionality that I want but it is acting quite strange. In some cases it works perfectly and in some it just doesn't work or messes up the the view.
I do this after the working time updated

scheduler.workingTime = newWorkingTime;
scheduler.renderContents();

Then when switch between 1,2,3,5 days view and different dates it sometimes works sometimes not.

In documentation it says that renderContents rerenders both the grid and header. I am still trying to figure out in what cases it not to work, and why in some cases it works perfectly fine. Would it help if I would post the scheduler config and toolbar code here for you to check out?


Post by mats »

Yes please always post the code required for us to run / debug. Calling renderContents should never be required.


Post by cubrilo »

Ok, just to mention that without calling the renderContents, when it works, after workingTime update (let's say change from 07-21 to 00-24) the view is updated with additional timespan but the time before and after the working hours is not rendered in the header, it's just expanded and emtpy.

Here is the scheduler config:

export default {
    appendTo: '',
    barMargin: 2,
    workingTime: {
        fromDay: 0,
        toDay: 7,
        fromHour: 7,
        toHour: 21
    },
    eventColor: 'green',
    eventStyle: 'border',
    resourceMargin: 2,
    rowHeight: 22,

allowOverlap: true,
fixedRowHeight: false,

zoomOnMouseWheel          : false,
zoomOnTimeAxisDoubleClick : false,

columns: [
    { type: 'tree', text: 'Staff', field: 'name', width: 230 },
],
viewPreset: new ViewPreset({
    id: 'myPreset',
    name: 'My view preset',
    tickWidth: 5,  
    displayDateFormat: 'HH:mm', 
    shiftIncrement: 1,         
    shiftUnit: 'day',       
    defaultSpan: 12,           

    timeResolution: {             
        unit: 'minute',  
        increment: 15
    },

    headers: [                   
        {             
            unit: 'day',
            dateFormat: 'ddd DD.MM.YYYY'
        },
        {
            unit: 'hour',
            increment: 2,
            dateFormat: 'HH:mm'
        }
    ],

    columnLinesFor: 1      

}),

features: {
    nonWorkingTime: true,
    timeRanges: true,
    resourceTimeRanges: true,
    labels: { bottomLabel: 'name' },
    group: false,
    tree: true,
    eventResize: {
        disabled: false,
        showTooltip: true
    },
    eventEdit: {
        // Add extra widgets to the event editor
        extraItems: [
            {
                type: 'text',
                name: 'desc',
                label: 'Description',
                index: 1
            }
        ]
    },
},
}

This is passed in the scheduler initialization after the data is loaded:

this.scheduler = new Scheduler({
                    project: projectData,
                    ...calendarOptions,
                    startDate: startDate,
                    endDate: endDate,
                    tbar: {}
                });
                
this.scheduler.tbar.add(toolbarConfigurator(this.scheduler, this.vm.getCalendarData, this.vm.showApproveTimespan) as any); //we initialize the toolbar here

And here is the toolbar configuration:

import { DateHelper, ProjectModel, Scheduler, Widget } from "bryntum-scheduler";

const toolbarConfigurator = (scheduler: Scheduler, refreshService: Function, openApproveWindow: Function): Widget[] => {
    const updateProject = (scheduler: Scheduler, updatedProject: ProjectModel): void => {
        scheduler.project.resourceStore = updatedProject.resourceStore;
        scheduler.project.eventStore = updatedProject.eventStore;
        scheduler.project.assignmentStore = updatedProject.assignmentStore;
    }

return [
    {
        type: 'buttongroup',
        color: 'b-gray',
        items: [
            {
                type: 'button',
                icon: 'b-fa-angle-left',
                tooltip: 'View previous day',
                onAction() {
                    refreshService(DateHelper.add(scheduler.startDate, -1, 'day'), DateHelper.add(scheduler.endDate, -1, 'day')).then(
                        updatedProject => {
                            updateProject(scheduler, updatedProject);
                            scheduler.setTimeSpan(DateHelper.add(scheduler.startDate, -1, 'day'), DateHelper.add(scheduler.endDate, -1, 'day'));
                            scheduler.renderContents();
                        }
                    );
                }
            },
            {
                type: 'button',
                ref: 'todayButton',
                text: 'Today',
                tooltip: 'View today, to see the current time line',
                onAction() {
                    const today = DateHelper.clearTime(new Date());
                    today.setHours(0);
                    refreshService(today, DateHelper.add(today, 22, 'hour')).then(
                        updatedProject => {
                            updateProject(scheduler, updatedProject);
                            scheduler.setTimeSpan(today, DateHelper.add(today, 18, 'hour'));
                            scheduler.renderContents();
                        }
                    );
                }
            },
            {
                type: 'button',
                icon: 'b-fa-angle-right',
                tooltip: 'View next day',
                //trigger: ('updateSchedulerDate', { date: DateHelper.add(scheduler.startDate, 1, 'day') }),
                onAction() {
                    refreshService(DateHelper.add(scheduler.startDate, 1, 'day'), DateHelper.add(scheduler.endDate, 1, 'day')).then(
                        updatedProject => {
                            updateProject(scheduler, updatedProject);
                            scheduler.setTimeSpan(DateHelper.add(scheduler.startDate, 1, 'day'), DateHelper.add(scheduler.endDate, 1, 'day'));
                            scheduler.renderContents();
                        }
                    );
                }
            },
            {
                type: 'button',
                icon: 'b-fa-redo',
                tooltip: 'Refresh',
                onAction() {
                    refreshService(scheduler.startDate, scheduler.endDate).then(
                        updatedProject => {
                            updateProject(scheduler, updatedProject);
                            scheduler.setTimeSpan(scheduler.startDate, scheduler.endDate);
                            scheduler.renderContents();
                        }
                    );
                }
            },
            {
                type: 'datefield',
                inputWidth: '6em',
                style: 'padding-left: 6px; padding-right: 6px',
                value: scheduler.startDate,
                editable: false,
                listeners: {
                    change: ({ value }) => {
                        refreshService(value, DateHelper.add(value, 1, 'day')).then(
                            updatedProject => {
                                updateProject(scheduler, updatedProject);
                                scheduler.setTimeSpan(value, DateHelper.add(value, 1, 'day'));
                                scheduler.renderContents();
                            }
                        );
                    }
                }
            },
            {
                type: 'button',
                icon: 'b-fa-check',
                tooltip: 'Approve orders',
                onAction() {
                    openApproveWindow({ startDate: scheduler.startDate, endDate: scheduler.endDate });
                }
            }
        ]
    },
    '->',
    {
        type: 'buttongroup',
        color: 'b-gray',
        items: [
            {
                type: 'checkbox',
                text: 'Hide Sat',
                style: 'padding-right: 6px',
                checked: false,
                onAction(e) {
                    if (e.checked) {
                           //here workingTime needs to be updated to exclude Saturday
                    }
                }
            },
            {
                type: 'checkbox',
                text: 'Hide Sun',
                style: 'padding-right: 6px',
                checked: false,
                onAction(e) {
                    console.log(e);
                    if (e.checked) {
                        // here workingTime needs to be updated to exclude Sunday
                    }
                }
            },
            {
                type: 'checkbox',
                text: '24h',
                style: 'padding-right: 6px',
                checked: false,
                onAction(e) {
                    console.log(e);
                    let workingTime = {};
                    if (e.checked) {
                        workingTime = {
                            fromDay: scheduler.workingTime.fromDay,
                            toDay: scheduler.workingTime.toDay,
                            fromHour: 0,
                            toHour: 24
                        }
                    } else {
                        workingTime = {
                            fromDay: scheduler.workingTime.fromDay,
                            toDay: scheduler.workingTime.toDay,
                            fromHour: 7,
                            toHour: 21
                        }
                    }
                    scheduler.workingTime = workingTime
                    scheduler.renderContents();
                }
            },
            {
                type: 'button',
                text: '1 day',
                tooltip: '1 day',
                onAction() {
                    refreshService(scheduler.startDate, DateHelper.add(scheduler.startDate, 1, 'day')).then(
                        updatedProject => {
                            updateProject(scheduler, updatedProject);
                            scheduler.setTimeSpan(scheduler.startDate, DateHelper.add(scheduler.startDate, 1, 'day'));
                            scheduler.renderContents();
                        }
                    );
                }
            },
            {
                type: 'button',
                text: '2 days',
                tooltip: '2 days',
                onAction() {
                    refreshService(scheduler.startDate, DateHelper.add(scheduler.startDate, 2, 'day')).then(
                        updatedProject => {
                            updateProject(scheduler, updatedProject);
                            scheduler.setTimeSpan(scheduler.startDate, DateHelper.add(scheduler.startDate, 2, 'day'));
                            scheduler.renderContents();
                        }
                    );
                }
            },
            {
                type: 'button',
                text: '3 days',
                tooltip: '3 days',
                onAction() {
                    refreshService(scheduler.startDate, DateHelper.add(scheduler.startDate, 3, 'day')).then(
                        updatedProject => {
                            updateProject(scheduler, updatedProject);
                            scheduler.setTimeSpan(scheduler.startDate, DateHelper.add(scheduler.startDate, 3, 'day'));
                            scheduler.renderContents();
                        }
                    );
                }
            },
            {
                type: 'button',
                text: '5 days',
                tooltip: '5 days',
                onAction() {
                    refreshService(scheduler.startDate, DateHelper.add(scheduler.startDate, 5, 'day')).then(
                        updatedProject => {
                            updateProject(scheduler, updatedProject);
                            scheduler.setTimeSpan(scheduler.startDate, DateHelper.add(scheduler.startDate, 5, 'day'));
                            scheduler.renderContents();
                        }
                    );
                }
            },
        ]
    },
    
    //unknown used only as suggested solution by linter to skip ts errors
] as unknown as Widget[]
}

export default toolbarConfigurator;

Just to mention that I added

scheduler.renderContents();

here to all the button calls just to see if it will make any difference, but in general it would make sense to me to use it only after the workingTime has been updated.


Post by pmiklashevich »

Could you please provide your code as a ZIP containing a runnable example? To create a testcase please apply minimal changes to one of our demos. Do not include node_modules and our sources, just demo code. We should be able to compile and run it. Please also attach a video/gif showing how the content gets changed for you and what exactly you'd like to change. And mention the Scheduler version you're using. Is it a simple scheduler or pro?

Pavlo Miklashevych
Sr. Frontend Developer


Post by cubrilo »

Here is the version info:

"license": "Commercial",
  "main": "scheduler.module.js",
  "name": "bryntum-scheduler",
  "types": "./scheduler.d.ts",
  "version": "4.0.8"

And I attached a working example. It is a simple angular app that just shows the scheduler.
Bryntum code is in Bryntum.Scheduler folder, I removed the code and left just the empty folder.

For some reason it renders it twice and just renders the header and toolbar, but it should be enough to see what is happening. In general event data that renders matches the time from header so when header works correctly probably everything will. Just try switching next/today/previous day, datepicker with 1/2/3/5 days and hide days and you will see that some combinations work and some don't.
For example, when I just load, and change 24h, nothing happens, if I press 1 day/ 2 days and then 24h it changes but throws in part of 3rd day. In some combinations it adds hours from midnight to 7/8h am but renders only time till e.g 16h and leftover time till 24h is not shown. And then in some cases, I think if I change datepicker value and play with 24h it sometimes works perfectly fine. Then when I turn on and off Saturday or Sunday the shaded part for these days missaligns with the expected position for these days.

Attachments
scheduler-test.zip
(153.06 KiB) Downloaded 96 times

Post by alex.l »

Thank you for the test case, I was able to reproduce the problem, this is a bug. Here is the link to track the status: https://github.com/bryntum/support/issues/2704

All the best,
Alex

All the best,
Alex


Post Reply