Request new features or modifications


Post by Dev_Coppelis »

Hi,
I would like to check if a feature is already available (as I assume it is a must have function) :
• From the advanced view, the possibility to copy/paste a parent task (or a group of tasks), including sub tasks and all the related data (dates, resources, relations, ..).

BR

Post by Maxim Gorkovsky »

Hello.
There is a plugin allowing to copy/paste various data, but it cannot create new records: clipboard. It is enabled by default in our advanced demo.
I made a feature request for plugin with such functionality: https://app.assembla.com/spaces/bryntum/tickets/5331

Post by Dev_Coppelis »

Hi,
thanks for creating feature request.
Please note that this copy/paste should include sub tasks.
Any idea on when this is supposed to be available ?

Post by Maxim Gorkovsky »

I'm afraid I cannot say when exactly we will start on this feature, we have a lot on our plate now. You can subscribe to the ticket to get updates. We have some drafts of similar feature, so should not take very long.
Also there is always option to prioritize features by contacting sales at bryntum.com

Do you expect copy action to copy everything related to task, i.e. children, dependencies and resource assignments?

Post by Dev_Coppelis »

ok thanks for the information.

Yes copy everything related to task (like MS Project) .

There is also a related feature : When importing MS project file, to insert the content at the current position on the Gantt (currently this action deletes existing tasks).

Need to create a request for this too ?

Post by Maxim Gorkovsky »

I am not sure if this is worthy of feature request. This task should be pretty simple. Try following:
1) See #importData method of the Importer plugin
2) Instead of loading data into stores (dependencies, resources,..), append it. See this doc: https://docs.sencha.com/extjs/6.5.1/clas ... d-loadData
3) Instead of setting root use node.appendChild where node is task record that you want to import to
4) Avoid setting project calendar and do not set newRoot id to 'root'

This should do the trick.

Post by Dev_Coppelis »

Hi,
Any news about this copy/paste feature ?
Maxim Gorkovsky wrote:Hello.
There is a plugin allowing to copy/paste various data, but it cannot create new records: clipboard. It is enabled by default in our advanced demo.
I made a feature request for plugin with such functionality: https://app.assembla.com/spaces/bryntum/tickets/5331

Post by Terence »

It's not prioritised or in the pipeline yet. If you want to speed things up, I suggest to contact sales@bryntum.com

Post by Dev_Coppelis »

Maxim Gorkovsky wrote:I am not sure if this is worthy of feature request. This task should be pretty simple. Try following:
1) See #importData method of the Importer plugin
2) Instead of loading data into stores (dependencies, resources,..), append it. See this doc: https://docs.sencha.com/extjs/6.5.1/clas ... d-loadData
3) Instead of setting root use node.appendChild where node is task record that you want to import to
4) Avoid setting project calendar and do not set newRoot id to 'root'

This should do the trick.
Hi Maxim,
i changed the loading data into stores (dependencies, resources) to append but i don't know how to get the id of task to append Child.
Kindly find the below code
Ext.define('Gnt.examples.advanced.overrides.Importer', {
    extend: 'Ext.AbstractPlugin',

    alias: 'plugin.msproject_importer',

    taskStore: null,
    dependencyStore: null,
    assignmentStore: null,
    resourceStore: null,
    calendarManager: null,

    taskMap: null,
    resourceMap: null,

    syncBlock: function () {
        return false;
    },

    init: function (gantt) {
        this.taskStore = gantt.taskStore;
        this.dependencyStore = gantt.dependencyStore;
        this.resourceStore = gantt.resourceStore;
        this.assignmentStore = gantt.assignmentStore;
        this.calendarManager = this.taskStore.calendarManager;

        this.taskModelIdProperty = this.taskStore.model.prototype.idProperty;
        this.resourceModelIdProperty = this.resourceStore.model.prototype.idProperty;
        this.assignmentModelIdProperty = this.assignmentStore.model.prototype.idProperty;
        this.assignmentModelTaskIdProperty = this.assignmentStore.model.prototype.taskIdField;
        this.assignmentModelResourceIdProperty = this.assignmentStore.model.prototype.resourceIdField;
        this.dependencyModelIdProperty = this.dependencyStore.model.prototype.idProperty;
        this.dependencyModelFromProperty = this.dependencyStore.model.prototype.fromField;
        this.dependencyModelToProperty = this.dependencyStore.model.prototype.toField;

        // if we have CalendarManager onboard we do calendars importing as well
        if (this.calendarManager) {
            this.calendarModelIdProperty = this.calendarManager.model.prototype.idProperty;
            this.taskModelCalendarIdProperty = this.taskStore.model.prototype.CalendarIdField;
            this.resourceModelCalendarIdProperty = this.resourceStore.model.prototype.CalendarIdField;
        }
    },

    /*
     * @param {Object} data A custom data set with 'tasks', 'dependencies', 'assignments' and 'resources' properties.
     * */
    importData: function (data) {
        this.calendarMap = {};
        this.taskMap = {};
        this.resourceMap = {};
        this.projectCalendar = null;

        var taskStore = this.taskStore;

        taskStore.on('beforesync', this.syncBlock);

        taskStore.suspendEarlyDatesResetNotification();
        taskStore.suspendLateDatesResetNotification();

        // import calendars if we have CalendarManager
        this.calendarManager && this.processCalendars(data);

        var tasks = this.getTaskTree(Ext.isArray(data.tasks) ? data.tasks : [data.tasks]);

        this.processResources(data);
        this.processDependencies(data);
        this.processAssignments(data);

        var newRoot = Ext.isArray(data.tasks) ? {} : tasks[0];
        newRoot.children = tasks;

        if (newRoot.isNode) {
            // TODO: set root node id to "root" to comply w/ server side demos
            newRoot.setId('root');
            // seems extjs doesn't track root id change and children keep parentId intact
            Ext.Array.each(newRoot.childNodes, function (node) { node.data.parentId = 'root'; });

            // if instance is passed then getTreeStore will return null
            // https://www.sencha.com/forum/showthread.php?297640
            newRoot.join(taskStore);
        }

        // set project calendar if it's provided
        // we set project calendar in silent mode to not readjust all the tasks
        this.projectCalendar && taskStore.setCalendar(this.calendarMap[this.projectCalendar].getCalendar(), true);
        
        taskStore.setRoot(newRoot);

        taskStore.un('beforesync', this.syncBlock);

        taskStore.resumeEarlyDatesResetNotification();
        taskStore.resumeLateDatesResetNotification();
    },

    /* RESOURCES */
    processResources: function (data) {
        var resources = [];

        Ext.Array.map(data.resources, this.processResource, this);

        this.resourceStore.loadData(resources, true);
    },

    processResource: function (resData) {
        var id = resData[this.resourceModelIdProperty];
        delete resData[this.resourceModelIdProperty];

        resData[this.resourceModelCalendarIdProperty] = this.calendarMap[resData[this.resourceModelCalendarIdProperty]];

        var resource = new this.resourceStore.model(resData);

        this.resourceMap[id] = resource;
        return resource;
    },
    /* EOF RESOURCES */

    /* DEPENDENCIES */
    processDependencies: function (data) {
        var deps = Ext.Array.map(data.dependencies, this.processDependency, this);

        this.dependencyStore.loadData(deps, true);
    },

    processDependency: function (depData) {
        var fromId = depData[this.dependencyModelFromProperty];
        var toId = depData[this.dependencyModelToProperty];
        delete depData[this.dependencyModelFromProperty];
        delete depData[this.dependencyModelToProperty];
        delete depData[this.dependencyModelIdProperty];
        var dep = new this.dependencyStore.model(depData);

        dep.setSourceTask(this.taskMap[fromId]);
        dep.setTargetTask(this.taskMap[toId]);

        return dep;
    },
    /* EOF DEPENDENCIES */

    /* ASSIGNMENTS */
    processAssignments: function (data) {
        Ext.Array.each(data.assignments, this.processAssignment, this);
    },

    processAssignment: function (asData) {
        var resourceId = asData[this.assignmentModelResourceIdProperty];
        var taskId = asData[this.assignmentModelTaskIdProperty];
        delete asData[this.assignmentModelIdProperty];
        delete asData[this.assignmentModelResourceIdProperty];
        delete asData[this.assignmentModelTaskIdProperty];

        this.taskMap[taskId].assign(this.resourceMap[resourceId], asData.Units);
    },
    /* EOF ASSIGNMENTS */

    /* TASKS  */
    getTaskTree: function (tasks) {
        return Ext.Array.map(tasks, this.processTask, this);
    },

    processTask: function (data) {
        var id = data[this.taskModelIdProperty];
        var children = data.children;

        delete data.children;
        delete data[this.taskModelIdProperty];

        data[this.taskModelCalendarIdProperty] = this.calendarMap[data[this.taskModelCalendarIdProperty]];

        var t = new this.taskStore.model(data);
        t.taskStore = this.taskStore;

        if (children) {
            t.appendChild(this.getTaskTree(children));
        }

        t._Id = id;
        this.taskMap[t._Id] = t;

        return t;
    },
    /* EOF TASKS  */

    /* CALENDARS */
    processCalendarChildren: function (children) {
        return Ext.Array.map(children, this.processCalendar, this);
    },

    processCalendar: function (data) {
        var id = data[this.calendarModelIdProperty];
        var children = data.children;

        delete data.children;
        delete data[this.calendarModelIdProperty];

        var t = new this.calendarManager.model(data);

        if (children) {
            t.appendChild(this.processCalendarChildren(children));
        }

        t._Id = id;
        this.calendarMap[t._Id] = t;

        return t;
    },

    // Entry point of calendars loading
    processCalendars: function (data) {
        var calendarManager = this.calendarManager;

        var metaData = data.calendars.metaData;

        delete data.calendars.metaData;

        var processed = this.processCalendarChildren([data.calendars]),
            newRoot = processed[0];

        if (newRoot.isNode) {
            // TODO: set root node id to "root" to comply w/ server side demos
            newRoot.setId('root');
            // seems extjs doesn't track root id change and children keep parentId intact
            Ext.Array.each(newRoot.childNodes, function (node) { node.data.parentId = 'root'; });

            // if instance is passed then getTreeStore will return null
            // https://www.sencha.com/forum/showthread.php?297640
            newRoot.join(calendarManager);
        }

        calendarManager.setRoot(newRoot);

        // remember passed project calendar identifier ..we will set it later after tasks are loaded
        this.projectCalendar = metaData && metaData.projectCalendar;
    }
    /* EOF CALENDARS */

});

Post by mats »

That's a bit too much code to review I'm afraid. To get the task id:
task.getId();

Post Reply