Skip to content

Adds new options for moving precedences and maintaining the positioning between dependent tasks #535

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,9 @@ Frappe Gantt offers a wide range of options to customize your chart.
| `ignore` | Ignored areas in the rendering | `weekend` _or_ Array of strings or date objects (`weekend` can be present to the array also). | `[]` |
| `language` | Language for localization. | ISO 639-1 codes like `en`, `fr`, `es`. | `en` |
| `lines` | Determines which grid lines to display. | `none` for no lines, `vertical` for only vertical lines, `horizontal` for only horizontal lines, `both` for complete grid. | `both` |
| `maintain_dependency_position`| If `true` moving or changing the end date of a task will result in the equivalent move in all dependent tasks. Also, if `move_precedences` is `true`, then moving or changing the start date of a task will result in an equivalent move for all predecing tasks | `true`, `false` | `true` |
| `move_dependencies` | Whether moving a task automatically moves its dependencies. | `true`, `false` | `true` |
| `move_precedences` | Whether moving a task automatically moves its precedent task. | `true`, `false` | `false` |
| `padding` | Padding around task bars (in pixels). | Any positive integer. | `18` |
| `popup_on` | Event to trigger the popup display. | `click` _or_ `hover` | `click` |
| `readonly_progress` | Disables editing task progress. | `true`, `false` | `false` |
Expand Down
2 changes: 2 additions & 0 deletions src/defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,9 @@ const DEFAULT_OPTIONS = {
ignore: [],
language: 'en',
lines: 'both',
maintain_dependency_position : false,
move_dependencies: true,
move_precedences: false,
padding: 18,
popup: (ctx) => {
ctx.set_title(ctx.task.name);
Expand Down
95 changes: 73 additions & 22 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ export default class Gantt {
})
.filter((t) => t);
this.setup_dependencies();
this.setup_precedences();
}

setup_dependencies() {
Expand All @@ -212,6 +213,16 @@ export default class Gantt {
}
}

setup_precedences() {
this.precedence_map = {};
for (let t of this.tasks) {
for (let d of t.dependencies) {
this.precedence_map[t.id] = this.precedence_map[t.id] || [];
this.precedence_map[t.id].push(d);
}
}
}

refresh(tasks) {
this.setup_tasks(tasks);
this.change_view_mode();
Expand Down Expand Up @@ -1075,6 +1086,7 @@ export default class Gantt {
let x_on_start = 0;
let x_on_scroll_start = 0;
let y_on_start = 0;
let width_on_start = 0;
let is_resizing_left = false;
let is_resizing_right = false;
let parent_bar_id = null;
Expand Down Expand Up @@ -1115,14 +1127,16 @@ export default class Gantt {
y_on_start = e.offsetY || e.layerY;

parent_bar_id = bar_wrapper.getAttribute('data-id');
let ids;
if (this.options.move_dependencies) {
ids = [
parent_bar_id,
...this.get_all_dependent_tasks(parent_bar_id),
];
} else {
ids = [parent_bar_id];
let parent_bar = this.get_bar(parent_bar_id);
width_on_start = parent_bar.$bar.getWidth();
let ids = [parent_bar_id];
if ((!this.options.maintain_dependency_position || !is_resizing_left)
&& this.options.move_dependencies) {
ids.push(...this.get_all_dependent_tasks(parent_bar_id));
}
if ((!this.options.maintain_dependency_position || !is_resizing_right)
&& this.options.move_precedences) {
ids.push(...this.get_all_precedent_tasks(parent_bar_id));
}
bars = ids.map((id) => this.get_bar(id));

Expand Down Expand Up @@ -1284,21 +1298,36 @@ export default class Gantt {
$bar.finaldx = this.get_snap_position(dx, $bar.ox);
this.hide_popup();
if (is_resizing_left) {
if (parent_bar_id === bar.task.id) {
bar.update_bar_position({
x: $bar.ox + $bar.finaldx,
width: $bar.owidth - $bar.finaldx,
});
} else {
bar.update_bar_position({
x: $bar.ox + $bar.finaldx,
});
if (
!this.options.maintain_dependency_position ||
width_on_start - ($bar.finaldx + this.get_unit_length()) > 0
) {
if (parent_bar_id === bar.task.id) {
bar.update_bar_position({
x: $bar.ox + $bar.finaldx,
width: $bar.owidth - $bar.finaldx,
});
} else {
bar.update_bar_position({
x: $bar.ox + $bar.finaldx,
});
}
}
} else if (is_resizing_right) {
if (parent_bar_id === bar.task.id) {
bar.update_bar_position({
width: $bar.owidth + $bar.finaldx,
});
if (
!this.options.maintain_dependency_position ||
width_on_start + ($bar.finaldx - this.get_unit_length()) > 0
) {
if (parent_bar_id === bar.task.id) {
bar.update_bar_position({
width: $bar.owidth + $bar.finaldx,
});
}
else if (this.options.maintain_dependency_position) {
bar.update_bar_position({
x: $bar.ox + $bar.finaldx,
});
}
}
} else if (
is_dragging &&
Expand Down Expand Up @@ -1433,7 +1462,23 @@ export default class Gantt {
return out.filter(Boolean);
}

get_snap_position(dx, ox) {
get_all_precedent_tasks(task_id) {
let out = [];
let from_process = [task_id];
while (from_process.length) {
const preds = from_process.reduce((acc, curr) => {
acc = acc.concat(this.precedence_map[curr]);
return acc;
}, []);

out = out.concat(preds);
from_process = preds.filter((d) => !from_process.includes(d));
}

return out.filter(Boolean);
}

get_unit_length() {
let unit_length = 1;
const default_snap =
this.options.snap_at || this.config.view_mode.snap_at || '1d';
Expand All @@ -1445,6 +1490,12 @@ export default class Gantt {
duration;
}

return unit_length;
}

get_snap_position(dx, ox) {
let unit_length = this.get_unit_length();

const rem = dx % (this.config.column_width / unit_length);

let final_dx =
Expand Down