Browse Source

[home2] Introduce requirejs and add the assist panel

This breaks the sharing, it will be fixed later.
Johan Ahlen 10 years ago
parent
commit
46646310fd

+ 110 - 93
desktop/core/src/desktop/static/desktop/js/home2.vm.js

@@ -14,113 +14,130 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+(function (root, factory) {
+  if(typeof define === "function" && define.amd) {
+    define([
+      'knockout',
+      'desktop/js/assist/assistHelper',
+      'knockout-mapping'
+    ], factory);
+  } else {
+    root.HomeViewModel = factory(ko, assistHelper);
+  }
+}(this, function (ko, AssistHelper) {
 
-function HomeViewModel(data) {
-  var self = this;
-
-  self.documents = ko.observableArray();
-  self.path = ko.mapping.fromJS('/');
-  self.mkdirFormPath = ko.observable('');
-  self.deleteFormPath = ko.observable('');
-  self.shareFormDocId = ko.observable('');
-  self.exportFormDocIds = ko.observable('');
-
-  self.page = ko.observable(1);
-  self.documentsPerPage = ko.observable(50);
-
-  self.renderableDocuments = ko.computed(function () {
-    return self.documents().slice((self.page() * 1 - 1) * self.documentsPerPage(), (self.page() * self.documentsPerPage()) - 1);
-  });
+  function HomeViewModel(options) {
+    var self = this;
 
-  self.totalPages = ko.computed(function () {
-    return Math.ceil(self.documents().length / self.documentsPerPage());
-  });
+    self.assistHelper = AssistHelper.getInstance(options);
+    self.isLeftPanelVisible = ko.observable();
+    self.assistHelper.withTotalStorage('assist', 'assist_panel_visible', self.isLeftPanelVisible, true);
 
-  self.hasPrevious = ko.computed(function () {
-    return self.page() > 1;
-  });
+    self.documents = ko.observableArray([]);
+    self.path = ko.mapping.fromJS('/');
+    self.mkdirFormPath = ko.observable('');
+    self.deleteFormPath = ko.observable('');
+    self.shareFormDocId = ko.observable('');
+    self.exportFormDocIds = ko.observable('');
 
-  self.hasNext = ko.computed(function () {
-    return self.page() < self.totalPages();
-  });
+    self.page = ko.observable(1);
+    self.documentsPerPage = ko.observable(50);
 
-  self.page.subscribe(function (value) {
-    if (isNaN(value * 1)) {
-      self.page(1);
-    }
-    if (value > self.totalPages()) {
-      self.page(self.totalPages());
-    }
-    if (value < 1) {
-      self.page(1);
-    }
-  });
-
-  self.nextPage = function () {
-    if (self.hasNext()) {
-      self.page(self.page() + 1);
-    }
-  }
-
-  self.previousPage = function () {
-    if (self.hasPrevious()) {
-      self.page(self.page() - 1);
-    }
-  }
+    self.renderableDocuments = ko.computed(function () {
+      return self.documents().slice((self.page() * 1 - 1) * self.documentsPerPage(), (self.page() * self.documentsPerPage()) - 1);
+    });
 
-  self.documents.subscribe(function () {
-    self.page(1);
-  });
+    self.totalPages = ko.computed(function () {
+      return Math.ceil(self.documents().length / self.documentsPerPage());
+    });
 
+    self.hasPrevious = ko.computed(function () {
+      return self.page() > 1;
+    });
 
-  self.loadDocuments = function(path) {
-    $.get("/desktop/api2/docs2/", {
-     path: path
-    }, function(data) {
-      self.path(path);
-      self.documents(data.documents);
-    }).fail(function (xhr) {
-      $(document).trigger("error", xhr.responseText);
+    self.hasNext = ko.computed(function () {
+      return self.page() < self.totalPages();
     });
-  };
-
-  self.mkdir = function() {
-    $.post("/desktop/api2/doc/mkdir", {
-      parent_path: ko.mapping.toJSON(self.path),
-      name: ko.mapping.toJSON(self.mkdirFormPath)
-    }, function (data) {
-      if (data.status == 0) {
-        self.loadDocuments(self.path()); // TODO proper refresh
-        self.mkdirFormPath('');
+
+    self.page.subscribe(function (value) {
+      if (isNaN(value * 1)) {
+        self.page(1);
       }
-      else {
-        $(document).trigger("error", data.message);
+      if (value > self.totalPages()) {
+        self.page(self.totalPages());
+      }
+      if (value < 1) {
+        self.page(1);
       }
-    }).fail(function (xhr) {
-      $(document).trigger("error", xhr.responseText);
     });
-  };
-
-  self.deleteDocument = function() {
-    $.post("/desktop/api2/doc/delete", {
-      doc_id: ko.mapping.toJSON(self.deleteFormPath),
-      skip_trash: ko.mapping.toJSON(false)
-    }, function (data) {
-      if (data.status == 0) {
-        self.loadDocuments(self.path()); // TODO proper refresh
-        self.mkdirFormPath('');
+
+    self.nextPage = function () {
+      if (self.hasNext()) {
+        self.page(self.page() + 1);
       }
-      else {
-        $(document).trigger("error", data.message);
+    };
+
+    self.previousPage = function () {
+      if (self.hasPrevious()) {
+        self.page(self.page() - 1);
       }
-    }).fail(function (xhr) {
-      $(document).trigger("error", xhr.responseText);
+    };
+
+    self.documents.subscribe(function () {
+      self.page(1);
     });
-  };
 
-  self.exportDocuments = function() {
-    $('#export-documents').find('input[name=\'documents\']').val(ko.mapping.toJSON(self.exportFormDocIds().split(",")));
-    $('#export-documents').find('form').submit();
-  };
 
-}
+    self.loadDocuments = function(path) {
+      $.get("/desktop/api2/docs2/", {
+       path: path
+      }, function(data) {
+        self.path(path);
+        self.documents(data.documents);
+      }).fail(function (xhr) {
+        $(document).trigger("error", xhr.responseText);
+      });
+    };
+
+    self.mkdir = function() {
+      $.post("/desktop/api2/doc/mkdir", {
+        parent_path: ko.mapping.toJSON(self.path),
+        name: ko.mapping.toJSON(self.mkdirFormPath)
+      }, function (data) {
+        if (data.status == 0) {
+          self.loadDocuments(self.path()); // TODO proper refresh
+          self.mkdirFormPath('');
+        }
+        else {
+          $(document).trigger("error", data.message);
+        }
+      }).fail(function (xhr) {
+        $(document).trigger("error", xhr.responseText);
+      });
+    };
+
+    self.deleteDocument = function() {
+      $.post("/desktop/api2/doc/delete", {
+        doc_id: ko.mapping.toJSON(self.deleteFormPath),
+        skip_trash: ko.mapping.toJSON(false)
+      }, function (data) {
+        if (data.status == 0) {
+          self.loadDocuments(self.path()); // TODO proper refresh
+          self.mkdirFormPath('');
+        }
+        else {
+          $(document).trigger("error", data.message);
+        }
+      }).fail(function (xhr) {
+        $(document).trigger("error", xhr.responseText);
+      });
+    };
+
+    self.exportDocuments = function() {
+      $('#export-documents').find('input[name=\'documents\']').val(ko.mapping.toJSON(self.exportFormDocIds().split(",")));
+      $('#export-documents').find('form').submit();
+    };
+  }
+
+  return HomeViewModel;
+}));

+ 227 - 214
desktop/core/src/desktop/static/desktop/js/share2.vm.js

@@ -14,261 +14,274 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+(function (root, factory) {
+  if(typeof define === "function" && define.amd) {
+    define([
+      'knockout',
+      'knockout-mapping'
+    ], factory);
+  } else {
+    root.ShareViewModel = factory(ko);
+  }
+}(this, function (ko) {
 
-var shareViewModel;
-
-function ShareViewModel(updateDocF) {
-  var self = this;
+  function ShareViewModel(updateDocF) {
+    var self = this;
 
-  self.hasInitBeenCalled = false;
-  self.hasSetupBeenCalled = false;
+    self.hasInitBeenCalled = false;
+    self.hasSetupBeenCalled = false;
 
-  self.selectedPerm = ko.observable('read');
-  self.selectedPermLabel = ko.computed(function() {
-    if (self.selectedPerm() == 'write') {
-      return 'Modify';
-    } else {
-      return 'Read';
-    }
-  });
+    self.selectedPerm = ko.observable('read');
+    self.selectedPermLabel = ko.computed(function() {
+      if (self.selectedPerm() == 'write') {
+        return 'Modify';
+      } else {
+        return 'Read';
+      }
+    });
 
-  self.selectedDoc = ko.observable(ko.mapping.fromJS({
-    perms: {
-      read: {
-        users: [],
-        groups: []
-      },
-      write: {
-        users: [],
-        groups: []
+    self.selectedDoc = ko.observable(ko.mapping.fromJS({
+      perms: {
+        read: {
+          users: [],
+          groups: []
+        },
+        write: {
+          users: [],
+          groups: []
+        }
       }
+    }))
+
+    self.updateDoc = updateDocF
+
+    self.setDocId = function(docId) {
+      if (docId == -1) { return false; }
+      $.get('/desktop/api2/doc/get', { id : docId }, function (data) {
+        shareViewModel.selectedDoc(data);
+      }).fail(function (response) {
+        $(document).trigger("error", "There was an error processing your action: " + response.responseText);
+      });
     }
-  }))
+  }
 
-  self.updateDoc = updateDocF
 
-  self.setDocId = function(docId) {
-    if (docId == -1) { return false; }
-    $.get('/desktop/api2/doc/get', { id : docId }, function (data) {
-      shareViewModel.selectedDoc(data);
-    }).fail(function (response) {
-      $(document).trigger("error", "There was an error processing your action: " + response.responseText);
+  function openShareModal() {
+    $("#documentShareModal").modal("show");
+    setupSharing(function(){
+      $("#documentShareAddBtn").removeClass("disabled");
+      $("#documentShareCaret").removeClass("disabled");
+      $("#documentShareTypeahead").removeAttr("disabled");
+      $(".notpretty").each(function(){
+        $(this).text(prettifyUsername($(this).attr("data-id")));
+      });
     });
   }
-}
 
+  function isShared() {
+    if (!shareViewModel) { return false; }
+    read = shareViewModel.selectedDoc().perms.read;
+    return read.users.length + read.groups.length > 0
+  }
 
-function openShareModal() {
-  $("#documentShareModal").modal("show");
-  setupSharing(function(){
-    $("#documentShareAddBtn").removeClass("disabled");
-    $("#documentShareCaret").removeClass("disabled");
-    $("#documentShareTypeahead").removeAttr("disabled");
-    $(".notpretty").each(function(){
-      $(this).text(prettifyUsername($(this).attr("data-id")));
-    });
-  });
-}
-
-function isShared() {
-  if (!shareViewModel) { return false; }
-  read = shareViewModel.selectedDoc().perms.read;
-  return read.users.length + read.groups.length > 0
-}
-
-function prettifyUsername(userId) {
-  var _user = null;
-  if (self.hasSetupBeenCalled) {
-    for (var i = 0; i < JSON_USERS_GROUPS.users.length; i++) {
-      if (JSON_USERS_GROUPS.users[i].id == userId) {
-        _user = JSON_USERS_GROUPS.users[i];
+  function prettifyUsername(userId) {
+    var _user = null;
+    if (self.hasSetupBeenCalled) {
+      for (var i = 0; i < JSON_USERS_GROUPS.users.length; i++) {
+        if (JSON_USERS_GROUPS.users[i].id == userId) {
+          _user = JSON_USERS_GROUPS.users[i];
+        }
+      }
+      if (_user != null) {
+        return (_user.first_name != "" ? _user.first_name + " " : "") + (_user.last_name != "" ? _user.last_name + " " : "") + ((_user.first_name != "" || _user.last_name != "") ? "(" : "") + _user.username + ((_user.first_name != "" || _user.last_name != "") ? ")" : "");
       }
     }
-    if (_user != null) {
-      return (_user.first_name != "" ? _user.first_name + " " : "") + (_user.last_name != "" ? _user.last_name + " " : "") + ((_user.first_name != "" || _user.last_name != "") ? "(" : "") + _user.username + ((_user.first_name != "" || _user.last_name != "") ? ")" : "");
-    }
+    return "";
   }
-  return "";
-}
 
-function initSharing(id, updateFunc) {
-  if(! updateFunc) {
-    updateFunc = function () {}
-  }
-  shareViewModel = new ShareViewModel(updateFunc);
-  ko.applyBindings(shareViewModel, $(id)[0]);
-  shareViewModel.hasInitBeenCalled = true;
-  return shareViewModel;
-}
-
-function setupSharing(id, updateFunc) {
-  if (shareViewModel == null || !shareViewModel.hasInitBeenCalled) {
-    shareViewModel = initSharing(id, updateFunc);
+  function initSharing(id, updateFunc) {
+    if(! updateFunc) {
+      updateFunc = function () {}
+    }
+    shareViewModel = new ShareViewModel(updateFunc);
+    ko.applyBindings(shareViewModel, $(id)[0]);
+    shareViewModel.hasInitBeenCalled = true;
+    return shareViewModel;
   }
 
-  if (! self.hasSetupBeenCalled){
-    $.getJSON('/desktop/api/users/autocomplete', function (data) {
-      self.hasSetupBeenCalled = true;
-      JSON_USERS_GROUPS = data;
-      dropdown = [];
-      usermap = {};
-      groupmap = {};
-
-      $.each(JSON_USERS_GROUPS.users, function (i, user) {
-        var _display = prettifyUsername(user.id);
-        usermap[_display] = user;
-        dropdown.push(_display);
-      });
-
-      $.each(JSON_USERS_GROUPS.groups, function (i, group) {
-        groupmap[group.name] = group;
-        dropdown.push(group.name);
-      });
+  function setupSharing(id, updateFunc) {
+    if (shareViewModel == null || !shareViewModel.hasInitBeenCalled) {
+      shareViewModel = initSharing(id, updateFunc);
+    }
 
-      $("#documentShareTypeahead").typeahead({
-        source: function (query, process) {
-          process(dropdown);
-        },
-        matcher: function (item) {
-          if (item.toLowerCase().indexOf(this.query.trim().toLowerCase()) != -1) {
-            return true;
-          }
-        },
-        sorter: function (items) {
-          return items.sort();
-        },
-        highlighter: function (item) {
-          var _icon = "fa";
-          if (usermap[item]) {
-            _icon += " fa-user";
+    if (! self.hasSetupBeenCalled){
+      $.getJSON('/desktop/api/users/autocomplete', function (data) {
+        self.hasSetupBeenCalled = true;
+        JSON_USERS_GROUPS = data;
+        dropdown = [];
+        usermap = {};
+        groupmap = {};
+
+        $.each(JSON_USERS_GROUPS.users, function (i, user) {
+          var _display = prettifyUsername(user.id);
+          usermap[_display] = user;
+          dropdown.push(_display);
+        });
+
+        $.each(JSON_USERS_GROUPS.groups, function (i, group) {
+          groupmap[group.name] = group;
+          dropdown.push(group.name);
+        });
+
+        $("#documentShareTypeahead").typeahead({
+          source: function (query, process) {
+            process(dropdown);
+          },
+          matcher: function (item) {
+            if (item.toLowerCase().indexOf(this.query.trim().toLowerCase()) != -1) {
+              return true;
+            }
+          },
+          sorter: function (items) {
+            return items.sort();
+          },
+          highlighter: function (item) {
+            var _icon = "fa";
+            if (usermap[item]) {
+              _icon += " fa-user";
+            }
+            else {
+              _icon += " fa-users";
+            }
+            var regex = new RegExp('(' + this.query + ')', 'gi');
+            return "<i class='" + _icon + "'></i> " + item.replace(regex, "<strong>$1</strong>");
+          },
+          updater: function (item) {
+            selectedUserOrGroup = usermap[item] ? usermap[item] : groupmap[item];
+            return item;
           }
-          else {
-            _icon += " fa-users";
+        });
+
+        $("#documentShareTypeahead").on("keyup", function (e) {
+          var _code = (e.keyCode ? e.keyCode : e.which);
+          if (_code == 13) {
+            handleTypeaheadSelection();
           }
-          var regex = new RegExp('(' + this.query + ')', 'gi');
-          return "<i class='" + _icon + "'></i> " + item.replace(regex, "<strong>$1</strong>");
-        },
-        updater: function (item) {
-          selectedUserOrGroup = usermap[item] ? usermap[item] : groupmap[item];
-          return item;
+        });
+
+        if (typeof id == "function"){
+          id();
         }
+      }).fail(function (response) {
+        $(document).trigger("error", "There was an error processing your action: " + response.responseText);
       });
 
-      $("#documentShareTypeahead").on("keyup", function (e) {
-        var _code = (e.keyCode ? e.keyCode : e.which);
-        if (_code == 13) {
+      $("#documentShareAddBtn").on("click", function () {
+        if (! $(this).hasClass("disabled")){
           handleTypeaheadSelection();
         }
       });
-
+    }
+    else {
       if (typeof id == "function"){
         id();
       }
-    }).fail(function (response) {
-      $(document).trigger("error", "There was an error processing your action: " + response.responseText);
-    });
+    }
 
-    $("#documentShareAddBtn").on("click", function () {
-      if (! $(this).hasClass("disabled")){
-        handleTypeaheadSelection();
+    return shareViewModel;
+  }
+
+  function updateSharePerm(perms, user) {
+    $(perms).each(function (cnt, item) {
+      if (item.id == user.id) {
+        perms.splice(cnt, 1);
       }
     });
+    shareViewModel.selectedDoc.valueHasMutated();
+    shareDocFinal();
   }
-  else {
-    if (typeof id == "function"){
-      id();
-    }
+
+  function removeUserReadShare(user) {
+    updateSharePerm(shareViewModel.selectedDoc().perms.read.users, user);
   }
 
-  return shareViewModel;
-}
+  function removeUserWriteShare(user) {
+    updateSharePerm(shareViewModel.selectedDoc().perms.write.users, user);
+  }
 
-function updateSharePerm(perms, user) {
-  $(perms).each(function (cnt, item) {
-    if (item.id == user.id) {
-      perms.splice(cnt, 1);
-    }
-  });
-  shareViewModel.selectedDoc.valueHasMutated();
-  shareDocFinal();
-}
-
-function removeUserReadShare(user) {
-  updateSharePerm(shareViewModel.selectedDoc().perms.read.users, user);
-}
-
-function removeUserWriteShare(user) {
-  updateSharePerm(shareViewModel.selectedDoc().perms.write.users, user);
-}
-
-function removeGroupReadShare(group) {
-  updateSharePerm(shareViewModel.selectedDoc().perms.read.groups, group);
-}
-
-function removeGroupWriteShare(group) {
-  updateSharePerm(shareViewModel.selectedDoc().perms.write.groups, group);
-}
-
-function changeDocumentSharePerm(perm) {
-  shareViewModel.selectedPerm(perm);
-}
-
-function handleTypeaheadSelection() {
-  if (selectedUserOrGroup != null) {
-    if (selectedUserOrGroup.hasOwnProperty("username")) {
-      shareViewModel.selectedDoc().perms[shareViewModel.selectedPerm()].users.push(selectedUserOrGroup);
-    }
-    else {
-      shareViewModel.selectedDoc().perms[shareViewModel.selectedPerm()].groups.push(selectedUserOrGroup);
-    }
-    shareViewModel.selectedDoc.valueHasMutated();
-    shareDocFinal();
+  function removeGroupReadShare(group) {
+    updateSharePerm(shareViewModel.selectedDoc().perms.read.groups, group);
   }
-  selectedUserOrGroup = null;
-  $("#documentShareTypeahead").val("");
-}
-
-function shareDocFinal() {
-  var _postPerms = {
-    read: {
-      user_ids: [],
-      group_ids: []
-    },
-    write: {
-      user_ids: [],
-      group_ids: []
-    }
+
+  function removeGroupWriteShare(group) {
+    updateSharePerm(shareViewModel.selectedDoc().perms.write.groups, group);
+  }
+
+  function changeDocumentSharePerm(perm) {
+    shareViewModel.selectedPerm(perm);
   }
 
-  $(shareViewModel.selectedDoc().perms.read.users).each(function (cnt, item) {
-    _postPerms.read.user_ids.push(item.id);
-  });
-
-  $(shareViewModel.selectedDoc().perms.read.groups).each(function (cnt, item) {
-    _postPerms.read.group_ids.push(item.id);
-  });
-
-  $(shareViewModel.selectedDoc().perms.write.users).each(function (cnt, item) {
-    _postPerms.write.user_ids.push(item.id);
-  });
-
-  $(shareViewModel.selectedDoc().perms.write.groups).each(function (cnt, item) {
-    _postPerms.write.group_ids.push(item.id);
-  });
-
-  $.post("/desktop/api2/doc/share", {
-    doc_id: shareViewModel.selectedDoc().id,
-    data: JSON.stringify(_postPerms)
-  }, function (response) {
-    if (response != null) {
-      if (response.status != 0) {
-        $(document).trigger("error", "There was an error processing your action: " + response.message);
+  function handleTypeaheadSelection() {
+    if (selectedUserOrGroup != null) {
+      if (selectedUserOrGroup.hasOwnProperty("username")) {
+        shareViewModel.selectedDoc().perms[shareViewModel.selectedPerm()].users.push(selectedUserOrGroup);
       }
       else {
-        shareViewModel.updateDoc(response.doc);
+        shareViewModel.selectedDoc().perms[shareViewModel.selectedPerm()].groups.push(selectedUserOrGroup);
+      }
+      shareViewModel.selectedDoc.valueHasMutated();
+      shareDocFinal();
+    }
+    selectedUserOrGroup = null;
+    $("#documentShareTypeahead").val("");
+  }
+
+  function shareDocFinal() {
+    var _postPerms = {
+      read: {
+        user_ids: [],
+        group_ids: []
+      },
+      write: {
+        user_ids: [],
+        group_ids: []
       }
     }
-  }).fail(function (response) {
-    $(document).trigger("error", "There was an error processing your action: " + response.responseText);
-  });
-}
+
+    $(shareViewModel.selectedDoc().perms.read.users).each(function (cnt, item) {
+      _postPerms.read.user_ids.push(item.id);
+    });
+
+    $(shareViewModel.selectedDoc().perms.read.groups).each(function (cnt, item) {
+      _postPerms.read.group_ids.push(item.id);
+    });
+
+    $(shareViewModel.selectedDoc().perms.write.users).each(function (cnt, item) {
+      _postPerms.write.user_ids.push(item.id);
+    });
+
+    $(shareViewModel.selectedDoc().perms.write.groups).each(function (cnt, item) {
+      _postPerms.write.group_ids.push(item.id);
+    });
+
+    $.post("/desktop/api2/doc/share", {
+      doc_id: shareViewModel.selectedDoc().id,
+      data: JSON.stringify(_postPerms)
+    }, function (response) {
+      if (response != null) {
+        if (response.status != 0) {
+          $(document).trigger("error", "There was an error processing your action: " + response.message);
+        }
+        else {
+          shareViewModel.updateDoc(response.doc);
+        }
+      }
+    }).fail(function (response) {
+      $(document).trigger("error", "There was an error processing your action: " + response.responseText);
+    });
+  }
+
+  return {
+    initSharing: initSharing
+  }
+}));

+ 180 - 111
desktop/core/src/desktop/templates/home2.mako

@@ -18,66 +18,116 @@
   from django.utils.translation import ugettext as _
 %>
 
+<%namespace name="assist" file="/assist.mako" />
+<%namespace name="tableStats" file="/table_stats.mako" />
+<%namespace name="require" file="/require.mako" />
+
 ${ commonheader(_('Welcome Home'), "home", user) | n,unicode }
 
+${ require.config() }
+
+${ tableStats.tableStats() }
+${ assist.assistPanel() }
+
 <style type="text/css">
-  .sidebar-nav {
-    margin-bottom: 10px;
+
+  html {
+    height: 100%;
   }
 
-  .sidebar-nav img {
-    margin-right: 6px;
+  body {
+    height:100%;
+    margin: 0;
+    padding: 0;
+    background-color: #FFF;
   }
 
-  .sidebar-nav .dropdown-menu a {
-    padding-left: 6px;
+  .vertical-full {
+    height:100%;
   }
 
-  .tag {
-    float: left;
-    margin-right: 6px;
-    margin-bottom: 4px;
+  .main-content {
+    height: auto;
+    width: 100%;
+    position: absolute;
+    top: 82px;
+    bottom: 0;
+    background-color: #FFF;
   }
 
-  .tag-counter {
-    margin-top: 3px;
-    margin-right: 4px;
+  .panel-container {
+    position: relative;
   }
 
-  .toggle-tag, .document-tags-modal-checkbox, .tags-modal-checkbox {
-    cursor: pointer;
+  .left-panel {
+    position: absolute;
+    height: 100%;
+    overflow: auto;
   }
 
-  .badge-left {
-    border-radius: 9px 0px 0px 9px;
-    padding-right: 5px;
-    font-weight: normal;
+  .resizer {
+    position: absolute;
+    height: 100%;
+    width: 4px;
+    cursor: col-resize;
   }
 
-  .badge-right {
-    border-radius: 0px 9px 9px 0px;
-    padding-left: 5px;
+  .resize-bar {
+    position: absolute;
+    height: 100%;
+    width: 2px;
+    background-color: #F1F1F1;
   }
 
-  .badge-right:hover {
-    background-color: #b94a48;
+  .right-panel {
+    position: absolute;
+    height: 100%;
+    overflow: auto;
   }
 
-  .airy li {
-    margin-bottom: 6px;
+  .show-assist {
+    position: fixed;
+    top: 80px;
+    background-color: #FFF;
+    width: 16px;
+    height: 24px;
+    line-height: 24px;
+    margin-left: -2px;
+    text-align: center;
+    -webkit-border-top-right-radius: 3px;
+    -webkit-border-bottom-right-radius: 3px;
+    -moz-border-radius-topright: 3px;
+    -moz-border-radius-bottomright: 3px;
+    border-top-right-radius: 3px;
+    border-bottom-right-radius: 3px;
+    z-index: 1000;
+    -webkit-transition: margin-left 0.2s linear;
+    -moz-transition: margin-left 0.2s linear;
+    -ms-transition: margin-left 0.2s linear;
+    transition: margin-left 0.2s linear;
   }
 
-  .white {
-    padding: 9px 18px;
-    margin-top: 1px;
-    overflow: hidden;
-    font-size: 14px;
-    line-height: 1.4;
-    color: #737373;
-    text-overflow: ellipsis;
+  .show-assist:hover {
+    margin-left: 0;
   }
 
+  .hide-assist {
+    position: absolute;
+    top: 2px;
+    right: 4px;
+    z-index: 1000;
+    color: #D1D1D1;
+    font-size: 12px;
+    -webkit-transition: margin-right 0.2s linear, color 0.5s ease;
+    -moz-transition: margin-right 0.2s linear, color 0.5s ease;
+    -ms-transition: margin-right 0.2s linear, color 0.5s ease;
+    transition: margin-right 0.2s linear, color 0.5s ease;
+  }
 
+  .hide-assist:hover {
+    margin-right: 2px;
+    color: #338bb8;
+  }
 </style>
 
 <div class="navbar navbar-inverse navbar-fixed-top nokids">
@@ -97,47 +147,64 @@ ${ commonheader(_('Welcome Home'), "home", user) | n,unicode }
   </div>
 </div>
 
-<div id='documentList' class="container-fluid">
-  <div class="row-fluid">
-    <div class="span2">
-      <div class="sidebar-nav">
-         <ul class="nav nav-list">
-          <li class="nav-header">${_('Actions')}</li>
-           <li class="dropdown">
-              <a href="#" data-toggle="dropdown"><i class="fa fa-plus-circle"></i> ${_('New document')}</a>
-              <ul class="dropdown-menu" role="menu">
-                % if 'beeswax' in apps:
-                  <li><a href="${ url('beeswax:index') }"><img src="${ static(apps['beeswax'].icon_path) }" class="app-icon"/> ${_('Hive Query')}</a></li>
-                % endif
-                % if 'impala' in apps:
-                  <li><a href="${ url('impala:index') }"><img src="${ static(apps['impala'].icon_path) }" class="app-icon"/> ${_('Impala Query')}</a></li>
-                % endif
-                % if 'pig' in apps:
-                  <li><a href="${ url('pig:index') }"><img src="${ static(apps['pig'].icon_path) }" class="app-icon"/> ${_('Pig Script')}</a></li>
-                % endif
-                % if 'spark' in apps:
-                  <li><a href="${ url('notebook:index') }"><img src="${ static(apps['spark'].icon_path) }" class="app-icon"/> ${_('Spark Job')}</a></li>
-                % endif
-                % if 'oozie' in apps:
-                <li class="dropdown-submenu">
-                  <a href="#"><img src="${ static(apps['oozie'].icon_path) }" class="app-icon"/> ${_('Oozie Scheduler')}</a>
-                  <ul class="dropdown-menu">
-                    <li><a href="${ url('oozie:new_workflow') }"><img src="${ static('oozie/art/icon_oozie_workflow_48.png') }" class="app-icon"/> ${_('Workflow')}</a></li>
-                    <li><a href="${ url('oozie:new_coordinator') }"><img src="${ static('oozie/art/icon_oozie_coordinator_48.png') }" class="app-icon"/> ${_('Coordinator')}</a></li>
-                    <li><a href="${ url('oozie:new_bundle') }"><img src="${ static('oozie/art/icon_oozie_bundle_48.png') }" class="app-icon"/> ${_('Bundle')}</a></li>
-                  </ul>
-                </li>
-                % endif
-              </ul>
-           </li>
-        </ul>
-      </div>
+<div id="documentList" class="main-content">
+  <a title="${_('Toggle Assist')}" class="pointer show-assist" data-bind="visible: !$root.isLeftPanelVisible(), click: function() { $root.isLeftPanelVisible(true); }" style="display:none;">
+    <i class="fa fa-chevron-right"></i>
+  </a>
 
-    </div>
-
-    <div class="span10">
-      <div class="card card-home" style="margin-top: 0">
+  <div class="vertical-full container-fluid" data-bind="style: { 'padding-left' : $root.isLeftPanelVisible() ? '0' : '20px' }">
+    <div class="vertical-full row-fluid panel-container">
+      <div class="assist-container left-panel" data-bind="visible: $root.isLeftPanelVisible" style="display: none;">
+        <a title="${_('Toggle Assist')}" class="pointer hide-assist" data-bind="click: function() { $root.isLeftPanelVisible(false) }">
+          <i class="fa fa-chevron-left"></i>
+        </a>
+        <div class="assist" data-bind="component: {
+        name: 'assist-panel',
+        params: {
+          sourceTypes: [{
+            name: 'hive',
+            type: 'hive'
+          }],
+          user: '${user.username}',
+          navigationSettings: {
+            openItem: true,
+            showPreview: true,
+            showStats: false
+          },
+          visibleAssistPanels: ['sql']
+        }
+      }"></div>
+      </div>
+      <div class="resizer" data-bind="visible: $root.isLeftPanelVisible, splitDraggable : { appName: 'notebook', leftPanelVisible: $root.isLeftPanelVisible }" style="display:none;"><div class="resize-bar">&nbsp;</div></div>
+      <div class="right-panel" data-bind="style: { 'padding-left' : $root.isLeftPanelVisible() ? '20px' : '0' }">
         <input id="searchInput" type="text" placeholder="${ _('Search for name, description, etc...') }" class="input-xlarge search-query" style="margin-left: 20px;margin-top: 5px">
+        <div class="dropdown" style="float: right;">
+          <a href="#" data-toggle="dropdown"><i class="fa fa-plus-circle"></i> ${_('New document')}</a>
+          <ul class="dropdown-menu" role="menu">
+            % if 'beeswax' in apps:
+              <li><a href="${ url('beeswax:index') }"><img src="${ static(apps['beeswax'].icon_path) }" class="app-icon"/> ${_('Hive Query')}</a></li>
+            % endif
+            % if 'impala' in apps:
+              <li><a href="${ url('impala:index') }"><img src="${ static(apps['impala'].icon_path) }" class="app-icon"/> ${_('Impala Query')}</a></li>
+            % endif
+            % if 'pig' in apps:
+              <li><a href="${ url('pig:index') }"><img src="${ static(apps['pig'].icon_path) }" class="app-icon"/> ${_('Pig Script')}</a></li>
+            % endif
+            % if 'spark' in apps:
+              <li><a href="${ url('notebook:index') }"><img src="${ static(apps['spark'].icon_path) }" class="app-icon"/> ${_('Spark Job')}</a></li>
+            % endif
+            % if 'oozie' in apps:
+              <li class="dropdown-submenu">
+                <a href="#"><img src="${ static(apps['oozie'].icon_path) }" class="app-icon"/> ${_('Oozie Scheduler')}</a>
+                <ul class="dropdown-menu">
+                  <li><a href="${ url('oozie:new_workflow') }"><img src="${ static('oozie/art/icon_oozie_workflow_48.png') }" class="app-icon"/> ${_('Workflow')}</a></li>
+                  <li><a href="${ url('oozie:new_coordinator') }"><img src="${ static('oozie/art/icon_oozie_coordinator_48.png') }" class="app-icon"/> ${_('Coordinator')}</a></li>
+                  <li><a href="${ url('oozie:new_bundle') }"><img src="${ static('oozie/art/icon_oozie_bundle_48.png') }" class="app-icon"/> ${_('Bundle')}</a></li>
+                </ul>
+              </li>
+            % endif
+          </ul>
+        </div>
         <h2 class="card-heading simple">${_('My Documents')}</h2>
         <span data-bind="text: path"></span>
         <br/>
@@ -197,11 +264,9 @@ ${ commonheader(_('Welcome Home'), "home", user) | n,unicode }
         </div>
       </div>
     </div>
-
   </div>
 </div>
 
-
 <script type="text/html" id="document-template">
   <tr>
     <td style="width: 26px"></td>
@@ -210,46 +275,50 @@ ${ commonheader(_('Welcome Home'), "home", user) | n,unicode }
   </tr>
 </script>
 
-
-${ commonshare2() | n,unicode }
+## ${ commonshare2() | n,unicode }
 ${ commonimportexport(request) | n,unicode }
 
-<script src="${ static('desktop/ext/js/datatables-paging-0.1.js') }" type="text/javascript" charset="utf-8"></script>
-<script src="${ static('desktop/ext/js/knockout.min.js') }" type="text/javascript" charset="utf-8"></script>
-<script src="${ static('desktop/ext/js/knockout-mapping.min.js') }" type="text/javascript" charset="utf-8"></script>
-<script src="${ static('desktop/js/home2.vm.js') }"></script>
-<script src="${ static('desktop/js/share2.vm.js') }"></script>
-
-
 <script type="text/javascript" charset="utf-8">
-  var viewModel, shareViewModel;
-
-  $(document).ready(function() {
-    viewModel = new HomeViewModel();
-    ko.applyBindings(viewModel, $('#documentList')[0]);
-
-    shareViewModel = initSharing("#documentShareModal");
-    shareViewModel.setDocId(-1);
-
-    viewModel.loadDocuments(location.getParameter('path') ? location.getParameter('path') : '/');
-
-    prepareShareModal = function(job) {
-      shareViewModel.setDocId(viewModel.shareFormDocId());
-      openShareModal();
-    };
-  });
-</script>
-
-
-<style type="text/css">
-  .tourSteps {
-    min-height: 150px;
-  }
-</style>
-
-
+  require([
+    'knockout',
+    'desktop/js/home2.vm',
+    'desktop/js/share2.vm',
+    'assistPanel',
+    'tableStats',
+    'knockout-mapping',
+    'knockout-sortable',
+    'ko.hue-bindings'
+  ], function (ko, HomeViewModel, ShareViewModel) {
+
+    ko.options.deferUpdates = true;
+
+    $(document).ready(function () {
+      var options = {
+        user: '${ user.username }',
+        i18n: {
+          errorFetchingTableDetails: '${_('An error occurred fetching the table details. Please try again.')}',
+          errorFetchingTableFields: '${_('An error occurred fetching the table fields. Please try again.')}',
+          errorFetchingTableSample: '${_('An error occurred fetching the table sample. Please try again.')}',
+          errorRefreshingTableStats: '${_('An error occurred refreshing the table stats. Please try again.')}',
+          errorLoadingDatabases: '${ _('There was a problem loading the databases. Please try again.') }',
+          errorLoadingTablePreview: '${ _('There was a problem loading the table preview. Please try again.') }'
+        }
+      };
+
+      var viewModel = new HomeViewModel(options);
+      viewModel.loadDocuments(location.getParameter('path') ? location.getParameter('path') : '/');
+      ko.applyBindings(viewModel, $('#documentList')[0]);
+
+##       ShareViewModel.initSharing("#documentShareModal");
+##       shareViewModel.setDocId(-1);
 ##
-## Add a Tour?
 ##
+##       prepareShareModal = function(job) {
+##         shareViewModel.setDocId(viewModel.shareFormDocId());
+##         openShareModal();
+##       };
+    });
+  });
+</script>
 
 ${ commonfooter(request, messages) | n,unicode }