Our pure JavaScript Scheduler component


Post by mos »

I'm experiencing a few issues working with TreeGroup feature in Scheduler Pro.

I've included a simplified example of a dataset below (Ref #1).
In this context, I'm intending to group by "["ParentName", "ResourceType"]". I'd rather not see the parent in the as a child/sub-node to the grouped item.

Issues:

  1. Parent is included as a child/sub-node to the grouped item. This occurs in the following contexts:
    a. Parent record has no children.
    b. Grouping property on Parent record is:
    i. Undefined or Null. Result: The parent record is included under a blank-titled group. (Ref: #2)
    ii. A Blank String. Result: Error: "Uncaught (in promise) Error: Id collision on generated_A_Test_Resource_". (Ref: #3)

  2. Unable to Sort Groups.
    a. There doesn't seem to be a way to default-sort groups or sub-groups when using TreeGroup.

  3. Grouping Issue when using a default filter value.
    a. When a default filter value is applied to resources (using a combo in my case); only the initially presented resources are grouped.
    b. Once the filter is removed, the other resources are shown, without a specified grouping applied.

Ref #1:

[
    {
        "Name": "First Parent Resource",
        "ParentName": "First Parent Resource",
        "ResourceType": "Parent",
        "Children": [
            {
                "Name": "Child Resource 1",
                "ParentName": "First Parent Resource",
                "ResourceType": "Square"
            },
            {
                "Name": "Child Resource 2",
                "ParentName": "First Parent Resource",
                "ResourceType": "Circle"
            }
        ]
    },
    {
        "Name": "The Second Parent Resource",
        "ParentName": "The Second Parent Resource",
        "ResourceType": "Parent",
        "Children": [
            {
                "Name": "Child Resource 4",
                "ParentName": "The Second Parent Resource",
                "ResourceType": "Circle"
            }
        ]
    },
    {
        "Name": "Third Parent Resource",
        "ParentName": "Third Parent Resource",
        "ResourceType": "Parent"
    }
]

Ref #2:

Ref2.png
Ref2.png (3.63 KiB) Viewed 448 times

Ref #3:

Ref3_1.png
Ref3_1.png (27.59 KiB) Viewed 448 times

Post by tasnim »

Could you please show the config that you're using to reproduce it?


Post by mos »

Including config snippet below.

export const schedulerProConfig = {
        project,
        columns: [
                {
                        type: 'tree',
                        text: 'Centers',
                        width: 250,
                        field: 'name',
                }
        ],
        features: {
                filterBar: true,
                tree: true,
                treeGroup: {
                        levels: ["ParentName", "ResourceType"]
                }
        }
}

Post by tasnim »

Hello,
I've modified the data that you're using. The Name should be name and the Children should be children and so on, as javascript is case sensitive.

So here is the modified that

[
    {
        "name": "First Parent Resource",
        "parentName": "First Parent Resource",
        "resourceType": "Parent",
        "children": [
            {
                "name": "Child Resource 1",
                "parentName": "First Parent Resource",
                "resourceType": "Square"
            },
            {
                "name": "Child Resource 2",
                "parentName": "First Parent Resource",
                "resourceType": "Circle"
            }
        ]
    },
    {
        "name": "The Second Parent Resource",
        "parentName": "The Second Parent Resource",
        "resourceType": "Parent",
        "children": [
            {
                "name": "Child Resource 4",
                "parentName": "The Second Parent Resource",
                "resourceType": "Circle"
            }
        ]
    },
    {
        "name": "Third Parent Resource",
        "parentName": "Third Parent Resource",
        "resourceType": "Parent"
    }
]

And change the treeGroup levels

    features : {
        treeGroup : {
            levels : ['parentName', 'resourceType']
        }
    },

And here is the output

Screenshot 2023-01-19 142008.png
Screenshot 2023-01-19 142008.png (26.57 KiB) Viewed 390 times

Hope it will help.

Good Luck :)


Post by mos »

Hi Tasnim,

Thanks for the response, and thanks for the correction to the snippet.
To clarify, that snippet was only meant as an example of the data structure I'm testing. (TreeGroup is working in my scheduler).

Referencing your screenshot & my initial message numbering:

#1: The two nodes under "Third Parent Resource" aren't needed. Any parent without children shouldn't present a group/child nodes.

#2: I'd like to sort "Square" above "Circle".

#3: If a default filter were added to these items, once the filter is cleared, the returned full list is ungrouped.

Thanks!

A comment not directly related... it appears bryntum codepen references aren't working, so it's not as easy to mock up/share a quick example when reporting an issue.


Post by johan.isaksson »

Hi,

Some clarifications:

#1 Since "Third Parent Resource" isn't defined as a parent, the feature is doing what it should. Try turning it into a parent by supplying an empty children array on it

#2 The resulting tree can be sorted using the usual store methods, by supplying a custom sorter function you should be able to arrange the generated nodes the way you want. Another (probably less appealing) option could be to use functions instead of field names for the levels, injecting something to order by first, eg. A - Square, B - Circle.

#3 The behaviour of tree grouping with an initial filter is undefined, how would you want it to behave? Based on that I could open a ticket on it

Best regards,
Johan Isaksson

Post by mats »

A comment not directly related... it appears bryntum codepen references aren't working, so it's not as easy to mock up/share a quick example when reporting an issue.

How do you mean codepen isn't working, can you please share where it's broken? Works fine for me:

Attachments
Screenshot 2023-01-20 at 16.57.37.png
Screenshot 2023-01-20 at 16.57.37.png (320 KiB) Viewed 346 times

Post by mos »

#1 - I'll break my observations into two parts. Certainly advise if your testing produced different results.

#1a - When an empty "children" array is supplied, to "Third Parent Resource", it excludes this item from the resource list. This is not the desired behavior.
The intended behavior is to include the parent once without also including it as a child-item on its own grouping. Using "convertEmptyParentToLeaf: true" here has no effect.

#1b - I'm actually using "transformFlatData: true" for my flat dataset. I'm including a modified snippet in Ref1-3 below to highlight data transformation and the resourcestore.

When I conditionally add an empty children array property to parents without a child record, it has the effect of excluding every item without children, and adding the parent record to every grouping remaining (Ref4).

...
Adding a #4 - Tregroup expands all children by default, and ignores the expand property.
This may be understandable given the grouping parent may not inherit the properties of parents or grouped items. I would be curious how to achieve this.

===

@mats
Opening the pen from this live demo for example. The error is:

Uncaught ReferenceError: SchedulerPro is not defined 
 at https://cdpn.io/cpe/boomboom/pen.js?key=pen.js-d990610c-613e-9869-fe1a-9c4c12bda4e9:1

I haven't noticed it working since the beginning of the year. It may be a similar situation reported here.
Based on your screenshot, I tested Gantt and confirmed it's working. SchedulerPro isn't.

===
Screenshots
Ref4

treeGroupIssue.png
treeGroupIssue.png (29.07 KiB) Viewed 327 times

===
Code Snippets

// Ref1: Separate Parent & Child Datasets

const staticResourceParents =
    [
        {
            "id": 1,
            "name": "First Parent Resource",
            "parentName": "First Parent Resource",
            "resourceType": "Parent",
            "childCount": 2,
        },
        {
            "id": 2,
            "name": "The Second Parent Resource",
            "parentName": "The Second Parent Resource",
            "resourceType": "Parent",
            "childCount": 1,
        },
        {
            "id": 3,
            "name": "Third Parent Resource",
            "parentName": "Third Parent Resource",
            "resourceType": "Parent",
            "childCount": 0,
        }
    ];

const staticResourceChildren = [
    {
        "id": 4,
        "name": "Child Resource 1",
        "parentId": 1,
        "parentName": "First Parent Resource",
        "resourceType": "Square"
    },
    {
        "id": 5,
        "name": "Child Resource 2",
        "parentId": 1,
        "parentName": "First Parent Resource",
        "resourceType": "Circle"
    },
    {
        "id": 6,
        "name": "Child Resource 4",
        "parentId": 2,
        "parentName": "The Second Parent Resource",
        "resourceType": "Circle"
    }
]
//Ref2 - Parent mapping

const mapParentData = (item, index) => ({
    ["name"]: item.name,
    ["parentId"]: item.parentId,
    ["parentName"]: item.parentName,
    ["resourceType"]: item.parentName,
    ...(item.childCount == 0 && { ["children"]: [] }), // Add empty children array to a parent with childcount = 0
});

export function getStaticData() {
    const parentData = staticResourceParents.map(mapParentData);
    const staticResourceDataset = [...parentData, ...staticResourceChildren];

return staticResourceDataset;
}
//Ref3 - Resource Store

const resourceStore = new ResourceStore({
        tree: true,
        transformFlatData: true,
        data: resourceData,
    });

Post by johan.isaksson »

The TreeGroup feature is designed to take all leaf records and generate transient parents based on the supplied levels, producing a symmetrical tree structure.

It extracts the leaves into a new store and generates parents, it does not and should not take any original parent into account.

With that said and what I understand about your requirements, probably the TreeGroup feature is not what you need. Instead I think you should try building the structure you want in application code, will prepare a small sample and post it here later.

Best regards,
Johan Isaksson

Post by johan.isaksson »

Here is some code to hopefully get you started. Try this on console in the tree demo in Scheduler (https://bryntum.com/products/scheduler/examples/tree/):

1 - Extract all leaves and create links to them (leaves can only have a single parent, links allows us to seemingly put them under another parent):

const links = scheduler.resourceStore.leaves.map(l => l.link());

2 - Create a new structure, placing the leaves where you want them:

const newStructure = {
    name     : 'Top',
    children : [
        {
            name     : 'Ones',
            children : links.filter(link => link.name === 'Gate 1')
        },
        {
            name     : 'Others',
            children : links.filter(link => link.name !== 'Gate 1')
        }
    ]
};

3 - Use that as data for a new store, attach it to Scheduler:

scheduler.store = new scheduler.store.constructor({ data : [newStructure] });

Should produce a custom view such as in the screenshot below:

bryntum.com_products_scheduler_examples_tree_(1024x768).png
bryntum.com_products_scheduler_examples_tree_(1024x768).png (260.88 KiB) Viewed 298 times

To revert back to the initial view, use:

scheduler.store = scheduler.resourceStore;
Best regards,
Johan Isaksson

Post Reply