Our state of the art Gantt chart


Post by jeanbaptiste.minani »

Hello here,
I have an issue, after adding the bryntum gantt Baseline Feature, the event of selecting/showing a specific baseline, is not working

the event that is not working it's on this button(Show baseline)
look my codes here:

import { Gantt, TaskModel, ProjectModel, Toast, DateHelper, StringHelper } from "../build-gantt/build/gantt.module.js";

class MyTaskModel extends  TaskModel {
    static get fields() {
        return [
            { name: 'weight', type: 'number' }
        ]
    }

* calculatePercentDone (proposedValue) {
    // call parent function to get original calculation result
    let value = yield* super.calculatePercentDone(proposedValue);

    let parentWeight=0;

    if(typeof this.children != "undefined") {

        this.children.forEach(function(element) {
            parentWeight+=element.weight*element.percentDone/100;
        })
    }

    return this.isParent ? parentWeight : value;
}
}

function setBaseline(index) {
    gantt.taskStore.setBaseline(index);
}

function toggleBaselineVisible(index, visible) {
    gantt.element.classList[visible ? 'remove' : 'add'](`b-hide-baseline-${index}`);
}

const project = new ProjectModel({
    taskModelClass : MyTaskModel,
    autoSync : true,
    transport : {
        load : {
            url: '../assets/build-gantt/_datasets/launch-saas.json'
        },
        sync : {
            url : 'https://localhost:8080/api/v1/task/sync'
        }
    },
    autoLoad : true,
    autoCalculatePercentDoneForParentTasks:false,

// The State TrackingManager which the UndoRedo widget in the toolbar uses
stm : {
    autoRecord : true
}
});

const gantt = new Gantt({
    project : project,
    
columns: [ { type : 'wbs' }, { type: 'name', field: 'name', text: 'Name' }, { type: 'number', min: 0, max: 100, text: 'Weight', align: 'center', field : 'weight' }, { type: 'startdate' , text: 'StartDate' }, { type: 'duration', text: 'Duration' }, { type : 'resourceassignment', width : 120, showAvatars : true }, { type: 'percentdone', text: 'Percentdone', showCircle : true, width : 70}, { type: 'predecessor', text: 'Predecessor' }, { type : 'schedulingmodecolumn' }, { type : 'calendar' }, { type : 'constrainttype' }, { type : 'constraintdate' }, { type : 'date', text : 'Deadline', field : 'deadline' }, { type: 'addnew', field: 'addnew', text: 'Addnew' }, ], style: 'font-size:0.85em', autoHeight: true, subGridConfigs: { locked: { flex: 3 }, normal: { flex: 4 } }, features: { criticalPaths: true, cellEdit : { addNewAtEnd: false, }, filter: true, taskEdit: { items: { generalTab: { items: { newGeneralField: { type: 'number', weight: 710, label: 'Weight', name: 'weight', min: 0, max: 100 } } } } }, baselines : { // Custom tooltip template for baselines template(data) { const me = this, { baseline } = data, { task } = baseline, delayed = task.startDate > baseline.startDate, overrun = task.durationMS > baseline.durationMS; let { decimalPrecision } = me; if (decimalPrecision == null) { decimalPrecision = me.client.durationDisplayPrecision; } const multiplier = Math.pow(10, decimalPrecision), displayDuration = Math.round(baseline.duration * multiplier) / multiplier; return ` <div class="b-gantt-task-title">${StringHelper.encodeHtml(task.name)} (${me.L('baseline')} ${baseline.parentIndex + 1})</div> <table> <tr><td>${me.L('Start')}:</td><td>${data.startClockHtml}</td></tr> ${baseline.milestone ? '' : ` <tr><td>${me.L('End')}:</td><td>${data.endClockHtml}</td></tr> <tr><td>${me.L('Duration')}:</td><td class="b-right">${displayDuration + ' ' + DateHelper.getLocalizedNameOfUnit(baseline.durationUnit, baseline.duration !== 1)}</td></tr> `} </table> ${delayed ? ` <h4 class="statusmessage b-baseline-delay"><i class="statusicon b-fa b-fa-exclamation-triangle"></i>${me.L('Delayed start by')} ${DateHelper.formatDelta(task.startDate - baseline.startDate)}</h4> ` : ''} ${overrun ? ` <h4 class="statusmessage b-baseline-overrun"><i class="statusicon b-fa b-fa-exclamation-triangle"></i>${me.L('Overrun by')} ${DateHelper.formatDelta(task.durationMS - baseline.durationMS)}</h4> ` : ''} `; } } }, dependencyIdField : 'wbsCode', tbar: { items: [ { type: 'buttonGroup', items: [ { color: 'b-green', ref: 'addTaskButton', icon: 'b-fa b-fa-plus', text: 'Create', tooltip: 'Create new task', style: 'margin-right: .5em', async onAction() { const newTask = { name: 'New task', duration: '1' }; const added = gantt.taskStore.rootNode.appendChild(newTask); // run propagation to calculate new task fields // await project.comitAsync(); // run propagation to calculate new task fields await gantt.project.propagateAsync(); // scroll to the added task. Smoothly. await gantt.scrollRowIntoView(added, { animate: true }); gantt.features.cellEdit.startEditing({ record: added, field: 'name' }); Toast.show({ html: 'Created a new task, you may update it at the same or click somewhere else to avoid update', color : 'b-light-green' }); } } ] }, { type: 'buttonGroup', items: [ { color: 'b-green', icon: 'b-fa b-fa-pen', text: 'Edit', tooltip: 'Edit selected task', onAction() { if (gantt.selectedRecord) { gantt.editTask(gantt.selectedRecord); } else { Toast.show('First select the task you want to edit'); } } } ] }, { type: 'buttonGroup', items: [ { type : 'button', text : 'Set baseline', icon : 'b-fa-bars', iconAlign : 'end', menu : [{ text : 'Set baseline 1', onItem() { setBaseline(1); } }, { text : 'Set baseline 2', onItem() { setBaseline(2); } }, { text : 'Set baseline 3', onItem() { setBaseline(3); } }] }, { type : 'button', text : 'Show baseline', icon : 'b-fa-bars', iconAlign : 'end', menu : [{ checked : true, text : 'Baseline 1', onToggle({ checked }) { toggleBaselineVisible(1, checked); } }, { checked : true, text : 'Baseline 2', onToggle({ checked }) { toggleBaselineVisible(2, checked); } }, { checked : true, text : 'Baseline 3', onToggle({ checked }) { toggleBaselineVisible(3, checked); } }] } ] }, { type : 'checkbox', text : 'Show baselines', checked : true, toggleable : true, onAction({ checked }) { gantt.features.baselines.disabled = !checked; } }, ] }, appendTo: document.getElementById('granttId') });

Post by saki »

Would you please post a runnable showcase that we can run, investigate and debug?


Post by jeanbaptiste.minani »

I was trying to give you more details with the whole codes/structure i'm using.. so that you will be able to see everything..

But actually the bellow function, it's the one that's not working. When I click to the "Show baseline" button

function toggleBaselineVisible(index, visible) {
    gantt.element.classList[visible ? 'remove' : 'add'](`b-hide-baseline-${index}`);
}

Post by saki »

That function adds or removes the CSS class from top-level gantt element so to debug it you would need to check:

  1. Does code gets into the function? A console.log before line 2 would show it.
  2. Is the CSS class added/removed to/from the gantt element?
  3. Is there a corresponding CSS rule to to the index such as in our demo?
    .b-hide-baseline-1 {
        .b-task-baseline[data-index="0"] {
            display : none;
        }
    }
    .b-hide-baseline-2 {
        .b-task-baseline[data-index="1"] {
            display : none;
        }
    }
  4. Isn't another more specific CSS class overriding the baseline visibility?

These are ideas without checking the real code and real markup. If you cannot make it working based on the above, post please the runnable showcase and we'll find out. Our modified example that would show the issue would do.

Notes:


Post by jeanbaptiste.minani »

Thanks Saki,
I've added those CSS styles.. as a new custom CSS styles.. and things are working now good.


Post Reply