diff --git a/web/package.json b/web/package.json
index 1025e28e..3a36bd56 100644
--- a/web/package.json
+++ b/web/package.json
@@ -4,6 +4,7 @@
     "axios-mock-adapter": "^1.14.1",
     "babel-core": "~6.24.0",
     "babel-loader": "~7.1.2",
+    "babel-plugin-transform-object-rest-spread": "^6.26.0",
     "babel-preset-airbnb": "^2.4.0",
     "babel-preset-es2015": "~6.24.0",
     "babel-preset-react": "~6.23.0",
@@ -65,7 +66,7 @@
     "dropzone": "^5.1.1",
     "eonasdan-bootstrap-datetimepicker": "^4.17.47",
     "exports-loader": "~0.6.4",
-    "flotr2": "^0.1.0",
+    "flotr2": "git+https://github.com/EnterpriseDB/Flotr2.git",
     "font-awesome": "^4.7.0",
     "hard-source-webpack-plugin": "^0.4.9",
     "immutability-helper": "^2.2.0",
diff --git a/web/pgadmin/browser/static/js/panel.js b/web/pgadmin/browser/static/js/panel.js
index 5238dcee..dbd2788f 100644
--- a/web/pgadmin/browser/static/js/panel.js
+++ b/web/pgadmin/browser/static/js/panel.js
@@ -165,7 +165,8 @@ define(
 
         if (eventName == 'panelClosed') {
           pgBrowser.save_current_layout(pgBrowser);
-          pgAdmin.Dashboard.toggleVisibility(false);
+          /* Pass the closed flag also */
+          pgAdmin.Dashboard.toggleVisibility(false, true);
         } else if (eventName == 'panelVisibilityChanged') {
           if (pgBrowser.tree) {
             pgBrowser.save_current_layout(pgBrowser);
@@ -174,8 +175,10 @@ define(
               pgAdmin.Dashboard.toggleVisibility(pgBrowser.panels.dashboard.panel.isVisible());
             }
             // Explicitly trigger tree selected event when we add the tab.
-            pgBrowser.Events.trigger('pgadmin-browser:tree:selected', selectedNode,
-              pgBrowser.tree.itemData(selectedNode), pgBrowser.Node);
+            if(selectedNode.length) {
+              pgBrowser.Events.trigger('pgadmin-browser:tree:selected', selectedNode,
+                pgBrowser.tree.itemData(selectedNode), pgBrowser.Node);
+            }
           }
         }
       },
diff --git a/web/pgadmin/dashboard/__init__.py b/web/pgadmin/dashboard/__init__.py
index ffd4a7bc..677dc18f 100644
--- a/web/pgadmin/dashboard/__init__.py
+++ b/web/pgadmin/dashboard/__init__.py
@@ -83,7 +83,7 @@ class DashboardModule(PgAdminModule):
             help_str=gettext('The number of seconds between graph samples.')
         )
 
-        self.session_stats_refresh = self.dashboard_preference.register(
+        self.tps_stats_refresh = self.dashboard_preference.register(
             'dashboards', 'tps_stats_refresh',
             gettext("Transaction throughput refresh rate"), 'integer',
             1, min_val=1, max_val=999999,
@@ -91,7 +91,7 @@ class DashboardModule(PgAdminModule):
             help_str=gettext('The number of seconds between graph samples.')
         )
 
-        self.session_stats_refresh = self.dashboard_preference.register(
+        self.ti_stats_refresh = self.dashboard_preference.register(
             'dashboards', 'ti_stats_refresh',
             gettext("Tuples in refresh rate"), 'integer',
             1, min_val=1, max_val=999999,
@@ -99,7 +99,7 @@ class DashboardModule(PgAdminModule):
             help_str=gettext('The number of seconds between graph samples.')
         )
 
-        self.session_stats_refresh = self.dashboard_preference.register(
+        self.to_stats_refresh = self.dashboard_preference.register(
             'dashboards', 'to_stats_refresh',
             gettext("Tuples out refresh rate"), 'integer',
             1, min_val=1, max_val=999999,
@@ -107,7 +107,7 @@ class DashboardModule(PgAdminModule):
             help_str=gettext('The number of seconds between graph samples.')
         )
 
-        self.session_stats_refresh = self.dashboard_preference.register(
+        self.bio_stats_refresh = self.dashboard_preference.register(
             'dashboards', 'bio_stats_refresh',
             gettext("Block I/O statistics refresh rate"), 'integer',
             1, min_val=1, max_val=999999,
@@ -131,6 +131,23 @@ class DashboardModule(PgAdminModule):
                              'will be displayed on dashboards.')
         )
 
+        self.graph_data_points = self.dashboard_preference.register(
+            'display', 'graph_data_points',
+            gettext("Show graph data points?"), 'boolean', False,
+            category_label=gettext('Display'),
+            help_str=gettext('If set to True, data points will be '
+                             'visible on graph lines.')
+        )
+
+        self.graph_mouse_track = self.dashboard_preference.register(
+            'display', 'graph_mouse_track',
+            gettext("Show mouse hover tooltip?"), 'boolean', False,
+            category_label=gettext('Display'),
+            help_str=gettext('If set to True, tooltip will appear on mouse '
+                             'hover on the graph lines giving the data point '
+                             'details')
+        )
+
     def get_exposed_url_endpoints(self):
         """
         Returns:
diff --git a/web/pgadmin/dashboard/static/js/charting.js b/web/pgadmin/dashboard/static/js/charting.js
new file mode 100644
index 00000000..1e275a5f
--- /dev/null
+++ b/web/pgadmin/dashboard/static/js/charting.js
@@ -0,0 +1,99 @@
+import Flotr from 'flotr2';
+
+export class Chart {
+  constructor(container, options) {
+    this.chartApi = Flotr;
+    /* Html Node where the graph goes */
+    this._container = container;
+    /* Graph library options */
+    this._options = {};
+    this._defaultOptions = {
+      legend: {
+        position: 'nw',
+        backgroundColor: '#D2E8FF',
+      },
+      lines: {
+        show: true,
+        lineWidth: 2,
+      },
+      shadowSize: 0,
+      resolution : 3,
+    };
+
+    this._dataset = null;
+    this._tooltipFormatter = null;
+    /* Just to store other data related to charts. Used nowhere here in the module */
+    this._otherData = {};
+    this.setOptions(options);
+  }
+
+  getContainer() {
+    return this._container;
+  }
+
+  getContainerDimensions() {
+    return {
+      height: this._container.clientHeight,
+      width: this._container.clientWidth,
+    };
+  }
+
+  getOptions() {
+    return this._options;
+  }
+
+  /* This should be changed if library changed */
+  setOptions(options, mergeOptions=true) {
+    /* If mergeOptions then merge the options, else replace existing options */
+    if(mergeOptions) {
+      this._options = {...this._defaultOptions, ...this._options, ...options};
+    } else {
+      this._options = {...this._defaultOptions, ...options};
+    }
+  }
+
+  removeOptions(optionKey) {
+    if(this._options[optionKey]) {
+      delete this._options[optionKey];
+    }
+  }
+
+  getOtherData(key) {
+    return this._otherData[key];
+  }
+
+  setOtherData(key, value) {
+    this._otherData[key] = value;
+  }
+
+  isVisible() {
+    let dim = this.getContainerDimensions();
+    return (dim.height > 0 && dim.width > 0);
+  }
+
+  isInPage() {
+    return (this._container === document.body) ? false : document.body.contains(this._container);
+  }
+
+  setTooltipFormatter(tooltipFormatter) {
+    let opt = this.getOptions();
+
+    this._tooltipFormatter = tooltipFormatter;
+
+    if(this._tooltipFormatter) {
+      this.setOptions({
+        mouse: {
+          ...opt.mouse,
+          trackFormatter: this._tooltipFormatter,
+        },
+      });
+    }
+  }
+
+  draw(dataset) {
+    this._dataset = dataset;
+    if(this._container) {
+      Flotr.draw(this._container, this._dataset, this._options);
+    }
+  }
+}
diff --git a/web/pgadmin/dashboard/static/js/dashboard.js b/web/pgadmin/dashboard/static/js/dashboard.js
index 514b2f19..84804ac2 100644
--- a/web/pgadmin/dashboard/static/js/dashboard.js
+++ b/web/pgadmin/dashboard/static/js/dashboard.js
@@ -1,11 +1,11 @@
 define('pgadmin.dashboard', [
   'sources/url_for', 'sources/gettext', 'require', 'jquery', 'underscore',
-  'sources/pgadmin', 'backbone', 'backgrid', 'flotr2',
+  'sources/pgadmin', 'backbone', 'backgrid', './charting',
   'pgadmin.alertifyjs', 'pgadmin.backform',
   'sources/nodes/dashboard', 'backgrid.filter',
   'pgadmin.browser', 'bootstrap', 'wcdocker',
 ], function(
-  url_for, gettext, r, $, _, pgAdmin, Backbone, Backgrid, Flotr,
+  url_for, gettext, r, $, _, pgAdmin, Backbone, Backgrid, charting,
   Alertify, Backform, NodesDashboard
 ) {
 
@@ -210,10 +210,8 @@ define('pgadmin.dashboard', [
       // Load the default welcome dashboard
       var url = url_for('dashboard.index');
 
-      /* Store the interval ids of the graph interval functions so that we can clear
-       * them when graphs are disabled
-       */
-      this.intervalIds = {};
+      /* Store the chart objects and there interval ids in this store */
+      this.chartStore = {};
 
       var dashboardPanel = pgBrowser.panels['dashboard'].panel;
       if (dashboardPanel) {
@@ -266,7 +264,7 @@ define('pgadmin.dashboard', [
           !_.isUndefined(itemData.connected) &&
             itemData.connected !== true
         ) {
-          self.clearIntervalId();
+          self.clearChartFromStore();
         }
       } else if (itemData && itemData._type) {
         var treeHierarchy = node.getTreeNodeHierarchy(item),
@@ -331,8 +329,8 @@ define('pgadmin.dashboard', [
               ) {
                 $(div).empty();
 
-                /* Clear all the interval functions of previous dashboards */
-                self.clearIntervalId();
+                /* Clear all the charts previous dashboards */
+                self.clearChartFromStore();
 
                 $.ajax({
                   url: url,
@@ -356,8 +354,8 @@ define('pgadmin.dashboard', [
                 !_.isUndefined(itemData.connected) &&
                   itemData.connected !== true
               ) {
-                /* Clear all the interval functions of previous dashboards */
-                self.clearIntervalId();
+                /* Clear all the charts previous dashboards */
+                self.clearChartFromStore();
               }
               $(div).html(
                 '<div class="alert alert-info pg-panel-message" role="alert">' + gettext('Please connect to the selected server to view the dashboard.') + '</div>'
@@ -371,7 +369,7 @@ define('pgadmin.dashboard', [
       }
     },
 
-    renderChartLoop: function(container, sid, did, url, options, counter, refresh) {
+    renderChartLoop: function(chartObj, sid, did, url, counter, refresh) {
       var data = [],
         dataset = [];
 
@@ -386,24 +384,22 @@ define('pgadmin.dashboard', [
           dataType: 'html',
         })
         .done(function(resp) {
-          $(container).removeClass('graph-error');
+          $(chartObj.getContainer()).removeClass('graph-error');
           data = JSON.parse(resp);
-          if (!dashboardVisible)
-            return;
 
           var y = 0,
             x;
           if (dataset.length == 0) {
             if (counter == true) {
               // Have we stashed initial values?
-              if (_.isUndefined($(container).data('counter_previous_vals'))) {
-                $(container).data('counter_previous_vals', data[0]);
+              if (_.isUndefined(chartObj.getOtherData('counter_previous_vals'))) {
+                chartObj.setOtherData('counter_previous_vals', data[0]);
               } else {
                 // Create the initial data structure
                 for (x in data[0]) {
                   dataset.push({
                     'data': [
-                      [0, data[0][x] - $(container).data('counter_previous_vals')[x]],
+                      [0, data[0][x] - chartObj.getOtherData('counter_previous_vals')[x]],
                     ],
                     'label': x,
                   });
@@ -429,10 +425,10 @@ define('pgadmin.dashboard', [
               } else {
                 // Store the current value, minus the previous one we stashed.
                 // It's possible the tab has been reloaded, in which case out previous values are gone
-                if (_.isUndefined($(container).data('counter_previous_vals')))
+                if (_.isUndefined(chartObj.getOtherData('counter_previous_vals')))
                   return;
 
-                dataset[y]['data'].unshift([0, data[0][x] - $(container).data('counter_previous_vals')[x]]);
+                dataset[y]['data'].unshift([0, data[0][x] - chartObj.getOtherData('counter_previous_vals')[x]]);
               }
 
               // Reset the time index to get a proper scrolling display
@@ -442,7 +438,7 @@ define('pgadmin.dashboard', [
 
               y++;
             }
-            $(container).data('counter_previous_vals', data[0]);
+            chartObj.setOtherData('counter_previous_vals', data[0]);
           }
 
           // Remove uneeded elements
@@ -453,12 +449,9 @@ define('pgadmin.dashboard', [
             }
           }
 
-          // Draw Graph, if the container still exists and has a size
-          var dashboardPanel = pgBrowser.panels['dashboard'].panel;
-          var div = dashboardPanel.layout().scene().find('.pg-panel-content');
-          if ($(div).find(container).length) { // Exists?
-            if (container.clientHeight > 0 && container.clientWidth > 0) { // Not hidden?
-              Flotr.draw(container, dataset, options);
+          if (chartObj.isInPage()) {
+            if (chartObj.isVisible()) {
+              chartObj.draw(dataset);
             }
           } else {
             return;
@@ -487,8 +480,8 @@ define('pgadmin.dashboard', [
             }
           }
 
-          $(container).addClass('graph-error');
-          $(container).html(
+          $(chartObj.getContainer()).addClass('graph-error');
+          $(chartObj.getContainer()).html(
             '<div class="alert alert-' + cls + ' pg-panel-message" role="alert">' + msg + '</div>'
           );
         });
@@ -510,15 +503,41 @@ define('pgadmin.dashboard', [
       //     { data: [[0, y0], [1, y1]...], label: 'Label 3', [options] }
       // ]
 
-      let self = this;
-      if(self.intervalIds[chartName]
+      let self = this,
+        tooltipFormatter = function(refresh, currVal) {
+          return(`Seconds ago: ${parseInt(currVal.x * refresh)}</br>
+                  Value: ${currVal.y}`);
+        };
+
+      if(self.chartStore[chartName]
         && self.old_preferences[prefName] != self.preferences[prefName]) {
-        self.clearIntervalId(chartName);
+        self.clearChartFromStore(chartName);
       }
-      if(!self.intervalIds[chartName]) {
-        self.intervalIds[chartName] = self.renderChartLoop(
-          container, self.sid, self.did, url,
-          options, counter, self.preferences[prefName]
+
+      if(self.chartStore[chartName]) {
+        let chartObj = self.chartStore[chartName].chartObj;
+        chartObj.setOptions(options, false);
+        chartObj.setTooltipFormatter(
+          tooltipFormatter.bind(null, self.preferences[prefName])
+        );
+      }
+
+      if(!self.chartStore[chartName]) {
+
+        let chartObj = new charting.Chart(container, options);
+
+        chartObj.setTooltipFormatter(
+          tooltipFormatter.bind(null, self.preferences[prefName])
+        );
+
+        self.chartStore[chartName] = {
+          'chartObj' : chartObj,
+          'intervalId' : undefined,
+        };
+
+        self.chartStore[chartName]['intervalId'] = self.renderChartLoop(
+          self.chartStore[chartName]['chartObj'], self.sid, self.did, url,
+          counter, self.preferences[prefName]
         );
       }
     },
@@ -666,17 +685,17 @@ define('pgadmin.dashboard', [
       });
     },
 
-    clearIntervalId: function(intervalId) {
+    clearChartFromStore: function(chartName) {
       var self = this;
-      if(!intervalId){
-        _.each(self.intervalIds, function(id, key) {
-          clearInterval(id);
-          delete self.intervalIds[key];
+      if(!chartName){
+        _.each(self.chartStore, function(chart, key) {
+          clearInterval(chart.intervalId);
+          delete self.chartStore[key];
         });
       }
       else {
-        clearInterval(self.intervalIds[intervalId]);
-        delete self.intervalIds[intervalId];
+        clearInterval(self.chartStore[chartName].intervalId);
+        delete self.chartStore[chartName];
       }
     },
 
@@ -737,20 +756,41 @@ define('pgadmin.dashboard', [
           yaxis: {
             autoscale: 1,
           },
-          legend: {
-            position: 'nw',
-            backgroundColor: '#D2E8FF',
-          },
-          shadowSize: 0,
-          resolution : 5,
         };
 
+        if(self.preferences.graph_data_points) {
+          /* Merge data points related options */
+          options_line = {
+            ...options_line,
+            ...{
+              points: {
+                show:true,
+                radius: 1,
+                hitRadius: 3,
+              },
+            },
+          };
+        }
+
+        if(self.preferences.graph_mouse_track) {
+          /* Merge mouse track related options */
+          options_line = {
+            ...options_line,
+            ...{
+              mouse: {
+                track:true,
+                position: 'sw',
+              },
+            },
+          };
+        }
+
         if(self.preferences.show_graphs && $('#dashboard-graphs').hasClass('dashboard-hidden')) {
           $('#dashboard-graphs').removeClass('dashboard-hidden');
         }
         else if(!self.preferences.show_graphs) {
           $('#dashboard-graphs').addClass('dashboard-hidden');
-          self.clearIntervalId();
+          self.clearChartFromStore();
         }
 
         if (self.preferences.show_activity && $('#dashboard-activity').hasClass('dashboard-hidden')) {
@@ -1344,8 +1384,11 @@ define('pgadmin.dashboard', [
         });
       }
     },
-    toggleVisibility: function(flag) {
-      dashboardVisible = flag;
+    toggleVisibility: function(visible, closed=false) {
+      dashboardVisible = visible;
+      if(closed) {
+        this.clearChartFromStore();
+      }
     },
     can_take_action: function(m) {
       // We will validate if user is allowed to cancel the active query
diff --git a/web/regression/javascript/dashboard/charting_spec.js b/web/regression/javascript/dashboard/charting_spec.js
new file mode 100644
index 00000000..00652090
--- /dev/null
+++ b/web/regression/javascript/dashboard/charting_spec.js
@@ -0,0 +1,91 @@
+import $ from 'jquery';
+import {Chart} from 'top/dashboard/static/js/charting';
+
+describe('In charting related testcases', ()=> {
+  let chartObj = undefined,
+    chartDiv = undefined,
+    options = {};
+
+  beforeEach(()=> {
+    $('body').append(
+      '<div id="charting-test-container"></div>'
+    );
+    chartDiv = $('#charting-test-container')[0];
+    chartObj = new Chart(chartDiv, options);
+  });
+
+  it('Chart api should be defined', ()=>{
+    expect(chartObj.chartApi).toBeDefined();
+  });
+
+  it('Return the correct container', ()=>{
+    expect(chartObj.getContainer()).toBe(chartDiv);
+  });
+
+  it('Returns the container dimensions', ()=>{
+    let dim = chartObj.getContainerDimensions();
+    expect(dim.height).toBeDefined();
+    expect(dim.width).toBeDefined();
+  });
+
+  it('Check if options are set', ()=>{
+    chartObj.setOptions({
+      mouse: {
+        track:true,
+      },
+    });
+
+    let opt = chartObj.getOptions();
+
+    expect(opt.mouse).toBeDefined();
+  });
+
+  it('Check if options are set with mergeOptions false', ()=>{
+    let overOpt = {
+      mouse: {
+        track:true,
+      },
+    };
+    chartObj.setOptions(overOpt, false);
+
+    let newOptShouldBe = {...chartObj._defaultOptions, ...overOpt};
+
+    let opt = chartObj.getOptions();
+    expect(JSON.stringify(opt)).toEqual(JSON.stringify(newOptShouldBe));
+  });
+
+  it('Check if other data is set', ()=>{
+    chartObj.setOtherData('some_val', 1);
+    expect(chartObj._otherData['some_val']).toEqual(1);
+  });
+
+  it('Check if other data is get', ()=>{
+    chartObj.setOtherData('some_val', 1);
+    expect(chartObj.getOtherData('some_val')).toEqual(1);
+  });
+
+  it('Check if isVisible returns correct', ()=>{
+    let dimSpy = spyOn(chartObj, 'getContainerDimensions');
+
+    dimSpy.and.returnValue({
+      height: 1, width: 1,
+    });
+    expect(chartObj.isVisible()).toBe(true);
+    dimSpy.and.stub();
+
+    dimSpy.and.returnValue({
+      height: 0, width: 0,
+    });
+    expect(chartObj.isVisible()).toBe(false);
+  });
+
+  it('Check if isInPage returns correct', ()=>{
+    expect(chartObj.isInPage()).toBe(true);
+    $('body').find('#charting-test-container').remove();
+    expect(chartObj.isInPage()).toBe(false);
+  });
+
+  afterEach(()=>{
+    $('body').find('#charting-test-container').remove();
+  });
+});
diff --git a/web/webpack.config.js b/web/webpack.config.js
index 4dbf1357..67466af4 100644
--- a/web/webpack.config.js
+++ b/web/webpack.config.js
@@ -144,6 +144,7 @@ module.exports = {
         loader: 'babel-loader',
         options: {
           presets: ['es2015', 'react'],
+          plugins: ['transform-object-rest-spread'],
         },
       },
     }, {
diff --git a/web/webpack.test.config.js b/web/webpack.test.config.js
index 757107ca..a7118711 100644
--- a/web/webpack.test.config.js
+++ b/web/webpack.test.config.js
@@ -58,6 +58,7 @@ module.exports = {
   resolve: {
     extensions: ['.js', '.jsx'],
     alias: {
+      'top': path.join(__dirname, './pgadmin'),
       'jquery': path.join(__dirname, './node_modules/jquery/dist/jquery'),
       'alertify': path.join(__dirname, './node_modules/alertifyjs/build/alertify'),
       'jquery.event.drag': path.join(__dirname, './node_modules/slickgrid/lib/jquery.event.drag-2.3.0'),
@@ -75,6 +76,8 @@ module.exports = {
       'slickgrid': nodeModulesDir + '/slickgrid/',
       'slickgrid.plugins': nodeModulesDir + '/slickgrid/plugins/',
       'slickgrid.grid': nodeModulesDir + '/slickgrid/slick.grid',
+      'bean': path.join(__dirname, './node_modules/flotr2/lib/bean'),
+      'flotr2': path.join(__dirname, './node_modules/flotr2/flotr2.amd'),
       'browser': path.resolve(__dirname, 'pgadmin/browser/static/js'),
       'pgadmin': sourcesDir + '/js/pgadmin',
       'pgadmin.sqlfoldcode': sourcesDir + '/js/codemirror/addon/fold/pgadmin-sqlfoldcode',
