Sfoglia il codice sorgente

[gantt] dependency arrow (#2154)

version-14
Faris Ansari 8 anni fa
committed by Rushabh Mehta
parent
commit
0d469e65f8
4 ha cambiato i file con 191 aggiunte e 106 eliminazioni
  1. +4
    -1
      frappe/public/css/gantt.css
  2. +3
    -6
      frappe/public/js/frappe/list/doclistview.js
  3. +180
    -98
      frappe/public/js/frappe/views/gantt.js
  4. +4
    -1
      frappe/public/less/gantt.less

+ 4
- 1
frappe/public/css/gantt.css Vedi File

@@ -28,7 +28,7 @@
} }
.gantt #arrow { .gantt #arrow {
fill: none; fill: none;
stroke: #333;
stroke: #666;
stroke-width: 1.4; stroke-width: 1.4;
} }
.gantt .bar { .gantt .bar {
@@ -37,6 +37,9 @@
stroke-width: 0; stroke-width: 0;
transition: stroke-width 0.3s ease; transition: stroke-width 0.3s ease;
} }
.gantt .bar-progress {
fill: #a3a3ff;
}
.gantt .bar-label { .gantt .bar-label {
fill: #fff; fill: #fff;
dominant-baseline: central; dominant-baseline: central;


+ 3
- 6
frappe/public/js/frappe/list/doclistview.js Vedi File

@@ -445,11 +445,7 @@ frappe.views.DocListView = frappe.ui.Listing.extend({
me.gantt = new Gantt({ me.gantt = new Gantt({
parent_selector: '#' + id, parent_selector: '#' + id,
bar: { bar: {
height: 20,
color: "#b8c2cc",
progress_color: "#a3a3ff",
hover_color: "#8D99A6",
hover_progress_color: "#7575ff"
height: 20
}, },
events: { events: {
bar_on_click: function (task) { bar_on_click: function (task) {
@@ -481,7 +477,8 @@ frappe.views.DocListView = frappe.ui.Listing.extend({
name: item[field_map.title], name: item[field_map.title],
id: item[field_map.id], id: item[field_map.id],
doctype: me.doctype, doctype: me.doctype,
progress: item.progress
progress: item.progress,
dependent: item.depends_on_tasks || ""
}); });
}) })
me.gantt.render(); me.gantt.render();


+ 180
- 98
frappe/public/js/frappe/views/gantt.js Vedi File

@@ -7,7 +7,6 @@ Opts:
column_width: 15 // pixels column_width: 15 // pixels
date_format: 'YYYY-MM-DD' date_format: 'YYYY-MM-DD'
bar.height: 26 bar.height: 26
bar.gap: 24
arrow.curve: 15 arrow.curve: 15


*/ */
@@ -18,6 +17,7 @@ var Gantt = Class.extend({
this.events = this.opts.events; this.events = this.opts.events;
this.tasks = []; this.tasks = [];
this._bars = []; this._bars = [];
this._arrows = [];
this.set_defaults(); this.set_defaults();
this.groups = {}; this.groups = {};
this.make(); this.make();
@@ -35,6 +35,12 @@ var Gantt = Class.extend({
"Week", "Week",
"Month" "Month"
], ],
bar: {
height: 20
},
arrow: {
curve: 5
},
view_mode: 'Day', view_mode: 'Day',
padding: 18, padding: 18,
date_format: 'YYYY-MM-DD' date_format: 'YYYY-MM-DD'
@@ -57,9 +63,10 @@ var Gantt = Class.extend({
this.setup_groups(); this.setup_groups();
this.make_grid(); this.make_grid();
this.make_dates(); this.make_dates();
this.make_arrows();
// this.make_label(); // this.make_label();
this.make_bars(); this.make_bars();
this.make_arrows();
this.set_arrows_on_bars();
this.setup_events(); this.setup_events();
this.set_width(); this.set_width();
this.set_scroll_position(); this.set_scroll_position();
@@ -73,6 +80,8 @@ var Gantt = Class.extend({
}, },
clear: function () { clear: function () {
this.canvas.clear(); this.canvas.clear();
this._bars = [];
this._arrows = [];
}, },
prepare_dates: function() { prepare_dates: function() {
var me = this; var me = this;
@@ -110,7 +119,7 @@ var Gantt = Class.extend({
cur_date = this.start.clone(); cur_date = this.start.clone();
} else { } else {
cur_date = (this.view_mode === 'Month') ? cur_date = (this.view_mode === 'Month') ?
cur_date = cur_date.clone().add(1, 'month') :
cur_date = cur_date.clone().add(1, 'month'):
cur_date.clone().add(this.opts.step, 'hours'); cur_date.clone().add(this.opts.step, 'hours');
} }
this.dates.push(cur_date); this.dates.push(cur_date);
@@ -172,7 +181,7 @@ var Gantt = Class.extend({
get_min_date: function() { get_min_date: function() {
return this.tasks.reduce(function(acc, curr) { return this.tasks.reduce(function(acc, curr) {
return curr._start.isSameOrBefore(acc._start) ? curr : acc; return curr._start.isSameOrBefore(acc._start) ? curr : acc;
})._start
})._start;
}, },
make_grid: function () { make_grid: function () {
this.make_grid_background(); this.make_grid_background();
@@ -184,8 +193,8 @@ var Gantt = Class.extend({
make_grid_background: function () { make_grid_background: function () {
var me = this; var me = this;
var grid_width = this.opts.label_width + this.dates.length * this.opts.column_width, var grid_width = this.opts.label_width + this.dates.length * this.opts.column_width,
grid_height = this.opts.header_height + this.opts.padding
+ (this.opts.bar.height + this.opts.padding) * this.tasks.length;
grid_height = this.opts.header_height + this.opts.padding +
(this.opts.bar.height + this.opts.padding) * this.tasks.length;


this.canvas.rect(0,0, grid_width, grid_height) this.canvas.rect(0,0, grid_width, grid_height)
.addClass('grid-background') .addClass('grid-background')
@@ -216,7 +225,7 @@ var Gantt = Class.extend({
row_width = me.opts.label_width + me.dates.length * me.opts.column_width, row_width = me.opts.label_width + me.dates.length * me.opts.column_width,
row_height = me.opts.bar.height + me.opts.padding, row_height = me.opts.bar.height + me.opts.padding,
row_y = me.opts.header_height + me.opts.padding/2; row_y = me.opts.header_height + me.opts.padding/2;
this.tasks.forEach(function (task, i) { this.tasks.forEach(function (task, i) {
var row_class = i % 2 ? "row-odd" : "row-even"; var row_class = i % 2 ? "row-odd" : "row-even";
me.canvas.rect(0, row_y, row_width, row_height) me.canvas.rect(0, row_y, row_width, row_height)
@@ -246,7 +255,7 @@ var Gantt = Class.extend({
tick_class += ' thick'; tick_class += ' thick';
} }
//thick ticks for quarters //thick ticks for quarters
if(me.view_mode === 'Month' && date.month() % 3 == 0) {
if(me.view_mode === 'Month' && date.month() % 3 === 0) {
tick_class += ' thick'; tick_class += ' thick';
} }


@@ -267,15 +276,15 @@ var Gantt = Class.extend({
}, },
make_grid_highlights: function() { make_grid_highlights: function() {
var me = this; var me = this;
//highlight today
//highlight today's date
if(me.view_mode === 'Day') { if(me.view_mode === 'Day') {
var x = me.opts.label_width + var x = me.opts.label_width +
moment().startOf('day').diff(me.start, 'hours') / me.opts.step * moment().startOf('day').diff(me.start, 'hours') / me.opts.step *
me.opts.column_width, me.opts.column_width,
y = 0, //me.opts.header_height + me.opts.padding/2;
y = 0,
width = me.opts.column_width, width = me.opts.column_width,
height = (me.opts.bar.height + me.opts.padding) * me.tasks.length
+ me.opts.header_height + me.opts.padding/2;
height = (me.opts.bar.height + me.opts.padding) * me.tasks.length +
me.opts.header_height + me.opts.padding/2;
me.canvas.rect(x, y, width, height) me.canvas.rect(x, y, width, height)
.addClass('today-highlight') .addClass('today-highlight')
.appendTo(me.groups.grid); .appendTo(me.groups.grid);
@@ -344,11 +353,11 @@ var Gantt = Class.extend({


me.canvas.text(primary_text_x, primary_text_y, primary_text) me.canvas.text(primary_text_x, primary_text_y, primary_text)
.addClass('primary-text') .addClass('primary-text')
.appendTo(me.groups.date)
.appendTo(me.groups.date);
if(secondary_text) { if(secondary_text) {
var $secondary_text = me.canvas.text(secondary_text_x, secondary_text_y, secondary_text) var $secondary_text = me.canvas.text(secondary_text_x, secondary_text_y, secondary_text)
.addClass('secondary-text') .addClass('secondary-text')
.appendTo(me.groups.date)
.appendTo(me.groups.date);


if($secondary_text.getBBox().x2 > me.groups.grid.getBBox().width) { if($secondary_text.getBBox().x2 > me.groups.grid.getBBox().width) {
$secondary_text.remove(); $secondary_text.remove();
@@ -379,39 +388,23 @@ var Gantt = Class.extend({
if(task.dependent) { if(task.dependent) {
var dependents = task.dependent.split(','); var dependents = task.dependent.split(',');
dependents.forEach(function (task_dependent) { dependents.forEach(function (task_dependent) {
task_dependent = task_dependent.trim();
var dependent = me.get_task(task_dependent);
var start_x = dependent._start.diff(me.start, 'hours')/me.opts.step
* me.opts.column_width + me.opts.label_width
+ (dependent._end.diff(dependent._start, 'hours')/me.opts.step
* me.opts.column_width) / 2;
var start_y = me.opts.header_height + me.opts.bar.height
+ (me.opts.padding + me.opts.bar.height) * dependent._index;
var end_x = task._start.diff(me.start, 'hours')/me.opts.step
* me.opts.column_width + me.opts.label_width;
var end_y = me.opts.header_height + me.opts.bar.height/2
+ (me.opts.padding + me.opts.bar.height) * task._index;

var path = Snap.format("M {start_x} {start_y} V {offset} a {curve} {curve} " +
"0 0 0 {curve} {curve}" +
"L {end_x} {end_y} m -5 -5 l 5 5 l -5 5",
{
start_x: start_x,
start_y: start_y + me.opts.padding,
end_x: end_x - me.opts.padding,
end_y: end_y + me.opts.padding,
offset: end_y - me.opts.arrow.curve + me.opts.padding,
curve: me.opts.arrow.curve
});
me.groups.arrow.add(me.canvas.path(path));
var dependent = me.get_task(task_dependent.trim());
if(!dependent) return;
var arrow = new Arrow({
gantt: me,
from_task: me._bars[dependent._index],
to_task: me._bars[task._index]
});
me.groups.arrow.add(arrow.element);
me._arrows.push(arrow);
}); });
} }
}); });
}, },
get_task: function (name) {
get_task: function (id) {
var result = null; var result = null;
this.tasks.forEach(function (task) { this.tasks.forEach(function (task) {
if (task.name === name){
if (task.id === id){
result = task; result = task;
} }
}); });
@@ -435,15 +428,10 @@ var Gantt = Class.extend({
make_bars: function () { make_bars: function () {
var me = this; var me = this;


var bar_position_x,
bar_position_y = this.opts.header_height + me.opts.padding;

this.tasks.forEach(function (task, i) { this.tasks.forEach(function (task, i) {

var bar = new Bar({ var bar = new Bar({
canvas: me.canvas, canvas: me.canvas,
task: task, task: task,
details: me.groups.details,
gantt: { gantt: {
offset: me.opts.label_width, offset: me.opts.label_width,
unit_width: me.opts.column_width, unit_width: me.opts.column_width,
@@ -453,18 +441,21 @@ var Gantt = Class.extend({
padding: me.opts.padding, padding: me.opts.padding,
view_mode: me.view_mode view_mode: me.view_mode
}, },
color: {
bar: me.opts.bar.color,
progress: me.opts.bar.progress_color,
hover_bar: me.opts.bar.hover_color,
hover_progress: me.opts.bar.hover_progress_color
}
popover_group: me.groups.details
}); });

me._bars.push(bar); me._bars.push(bar);
me.groups.bar.add(bar.group); me.groups.bar.add(bar.group);
}); });
}, },
set_arrows_on_bars: function() {
var me = this;
this._bars.forEach(function(bar) {
bar.arrows = me._arrows.filter(function(arrow) {
if(arrow.from_task.task.id === bar.task.id || arrow.to_task.task.id === bar.task.id)
return arrow;
});
});
},
setup_events: function() { setup_events: function() {
var me = this; var me = this;
this._bars.forEach(function(bar) { this._bars.forEach(function(bar) {
@@ -479,7 +470,7 @@ var Gantt = Class.extend({
me.canvas.selectAll('.bar-wrapper').forEach(function(el) { me.canvas.selectAll('.bar-wrapper').forEach(function(el) {
el.removeClass('active'); el.removeClass('active');
}); });
})
});
} }
}); });


@@ -538,7 +529,6 @@ var Bar = Class.extend({
this.handle_group = this.canvas.group().addClass('handle-group').appendTo(this.group); this.handle_group = this.canvas.group().addClass('handle-group').appendTo(this.group);
}, },
prepare_plugins: function() { prepare_plugins: function() {
var me = this;
this.filters = {}; this.filters = {};
Snap.plugin(function (Snap, Element, Paper, global, Fragment) { Snap.plugin(function (Snap, Element, Paper, global, Fragment) {
Element.prototype.get = function (attr) { Element.prototype.get = function (attr) {
@@ -553,16 +543,6 @@ var Bar = Class.extend({
Element.prototype.getWidth = function () { Element.prototype.getWidth = function () {
return this.get("width"); return this.get("width");
}; };
Element.prototype.setStartDate = function(date) {
date = moment(date)
var x = me.gantt.offset + (date.diff(me.gantt.start, 'hours')/me.gantt.step)*me.gantt.unit_width;
return this.attr('x', x);
}
Element.prototype.setEndDate = function(date) {
date = moment(date)
var x = me.gantt.offset + (date.diff(me.gantt.start, 'hours')/me.gantt.step)*me.gantt.unit_width;
return this.attr('x', x);
}
}); });
}, },
draw: function () { draw: function () {
@@ -572,19 +552,18 @@ var Bar = Class.extend({
this.draw_resize_handles(); this.draw_resize_handles();
}, },
draw_bar: function() { draw_bar: function() {
this.canvas.rect(this.x, this.y,
this.width, this.height,
this.corner_radius, this.corner_radius)
this.bar = this.canvas.rect(this.x, this.y,
this.width, this.height,
this.corner_radius, this.corner_radius)
.addClass("bar") .addClass("bar")
.appendTo(this.bar_group); .appendTo(this.bar_group);
}, },
draw_progress_bar: function() { draw_progress_bar: function() {
this.canvas.rect(this.x, this.y,
this.progress_width, this.height,
this.corner_radius, this.corner_radius)
.attr("fill", this.color.progress)
this.bar_progress = this.canvas.rect(this.x, this.y,
this.progress_width, this.height,
this.corner_radius, this.corner_radius)
.addClass("bar-progress") .addClass("bar-progress")
.appendTo(this.bar_group)
.appendTo(this.bar_group);
}, },
draw_label: function() { draw_label: function() {
this.canvas.text(this.x + this.width/2, this.canvas.text(this.x + this.width/2,
@@ -623,11 +602,11 @@ var Bar = Class.extend({


this.group.mouseover(function (e, x, y) { this.group.mouseover(function (e, x, y) {
var details_box = me.canvas.group(); var details_box = me.canvas.group();
me.details.clear();
me.popover_group.clear();
var pos = me.get_details_position(me.group); var pos = me.get_details_position(me.group);


details_box.attr({ transform: "translate(" + pos.x +"," + pos.y + ")" }) details_box.attr({ transform: "translate(" + pos.x +"," + pos.y + ")" })
.appendTo(me.details);
.appendTo(me.popover_group);


var line1_text = me.task.name + ": " + var line1_text = me.task.name + ": " +
me.task._start.format("MMM D") + " - " + me.task._start.format("MMM D") + " - " +
@@ -668,7 +647,7 @@ var Bar = Class.extend({
dy: 90, dy: 90,
"fill": "#757575" "fill": "#757575"
}).appendTo(details_box); }).appendTo(details_box);
me.details.attr({
me.popover_group.attr({
x: x, x: x,
y: y, y: y,
"font-size": 14 "font-size": 14
@@ -726,7 +705,7 @@ var Bar = Class.extend({
return { return {
left: me.handle_group.select('.handle.left'), left: me.handle_group.select('.handle.left'),
right: me.handle_group.select('.handle.right') right: me.handle_group.select('.handle.right')
}
};
}, },
bind_drag: function() { bind_drag: function() {
var me = this; var me = this;
@@ -776,9 +755,6 @@ var Bar = Class.extend({
for (var i = 0; i < modes.length; i++) { for (var i = 0; i < modes.length; i++) {
if(me.gantt.view_mode === modes[i]) return true; if(me.gantt.view_mode === modes[i]) return true;
} }
// modes.forEach(function(mode) {
// if(me.gantt.view_mode === mode) return true;
// })
return false; return false;
} }
}, },
@@ -786,9 +762,10 @@ var Bar = Class.extend({
var bar = this.group.select('.bar'); var bar = this.group.select('.bar');
if(x) this.update_attr(bar, "x", x); if(x) this.update_attr(bar, "x", x);
if(width) this.update_attr(bar, "width", width); if(width) this.update_attr(bar, "width", width);
this.update_label_position(this);
this.update_handle_position(this);
this.update_progressbar_position(this);
this.update_label_position();
this.update_handle_position();
this.update_progressbar_position();
this.update_arrow_position();
}, },
click: function(callback) { click: function(callback) {
var me = this; var me = this;
@@ -825,7 +802,6 @@ var Bar = Class.extend({
setTimeout(function() { me.action_completed = false; }, 2000); setTimeout(function() { me.action_completed = false; }, 2000);
}, },
compute_date: function(x) { compute_date: function(x) {
var pos = x - this.gantt.offset;
var shift = (x - this.compute_x())/this.gantt.unit_width; var shift = (x - this.compute_x())/this.gantt.unit_width;
var date = this.task._start.clone().add(this.gantt.step*shift, 'hours'); var date = this.task._start.clone().add(this.gantt.step*shift, 'hours');
return date; return date;
@@ -850,34 +826,35 @@ var Bar = Class.extend({
return bar_progress.getWidth() / bar.getWidth() * 100; return bar_progress.getWidth() / bar.getWidth() * 100;
}, },
compute_x: function() { compute_x: function() {
var x = this.gantt.offset
+ (this.task._start.diff(this.gantt.start, 'hours')/this.gantt.step
* this.gantt.unit_width);
var x = this.gantt.offset +
(this.task._start.diff(this.gantt.start, 'hours')/this.gantt.step *
this.gantt.unit_width);
if(this.gantt.view_mode === 'Month') { if(this.gantt.view_mode === 'Month') {
x = this.gantt.offset
+ this.task._start.diff(this.gantt.start, 'days') * this.gantt.unit_width/30
x = this.gantt.offset +
this.task._start.diff(this.gantt.start, 'days') *
this.gantt.unit_width/30;
} }
return x; return x;
}, },
compute_y: function() { compute_y: function() {
return this.gantt.header_height + this.gantt.padding
+ this.task._index * (this.height + this.gantt.padding)
return this.gantt.header_height + this.gantt.padding +
this.task._index * (this.height + this.gantt.padding);
}, },
get_snap_position: function(me, bar, dx) { get_snap_position: function(me, bar, dx) {
var odx = dx, rem, position, scale;
var odx = dx, rem, position;


if (me.gantt.view_mode === 'Week') { if (me.gantt.view_mode === 'Week') {
rem = dx % (me.gantt.unit_width/7); rem = dx % (me.gantt.unit_width/7);
position = odx - rem + position = odx - rem +
((rem < me.gantt.unit_width/7) ? 0 : me.gantt.unit_width/7);
((rem < me.gantt.unit_width/14) ? 0 : me.gantt.unit_width/7);
} else if (me.gantt.view_mode === 'Month') { } else if (me.gantt.view_mode === 'Month') {
rem = dx % (me.gantt.unit_width/30); rem = dx % (me.gantt.unit_width/30);
position = odx - rem + position = odx - rem +
((rem < me.gantt.unit_width/30) ? 0 : me.gantt.unit_width/30);
((rem < me.gantt.unit_width/60) ? 0 : me.gantt.unit_width/30);
} else { } else {
rem = dx % me.gantt.unit_width; rem = dx % me.gantt.unit_width;
position = odx - rem + position = odx - rem +
((rem < me.gantt.unit_width) ? 0 : me.gantt.unit_width);
((rem < me.gantt.unit_width/2) ? 0 : me.gantt.unit_width);
} }
return position; return position;
}, },
@@ -888,13 +865,15 @@ var Bar = Class.extend({
} }
return element; return element;
}, },
update_progressbar_position: function(me) {
update_progressbar_position: function() {
var me = this;
var bar = me.group.select('.bar'); var bar = me.group.select('.bar');
var bar_progress = me.group.select('.bar-progress'); var bar_progress = me.group.select('.bar-progress');
bar_progress.attr('x', bar.getX()); bar_progress.attr('x', bar.getX());
bar_progress.attr('width', bar.getWidth() * (me.task.progress/100)); bar_progress.attr('width', bar.getWidth() * (me.task.progress/100));
}, },
update_label_position: function(me) {
update_label_position: function() {
var me = this;
var bar = me.group.select(".bar"); var bar = me.group.select(".bar");
var label = me.group.select('.bar-label'); var label = me.group.select('.bar-label');
if(label.getBBox().width > bar.getWidth()){ if(label.getBBox().width > bar.getWidth()){
@@ -903,7 +882,8 @@ var Bar = Class.extend({
label.removeClass('big').attr('x', bar.getX() + bar.getWidth()/2); label.removeClass('big').attr('x', bar.getX() + bar.getWidth()/2);
} }
}, },
update_handle_position: function(me) {
update_handle_position: function() {
var me = this;
var bar = me.group.select(".bar"); var bar = me.group.select(".bar");
me.handle_group.select(".handle.left").attr({ me.handle_group.select(".handle.left").attr({
"x": bar.getX() + 1, "x": bar.getX() + 1,
@@ -912,9 +892,111 @@ var Bar = Class.extend({
"x": bar.getX() + bar.getWidth() - 9, "x": bar.getX() + bar.getWidth() - 9,
}); });
}, },
update_arrow_position: function() {
this.arrows.forEach(function(arrow) {
arrow.update();
});
},
unselect_all: function() { unselect_all: function() {
this.canvas.selectAll('.bar-wrapper').forEach(function(el) { this.canvas.selectAll('.bar-wrapper').forEach(function(el) {
el.removeClass('active'); el.removeClass('active');
}); });
} }
}); });

/*
Class: Arrow
from_task ---> to_task

Opts:
gantt (Gantt object)
from_task (Bar object)
to_task (Bar object)
*/

var Arrow = Class.extend({
init: function (opts) {
for(var key in opts) {
if(opts.hasOwnProperty(key))
this[key] = opts[key];
}
this.prepare();
this.draw();
},
prepare: function() {
var gantt = this.gantt,
from_task = this.from_task,
to_task = this.to_task;

this.start_x =from_task.bar.getX() + from_task.bar.getWidth()/2;

while(to_task.bar.getX() < this.start_x + gantt.opts.padding &&
this.start_x > from_task.bar.getX() + gantt.opts.padding)
{
this.start_x -= 10;
}

this.start_y = gantt.opts.header_height + gantt.opts.bar.height +
(gantt.opts.padding + gantt.opts.bar.height) * from_task.task._index +
gantt.opts.padding;

this.end_x = to_task.bar.getX() - gantt.opts.padding/2;
this.end_y = gantt.opts.header_height + gantt.opts.bar.height/2 +
(gantt.opts.padding + gantt.opts.bar.height) * to_task.task._index +
gantt.opts.padding;

var from_is_below_to = (from_task.task._index > to_task.task._index);
this.curve = gantt.opts.arrow.curve;
this.clockwise = from_is_below_to ? 1 : 0;
this.curve_y = from_is_below_to ? -this.curve : this.curve;
this.offset = from_is_below_to ?
this.end_y + gantt.opts.arrow.curve:
this.end_y - gantt.opts.arrow.curve;

this.path =
Snap.format("M {start_x} {start_y} V {offset} " +
"a {curve} {curve} 0 0 {clockwise} {curve} {curve_y} " +
"L {end_x} {end_y} m -5 -5 l 5 5 l -5 5",
{
start_x: this.start_x,
start_y: this.start_y,
end_x: this.end_x,
end_y: this.end_y,
offset: this.offset,
curve: this.curve,
clockwise: this.clockwise,
curve_y: this.curve_y
});

if(to_task.bar.getX() < from_task.bar.getX() + gantt.opts.padding) {
this.path =
Snap.format("M {start_x} {start_y} v {down_1} " +
"a {curve} {curve} 0 0 1 -{curve} {curve} H {left} " +
"a {curve} {curve} 0 0 {clockwise} -{curve} {curve_y} V {down_2} " +
"a {curve} {curve} 0 0 {clockwise} {curve} {curve_y} " +
"L {end_x} {end_y} m -5 -5 l 5 5 l -5 5",
{
start_x: this.start_x,
start_y: this.start_y,
end_x: this.end_x,
end_y: this.end_y,
down_1: this.gantt.opts.padding/2 - this.curve,
down_2: to_task.bar.getY() + to_task.bar.get('height')/2 - this.curve_y,
left: to_task.bar.getX() - gantt.opts.padding,
offset: this.offset,
curve: this.curve,
clockwise: this.clockwise,
curve_y: this.curve_y
});
}
},
draw: function() {
this.element = this.gantt.canvas.path(this.path)
.attr("data-from", this.from_task.task.id)
.attr("data-to", this.to_task.task.id);
},
update: function() {
this.prepare();
this.element.attr('d', this.path);
}
});

+ 4
- 1
frappe/public/less/gantt.less Vedi File

@@ -34,7 +34,7 @@


#arrow { #arrow {
fill: none; fill: none;
stroke: #333;
stroke: #666;
stroke-width: 1.4; stroke-width: 1.4;
} }


@@ -44,6 +44,9 @@
stroke-width: 0; stroke-width: 0;
transition: stroke-width .3s ease; transition: stroke-width .3s ease;
} }
.bar-progress {
fill: #a3a3ff;
}
.bar-label { .bar-label {
fill: #fff; fill: #fff;
dominant-baseline: central; dominant-baseline: central;


Caricamento…
Annulla
Salva