frappe / gantt

Open Source Javascript Gantt
https://frappe.io/gantt
MIT License
4.74k stars 1.05k forks source link

it is possible to make many tasks in one row in the gantt ? #95

Open sbaiti opened 6 years ago

sbaiti commented 6 years ago

image

like this many tasks in one row , someone support please ?

netchampfaris commented 6 years ago

Not possible currently. Can you explain any use case that needs such arrangement of tasks ?

sbaiti commented 6 years ago

we need to show the blocked time Frame of a user like this gantt multiple users 67f66106-abd7-48d5-aaf5-3c8b4706447e 1

fooksem commented 6 years ago

We would also be interested in this feature!

chuongtrh commented 6 years ago

+1 Voted for this feature.

kkarabiber-s commented 5 years ago

+1

MartijnHarmenzon commented 5 years ago

Would also like to see this option. Is there any update on this feature?

satya5561 commented 4 years ago

Also like to see this option. Is there any update on this feature?

satya5561 commented 4 years ago

image

like this many tasks in one row , someone support please ?

image

like this many tasks in one row , someone support please ?

have you got anything

qool commented 4 years ago

I have a simple workaround. Not sure if it is ready for PR, but solved my problem...

Search for this lines in index.js:107

// cache index
task._index = i;

and add this code right after:

if (typeof task.custom_index === 'number') {
    task._index = task.custom_index;
}

When you pass task data with optional parameter custom_index, you will get inline task rendered in row based on that index. You have to compute it in your own and pass as number:

// example data for inline tasks

let taskData = {
 custom_index: 0,
 id: "some-udid-a",
 name: "task-A",
 start: "YYYY-MM-DD",
 end: "YYYY-MM-DD",
 progress: 0,
 dependencies: ''
},{
 custom_index: 0,
 id: "some-udid-b",
 name: "task-B",
 start: "YYYY-MM-DD",
 end: "YYYY-MM-DD",
 progress: 0,
 dependencies: ''
},{
 custom_index: 1,
 id: "some-udid-a",
 name: "task-C",
 start: "YYYY-MM-DD",
 end: "YYYY-MM-DD",
 progress: 0,
 dependencies: ''
};

Resulted in:

image

Overlapping tasks wil be also rendered ... overlapping each other, the latter on the top. You can use different css class (e.g. lower opacity) to make the overlap visible ;)

Not tested with dependent rows.

joergviola commented 4 years ago

Thank you! This works like a charme! Renamed custom_index to row in my code and now that look pretty natural.

JelleWolbers commented 4 years ago

Thanks @qool, this worked perfectly!

William-Wildridge commented 3 years ago

It's a very nice solution. In 2021, it brings the tasks onto the 'custom_index' distinct rows, however the total number of rows aren't reduced. 2021-05-22 (11)

jellederijke commented 2 years ago

@William-Wildridge I struggled with this issue, as wel.. After much tinkering I have created a fix. Do note that I am by no means a JS expert. But this does work for me.

I have modified @qool 's fix by using the term row_id, like so: // cache index task._index = i; if (typeof task.row_id === 'number') { task._index = task.row_id; }

Then I needed to know how many unique row_id's I have and iterate over these unique rows, instead of iterating over the tasks. I did this by editing the make_grid_rows() like so:

make_grid_rows() {
        let counter_rows = 0;
        const distinctRows = [...new Set(this.tasks.map(x => x.row_id))];
        for (let row of distinctRows){
            counter_rows = counter_rows + 1;
        }
        console.log(counter_rows + " unique rows")

        const rows_layer = createSVG('g', { append_to: this.layers.grid });
        const lines_layer = createSVG('g', { append_to: this.layers.grid });
        const row_width = this.dates.length * this.options.column_width;
        const row_height = this.options.bar_height + this.options.padding;

        let row_y = this.options.header_height + this.options.padding / 2;
        //var counter = 0;

        for (let row of distinctRows) {
            // console.log("for each log");
            // console.log(counter);
            // counter = counter + 1;
            // console.log(counter);
            // console.log('row id:' + task.row_id)

            createSVG('rect', {
                x: 0,
                y: row_y,
                width: row_width,
                height: row_height,
                class: 'grid-row',
                append_to: rows_layer
            });

            createSVG('line', {
                x1: 0,
                y1: row_y + row_height,
                x2: row_width,
                y2: row_y + row_height,
                class: 'row-line',
                append_to: lines_layer
            });

            row_y += this.options.bar_height + this.options.padding;
        }
    }

I hope someone finds this fix useful!

bg

Jelle

Nikhilbk1705 commented 2 years ago

I have a simple workaround. Not sure if it is ready for PR, but solved my problem...

Search for this lines in index.js:107

// cache index task._index = i; and add this code right after:

if (typeof task.custom_index === 'number') { task._index = task.custom_index; } When you pass task data with optional parameter custom_index, you will get inline task rendered in row based on that index. You have to compute it in your own and pass as number:

// example data for inline tasks

let taskData = { custom_index: 0, id: "some-udid-a", name: "task-A", start: "YYYY-MM-DD", end: "YYYY-MM-DD", progress: 0, dependencies: '' },{ custom_index: 0, id: "some-udid-b", name: "task-B", start: "YYYY-MM-DD", end: "YYYY-MM-DD", progress: 0, dependencies: '' },{ custom_index: 1, id: "some-udid-a", name: "task-C", start: "YYYY-MM-DD", end: "YYYY-MM-DD", progress: 0, dependencies: '' }; Resulted in:

image

Overlapping tasks wil be also rendered ... overlapping each other, the latter on the top. You can use different css class (e.g. lower opacity) to make the overlap visible ;)

Not tested with dependent rows.

Thanks for the solution,but it will add an extra empty row at the end chart

jellederijke commented 2 years ago

I have a simple workaround. Not sure if it is ready for PR, but solved my problem... Search for this lines in index.js:107 // cache index task._index = i; and add this code right after: if (typeof task.custom_index === 'number') { task._index = task.custom_index; } When you pass task data with optional parameter custom_index, you will get inline task rendered in row based on that index. You have to compute it in your own and pass as number: // example data for inline tasks let taskData = { custom_index: 0, id: "some-udid-a", name: "task-A", start: "YYYY-MM-DD", end: "YYYY-MM-DD", progress: 0, dependencies: '' },{ custom_index: 0, id: "some-udid-b", name: "task-B", start: "YYYY-MM-DD", end: "YYYY-MM-DD", progress: 0, dependencies: '' },{ custom_index: 1, id: "some-udid-a", name: "task-C", start: "YYYY-MM-DD", end: "YYYY-MM-DD", progress: 0, dependencies: '' }; Resulted in: image Overlapping tasks wil be also rendered ... overlapping each other, the latter on the top. You can use different css class (e.g. lower opacity) to make the overlap visible ;) Not tested with dependent rows.

Thanks for the solution,but it will add an extra empty row at the end chart

Please see my above post to fix your issue.

Nikhilbk1705 commented 2 years ago

I have a simple workaround. Not sure if it is ready for PR, but solved my problem... Search for this lines in index.js:107 // cache index task._index = i; and add this code right after: if (typeof task.custom_index === 'number') { task._index = task.custom_index; } When you pass task data with optional parameter custom_index, you will get inline task rendered in row based on that index. You have to compute it in your own and pass as number: // example data for inline tasks let taskData = { custom_index: 0, id: "some-udid-a", name: "task-A", start: "YYYY-MM-DD", end: "YYYY-MM-DD", progress: 0, dependencies: '' },{ custom_index: 0, id: "some-udid-b", name: "task-B", start: "YYYY-MM-DD", end: "YYYY-MM-DD", progress: 0, dependencies: '' },{ custom_index: 1, id: "some-udid-a", name: "task-C", start: "YYYY-MM-DD", end: "YYYY-MM-DD", progress: 0, dependencies: '' }; Resulted in: image Overlapping tasks wil be also rendered ... overlapping each other, the latter on the top. You can use different css class (e.g. lower opacity) to make the overlap visible ;) Not tested with dependent rows.

Thanks for the solution,but it will add an extra empty row at the end chart

Please see my above post to fix your issue.

Thanks for the quick response, so kind of you. My issue is , i am getting the multiple bar in each row, but for every multiple bar i render in the single row, i don't know why ,there is an extra empty row added at bottom of chart, i will attach picture of my issue it will give you better idea and my task array screenshot is also attached.

issue image

jellederijke commented 2 years ago

Thanks for the quick response, so kind of you. My issue is , i am getting the multiple bar in each row, but for every multiple bar i render in the single row, i don't know why ,there is an extra empty row added at bottom of chart, i will attach picture of my issue it will give you better idea and my task array screenshot is also attached.

issue image

This is the exact issue that my above fix solves. So please try to look into this fix in order to solve your empty rows.

Nikhilbk1705 commented 2 years ago

Thanks for the quick response, so kind of you. My issue is , i am getting the multiple bar in each row, but for every multiple bar i render in the single row, i don't know why ,there is an extra empty row added at bottom of chart, i will attach picture of my issue it will give you better idea and my task array screenshot is also attached. issue image

This is the exact issue that my above fix solves. So please try to look into this fix in order to solve your empty rows.

Thank you so much for your quick reply, it worked like CHARM!!!. Previously i was looking into your earlier solution, so i didn't able to solve, then i noticed your latest solution then I am able solve the issue. Once again thank you so much, it helped alot.

tallvincent commented 1 year ago

@William-Wildridge I struggled with this issue, as wel.. After much tinkering I have created a fix. Do note that I am by no means a JS expert. But this does work for me.

I have modified @qool 's fix by using the term row_id, like so: // cache index task._index = i; if (typeof task.row_id === 'number') { task._index = task.row_id; }

Then I needed to know how many unique row_id's I have and iterate over these unique rows, instead of iterating over the tasks. I did this by editing the make_grid_rows() like so:

make_grid_rows() {
        let counter_rows = 0;
        const distinctRows = [...new Set(this.tasks.map(x => x.row_id))];
        for (let row of distinctRows){
            counter_rows = counter_rows + 1;
        }
        console.log(counter_rows + " unique rows")

        const rows_layer = createSVG('g', { append_to: this.layers.grid });
        const lines_layer = createSVG('g', { append_to: this.layers.grid });
        const row_width = this.dates.length * this.options.column_width;
        const row_height = this.options.bar_height + this.options.padding;

        let row_y = this.options.header_height + this.options.padding / 2;
        //var counter = 0;

        for (let row of distinctRows) {
            // console.log("for each log");
            // console.log(counter);
            // counter = counter + 1;
            // console.log(counter);
            // console.log('row id:' + task.row_id)

            createSVG('rect', {
                x: 0,
                y: row_y,
                width: row_width,
                height: row_height,
                class: 'grid-row',
                append_to: rows_layer
            });

            createSVG('line', {
                x1: 0,
                y1: row_y + row_height,
                x2: row_width,
                y2: row_y + row_height,
                class: 'row-line',
                append_to: lines_layer
            });

            row_y += this.options.bar_height + this.options.padding;
        }
    }

I hope someone finds this fix useful!

bg

Jelle

For anyone interested, if you want the total grid background to scale to the number of unique rows, add the following into the make_grid_background() in index.js (line ~310):

const distinct_rows = [...new Set(this.tasks.map(x => x.row_id))];

And then grid_height needs to be dependent on the length of distinct_rows instead of this.tasks

const grid_height =
            this.options.header_height +
            this.options.padding +
            (this.options.bar_height + this.options.padding) *
                distinct_rows.length;

Full make_grid_background() function:

make_grid_background() {
        const grid_width = this.dates.length * this.options.column_width;
        // check distinct rows so the grid height isn't relative to the total tasks
        const distinct_rows = [...new Set(this.tasks.map(x => x.row_id))];
        const grid_height =
            this.options.header_height +
            this.options.padding +
            (this.options.bar_height + this.options.padding) *
                distinct_rows.length;

        createSVG('rect', {
            x: 0,
            y: 0,
            width: grid_width,
            height: grid_height,
            class: 'grid-background',
            append_to: this.layers.grid,
        });

        $.attr(this.$svg, {
            // +XX is required so info is shown correctly - 50 seems like a good middle ground
            height: grid_height + this.options.padding + 50, 
            width: '100%',
        });
    }