← Back to team overview

openerp-dev-web team mailing list archive

lp:~openerp-dev/openobject-client-web/trunk-proto61-dhtmlx-gantt-cpa into lp:~openerp-dev/openobject-client-web/trunk-proto61

 

Chirag Patel (OpenERP) has proposed merging lp:~openerp-dev/openobject-client-web/trunk-proto61-dhtmlx-gantt-cpa into lp:~openerp-dev/openobject-client-web/trunk-proto61.

Requested reviews:
  OpenERP R&D Team (openerp-dev)

For more details, see:
https://code.launchpad.net/~openerp-dev/openobject-client-web/trunk-proto61-dhtmlx-gantt-cpa/+merge/57837

Hello,

Gantt view:-

Implemented
-----------
* use dataset (removed logic from py)
* Removed fixed day_length 8 hours
* use do_search() for search

Question
--------
* Sidebar checkbox required or not(because we use search view)?
-- 
https://code.launchpad.net/~openerp-dev/openobject-client-web/trunk-proto61-dhtmlx-gantt-cpa/+merge/57837
Your team OpenERP R&D Team is requested to review the proposed merge of lp:~openerp-dev/openobject-client-web/trunk-proto61-dhtmlx-gantt-cpa into lp:~openerp-dev/openobject-client-web/trunk-proto61.
=== modified file 'addons/base_gantt/__openerp__.py'
--- addons/base_gantt/__openerp__.py	2011-04-13 14:20:01 +0000
+++ addons/base_gantt/__openerp__.py	2011-04-15 09:57:31 +0000
@@ -3,8 +3,8 @@
     "version": "2.0",
     "depends": ['base'],
     "js": [
-        'static/lib/dhtmlxGantt/codebase/dhtmlxcommon.js',
-        'static/lib/dhtmlxGantt/codebase/dhtmlxgantt.js',
+        'static/lib/dhtmlxGantt/sources/dhtmlxcommon.js',
+        'static/lib/dhtmlxGantt/sources/dhtmlxgantt.js',
         'static/src/js/gantt.js'
     ],
     "css": ['static/lib/dhtmlxGantt/codebase/dhtmlxgantt.css'],

=== modified file 'addons/base_gantt/controllers/main.py'
--- addons/base_gantt/controllers/main.py	2011-04-07 12:13:31 +0000
+++ addons/base_gantt/controllers/main.py	2011-04-15 09:57:31 +0000
@@ -1,184 +1,24 @@
-import glob, os
-from xml.etree import ElementTree
-import math
-import simplejson
 import openerpweb
-import time
-import datetime
-from base.controllers.main import Xml2Json
-   
-
-COLOR_PALETTE = ['#f57900', '#cc0000', '#d400a8', '#75507b', '#3465a4', '#73d216', '#c17d11', '#edd400',
-                 '#fcaf3e', '#ef2929', '#ff00c9', '#ad7fa8', '#729fcf', '#8ae234', '#e9b96e', '#fce94f',
-                 '#ff8e00', '#ff0000', '#b0008c', '#9000ff', '#0078ff', '#00ff00', '#e6ff00', '#ffff00',
-                 '#905000', '#9b0000', '#840067', '#510090', '#0000c9', '#009b00', '#9abe00', '#ffc900', ]
-
-_colorline = ['#%02x%02x%02x' % (25 + ((r + 10) % 11) * 23, 5 + ((g + 1) % 11) * 20, 25 + ((b + 4) % 11) * 23) for r in range(11) for g in range(11) for b in range(11) ]
-
-def choice_colors(n):
-        if n > len(COLOR_PALETTE):
-            return _colorline[0:-1:len(_colorline) / (n + 1)]
-        elif n:
-            return COLOR_PALETTE[:n]
-        return []
- 
-class GanttView(openerpweb.Controller):
+from base.controllers.main import View
+
+class GanttView(View):
     _cp_path = "/base_gantt/ganttview"
    
-    date_start = None
-    date_delay = None
-    date_stop = None
-    color_field = None
-    
-    day_length = 8
-    fields = {}
-    events = []
-    calendar_fields = {}
-    ids = []
     model = ''
     domain = []
     context = {}
-    event_res = []
-    colors = {}
-    color_values = []
  
     @openerpweb.jsonrequest
     def load(self, req, model, view_id):
-        m = req.session.model(model)
-        r = m.fields_view_get(view_id, 'gantt')
-        r["arch"] = Xml2Json.convert_to_structure(r["arch"])
-        return {'fields_view':r}
-    
-    @openerpweb.jsonrequest
-    def get_events(self, req, **kw):
-
-        self.model = kw['model']
-        self.fields = kw['fields']
-        self.day_length = kw['day_length']
-        self.calendar_fields = kw['calendar_fields']
-        self.color_field = kw.get('color_field') or self.color_field or None
-        self.fields[self.color_field] = ""
-        self.colors = kw.get('colors') or {}
-        self.text = self.calendar_fields['text']['name']
-        
-        self.date_start = self.calendar_fields['date_start']['name']
-        self.fields[self.date_start] = ""
-        
-        if self.calendar_fields.get('date_stop'):
-            self.date_stop = self.calendar_fields['date_stop']['name']
-            self.fields[self.date_stop] = ""
-        if self.calendar_fields.get('date_delay'):
-            self.date_delay = self.calendar_fields['date_delay']['name']
-            self.fields[self.date_delay] = ""
-        if self.calendar_fields.get('parent'):
-            self.parent = self.calendar_fields['parent']['name']
-            self.fields[self.parent] = ""
-            
-        model = req.session.model(self.model)
-        event_ids = model.search([])
-        
-        return self.create_event(event_ids, model)
-        
-    def create_event(self, event_ids, model):
-    
-        self.events = model.read(event_ids, self.fields.keys())
-        result = []
-        for evt in self.events:
-            
-            event_res = {}
-            key = evt[self.color_field]
-            name = key
-            value = key
-            if isinstance(key, list): # M2O, XMLRPC returns List instead of Tuple
-                name = key[0]
-                value = key[-1]
-                evt[self.color_field] = key = key[-1]
-            if isinstance(key, tuple): # M2O
-                value, name = key
-                
-            self.colors[key] = (name, value, None)
-            
-            st_date = evt.get(self.date_start)
-            if st_date:
-                self.set_format(st_date)
-                if self.date_delay:
-                    duration = evt.get(self.date_delay)
-                else:
-                    en_date = evt.get(self.date_stop)
-                    
-                    duration = (time.mktime(time.strptime(en_date, self.format))-\
-                                time.mktime(time.strptime(st_date, self.format)))/ (60 * 60)
-
-                    if duration > self.day_length :
-                        d = math.floor(duration / 24)
-                        h = duration % 24
-                        duration = d * self.day_length + h
-                
-                event_res = {}
-                event_res['start_date'] = st_date
-                event_res['duration'] = duration
-                event_res['text'] = evt.get(self.text)
-                event_res['id'] = evt['id']
-                event_res['parent'] = evt.get(self.parent)
-                result.append(event_res)
-                
-        colors = choice_colors(len(self.colors))
-        for i, (key, value) in enumerate(self.colors.items()):
-            self.colors[key] = [value[0], value[1], colors[i]]
-            
-        return {'result': result,'sidebar': self.colors}
-
-    def set_format(self, st_date):
-        if len(st_date) == 10 :
-            self.format = "%Y-%m-%d"
-        else :
-            self.format = "%Y-%m-%d %H:%M:%S"
-        return
-            
-    def check_format(self, date):
-        if self.format == "%Y-%m-%d %H:%M:%S":
-            date = date + " 00:00:00"
-        return date    
-
-    @openerpweb.jsonrequest
-    def on_event_resize(self, req, **kw):
-        if self.date_delay:
-            key = self.date_delay
-            value = kw['duration']
-        else:
-            key = self.date_stop
-            value = self.check_format(kw['end_date'])
-        try:
-            model = req.session.model(self.model)
-            res = model.write(kw['id'], {key : value})
-        except Exception, e:
-            print "eeeeeeeeeeeeeeeeeeeeeeeeeee",e
-        return True
-    
-    @openerpweb.jsonrequest
-    def on_event_drag(self, req, **kw):
-        start_date = self.check_format(kw['start_date']) 
-        if self.date_delay:
-            key = self.date_delay
-            value = kw['duration']
-        else:
-            key = self.date_stop
-            value = self.check_format(kw['end_date'])
-        try:
-            model = req.session.model(self.model)
-            res = model.write(kw['id'], {self.date_start : start_date, key : value})
-        except Exception, e:
-            print "eeeeeeeeeeeeeeeeeeeeeeeeeee",e
-        return True
-    
+        fields_view = self.fields_view_get(req, model, view_id, 'gantt')
+        return {'fields_view':fields_view}
+        
     @openerpweb.jsonrequest
     def reload_gantt(self, req, **kw):
         
         model = req.session.model(kw['model'])
-        if (kw['domain']):
-            domain = (kw['color_field'],'in', kw['domain']) 
-            event_ids = model.search([domain])
-        else:
-            event_ids = model.search([])
-        return self.create_event(event_ids, model)
+        domain = kw['domain']
+        
+        event_ids = model.search(domain)
+        return event_ids
     
\ No newline at end of file

=== modified file 'addons/base_gantt/static/lib/dhtmlxGantt/sources/dhtmlxgantt.js'
--- addons/base_gantt/static/lib/dhtmlxGantt/sources/dhtmlxgantt.js	2011-04-07 12:13:31 +0000
+++ addons/base_gantt/static/lib/dhtmlxGantt/sources/dhtmlxgantt.js	2011-04-15 09:57:31 +0000
@@ -348,7 +348,7 @@
  *  @type: public
  *  @topic: 0
  */
-function GanttChart()
+function GanttChart(day_length)
 {
     this.Error = new GanttError();
     this.dhtmlXMLSenderObject = new dhtmlXMLSenderObject(this);
@@ -356,7 +356,7 @@
     //settings
     this.heightTaskItem = 12;
     this.dayInPixels = 24;
-    this.hoursInDay = 8;
+    this.hoursInDay = day_length;
     this._showTreePanel = true;
     this._showTooltip = true;
     this.isShowDescTask = false;

=== modified file 'addons/base_gantt/static/src/js/gantt.js'
--- addons/base_gantt/static/src/js/gantt.js	2011-04-13 14:20:01 +0000
+++ addons/base_gantt/static/src/js/gantt.js	2011-04-15 09:57:31 +0000
@@ -7,7 +7,8 @@
 openerp.base.views.add('gantt', 'openerp.base_gantt.GanttView');
 openerp.base_gantt.GanttView = openerp.base.Controller.extend({
 
-    init: function(view_manager, session, element_id, dataset, view_id) {
+init: function(view_manager, session, element_id, dataset, view_id) {
+    
         this._super(session, element_id);
         this.view_manager = view_manager;
         this.dataset = dataset;
@@ -16,82 +17,224 @@
         this.fields_views = {};
         this.widgets = {};
         this.widgets_counter = 0;
-        this.fields = {};
-        this.datarecord = {};
-        this.calendar_fields = {};
-    },
-    do_show: function () {
-        // TODO: re-trigger search
-        this.$element.show();
-    },
-    do_hide: function () {
-        this.$element.hide();
-    },
+        this.fields = this.dataset.fields ? this.dataset.fields: {};
+        this.ids = this.dataset.ids;
+		this.name = "";
+		this.date_start = "";
+		this.date_delay = "";
+		this.date_stop = "";
+		this.color_field = "";
+		this.day_lenth = 8;
+		this.colors = [];
+		this.color_values = [];
+		this.calendar_fields = {};
+		this.info_fields = [];
+		this.domain = this.dataset._domain ? this.dataset._domain: [];
+		this.context = {};
+		
+    },
+    
     start: function() {
+    
         this.rpc("/base_gantt/ganttview/load", {"model": this.model, "view_id": this.view_id}, this.on_loaded);
+        
     },
+    
     on_loaded: function(data) {
+    
+    	var self = this;
         this.fields_view = data.fields_view;
-        var self = this;
         this.name = this.fields_view.name || this.fields_view.arch.attrs.string;
         this.view_id = this.fields_view.view_id;
 
         this.date_start = this.fields_view.arch.attrs.date_start;
         this.date_delay = this.fields_view.arch.attrs.date_delay;
         this.date_stop = this.fields_view.arch.attrs.date_stop;
+
         this.color_field = this.fields_view.arch.attrs.color;
-
         this.day_length = this.fields_view.arch.attrs.day_length || 8;
         this.colors = this.fields_view.arch.attrs.colors;
-        this.fields = this.fields_view.fields;
 
         this.text = this.fields_view.arch.children[0].children[0].attrs.name;
         this.parent = this.fields_view.arch.children[0].attrs.link;
-
-        this.calendar_fields['parent'] = {'name': this.parent};
-        this.calendar_fields['date_start'] = {'name': this.date_start};
-        this.calendar_fields['text'] = {'name': this.text};
-        if(this.date_delay)
-            this.calendar_fields['date_delay'] = {'name': this.date_delay};
-        if(this.date_stop)
-            this.calendar_fields['date_stop'] = {'name': this.date_stop};
-
-        this.calendar_fields['day_length'] = this.day_length;
-        this.rpc('/base_gantt/ganttview/get_events',
-                {'model': this.model,
-                'fields': this.fields,
-                'color_field': this.color_field,
-                'day_length': this.day_length,
-                'calendar_fields': this.calendar_fields,
-                'colors': this.colors,
-                'info_fields': this.info_fields
-                },
-                function(res) {
-                    self.create_gantt();
-                    self.load_event(res);
-                })
+        
+        this.format = "%Y-%m-%d";
+        this.time = "00:00:00";
+        
+        self.create_gantt();
+		self.get_events(self.ids);	
+			
         this.$element.html(QWeb.render("GanttView", {"view": this, "fields_view": this.fields_view}));
 
     },
+    
+    create_gantt: function() {
+
+	    ganttChartControl = new GanttChart(this.day_length);
+	    ganttChartControl.setImagePath("/base_gantt/static/lib/dhtmlxGantt/codebase/imgs/");
+	    ganttChartControl.setEditable(true);
+	    ganttChartControl.showTreePanel(true);
+	    ganttChartControl.showContextMenu(true);
+	    ganttChartControl.showDescTask(true,'d,s-f');
+	    ganttChartControl.showDescProject(true,'n,d');
+        
+    },
+    
+    get_events: function(event_ids) {
+    
+    	var self = this;
+    	this.dataset.read_ids(event_ids, {}, function(result) {
+				self.load_event(result);
+		});
+		
+    },
+    
+    load_event: function(events) {
+    
+        var self = this;
+        var result = events;
+        var project_id = new Array();
+        var project = new Array();
+        var sidebar = {}
+        var j = -1;
+
+        for (i in result) {
+        	
+        	if (result[i][this.date_start] != false){
+	            var parent_id =  result[i][this.parent][0];
+	            var parent_name = result[i][this.parent][1];
+				
+	            if (jQuery.inArray(parent_id, project_id) == -1){
+	                if (parent_id == undefined){
+	                    parent_name = "";
+	                }
+	                j = j + 1;
+	                project[j] = new GanttProjectInfo(parent_id, parent_name, new Date(2011, 1, 1));
+	                project_id[j] = parent_id;
+	            }
+	            
+	            var id = result[i]['id'];
+	            var text = result[i][this.text];
+	            
+	            var start_date = this.convert_date_format(result[i][this.date_start]);
+				
+	            if (this.date_stop != undefined){
+	            	if (result[i][this.date_stop] != false){
+	            		var stop_date = this.convert_date_format(result[i][this.date_stop]);
+	            		var duration= self.hours_between(start_date, stop_date);
+	            	}
+	            	else{
+	            		var duration = 0;
+	            	}
+	            }
+	            else{
+	            	var duration = result[i][this.date_delay];
+	            }
+	            if (duration == false)
+	            	duration = 0
+	            		
+	            var task = new GanttTaskInfo(id, text, start_date, duration, 100, "");
+	            
+	            k = project_id.indexOf(parent_id);
+	            project[k].addTask(task);
+			}
+        }
+
+        for (i in project_id){
+            ganttChartControl.addProject(project[i]);
+        }  
+         
+        ganttChartControl.create("GanttDiv");
+        ganttChartControl.attachEvent("onTaskEndResize", function(task) {self.on_task_end_resize(task);})
+        ganttChartControl.attachEvent("onTaskEndDrag", function(task) {self.on_task_end_drag(task);})
+        
+    },
+    
+    hours_between: function(date1, date2) {
+    
+	    var ONE_DAY = 1000 * 60 * 60 * 24
+	    var date1_ms = date1.getTime()
+	    var date2_ms = date2.getTime()
+	    var difference_ms = Math.abs(date1_ms - date2_ms)
+	    
+	    d = Math.round(difference_ms / ONE_DAY)
+	    h = Math.round(difference_ms % ONE_DAY)
+	    
+	    return (d * this.day_length) + h;
+
+	},
+    
+    on_task_end_resize : function(task) {
+
+            var event_id = task.getId();
+            var data = {};
+            
+            if (this.date_stop != undefined){
+				data[this.date_stop] = this.reverse_convert_date_format(task.getFinishDate());
+            }else{
+            	data[this.date_delay] = task.getDuration();
+            }	
+       		this.dataset.write(event_id, data, function(result) {});
+       		
+    },
+    
+    on_task_end_drag : function(task) {
+                
+        	var event_id = task.getId();
+            var data = {};
+
+            data[this.date_start] = this.reverse_convert_date_format(task.getEST());
+            
+            if (this.date_stop != undefined){
+				data[this.date_stop] = this.reverse_convert_date_format(task.getFinishDate());
+            }else{
+            	data[this.date_delay] = task.getDuration();
+            }	
+            
+            this.dataset.write(event_id, data, function(result) {});
+            
+    },
+    
+    do_show: function () {
+    
+    	this.$element.show();
+    	
+    },
+    
+    do_hide: function () {
+    
+        this.$element.hide();
+        
+    },
+    
     convert_date_format: function(date) {
-        date=date+"";
-        if(typeof (date)!="string"||date.length===0){
+    	var self = this;
+    	
+  		if (date.length == 19){
+			self.format = "%Y-%m-%d %H:%M:%S";
+			self.time = date.split(' ')[1];
+		}
+		
+        date = date+"";
+        if(typeof (date) != "string" || date.length === 0){
             return null;
         }
         var iso=date.split("-");
-        if(iso.length===0){
+        if(iso.length === 0){
             return null;
         }
         var day = iso[2];
+        
         var iso_hours = day.split(' ');
 
         if (iso_hours.length > 1) {
             day = iso_hours[0];
-            var iso_date_hours = iso_hours[1].split(':')
+            var iso_date_hours = iso_hours[1].split(':');
             var new_date = new Date(iso[0], iso[1] - 1, day);
             new_date.setHours(iso_date_hours[0]);
             new_date.setMinutes(iso_date_hours[1]);
             new_date.setSeconds(iso_date_hours[2]);
+            
         }
         else {
             var new_date = new Date(iso[0], iso[1] - 1, day);
@@ -100,125 +243,52 @@
         new_date.setMonth(iso[1]-1);
         new_date.setDate(day);
         return new_date;
+        
     },
     
-    create_gantt: function() {
-        ganttChartControl = new GanttChart();
-        ganttChartControl.setImagePath("/base_gantt/static/lib/dhtmlxGantt/codebase/imgs/");
-        ganttChartControl.setEditable(true);
-        ganttChartControl.showTreePanel(true);
-        ganttChartControl.showContextMenu(true);
-        ganttChartControl.showDescTask(true,'d,s-f');
-        ganttChartControl.showDescProject(true,'n,d');
-    },   
-    load_event: function(res) {
-        var self = this   
-        var result = res.result;
-        var sidebar = res.sidebar;
-        var project_id = new Array();
-        var project = new Array();
-        var j = -1;
-        var self = this;
-        for (i in result) {
-        
-            var parent_id =  result[i]['parent'][0];
-            var parent_name = result[i]['parent'][1];
-            
-            if (jQuery.inArray(parent_id, project_id) == -1){
-                if (parent_id == undefined){
-                    parent_name = "";
-                }
-                j = j + 1;
-                project[j] = new GanttProjectInfo(parent_id, parent_name, new Date(2011, 1, 1));
-                project_id[j] = parent_id;
-            }
-            
-            var id = result[i]['id'];
-            var text = result[i]['text'];
-            var start_date = this.convert_date_format(result[i]['start_date']);
-            var duration = result[i]['duration'];
-            
-            var task = new GanttTaskInfo(id, text, start_date, duration, 100, "");
-            
-            k = project_id.indexOf(parent_id);
-            project[k].addTask(task);
+    reverse_convert_date_format: function(date) {
+    	var self = this;
 
-        }
-        for (i in project_id){
-            ganttChartControl.addProject(project[i]);
-        }   
-        ganttChartControl.create("GanttDiv");
-        ganttChartControl.attachEvent("onTaskEndResize", function(task) {self.on_task_end_resize(task);})
-        ganttChartControl.attachEvent("onTaskEndDrag", function(task) {self.on_task_end_drag(task);})
+    	if (self.format == "%Y-%m-%d %H:%M:%S")
+    	{
+    		return date.getFullYear()+'-'+(date.getMonth()+1)+'-'+date.getDate()+' '+self.time;
+    	}
+    	else
+    	{
+    		return date.getFullYear()+"-"+(date.getMonth()+1)+"-"+date.getDate();
+    	}
         
-        //Create Sidebar
-        if (jQuery('#cal-sidebar-option').length == 0){
-            jQuery('#gantt-sidebar').append(
-                jQuery('<table>',{'width':'100%','cellspacing': 0, 'cellpadding': 0, 'id':'cal-sidebar-option'})
-            )
-            for(s in sidebar) {
-                jQuery('#cal-sidebar-option').append(
-                    jQuery('<tr>').append(
-                        jQuery('<td>').append(
-                            jQuery('<div>')
-                            .append(
-                                jQuery('<input>',
-                                {
-                                    'type': 'checkbox', 
-                                    'id':sidebar[s][0],
-                                    'value':sidebar[s][0]
-                                }).bind('click',function(){
-                                    self.reload_gantt(self.color_field,self.model)
-                                }),
-                                sidebar[s][1]
-                            )
-                            .css('background-color',sidebar[s][sidebar[s].length-1])
-                        )
-                    )
-                )
-            }
-        }
     },
-    reload_gantt: function(color_field, model) {
-        var domain = [];
-        var self = this;
-        jQuery('input[type=checkbox]:checked','#cal-sidebar-option').each(function() {
-            domain.push(parseInt(jQuery(this).attr('id')))
-        });
+    
+    reload_gantt: function(domain) {
+   
+   		var self = this;
+   		
         this.rpc('/base_gantt/ganttview/reload_gantt',{
-            'domain':domain,
-            'color_field':color_field,
-            'model': model
-        },function(res) {
+            'domain': domain,
+            'model': self.model
+        },function(event_ids) {
             ganttChartControl.clearAll();
             jQuery("#GanttDiv").children().remove();
-            self.load_event(res);
+            self.get_events(event_ids);
         });
-    },
-    reverse_convert_date_format: function(date) {
-        return date.getFullYear()+"-"+(date.getMonth()+1)+"-"+date.getDate();
+        
     },
     
-    on_task_end_resize : function(task) {
-        this.rpc('/base_gantt/ganttview/on_event_resize',
-                {'id' : task.getId(),
-                'end_date' : this.reverse_convert_date_format(task.getFinishDate()),
-                'duration' : task.getDuration()
-                },
-                function(result) {
-                })
-    },
-    on_task_end_drag : function(task) {
-        this.rpc('/base_gantt/ganttview/on_event_drag',
-                {'id' : task.getId(),
-                'start_date' : this.reverse_convert_date_format(task.getEST()),
-                'end_date' : this.reverse_convert_date_format(task.getFinishDate()),
-                'duration' : task.getDuration()
-                },
-                function(result) {
-                })
+    do_search: function (domains, contexts, groupbys) {
+        var self = this;
+        return this.rpc('/base/session/eval_domain_and_context', {
+            domains: domains,
+            contexts: contexts,
+            group_by_seq: groupbys
+        }, function (results) {
+        
+            self.dataset.context = results.context;
+            self.dataset.domain = results.domain;
+            return self.reload_gantt(self.dataset.domain);
+        });
     }
-
+    
 });
 
 // here you may tweak globals object, if any, and play with on_* or do_* callbacks on them

=== modified file 'addons/base_gantt/static/src/xml/base_gantt.xml'
--- addons/base_gantt/static/src/xml/base_gantt.xml	2011-04-13 14:20:01 +0000
+++ addons/base_gantt/static/src/xml/base_gantt.xml	2011-04-15 09:57:31 +0000
@@ -3,12 +3,9 @@
     <h3 class="title"><t t-esc="view.fields_view.arch.attrs.string"/></h3>
     <table class="gantt-view" width="100%" height="100%" cellspacing="0" cellpadding="0">
       <tr>
-        <td style="width:85%">
+        <td>
           <div style="width:100%;height:300px;position:relative" id="GanttDiv"/>
         </td>
-        <td valign = "top">
-          <div id="gantt-sidebar"/>
-        </td>
       </tr>
     </table>
   </t>


Follow ups