diff --git a/web/package.json b/web/package.json
index 9ec32d45..df303b03 100644
--- a/web/package.json
+++ b/web/package.json
@@ -126,6 +126,7 @@
     "react-dom": "^17.0.1",
     "react-select": "^4.2.1",
     "react-table": "^7.6.3",
+    "react-window": "^1.8.5",
     "select2": "^4.0.13",
     "shim-loader": "^1.0.1",
     "slickgrid": "git+https://github.com/6pac/SlickGrid.git#2.3.16",
diff --git a/web/pgadmin/browser/static/css/wizard.css b/web/pgadmin/browser/static/css/wizard.css
index 7ed0f34e..a671546c 100644
--- a/web/pgadmin/browser/static/css/wizard.css
+++ b/web/pgadmin/browser/static/css/wizard.css
@@ -83,3 +83,18 @@
   margin-top: 20px !important;
   margin-bottom: 10px !important;
 }
+
+.wizard {
+    width: 100%;
+    /*height: 550px;*/
+}
+
+.step {
+    height: inherit;
+    width: initial;
+}
+
+.wizard-footer {
+    border-top: 1px solid #dde0e6 !important;
+    padding: 0.5rem;
+}
diff --git a/web/pgadmin/browser/static/js/PgTable.jsx b/web/pgadmin/browser/static/js/PgTable.jsx
new file mode 100644
index 00000000..6c45c58a
--- /dev/null
+++ b/web/pgadmin/browser/static/js/PgTable.jsx
@@ -0,0 +1,272 @@
+/* eslint-disable react/display-name */
+/* eslint-disable react/prop-types */
+
+import React from 'react';
+import { useTable, useBlockLayout, useRowSelect, useSortBy, useResizeColumns, useFlexLayout } from 'react-table';
+import { FixedSizeList } from 'react-window';
+import { makeStyles } from '@material-ui/core/styles';
+import clsx from 'clsx';
+import PropTypes from 'prop-types';
+
+const useStyles = makeStyles((theme) => ({
+  root: {
+    display: 'flex',
+    flexDirection: 'column',
+    height: '100%',
+    ...theme.mixins.panelBorder,
+    backgroundColor: theme.palette.background.default,
+  },
+  table: {
+    borderSpacing: 0,
+    width: '100%',
+    overflow: 'hidden',
+    backgroundColor: theme.otherVars.tableBg,
+    ...theme.mixins.panelBorder,
+    //backgroundColor: theme.palette.background.default,
+  },
+
+  tableCell: {
+    margin: 0,
+    padding: theme.spacing(0.5),
+    ...theme.mixins.panelBorder.bottom,
+    ...theme.mixins.panelBorder.right,
+    position: 'relative',
+    overflow: 'hidden',
+    textOverflow: 'ellipsis',
+    whiteSpace: 'nowrap',
+  },
+  selectCell: {
+    textAlign: 'center'
+  },
+  tableCellHeader: {
+    fontWeight: theme.typography.fontWeightBold,
+    padding: theme.spacing(1, 0.5),
+    textAlign: 'left',
+    overflowY: 'auto',
+    overflowX: 'hidden',
+    alignContent: 'center',
+    ...theme.mixins.panelBorder.bottom,
+    ...theme.mixins.panelBorder.right,
+  },
+  resizer: {
+    display: 'inline-block',
+    width: '5px',
+    height: '100%',
+    position: 'absolute',
+    right: 0,
+    top: 0,
+    transform: 'translateX(50%)',
+    zIndex: 1,
+    touchAction: 'none',
+  },
+  cellIcon: {
+    paddingLeft: '1.5em',
+    height: 35
+  }
+}),
+);
+
+export default function pgTable({ columns, data, enableSelect, ...props }) {
+  // Use the state and functions returned from useTable to build your UI
+  const classes = useStyles();
+  const defaultColumn = React.useMemo(
+    () => ({
+      minWidth: 175,
+    }),
+    []
+  );
+
+  const scrollBarSize = React.useMemo(() => scrollbarWidth(), []);
+
+  const IndeterminateCheckbox = React.forwardRef(
+    ({ indeterminate, ...rest }, ref) => {
+      const defaultRef = React.useRef();
+      const resolvedRef = ref || defaultRef;
+
+      React.useImperativeHandle(ref, () => ({
+        getSelectedRows: () => selectedRowIds
+      }), [selectedRowIds]);
+
+
+      React.useEffect(() => {
+        resolvedRef.current.indeterminate = indeterminate;
+      }, [resolvedRef, indeterminate]);
+      return (
+        <>
+          <input type="checkbox" ref={resolvedRef} {...rest} />
+        </>
+      );
+    },
+  );
+
+  IndeterminateCheckbox.displayName = 'SelectCheckbox';
+
+  IndeterminateCheckbox.propTypes = {
+    indeterminate: PropTypes.bool,
+    rest: PropTypes.func,
+    getToggleAllRowsSelectedProps: PropTypes.func,
+    row: PropTypes.object,
+  };
+
+  const {
+    getTableProps,
+    getTableBodyProps,
+    headerGroups,
+    rows,
+    totalColumnsWidth,
+    prepareRow,
+    selectedFlatRows,
+    state: { selectedRowIds }
+  } = useTable(
+    {
+      columns,
+      data,
+      defaultColumn,
+      enableSelect,
+    },
+    useBlockLayout,
+    useSortBy,
+    useRowSelect,
+    useResizeColumns,
+    useFlexLayout,
+    hooks => {
+      hooks.visibleColumns.push(CLOUMNS => {
+        if (enableSelect) {
+          return [
+            // Let's make a column for selection
+            {
+              id: 'selection',
+              // The header can use the table's getToggleAllRowsSelectedProps method
+              // to render a checkbox
+              Header: ({ getToggleAllRowsSelectedProps }) => (
+                <div className={classes.selectCell}>
+                  <IndeterminateCheckbox {...getToggleAllRowsSelectedProps()} />
+                </div>
+              ),
+              // The cell can use the individual row's getToggleRowSelectedProps method
+              // to the render a checkbox
+              Cell: ({ row }) => (
+                <div className={classes.selectCell}>
+                  <IndeterminateCheckbox {...row.getToggleRowSelectedProps()} />
+                </div>
+              ),
+              sortble: false,
+              width: 50,
+              minWidth: 0,
+            },
+            ...CLOUMNS,
+          ];
+        } else {
+          return [...CLOUMNS];
+        }
+      });
+      hooks.useInstanceBeforeDimensions.push(({ headerGroups }) => {
+        // fix the parent group of the selection button to not be resizable
+        const selectionGroupHeader = headerGroups[0].headers[0];
+        selectionGroupHeader.resizable = false;
+      });
+    }
+  );
+
+  React.useEffect(() => {
+    if (props.setSelectedRows) {
+      props.setSelectedRows(selectedFlatRows);
+    }
+  }, [selectedRowIds]);
+
+  React.useEffect(() => {
+    if (props.getSelectedRows) {
+      props.getSelectedRows(selectedFlatRows);
+    }
+  }, [selectedRowIds]);
+
+
+  const RenderRow = React.useCallback(
+    ({ index, style }) => {
+      const row = rows[index];
+      prepareRow(row);
+      return (
+        <div
+          {...row.getRowProps({
+            style,
+          })}
+          className={classes.tr}
+        >
+          {row.cells.map((cell) => {
+            return (
+              <div key={cell.column.id} {...cell.getCellProps()} className={clsx(classes.tableCell, row.original.icon && row.original.icon[cell.column.id], row.original.icon[cell.column.id] && classes.cellIcon)} title={cell.value}>
+                {cell.render('Cell')}
+              </div>
+            );
+          })}
+        </div>
+      );
+    },
+    [prepareRow, rows, selectedRowIds]
+  );
+  // Render the UI for your table
+  return (
+    <div {...getTableProps()} className={classes.table}>
+      <div>
+        {headerGroups.map(headerGroup => (
+          <div key={''} {...headerGroup.getHeaderGroupProps()}>
+            {headerGroup.headers.map(column => (
+              <div key={column.id} {...column.getHeaderProps()} className={clsx(classes.tableCellHeader, column.className)}>
+                <div {...(column.sortble ? column.getSortByToggleProps() : {})}>
+                  {column.render('Header')}
+                  <span>
+                    {column.isSorted
+                      ? column.isSortedDesc
+                        ? ' 🔽'
+                        : ' 🔼'
+                      : ''}
+                  </span>
+                  {column.resizable &&
+                    <div
+                      {...column.getResizerProps()}
+                      className={classes.resizer}
+                    />}
+                </div>
+              </div>
+            ))}
+          </div>
+        ))}
+      </div>
+
+      <div {...getTableBodyProps()}>
+        <FixedSizeList
+          height={props?.height ? props.height : 400}
+          itemCount={rows.length}
+          itemSize={35}
+          width={rows.length * 35 > 385 ? totalColumnsWidth + scrollBarSize : totalColumnsWidth}
+          sorted={props?.sortOptions}
+        >
+          {RenderRow}
+        </FixedSizeList>
+      </div>
+    </div>
+
+
+
+  );
+}
+
+const scrollbarWidth = () => {
+  // thanks too https://davidwalsh.name/detect-scrollbar-width
+  const scrollDiv = document.createElement('div');
+  scrollDiv.setAttribute('style', 'width: 100px; height: 100px; overflow: scroll; position:absolute; top:-9999px;');
+  document.body.appendChild(scrollDiv);
+  const scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth;
+  document.body.removeChild(scrollDiv);
+  return scrollbarWidth;
+};
+
+pgTable.propTypes = {
+  stepId: PropTypes.number,
+  height: PropTypes.number,
+  className: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
+  children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]),
+  getToggleAllRowsSelectedProps: PropTypes.func,
+};
+
+
diff --git a/web/pgadmin/browser/static/js/WizardStep.jsx b/web/pgadmin/browser/static/js/WizardStep.jsx
new file mode 100644
index 00000000..8d842a6e
--- /dev/null
+++ b/web/pgadmin/browser/static/js/WizardStep.jsx
@@ -0,0 +1,44 @@
+import React from 'react';
+import { makeStyles } from '@material-ui/core/styles';
+import { Box } from '@material-ui/core';
+import clsx from 'clsx';
+import PropTypes from 'prop-types';
+const useStyles = makeStyles(() =>
+  ({
+    stepPanel: {
+      height: '100%',
+      width: '100%',
+      // paddingLeft: '2em',
+      minHeight: '100px',
+      // paddingTop: '1em',
+      paddingBottom: '1em',
+      paddingRight: '1em',
+      overflow: 'auto',
+    }
+  }));
+
+export default function WizardStep({stepId, className, ...props }) {
+  const classes = useStyles();
+
+  return (
+
+    <Box id={stepId} className={clsx(classes.stepPanel, className)} style={props?.height ? {height: props.height} : null}>
+      {
+        React.Children.map(props.children, (child) => {
+          return (
+            <>
+              {child}
+            </>
+          );
+        })
+      }
+    </Box>
+  );
+}
+
+WizardStep.propTypes = {
+  stepId: PropTypes.number,
+  height: PropTypes.number,
+  className: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
+  children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]),
+};
diff --git a/web/pgadmin/browser/static/js/WizardView.jsx b/web/pgadmin/browser/static/js/WizardView.jsx
new file mode 100644
index 00000000..85653ccf
--- /dev/null
+++ b/web/pgadmin/browser/static/js/WizardView.jsx
@@ -0,0 +1,189 @@
+import React from 'react';
+import { makeStyles } from '@material-ui/core/styles';
+import clsx from 'clsx';
+import FastForwardIcon from '@material-ui/icons/FastForward';
+import FastRewindIcon from '@material-ui/icons/FastRewind';
+import ChevronRightIcon from '@material-ui/icons/ChevronRight';
+import CheckIcon from '@material-ui/icons/Check';
+import { DefaultButton, PrimaryButton } from '../../../static/js/components/Buttons';
+import PropTypes from 'prop-types';
+import { Box } from '@material-ui/core';
+import gettext from 'sources/gettext';
+
+
+const useStyles = makeStyles((theme) =>
+  ({
+    root: {
+      display: 'flex',
+      flexDirection: 'column',
+      height: '100%',
+    },
+    rightPanel: {
+      position: 'relative',
+      minHeight: 100,
+      display: 'flex',
+      paddingLeft: '1.5em',
+      paddingTop: '0em',
+      flex: 5,
+      overflow: 'auto',
+      height: '100%'
+    },
+    leftPanel: {
+      display: 'flex',
+      // padding: '2em',
+      flexDirection: 'column',
+      alignItems: 'flex-start',
+      borderRight: '1px solid',
+      ...theme.mixins.panelBorder.right,
+      flex: 1.5
+    },
+    label: {
+      display: 'inline-block',
+      position: 'relative',
+      top: '20%'
+    },
+    labelArrow: {
+      display: 'inline-block',
+      position: 'relative',
+      top: '20%'
+      // verticalAlign: 'bottom'
+    },
+    stepLabel: {
+      padding: '1em',
+      display: 'inline-flex'
+    },
+    active: {
+      fontWeight: 600
+    },
+    activeIndex: {
+      backgroundColor: '#326690 !important',
+      color: '#fff'
+    },
+    stepIndex: {
+      padding: '0.5em 1em ',
+      width: '2.5em',
+      height: '2.5em',
+      borderRadius: '2em',
+      marginRight: '0.5em',
+      backgroundColor: '#ddd',
+      display: 'inline-block'
+    },
+    wizard: {
+      width: '100%',
+      height: '100%',
+      minHeight: 100,
+      display: 'flex',
+      flexWrap: 'wrap',
+    },
+    wizardFooter: {
+      borderTop: '1px solid #dde0e6 !important',
+      padding: '0.5rem',
+      display: 'flex',
+      flexDirection: 'row-reverse',
+      flex: 1
+    },
+    backButton: {
+
+      marginRight: theme.spacing(1),
+    },
+    instructions: {
+      marginTop: theme.spacing(1),
+      marginBottom: theme.spacing(1),
+    },
+    actionBtn: {
+      alignItems: 'flex-start',
+    },
+    buttonMargin: {
+      marginLeft: '0.5em'
+    },
+    stepDefaultStyle: {
+      width: '100%',
+      height: '100%'
+    }
+
+  }),
+);
+
+function Wizard({ stepList, onStepChange, onSave, className, ...props }) {
+  const classes = useStyles();
+  const [activeStep, setActiveStep] = React.useState(0);
+  const steps = stepList && stepList.length > 0 ? stepList : [];
+  const [disableNext, setdisableNext] = React.useState(false);
+
+
+  const handleNext = () => {
+    setActiveStep((prevActiveStep) => prevActiveStep + 1);
+  };
+
+  const handleBack = () => {
+    setActiveStep((prevActiveStep) => prevActiveStep - 1 < 0 ? prevActiveStep : prevActiveStep - 1);
+  };
+
+  React.useEffect(() => {
+    if (onStepChange) {
+      onStepChange({ currentStep: activeStep });
+    }
+  }, [activeStep]);
+
+  React.useEffect(() => {
+    if (props.disableNextStep) {
+      setdisableNext(props.disableNextStep());
+    }
+  });
+
+
+  return (
+    <div className={classes.root}>
+      <div className={clsx(classes.wizard, className)}>
+        <Box className={classes.leftPanel}>
+          {steps.map((label, index) => (
+            <Box key={label} className={clsx(classes.stepLabel, index === activeStep ? classes.active : '')}>
+              <Box className={clsx(classes.stepIndex, index === activeStep ? classes.activeIndex : '')}>{index + 1}</Box>
+              <Box className={classes.label}>{label} </Box>
+              <Box className={classes.labelArrow}>{index === activeStep ? <ChevronRightIcon /> : null}</Box>
+            </Box>
+          ))}
+        </Box>
+
+        <div className={clsx(classes.rightPanel, props.stepPanelCss)}>
+          {
+            React.Children.map(props.children, (child) => {
+              return (
+                <div hidden={child.props.stepId !== activeStep} className={clsx(child.props.className, classes.stepDefaultStyle)}>
+                  {child}
+                </div>
+              );
+            })
+          }
+
+        </div>
+      </div>
+      <div className={classes.wizardFooter}>
+        <Box className={classes.actionBtn} marginLeft="auto">
+          <DefaultButton onClick={handleBack} disabled={activeStep === 0} className={classes.buttonMargin} startIcon={<FastRewindIcon />}>
+            {gettext('Back')}
+          </DefaultButton>
+          <DefaultButton onClick={() => handleNext()} className={classes.buttonMargin} startIcon={<FastForwardIcon />} disabled={activeStep == steps.length - 1 || disableNext}>
+            {gettext('Next')}
+          </DefaultButton>
+          <PrimaryButton className={classes.buttonMargin} startIcon={<CheckIcon />} disabled={activeStep == steps.length - 1 ? false : true} onClick={onSave}>
+            {gettext('Finish')}
+          </PrimaryButton>
+        </Box>
+      </div>
+    </div>
+  );
+}
+
+export default Wizard;
+
+Wizard.propTypes = {
+  props: PropTypes.object,
+  stepList: PropTypes.array,
+  onSave: PropTypes.func,
+  onStepChange: PropTypes.func,
+  className: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
+  disableNextStep: PropTypes.func,
+  stepPanelCss: PropTypes.string,
+  children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]),
+};
diff --git a/web/pgadmin/browser/static/js/table.jsx b/web/pgadmin/browser/static/js/table.jsx
new file mode 100644
index 00000000..e69de29b
diff --git a/web/pgadmin/tools/grant_wizard/static/js/grant_wizard.js b/web/pgadmin/tools/grant_wizard/static/js/grant_wizard.js
index 4d19ec4b..827d0a44 100644
--- a/web/pgadmin/tools/grant_wizard/static/js/grant_wizard.js
+++ b/web/pgadmin/tools/grant_wizard/static/js/grant_wizard.js
@@ -6,6 +6,11 @@
 // This software is released under the PostgreSQL Licence
 //
 //////////////////////////////////////////////////////////////
+import React from 'react';
+import ReactDOM from 'react-dom';
+import Theme from 'sources/Theme';
+import GrantWizard from './grant_wizard_view';
+
 
 // Grant Wizard
 define([
@@ -28,134 +33,6 @@ define([
     return pgBrowser.GrantWizard;
   }
 
-  /**
-    It is sub model for field "Objects". It has fields
-    for database object types such as Schemas, Views and
-    Sequence etc.
-  */
-  var DatabaseObjectModel = pgNode.Model.extend({
-    defaults: {
-      selected: false,
-      icon: 'icon-unknown',
-      name: undefined,
-      name_with_args: undefined,
-      nspname: undefined,
-      proargs: undefined,
-      object_type: undefined,
-      object_id: undefined,
-    },
-    idAttribute: 'object_id', // to uniquely identify a model object
-    toJSON: function() {
-      var d = pgNode.Model.prototype.toJSON.apply(this);
-      delete d.icon;
-      return d;
-    },
-    parse: function(res) {
-
-      // Create unique object id
-      res.object_id = res.name_with_args;
-
-      // create name with args if its object is function
-      if (!_.isUndefined(res.object_type) &&
-        (res.object_type == 'Function' ||
-          res.object_type == 'Trigger Function' ||
-          res.object_type == 'Procedure'
-        ))
-        res.name_with_args = res.name + '(' + (typeof(res.proargs) != 'undefined' ? res.proargs : '') + ')';
-      else
-        res.name_with_args = res.name;
-
-      return res;
-    },
-
-    validate: function() {
-
-      /*
-       * Triggers error messages for object types "selected"
-       * if it is empty/undefined/null
-       */
-      var err = {},
-        errmsg,
-        node = this.get('objects').toJSON();
-      if (_.isEmpty(node)) {
-        err['selected'] = gettext('Please select any database object.');
-        errmsg = err['selected'];
-        this.errorModel.set('selected', errmsg);
-        return errmsg;
-      } else {
-        this.errorModel.unset('selected');
-      }
-      return null;
-    },
-  });
-
-  // Define columns for the Db Object Types grid
-  var columns = [{
-    name: 'selected',
-
-    /*
-    Override render method of Backgrid.Extension.SelectRowCell
-    class. It has an issue: It doesn't mark rows checked if we move to next
-    page and then go back to previous page. but it must show.
-    so we handle this case by overriding the render method.
-    */
-    cell: Backgrid.Extension.SelectRowCell.extend({
-      render: function() {
-
-        // Do not use parent's render function. It set's tabindex to -1 on
-        // checkboxes.
-
-        var col = this.column.get('name');
-        let id = `row-${_.uniqueId(col)}`;
-        this.$el.empty().append(`
-          <div class="custom-control custom-checkbox custom-checkbox-no-label">
-            <input tabindex="-1" type="checkbox" class="custom-control-input" id="${id}" />
-            <label class="custom-control-label" for="${id}">
-              <span class="sr-only">` + gettext('Select All') + `<span>
-            </label>
-          </div>
-        `);
-        this.delegateEvents();
-
-        if (this.model && this.model.has(col)) {
-          if (this.model.get(col)) {
-            this.$el.parent().toggleClass('selected', true);
-            this.model.trigger('backgrid:selected', this.model, true);
-          }
-        }
-        return this;
-      },
-    }),
-
-    headerCell: 'select-all',
-
-  }, {
-    name: 'object_type',
-    label: gettext('Object Type'),
-    editable: false,
-    cell: Backgrid.Cell.extend({
-      render: function() {
-
-        // Override render to add icon to Db Object column
-        Backgrid.Cell.prototype.render.apply(this, arguments);
-        this.$el.addClass(this.model.get('icon')).css({
-          'padding-left': '24px',
-        });
-
-        return this;
-      },
-    }),
-  }, {
-    name: 'nspname',
-    label: gettext('Schema'),
-    cell: 'string',
-    editable: false,
-  }, {
-    name: 'name_with_args',
-    label: gettext('Name'),
-    cell: 'string',
-    editable: false,
-  }];
 
   // Create an Object GrantWizard of pgBrowser class
   pgBrowser.GrantWizard = {
@@ -211,997 +88,66 @@ define([
         Alertify.dialog('wizardDialog', function factory() {
 
           // Generate wizard main container
-          var $container = $('<div class=\'wizard_dlg\'></div>');
+          var $container = $('<div class=\'wizard_dlg\' id=\'grantWizardDlg\'></div>');
           return {
-            main: function(title) {
-              this.set('title', title);
+            main: function () {
             },
-            setup: function() {
+            setup: function () {
               return {
                 // Set options for dialog
                 options: {
                   frameless: true,
                   resizable: true,
                   autoReset: false,
-                  maximizable: false,
-                  closable: false,
+                  maximizable: true,
+                  closable: true,
                   closableByDimmer: false,
-                  modal: false,
+                  modal: true,
                   pinnable: false,
+                  footerless: true
                 },
               };
             },
-            /**
-              Returns a Paginator Class Object which is again to be rendered
-
-              @class {Backgrid.Extension.Paginator}
-              @param {Backbone.Collection} coll - from which data is fetched
-              @return {Object} paginator
-            */
-            DbPaginator: function(coll) {
-              var paginator = this.paginator = new Backgrid.Extension.Paginator({
-                collection: coll,
-                windowSize: 8,
-              });
-              return paginator;
-            },
-
-            /**
-              Create new Filter which will filter the
-              rendered grid for Select Type Tabular Data
-              @param {Backbone.PageableCollection} coll
-            */
-            DbObjectFilter: function(coll) {
-              var clientSideFilter = this.clientSideFilter = new Backgrid.Extension.ClientSideFilter({
-                collection: coll,
-                placeholder: gettext('Search by object type or name'),
-
-                // The model fields to search for matches
-                fields: ['object_type', 'name'],
-
-                // How long to wait after typing has stopped before searching can start
-                wait: 150,
-              });
-              return clientSideFilter;
-            },
-
-            //Enable Disable Next button of PrivilegePage
-            updateButtons: function(modified) {
-              if (!modified)
-                $('.wizard-next').prop('disabled', true);
-              else
-                $('.wizard-next').prop('disabled', false);
-            },
-
-            /**
-              Callback called when an errorModel is set
-              with invalid value and errormsg is set into
-              status bar element and next button is disabled
-            */
-            onSessionInvalid: function(msg) {
-              $('.pg-prop-status-bar .alert-text').html(msg);
-              $('.pg-prop-status-bar').css('visibility', 'visible');
-
-              // Enable disable Next button
-              this.updateButtons(false);
-              return true;
-            },
-
-            /**
-              Callback called when anything is set into model
-              thus hide error msg element and enable next button
-              status bar element and next button is disabled
-            */
-            onSessionValidated: function(sessHasChanged) {
-              $('.pg-prop-status-bar .alert-text').empty();
-              $('.pg-prop-status-bar').css('visibility', 'hidden');
-
-              // Enable disable Next button
-              this.updateButtons(sessHasChanged);
-            },
-
-            /**
-              Remove/Delete objects, attributes
-              in wizard on wizard close or finish
-              to reclaim memory
-            */
-            releaseObjects: function() {
-              var self = this;
-
-              if (!_.isUndefined(self.dbObjectFilter)) {
-                self.dbObjectFilter.remove();
-                self.dbObjectFilter = undefined;
-              }
-
-              if (!_.isUndefined(self.clientSideFilter)) {
-                self.clientSideFilter.remove();
-                self.clientSideFilter = undefined;
-              }
-
-              // clear object priv array
-              if (!_.isNull(self.obj_priv) &&
-                !_.isUndefined(self.obj_priv)) {
-                self.obj_priv = [];
-                delete self.obj_priv;
-              }
-
-              // Delete Wizard Pages, clear model and cleanup view
-              if (!_.isUndefined(self.dbObjectTypePage) &&
-                !_.isNull(self.dbObjectTypePage)) {
-                if (!_.isUndefined(self.dbObjectTypePage.get('model')) &&
-                  !_.isNull(self.dbObjectTypePage.get('model'))) {
-                  self.dbObjectTypePage.get('model').clear();
-                  self.dbObjectTypePage.get('view').cleanup();
-                  self.dbObjectTypePage = undefined;
-                }
-              }
-
-              if (!_.isUndefined(self.privilegePage) &&
-                !_.isNull(self.privilegePage)) {
-                if (!_.isUndefined(self.privilegePage.get('model')) &&
-                  !_.isNull(self.privilegePage.get('model'))) {
-                  self.privilegePage.get('model').clear();
-                  self.privilegePage.get('view').cleanup();
-                  self.privilegePage = undefined;
-                }
-              }
-
-              if (!_.isUndefined(self.reviewSQLPage) &&
-                !_.isNull(self.reviewSQLPage)) {
-                if (!_.isUndefined(self.reviewSQLPage.get('model')) &&
-                  !_.isNull(self.reviewSQLPage.get('model'))) {
-                  self.reviewSQLPage.get('model').clear();
-                  self.reviewSQLPage = undefined;
-                }
-              }
-
-              // Remove Sql control
-              if (!_.isUndefined(self.sqlControl)) {
-                self.sqlControl.remove();
-              }
-
-              // Clear privModel
-              if (!_.isNull(self.privModel) &&
-                !_.isUndefined(self.privModel)) {
-                self.privModel.clear();
-              }
-
-              // Remove collection containing db object data
-              if (!_.isNull(self.coll) &&
-                !_.isUndefined(self.coll)) {
-                self.coll.reset();
-                self.coll = undefined;
-              }
-              // Delete Wizard
-              if (!_.isNull(self.wizard) &&
-                !_.isUndefined(self.wizard)) {
-                self.wizard.collection.reset();
-                self.wizard.curr_page = undefined;
-              }
-
-            },
-
-            /**
-              Every time a wizard is opened, this function
-              is called everytime. It has Wizard Pages which
-              are rendered by the Wizard Class:
-
-              @class {pgBrowser.WizardPage} dbObjectType1 - This page
-              @extends {Backbone.Model}
-              renders a grid of Database Object Types such as
-                Schemas, Views and Sequences etc.
-
-              @class {pgBrowser.WizardPage} WizardPage2 - This page
-              @extends {Backbone.Model}
-              adds Privilege Control which provides grant privileges
-              such as "Create, Insert, Delete, Update" so on the
-              database objects selected on Wizard Pages.
-
-              @class {pgBrowser.WizardPage} WizardPage3 - This page
-              displays the generated GRANT SQL query for the Db
-              objects selected with the specific privileges added to it.
-              @extends {Backbone.Model}
-
-              @class {Backbone.Collection} WizardCollection - It is the
-              collection of wizard pages
-
-              @class {pgBrowser.Wizard} wizard - Its task is:
-              - Create a Wizard
-              - Add Buttons, Callbacks to it.
-              - Render WizardPages
-              @extends {Backbone.View}
-
-            */
-            build: function() {
+            build: function () {
               this.elements.content.appendChild($container.get(0));
               Alertify.pgDialogBuild.apply(this);
-            },
-
-            //Returns list of Acls defined for nodes
-            get_json_data: function(gid, sid, did) {
-              return $.ajax({
-                async: false,
-                url: url_for(
-                  'grant_wizard.acl', {
-                    'sid': encodeURI(sid),
-                    'did': encodeURI(did),
-                  }
-                ),
-                dataType: 'json',
-              });
-
-            },
-
-            prepare: function() {
-              var that = this;
-              $container.empty().append('<div class=\'grant_wizard_container\'></div>');
-
-              // Define el for wizard view
-              var el = $('.grant_wizard_container');
-
-              // Extract the data from the selected tree node
               var t = pgBrowser.tree,
                 i = t.selected(),
                 d = this.d = i && i.length == 1 ? t.itemData(i) : undefined,
                 info = this.info = pgBrowser.Node.getTreeNodeHierarchy(i);
 
-              if(_.isUndefined(d))
-                return;
-              /**
-                Generate a URL using:
-                gid, did, sid(server id), node_id(node id),
-                node_(node name), node_type(node type)
-                and pass it to collection which will fetch Object Type properties.
-              */
-              var gid = info['server_group']._id,
-                sid = info.server._id,
-                did = info.database._id,
-                node_id = d._id,
-
-                /**
-                  get node name only. used in mapping with object types defined
-                  in allowed_acl.json
-                 */
-                node_type = d._type.replace('coll-', '').replace(
-                  'materialized_', ''
-                );
-
-              // Fetch privileges specific to nodes
-              var json_data = this.get_json_data(gid, sid, did);
-              var privDict = JSON.parse(json_data.responseText);
+              var sid = info.server._id,
+                did = info.database._id;
 
-              // Collection url to fetch database object types for objects field
-              var baseUrl = url_for(
-                  'grant_wizard.objects', {
-                    'sid': encodeURI(sid),
-                    'did': encodeURI(did),
-                    'node_id': encodeURI(node_id),
-                    'node_type': encodeURI(node_type),
-                  }),
-                // Model's save url
-                saveUrl = url_for(
-                  'grant_wizard.apply', {
-                    'sid': encodeURI(sid),
-                    'did': encodeURI(did),
-                  }),
-                Coll = Backbone.Collection.extend({
-                  model: DatabaseObjectModel,
-                  url: baseUrl,
-                }),
-                // Create instances of collection and filter
-                coll = this.coll = new Coll(),
-                self = this;
-
-              // Generate encoded url based on wizard type
-              this.msql_url = url_for(
-                'grant_wizard.modified_sql', {
-                  'sid': encodeURI(sid),
-                  'did': encodeURI(did),
-                });
-
-              coll.comparator = function(model) {
-                return model.get('object_type');
-              };
-
-              coll.sort();
-              this.dbObjectFilter = this.DbObjectFilter(coll);
-              coll.fullCollection = this.dbObjectFilter.shadowCollection;
-
-              /**
-                privArray holds objects selected which further helps
-                in creating privileges Model
-              */
-              self.privArray = [];
-
-              /**
-                Override backgrid listener "backgrid:selected" to
-                Add/Remove model to/from objects collection
-              */
-              coll.on('backgrid:selected', function(model, selected) {
-                model.set('selected', selected);
-                var object_type = model.get('object_type');
-                switch (object_type) {
-                case 'Function':
-                  object_type = 'function';
-                  break;
-                case 'Trigger Function':
-                  object_type = 'function';
-                  break;
-                case 'Procedure':
-                  object_type = 'procedure';
-                  break;
-                case 'Table':
-                  object_type = 'table';
-                  break;
-                case 'Sequence':
-                  object_type = 'sequence';
-                  break;
-                case 'View':
-                  object_type = 'table';
-                  break;
-                case 'Materialized View':
-                  object_type = 'table';
-                  break;
-                case 'Foreign Table':
-                  object_type = 'foreign_table';
-                  break;
-                case 'Package':
-                  object_type = 'package';
-                  break;
-                default:
-                  break;
+              setTimeout(function () {
+                if (document.getElementById('grantWizardDlg')) {
+                  ReactDOM.render(
+                    <Theme>
+                      <GrantWizard sid={sid} did={did} nodeInfo={info} nodeData={d} />
+                    </Theme>,
+                    document.getElementById('grantWizardDlg'));
                 }
+              }, 500);
 
-                /**
-                  if a row (checkbox) is checked, add that model
-                  into collection, when unchecked remove it from
-                  model.
-
-                  Also push/pop object type in/from privArray
-                */
-                if (selected) {
-                  if (_.indexOf(self.privArray, object_type) == -1)
-                    self.privArray.push(object_type);
-                  newModel.get('objects').add(model, {
-                    silent: true,
-                  });
-                } else {
-                  var idx = self.privArray.indexOf(object_type);
-                  if (idx != -1)
-                    self.privArray.splice(idx, 1);
-                  newModel.get('objects').remove(model);
-                }
-
-                // validate model on checkbox check/uncheck
-                var msg = model.validate.call(newModel);
-
-                /**
-                  If no object type is selected, set error msg
-                  and disable next button, else enable next button
-                */
-                if (msg)
-                  self.onSessionInvalid.call(self, msg);
-                else
-                  self.onSessionValidated.call(self, true);
-              });
-
-              /**
-                It is the main model with schema defined
-                Every time a new wizard is opened,
-                a new model should create.
-              */
-              var GrantWizardModel = pgNode.Model.extend({
-                defaults: {
-                  objects: undefined,
-                  acl: undefined,
-                },
-                schema: [{
-                  id: 'objects',
-                  label: gettext('Objects'),
-                  model: DatabaseObjectModel,
-                  type: 'collection',
-                  group: gettext('Objects'),
-                },
-                {
-                  id: 'acl',
-                  label: gettext('Privileges'),
-                  model: pgBrowser.Node.PrivilegeRoleModel,
-                  type: 'collection',
-                  canAdd: true,
-                  canDelete: true,
-                  control: 'unique-col-collection',
-                },
-                ],
-                urlRoot: saveUrl,
-              });
-
-              /**
-                Create instance of GrantWizard Model, provide urlRoot
-                node_info object, Generate fields objects
-              */
-              var newModel = new GrantWizardModel({}, {
-                node_info: info,
-              });
-
-              /**
-                Fetch data from server and set into grid
-                and show/hide progress bar
-              */
-              $('.wizard-progress-bar p').show();
-
-              var fetchAjaxHook = function() {
-                $('.wizard-progress-bar p').removeClass('alert-danger').addClass('alert-info');
-                $('.wizard-progress-bar p').text(gettext('Please wait while fetching records...'));
-                coll.fetch({
-                  success: function(c, xhr) {
-                    $('.wizard-progress-bar p').html('');
-                    $('.wizard-progress-bar').hide();
-                    c.set(xhr.result, {parse: true});
-                    // If some objects failed while fetching then we will notify the user
-                    if (xhr && xhr.info && xhr.info !== '') {
-                      $('.pg-prop-status-bar .alert-text').html(xhr.info);
-                      $('.pg-prop-status-bar').css('visibility', 'visible');
-                    }
-                  },
-                  error: function(model, xhr, options) {
-                    // If the main request fails as whole then
-                    $('.wizard-progress-bar p').removeClass('alert-info').addClass('alert-danger');
-                    $('.wizard-progress-bar p').text(gettext('Unable to fetch the database objects'));
-
-                    Alertify.pgNotifier(
-                      options.textStatus, xhr,
-                      gettext('Unable to fetch the database objects'),
-                      function(msg) {
-                        if(msg === 'CRYPTKEY_SET') {
-                          fetchAjaxHook();
-                        } else {
-                          $('.wizard-progress-bar p').removeClass('alert-info').addClass('alert-danger');
-                          $('.wizard-progress-bar p').text(msg);
-                        }
-                      }
-                    );
-                  },
-                  reset: true,
-                }, this);
-              };
-              fetchAjaxHook();
-
-              //////////////////////////////////////////////////////////////////////
-              //                                                                  //
-              //            Wizard Page for Db Object Type                        //
-              //                                                                  //
-              //////////////////////////////////////////////////////////////////////
-
-              /**
-                Create wizard page. It renders a grid of
-                Database Object Types such as
-                Schemas, Views and Sequences etc.
-                Set default values
-              */
-              var dbObjectTypePage = self.dbObjectTypePage = new pgBrowser.WizardPage({
-                id: 1,
-                page_title: gettext('Object Selection (step 1 of 3)'),
-                disable_prev: true,
-                disable_next: true,
-                show_description: '',
-                show_progress_bar: gettext('Please wait while fetching records...'),
-                model: newModel,
-                view: new(function() {
-
-                  // Set page Instance
-                  var pageView = this;
-
-                  _.extend(pageView, {
-
-                    // Remove grid if it is before render
-                    cleanup: function() {
-                      if (this.grid) {
-                        this.grid.remove();
-                        delete this.grid;
-                        this.grid = null;
-                      }
-
-                      // Remove grid element if exists
-                      if (this.el) {
-                        $(this.el).remove();
-                        delete this.el;
-                      }
-                    },
-
-                    // Delete grid before render
-                    grid: null,
-
-                    render: function() {
-
-                      // Create a grid container
-                      var gridBody =
-                        $(`
-                        <div class="db_objects_container pg-el-xs-12">
-                          <div class="db_objects_header d-flex py-1">
-                            <div>` + gettext('Please select the objects to grant privileges to from the list below.') + `</div>
-                            <div class="db_objects_filter ml-auto">
-                              <div class="input-group">
-                                <div class="input-group-prepend">
-                                  <span class="input-group-text fa fa-search" id="labelSearch"></span>
-                                </div>
-                                <input type="search" class="form-control" id="txtGridSearch" placeholder="` + gettext('Search') + '" aria-label="' + gettext('Search') + `" aria-describedby="labelSearch">
-                              </div>
-                            </div>
-                          </div>
-                          <div class="db_objects_grid"></div>
-                        </div>`);
-
-                      // Remove grid if exits before render
-                      if (this.grid) {
-                        this.cleanup();
-                      }
-
-                      // Initialize a new Grid instance
-                      this.grid = new Backgrid.Grid({
-                        columns: _.clone(columns),
-                        collection: coll,
-                        className: 'backgrid presentation table table-bordered table-hover object_type_table',
-                      });
-
-                      // Render selection Type grid and paginator
-                      gridBody.find('.db_objects_grid').append(this.grid.render().$el);
-
-                      // Render Search Filter
-                      self.clientSideFilter.setCustomSearchBox(gridBody.find('#txtGridSearch'));
-
-                      // Assign gridBody content to page element
-                      this.el = gridBody;
-
-                      /**
-                        Fetch selected models from collection and
-                        make rows checked in grid
-                      */
-                      newModel.get('objects').each(function(m) {
-                        var model = coll.get(m.get('object_id'));
-                        if (model) {
-                          coll.trigger('backgrid:selected', model, true);
-                        }
-                      });
-
-                      // Refresh grid to re render rows.
-                      coll.trigger('backgrid:refresh');
-
-                      return this;
-                    },
-                  });
-                }),
-
-                beforeNext: function(obj) {
-                  var ctx = this;
-                  obj.options.disable_next = true;
-
-                  /**
-                    Enable/Disable next button of privilegePage if objects
-                    are present in model
-                  */
-                  if (!_.isNull(newModel.get('acl')) &&
-                    !_.isUndefined(newModel.get('acl'))) {
-                    if (newModel.get('acl').length > 0)
-                      obj.collection.at(1).set('disable_next', false);
-                  }
-
-                  // Clean the view
-                  if (ctx.view) {
-                    ctx.view.cleanup();
-                    delete ctx.view;
-                    ctx.view = null;
-                  }
-                  return true;
-                },
-
-              });
-
-              //////////////////////////////////////////////////////////////////////
-              //                                                                  //
-              //            Wizard Page for Privilege Control                     //
-              //                                                                  //
-              //////////////////////////////////////////////////////////////////////
-
-              // Wizard for Privelege control
-              var privilegePage = self.privilegePage = new pgBrowser.WizardPage({
-                id: 2,
-                page_title: gettext('Privilege Selection (step 2 of 3)'),
-                show_description: gettext('Please add the required privileges for the selected objects.'),
-                disable_next: true,
-                model: newModel,
-
-                // Create a view function object
-                view: new(function() {
-                  var pageView = this;
-                  _.extend(pageView, {
-
-                    // Render Privelege control to generate its html markup
-                    render: function() {
-
-                      var obj_priv = [];
-                      self.privArray = _.uniq(self.privArray);
-                      _.each(self.privArray, function(priv) {
-                        self.obj_priv = obj_priv = _.union(obj_priv, privDict[priv].acl);
-                      });
-
-                      /**
-                        Define PrivModel and its instance.
-                        Privileges array is generated based on
-                        the type of nodes selected.
-                       */
-                      var PrivModel = pgNode.Model.extend({
-                        defaults: {
-                          acl: undefined,
-                        },
-                        schema: [{
-                          id: 'acl',
-                          label: gettext('Privileges'),
-                          model: pgBrowser.Node.PrivilegeRoleModel.extend({
-
-                            // privileges are selected based on node clicked
-                            privileges: obj_priv,
-                          }),
-                          uniqueCol: ['grantee', 'grantor'],
-                          editable: true,
-                          type: 'collection',
-                          canAdd: true,
-                          canDelete: true,
-                          control: 'unique-col-collection',
-                        } ],
-                      });
-
-                      /**
-                        When privelege control is re-rendered, in order to
-                        render privileges based on object type selected,
-                        delete privileges from privModel which are now not
-                        present in object privileges array(object_priv)
-                       */
-                      var data = {};
-                      if (self.privModel) {
-                        data = self.privModel.toJSON();
-                        var rolePrivs = data['acl'];
-                        if (!_.isUndefined(rolePrivs) && rolePrivs.length > 0) {
-                          for (var idx in rolePrivs) {
-                            var rolePriv = (rolePrivs[idx])['privileges'],
-                              removeIdx = [],
-                              j;
-
-                            for (j in rolePriv) {
-                              var p = rolePriv[j];
-                              if (_.indexOf(obj_priv, p['privilege_type']) == -1) {
-                                removeIdx.push(j);
-                              }
-                            }
-
-                            for (j in removeIdx) {
-                              rolePriv.splice(j, 1);
-                            }
-                          }
-                        } else {
-                          console.warn('Acls are not defined');
-                        }
-                      }
-
-                      // Instantiate privModel
-                      self.privModel = new PrivModel(data, {
-                        node_info: self.info,
-                      });
-
-                      /*
-                      To track changes into model, start new session
-                      and Add event listener for privileges control
-                      */
-                      self.privModel.startNewSession();
-                      self.privModel.on('pgadmin-session:valid', self.onSessionValidated.bind(self));
-                      self.privModel.on('pgadmin-session:invalid', self.onSessionInvalid.bind(self));
-
-                      /**
-                        Create Field Object which has properties like
-                        node_data, node_info which is required for rendering
-                        Privilege control
-                        */
-                      var fields = Backform.generateViewSchema(
-                        self.info, self.privModel, 'create', self.d._type, self.d
-                      );
-                      var privilegesField = new Backform.Field(fields[0].fields[0]);
-
-                      this.privControl = new(privilegesField.get('control'))({
-                        field: privilegesField,
-                        model: self.privModel,
-                      });
-
-                      return {
-                        el: this.privControl.render().$el,
-                      };
-                    },
-
-                    // Remove the privilege control
-                    cleanup: function() {
-                      if (this.privControl) {
-                        this.privControl.remove();
-                        delete this.privControl;
-                        this.privControl = null;
-                      }
-                    },
-                  });
-                }),
-
-                beforePrev: function(wizardObj) {
-
-                  // Remove the privilege control
-                  if (this.view) {
-                    this.view.cleanup();
-                    delete this.view;
-                    this.view = null;
-                  }
-
-                  /**
-                    Enable/Disable next button of DbObjectType page if objects
-                    are present in model
-                   */
-                  var objectsModel = newModel.get('objects');
-
-                  if (!_.isUndefined(objectsModel) && !_.isEmpty(objectsModel) &&
-                    objectsModel.length > 0) {
-                    wizardObj.collection.at(0).set('disable_next', false);
-
-                    // Don't show progress bar
-                    wizardObj.collection.at(0).set('show_progress_bar', '');
-                  }
-
-                  /**
-                    We're re-rendering the controls as they are deleted
-                    before heading to next page
-                    Refresh Backgrid to re-render the elements selected
-                    re-render Filter
-                  */
-                  newModel.trigger('backgrid:refresh', newModel, false);
-                  self.clientSideFilter.render();
-                  return true;
-                },
-
-                beforeNext: function() {
-                  return true;
-                },
-
-                onNext: function() {
-
-                  // Assign acls of privModel to main model newModel
-                  if (!_.isUndefined(self.privModel)) {
-                    newModel.set({
-                      'acl': self.privModel.get('acl'),
-                    });
-                  }
-
-                  // Remove the privilege control
-                  if (this.view) {
-                    this.view.cleanup();
-                    delete this.view;
-                    this.view = null;
-                  }
-
-                  // Enable finish button
-                  self.wizard.options.disable_finish = false;
-
-                  /**
-                    triggers to get SQL queries data to render
-                    into the reviewSQLPage
-                  */
-                  newModel.trigger('pgadmin-wizard:nextpage:sql', {
-                    'node_type': node_type,
-                  });
-                },
-              });
-
-
-              //////////////////////////////////////////////////////////////////////
-              //                                                                  //
-              //            Review SQL Query Page                                 //
-              //                                                                  //
-              //////////////////////////////////////////////////////////////////////
-
-              //Create SqlField Object
-              var sqlField = new Backform.Field({
-                  id: 'sqltab',
-                  label: gettext('Sql Tab'),
-
-                  /**
-                    Extend 'SqlTabControl' to define new
-                    function 'onWizardNextPageChange'
-                    which gets triggered on next button
-                    click to fetch generated SQL query
-                    for the selected db objects.
-                  */
-                  control: Backform.SqlTabControl.extend({
-                    initialize: function() {
-
-                      // Initialize parent class
-                      Backform.SqlTabControl.prototype.initialize.apply(this, arguments);
-
-                      this.msql_url = self.msql_url;
-
-                      // define trigger events for prev and next page
-                      this.model.on('pgadmin-wizard:nextpage:sql', this.onWizardNextPageChange, this);
-                      this.model.on('pgadmin-wizard:prevpage:sql', this.onWizardPrevPageChange, this);
-                    },
-
-                    // This method fetches the modified SQL for the wizard
-                    onWizardNextPageChange: function() {
-
-                      var ctx = this;
-
-                      // Fetches modified SQL
-                      $.ajax({
-                        url: this.msql_url,
-                        type: 'POST',
-                        cache: false,
-                        data: JSON.stringify(ctx.model.toJSON(true)),
-                        dataType: 'json',
-                        contentType: 'application/json',
-                      }).done(function(res) {
-                        ctx.sqlCtrl.clearHistory();
-                        ctx.sqlCtrl.setValue(res.data);
-                        ctx.sqlCtrl.refresh();
-                      }).fail(function() {
-                        ctx.model.trigger('pgadmin-view:msql:error');
-                      }).always(function() {
-                        ctx.model.trigger('pgadmin-view:msql:fetched');
-                      });
-                    },
-
-                    remove: function() {
-
-                      // Clear html dom elements of CodeMirror sql tab
-                      self.sqlControl.unbind(); // Unbind all local event bindings
-                      var cmElem = self.sqlControl.sqlCtrl.getWrapperElement();
-                      $(cmElem).remove();
-                      self.sqlControl.sqlCtrl = undefined;
-                    },
-
-                  }),
-                }),
-
-                /**
-                  Create sqlField view instance
-                  to render it into wizard page
-                */
-                sqlControl = self.sqlControl = new(sqlField.get('control'))({
-                  field: sqlField,
-                  model: newModel,
-                });
-
-              // Wizard for SQL tab control
-              var reviewSQLPage = self.reviewSQLPage = new pgBrowser.WizardPage({
-                id: 3,
-                page_title: gettext('Final (Review Selection) (step 3 of 3)'),
-                show_description: gettext('The SQL below will be executed on the ' +
-                  'database server to grant the selected privileges. ' +
-                  'Please click on <strong>Finish</strong> to complete the process.'),
-                model: newModel,
-                view: new(function() {
-
-                  // Render SqlTab control to generate its html markup
-                  var sqlCtrlHtml = sqlControl.render().$el;
-                  sqlCtrlHtml.addClass('h-100');
-                  this.render = function() {
-                    return {
-                      el: sqlCtrlHtml,
-                    };
-                  };
-                }),
-
-                beforePrev: function(wizardObj) {
-
-                  /**
-                    Enable next button if privilege
-                    model is not empty else disable
-                    next button
-                   */
-                  var aclModel = newModel.get('acl');
-
-                  if (!_.isUndefined(wizardObj.collection) &&
-                    wizardObj.collection.models.length > 0) {
-                    if (!_.isUndefined(aclModel) && !_.isEmpty(aclModel) &&
-                      aclModel.length > 0) {
-                      wizardObj.collection.at(1).set('disable_next', false);
-                    } else {
-                      wizardObj.collection.at(1).set('disable_next', true);
-                    }
-
-                    return true;
-                  }
-                },
-              });
-
-
-              // Create Wizard Collection of Wizard Pages
-              var WizardCollection = Backbone.Collection.extend({
-                model: pgBrowser.WizardPage,
-              });
-
-              // It holds all the wizard pages to be rendered
-              this.wizardCollection = new WizardCollection(
-                [dbObjectTypePage, privilegePage, reviewSQLPage]
-              );
-
-              /**
-                Create wizard which has following operations:
-                - renders wizard pages
-                - defines the first page to render in wizard
-                - Save the model on finishbutton
-                - Remove wizard on cancel button
-                */
-              self.wizard = new(pgBrowser.Wizard.extend({
-                options: {
-                  title: gettext('Grant Wizard'),
-                  /* Main Wizard Title */
-                  width: '',
-                  height: '',
-                  curr_page: 0,
-                  show_left_panel: false,
-                  show_header_cancel_btn: true,
-                  show_header_maximize_btn: true,
-                  disable_finish: true,
-                  dialog_api: that,
-                  wizard_help: url_for(
-                    'help.static', {
-                      'filename': 'grant_wizard.html',
-                    }
-                  ),
-                },
-
-                // Callback for finish button
-                onFinish: function() {
-                  var m = newModel,
-                    grant_data = m.toJSON('GET');
-
-                  // Save model
-                  if (grant_data && !_.isEmpty(grant_data) && !_.isUndefined(grant_data.objects)) {
-                    m.save({}, {
-                      attrs: grant_data,
-                      validate: false,
-                      cache: false,
-                      success: function() {
-
-                        // Release wizard objects
-                        self.releaseObjects();
-                        self.close();
-                      },
-                      error: function(model, jqxhr) {
-                        Alertify.pgNotifier(
-                          'error', jqxhr,
-                          gettext('Error saving properties')
-                        );
-
-                        // Release wizard objects
-                        self.releaseObjects();
-                        self.close();
-                      },
-                    });
-                  }
-                },
-
-                // Callback for cancel button
-                onCancel: function() {
-
-                  // Release wizard objects
-                  self.releaseObjects();
-                  self.close();
-                },
-              }))({
-                collection: this.wizardCollection,
-                el: el,
-                model: newModel,
-              });
-
-              // Render wizard
-              self.wizard.render();
             },
+            prepare: function () {
+              $container.empty().append('<div class=\'grant_wizard_container\'></div>');
+            },
+            hooks: {
+              // Triggered when the dialog is closed
+              onclose: function () {
+                // Clear the view and remove the react component.
+                return setTimeout((function () {
+                  ReactDOM.unmountComponentAtNode(document.getElementById('grantWizardDlg'));
+                  return Alertify.wizardDialog().destroy();
+                }), 500);
+              },
+            }
           };
         });
       }
       // Call Grant Wizard Dialog and set dimensions for wizard
-      Alertify.wizardDialog(true).resizeTo(pgBrowser.stdW.lg,pgBrowser.stdH.lg);
+      Alertify.wizardDialog('').resizeTo(pgBrowser.stdW.lg, pgBrowser.stdH.lg);
     },
   };
 
diff --git a/web/pgadmin/tools/grant_wizard/static/js/grant_wizard.ui.js b/web/pgadmin/tools/grant_wizard/static/js/grant_wizard.ui.js
new file mode 100644
index 00000000..ef23d7f9
--- /dev/null
+++ b/web/pgadmin/tools/grant_wizard/static/js/grant_wizard.ui.js
@@ -0,0 +1,35 @@
+import gettext from 'sources/gettext';
+import BaseUISchema from 'sources/SchemaView/base_schema.ui';
+
+export default class GrantWizardSchema extends BaseUISchema {
+  constructor(getPrivilegeRoleSchema, fieldOptions = {}, initValues) {
+    super({
+      oid: null,
+      privilege: [],
+      ...initValues
+    });
+
+    this.getPrivilegeRoleSchema = getPrivilegeRoleSchema;
+    this.fieldOptions = {
+      ...fieldOptions,
+    };
+
+  }
+
+  get idAttribute() {
+    return 'oid';
+  }
+
+  get baseFields() {
+    return [
+      {
+        id: 'privilege', label: gettext('Privileges'), type: 'collection',
+        schema: this.getPrivilegeRoleSchema(['a', 'r', 'w', 'd', 'D', 'x', 't', 'C', 'T', 'U', 'X']),
+        uniqueCol: ['grantee'],
+        editable: false, mode: ['create'],
+        canAdd: true, canDelete: true,
+      }
+    ];
+  }
+
+}
diff --git a/web/pgadmin/tools/grant_wizard/static/js/grant_wizard_view.jsx b/web/pgadmin/tools/grant_wizard/static/js/grant_wizard_view.jsx
new file mode 100644
index 00000000..98475f05
--- /dev/null
+++ b/web/pgadmin/tools/grant_wizard/static/js/grant_wizard_view.jsx
@@ -0,0 +1,214 @@
+/////////////////////////////////////////////////////////////
+//
+// pgAdmin 4 - PostgreSQL Tools
+//
+// Copyright (C) 2013 - 2021, The pgAdmin Development Team
+// This software is released under the PostgreSQL Licence
+//
+//////////////////////////////////////////////////////////////
+
+import gettext from 'sources/gettext';
+import url_for from 'sources/url_for';
+import React from 'react';
+import { Box } from '@material-ui/core';
+import Wizard from '../../../../browser/static/js/WizardView';
+import WizardStep from '../../../../browser/static/js/WizardStep';
+import PgTable from '../../../../browser/static/js/PgTable';
+import { getNodePrivilegeRoleSchema } from '../../../../browser/server_groups/servers/static/js/privilege.ui.js';
+import { InputSQL } from '../../../../static/js/components/FormComponents';
+import getApiInstance from '../../../../static/js/api_instance';
+import SchemaView from '../../../../static/js/SchemaView';
+import clsx from 'clsx';
+import Loader from 'sources/components/Loader';
+import GrantWizardSchema from './grant_wizard.ui';
+import Alertify from 'pgadmin.alertifyjs';
+import PropTypes from 'prop-types';
+
+
+export default function GrantWizard({ sid, did, nodeInfo, nodeData}) {
+  var columns = [
+    {
+
+      Header: 'Object Type',
+      accessor: 'object_type',
+      sortble: true,
+      resizable: true,
+    },
+    {
+      Header: 'Schema',
+      accessor: 'nspname',
+      sortble: true,
+      resizable: true,
+    },
+    {
+      Header: 'Name',
+      accessor: 'name',
+      sortble: true,
+      resizable: true,
+    }
+  ];
+  var steps = ['Select object', 'Privileges', 'SQL'];
+  const [selectedObject, setSelectedObject] = React.useState([]);
+  const [selectedAcl, setSelectedAcl] = React.useState({});
+  const [msqlData, setSQL] = React.useState('');
+  const [stepType, setStepType] = React.useState('');
+  const [grantWizardTitle, setgrantWizardTitle] = React.useState('Grant Wizard - ');
+  const [loaderText, setLoaderText] = React.useState('');
+  const [tablebData, setTableData] = React.useState([]);
+
+  const api = getApiInstance();
+  var selectedObjectTypes = new Set();
+
+  const validatePrivilege = () => {
+    var isValid = true;
+    selectedAcl.privilege.forEach((priv) => {
+      if ((_.isUndefined(priv.grantee) || _.isUndefined(priv.privileges) || priv.privileges.length === 0) && isValid) {
+        isValid = false;
+      }
+    });
+
+    return !isValid;
+  };
+
+  React.useEffect(() => {
+    setLoaderText('Loading...');
+    var node_type = nodeData._type.replace('coll-', '').replace(
+      'materialized_', ''
+    );
+    var _url = url_for(
+      'grant_wizard.objects', {
+        'sid': encodeURI(sid),
+        'did': encodeURI(did),
+        'node_id': encodeURI(nodeData._id),
+        'node_type': encodeURI(node_type),
+      });
+    api.get(_url)
+      .then(res => {
+        var data = res.data.result;
+        data.forEach(element => {
+          if (element.icon)
+            element['icon'] = {
+              'object_type': element.icon
+            };
+        });
+        setTableData(data);
+        setLoaderText('');
+      })
+      .catch(() => {
+        Alertify.error(gettext('Error while fetching grant wizard data.'));
+        setLoaderText('');
+      });
+  }, [nodeData]);
+
+  return (
+    <>
+      <Box className={clsx('ajs-header', 'grant-wizard-title')}>{grantWizardTitle}</Box>
+      <Loader message={loaderText} />
+      <Wizard stepList={steps} className={''} disableNextStep={() => {
+        return selectedObject.length > 0 && stepType === 'object_type' ? false : selectedAcl?.privilege?.length > 0 && stepType === 'privileges' ? validatePrivilege() : true;
+      }}
+      onStepChange={(data) => {
+        var stepName = '';
+
+        switch (data.currentStep) {
+        case 0:
+          stepName = 'Object selection';
+          setStepType('object_type');
+          break;
+        case 1:
+          stepName = 'Privilege selection';
+          setStepType('privileges');
+          break;
+        case 2:
+          setLoaderText('Loading SQL ...');
+          stepName = 'Final (Review selection)';
+
+          var msql_url = url_for(
+            'grant_wizard.modified_sql', {
+              'sid': encodeURI(sid),
+              'did': encodeURI(did),
+            });
+          var post_data = {
+            acl: selectedAcl.privilege,
+            objects: selectedObject
+          };
+          api.post(msql_url, post_data)
+            .then(res => {
+              setSQL(res.data.data);
+              setLoaderText('');
+            })
+            .catch(() => {
+              Alertify.error(gettext('Error while fetching SQL.'));
+            });
+          break;
+        default:
+          stepName = '';
+          setStepType('');
+        }
+        setgrantWizardTitle(`Grant Wizard - ${stepName} ( step ${data.currentStep + 1} of ${steps.length} )`);
+      }}
+      onSave={() => {
+        setLoaderText('Saving...');
+        var _url = url_for(
+          'grant_wizard.apply', {
+            'sid': encodeURI(sid),
+            'did': encodeURI(did),
+          });
+        const post_data = {
+          acl: selectedAcl.privilege,
+          objects: selectedObject
+        };
+        api.post(_url, post_data)
+          .then(() => {
+            setLoaderText('');
+            Alertify.wizardDialog().close();
+          })
+          .catch(() => {
+            setLoaderText('');
+            Alertify.error(gettext('Error while saving grant wizard data.'));
+          });
+      }}>
+
+        <WizardStep stepId={0} className={clsx('grant-wizard-step', 'step-panel-css')} >
+          <PgTable height={window.innerHeight - 371} sortOptions={[{ id: 'object_type', desc: true }]} columns={columns} data={tablebData} enableSelect={true} sortable={true}
+            getSelectedRows={(selRows) => {
+              var selObj = [];
+              if (selRows.length > 0) {
+                selRows.forEach((row) => {
+                  selectedObjectTypes.add(row.values.object_type);
+                  selObj.push(row.values);
+                });
+              }
+              setSelectedObject(selObj);
+            }}>
+          </PgTable>
+        </WizardStep>
+        <WizardStep stepId={1} className={clsx('grant-wizard-step', 'privilege-step')}>
+          <SchemaView
+            formType={'dialog'}
+            getInitData={()=>{}}
+            viewHelperProps={{ mode: 'create' }}
+            schema={new GrantWizardSchema((privileges) => getNodePrivilegeRoleSchema('', nodeInfo, nodeData, privileges))}
+            showFooter={false}
+            isTabView={false}
+            onDataChange={(isChanged, changedData) => {
+              setSelectedAcl(changedData);
+            }}
+          />
+        </WizardStep>
+        <WizardStep stepId={2} className={'grant-wizard-step'}>
+          <InputSQL onLable={true} className={'grant-wizard-sql'} readonly={true} value={msqlData.toString()}></InputSQL>
+        </WizardStep>
+      </Wizard>
+    </>
+  );
+}
+
+GrantWizard.propTypes = {
+  sid: PropTypes.string,
+  did: PropTypes.number,
+  nodeInfo: PropTypes.object,
+  nodeData: PropTypes.object,
+};
+
+
diff --git a/web/pgadmin/tools/grant_wizard/static/scss/_grant_wizard.scss b/web/pgadmin/tools/grant_wizard/static/scss/_grant_wizard.scss
index 185a2f69..1e5d390c 100644
--- a/web/pgadmin/tools/grant_wizard/static/scss/_grant_wizard.scss
+++ b/web/pgadmin/tools/grant_wizard/static/scss/_grant_wizard.scss
@@ -130,3 +130,37 @@
   width: 100%;
   height: 100%;
 }
+
+.grant-wizard-sql {
+  height: 100%;
+  width: 100%;
+}
+
+#grantWizardDlg {
+  padding-top: 3em;
+}
+
+.grant-wizard-title{
+  top: 0px !important;
+  opacity: 1 !important;
+  border-radius: 6px 6px 0px 0px !important;
+  margin: 0 !important;
+  width: 100%;
+}
+
+.grant-wizard-step {
+  height: 100%;
+}
+
+.grant-wizard-objcol {
+  min-width: 8em !important;
+  width: 8em !important;
+}
+
+.privilege-step {
+  height: 400px;;
+}
+
+.step-panel-css {
+  height: 500px;
+}
diff --git a/web/regression/javascript/grant_wizard/wizard_spec.js b/web/regression/javascript/grant_wizard/wizard_spec.js
new file mode 100644
index 00000000..5a1c5ba6
--- /dev/null
+++ b/web/regression/javascript/grant_wizard/wizard_spec.js
@@ -0,0 +1,58 @@
+/////////////////////////////////////////////////////////////
+//
+// pgAdmin 4 - PostgreSQL Tools
+//
+// Copyright (C) 2013 - 2021, The pgAdmin Development Team
+// This software is released under the PostgreSQL Licence
+//
+//////////////////////////////////////////////////////////////
+
+import jasmineEnzyme from 'jasmine-enzyme';
+import React from 'react';
+import '../helper/enzyme.helper';
+import { createMount } from '@material-ui/core/test-utils';
+import pgAdmin from 'sources/pgadmin';
+import { messages } from '../fake_messages';
+// import GrantWizard from '../../../pgadmin/tools/grant_wizard/static/js/grant_wizard_view';
+import Theme from 'sources/Theme';
+import Wizard from '../../../pgadmin/browser/static/js/WizardView';
+import WizardStep from '../../../pgadmin/browser/static/js/WizardStep';
+
+describe('Wizard', () => {
+  let mount;
+
+  /* Use createMount so that material ui components gets the required context */
+  /* https://material-ui.com/guides/testing/#api */
+  beforeAll(() => {
+    mount = createMount();
+  });
+
+  afterAll(() => {
+    mount.cleanUp();
+  });
+
+  beforeEach(() => {
+    jasmineEnzyme();
+    /* messages used by validators */
+    pgAdmin.Browser = pgAdmin.Browser || {};
+    pgAdmin.Browser.messages = pgAdmin.Browser.messages || messages;
+    pgAdmin.Browser.utils = pgAdmin.Browser.utils || {};
+  });
+
+  it('WizardPanel', () => {
+    mount(
+      <Theme>
+        <Wizard
+          stepList={['Test']}
+          onStepChange={()=> {}}
+          onSave={()=>{}}
+          className={''}
+          disableNextStep={()=>{return false;}}
+        >
+          <WizardStep stepId={0} className={''}>
+          </WizardStep>
+        </Wizard>
+      </Theme>);
+  });
+});
+
diff --git a/web/regression/javascript/schema_ui_files/grant_wizard.ui.spec.js b/web/regression/javascript/schema_ui_files/grant_wizard.ui.spec.js
new file mode 100644
index 00000000..662ede23
--- /dev/null
+++ b/web/regression/javascript/schema_ui_files/grant_wizard.ui.spec.js
@@ -0,0 +1,64 @@
+/////////////////////////////////////////////////////////////
+//
+// pgAdmin 4 - PostgreSQL Tools
+//
+// Copyright (C) 2013 - 2021, The pgAdmin Development Team
+// This software is released under the PostgreSQL Licence
+//
+//////////////////////////////////////////////////////////////
+
+import jasmineEnzyme from 'jasmine-enzyme';
+import React from 'react';
+import '../helper/enzyme.helper';
+import { createMount } from '@material-ui/core/test-utils';
+import pgAdmin from 'sources/pgadmin';
+import { messages } from '../fake_messages';
+import SchemaView from '../../../pgadmin/static/js/SchemaView';
+import BaseUISchema from 'sources/SchemaView/base_schema.ui';
+import GrantWizardSchema from '../../../pgadmin/tools/grant_wizard/static/js/grant_wizard.ui';
+
+
+class MockSchema extends BaseUISchema {
+  get baseFields() {
+    return [];
+  }
+}
+
+describe('GrantWizard', () => {
+  let mount;
+  let schemaObj = new GrantWizardSchema(
+    () => new MockSchema(),
+  );
+
+  /* Use createMount so that material ui components gets the required context */
+  /* https://material-ui.com/guides/testing/#api */
+  beforeAll(() => {
+    mount = createMount();
+  });
+
+  afterAll(() => {
+    mount.cleanUp();
+  });
+
+  beforeEach(() => {
+    jasmineEnzyme();
+    /* messages used by validators */
+    pgAdmin.Browser = pgAdmin.Browser || {};
+    pgAdmin.Browser.messages = pgAdmin.Browser.messages || messages;
+    pgAdmin.Browser.utils = pgAdmin.Browser.utils || {};
+  });
+
+  it('create', () => {
+    mount(<SchemaView
+      formType='dialog'
+      schema={schemaObj}
+      viewHelperProps={{
+        mode: 'create',
+      }}
+      onDataChange={() => { }}
+      showFooter={false}
+      isTabView={false}
+    />);
+  });
+});
+
