mirror of
https://github.com/EGroupware/egroupware.git
synced 2025-01-21 05:19:07 +01:00
* Additional columns for Gantt chart
This commit is contained in:
parent
44b6f5ff78
commit
35fc079c7f
@ -57,6 +57,14 @@ var et2_gantt = et2_inputWidget.extend([et2_IResizeable,et2_IInput],
|
|||||||
"default": "minute",
|
"default": "minute",
|
||||||
"description": "The unit for task duration values. One of minute, hour, week, year."
|
"description": "The unit for task duration values. One of minute, hour, week, year."
|
||||||
},
|
},
|
||||||
|
columns: {
|
||||||
|
name: "Columns",
|
||||||
|
type: "any",
|
||||||
|
default: [
|
||||||
|
{name: "text", label: egw.lang('Title'), tree: true, width: '*'}
|
||||||
|
],
|
||||||
|
description: "Columns for the grid portion of the gantt chart. An array of objects with keys name, label, etc. See http://docs.dhtmlx.com/gantt/api__gantt_columns_config.html"
|
||||||
|
},
|
||||||
value: {type: 'any'},
|
value: {type: 'any'},
|
||||||
needed: {ignore: true},
|
needed: {ignore: true},
|
||||||
onfocus: {ignore: true},
|
onfocus: {ignore: true},
|
||||||
@ -76,6 +84,7 @@ var et2_gantt = et2_inputWidget.extend([et2_IResizeable,et2_IInput],
|
|||||||
show_progress: true,
|
show_progress: true,
|
||||||
order_branch: false,
|
order_branch: false,
|
||||||
min_column_width: 30,
|
min_column_width: 30,
|
||||||
|
min_grid_column_width: 30,
|
||||||
task_height: 25,
|
task_height: 25,
|
||||||
fit_tasks: true,
|
fit_tasks: true,
|
||||||
autosize: '',
|
autosize: '',
|
||||||
@ -177,6 +186,10 @@ var et2_gantt = et2_inputWidget.extend([et2_IResizeable,et2_IInput],
|
|||||||
{
|
{
|
||||||
this.set_value(this.options.value);
|
this.set_value(this.options.value);
|
||||||
}
|
}
|
||||||
|
if(this.options.columns)
|
||||||
|
{
|
||||||
|
this.set_columns(this.options.columns);
|
||||||
|
}
|
||||||
|
|
||||||
// Update start & end dates with chart values for consistency
|
// Update start & end dates with chart values for consistency
|
||||||
if(start_date && this.options.value.data && this.options.value.data.length)
|
if(start_date && this.options.value.data && this.options.value.data.length)
|
||||||
@ -244,6 +257,82 @@ var et2_gantt = et2_inputWidget.extend([et2_IResizeable,et2_IInput],
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the columns for the grid (left) portion
|
||||||
|
*
|
||||||
|
* @param {Object[]} columns - A list of columns
|
||||||
|
* @param {string} columns[].name The column's ID
|
||||||
|
* @param {string} columns[].label The title for the column header
|
||||||
|
* @param {string} columns[].width Width of the column
|
||||||
|
*
|
||||||
|
* @see http://docs.dhtmlx.com/gantt/api__gantt_columns_config.html for full options
|
||||||
|
*/
|
||||||
|
set_columns: function(columns)
|
||||||
|
{
|
||||||
|
this.gantt_config.columns = columns;
|
||||||
|
|
||||||
|
var displayed_columns = [];
|
||||||
|
var gantt_widget = this;
|
||||||
|
|
||||||
|
// Make sure there's enough room for them all
|
||||||
|
var width = 0;
|
||||||
|
for(var col in columns)
|
||||||
|
{
|
||||||
|
// Preserve original width, gantt will resize column to fit
|
||||||
|
if(!columns[col]._width)
|
||||||
|
{
|
||||||
|
columns[col]._width = columns[col].width;
|
||||||
|
}
|
||||||
|
columns[col].width = columns[col]._width;
|
||||||
|
if(!columns[col].template)
|
||||||
|
{
|
||||||
|
// Use an et2 widget to render the column value, if one was provided
|
||||||
|
// otherwise, just display the value
|
||||||
|
columns[col].template = function(task) {
|
||||||
|
var value = typeof task[this.name] == 'undefined'||task[this.name] == null ? '':task[this.name];
|
||||||
|
|
||||||
|
// No value, but there's a project title. Try reading the project value.
|
||||||
|
if(!value && this.name.indexOf('pe_') == 0 && task.pm_title)
|
||||||
|
{
|
||||||
|
var pm_col = this.name.replace('pe_','pm_');
|
||||||
|
value = typeof task[pm_col] == 'undefined' || task[pm_col] == null ? '':task[pm_col];
|
||||||
|
}
|
||||||
|
if(this.widget && typeof this.widget == 'string')
|
||||||
|
{
|
||||||
|
this.widget = et2_createWidget(this.widget, {readonly:true}, gantt_widget);
|
||||||
|
}
|
||||||
|
if (this.widget)
|
||||||
|
{
|
||||||
|
this.widget.set_value(value);
|
||||||
|
value = $j(this.widget.getDOMNode()).html();
|
||||||
|
}
|
||||||
|
return '<div class="gantt_column_'+this.name+'">' + value + '</div>';
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actual hiding is available in the pro version of gantt chart
|
||||||
|
if(!columns[col].hide)
|
||||||
|
{
|
||||||
|
displayed_columns.push(columns[col]);
|
||||||
|
width += parseInt(columns[col]._width) || 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
// Add in add column
|
||||||
|
displayed_columns.push({name: 'add', width: 26});
|
||||||
|
width += 26;
|
||||||
|
|
||||||
|
if(width != this.gantt_config.grid_width || typeof this.gantt_config.grid_width == 'undefined')
|
||||||
|
{
|
||||||
|
this.gantt_config.grid_width = Math.min(Math.max(200, width), this.htmlNode.width());
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.gantt == null) return;
|
||||||
|
this.gantt.config.columns = displayed_columns;
|
||||||
|
this.gantt.config.grid_width = this.gantt_config.grid_width;
|
||||||
|
this.gantt.render();
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the data to be displayed in the gantt chart.
|
* Sets the data to be displayed in the gantt chart.
|
||||||
*
|
*
|
||||||
@ -700,11 +789,9 @@ var et2_gantt = et2_inputWidget.extend([et2_IResizeable,et2_IInput],
|
|||||||
// Some crazy stuff make sure timing is OK to scroll after re-render
|
// Some crazy stuff make sure timing is OK to scroll after re-render
|
||||||
// TODO: Make this more consistently go to where you click
|
// TODO: Make this more consistently go to where you click
|
||||||
var id = gantt_widget.gantt.attachEvent("onGanttRender", function() {
|
var id = gantt_widget.gantt.attachEvent("onGanttRender", function() {
|
||||||
console.log('Render');
|
|
||||||
gantt_widget.gantt.detachEvent(id);
|
gantt_widget.gantt.detachEvent(id);
|
||||||
gantt_widget.gantt.scrollTo(parseInt($j('.gantt_task_scale',gantt_widget.gantt_node).width() *current_position),0);
|
gantt_widget.gantt.scrollTo(parseInt($j('.gantt_task_scale',gantt_widget.gantt_node).width() *current_position),0);
|
||||||
window.setTimeout(function() {
|
window.setTimeout(function() {
|
||||||
console.log("Scroll to");
|
|
||||||
gantt_widget.gantt.scrollTo(parseInt($j('.gantt_task_scale',gantt_widget.gantt_node).width() *current_position),0);
|
gantt_widget.gantt.scrollTo(parseInt($j('.gantt_task_scale',gantt_widget.gantt_node).width() *current_position),0);
|
||||||
},100);
|
},100);
|
||||||
});
|
});
|
||||||
@ -729,6 +816,12 @@ var et2_gantt = et2_inputWidget.extend([et2_IResizeable,et2_IInput],
|
|||||||
*/
|
*/
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.gantt.attachEvent("onGridHeaderClick", function(column_name, e) {
|
||||||
|
if(column_name === "add")
|
||||||
|
{
|
||||||
|
gantt_widget._column_selection(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
this.gantt.attachEvent("onContextMenu",function(taskId, linkId, e) {
|
this.gantt.attachEvent("onContextMenu",function(taskId, linkId, e) {
|
||||||
if(gantt_widget.options.readonly) return false;
|
if(gantt_widget.options.readonly) return false;
|
||||||
if(taskId)
|
if(taskId)
|
||||||
@ -901,6 +994,91 @@ var et2_gantt = et2_inputWidget.extend([et2_IResizeable,et2_IInput],
|
|||||||
}, this, et2_inputWidget);
|
}, this, et2_inputWidget);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start UI for selecting among defined columns
|
||||||
|
*/
|
||||||
|
_column_selection: function(e)
|
||||||
|
{
|
||||||
|
var self = this;
|
||||||
|
var columns = [];
|
||||||
|
var columns_selected = [];
|
||||||
|
for (var i = 0; i < this.gantt_config.columns.length; i++)
|
||||||
|
{
|
||||||
|
var col = this.gantt_config.columns[i];
|
||||||
|
columns.push({
|
||||||
|
value: col.name,
|
||||||
|
label: col.label
|
||||||
|
})
|
||||||
|
if(!col.hide)
|
||||||
|
{
|
||||||
|
columns_selected.push(col.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build the popup
|
||||||
|
if(!this.selectPopup)
|
||||||
|
{
|
||||||
|
var select = et2_createWidget("select", {
|
||||||
|
multiple: true,
|
||||||
|
rows: 8,
|
||||||
|
empty_label:this.egw().lang("select columns"),
|
||||||
|
selected_first: false
|
||||||
|
}, this);
|
||||||
|
select.set_select_options(columns);
|
||||||
|
select.set_value(columns_selected);
|
||||||
|
|
||||||
|
var okButton = et2_createWidget("buttononly", {}, this);
|
||||||
|
okButton.set_label(this.egw().lang("ok"));
|
||||||
|
okButton.onclick = function() {
|
||||||
|
// Update columns
|
||||||
|
var value = select.getValue() || [];
|
||||||
|
for (var i = 0; i < columns.length; i++)
|
||||||
|
{
|
||||||
|
self.gantt_config.columns[i].hide = value.indexOf(columns[i].value) < 0 ;
|
||||||
|
}
|
||||||
|
self.set_columns(self.gantt_config.columns);
|
||||||
|
|
||||||
|
// Update Implicit preference
|
||||||
|
this.egw().set_preference(self.getInstanceManager().app, 'gantt_columns_' + self.id, value);
|
||||||
|
|
||||||
|
// Hide popup
|
||||||
|
self.selectPopup.toggle();
|
||||||
|
self.selectPopup.remove();
|
||||||
|
self.selectPopup = null;
|
||||||
|
$j('body').off('click.gantt');
|
||||||
|
};
|
||||||
|
|
||||||
|
var cancelButton = et2_createWidget("buttononly", {}, this);
|
||||||
|
cancelButton.set_label(this.egw().lang("cancel"));
|
||||||
|
cancelButton.onclick = function() {
|
||||||
|
self.selectPopup.toggle();
|
||||||
|
self.selectPopup.remove();
|
||||||
|
self.selectPopup = null;
|
||||||
|
$j('body').off('click.gantt');
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create and add popup
|
||||||
|
this.selectPopup = jQuery(document.createElement("div"))
|
||||||
|
.addClass("colselection ui-dialog ui-widget-content")
|
||||||
|
.append(select.getDOMNode())
|
||||||
|
.append(okButton.getDOMNode())
|
||||||
|
.append(cancelButton.getDOMNode())
|
||||||
|
.appendTo(this.getInstanceManager().DOMContainer);
|
||||||
|
// Bind so if you click elsewhere, it closes
|
||||||
|
window.setTimeout(function() {$j(document).one('mouseup.gantt', function(e){
|
||||||
|
if(!self.selectPopup.is(e.target) && self.selectPopup.has(e.target).length === 0)
|
||||||
|
{
|
||||||
|
cancelButton.onclick();
|
||||||
|
}
|
||||||
|
});},1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.selectPopup.toggle();
|
||||||
|
}
|
||||||
|
this.selectPopup.position({my:'right top', at:'right bottom', of: e.target});
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Link the actions to the DOM nodes / widget bits.
|
* Link the actions to the DOM nodes / widget bits.
|
||||||
* Overridden to make the gantt chart a container, so it can't be selected.
|
* Overridden to make the gantt chart a container, so it can't be selected.
|
||||||
|
@ -1623,6 +1623,28 @@ div.et2_toolbar_activeList h.ui-accordion-header {
|
|||||||
{
|
{
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
}
|
}
|
||||||
|
/* Style the gantt grid (left side) allowing 2 lines */
|
||||||
|
.et2_gantt .gantt_grid_scale :not(.gantt_grid_head_add) {
|
||||||
|
white-space: normal;
|
||||||
|
line-height: 16px;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
/* Column selector */
|
||||||
|
.et2_gantt .gantt_grid_scale .gantt_grid_head_add {
|
||||||
|
background-image: url(images/selectcols.png);
|
||||||
|
padding: 0px;
|
||||||
|
margin: 0px;
|
||||||
|
}
|
||||||
|
.et2_gantt .gantt_grid_data .gantt_add {
|
||||||
|
display: none;
|
||||||
|
padding: 0px;
|
||||||
|
margin: 0px;
|
||||||
|
}
|
||||||
|
/* Display inline, since there's only 1 line*/
|
||||||
|
.et2_gantt .gantt_grid_data li {
|
||||||
|
display: inline-block;
|
||||||
|
padding-right: 0.5ex;
|
||||||
|
}
|
||||||
.et2_gantt .gantt_task_progress
|
.et2_gantt .gantt_task_progress
|
||||||
{
|
{
|
||||||
text-align: left;
|
text-align: left;
|
||||||
|
Loading…
Reference in New Issue
Block a user