Show cool things you have done with our products


Post by laxmikantgavali »

Below is the list of issues that I wish to seek your help on
1. Customization of task menu.
2. Calling customize event on menu item click and refreshing respective task after event occur.
3. Html script on page but it is not visible in page

Following is the code that I had tried. Please correct me if did any thing wrong.
Ext.onReady(function() {
    Ext.QuickTips.init();
    
    App.init();
});

TaskPriority = {
    Low : 0,
    Normal : 1,
    High : 2
};

App = {

    // Initialize application
    init: function() {
        Ext.define("TaskModelWithBaseline", {
            extend: "Gnt.model.Task",

            // Some custom field definitions
            fields: [
                { name: 'Id', type: 'int', useNull: true },
                { name: 'Type', type: 'int', useNull: true },
                { name: 'StartDate', type: 'date', dateFormat: 'MS' },
                { name: 'EndDate', type: 'date', dateFormat: 'MS' },
                { name: 'Priority', defaultValue: 1 },
                { name: 'BaselineStartDate', type: 'date', dateFormat: 'MS' },
                { name: 'BaselineEndDate', type: 'date', dateFormat: 'MS' },
                { name: 'BaselinePercentDone' },
                { name: 'TillTodayPercentDone' }

            ]
        });


        var taskStore = Ext.create("Gnt.data.TaskStore", {
            model: 'TaskModelWithBaseline',
            proxy: {
                type: 'ajax',
                headers: { "Content-Type": 'application/json' },
                api: {
                    read: 'webservices/Tasks.asmx/Get',
                    create: 'webservices/Tasks.asmx/Create',
                    destroy: 'webservices/Tasks.asmx/Delete',
                    update: 'webservices/Tasks.asmx/Update'
                },
                writer: {
                    type: 'json',
                    root: 'jsonData',
                    encode: false,
                    allowSingle: false
                },
                reader: {
                    type: 'json',
                    root: function(o) {
                        if (o.d) {
                            return o.d;
                        } else {
                            return o.children;
                        }
                    }
                }
            }
        });

        var printableMilestoneTpl = new Gnt.template.Milestone({
            prefix: 'foo',
            printable: true,
            imgSrc: 'images/milestone.png'
        });

        var start = dt, //new Date(2010, 12, 1),
            end = Sch.util.Date.add(start, Sch.util.Date.MONTH, 10);
        debugger;
        var g = Ext.create("Gnt.panel.Gantt", {
            height: '100%',
            width: '100%',
            region: 'center',
            //selModel: new Ext.selection.TreeModel({ ignoreRightMouseSelection: false, mode: 'MULTI' }),
            renderTo: Ext.getBody(),
            //leftLabelField: 'Name',
            highlightWeekends: false,
            showTodayLine: true,
            showBaseline: true,
            loadMask: false,
            startDate: start,
            endDate: end,
            multiSelect: true,
            cascadeChanges: true,
            viewPreset: 'weekAndDayLetter',
            // Add some extra functionality
            plugins: [
                        Ext.create("Gnt.plugin.TaskContextMenu"),
                           new Gnt.plugin.Printable({
                               printRenderer: function(task, tplData) {
                                   if (task.isMilestone()) {
                                       return;
                                   } else if (task.isLeaf()) {
                                       var availableWidth = tplData.width - 4,
                        progressWidth = Math.floor(availableWidth * task.get('PercentDone') / 100);

                                       return {
                                           // Style borders to act as background/progressbar
                                           progressBarStyle: Ext.String.format('width:{2}px;border-left:{0}px solid #7971E2;border-right:{1}px solid #E5ECF5;', progressWidth, availableWidth - progressWidth, availableWidth)
                                       };
                                   } else {
                                       var availableWidth = tplData.width - 2,
                        progressWidth = Math.floor(availableWidth * task.get('PercentDone') / 100);

                                       return {
                                           // Style borders to act as background/progressbar
                                           progressBarStyle: Ext.String.format('width:{2}px;border-left:{0}px solid #FFF3A5;border-right:{1}px solid #FFBC00;', progressWidth, availableWidth - progressWidth, availableWidth)
                                       };
                                   }
                               },

                               beforePrint: function(sched) {
                                   var v = sched.getSchedulingView();
                                   this.oldRenderer = v.eventRenderer;
                                   this.oldMilestoneTemplate = v.milestoneTemplate;
                                   v.milestoneTemplate = printableMilestoneTpl;
                                   v.eventRenderer = this.printRenderer;
                               },

                               afterPrint: function(sched) {
                                   var v = sched.getSchedulingView();
                                   v.eventRenderer = this.oldRenderer;
                                   v.milestoneTemplate = this.oldMilestoneTemplate;
                               }
                           })
                        ],
            eventRenderer: function(task) {
                var prioCls;
                switch (task.get('Priority')) {
                    case TaskPriority.Low:
                        prioCls = 'sch-gantt-prio-low';
                        break;

                    case TaskPriority.Normal:
                        prioCls = 'sch-gantt-prio-normal';
                        break;

                    case TaskPriority.High:
                        prioCls = 'sch-gantt-prio-high';
                        break;
                }

                return {
                    cls: prioCls
                };
            },

            // Setup your static columns
            columns: [
               new Gnt.column.WBS(),
               {
                   xtype: 'treecolumn',
                   header: 'Components',
                   dataIndex: 'Name',
                   width: 150
               },
               new Gnt.column.StartDate(),
               new Gnt.column.Duration(),
               new Gnt.column.PercentDone()
            ],
            taskStore: taskStore,
            tooltipTpl: new Ext.XTemplate(
                '<h4 class="tipHeader">{Name}</h4>',
                '<table class="tipHeader">',
                    '<tr><td>Start:</td> <td align="right">{[Ext.Date.format(values.StartDate, "d-m-y")]}</td></tr>',
                    '<tr><td>End:</td> <td align="right">{[Ext.Date.format(values.EndDate, "d-m-y")]}</td></tr>',
                    '<tr><td>Progress:</td><td align="right">{PercentDone}%</td></tr>',
                    '<tr><td>Till Date:</td><td align="right">{TillTodayPercentDone}%</td></tr>',
                '</table>'
            ).compile(),

            tbar: [
                {
                    text: 'Show baseline',
                    enableToggle: true,
                    pressed: true,
                    handler: function() {
                        g.el.toggleCls('sch-ganttpanel-showbaseline');
                    }
                },
                {
                    text: 'Collapse all',
                    iconCls: 'icon-collapseall',
                    handler: function() {
                        g.collapseAll();
                    }
                },
                 {
                     text: 'Expand all',
                     iconCls: 'icon-expandall',
                     handler: function() {
                         g.expandAll();
                     }
                 },
                {
                    text: 'Zoom to fit',
                    iconCls: 'icon-zoomtofit',
                    handler: function() {
                        g.zoomToFit();
                    }
                },
                {
                    text: 'Save',
                    iconCls: 'icon-save',
                    handler: function() {
                        taskStore.sync();
                    }
                },
                {
                    iconCls: 'icon-print',
                    scale: 'large',
                    text: 'Print',
                    handler: function() {
                        // Make sure this fits horizontally on one page.
                        g.zoomToFit();
                        g.print();
                    }
                }

            ]
        });
        return g;
    }
};



Ext.define("Gnt.plugin.TaskContextMenu", {
    extend: "Ext.menu.Menu",

    requires: [
        'Gnt.model.Dependency'
    ],

    plain: true,

    /**
    * @cfg {String} triggerEvent
    * The event upon which the menu shall be shown. Defaults to 'taskcontextmenu', meaning the menu is shown when right-clicking a task.
    * You can change this to 'itemcontextmenu' if you want the menu to be shown when right clicking the a grid cell too.
    */
    triggerEvent: 'taskcontextmenu',

    /**
    * @cfg {Object} texts 
    * A object, purposed for I18n. Contains the following keys/values:

    - newTaskText         : 'New task', 
    - newMilestoneText    : 'New milestone', 
    - deleteTask          : 'Delete task',
    - editLeftLabel       : 'Edit left label',
    - editRightLabel      : 'Edit right label',
    - add                 : 'Add...',
    - deleteDependency    : 'Delete dependency...',
    - addTaskAbove        : 'Task above',
    - addTaskBelow        : 'Task below',
    - addMilestone        : 'Milestone',
    - addSubtask          : 'Sub-task',
    - addSuccessor        : 'Successor',
    - addPredecessor      : 'Predecessor'

     */
    texts: {
        newTaskText: 'Add Component',
        newMilestoneText: 'New milestone',
        deleteTask: 'Delete Component(s)',
        editLeftLabel: 'Edit left label',
        editRightLabel: 'Edit right label',
        add: 'Add...',
        deleteDependency: 'Delete dependency...',
        addTaskAbove: 'Task above',
        addTaskBelow: 'Task below',
        addMilestone: 'Milestone',
        addSubtask: 'Sub-task',
        addSuccessor: 'Successor',
        addPredecessor: 'Predecessor'
    },


    grid: null,
    /**
    * @property {Gnt.model.Task} rec Contains the task model, on which the right click have occured
    */
    rec: null,

    lastHighlightedItem: null,


    /**
    * This method is being called during plugin initialization. Override if you need to customize the items in the menu. 
    * The method should return the array of the menu items, which will be used as the value of `items` property.
    * @return {Array}
    */
    createMenuItems: function() {
        var texts = this.texts;

        return [
            {
                handler: this.deleteTask,
                requiresTask: true,
                scope: this,
                text: texts.deleteTask
            },
            {
                handler: this.editLeftLabel,
                requiresTask: true,
                scope: this,
                text: texts.editLeftLabel
            },
            {
                handler: this.editRightLabel,
                requiresTask: true,
                scope: this,
                text: texts.editRightLabel
            },
            {
                text: texts.add,

                menu: {
                    plain: true,
                    items: [
                        {
                            handler: this.addTaskAboveAction,
                            requiresTask: true,
                            scope: this,
                            text: texts.addTaskAbove
                        },
                        {
                            handler: this.addTaskBelowAction,
                            scope: this,
                            text: texts.addTaskBelow
                        },
                        {
                            handler: this.addMilestone,
                            scope: this,
                            text: texts.addMilestone
                        },
                        {
                            handler: this.addSubtask,
                            requiresTask: true,
                            scope: this,
                            text: texts.addSubtask
                        },
                        {
                            handler: this.addSuccessor,
                            requiresTask: true,
                            scope: this,
                            text: texts.addSuccessor
                        },
                        {
                            handler: this.addPredecessor,
                            requiresTask: true,
                            scope: this,
                            text: texts.addPredecessor
                        }
                    ]
                }
            },
            {
                text: texts.deleteDependency,
                requiresTask: true,
                menu: {
                    plain: true,

                    listeners: {
                        beforeshow: this.populateDependencyMenu,

                        // highlight dependencies on mouseover of the menu item
                        mouseover: this.onDependencyMouseOver,

                        // unhighlight dependencies on mouseout of the menu item
                        mouseleave: this.onDependencyMouseOut,

                        scope: this
                    }
                }
            }
        ];
    },


    // backward compat
    buildMenuItems: function() {
        this.items = this.createMenuItems();
    },


    initComponent: function() {
        this.buildMenuItems();

        this.callParent(arguments);
    },


    init: function(grid) {
        grid.on('destroy', this.cleanUp, this);
        var scheduleView = grid.getSchedulingView(),
            lockedView = grid.lockedGrid.getView();

        if (this.triggerEvent === 'itemcontextmenu') {
            lockedView.on('itemcontextmenu', this.onItemContextMenu, this);
            scheduleView.on('itemcontextmenu', this.onItemContextMenu, this);
        } else {
            scheduleView.on('taskcontextmenu', this.onTaskContextMenu, this);
        }

        // Handle case of empty schedule too
        scheduleView.on('containercontextmenu', this.onContainerContextMenu, this);
        lockedView.on('containercontextmenu', this.onContainerContextMenu, this);

        this.grid = grid;
    },


    populateDependencyMenu: function(menu) {
        var grid = this.grid,
            taskStore = grid.getTaskStore(),
            dependencies = this.rec.getAllDependencies(),
            depStore = grid.dependencyStore;

        menu.removeAll();

        if (dependencies.length === 0) {
            return false;
        }

        var taskId = this.rec.getId() || this.rec.internalId;

        Ext.each(dependencies, function(dependency) {
            var fromId = dependency.get('From'),
                task = taskStore.getById(fromId == taskId ? dependency.get('To') : fromId);

            if (task) {
                menu.add({
                    depId: dependency.internalId,
                    text: Ext.util.Format.ellipsis(task.get('Name'), 30),

                    scope: this,
                    handler: function(menuItem) {
                        // in 4.0.2 `indexOfId` returns the record by the `internalId`
                        // in 4.0.7 `indexOfId` returns the record by its "real" id
                        // so need to manually scan the store to find the record

                        var record;

                        depStore.each(function(dependency) {
                            if (dependency.internalId == menuItem.depId) { record = dependency; return false; }
                        });

                        depStore.remove(record);
                    }
                });
            }
        }, this);
    },


    onDependencyMouseOver: function(menu, item, e) {
        if (item) {
            var schedulingView = this.grid.getSchedulingView();

            if (this.lastHighlightedItem) {
                schedulingView.unhighlightDependency(this.lastHighlightedItem.depId);
            }

            this.lastHighlightedItem = item;

            schedulingView.highlightDependency(item.depId);
        }
    },


    onDependencyMouseOut: function(menu, e) {
        if (this.lastHighlightedItem) {
            this.grid.getSchedulingView().unhighlightDependency(this.lastHighlightedItem.depId);
        }
    },


    cleanUp: function() {
        if (this.menu) {
            this.menu.destroy();
        }
    },

    onTaskContextMenu: function(g, record, e) {
        this.activateMenu(record, e);
    },

    onItemContextMenu: function(view, record, item, index, e) {
        this.activateMenu(record, e);
    },

    onContainerContextMenu: function(g, e) {
        this.activateMenu(null, e);
    },

    activateMenu: function(rec, e) {
        e.stopEvent();

        this.rec = rec;
        var reqTasks = this.query('[requiresTask]');
        Ext.each(reqTasks, function(item) {
            item.setDisabled(!rec);
        });

        this.showAt(e.getXY());
    },


    copyTask: function(originalRecord) {
        var taskStore = this.grid.getTaskStore(),
            newTask = new taskStore.model({
                PercentDone: 0,
                Name: this.texts.newTaskText,
                StartDate: (originalRecord && originalRecord.getStartDate()) || null,
                EndDate: (originalRecord && originalRecord.getEndDate()) || null,
                Duration: (originalRecord && originalRecord.get('Duration')) || null,
                DurationUnit: (originalRecord && originalRecord.get('DurationUnit')) || 'd',
                leaf: true
            });

        //        newTask.calendar    = taskStore.calendar;

        return newTask;
    },


    addTaskAbove: function(newTask) {
        var task = this.rec;

        if (task) {
            task.parentNode.insertBefore(newTask, task);
        } else {
            this.grid.taskStore.getRootNode().appendChild(newTask);
        }
    },


    addTaskBelow: function(newTask) {
        var task = this.rec;

        if (task) {
            task.parentNode.insertBefore(newTask, task.nextSibling);
        } else {
            this.grid.taskStore.getRootNode().appendChild(newTask);
        }
    },


    // actions follow below
    deleteTask: function() {
        var tasks = this.grid.getSelectionModel().selected;

        // TODO move to task model and include check for recalculateParentsAfterEdit or similar
        if (tasks.getCount() === 1 && tasks.first().parentNode.childNodes.length == 1) {
            tasks.first().parentNode.set('leaf', true);
        }

        tasks.each(function(t) {
            t.remove();
        });
    },


    editLeftLabel: function() {
        this.grid.getSchedulingView().editLeftLabel(this.rec);
    },


    editRightLabel: function() {
        this.grid.getSchedulingView().editRightLabel(this.rec);
    },


    /**
    * Handler for the "add task above" menu item
    */
    addTaskAboveAction: function() {
        this.addTaskAbove(this.copyTask(this.rec));
    },


    /**
    * Handler for the "add task below" menu item
    */
    addTaskBelowAction: function() {
        this.addTaskBelow(this.copyTask(this.rec));
    },


    /**
    * Handler for the "add subtask" menu item
    */
    addSubtask: function() {
        var task = this.rec;

        task.set('leaf', false);
        task.appendChild(this.copyTask(task));

        task.expand();
    },


    /**
    * Handler for the "add successor" menu item
    */
    addSuccessor: function() {
        var task = this.rec,
            depStore = this.grid.dependencyStore,
            newTask = this.copyTask(task);

        this.addTaskBelow(newTask);

        newTask.set('StartDate', task.getEndDate());
        newTask.setDuration(1, Sch.util.Date.DAY);

        var dependencyClass = depStore.model;

        depStore.add(
            new dependencyClass({
                From: task.getId() || task.internalId,
                To: newTask.getId() || newTask.internalId,
                Type: dependencyClass.EndToStart
            })
        );
    },


    /**
    * Handler for the "add predecessor" menu item
    */
    addPredecessor: function() {
        var task = this.rec;
        var depStore = this.grid.dependencyStore;
        var newTask = this.copyTask(task);

        this.addTaskAbove(newTask);

        newTask.set({
            StartDate: newTask.calculateStartDate(task.getStartDate(), 1, Sch.util.Date.DAY),
            EndDate: task.getStartDate(),
            Duration: 1,
            DurationUnit: Sch.util.Date.DAY
        });

        var dependencyClass = depStore.model;

        depStore.add(
            new dependencyClass({
                From: newTask.getId() || newTask.internalId,
                To: task.getId() || task.internalId,
                Type: dependencyClass.EndToStart
            })
        );
    },


    /**
    * Handler for the "add milestone" menu item
    */
    addMilestone: function() {
        var task = this.rec,
            newTask = this.copyTask(task);

        this.addTaskBelow(newTask);

        newTask.setStartDate(newTask.getEndDate(), false);
    }
});

Post by mats »

So you basically just pasted what I sent you? That won't work. The second half of your code is the TaskContextMenu, you're trying to redefine it with the same name we use "Gnt.plugin.TaskContextMenu". You need to use your own naming for your classes (I'd advise not to use the Gnt namespace since that is 'ours', for clarity).

Post by laxmikantgavali »

Thanks, Now its working.

Post Reply