diff --git a/web/pgadmin/static/js/codemirror/addon/fold/pgadmin-sqlfoldcode.js b/web/pgadmin/static/js/codemirror/addon/fold/pgadmin-sqlfoldcode.js
new file mode 100644
index 0000000..f0e9ecc
--- /dev/null
+++ b/web/pgadmin/static/js/codemirror/addon/fold/pgadmin-sqlfoldcode.js
@@ -0,0 +1,83 @@
+(function(mod) {
+  if (typeof exports == "object" && typeof module == "object") // CommonJS
+    mod(require("codemirror"));
+  else if (typeof define == "function" && define.amd) // AMD
+    define(["codemirror"], mod);
+  else // Plain browser env
+    mod(CodeMirror);
+})(function(CodeMirror) {
+  "use strict";
+
+  CodeMirror.pgadminKeywordRangeFinder = function(cm, start, startTkn, endTkn) {
+    var line = start.line, lineText = cm.getLine(line);
+    var at = lineText.length, startChar, tokenType;
+    for (; at > 0;) {
+      var found = lineText.lastIndexOf(startTkn, at);
+      var startToken = startTkn;
+      var endToken = endTkn;
+      if (found < start.ch) {
+        var found = lineText.lastIndexOf("[", at);
+        if (found < start.ch) break;
+        var startToken = '[';
+        var endToken = ']';
+      }
+
+      tokenType = cm.getTokenAt(CodeMirror.Pos(line, found + 1)).type;
+      if (!/^(comment|string)/.test(tokenType)) { startChar = found; break; }
+      at = found - 1;
+    }
+    if (startChar == null || lineText.lastIndexOf(startToken) > startChar) return;
+    var count = 1, lastLine = cm.lineCount(), end, endCh;
+    outer: for (var i = line + 1; i < lastLine; ++i) {
+      var text = cm.getLine(i), pos = 0;
+      for (;;) {
+        var nextOpen = text.indexOf(startToken, pos), nextClose = text.indexOf(endToken, pos);
+        if (nextOpen < 0) nextOpen = text.length;
+        if (nextClose < 0) nextClose = text.length;
+        pos = Math.min(nextOpen, nextClose);
+        if (pos == text.length) break;
+        if (cm.getTokenAt(CodeMirror.Pos(i, pos + 1)).type == tokenType) {
+          if (pos == nextOpen) ++count;
+          else if (!--count) {
+            end = i;
+            endCh = pos;
+            break outer;
+          }
+        }
+        ++pos;
+      }
+    }
+    if (end == null || end == line + 1) return;
+    return {from: CodeMirror.Pos(line, startChar + startTkn.length),
+          to: CodeMirror.Pos(end, endCh)};
+  };
+
+  CodeMirror.pgadminBeginRangeFinder = function(cm, start) {
+    var startToken = 'BEGIN';
+    var endToken = 'END;';
+    var fromToPos = CodeMirror.pgadminKeywordRangeFinder(cm, start, startToken, endToken);
+    return fromToPos;
+  };
+
+  CodeMirror.pgadminIfRangeFinder = function(cm, start) {
+    var startToken = 'IF';
+    var endToken = 'END IF';
+    var fromToPos = CodeMirror.pgadminKeywordRangeFinder(cm, start, startToken, endToken);
+    return fromToPos;
+  };
+
+  CodeMirror.pgadminLoopRangeFinder = function(cm, start) {
+    var startToken = 'LOOP';
+    var endToken = 'END LOOP';
+    var fromToPos = CodeMirror.pgadminKeywordRangeFinder(cm, start, startToken, endToken);
+    return fromToPos;
+  };
+
+  CodeMirror.pgadminCaseRangeFinder = function(cm, start) {
+    var startToken = 'CASE';
+    var endToken = 'END CASE';
+    var fromToPos = CodeMirror.pgadminKeywordRangeFinder(cm, start, startToken, endToken);
+    return fromToPos;
+  };
+
+});
diff --git a/web/pgadmin/static/js/slickgrid/slick.pgadmin.editors.js b/web/pgadmin/static/js/slickgrid/slick.pgadmin.editors.js
new file mode 100644
index 0000000..1645416
--- /dev/null
+++ b/web/pgadmin/static/js/slickgrid/slick.pgadmin.editors.js
@@ -0,0 +1,867 @@
+/***
+ * Contains JSON SlickGrid editors.
+ * @module Editors
+ * @namespace Slick
+ */
+
+(function ($) {
+  // register namespace
+  $.extend(true, window, {
+    "Slick": {
+      "Editors": {
+        "pgText": pgTextEditor,
+        "JsonText": JsonTextEditor,
+        // Below editor will read only editors, Just to display data
+        "ReadOnlyText": ReadOnlyTextEditor,
+        "ReadOnlyCheckbox": ReadOnlyCheckboxEditor,
+        "Checkbox": CheckboxEditor, // Override editor to implement checkbox with three states
+        "ReadOnlypgText": ReadOnlypgTextEditor,
+        "ReadOnlyJsonText": ReadOnlyJsonTextEditor,
+        "CustomNumber": CustomNumberEditor
+      }
+    }
+  });
+
+  // Text data type editor
+  function pgTextEditor(args) {
+    var $input, $wrapper;
+    var defaultValue;
+    var scope = this;
+
+    this.init = function () {
+      var $container = $("body");
+
+      $wrapper = $("<DIV style='z-index:10000;position:absolute;background:white;padding:5px;border:3px solid gray; -moz-border-radius:10px; border-radius:10px;'/>")
+          .appendTo($container);
+
+      $input = $("<TEXTAREA hidefocus rows=5 style='backround:white;width:250px;height:80px;border:0;outline:0'>")
+          .appendTo($wrapper);
+
+      $("<DIV style='text-align:right'><BUTTON class='btn btn-primary fa fa-lg fa-save long_text_editor pg-alertify-button'>Save</BUTTON>"
+         + "<BUTTON class='btn btn-danger fa fa-lg fa-times long_text_editor pg-alertify-button'>Cancel</BUTTON></DIV>")
+          .appendTo($wrapper);
+
+      $wrapper.find("button:first").bind("click", this.save);
+      $wrapper.find("button:last").bind("click", this.cancel);
+      $input.bind("keydown", this.handleKeyDown);
+
+      scope.position(args.position);
+      $input.focus().select();
+    };
+
+    this.handleKeyDown = function (e) {
+      if (e.which == $.ui.keyCode.ENTER && e.ctrlKey) {
+        scope.save();
+      } else if (e.which == $.ui.keyCode.ESCAPE) {
+        e.preventDefault();
+        scope.cancel();
+      } else if (e.which == $.ui.keyCode.TAB && e.shiftKey) {
+        e.preventDefault();
+        args.grid.navigatePrev();
+      } else if (e.which == $.ui.keyCode.TAB) {
+        e.preventDefault();
+        args.grid.navigateNext();
+      }
+    };
+
+    this.save = function () {
+      args.commitChanges();
+    };
+
+    this.cancel = function () {
+      $input.val(defaultValue);
+      args.cancelChanges();
+    };
+
+    this.hide = function () {
+      $wrapper.hide();
+    };
+
+    this.show = function () {
+      $wrapper.show();
+    };
+
+    this.position = function (position) {
+      var _elem_height = $wrapper.parent().find('#datagrid').height(),
+      is_hidden, _position;
+      // We can not display editor partially visible so we will lift it above select column
+      if(position.top > _elem_height) {
+        is_hidden = position.bottom - _elem_height;
+      }
+
+      if(is_hidden) {
+        _position = position.top - is_hidden;
+      } else {
+        _position = position.top - 5;
+      }
+
+      $wrapper
+          .css("top", _position)
+          .css("left", position.left - 5)
+    };
+
+    this.destroy = function () {
+      $wrapper.remove();
+    };
+
+    this.focus = function () {
+      $input.focus();
+    };
+
+    // When text editor opens
+    this.loadValue = function (item) {
+      if (item[args.column.field] === "") {
+        $input.val("''");
+      }
+      else {
+        $input.val(defaultValue = item[args.column.field]);
+        $input.select();
+      }
+    };
+
+    this.serializeValue = function () {
+      var value = $input.val();
+      // If empty return null
+      if (value === "") {
+        return null;
+      }
+      // single/double quotes represent an empty string
+      // If found return ''
+      else if (value === "''" || value === '""') {
+        return '';
+      }
+      else {
+        // If found string literals - \"\", \'\', \\'\\' and \\\\'\\\\'
+        // then remove slashes.
+        value = value.replace("\\'\\'", "''");
+        value = value.replace('\\"\\"', '""');
+        value = value = value.replace(/\\\\/g, '\\');
+        return value;
+      }
+    };
+
+    this.applyValue = function (item, state) {
+      item[args.column.field] = state;
+    };
+
+    this.isValueChanged = function () {
+      return (!($input.val() == "" && defaultValue == null)) && ($input.val() != defaultValue);
+    };
+
+    this.validate = function () {
+      if (args.column.validator) {
+        var validationResults = args.column.validator($input.val());
+        if (!validationResults.valid) {
+          return validationResults;
+        }
+      }
+
+      return {
+        valid: true,
+        msg: null
+      };
+    };
+
+    this.init();
+  }
+
+  // JSON data type editor
+  function JsonTextEditor(args) {
+    var $input, $wrapper;
+    var defaultValue;
+    var scope = this;
+
+    this.init = function () {
+      var $container = $("body");
+
+      $wrapper = $("<DIV style='z-index:10000;position:absolute;background:white;padding:5px;border:3px solid gray; -moz-border-radius:10px; border-radius:10px;'/>")
+          .appendTo($container);
+
+      $input = $("<TEXTAREA hidefocus rows=5 style='backround:white;width:250px;height:80px;border:0;outline:0'>")
+          .appendTo($wrapper);
+
+      $("<DIV style='text-align:right'><BUTTON class='btn btn-primary fa fa-lg fa-save long_text_editor pg-alertify-button'>Save</BUTTON>"
+         + "<BUTTON class='btn btn-danger fa fa-lg fa-times long_text_editor pg-alertify-button'>Cancel</BUTTON></DIV>")
+          .appendTo($wrapper);
+
+      $wrapper.find("button:first").bind("click", this.save);
+      $wrapper.find("button:last").bind("click", this.cancel);
+      $input.bind("keydown", this.handleKeyDown);
+
+      scope.position(args.position);
+      $input.focus().select();
+    };
+
+    this.handleKeyDown = function (e) {
+      if (e.which == $.ui.keyCode.ENTER && e.ctrlKey) {
+        scope.save();
+      } else if (e.which == $.ui.keyCode.ESCAPE) {
+        e.preventDefault();
+        scope.cancel();
+      } else if (e.which == $.ui.keyCode.TAB && e.shiftKey) {
+        e.preventDefault();
+        args.grid.navigatePrev();
+      } else if (e.which == $.ui.keyCode.TAB) {
+        e.preventDefault();
+        args.grid.navigateNext();
+      }
+    };
+
+    this.save = function () {
+      args.commitChanges();
+    };
+
+    this.cancel = function () {
+      $input.val(defaultValue);
+      args.cancelChanges();
+    };
+
+    this.hide = function () {
+      $wrapper.hide();
+    };
+
+    this.show = function () {
+      $wrapper.show();
+    };
+
+    this.position = function (position) {
+      var _elem_height = $wrapper.parent().find('#datagrid').height(),
+      is_hidden, _position;
+      // We can not display editor partially visible so we will lift it above select column
+      if(position.top > _elem_height) {
+        is_hidden = position.bottom - _elem_height;
+      }
+
+      if(is_hidden) {
+        _position = position.top - is_hidden;
+      } else {
+        _position = position.top - 5;
+      }
+
+      $wrapper
+          .css("top", position.top - 5)
+          .css("left", position.left - 5)
+    };
+
+    this.destroy = function () {
+      $wrapper.remove();
+    };
+
+    this.focus = function () {
+      $input.focus();
+    };
+
+    this.loadValue = function (item) {
+      var data = defaultValue = item[args.column.field];
+      if (typeof data === "object" && !Array.isArray(data)) {
+        data = JSON.stringify(data);
+      } else if (Array.isArray(data)) {
+        var temp = [];
+        $.each(data, function(i, val) {
+          if (typeof val === "object") {
+            temp.push(JSON.stringify(val));
+          } else {
+            temp.push(val)
+          }
+        });
+        data = "[" + temp.join() + "]";
+      }
+      $input.val(data);
+      $input.select();
+    };
+
+    this.serializeValue = function () {
+      if ($input.val() === "") {
+        return null;
+      }
+      return $input.val();
+    };
+
+    this.applyValue = function (item, state) {
+      item[args.column.field] = state;
+    };
+
+    this.isValueChanged = function () {
+      return (!($input.val() == "" && defaultValue == null)) && ($input.val() != defaultValue);
+    };
+
+    this.validate = function () {
+      if (args.column.validator) {
+        var validationResults = args.column.validator($input.val());
+        if (!validationResults.valid) {
+          return validationResults;
+        }
+      }
+
+      return {
+        valid: true,
+        msg: null
+      };
+    };
+
+    this.init();
+  }
+
+  // Text data type editor
+  function ReadOnlypgTextEditor(args) {
+    var $input, $wrapper;
+    var defaultValue;
+    var scope = this;
+
+    this.init = function () {
+      var $container = $("body");
+
+      $wrapper = $("<DIV style='z-index:10000;position:absolute;background:white;padding:5px;border:3px solid gray; -moz-border-radius:10px; border-radius:10px;'/>")
+          .appendTo($container);
+
+      $input = $("<TEXTAREA hidefocus rows=5 style='backround:white;width:250px;height:80px;border:0;outline:0' readonly>")
+          .appendTo($wrapper);
+
+      $("<DIV style='text-align:right'><BUTTON class='btn btn-primary fa fa-lg fa-times long_text_editor pg-alertify-button'>Close</BUTTON></DIV>")
+       .appendTo($wrapper);
+
+      $wrapper.find("button:first").bind("click", this.cancel);
+      $input.bind("keydown", this.handleKeyDown);
+
+      scope.position(args.position);
+      $input.focus().select();
+    };
+
+    this.handleKeyDown = function (e) {
+      if (e.which == $.ui.keyCode.ENTER && e.ctrlKey) {
+        scope.cancel();
+      } else if (e.which == $.ui.keyCode.ESCAPE) {
+        e.preventDefault();
+        scope.cancel();
+      } else if (e.which == $.ui.keyCode.TAB && e.shiftKey) {
+        scope.cancel();
+        e.preventDefault();
+        args.grid.navigatePrev();
+      } else if (e.which == $.ui.keyCode.TAB) {
+        scope.cancel();
+        e.preventDefault();
+        args.grid.navigateNext();
+      }
+    };
+
+    this.cancel = function () {
+      $input.val(defaultValue);
+      args.cancelChanges();
+    };
+
+    this.hide = function () {
+      $wrapper.hide();
+    };
+
+    this.show = function () {
+      $wrapper.show();
+    };
+
+    this.position = function (position) {
+      var _elem_height = $wrapper.parent().find('#datagrid').height(),
+        is_hidden, _position;
+      // We can not display editor partially visible so we will lift it above select column
+      if(position.top > _elem_height) {
+        is_hidden = position.bottom - _elem_height;
+      }
+
+      if(is_hidden) {
+        _position = position.top - is_hidden;
+      } else {
+        _position = position.top - 5;
+      }
+
+      $wrapper
+          .css("top", _position)
+          .css("left", position.left - 5)
+    };
+
+    this.destroy = function () {
+      $wrapper.remove();
+    };
+
+    this.focus = function () {
+      $input.focus();
+    };
+
+    this.loadValue = function (item) {
+      $input.val(defaultValue = item[args.column.field]);
+      $input.select();
+    };
+
+    this.serializeValue = function () {
+      return $input.val();
+    };
+
+    this.applyValue = function (item, state) {
+      item[args.column.field] = state;
+    };
+
+    this.isValueChanged = function () {
+      return (!($input.val() == "" && defaultValue == null)) && ($input.val() != defaultValue);
+    };
+
+    this.validate = function () {
+      if (args.column.validator) {
+        var validationResults = args.column.validator($input.val());
+        if (!validationResults.valid) {
+          return validationResults;
+        }
+      }
+
+      return {
+        valid: true,
+        msg: null
+      };
+    };
+
+    this.init();
+  }
+
+  /* Override CheckboxEditor to implement checkbox with three states.
+   * 1) checked=true
+   * 2) unchecked=false
+   * 3) indeterminate=null/''
+   */
+  function CheckboxEditor(args) {
+    var $select, el;
+    var defaultValue;
+    var scope = this;
+
+    this.init = function () {
+      $select = $("<INPUT type=checkbox value='true' class='editor-checkbox' hideFocus>");
+      $select.appendTo(args.container);
+      $select.focus();
+
+      // The following code is taken from https://css-tricks.com/indeterminate-checkboxes/
+      $select.data('checked', 0).bind("click", function (e) {
+        el = $(this);
+        switch(el.data('checked')) {
+          // unchecked, going indeterminate
+          case 0:
+            el.data('checked', 1);
+            el.prop('indeterminate', true);
+            break;
+
+          // indeterminate, going checked
+          case 1:
+            el.data('checked', 2);
+            el.prop('indeterminate', false);
+            el.prop('checked', true);
+            break;
+
+          // checked, going unchecked
+          default:
+            el.data('checked', 0);
+            el.prop('indeterminate', false);
+            el.prop('checked', false);
+        }
+      });
+    };
+
+    this.destroy = function () {
+      $select.remove();
+    };
+
+    this.focus = function () {
+      $select.focus();
+    };
+
+    this.loadValue = function (item) {
+      defaultValue = item[args.column.field];
+      if (_.isNull(defaultValue)) {
+        $select.prop('indeterminate', true);
+      }
+      else {
+        defaultValue = !!item[args.column.field];
+        if (defaultValue) {
+          $select.prop('checked', true);
+        } else {
+          $select.prop('checked', false);
+        }
+      }
+    };
+
+    this.serializeValue = function () {
+      if ($select.prop('indeterminate')) {
+        return null;
+      }
+      return $select.prop('checked');
+    };
+
+    this.applyValue = function (item, state) {
+      item[args.column.field] = state;
+    };
+
+    this.isValueChanged = function () {
+      return (this.serializeValue() !== defaultValue);
+    };
+
+    this.validate = function () {
+      return {
+        valid: true,
+        msg: null
+      };
+    };
+
+    this.init();
+  }
+
+  // JSON data type editor
+  function ReadOnlyJsonTextEditor(args) {
+    var $input, $wrapper;
+    var defaultValue;
+    var scope = this;
+
+    this.init = function () {
+      var $container = $("body");
+
+      $wrapper = $("<DIV style='z-index:10000;position:absolute;background:white;padding:5px;border:3px solid gray; -moz-border-radius:10px; border-radius:10px;'/>")
+          .appendTo($container);
+
+      $input = $("<TEXTAREA hidefocus rows=5 style='backround:white;width:250px;height:80px;border:0;outline:0' readonly>")
+          .appendTo($wrapper);
+
+      $("<DIV style='text-align:right'><BUTTON class='btn btn-primary fa fa-lg fa-times long_text_editor pg-alertify-button'>Close</BUTTON></DIV>")
+       .appendTo($wrapper);
+
+      $wrapper.find("button:first").bind("click", this.cancel);
+      $input.bind("keydown", this.handleKeyDown);
+
+      scope.position(args.position);
+      $input.focus().select();
+    };
+
+    this.handleKeyDown = function (e) {
+      if (e.which == $.ui.keyCode.ENTER && e.ctrlKey) {
+        scope.cancel();
+      } else if (e.which == $.ui.keyCode.ESCAPE) {
+        e.preventDefault();
+        scope.cancel();
+      } else if (e.which == $.ui.keyCode.TAB && e.shiftKey) {
+        scope.cancel();
+        e.preventDefault();
+        args.grid.navigatePrev();
+      } else if (e.which == $.ui.keyCode.TAB) {
+        scope.cancel();
+        e.preventDefault();
+        args.grid.navigateNext();
+      }
+    };
+
+    this.cancel = function () {
+      $input.val(defaultValue);
+      args.cancelChanges();
+    };
+
+    this.hide = function () {
+      $wrapper.hide();
+    };
+
+    this.show = function () {
+      $wrapper.show();
+    };
+
+    this.position = function (position) {
+      var _elem_height = $wrapper.parent().find('#datagrid').height(),
+        is_hidden, _position;
+      // We can not display editor partially visible so we will lift it above select column
+      if(position.top > _elem_height) {
+        is_hidden = position.bottom - _elem_height;
+      }
+
+      if(is_hidden) {
+        _position = position.top - is_hidden;
+      } else {
+        _position = position.top - 5;
+      }
+
+      $wrapper
+          .css("top", _position)
+          .css("left", position.left - 5)
+    };
+
+    this.destroy = function () {
+      $wrapper.remove();
+    };
+
+    this.focus = function () {
+      $input.focus();
+    };
+
+    this.loadValue = function (item) {
+      var data = defaultValue = item[args.column.field];
+      if (typeof data === "object" && !Array.isArray(data)) {
+        data = JSON.stringify(data);
+      } else if (Array.isArray(data)) {
+        var temp = [];
+        $.each(data, function(i, val) {
+          if (typeof val === "object") {
+            temp.push(JSON.stringify(val));
+          } else {
+            temp.push(val)
+          }
+        });
+        data = "[" + temp.join() + "]";
+      }
+      $input.val(data);
+      $input.select();
+    };
+
+    this.serializeValue = function () {
+      return $input.val();
+    };
+
+    this.applyValue = function (item, state) {
+      item[args.column.field] = state;
+    };
+
+    this.isValueChanged = function () {
+      return (!($input.val() == "" && defaultValue == null)) && ($input.val() != defaultValue);
+    };
+
+    this.validate = function () {
+      if (args.column.validator) {
+        var validationResults = args.column.validator($input.val());
+        if (!validationResults.valid) {
+          return validationResults;
+        }
+      }
+
+      return {
+        valid: true,
+        msg: null
+      };
+    };
+
+    this.init();
+  }
+
+  function ReadOnlyTextEditor(args) {
+    var $input;
+    var defaultValue;
+    var scope = this;
+
+    this.init = function () {
+      $input = $("<INPUT type=text class='editor-text' readonly/>")
+          .appendTo(args.container)
+          .bind("keydown.nav", function (e) {
+            if (e.keyCode === $.ui.keyCode.LEFT || e.keyCode === $.ui.keyCode.RIGHT) {
+              e.stopImmediatePropagation();
+            }
+          })
+          .focus()
+          .select();
+    };
+
+    this.destroy = function () {
+      $input.remove();
+    };
+
+    this.focus = function () {
+      $input.focus();
+    };
+
+    this.getValue = function () {
+      return $input.val();
+    };
+
+    this.loadValue = function (item) {
+      var value = item[args.column.field];
+
+      // Check if value is null or undefined
+      if (value === undefined && typeof value === "undefined") {
+        value = ""
+      }
+      defaultValue = value;
+      $input.val(defaultValue);
+      $input[0].defaultValue = defaultValue;
+      $input.select();
+    };
+
+    this.serializeValue = function () {
+      return $input.val();
+    };
+
+    this.applyValue = function (item, state) {
+      item[args.column.field] = state;
+    };
+
+    this.isValueChanged = function () {
+      return (!($input.val() == "" && defaultValue == null)) && ($input.val() != defaultValue);
+    };
+
+    this.validate = function () {
+      if (args.column.validator) {
+        var validationResults = args.column.validator($input.val());
+        if (!validationResults.valid) {
+          return validationResults;
+        }
+      }
+
+      return {
+        valid: true,
+        msg: null
+      };
+    };
+
+    this.init();
+  }
+
+  function ReadOnlyCheckboxEditor(args) {
+    var $select, el;
+    var defaultValue;
+    var scope = this;
+
+    this.init = function () {
+      $select = $("<INPUT type=checkbox value='true' class='editor-checkbox' hideFocus disabled>");
+      $select.appendTo(args.container);
+      $select.focus();
+
+      // The following code is taken from https://css-tricks.com/indeterminate-checkboxes/
+      $select.data('checked', 0).bind("click", function (e) {
+        el = $(this);
+        switch(el.data('checked')) {
+          // unchecked, going indeterminate
+          case 0:
+            el.data('checked', 1);
+            el.prop('indeterminate', true);
+            break;
+
+          // indeterminate, going checked
+          case 1:
+            el.data('checked', 2);
+            el.prop('indeterminate', false);
+            el.prop('checked', true);
+            break;
+
+          // checked, going unchecked
+          default:
+            el.data('checked', 0);
+            el.prop('indeterminate', false);
+            el.prop('checked', false);
+        }
+      });
+    };
+
+    this.destroy = function () {
+      $select.remove();
+    };
+
+    this.focus = function () {
+      $select.focus();
+    };
+
+    this.loadValue = function (item) {
+      defaultValue = item[args.column.field];
+      if (_.isNull(defaultValue)) {
+        $select.prop('indeterminate', true);
+      }
+      else {
+        defaultValue = !!item[args.column.field];
+        if (defaultValue) {
+          $select.prop('checked', true);
+        } else {
+          $select.prop('checked', false);
+        }
+      }
+    };
+
+    this.serializeValue = function () {
+      if ($select.prop('indeterminate')) {
+        return null;
+      }
+      return $select.prop('checked');
+    };
+
+    this.applyValue = function (item, state) {
+      item[args.column.field] = state;
+    };
+
+    this.isValueChanged = function () {
+      return (this.serializeValue() !== defaultValue);
+    };
+
+    this.validate = function () {
+      return {
+        valid: true,
+        msg: null
+      };
+    };
+
+    this.init();
+  }
+
+  function CustomNumberEditor(args) {
+    var $input;
+    var defaultValue;
+    var scope = this;
+
+    this.init = function () {
+      $input = $("<INPUT type=text class='editor-text' />");
+
+      $input.bind("keydown.nav", function (e) {
+        if (e.keyCode === $.ui.keyCode.LEFT || e.keyCode === $.ui.keyCode.RIGHT) {
+          e.stopImmediatePropagation();
+        }
+      });
+
+      $input.appendTo(args.container);
+      $input.focus().select();
+    };
+
+    this.destroy = function () {
+      $input.remove();
+    };
+
+    this.focus = function () {
+      $input.focus();
+    };
+
+    this.loadValue = function (item) {
+      defaultValue = item[args.column.field];
+      $input.val(defaultValue);
+      $input[0].defaultValue = defaultValue;
+      $input.select();
+    };
+
+    this.serializeValue = function () {
+      if ($input.val() === "") {
+        return null;
+      }
+      return $input.val();
+    };
+
+    this.applyValue = function (item, state) {
+      item[args.column.field] = state;
+    };
+
+    this.isValueChanged = function () {
+      return (!($input.val() == "" && defaultValue == null)) && ($input.val() != defaultValue);
+    };
+
+    this.validate = function () {
+      if (isNaN($input.val())) {
+        return {
+          valid: false,
+          msg: "Please enter a valid integer"
+        };
+      }
+
+      if (args.column.validator) {
+        var validationResults = args.column.validator($input.val());
+        if (!validationResults.valid) {
+          return validationResults;
+        }
+      }
+
+      return {
+        valid: true,
+        msg: null
+      };
+    };
+
+    this.init();
+  }
+
+})(jQuery);
diff --git a/web/pgadmin/static/js/slickgrid/slick.pgadmin.formatters.js b/web/pgadmin/static/js/slickgrid/slick.pgadmin.formatters.js
new file mode 100644
index 0000000..b066095
--- /dev/null
+++ b/web/pgadmin/static/js/slickgrid/slick.pgadmin.formatters.js
@@ -0,0 +1,77 @@
+/***
+ * Contains pgAdmin4 related SlickGrid formatters.
+ *
+ * @module Formatters
+ * @namespace Slick
+ */
+
+(function ($) {
+  // register namespace
+  $.extend(true, window, {
+    "Slick": {
+      "Formatters": {
+        "JsonString": JsonFormatter,
+        "Numbers": NumbersFormatter,
+        "Checkmark": CheckmarkFormatter,
+        "Text": TextFormatter,
+      }
+    }
+  });
+
+  function JsonFormatter(row, cell, value, columnDef, dataContext) {
+    if (value == null || value === "") {
+      return "";
+    } else {
+      // Stringify only if it's json object
+      if (typeof value === "object" && !Array.isArray(value)) {
+        return JSON.stringify(value);
+      } else if (Array.isArray(value)) {
+        var temp = [];
+        $.each(value, function(i, val) {
+          if (typeof val === "object") {
+            temp.push(JSON.stringify(val));
+          } else {
+            temp.push(val)
+          }
+        });
+        return "[" + temp.join() + "]"
+      } else {
+        return value;
+      }
+    }
+  }
+
+  function NumbersFormatter(row, cell, value, columnDef, dataContext) {
+    if (_.isUndefined(value) || value === null) {
+      return "<span class='pull-right'>[null]</span>";
+    }
+    else if (value === "") {
+      return '';
+    }
+    else {
+      return "<span style='float:right'>" + value + "</span>";
+    }
+  }
+
+  function CheckmarkFormatter(row, cell, value, columnDef, dataContext) {
+    /* Checkbox has 3 states
+     * 1) checked=true
+     * 2) unchecked=false
+     * 3) indeterminate=null/''
+     */
+    if (value == null || value === "") {
+      return "<span class='pull-left'>[null]</span>";
+    }
+    return value ? "true" : "false";
+  }
+
+  function TextFormatter(row, cell, value, columnDef, dataContext) {
+    if (_.isUndefined(value) || value === null) {
+      return "<span class='pull-left'>[null]</span>";
+    }
+    else {
+      return value;
+    }
+  }
+
+})(jQuery);
diff --git a/web/pgadmin/static/vendor/codemirror/addon/fold/pgadmin-sqlfoldcode.js b/web/pgadmin/static/vendor/codemirror/addon/fold/pgadmin-sqlfoldcode.js
deleted file mode 100644
index 81f8393..0000000
--- a/web/pgadmin/static/vendor/codemirror/addon/fold/pgadmin-sqlfoldcode.js
+++ /dev/null
@@ -1,83 +0,0 @@
-(function(mod) {
-  if (typeof exports == "object" && typeof module == "object") // CommonJS
-    mod(require("../../lib/codemirror"));
-  else if (typeof define == "function" && define.amd) // AMD
-    define(["../../lib/codemirror"], mod);
-  else // Plain browser env
-    mod(CodeMirror);
-})(function(CodeMirror) {
-  "use strict";
-
-  CodeMirror.pgadminKeywordRangeFinder = function(cm, start, startTkn, endTkn) {
-    var line = start.line, lineText = cm.getLine(line);
-    var at = lineText.length, startChar, tokenType;
-    for (; at > 0;) {
-      var found = lineText.lastIndexOf(startTkn, at);
-      var startToken = startTkn;
-      var endToken = endTkn;
-      if (found < start.ch) {
-        var found = lineText.lastIndexOf("[", at);
-        if (found < start.ch) break;
-        var startToken = '[';
-        var endToken = ']';
-      }
-
-      tokenType = cm.getTokenAt(CodeMirror.Pos(line, found + 1)).type;
-      if (!/^(comment|string)/.test(tokenType)) { startChar = found; break; }
-      at = found - 1;
-    }
-    if (startChar == null || lineText.lastIndexOf(startToken) > startChar) return;
-    var count = 1, lastLine = cm.lineCount(), end, endCh;
-    outer: for (var i = line + 1; i < lastLine; ++i) {
-      var text = cm.getLine(i), pos = 0;
-      for (;;) {
-        var nextOpen = text.indexOf(startToken, pos), nextClose = text.indexOf(endToken, pos);
-        if (nextOpen < 0) nextOpen = text.length;
-        if (nextClose < 0) nextClose = text.length;
-        pos = Math.min(nextOpen, nextClose);
-        if (pos == text.length) break;
-        if (cm.getTokenAt(CodeMirror.Pos(i, pos + 1)).type == tokenType) {
-          if (pos == nextOpen) ++count;
-          else if (!--count) {
-            end = i;
-            endCh = pos;
-            break outer;
-          }
-        }
-        ++pos;
-      }
-    }
-    if (end == null || end == line + 1) return;
-    return {from: CodeMirror.Pos(line, startChar + startTkn.length),
-          to: CodeMirror.Pos(end, endCh)};
-  };
-
-  CodeMirror.pgadminBeginRangeFinder = function(cm, start) {
-    var startToken = 'BEGIN';
-    var endToken = 'END;';
-    var fromToPos = CodeMirror.pgadminKeywordRangeFinder(cm, start, startToken, endToken);
-    return fromToPos;
-  };
-
-  CodeMirror.pgadminIfRangeFinder = function(cm, start) {
-    var startToken = 'IF';
-    var endToken = 'END IF';
-    var fromToPos = CodeMirror.pgadminKeywordRangeFinder(cm, start, startToken, endToken);
-    return fromToPos;
-  };
-
-  CodeMirror.pgadminLoopRangeFinder = function(cm, start) {
-    var startToken = 'LOOP';
-    var endToken = 'END LOOP';
-    var fromToPos = CodeMirror.pgadminKeywordRangeFinder(cm, start, startToken, endToken);
-    return fromToPos;
-  };
-
-  CodeMirror.pgadminCaseRangeFinder = function(cm, start) {
-    var startToken = 'CASE';
-    var endToken = 'END CASE';
-    var fromToPos = CodeMirror.pgadminKeywordRangeFinder(cm, start, startToken, endToken);
-    return fromToPos;
-  };
-
-});
diff --git a/web/pgadmin/static/vendor/slickgrid/slick.pgadmin.editors.js b/web/pgadmin/static/vendor/slickgrid/slick.pgadmin.editors.js
deleted file mode 100644
index 1645416..0000000
--- a/web/pgadmin/static/vendor/slickgrid/slick.pgadmin.editors.js
+++ /dev/null
@@ -1,867 +0,0 @@
-/***
- * Contains JSON SlickGrid editors.
- * @module Editors
- * @namespace Slick
- */
-
-(function ($) {
-  // register namespace
-  $.extend(true, window, {
-    "Slick": {
-      "Editors": {
-        "pgText": pgTextEditor,
-        "JsonText": JsonTextEditor,
-        // Below editor will read only editors, Just to display data
-        "ReadOnlyText": ReadOnlyTextEditor,
-        "ReadOnlyCheckbox": ReadOnlyCheckboxEditor,
-        "Checkbox": CheckboxEditor, // Override editor to implement checkbox with three states
-        "ReadOnlypgText": ReadOnlypgTextEditor,
-        "ReadOnlyJsonText": ReadOnlyJsonTextEditor,
-        "CustomNumber": CustomNumberEditor
-      }
-    }
-  });
-
-  // Text data type editor
-  function pgTextEditor(args) {
-    var $input, $wrapper;
-    var defaultValue;
-    var scope = this;
-
-    this.init = function () {
-      var $container = $("body");
-
-      $wrapper = $("<DIV style='z-index:10000;position:absolute;background:white;padding:5px;border:3px solid gray; -moz-border-radius:10px; border-radius:10px;'/>")
-          .appendTo($container);
-
-      $input = $("<TEXTAREA hidefocus rows=5 style='backround:white;width:250px;height:80px;border:0;outline:0'>")
-          .appendTo($wrapper);
-
-      $("<DIV style='text-align:right'><BUTTON class='btn btn-primary fa fa-lg fa-save long_text_editor pg-alertify-button'>Save</BUTTON>"
-         + "<BUTTON class='btn btn-danger fa fa-lg fa-times long_text_editor pg-alertify-button'>Cancel</BUTTON></DIV>")
-          .appendTo($wrapper);
-
-      $wrapper.find("button:first").bind("click", this.save);
-      $wrapper.find("button:last").bind("click", this.cancel);
-      $input.bind("keydown", this.handleKeyDown);
-
-      scope.position(args.position);
-      $input.focus().select();
-    };
-
-    this.handleKeyDown = function (e) {
-      if (e.which == $.ui.keyCode.ENTER && e.ctrlKey) {
-        scope.save();
-      } else if (e.which == $.ui.keyCode.ESCAPE) {
-        e.preventDefault();
-        scope.cancel();
-      } else if (e.which == $.ui.keyCode.TAB && e.shiftKey) {
-        e.preventDefault();
-        args.grid.navigatePrev();
-      } else if (e.which == $.ui.keyCode.TAB) {
-        e.preventDefault();
-        args.grid.navigateNext();
-      }
-    };
-
-    this.save = function () {
-      args.commitChanges();
-    };
-
-    this.cancel = function () {
-      $input.val(defaultValue);
-      args.cancelChanges();
-    };
-
-    this.hide = function () {
-      $wrapper.hide();
-    };
-
-    this.show = function () {
-      $wrapper.show();
-    };
-
-    this.position = function (position) {
-      var _elem_height = $wrapper.parent().find('#datagrid').height(),
-      is_hidden, _position;
-      // We can not display editor partially visible so we will lift it above select column
-      if(position.top > _elem_height) {
-        is_hidden = position.bottom - _elem_height;
-      }
-
-      if(is_hidden) {
-        _position = position.top - is_hidden;
-      } else {
-        _position = position.top - 5;
-      }
-
-      $wrapper
-          .css("top", _position)
-          .css("left", position.left - 5)
-    };
-
-    this.destroy = function () {
-      $wrapper.remove();
-    };
-
-    this.focus = function () {
-      $input.focus();
-    };
-
-    // When text editor opens
-    this.loadValue = function (item) {
-      if (item[args.column.field] === "") {
-        $input.val("''");
-      }
-      else {
-        $input.val(defaultValue = item[args.column.field]);
-        $input.select();
-      }
-    };
-
-    this.serializeValue = function () {
-      var value = $input.val();
-      // If empty return null
-      if (value === "") {
-        return null;
-      }
-      // single/double quotes represent an empty string
-      // If found return ''
-      else if (value === "''" || value === '""') {
-        return '';
-      }
-      else {
-        // If found string literals - \"\", \'\', \\'\\' and \\\\'\\\\'
-        // then remove slashes.
-        value = value.replace("\\'\\'", "''");
-        value = value.replace('\\"\\"', '""');
-        value = value = value.replace(/\\\\/g, '\\');
-        return value;
-      }
-    };
-
-    this.applyValue = function (item, state) {
-      item[args.column.field] = state;
-    };
-
-    this.isValueChanged = function () {
-      return (!($input.val() == "" && defaultValue == null)) && ($input.val() != defaultValue);
-    };
-
-    this.validate = function () {
-      if (args.column.validator) {
-        var validationResults = args.column.validator($input.val());
-        if (!validationResults.valid) {
-          return validationResults;
-        }
-      }
-
-      return {
-        valid: true,
-        msg: null
-      };
-    };
-
-    this.init();
-  }
-
-  // JSON data type editor
-  function JsonTextEditor(args) {
-    var $input, $wrapper;
-    var defaultValue;
-    var scope = this;
-
-    this.init = function () {
-      var $container = $("body");
-
-      $wrapper = $("<DIV style='z-index:10000;position:absolute;background:white;padding:5px;border:3px solid gray; -moz-border-radius:10px; border-radius:10px;'/>")
-          .appendTo($container);
-
-      $input = $("<TEXTAREA hidefocus rows=5 style='backround:white;width:250px;height:80px;border:0;outline:0'>")
-          .appendTo($wrapper);
-
-      $("<DIV style='text-align:right'><BUTTON class='btn btn-primary fa fa-lg fa-save long_text_editor pg-alertify-button'>Save</BUTTON>"
-         + "<BUTTON class='btn btn-danger fa fa-lg fa-times long_text_editor pg-alertify-button'>Cancel</BUTTON></DIV>")
-          .appendTo($wrapper);
-
-      $wrapper.find("button:first").bind("click", this.save);
-      $wrapper.find("button:last").bind("click", this.cancel);
-      $input.bind("keydown", this.handleKeyDown);
-
-      scope.position(args.position);
-      $input.focus().select();
-    };
-
-    this.handleKeyDown = function (e) {
-      if (e.which == $.ui.keyCode.ENTER && e.ctrlKey) {
-        scope.save();
-      } else if (e.which == $.ui.keyCode.ESCAPE) {
-        e.preventDefault();
-        scope.cancel();
-      } else if (e.which == $.ui.keyCode.TAB && e.shiftKey) {
-        e.preventDefault();
-        args.grid.navigatePrev();
-      } else if (e.which == $.ui.keyCode.TAB) {
-        e.preventDefault();
-        args.grid.navigateNext();
-      }
-    };
-
-    this.save = function () {
-      args.commitChanges();
-    };
-
-    this.cancel = function () {
-      $input.val(defaultValue);
-      args.cancelChanges();
-    };
-
-    this.hide = function () {
-      $wrapper.hide();
-    };
-
-    this.show = function () {
-      $wrapper.show();
-    };
-
-    this.position = function (position) {
-      var _elem_height = $wrapper.parent().find('#datagrid').height(),
-      is_hidden, _position;
-      // We can not display editor partially visible so we will lift it above select column
-      if(position.top > _elem_height) {
-        is_hidden = position.bottom - _elem_height;
-      }
-
-      if(is_hidden) {
-        _position = position.top - is_hidden;
-      } else {
-        _position = position.top - 5;
-      }
-
-      $wrapper
-          .css("top", position.top - 5)
-          .css("left", position.left - 5)
-    };
-
-    this.destroy = function () {
-      $wrapper.remove();
-    };
-
-    this.focus = function () {
-      $input.focus();
-    };
-
-    this.loadValue = function (item) {
-      var data = defaultValue = item[args.column.field];
-      if (typeof data === "object" && !Array.isArray(data)) {
-        data = JSON.stringify(data);
-      } else if (Array.isArray(data)) {
-        var temp = [];
-        $.each(data, function(i, val) {
-          if (typeof val === "object") {
-            temp.push(JSON.stringify(val));
-          } else {
-            temp.push(val)
-          }
-        });
-        data = "[" + temp.join() + "]";
-      }
-      $input.val(data);
-      $input.select();
-    };
-
-    this.serializeValue = function () {
-      if ($input.val() === "") {
-        return null;
-      }
-      return $input.val();
-    };
-
-    this.applyValue = function (item, state) {
-      item[args.column.field] = state;
-    };
-
-    this.isValueChanged = function () {
-      return (!($input.val() == "" && defaultValue == null)) && ($input.val() != defaultValue);
-    };
-
-    this.validate = function () {
-      if (args.column.validator) {
-        var validationResults = args.column.validator($input.val());
-        if (!validationResults.valid) {
-          return validationResults;
-        }
-      }
-
-      return {
-        valid: true,
-        msg: null
-      };
-    };
-
-    this.init();
-  }
-
-  // Text data type editor
-  function ReadOnlypgTextEditor(args) {
-    var $input, $wrapper;
-    var defaultValue;
-    var scope = this;
-
-    this.init = function () {
-      var $container = $("body");
-
-      $wrapper = $("<DIV style='z-index:10000;position:absolute;background:white;padding:5px;border:3px solid gray; -moz-border-radius:10px; border-radius:10px;'/>")
-          .appendTo($container);
-
-      $input = $("<TEXTAREA hidefocus rows=5 style='backround:white;width:250px;height:80px;border:0;outline:0' readonly>")
-          .appendTo($wrapper);
-
-      $("<DIV style='text-align:right'><BUTTON class='btn btn-primary fa fa-lg fa-times long_text_editor pg-alertify-button'>Close</BUTTON></DIV>")
-       .appendTo($wrapper);
-
-      $wrapper.find("button:first").bind("click", this.cancel);
-      $input.bind("keydown", this.handleKeyDown);
-
-      scope.position(args.position);
-      $input.focus().select();
-    };
-
-    this.handleKeyDown = function (e) {
-      if (e.which == $.ui.keyCode.ENTER && e.ctrlKey) {
-        scope.cancel();
-      } else if (e.which == $.ui.keyCode.ESCAPE) {
-        e.preventDefault();
-        scope.cancel();
-      } else if (e.which == $.ui.keyCode.TAB && e.shiftKey) {
-        scope.cancel();
-        e.preventDefault();
-        args.grid.navigatePrev();
-      } else if (e.which == $.ui.keyCode.TAB) {
-        scope.cancel();
-        e.preventDefault();
-        args.grid.navigateNext();
-      }
-    };
-
-    this.cancel = function () {
-      $input.val(defaultValue);
-      args.cancelChanges();
-    };
-
-    this.hide = function () {
-      $wrapper.hide();
-    };
-
-    this.show = function () {
-      $wrapper.show();
-    };
-
-    this.position = function (position) {
-      var _elem_height = $wrapper.parent().find('#datagrid').height(),
-        is_hidden, _position;
-      // We can not display editor partially visible so we will lift it above select column
-      if(position.top > _elem_height) {
-        is_hidden = position.bottom - _elem_height;
-      }
-
-      if(is_hidden) {
-        _position = position.top - is_hidden;
-      } else {
-        _position = position.top - 5;
-      }
-
-      $wrapper
-          .css("top", _position)
-          .css("left", position.left - 5)
-    };
-
-    this.destroy = function () {
-      $wrapper.remove();
-    };
-
-    this.focus = function () {
-      $input.focus();
-    };
-
-    this.loadValue = function (item) {
-      $input.val(defaultValue = item[args.column.field]);
-      $input.select();
-    };
-
-    this.serializeValue = function () {
-      return $input.val();
-    };
-
-    this.applyValue = function (item, state) {
-      item[args.column.field] = state;
-    };
-
-    this.isValueChanged = function () {
-      return (!($input.val() == "" && defaultValue == null)) && ($input.val() != defaultValue);
-    };
-
-    this.validate = function () {
-      if (args.column.validator) {
-        var validationResults = args.column.validator($input.val());
-        if (!validationResults.valid) {
-          return validationResults;
-        }
-      }
-
-      return {
-        valid: true,
-        msg: null
-      };
-    };
-
-    this.init();
-  }
-
-  /* Override CheckboxEditor to implement checkbox with three states.
-   * 1) checked=true
-   * 2) unchecked=false
-   * 3) indeterminate=null/''
-   */
-  function CheckboxEditor(args) {
-    var $select, el;
-    var defaultValue;
-    var scope = this;
-
-    this.init = function () {
-      $select = $("<INPUT type=checkbox value='true' class='editor-checkbox' hideFocus>");
-      $select.appendTo(args.container);
-      $select.focus();
-
-      // The following code is taken from https://css-tricks.com/indeterminate-checkboxes/
-      $select.data('checked', 0).bind("click", function (e) {
-        el = $(this);
-        switch(el.data('checked')) {
-          // unchecked, going indeterminate
-          case 0:
-            el.data('checked', 1);
-            el.prop('indeterminate', true);
-            break;
-
-          // indeterminate, going checked
-          case 1:
-            el.data('checked', 2);
-            el.prop('indeterminate', false);
-            el.prop('checked', true);
-            break;
-
-          // checked, going unchecked
-          default:
-            el.data('checked', 0);
-            el.prop('indeterminate', false);
-            el.prop('checked', false);
-        }
-      });
-    };
-
-    this.destroy = function () {
-      $select.remove();
-    };
-
-    this.focus = function () {
-      $select.focus();
-    };
-
-    this.loadValue = function (item) {
-      defaultValue = item[args.column.field];
-      if (_.isNull(defaultValue)) {
-        $select.prop('indeterminate', true);
-      }
-      else {
-        defaultValue = !!item[args.column.field];
-        if (defaultValue) {
-          $select.prop('checked', true);
-        } else {
-          $select.prop('checked', false);
-        }
-      }
-    };
-
-    this.serializeValue = function () {
-      if ($select.prop('indeterminate')) {
-        return null;
-      }
-      return $select.prop('checked');
-    };
-
-    this.applyValue = function (item, state) {
-      item[args.column.field] = state;
-    };
-
-    this.isValueChanged = function () {
-      return (this.serializeValue() !== defaultValue);
-    };
-
-    this.validate = function () {
-      return {
-        valid: true,
-        msg: null
-      };
-    };
-
-    this.init();
-  }
-
-  // JSON data type editor
-  function ReadOnlyJsonTextEditor(args) {
-    var $input, $wrapper;
-    var defaultValue;
-    var scope = this;
-
-    this.init = function () {
-      var $container = $("body");
-
-      $wrapper = $("<DIV style='z-index:10000;position:absolute;background:white;padding:5px;border:3px solid gray; -moz-border-radius:10px; border-radius:10px;'/>")
-          .appendTo($container);
-
-      $input = $("<TEXTAREA hidefocus rows=5 style='backround:white;width:250px;height:80px;border:0;outline:0' readonly>")
-          .appendTo($wrapper);
-
-      $("<DIV style='text-align:right'><BUTTON class='btn btn-primary fa fa-lg fa-times long_text_editor pg-alertify-button'>Close</BUTTON></DIV>")
-       .appendTo($wrapper);
-
-      $wrapper.find("button:first").bind("click", this.cancel);
-      $input.bind("keydown", this.handleKeyDown);
-
-      scope.position(args.position);
-      $input.focus().select();
-    };
-
-    this.handleKeyDown = function (e) {
-      if (e.which == $.ui.keyCode.ENTER && e.ctrlKey) {
-        scope.cancel();
-      } else if (e.which == $.ui.keyCode.ESCAPE) {
-        e.preventDefault();
-        scope.cancel();
-      } else if (e.which == $.ui.keyCode.TAB && e.shiftKey) {
-        scope.cancel();
-        e.preventDefault();
-        args.grid.navigatePrev();
-      } else if (e.which == $.ui.keyCode.TAB) {
-        scope.cancel();
-        e.preventDefault();
-        args.grid.navigateNext();
-      }
-    };
-
-    this.cancel = function () {
-      $input.val(defaultValue);
-      args.cancelChanges();
-    };
-
-    this.hide = function () {
-      $wrapper.hide();
-    };
-
-    this.show = function () {
-      $wrapper.show();
-    };
-
-    this.position = function (position) {
-      var _elem_height = $wrapper.parent().find('#datagrid').height(),
-        is_hidden, _position;
-      // We can not display editor partially visible so we will lift it above select column
-      if(position.top > _elem_height) {
-        is_hidden = position.bottom - _elem_height;
-      }
-
-      if(is_hidden) {
-        _position = position.top - is_hidden;
-      } else {
-        _position = position.top - 5;
-      }
-
-      $wrapper
-          .css("top", _position)
-          .css("left", position.left - 5)
-    };
-
-    this.destroy = function () {
-      $wrapper.remove();
-    };
-
-    this.focus = function () {
-      $input.focus();
-    };
-
-    this.loadValue = function (item) {
-      var data = defaultValue = item[args.column.field];
-      if (typeof data === "object" && !Array.isArray(data)) {
-        data = JSON.stringify(data);
-      } else if (Array.isArray(data)) {
-        var temp = [];
-        $.each(data, function(i, val) {
-          if (typeof val === "object") {
-            temp.push(JSON.stringify(val));
-          } else {
-            temp.push(val)
-          }
-        });
-        data = "[" + temp.join() + "]";
-      }
-      $input.val(data);
-      $input.select();
-    };
-
-    this.serializeValue = function () {
-      return $input.val();
-    };
-
-    this.applyValue = function (item, state) {
-      item[args.column.field] = state;
-    };
-
-    this.isValueChanged = function () {
-      return (!($input.val() == "" && defaultValue == null)) && ($input.val() != defaultValue);
-    };
-
-    this.validate = function () {
-      if (args.column.validator) {
-        var validationResults = args.column.validator($input.val());
-        if (!validationResults.valid) {
-          return validationResults;
-        }
-      }
-
-      return {
-        valid: true,
-        msg: null
-      };
-    };
-
-    this.init();
-  }
-
-  function ReadOnlyTextEditor(args) {
-    var $input;
-    var defaultValue;
-    var scope = this;
-
-    this.init = function () {
-      $input = $("<INPUT type=text class='editor-text' readonly/>")
-          .appendTo(args.container)
-          .bind("keydown.nav", function (e) {
-            if (e.keyCode === $.ui.keyCode.LEFT || e.keyCode === $.ui.keyCode.RIGHT) {
-              e.stopImmediatePropagation();
-            }
-          })
-          .focus()
-          .select();
-    };
-
-    this.destroy = function () {
-      $input.remove();
-    };
-
-    this.focus = function () {
-      $input.focus();
-    };
-
-    this.getValue = function () {
-      return $input.val();
-    };
-
-    this.loadValue = function (item) {
-      var value = item[args.column.field];
-
-      // Check if value is null or undefined
-      if (value === undefined && typeof value === "undefined") {
-        value = ""
-      }
-      defaultValue = value;
-      $input.val(defaultValue);
-      $input[0].defaultValue = defaultValue;
-      $input.select();
-    };
-
-    this.serializeValue = function () {
-      return $input.val();
-    };
-
-    this.applyValue = function (item, state) {
-      item[args.column.field] = state;
-    };
-
-    this.isValueChanged = function () {
-      return (!($input.val() == "" && defaultValue == null)) && ($input.val() != defaultValue);
-    };
-
-    this.validate = function () {
-      if (args.column.validator) {
-        var validationResults = args.column.validator($input.val());
-        if (!validationResults.valid) {
-          return validationResults;
-        }
-      }
-
-      return {
-        valid: true,
-        msg: null
-      };
-    };
-
-    this.init();
-  }
-
-  function ReadOnlyCheckboxEditor(args) {
-    var $select, el;
-    var defaultValue;
-    var scope = this;
-
-    this.init = function () {
-      $select = $("<INPUT type=checkbox value='true' class='editor-checkbox' hideFocus disabled>");
-      $select.appendTo(args.container);
-      $select.focus();
-
-      // The following code is taken from https://css-tricks.com/indeterminate-checkboxes/
-      $select.data('checked', 0).bind("click", function (e) {
-        el = $(this);
-        switch(el.data('checked')) {
-          // unchecked, going indeterminate
-          case 0:
-            el.data('checked', 1);
-            el.prop('indeterminate', true);
-            break;
-
-          // indeterminate, going checked
-          case 1:
-            el.data('checked', 2);
-            el.prop('indeterminate', false);
-            el.prop('checked', true);
-            break;
-
-          // checked, going unchecked
-          default:
-            el.data('checked', 0);
-            el.prop('indeterminate', false);
-            el.prop('checked', false);
-        }
-      });
-    };
-
-    this.destroy = function () {
-      $select.remove();
-    };
-
-    this.focus = function () {
-      $select.focus();
-    };
-
-    this.loadValue = function (item) {
-      defaultValue = item[args.column.field];
-      if (_.isNull(defaultValue)) {
-        $select.prop('indeterminate', true);
-      }
-      else {
-        defaultValue = !!item[args.column.field];
-        if (defaultValue) {
-          $select.prop('checked', true);
-        } else {
-          $select.prop('checked', false);
-        }
-      }
-    };
-
-    this.serializeValue = function () {
-      if ($select.prop('indeterminate')) {
-        return null;
-      }
-      return $select.prop('checked');
-    };
-
-    this.applyValue = function (item, state) {
-      item[args.column.field] = state;
-    };
-
-    this.isValueChanged = function () {
-      return (this.serializeValue() !== defaultValue);
-    };
-
-    this.validate = function () {
-      return {
-        valid: true,
-        msg: null
-      };
-    };
-
-    this.init();
-  }
-
-  function CustomNumberEditor(args) {
-    var $input;
-    var defaultValue;
-    var scope = this;
-
-    this.init = function () {
-      $input = $("<INPUT type=text class='editor-text' />");
-
-      $input.bind("keydown.nav", function (e) {
-        if (e.keyCode === $.ui.keyCode.LEFT || e.keyCode === $.ui.keyCode.RIGHT) {
-          e.stopImmediatePropagation();
-        }
-      });
-
-      $input.appendTo(args.container);
-      $input.focus().select();
-    };
-
-    this.destroy = function () {
-      $input.remove();
-    };
-
-    this.focus = function () {
-      $input.focus();
-    };
-
-    this.loadValue = function (item) {
-      defaultValue = item[args.column.field];
-      $input.val(defaultValue);
-      $input[0].defaultValue = defaultValue;
-      $input.select();
-    };
-
-    this.serializeValue = function () {
-      if ($input.val() === "") {
-        return null;
-      }
-      return $input.val();
-    };
-
-    this.applyValue = function (item, state) {
-      item[args.column.field] = state;
-    };
-
-    this.isValueChanged = function () {
-      return (!($input.val() == "" && defaultValue == null)) && ($input.val() != defaultValue);
-    };
-
-    this.validate = function () {
-      if (isNaN($input.val())) {
-        return {
-          valid: false,
-          msg: "Please enter a valid integer"
-        };
-      }
-
-      if (args.column.validator) {
-        var validationResults = args.column.validator($input.val());
-        if (!validationResults.valid) {
-          return validationResults;
-        }
-      }
-
-      return {
-        valid: true,
-        msg: null
-      };
-    };
-
-    this.init();
-  }
-
-})(jQuery);
diff --git a/web/pgadmin/static/vendor/slickgrid/slick.pgadmin.formatters.js b/web/pgadmin/static/vendor/slickgrid/slick.pgadmin.formatters.js
deleted file mode 100644
index b066095..0000000
--- a/web/pgadmin/static/vendor/slickgrid/slick.pgadmin.formatters.js
+++ /dev/null
@@ -1,77 +0,0 @@
-/***
- * Contains pgAdmin4 related SlickGrid formatters.
- *
- * @module Formatters
- * @namespace Slick
- */
-
-(function ($) {
-  // register namespace
-  $.extend(true, window, {
-    "Slick": {
-      "Formatters": {
-        "JsonString": JsonFormatter,
-        "Numbers": NumbersFormatter,
-        "Checkmark": CheckmarkFormatter,
-        "Text": TextFormatter,
-      }
-    }
-  });
-
-  function JsonFormatter(row, cell, value, columnDef, dataContext) {
-    if (value == null || value === "") {
-      return "";
-    } else {
-      // Stringify only if it's json object
-      if (typeof value === "object" && !Array.isArray(value)) {
-        return JSON.stringify(value);
-      } else if (Array.isArray(value)) {
-        var temp = [];
-        $.each(value, function(i, val) {
-          if (typeof val === "object") {
-            temp.push(JSON.stringify(val));
-          } else {
-            temp.push(val)
-          }
-        });
-        return "[" + temp.join() + "]"
-      } else {
-        return value;
-      }
-    }
-  }
-
-  function NumbersFormatter(row, cell, value, columnDef, dataContext) {
-    if (_.isUndefined(value) || value === null) {
-      return "<span class='pull-right'>[null]</span>";
-    }
-    else if (value === "") {
-      return '';
-    }
-    else {
-      return "<span style='float:right'>" + value + "</span>";
-    }
-  }
-
-  function CheckmarkFormatter(row, cell, value, columnDef, dataContext) {
-    /* Checkbox has 3 states
-     * 1) checked=true
-     * 2) unchecked=false
-     * 3) indeterminate=null/''
-     */
-    if (value == null || value === "") {
-      return "<span class='pull-left'>[null]</span>";
-    }
-    return value ? "true" : "false";
-  }
-
-  function TextFormatter(row, cell, value, columnDef, dataContext) {
-    if (_.isUndefined(value) || value === null) {
-      return "<span class='pull-left'>[null]</span>";
-    }
-    else {
-      return value;
-    }
-  }
-
-})(jQuery);
diff --git a/web/pgadmin/tools/__init__.py b/web/pgadmin/tools/__init__.py
index 178f8d3..a81519c 100644
--- a/web/pgadmin/tools/__init__.py
+++ b/web/pgadmin/tools/__init__.py
@@ -15,8 +15,34 @@ from pgadmin.utils.ajax import bad_request
 
 MODULE_NAME = 'tools'
 
+class ToolsModule(PgAdminModule):
+    def get_own_javascripts(self):
+        from flask import url_for
+        return [{
+            'name': 'pgadmin-sqlfoldcode',
+            'path': url_for(
+                'static',
+                filename='js/codemirror/addon/fold/pgadmin-sqlfoldcode'
+            ),
+            'when': 'debugger'
+        },{
+            'name': 'slick.pgadmin.editors',
+            'path': url_for(
+                'static',
+                filename='js/slickgrid/slick.pgadmin.editors'
+            ),
+            'when': 'debugger'
+        },{
+            'name': 'slick.pgadmin.formatters',
+            'path': url_for(
+                'static',
+                filename='js/slickgrid/slick.pgadmin.formatters'
+            ),
+            'when': 'debugger'
+        }]
+
 # Initialise the module
-blueprint = PgAdminModule(MODULE_NAME, __name__)
+blueprint = ToolsModule(MODULE_NAME, __name__)
 
 
 @blueprint.route("/")
diff --git a/web/pgadmin/tools/debugger/templates/debugger/js/direct.js b/web/pgadmin/tools/debugger/templates/debugger/js/direct.js
index 442acf0..971b113 100644
--- a/web/pgadmin/tools/debugger/templates/debugger/js/direct.js
+++ b/web/pgadmin/tools/debugger/templates/debugger/js/direct.js
@@ -2,7 +2,7 @@ define(
   ['jquery', 'underscore', 'underscore.string', 'alertify', 'pgadmin','pgadmin.browser',
    'backbone', 'backgrid', 'codemirror', 'backform','pgadmin.tools.debugger.ui',
   'wcdocker', 'pgadmin.backform', 'pgadmin.backgrid', 'codemirror/addon/selection/active-line',
-  'codemirror/addon/fold/foldgutter', 'codemirror/addon/fold/foldcode', 'codemirror/addon/fold/pgadmin-sqlfoldcode'],
+  'codemirror/addon/fold/foldgutter', 'codemirror/addon/fold/foldcode', 'pgadmin-sqlfoldcode'],
   function($, _, S, Alertify, pgAdmin, pgBrowser, Backbone, Backgrid, CodeMirror, Backform, debug_function_again) {
 
   if (pgAdmin.Browser.tree != null) {
diff --git a/web/pgadmin/tools/sqleditor/templates/sqleditor/js/sqleditor.js b/web/pgadmin/tools/sqleditor/templates/sqleditor/js/sqleditor.js
index dd940b9..82e8ebe 100644
--- a/web/pgadmin/tools/sqleditor/templates/sqleditor/js/sqleditor.js
+++ b/web/pgadmin/tools/sqleditor/templates/sqleditor/js/sqleditor.js
@@ -7,15 +7,15 @@ define(
     'codemirror/addon/selection/active-line', 'codemirror/addon/fold/foldcode',
     'codemirror/addon/fold/foldgutter', 'codemirror/addon/hint/show-hint',
     'codemirror/addon/hint/sql-hint', 'pgadmin.file_manager',
-    'codemirror/addon/fold/pgadmin-sqlfoldcode',
+    'pgadmin-sqlfoldcode',
     'codemirror/addon/scroll/simplescrollbars',
     'codemirror/addon/dialog/dialog',
     'codemirror/addon/search/search',
     'codemirror/addon/search/searchcursor',
     'codemirror/addon/search/jump-to-line',
     'backgrid.sizeable.columns', 'slickgrid/slick.formatters',
-    'slickgrid/slick.pgadmin.formatters', 'slickgrid/slick.editors',
-    'slickgrid/slick.pgadmin.editors', 'slickgrid/plugins/slick.autotooltips',
+    'slick.pgadmin.formatters', 'slickgrid/slick.editors',
+    'slick.pgadmin.editors', 'slickgrid/plugins/slick.autotooltips',
     'slickgrid/plugins/slick.cellrangedecorator',
     'slickgrid/plugins/slick.cellrangeselector',
     'slickgrid/plugins/slick.cellselectionmodel',
