Ask for help related to our 2.x versions.

Post by chris3farrell »

Integrating Bryntum Ext Scheduler With Cmd generated Ext app

Using Cmd 3.0.0.141, I have successfully generated a workspace and an ext app in that workspace. The application builds correctly until I attempt to integrate the Bryntum Scheduler, where I encounter an error when I try to refresh or build:

"Failed to resolve dependency Sch.panel.SchedulerTree for file ExtCalendar.view.Tree"

My structure is:

workspace
workspace/.sencha
workspace/build/
workspace/common/
workspace/ext/
workspace/extCalendar/
workspace/extCalendar/.sencha/
workspace/extCalendar/app.json
workspace/extCalendar/index.html
workspace/extCalendar/app/
workspace/extCalendar/app/model/
workspace/extCalendar/app/view/
workspace/extCalendar/app/store/
workspace/extCalendar/app/controller/
workspace/extCalendar/app/app.js
workspace/extCalendar/app/sch-all-debug.js (the Bryntum Scheduler file)

I've tried:
Adding a "js" path: ...{"path":"app/sch-all-debug.js"}... to app.json (orginally thought this was all I would have to do)
Adding <script src="app/sch-all-debug.js"> to index.html
Adding Ext.Loader.setConfig({ enabled:true, disableCaching : true }) to app.js
Adding Ext.Loader.setPath('Sch', 'js/Sch') to app.js
Adding Ext.require([ 'Sch.panel.SchedulerTree' ]) to app.js

Seems like I'm missing something rudimentary about the Sch namespace, and I'm not sure how to debug the issue....so, I'm doing a lot of trial and error to no avail.

Any advice?

Post by mats »

I haven't used Sencha Cmd for this personally - but this should definitely 'just work'. We'll try to look into this shortly!

Tired of debugging javascript errors in web applications? Try our powerful error logging service RootCause


Post by jakub »

Investigating this one. Can you share what were the steps you've taken so far ? Generated workspace, then some app which has Sch in it's dependencies ?
JavaScript/Angular/ExtJS consulting - kuba@virtualdesign.pl

Post by chris3farrell »

Steps are:

1. install Compass
2. download Cmd installer (3.0.0.141) and run it (installs in ~/Sencha/Cmd/{version}/)
3. make sure it added itself to your PATH and added the environment variable - if not, add them manually
4. download ExtJS 4.1.1a
5. use Cmd to generate a workspace
6. use Cmd to generate an ext app in that workspace
7. use Cmd to build the new app, it should build without error
8. add the scheduler to the app - not sure how to do this correctly, I tried a few different things mentioned previously.

All of the scheduler examples have a very different architecture than the Cmd generated app, and I'm finding it challenging to translate.
a. I would like to have my objects (app, viewport, models, stores, controllers, views, etc) defined in separate files, rather than created in a single file.
b. the Cmd generated app uses Ext.application, rather than onReady.
c. the Cmd app seems to prescribe the use of app.json to define dependencies, rather than Ext.require.
d. as I investigated the examples to try and figure out what I'm doing wrong, I realized that I don't understand what
the Loader setPath 'Sch' at '../../js/Sch' in all of the examples does. The examples all work
perfectly, but there's no /../../js folder on my machine - is this a virtual path created by the scheduler script? How does that work?
e. when I run an example, set a breakpoiont, and then inspect with developer tools, I can add 'Sch' to the 'Watch Expressions' and
see it defined, but I don't see it listed in the global namespace. So, I don't know how it gets there or where it should be defined.

Thank you for looking into this! Let me know if you need more info or would like me to post my files.

Post by jakub »

Thanks for the update. I already got the cmd working after some struggling with paths and correct ext versions so I'll try to check why scheduler's not working there. As for the path to loader, it's just a relative path to the Scheduler sources used in the examples in case the sch-all.js is not included in the header.
JavaScript/Angular/ExtJS consulting - kuba@virtualdesign.pl

Post by jakub »

What I was able to learn so far, the app.json is used only for building process so it won't influence your app right now. One way I got this running was using this code in index.html :
<!DOCTYPE HTML>
<html>
<head>
    <meta charset="UTF-8">
    <title>App</title>
    <link rel="stylesheet" href="resources/css/default/app.css">
    <link rel="stylesheet" href="../../ExtScheduler2.x/resources/sch-all.css">
    <script src="ext/ext-all-debug.js"></script>
    <script src="../../ExtScheduler2.x/sch-all.js"></script>
    <script src="app/app.js"></script>
</head>
<body>
    <div id="scheduler1"></div>
</body>
</html>
and in the app.js I've used one of the scheduler's example.
Ext.ns('App');

Ext.onReady(function() {
    App.SchedulerDemo.init();
});

App.SchedulerDemo = {
    
    // Initialize application
    init : function() {
        
        Ext.define('App.CustomResource', {
            extend      : 'Sch.model.Resource', 
            fields      : [
                { name  : 'FavoriteColor' }
            ]
        })
        
        var s1 = new Sch.panel.SchedulerGrid({
            title               : 'Both columns to the left',
            eventBarTextField   : 'Title',
            viewPreset          : 'hourAndDay',
            startDate           : new Date(2010, 11, 9, 8),
            endDate             : new Date(2010, 11, 9, 16),
            renderTo            : 'scheduler1',
            height              : 270,
            width               : 700,
            split               : true,
            tbar: [{
                text : 'Add new row',
                handler : function() {
                    s1.resourceStore.insert(0, new s1.resourceStore.model({
                        Name : 'New guy',
                        FavoriteColor : 'black'
                    }));
                }
            }],

            // Setup static columns
            columns : [
                {header : 'Name',           width:110, dataIndex : 'Name'},
                {header : 'Favorite Color', width:100, dataIndex : 'FavoriteColor'}
            ],
                            
            // Store holding all the resources
            resourceStore : new Sch.data.ResourceStore({
                sortInfo    : { field: 'Name', direction: "ASC" },
                
                model       : 'App.CustomResource',
                
                data        : [
                    {Id : 'MadMike', Name : 'Mike', FavoriteColor : 'blue'},
                    {Id : 'LindaAnderson', Name : 'Linda', FavoriteColor : 'red'},
                    {Id : 'DonJohnson', Name : 'Don', FavoriteColor : 'yellow'},
                    {Id : 'KarenJohnson', Name : 'Karen', FavoriteColor : 'black'},
                    {Id : 'DougHendricks', Name : 'Doug', FavoriteColor : 'green'},
                    {Id : 'PeterPan', Name : 'Peter', FavoriteColor : 'lime'}
                ]
            }),
        
            // Store holding all the events
            eventStore : new Sch.data.EventStore({
                data        : [
                    { ResourceId: 'MadMike',        Title : 'Assignment 1', StartDate : "2010-12-09 10:00", EndDate : "2010-12-09 11:00"},
                    { ResourceId: 'LindaAnderson',  Title : 'Assignment 2', StartDate : "2010-12-09 10:00", EndDate : "2010-12-09 12:00"},
                    { ResourceId: 'DonJohnson',     Title : 'Assignment 3', StartDate : "2010-12-09 13:00", EndDate : "2010-12-09 15:00"},
                    { ResourceId: 'KarenJohnson',   Title : 'Assignment 4', StartDate : "2010-12-09 13:00", EndDate : "2010-12-09 15:00"},
                    { ResourceId: 'DougHendricks',  Title : 'Assignment 5', StartDate : "2010-12-09 12:00", EndDate : "2010-12-09 13:00"},
                    { ResourceId: 'PeterPan',       Title : 'Assignment 6', StartDate : "2010-12-09 14:00", EndDate : "2010-12-09 16:00"}
                ]
            })
        });
    }
};
Now I'm trying to set this properly with bootstrap.js and using Ext.application.
JavaScript/Angular/ExtJS consulting - kuba@virtualdesign.pl

Post by chris3farrell »

jakub wrote:As for the path to loader, it's just a relative path to the Scheduler sources used in the examples in case the sch-all.js is not included in the header.
Oh, I see. The setPath call in the examples is an alternative to the html header <script>.
And, it is simply ignored without warning or error.
Phew..I thought I was going crazy. Thank you for clarifying.

Post by chris3farrell »

jakub wrote:Now I'm trying to set this properly with bootstrap.js and using Ext.application.
Thank you.

So, a detail I have gathered from your reply is that I do not need to build in order to test/debug.
I can simply serve my workspace/extCalendar/index.html, correct?

When I do that, I find that replacing the Cmd generated <script src='ext-debug.js'> in index.html with ext-all-debug.js got me further along.
The 50 or so 404's for Sch/{classname} all go away, so that's good : )

But, I'm still not up and running, with my MVC style set up (below) I'm getting:
"Uncaught TypeError: Object [object Object] has no method 'getRootNode' "

And, when I try to build (or refresh) I still get:
"Failed to resolve dependency Sch.panel.SchedulerTree for file ExtCalendar.view.Tree"



My Index.html:
<!DOCTYPE HTML>
<html>
<head>
    <meta charset="UTF-8">
    <title>ExtCalendar</title>
    <link rel="stylesheet" href="resources/css/flag/app.css">
    <!--Scheduler styles-->
    <link rel="stylesheet" href="resources/css/sch-all.css"/>

    <!-- <x-compile> -->
        <!-- <x-bootstrap> -->
            <script src="../ext/ext-all-debug.js"></script>
            <script src="bootstrap.js"></script>
            <!--Scheduler files-->
            <script src="app/sch-all-debug.js"></script>
        <!-- </x-bootstrap> -->



        <script src="app/app.js"></script>
    <!-- </x-compile> -->
</head>
<body></body>
</html>

My app.js
Ext.application({
    
    models: ['Tree'],
    stores: ['TreeNodes', 'Events'],
    controllers: ['Main'],
    views: ['Main', 'Tree'],

    name: 'ExtCalendar',

    autoCreateViewport: true
});

my Viewport:
Ext.define('ExtCalendar.view.Viewport', {
    renderTo: Ext.getBody(),
    extend: 'Ext.container.Viewport',
    requires:[
        'Ext.tab.Panel',
        'Ext.layout.container.Border',
        'ExtCalendar.view.Tree'
    ],

    maintainFlex: false,
    layout: {
        type: 'border'
    },

    items: [
                {
                    region: 'north',
                    xtype: 'panel',
                    title: 'north',
                    height: 50
                },
                {
                    region: 'east',
                    xtype: 'panel',
                    title: 'east',
                    width: 150
                },
                {
                    region: 'center',
                    xtype: 'tree'
                }
            ]
});
my Tree
Ext.define("ExtCalendar.view.Tree", {
    
    extend                      : 'Sch.panel.SchedulerTree',
    alias                       : 'widget.tree',
    title                       : 'Content Visualizer',
    
    
	allowOverlap                : true,
    enableDragCreation          : false,
	constrainDragToResource     : true,
    multiSelect                 : false,
    resizeHandles               : 'none',
    eventResizeHandles          : 'none',
    rowHeight                   : 30,
    viewPreset                  : 'weekAndMonth',
    startDate                   : new Date(2012, 6, 16, 0),
    endDate                     : new Date(2012, 11, 30, 23),

    viewConfig: {

    },
    dragConfig : null,

    eventStore      : 'Events',
    resourceStore   : 'TreeNodes',

    tbar    : 
    [
        {
            text : 'Hours',
            toggleGroup : 'presets',
            enableToggle : true,
            iconCls : 'icon-calendar',
            handler : function() {
                tree.switchViewPreset('hourAndDay', new Date(2012, 6, 24), new Date(2012, 7, 1));
            }
        },
        {
            text : 'Days',
            toggleGroup : 'presets',
            enableToggle : true,
            iconCls : 'icon-calendar',
            handler : function() {
                tree.switchViewPreset('weekAndDay', new Date(2012, 6, 24), new Date(2012, 7, 1));
            }
        },
        {
            text : 'Weeks',
            toggleGroup : 'presets',
            enableToggle : true,
            pressed : true,
            iconCls : 'icon-calendar',
            handler : function() {
                tree.switchViewPreset('weekAndMonth', tree.startDate, tree.endDate);
            }
        },
        {
            text : 'Weeks 2',
            toggleGroup : 'presets',
            enableToggle : true,
            iconCls : 'icon-calendar',
            handler : function() {
                tree.switchViewPreset('weekAndDayLetter', tree.startDate, tree.endDate);
            }
        },
        {
            text : 'Weeks 3',
            toggleGroup : 'presets',
            enableToggle : true,
            iconCls : 'icon-calendar',
            handler : function() {
                tree.switchViewPreset('weekDateAndMonth', tree.startDate, tree.endDate);
            }
        },
        {
            text : 'Months',
            toggleGroup : 'presets',
            enableToggle : true,
            iconCls : 'icon-calendar',
            handler : function() {
                tree.switchViewPreset('monthAndYear', tree.startDate, tree.endDate);
            }
        },
        {
            text : 'Years',
            enableToggle : true,
            toggleGroup : 'presets',
            iconCls : 'icon-calendar',
            handler : function() {
                tree.switchViewPreset('year', new Date(2012, 5, 1), new Date(2013, 2, 28));
            }
        },
        '->',
        {
            text : '+',
            scale: 'medium',
            iconCls: 'zoomIn',
            handler: function () {
                tree.zoomIn();
            }
        },
        {
            text : '-',
            scale: 'medium',
            iconCls: 'zoomOut',
            handler: function () {
                tree.zoomOut();
            }
        }                                                 
    ],


    getTimelineRecordByEventRecord : function(groupId) {
        return this.timelineStore.getById(groupId);
    },

    eventRenderer : function(item, resource, tplData, row, col) {
        meta.cls = 'leaf';
        meta.style = 'background-color:' + (resource.get('Color') || 'Coral');
        return item.get('Name');
    },

    initComponent: function() {
        var me = this;
        Ext.apply(this, {
            
            
            columns: 
            [
                {
                    xtype       : 'treecolumn',
                    text        : 'CONTENT',
                    width       : 300,
                    sortable    : false,
                    dataIndex   : 'Name'
                },
                {
                    text        : 'STAKEHOLDERS',
                    width       : 200,
                    sortable    : false,
                    dataIndex   : 'Stakeholders'

                }
            ],


		    plugins : [
                
		    ]
        });
        

        //this.resourceStore = Ext.data.StoreManager.lookup('treeNodeStore');
        this.eventStore = Ext.create('ExtCalendar.store.Events');
        this.resourceStore = Ext.create('ExtCalendar.store.TreeNodes');
        
        this.callParent(arguments);


    },

    afterRender : function() {
        //this.callParent(arguments);
        
    }
});


my tree's resource store:
 Ext.define('ExtCalendar.store.TreeNodes', {
    extend : "Sch.data.ResourceStore",
    model : 'ExtCalendar.model.Tree',
    storeId : 'treeNodeStore',
   
    folderSort  : true,

    proxy: {
        type    : 'ajax',
        url     : '../../tempdata/tree-data.js'
    },
    autoLoad : true,
    autoSync : true
});
my event store:
 Ext.define('ExtCalendar.store.Events', {
    extend  : 'Sch.data.EventStore',
    model   : 'Sch.model.Event',
    storeId : 'eventStore',

    proxy   : {
        type    : 'ajax',
        url     : '../../tempdata/event-data.js'
    },
    autoLoad : true,
    autoSync : true
});

Post by chris3farrell »

Some progress.
I started using 'ext-all-dev.js' in hopes of getting some more info.

Chasing the error: "Uncaught TypeError: Object [object Object] has no method 'getRootNode' "
led me to notice that I was extending ResourceStore instead of ResourceTreeStore.

Now, the Scheduler renders when I test. None of my tree nodes have titles, and none of my events are rendering,
but the component is displaying in the viewport without console errors. It still will not build or refresh. Same error there.

And I do now see 2 Ex.Loader warnings:
[Ext.Loader] Synchronously loading 'ExtCalendar.store.TreeNodes'; consider adding Ext.require('ExtCalendar.store.TreeNodes') above Ext.onReady
[Ext.Loader] Synchronously loading 'ExtCalendar.store.Events'; consider adding Ext.require('ExtCalendar.store.Events') above Ext.onReady

I tried placing a requires:['ExtCalendar.store.TreeNodes', 'ExtCalendar.store.Events'] in my Ext.application and in my Tree to no avail.

To resolve:

- build dependencies
- Ext.Loader warnings
- missing tree titles and missing scheduler events

Post by chris3farrell »

chris3farrell wrote: - missing tree titles and missing scheduler events
This issue is interesting. Some of the values from my tree-data.json are rendering ('icnClass' and 'expanded'), and others are not ('Name').
If I change the value of icnClass or expanded, the changes are displayed.
So, I can see the tree's structure, but not the data mapped to either of my columns.

On setting a breakpoint in my Tree, I am able to see the resourceStore and eventStore objects populated with the loaded data.
So, I'm not sure why the events and column data are not rendering. Is it a racing/timing issue?
Maybe the columns are created before the data is loaded?

Post Reply