Our state of the art Gantt chart


Post by Jerther »

Hi!

in 2.1.7 I had this class:

class TaskEditor extends TaskEditor {
    static get defaultConfig() {
        return {
            width: '50em',
            height: '36em',
            extraItems: {
                generaltab: [
                    {
                        html    : '',
                        cls  : 'b-divider',
                        flex : '1 0 100%'
                    }, {
                        type  : 'tagsfield',
                        ref   : 'tagsField',
                        name  : 'tags',
                        label : "Tags",
                        flex  : '0 100%',
                        cls   : 'b-inline'
                    }
                ],
                advancedtab: [{
                    type: 'checkbox',
                    label: "Initially expanded",
                    name: 'initiallyExpanded',
                    ref: 'initiallyExpandedField',
                    flex: '1 0 50%',
                }]
            }
        };
    }
}

I followed this guide to migrate to 4.5.1: https://www.bryntum.com/docs/gantt/#Gantt/guides/upgrades/4.0.0.md#taskeditor-configs-changes

The guide is for the TaskEdit feature but I figured the changes were the same for class configuration. Maybe I was wrong. We'll see ;) Anyway I came up with this:

class MyTaskEditor extends TaskEditor {
    static get type() {
        return 'mytaskeditor';
    }
    static get defaultConfig() {
        return {
            autoClose: false,
            width: '50em',
            height: '36em',
            items: {
                generalTab: {
                    items: {
                        spacer1: {
                            html    : '',
                            cls  : 'b-divider',
                            flex : '1 0 100%'
                        },
                        tags: {
                            type  : 'tagsfield',
                            ref   : 'tagsField',
                            label : "Tags",
                            flex  : '0 100%',
                            cls   : 'b-inline'
                        }
                    }
                },
                advancedTab: {
                    items: {
                        initiallyExpanded: {
                            type: 'checkbox',
                            label: "Initially expanded",
                            ref: 'initiallyExpandedField',
                            flex: '1 0 50%',
                        }
                    }
                },
            },
        };
    }
}

And as usual, I use this to set the task editor class:

new Gantt({
    appendTo : 'container',
    features : {
        taskEdit : {
            editorClass: MyTaskEditor
        }
    },
    // ...
});

Currently, there is a problem with editorClass which is already discussed here . However, using the workaround I included, I managed to get it to work, but then I have a crash because of the items part in the defaultConfig:

TypeError: clonedItems.find is not a function

I think it expects the items config to be an array but the documentation says it can be an object. I tried to set it as an array like so:

static get defaultConfig() {
        return {
            autoClose: false,
            width: '50em',
            height: '36em',
            items: [
                {
                    ref: 'generalTab',
                    items: {
                        spacer1: {
                            html    : '',
                            cls  : 'b-divider',
                            flex : '1 0 100%'
                        },
                        tags: {
                            type  : 'tagsfield',
                            ref   : 'tagsField',
                            label : "Tags",
                            flex  : '0 100%',
                            cls   : 'b-inline'
                        }
                    }
                },
                {
                    ref: 'advancedTab',
                    items: {
                        initiallyExpanded: {
                            type: 'checkbox',
                            label: "Initially expanded",
                            ref: 'initiallyExpandedField',
                            flex: '1 0 50%',
                        }
                    }
                },
            ],
        };
    }

But then I get another error:

TypeError: Cannot read property 'items' of undefined

If I remove the items config from defaultConfig, then it works fine.

Last edited by Jerther on Fri Jun 18, 2021 2:18 pm, edited 1 time in total.

Post by saki »

Perhaps you could take a look at GanttTaskEditor which contains TabPanel as the first item while yours contain tabs at the first level.

Or we need a showcase to trace the problem down to its root.


Post by Jerther »

Good point Saki.

So here's how it looks after adjusting the widget hierarchy:

class MyTaskEditor extends TaskEditor {
    static get type() {
        return 'mytaskeditor';
    }
    static get defaultConfig() {
        return {
            autoClose: false,
            width: '50em',
            height: '36em',
            items: {
                tabs: {
                    items: {
                        generalTab: {
                            items: {
                                spacer1: {
                                    html    : '',
                                    cls  : 'b-divider',
                                    flex : '1 0 100%'
                                },
                                tags: {
                                    type  : 'tagsfield',
                                    ref   : 'tagsField',
                                    label : "Tags",
                                    flex  : '0 100%',
                                    cls   : 'b-inline'
                                }
                            }
                        },
                        advancedTab: {
                            items: {
                                initiallyExpanded: {
                                    type: 'checkbox',
                                    label: "Initially expanded",
                                    ref: 'initiallyExpandedField',
                                    flex: '1 0 50%',
                                }
                            }
                        },
                    },
                },
            },
        };
    }
}

I still get "TypeError: clonedItems.find is not a function" like it's expecting an array, even though the doc says it could also be an object. Let's try an array again:

class MyTaskEditor extends TaskEditor {
    static get type() {
        return 'mytaskeditor';
    }
    static get defaultConfig() {
        return {
            autoClose: false,
            width: '50em',
            height: '36em',
            items: [
                {
                    ref: 'tabs',
                    items: {
                        generalTab: {
                            items: {
                                spacer1: {
                                    html    : '',
                                    cls  : 'b-divider',
                                    flex : '1 0 100%'
                                },
                                tags: {
                                    type  : 'tagsfield',
                                    ref   : 'tagsField',
                                    label : "Tags",
                                    flex  : '0 100%',
                                    cls   : 'b-inline'
                                }
                            }
                        },
                        advancedTab: {
                            items: {
                                initiallyExpanded: {
                                    type: 'checkbox',
                                    label: "Initially expanded",
                                    ref: 'initiallyExpandedField',
                                    flex: '1 0 50%',
                                }
                            }
                        },
                    },
                },
            ],
        };
    }
}

No more crash but the task editor show up almost completely empty:

Image

Any idea?


Post by saki »

Try this:

class MyTaskEditor extends TaskEditor {

    static $name = 'MyTaskEditor'

    static get type() {
        return 'mytaskeditor';
    }

    static get defaultConfig() {
        return {
            autoClose : false,
            width     : '50em',
            height    : '36em',
            items     : [
                {
                    type        : 'tabpanel',
                    defaultType : 'formtab',
                    ref         : 'tabs',
                    flex        : '1 0 100%',
                    autoHeight  : true,

                    layoutConfig : {
                        alignItems   : 'stretch',
                        alignContent : 'stretch'
                    },

                    items : {
                        generalTab : {
                            title : 'General',
                            items : {
                                spacer1 : {
                                    html : '',
                                    cls  : 'b-divider'
                                },
                                tags : {
                                    type  : 'text',
                                    name  : 'tags',
                                    label : 'Tags'
                                }
                            }
                        },
                        advancedTab : {
                            title : 'Advanced',
                            items : {
                                initiallyExpanded : {
                                    type  : 'checkbox',
                                    label : 'Initially expanded',
                                    name  : 'initiallyExpanded'
                                }
                            }
                        }
                    }
                }
            ]
        };
    }
};

MyTaskEditor.initClass();

const gantt = new Gantt({
    features : {
        taskEdit : {
            editorClass : MyTaskEditor
        }
    },
    // etc.
})

The way to do it is to take our code – GanttTaskEditor in this case – and make it working in the app. Source code of GeneralTab (and other tabs) can also help. Once it's working then there's time to add all fields.


Post by Jerther »

Thanks Saki. Well this kind of works but it's not quite what I'm looking for. It's replacing the content of the task editor altogether while I'm just trying to improve it the way extraItems used to. Remember, I'm migrating from 2.1.7 and I'm looking for the same behavior, without using deprecated stuff.

I could copy and adapt the whole configuration code from the original TaskEditor but that kind of defeats the purpose of inheritance and it's also looking for trouble in the long run ;)


Post by saki »

I had an impression that you want a completely new editor, you created a new extension class for it after all. If you only need to patch the existing one here and there (hide some fields and add new ones, hide some tabs and add new ones) then https://bryntum.com/docs/gantt/#Gantt/feature/TaskEdit is a very good starting point.

You can also take a look at the source of taskeditor demo that adds some items to the General Tab, turns of the Notes tab and adds Files tab with this code:

    features : {
        taskEdit : {
            items : {
                generalTab : {
                    // change title of General tab
                    title : 'Common',
                    items : {
                        customDivider : {
                            html    : '',
                            dataset : {
                                text : 'Custom fields'
                            },
                            cls  : 'b-divider',
                            flex : '1 0 100%'
                        },
                        deadlineField : {
                            type  : 'datefield',
                            name  : 'deadline',
                            label : 'Deadline',
                            flex  : '1 0 50%',
                            cls   : 'b-inline'
                        },
                        colorField : {
                            type  : 'colorfield',
                            name  : 'color',
                            label : 'Color',
                            flex  : '1 0 50%',
                            cls   : 'b-inline'
                        }
                    }
                },
                // remove Notes tab
                notestab : false,
                // add custom Files tab to the second position
                filesTab : {
                    type   : 'filestab',
                    weight : 110
                }
            }
        }
    },

Post by Jerther »

It was also possible to configure the feature in 2.1.7 but back then I chose to extend the class because it made the code much cleaner by grouping all the task editor related code. The example I gave here is just a snippit; my actual class is much bigger. I also use the extended class to override some things that cannot be overriden via the feature.

So before I go ahead and rewrite a good chunk of my code, could you confirm that it's not possible to do this through an extended class anymore, like in 2.1.7? (and that it still won't be in 4.1.6 ;) )


Post by pmiklashevich »

Extending our classes to develop a new functionality is fully supported. Unless you override a private thing, you should be able to update the Bryntum version with no issues. When you updated through a major version, there might be an API which is deprecated. When you updated through more than one major version, some API can be removed. You can check out the changelog (of all products: grid, scheduler, and gantt), and the upgrade guides. Pay attention to [BREAKING] and [DEPRECATED] things. If you spot an API change that hasn't been covered with backward compatibility and docs, please report.
https://www.bryntum.com/docs/gantt/#Gantt/guides/upgrades/4.0.0.md
https://www.bryntum.com/products/gantt/changelog/

Pavlo Miklashevych
Sr. Frontend Developer


Post by Jerther »

Hi Pavel,

Yes extraItems is covered in the upgrade guide but only for the editorConfig of the taskEdit feature! The extraItems config for the TaskEditor class is also deprecated https://www.bryntum.com/docs/gantt/#Gantt/widget/TaskEditor#config-extraItems but it is NOT covered in the upgrade guide.

The editorConfig of the taskEdit feature MERGES the items, and I've observed with Saki that the defaultConfig() property of the class REPLACES them entirely.

I could switch to using the editorConfig of the taskEdit feature instead but that would break my code fairly heavily.


Post by pmiklashevich »

Yes extraItems is covered in the upgrade guide but only for the editorConfig of the taskEdit feature! The extraItems config for the TaskEditor class is also deprecated Gantt.widget.TaskEditor#extraItems but it is NOT covered in the upgrade guide.

https://www.bryntum.com/docs/gantt/#Gantt/feature/TaskEdit#config-editorConfig is a configuration for https://www.bryntum.com/docs/gantt/#Gantt/widget/TaskEditor. So that is covered.

The editorConfig of the taskEdit feature MERGES the items, and I've observed with Saki that the defaultConfig() property of the class REPLACES them entirely.

You can copy default config from our definition, and then apply your changes.

Please read:
https://www.bryntum.com/docs/gantt/#Core/guides/advanced/classes.md
https://www.bryntum.com/docs/gantt/#Core/guides/advanced/widgets.md

defaultConfig was never public. "defaultConfig" is getting replaced with "configurable". In fact in the TaskEditor both are used.

Pavlo Miklashevych
Sr. Frontend Developer


Post Reply