浏览代码

HUE-2742 [hbase] Apply canWrite to the codemirror binding

Reformatted the JS too
Enrico Berti 10 年之前
父节点
当前提交
be8ad6d

+ 13 - 14
apps/hbase/src/hbase/static/hbase/js/api.js

@@ -17,11 +17,11 @@
 var API = {
   //base querying function
   //query(functionName, ClusterName, arg0, arg1).done(callback)
-  query: function() {
+  query: function () {
     // all url building should be in this function
     var url = "/hbase/api";
     var $_POST = {};
-    for(var i=0;i<arguments.length;i++) {
+    for (var i = 0; i < arguments.length; i++) {
       if (arguments[i] == null)
         arguments[i] = "";
       arguments[i] = arguments[i] + "";
@@ -33,15 +33,14 @@ var API = {
       }
       url += '/' + encodeURIComponent(arguments[i]);
     }
-    var queryObject = {url:url, method:'POST', startTime: new Date().getTime(), status:'running...'};
-    var handler = $.post(url, $_POST).error(function(response) {
+    var queryObject = {url: url, method: 'POST', startTime: new Date().getTime(), status: 'running...'};
+    var handler = $.post(url, $_POST).error(function (response) {
       $(document).trigger("error", JSON.parse(response.responseText).message);
     });
     var doneHandle = handler.done;
-    handler.done = function() {
+    handler.done = function () {
       var cb = arguments[0];
-      return doneHandle.apply(handler, [function(data)
-      {
+      return doneHandle.apply(handler, [function (data) {
         app.views.tabledata.truncateLimit(data.limit);
         data = data.data;
         return cb(data);
@@ -49,29 +48,29 @@ var API = {
     };
     return handler;
   },
-  queryArray: function(action, args) {
+  queryArray: function (action, args) {
     return API.query.apply(this, [action].concat(args));
   },
   //function,arg0,arg1, queries the current cluster
-  queryCluster: function() {
+  queryCluster: function () {
     var args = Array.prototype.slice.call(arguments);
     args.splice(1, 0, app.cluster());
     return API.query.apply(this, args);
   },
-  queryTable: function() {
+  queryTable: function () {
     var args = Array.prototype.slice.call(arguments);
     args.splice(1, 0, app.views.tabledata.name());
     return API.queryCluster.apply(this, args);
   },
   //functions to abstract away API structure, in case API changes:
   //only have function name, data, and callbacks. no URL or api-facing.
-  createTable: function(cluster, tableName, columns, callback) {
-     return API.query('createTable', cluster, tableName, columns).done(callback);
+  createTable: function (cluster, tableName, columns, callback) {
+    return API.query('createTable', cluster, tableName, columns).done(callback);
   },
-  getTableNames: function(cluster, callback) {
+  getTableNames: function (cluster, callback) {
     return API.query('getTableNames', cluster).done(callback);
   },
-  getTableList: function(cluster, callback) {
+  getTableList: function (cluster, callback) {
     return API.query('getTableList', cluster).done(callback);
   }
 }

+ 121 - 115
apps/hbase/src/hbase/static/hbase/js/app.js

@@ -14,18 +14,18 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-var AppViewModel = function() {
+var AppViewModel = function () {
   var self = this;
 
   self.station = ko.observable("");
   self.pageTitle = ko.observable("");
   self.focusModel = ko.observable();
   self.cluster = ko.observable("");
-  self.cluster.subscribe(function() {
+  self.cluster.subscribe(function () {
     app.views.tabledata.name('');
   });
   self.clusters = ko.observableArray();
-  self.clusterNames = ko.computed(function() {
+  self.clusterNames = ko.computed(function () {
     return ko.utils.arrayMap(self.clusters(), function (cluster_config) {
       return cluster_config.name;
     });
@@ -33,23 +33,24 @@ var AppViewModel = function() {
   self.search = new tagsearch();
 
   self.views = {
-    tables: new DataTableViewModel({columns:['Table Name', 'Enabled'], el: 'views.tables', reload: function(callback) {
+    tables: new DataTableViewModel({columns: ['Table Name', 'Enabled'], el: 'views.tables', reload: function (callback) {
       var d_self = this;
       d_self.isReLoading(true);
       d_self.items.removeAll();
-      API.queryCluster("getTableList").done(function(data) {
+      API.queryCluster("getTableList").done(function (data) {
         d_self.items.removeAll(); //need to remove again before callback executes
-        function _isDropped (tableName) {
+        function _isDropped(tableName) {
           var _found = false;
-          d_self.droppedTables.forEach(function(t){
-            if (t.name == tableName){
+          d_self.droppedTables.forEach(function (t) {
+            if (t.name == tableName) {
               _found = true;
             }
           });
           return _found;
         }
+
         var _items = [];
-        for(q=0; q<data.length; q++) {
+        for (q = 0; q < data.length; q++) {
           if (!_isDropped(data[q].name)) {
             _items.push(new TableDataRow(data[q]));
           }
@@ -57,37 +58,40 @@ var AppViewModel = function() {
         d_self.droppedTables = [];
         d_self.items(_items);
         d_self._el.find('a[data-row-selector=true]').jHueRowSelector();
-        if(callback!=null)
+        if (callback != null)
           callback();
         d_self.isReLoading(false);
       });
     }}),
-    tabledata: new SmartViewModel({'canWrite': canWrite, el: 'views.tabledata', reload: function(callback) //move inside SmartViewModel class?
+    tabledata: new SmartViewModel({'canWrite': canWrite, el: 'views.tabledata', reload: function (callback) //move inside SmartViewModel class?
     {
       var t_self = this;
+
       function getColumnFamilies() {
         var cols = [];
         var cfs = t_self.columnFamilies();
-        for(var i=0; i<cfs.length; i++) {
-          if(cfs[i].enabled()) {
+        for (var i = 0; i < cfs.length; i++) {
+          if (cfs[i].enabled()) {
             cols.push(cfs[i].name);
           }
         }
         return cols;
       }
-      API.queryTable("getRowQuerySet", JSON.stringify(getColumnFamilies()), ko.toJSON(t_self.querySet())).done(function(data) {
-        if(data.length > 0) {
+
+      API.queryTable("getRowQuerySet", JSON.stringify(getColumnFamilies()), ko.toJSON(t_self.querySet())).done(function (data) {
+        if (data.length > 0) {
           var keys = Object.keys(data);
           var items = [];
-          for(var i=0; i<keys.length; i++) {
-            var row = new SmartViewDataRow({'canWrite': canWrite, items: [], row:data[keys[i]].row, reload: function(options) {
+          for (var i = 0; i < keys.length; i++) {
+            var row = new SmartViewDataRow({'canWrite': canWrite, items: [], row: data[keys[i]].row, reload: function (options) {
               var self = this;
               options = (options == null) ? {} : options;
               options = ko.utils.extend({
-                callback: function(data){},
+                callback: function (data) {
+                },
                 columns: getColumnFamilies()
               }, options);
-              API.queryTable("getRow", JSON.stringify(options.columns), prepForTransport(self.row)).done(function(data) {
+              API.queryTable("getRow", JSON.stringify(options.columns), prepForTransport(self.row)).done(function (data) {
                 self.setItems(data.columns);
                 callback(data);
                 self.isLoading(false);
@@ -98,15 +102,15 @@ var AppViewModel = function() {
           }
           t_self.items(items);
         }
-        if(typeof(callback) === 'function')
+        if (typeof(callback) === 'function')
           callback();
         $('*[data-toggle="tooltip"]').tooltip();
       });
     }})
   };
 
-  self.initialize = function() {
-    return API.query('getClusters').done(function(data) {
+  self.initialize = function () {
+    return API.query('getClusters').done(function (data) {
       app.clusters(data);
     });
   };
@@ -120,89 +124,91 @@ ko.applyBindings(app);
 //routing
 
 routed = false;
-app.initialize().done(function() {
+app.initialize().done(function () {
   routie({
-      ':cluster/:table/query': function(cluster, table) {
-        routie(cluster + '/' + table);
-      },
-      ':cluster/:table/query/:query': function(cluster, table, query) {
-        logGA('query_table');
-        $.totalStorage('hbase_cluster', cluster);
-        app.station('table');
-        app.search.cur_input(query);
-        Router.setTable(cluster, table);
-        resetElements();
-        Views.render('dataview');
-        app.views.tabledata._reloadcfs(function(){
-          app.search.evaluate();
-          app.views.tabledata.searchQuery(query);
-        });
-        routed = true;
-      },
-      ':cluster/:table': function(cluster, table) {
-        logGA('view_table');
+    ':cluster/:table/query': function (cluster, table) {
+      routie(cluster + '/' + table);
+    },
+    ':cluster/:table/query/:query': function (cluster, table, query) {
+      logGA('query_table');
+      $.totalStorage('hbase_cluster', cluster);
+      app.station('table');
+      app.search.cur_input(query);
+      Router.setTable(cluster, table);
+      resetElements();
+      Views.render('dataview');
+      app.views.tabledata._reloadcfs(function () {
+        app.search.evaluate();
+        app.views.tabledata.searchQuery(query);
+      });
+      routed = true;
+    },
+    ':cluster/:table': function (cluster, table) {
+      logGA('view_table');
+      $.totalStorage('hbase_cluster', cluster);
+      Router.setTable(cluster, table);
+      resetSearch();
+      resetElements();
+      app.station('table');
+      Views.render('dataview');
+      routed = true;
+    },
+    ':cluster': function (cluster) {
+      if ($.inArray(cluster, app.clusterNames()) == -1) {
+        routie('');
+      } else {
+        logGA('view_cluster');
         $.totalStorage('hbase_cluster', cluster);
-        Router.setTable(cluster, table);
+        app.station('cluster');
+        app.cluster(cluster);
+        app.pageTitle(cluster);
+        Views.render('clusterview');
         resetSearch();
         resetElements();
-        app.station('table');
-        Views.render('dataview');
-        routed = true;
-      },
-      ':cluster': function(cluster) {
-        if ($.inArray(cluster, app.clusterNames()) == -1) {
-          routie('');
-        } else {
-          logGA('view_cluster');
-          $.totalStorage('hbase_cluster', cluster);
-          app.station('cluster');
-          app.cluster(cluster);
-          app.pageTitle(cluster);
-          Views.render('clusterview');
-          resetSearch();
-          resetElements();
-          app.views.tabledata.name('');
-          app.views.tables.reload();
-          routed = true;
-        }
-        resetElements();
-        routed = true;
-      },
-      'error': function() {
-        logGA('error');
+        app.views.tabledata.name('');
+        app.views.tables.reload();
         routed = true;
-      },
-      '': function(){
-        var cluster = $.totalStorage('hbase_cluster');
-        if (cluster != null && $.inArray(cluster, app.clusterNames()) > -1) {
-          routie(cluster);
-        } else {
-          routie(app.clusterNames()[0]);
-        }
-        resetElements();
-        routed = true;
-      },
-      '*': function() {
-        logGA('');
-        if(!routed)
-          history.back();
-        routed = false;
       }
+      resetElements();
+      routed = true;
+    },
+    'error': function () {
+      logGA('error');
+      routed = true;
+    },
+    '': function () {
+      var cluster = $.totalStorage('hbase_cluster');
+      if (cluster != null && $.inArray(cluster, app.clusterNames()) > -1) {
+        routie(cluster);
+      } else {
+        routie(app.clusterNames()[0]);
+      }
+      resetElements();
+      routed = true;
+    },
+    '*': function () {
+      logGA('');
+      if (!routed)
+        history.back();
+      routed = false;
+    }
   });
 });
 
 
-$.fn.renderElement = function(data){utils.renderElement($(this,data))};
+$.fn.renderElement = function (data) {
+  utils.renderElement($(this, data))
+};
 
-$.fn.showIndicator = function() {
+$.fn.showIndicator = function () {
   $(this).addClass('isLoading');
 }
 
-$.fn.hideIndicator = function() {
+$.fn.hideIndicator = function () {
   $(this).removeClass('isLoading');
 }
 
-$.fn.toggleIndicator = function() {
+$.fn.toggleIndicator = function () {
   $(this).toggleClass('isLoading');
 }
 
@@ -210,14 +216,14 @@ function bindSubmit() {
   var self = this;
   var data = [];
   var hash_cache = {};
-  if ($(this).attr("id") == "new_table_modal"){
+  if ($(this).attr("id") == "new_table_modal") {
     var _cols = [];
-    $(this).find(".columns li.column").each(function(cnt, column){
+    $(this).find(".columns li.column").each(function (cnt, column) {
       var _props = {
         name: $(column).find("input[name='table_columns']").val()
       };
-      $(column).find(".columnProperties li").each(function(icnt, property){
-        if (! $(property).hasClass("columnPropertyEmpty")) {
+      $(column).find(".columnProperties li").each(function (icnt, property) {
+        if (!$(property).hasClass("columnPropertyEmpty")) {
           _props[$(property).find("select").val()] = $(property).find("input[name='table_columns_property_value']").val();
         }
       });
@@ -232,17 +238,17 @@ function bindSubmit() {
     ]
   }
   else {
-    $(this).find('.controls > input, .controls > textarea, .controls > ul input').not('input[type=submit]').each(function() {
-      if($(this).hasClass('ignore'))
+    $(this).find('.controls > input, .controls > textarea, .controls > ul input').not('input[type=submit]').each(function () {
+      if ($(this).hasClass('ignore'))
         return;
       var use_post = $(this).data('use-post');
       var submitVal = null;
-      if($(this).data('subscribe')) {
+      if ($(this).data('subscribe')) {
         var target = $($(this).data('subscribe'));
-        switch(target[0].tagName) {
+        switch (target[0].tagName) {
           case "UL":
             var serialized = {};
-            target.find('li').each(function() {
+            target.find('li').each(function () {
               serialized[$(this).find('input')[0].value] = $(this).find('input')[1].value;
             });
             submitVal = serialized;
@@ -250,9 +256,9 @@ function bindSubmit() {
             break;
         }
       }
-      else if($(this).hasClass('serializeHash')) {
+      else if ($(this).hasClass('serializeHash')) {
         var target = $(this).attr('name');
-        if(!hash_cache[target])
+        if (!hash_cache[target])
           hash_cache[target] = {};
         hash_cache[target][$(this).data(key)] = $(this).val();
       }
@@ -260,8 +266,8 @@ function bindSubmit() {
         submitVal = $(this).val();
         //change reload next
       }
-      if(submitVal) {
-        if(use_post) {
+      if (submitVal) {
+        if (use_post) {
           submitVal = "hbase-post-key-" + JSON.stringify(submitVal);
         } else {
           submitVal = prepForTransport(submitVal);
@@ -273,22 +279,22 @@ function bindSubmit() {
 
   $(this).find('input[type=submit]').addClass('disabled').showIndicator();
   var ui = app.focusModel();
-  if(ui)
+  if (ui)
     ui.isLoading(true);
 
-  API.queryArray($(this).attr('action'), data).complete(function() {
+  API.queryArray($(this).attr('action'), data).complete(function () {
     $(self).find('input[type=submit]').removeClass('disabled').hideIndicator();
-    if(ui)
+    if (ui)
       ui.isLoading(false);
-  }).success(function() {
+  }).success(function () {
     $(self).modal('hide');
-    if(ui)
+    if (ui)
       app.focusModel().reload();
   });
 
   return false;
 }
-$('form.ajaxSubmit').submit(bindSubmit).on('hidden', function() {
+$('form.ajaxSubmit').submit(bindSubmit).on('hidden', function () {
   $(this).trigger('reset');
 });
 
@@ -297,39 +303,39 @@ var prepareNewTableForm = function () {
   addColumnToNewTableForm();
 }
 
-var addColumnToNewTableForm = function() {
+var addColumnToNewTableForm = function () {
   var $li = $("<li>").addClass("column").css("marginBottom", "10px").html($("#columnTemplate").html());
   $li.find("ul").html($("#columnPropertyEmptyTemplate").html());
   $li.appendTo($("#new_table_modal .modal-body ul.columns"));
 }
 
-var addColumnPropertyToColumn = function (col){
+var addColumnPropertyToColumn = function (col) {
   var $li = $("<li>").addClass("columnProperty").css("marginBottom", "5px").html($("#columnPropertyTemplate").html());
-  $li.find("select").on("change", function(){
+  $li.find("select").on("change", function () {
     $li.find("[name='table_columns_property_value']").attr("placeholder", $(this).find("option:selected").data("default"));
   });
   $li.appendTo(col.find("ul"));
 }
 
-$(document).on("click", "a.action_addColumn", function() {
+$(document).on("click", "a.action_addColumn", function () {
   addColumnToNewTableForm();
 });
 
 
-$(document).on("click", "a.action_removeColumn", function() {
+$(document).on("click", "a.action_removeColumn", function () {
   $(this).parents("li").remove();
 });
 
-$(document).on("click", "a.action_addColumnProperty", function() {
+$(document).on("click", "a.action_addColumnProperty", function () {
   addColumnPropertyToColumn($(this).parents(".column"));
   $(this).parents(".column").find(".columnPropertyEmpty").remove();
 });
 
-$(document).on("click", "a.action_removeColumnProperty", function() {
+$(document).on("click", "a.action_removeColumnProperty", function () {
   var _col = $(this).parents(".column");
   _col.find(".columnPropertyEmpty").remove();
   $(this).parent().remove();
-  if (_col.find("li").length == 0){
+  if (_col.find("li").length == 0) {
     _col.find("ul").html($("#columnPropertyEmptyTemplate").html());
   }
 });

+ 40 - 38
apps/hbase/src/hbase/static/hbase/js/base.js

@@ -14,62 +14,62 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-var BaseModel = function() {
+var BaseModel = function () {
 }
 
-var ListViewModel = function(options) {
+var ListViewModel = function (options) {
   var self = this, _defaults = {
     items: [],
-    reload: function() {
+    reload: function () {
 
     },
     sortFields: {}
   };
-  options = ko.utils.extend(_defaults,options);
-  BaseModel.apply(this,[options]);
+  options = ko.utils.extend(_defaults, options);
+  BaseModel.apply(this, [options]);
 
   self.canWrite = ko.observable(options.canWrite);
   self.items = ko.observableArray(options.items);
   self.sortDropDown = new SortDropDownView({sortFields: options.sortFields, target: self.items});
-  self.selectAll = function(){
-    for(t=0; t<self.items().length; t++)
+  self.selectAll = function () {
+    for (t = 0; t < self.items().length; t++)
       self.items()[t].isSelected(true);
     return self;
   };
-  self.deselectAll = function() {
-    for(q=0; q<self.items().length; q++)
+  self.deselectAll = function () {
+    for (q = 0; q < self.items().length; q++)
       self.items()[q].isSelected(false);
     return self;
   };
-  self.toggleSelectAll = function() {
-    if(self.selected().length != self.items().length)
+  self.toggleSelectAll = function () {
+    if (self.selected().length != self.items().length)
       return self.selectAll();
     return self.deselectAll();
   };
-  self.selected = function(){
+  self.selected = function () {
     var acc = [];
     var items = self.items();
-    for(i=0; i<items.length; i++) {
-      if(items[i].isSelected())
+    for (i = 0; i < items.length; i++) {
+      if (items[i].isSelected())
         acc.push(items[i]);
     }
     return acc;
   };
-  self.batchSelected = function(action) {
+  self.batchSelected = function (action) {
     var selected = self.selected();
     var batchCount = 0;
 
-    for(q=0; q<selected.length; q++) {
+    for (q = 0; q < selected.length; q++) {
       self.isLoading(true);
       var call = action.apply(selected[q], arguments);
-      var callback = function() {
+      var callback = function () {
         batchCount++;
-        if(batchCount >= selected.length) {
+        if (batchCount >= selected.length) {
           self.reload();
           self.isLoading(false);
         }
       };
-      if(call === true) {
+      if (call === true) {
         callback();
       } else if (call != null && 'complete' in call) {
         call.complete(callback);
@@ -78,31 +78,31 @@ var ListViewModel = function(options) {
       }
     }
   };
-  self.batchSelectedAlias = function(actionAlias) {
-    self.batchSelected(function() {
+  self.batchSelectedAlias = function (actionAlias) {
+    self.batchSelected(function () {
       return this[actionAlias]();
     });
   };
-  self.enableSelected = function() {
-    self.batchSelected(function() {
+  self.enableSelected = function () {
+    self.batchSelected(function () {
       return this.enable();
     });
   };
-  self.disableSelected = function() {
-    confirm("Confirm Disable", "Disable these tables?", function() {
-      self.batchSelected(function() {
+  self.disableSelected = function () {
+    confirm("Confirm Disable", "Disable these tables?", function () {
+      self.batchSelected(function () {
         return this.disable();
       });
     });
   };
-  self.dropSelected = function() {
-    confirm("Confirm Delete", "Are you sure you want to drop the selected items? (WARNING: This cannot be undone!)", function() {
-      self.batchSelected(function() {
+  self.dropSelected = function () {
+    confirm("Confirm Delete", "Are you sure you want to drop the selected items? (WARNING: This cannot be undone!)", function () {
+      self.batchSelected(function () {
         var s = this;
         self.droppedTables.push(s);
-        if(s.enabled && s.enabled()) {
+        if (s.enabled && s.enabled()) {
           self.isLoading(true);
-          return s.disable(function() {
+          return s.disable(function () {
             s.drop(true);
           });
         } else {
@@ -111,11 +111,11 @@ var ListViewModel = function(options) {
       });
     });
   };
-  self.reload = function(callback){
+  self.reload = function (callback) {
     self.items.removeAll();
     self.isLoading(true);
-    options.reload.apply(self,[function() {
-      if(callback!=null)
+    options.reload.apply(self, [function () {
+      if (callback != null)
         callback();
       self.sortDropDown.sort();
       self.isLoading(false);
@@ -127,11 +127,13 @@ var ListViewModel = function(options) {
   self.droppedTables = [];
 };
 
-var DataRow = function(options) {
+var DataRow = function (options) {
   var self = this;
-  ko.utils.extend(self,options); //applies options on itself
-  BaseModel.apply(self,[options]);
+  ko.utils.extend(self, options); //applies options on itself
+  BaseModel.apply(self, [options]);
 
   self.isSelected = ko.observable(false);
-  self.select = function(){self.isSelected(!self.isSelected());};
+  self.select = function () {
+    self.isSelected(!self.isSelected());
+  };
 };

文件差异内容过多而无法显示
+ 251 - 236
apps/hbase/src/hbase/static/hbase/js/controls.js


+ 8 - 8
apps/hbase/src/hbase/static/hbase/js/nav.js

@@ -15,12 +15,12 @@
 // limitations under the License.
 
 var Router = {
-  go: function(page) {
-    if(!Views.render(page))
+  go: function (page) {
+    if (!Views.render(page))
       return history.back();
     return page;
   },
-  setTable: function(cluster, table) {
+  setTable: function (cluster, table) {
     Router.setCluster(cluster);
     app.pageTitle(cluster + ' / ' + table);
     app.views.tabledata.name(table);
@@ -32,28 +32,28 @@ var Router = {
       fileFieldLabel: 'hbase_file',
       multiple: false,
       onComplete: function (id, fileName, response) {
-        if(response.response != null)
+        if (response.response != null)
           $(document).trigger("error", $(response.response).find('.alert strong').text());
         else
           app.views.tabledata.reload();
       }
     });
   },
-  setCluster: function(cluster) {
+  setCluster: function (cluster) {
     app.cluster(cluster);
   }
 }
 
 var Views = {
-  render:function(view) {
+  render: function (view) {
     page = $('.hbase-page#hbase-page-' + view);
-    if(!page)
+    if (!page)
       return false;
     $('.hbase-page.active').removeClass('active');
     page.addClass('active');
     return page;
   },
-  displayError:function(error) {
+  displayError: function (error) {
     console.log(error);
   }
 }

+ 100 - 89
apps/hbase/src/hbase/static/hbase/js/utils.js

@@ -16,24 +16,24 @@
 
 var utils = {
   //take an element with mustache templates as content and re-render
-  renderElement:function(element,data) {
+  renderElement: function (element, data) {
     element.html(Mustache.render(element.html(), data));
   },
-  renderElements:function(selector,data) {
-    if(selector == null || typeof(selector) == "undefined")
+  renderElements: function (selector, data) {
+    if (selector == null || typeof(selector) == "undefined")
       selector = '';
-    $(selector).each(function() {
+    $(selector).each(function () {
       utils._renderElement(this);
     });
   },
-  renderPage:function(page_selector,data) {
-    return utils.renderElements('.' + PAGE_TEMPLATE_PREFIX + page_selector,data);
+  renderPage: function (page_selector, data) {
+    return utils.renderElements('.' + PAGE_TEMPLATE_PREFIX + page_selector, data);
   },
-  setTitle:function(title) {
+  setTitle: function (title) {
     $('.page-title').text(title);
     return this;
   },
-  getTitle:function() {
+  getTitle: function () {
     return $('.page-title').text();
   }
 }
@@ -42,22 +42,22 @@ var utils = {
 function hashToArray(hash) {
   var keys = Object.keys(hash);
   var output = [];
-  for(var i=0;i<keys.length;i++) {
-    output.push({'key':keys[i],'value':hash[keys[i]]});
+  for (var i = 0; i < keys.length; i++) {
+    output.push({'key': keys[i], 'value': hash[keys[i]]});
   }
   return output;
 }
 
 function stringHashColor(str) {
   var r = 0, g = 0, b = 0, a = 0;
-  for(var i=0;i<str.length;i++) {
+  for (var i = 0; i < str.length; i++) {
     var c = str.charCodeAt(i);
     a += c;
     r += Math.floor(Math.abs(Math.sin(c)) * a);
     g += Math.floor(Math.abs(Math.cos(c)) * a);
     b += Math.floor(Math.abs(Math.tan(c)) * a);
   }
-    return 'rgb('+(r%190)+','+(g%190)+','+(b%190)+')'; //always keep values under 180, to keep it darker
+  return 'rgb(' + (r % 190) + ',' + (g % 190) + ',' + (b % 190) + ')'; //always keep values under 180, to keep it darker
 }
 
 function scrollTo(posY) {
@@ -65,9 +65,10 @@ function scrollTo(posY) {
 }
 
 function lockClickOrigin(func, origin) {
-  return function(target, ev) {
-    if(origin != ev.target)
-      return function(){};
+  return function (target, ev) {
+    if (origin != ev.target)
+      return function () {
+      };
     return func(target, ev);
   };
 }
@@ -75,7 +76,7 @@ function lockClickOrigin(func, origin) {
 function confirm(title, text, callback) {
   var modal = $('#confirm-modal');
   ko.cleanNode(modal[0]);
-  modal.attr('data-bind','template: {name: "confirm_template"}');
+  modal.attr('data-bind', 'template: {name: "confirm_template"}');
   ko.applyBindings({
     title: title,
     text: text
@@ -85,47 +86,50 @@ function confirm(title, text, callback) {
 }
 
 function launchModal(modal, data) {
-  var element = $('#'+modal);
+  var element = $('#' + modal);
   ko.cleanNode(element[0]);
-  element.attr('data-bind','template: {name: "' + modal + '_template"}');
+  element.attr('data-bind', 'template: {name: "' + modal + '_template"}');
   ko.applyBindings(data, element[0]);
   element.is('.ajaxSubmit') ? element.submit(bindSubmit) : '';
-  switch(modal) {
+  switch (modal) {
     case 'cell_edit_modal':
-      if(data.mime.split('/')[0] == 'text') {
+      if (data.mime.split('/')[0] == 'text') {
         var target = document.getElementById('codemirror_target');
         var mime = data.mime;
-        if(mime == "text/json") {
+        if (mime == "text/json") {
           mime = {name: "javascript", json: true};
         }
-            var cm = CodeMirror.fromTextArea(target, {
-              mode: mime,
-              tabMode: 'indent',
-              lineNumbers: true
-            });
-            setTimeout(function(){cm.refresh()}, 401); //CM invis bug workaround
-            element.find('input[type=submit]').click(function() {
-              cm.save();
-            });
-          }
-          app.focusModel(data.content);
+        var cm = CodeMirror.fromTextArea(target, {
+          mode: mime,
+          tabMode: 'indent',
+          lineNumbers: true,
+          readOnly: $(target).is(":disabled")
+        });
+        setTimeout(function () {
+          cm.refresh()
+        }, 401); //CM invis bug workaround
+        element.find('input[type=submit]').click(function () {
+          cm.save();
+        });
+      }
+      app.focusModel(data.content);
       data.content.history.reload();
 
-      if(data.content.parent) {
+      if (data.content.parent) {
         var path = '/hbase/api/putUpload/"' + app.cluster() + '"/"' + app.views.tabledata.name() + '"/"' + data.content.parent.row + '"/"' + data.content.name + '"';
         var uploader = new qq.FileUploaderBasic({
           button: document.getElementById("file-upload-btn"),
           action: path,
           fileFieldLabel: 'hbase_file',
           multiple: false,
-          onComplete:function (id, fileName, response) {
+          onComplete: function (id, fileName, response) {
             data.content.reload();
           }
         });
       }
       break;
     case 'new_row_modal':
-      $('a.action_addColumnValue').click(function() {
+      $('a.action_addColumnValue').click(function () {
         $(this).parent().find("ul").append("<li><input type=\"text\" name=\"column_values\" class=\"ignore\" placeholder = \"family:column_name\"/> <input type=\"text\" name=\"column_values\" class=\"ignore\" placeholder = \"cell_value\"/></li>")
       });
       break;
@@ -135,28 +139,28 @@ function launchModal(modal, data) {
         action: '',
         fileFieldLabel: 'hbase_file',
         multiple: false,
-        onComplete:function (id, fileName, response) {
-          if(response.status == null) {
+        onComplete: function (id, fileName, response) {
+          if (response.status == null) {
             data.reload();
             element.modal('hide');
           } else {
             $(document).trigger("error", $(response.response).find('div.alert strong').text());
           }
         },
-        onSubmit: function() {
+        onSubmit: function () {
           uploader._handler._options.action = '/hbase/api/putUpload/"' + app.cluster() + '"/"' + app.views.tabledata.name() + '"/' + prepForTransport(data.row) + '/"' + element.find('#new_column_name').val() + '"';
         }
       });
       break;
   }
-  if(!element.hasClass('in'))
+  if (!element.hasClass('in'))
     element.modal('show');
   logGA(modal.slice(0, modal.indexOf('_modal') != -1 ? modal.indexOf('_modal') : modal.length));
 }
 
 function editCell($data) {
   if ($data.value().length > 146) {
-    launchModal('cell_edit_modal',{
+    launchModal('cell_edit_modal', {
       content: $data,
       mime: detectMimeType($data.value())
     });
@@ -168,51 +172,56 @@ function editCell($data) {
 function parseXML(xml) {
   var parser, xmlDoc;
   if (window.DOMParser) {
-     parser = new DOMParser();
-      xmlDoc = parser.parseFromString(xml,"text/xml");
+    parser = new DOMParser();
+    xmlDoc = parser.parseFromString(xml, "text/xml");
   }
   else {
     xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
     xmlDoc.async = false;
     xmlDoc.loadXML(xml);
-    }
-    return new XMLSerializer().serializeToString(xmlDoc);
+  }
+  return new XMLSerializer().serializeToString(xmlDoc);
 }
 
 function detectMimeType(data) {
   var MIME_TESTS = {
-    'text/plain':function(data){return !data;},
-    'type/int':function(data){return !isNaN(parseInt(data));},
-    'text/json':function(data) {
+    'text/plain': function (data) {
+      return !data;
+    },
+    'type/int': function (data) {
+      return !isNaN(parseInt(data));
+    },
+    'text/json': function (data) {
       try {
         return JSON.parse(data);
       }
-      catch(err){}
+      catch (err) {
+      }
     },
-    'text/xml':function(data) {
+    'text/xml': function (data) {
       return parseXML(data).indexOf('parsererror') == -1;
     }
   }
   var keys = Object.keys(MIME_TESTS);
-  for(var i=0;i<keys.length;i++) {
-    if(MIME_TESTS[keys[i]](data))
+  for (var i = 0; i < keys.length; i++) {
+    if (MIME_TESTS[keys[i]](data))
       return keys[i];
   }
   //images
-  var types = ['image/png','image/gif','image/jpg','application/pdf']
-  var b64 = ['iVBORw','R0lG','/9j/','JVBERi']
+  var types = ['image/png', 'image/gif', 'image/jpg', 'application/pdf']
+  var b64 = ['iVBORw', 'R0lG', '/9j/', 'JVBERi']
   try {
     var decoded = atob(data).toLowerCase().trim();
-    for(var i=0;i<types.length;i++) {
+    for (var i = 0; i < types.length; i++) {
       var location = decoded.indexOf(types[i].split('/')[1]);
-      if(location >= 0 && location<10) //stupid guess
+      if (location >= 0 && location < 10) //stupid guess
         return types[i];
     }
   }
-  catch(error) {
+  catch (error) {
   }
-  for(var i=0;i<types.length;i++) {
-    if(data.indexOf(b64[i]) >= 0 && data.indexOf(b64[i]) <= 10)
+  for (var i = 0; i < types.length; i++) {
+    if (data.indexOf(b64[i]) >= 0 && data.indexOf(b64[i]) <= 10)
       return types[i];
   }
   return 'type/null';
@@ -230,15 +239,15 @@ function formatTimestamp(timestamp) {
 
 function resetElements() {
   $(window).unbind('scroll');
-  $(window).scroll(function(e) {
-    $(".subnav.sticky").each(function() {
+  $(window).scroll(function (e) {
+    $(".subnav.sticky").each(function () {
       var padder = $(this).data('padder'), top = $(this).position().top + (padder ? window.scrollY : 0);
-      if(padder && top <= padder.position().top) {
+      if (padder && top <= padder.position().top) {
         $(this).removeClass('subnav-fixed').data('padder').remove();
         $(this).removeData('padder');
       }
-      else if(!padder && top <= window.scrollY + $('.navbar').outerHeight()) {
-        $(this).addClass('subnav-fixed').data('padder',$('<div></div>').insertBefore($(this)).css('height',$(this).outerHeight()));
+      else if (!padder && top <= window.scrollY + $('.navbar').outerHeight()) {
+        $(this).addClass('subnav-fixed').data('padder', $('<div></div>').insertBefore($(this)).css('height', $(this).outerHeight()));
       }
     });
   });
@@ -251,8 +260,8 @@ function resetSearch() {
 };
 
 function prepForTransport(value) {
-  value = value.replace(/\"/g,'\\\"').replace(/\//g,'\\/');
-  if(isNaN(parseInt(value)) && value.trim() != '')
+  value = value.replace(/\"/g, '\\\"').replace(/\//g, '\\/');
+  if (isNaN(parseInt(value)) && value.trim() != '')
     value = '"' + value + '"';
   return encodeURIComponent(value);
 };
@@ -268,20 +277,20 @@ function logGA(postfix) {
 };
 
 function table_search(value) {
-  routie(app.cluster() + '/' + app.views.tabledata.name() +'/query/' + value);
+  routie(app.cluster() + '/' + app.views.tabledata.name() + '/query/' + value);
 }
 
 function getEditablePosition(contentEditable, trimWhitespaceNodes) {
   var el = contentEditable;
-  if(window.getSelection().getRangeAt(0).startContainer == el) //raw reference for FF fix
+  if (window.getSelection().getRangeAt(0).startContainer == el) //raw reference for FF fix
     return 0;
   var index = window.getSelection().getRangeAt(0).startOffset; //ff
   var cur_node = window.getSelection().getRangeAt(0).startContainer; //ff
-  while(cur_node != null && cur_node != el) {
+  while (cur_node != null && cur_node != el) {
     var cur_sib = cur_node.previousSibling || cur_node.previousElementSibling;
-    while(cur_sib != null) {
+    while (cur_sib != null) {
       var val = $(cur_sib).text() || cur_sib.nodeValue;
-      if(typeof val !== "undefined" && val != null) {
+      if (typeof val !== "undefined" && val != null) {
         index += trimWhitespaceNodes ? val.length : val.length;
       }
       cur_sib = cur_sib.previousSibling;
@@ -291,16 +300,16 @@ function getEditablePosition(contentEditable, trimWhitespaceNodes) {
   return index;
 };
 
-function setCursor(node, pos, trimWhitespaceNodes){
+function setCursor(node, pos, trimWhitespaceNodes) {
   var sel = window.getSelection();
   var range = document.createRange();
   node = function selectNode(node) {
     var nodes = node.childNodes;
-    if(pos > 0) {
-      for(var i=0; i<nodes.length; i++) {
+    if (pos > 0) {
+      for (var i = 0; i < nodes.length; i++) {
         var val = trimWhitespaceNodes ? nodes[i].nodeValue.trim() : nodes[i].nodeValue;
-        if(val) {
-          if(val.length >= pos) {
+        if (val) {
+          if (val.length >= pos) {
             return nodes[i];
           } else {
             pos -= val.length;
@@ -319,13 +328,14 @@ function setCursor(node, pos, trimWhitespaceNodes){
     sel.removeAllRanges();
     sel.addRange(range);
     return range;
-  } catch (err) { }
+  } catch (err) {
+  }
 }
 
 function pullFromRenderer(str, renderer) {
   try {
     return str.match(renderer.select)[0].match(renderer.tag)[0];
-  } catch (e){
+  } catch (e) {
     return "";
   }
 }
@@ -333,30 +343,31 @@ function pullFromRenderer(str, renderer) {
 window.selectIndex = null;
 var fallback = typeof window.getSelection === "undefined";
 ko.bindingHandlers.editableText = {
-  init: function(element, valueAccessor, allBindingsAccessor) {
-    $(element).on('keydown', function() {
-      setTimeout(function() {
+  init: function (element, valueAccessor, allBindingsAccessor) {
+    $(element).on('keydown', function () {
+      setTimeout(function () {
         var modelValue = valueAccessor();
         var elementValue = $(element).text();
         if (ko.isWriteableObservable(modelValue) && elementValue != modelValue()) {
-          if(!fallback)
+          if (!fallback)
             window.selectIndex = getEditablePosition(element); //firefox does some tricky predictive stuff here
           modelValue(elementValue);
         }
         else { //handle non-observable one-way binding
-            var allBindings = allBindingsAccessor();
-            if (allBindings['_ko_property_writers'] && allBindings['_ko_property_writers'].htmlValue) allBindings['_ko_property_writers'].htmlValue(elementValue);
-        }}, 1);
-      });
+          var allBindings = allBindingsAccessor();
+          if (allBindings['_ko_property_writers'] && allBindings['_ko_property_writers'].htmlValue) allBindings['_ko_property_writers'].htmlValue(elementValue);
+        }
+      }, 1);
+    });
   },
-  update: function(element, valueAccessor) {
+  update: function (element, valueAccessor) {
     var value = ko.utils.unwrapObservable(valueAccessor()) || "";
-    if(value.trim() == "" && !app.search.focused()) {
+    if (value.trim() == "" && !app.search.focused()) {
       app.search.doBlur();
     } else {
-      if(!fallback) {
+      if (!fallback) {
         element.innerHTML = app.search.render(value, searchRenderers);
-        if(window.selectIndex != null) {
+        if (window.selectIndex != null) {
           setCursor(element, window.selectIndex);
         }
       }

+ 3 - 3
apps/hbase/src/hbase/templates/app.mako

@@ -97,7 +97,7 @@ ${ commonheader(None, "hbase", user) | n,unicode }
             % endif
             <a class="corner-btn btn" data-bind="event: { mousedown: function(){launchModal('cell_edit_modal', {content:$data, mime: detectMimeType($data.value())})} }"><i class="fa fa-pencil"></i> ${_('Full Editor')}</a>
             <pre data-bind="text: ($data.value().length > 146 ? $data.value().substring(0, 144) + '...' : $data.value()).replace(/(\r\n|\n|\r)/gm,''), click: editCell.bind(null, $data), clickBubble: false, visible: ! $data.isLoading() && ! $data.editing()"></pre>
-            <textarea data-bind="visible: !$data.isLoading() && $data.editing(), disable: ! canWrite, hasfocus: $data.editing, value: $data.value, click:function(){}, clickBubble: false"></textarea>
+            <textarea data-bind="visible: !$data.isLoading() && $data.editing(), disable: ! app.views.tabledata.canWrite(), hasfocus: $data.editing, value: $data.value, click:function(){}, clickBubble: false"></textarea>
             <img src="${ static('desktop/art/spinner.gif') }" data-bind="visible: $data.isLoading() " />
           </div>
         </li>
@@ -407,7 +407,7 @@ ${ commonheader(None, "hbase", user) | n,unicode }
     </script>
 
     <script id="cell_text_template" type="text/html">
-      <textarea id="codemirror_target" data-bind="text: $data.content.value" data-use-post="true"></textarea>
+      <textarea id="codemirror_target" data-bind="text: $data.content.value, disable: ! app.views.tabledata.canWrite()" data-use-post="true"></textarea>
     </script>
 
     <script id="cell_application_template" type="text/html">
@@ -415,7 +415,7 @@ ${ commonheader(None, "hbase", user) | n,unicode }
     </script>
 
     <script id="cell_type_template" type="text/html">
-      <textarea style="width:100%; height: 450px;" data-bind="text: $data.content.value, disable: ! canWrite" data-use-post="true"></textarea>
+      <textarea style="width:100%; height: 450px;" data-bind="text: $data.content.value, disable: ! app.views.tabledata.canWrite()" data-use-post="true"></textarea>
     </script>
   </div>
 

部分文件因为文件数量过多而无法显示