You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by be...@apache.org on 2016/02/23 22:00:13 UTC

fauxton commit: updated refs/heads/master to b8c4554

Repository: couchdb-fauxton
Updated Branches:
  refs/heads/master 37cfb74bc -> b8c4554cf


Truncate large docs in JSON view

Currently there's no restriction on the size of documents that
we attempt to display in JSON view. If the user uses
include_docs=true it can actually crash people's browsers if the
documents are too large.

This PR adds in a truncation option to the Document component,
defaulting to enabled, and 500 lines. It displays a simple
"truncated" note at the bottom of the result.


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/b8c4554c
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/b8c4554c
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/b8c4554c

Branch: refs/heads/master
Commit: b8c4554cfb40aab253328afd31b77591d5246fcc
Parents: 37cfb74
Author: Ben Keen <be...@gmail.com>
Authored: Tue Feb 16 16:25:22 2016 -0800
Committer: Ben Keen <be...@gmail.com>
Committed: Tue Feb 23 10:19:34 2016 -0800

----------------------------------------------------------------------
 app/addons/components/assets/less/docs.less     |  8 ++++
 .../components/react-components.react.jsx       | 42 +++++++++++++++-----
 app/addons/components/tests/docSpec.react.jsx   | 39 ++++++++++++++++++
 app/addons/documents/helpers.js                 | 18 ++++++++-
 app/addons/documents/tests/helpersSpec.js       | 21 ++++++++++
 5 files changed, 116 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/b8c4554c/app/addons/components/assets/less/docs.less
----------------------------------------------------------------------
diff --git a/app/addons/components/assets/less/docs.less b/app/addons/components/assets/less/docs.less
index ed93f34..04b79f8 100644
--- a/app/addons/components/assets/less/docs.less
+++ b/app/addons/components/assets/less/docs.less
@@ -105,3 +105,11 @@
     background-color: @docCheckBoxCheckedBG;
   }
 }
+
+.doc-content-truncated {
+  background-color: #4d4d4d;
+  color: #bbbbbb;
+  padding: 10px;
+  font-size: 13px;
+  margin: 0;
+}

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/b8c4554c/app/addons/components/react-components.react.jsx
----------------------------------------------------------------------
diff --git a/app/addons/components/react-components.react.jsx b/app/addons/components/react-components.react.jsx
index 356197f..499eb97 100644
--- a/app/addons/components/react-components.react.jsx
+++ b/app/addons/components/react-components.react.jsx
@@ -17,7 +17,6 @@ define([
   'react-dom',
   'addons/components/actions',
   'addons/components/stores',
-
   'addons/fauxton/components.react',
   'addons/documents/helpers',
   'ace/ace',
@@ -25,8 +24,8 @@ define([
   'libs/react-bootstrap'
 ],
 
-function (app, FauxtonAPI, React, ReactDOM, Actions, Stores,
-  FauxtonComponents, Helpers, ace, beautifyHelper, ReactBootstrap) {
+function (app, FauxtonAPI, React, ReactDOM, Actions, Stores, FauxtonComponents, Helpers, ace, beautifyHelper,
+  ReactBootstrap) {
 
   var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;
   var componentStore = Stores.componentStore;
@@ -36,7 +35,7 @@ function (app, FauxtonAPI, React, ReactDOM, Actions, Stores,
 
     propTypes: {
       elements: React.PropTypes.array.isRequired,
-      removeBadge: React.PropTypes.func.isRequired,
+      removeBadge: React.PropTypes.func.isRequired
     },
 
     getDefaultProps: function () {
@@ -994,7 +993,16 @@ function (app, FauxtonAPI, React, ReactDOM, Actions, Stores,
   var Document = React.createClass({
     propTypes: {
       docIdentifier: React.PropTypes.string.isRequired,
-      docChecked: React.PropTypes.func.isRequired
+      docChecked: React.PropTypes.func.isRequired,
+      truncate: React.PropTypes.bool,
+      maxRows: React.PropTypes.number
+    },
+
+    getDefaultProps: function () {
+      return {
+        truncate: true,
+        maxRows: 500
+      };
     },
 
     onChange: function (e) {
@@ -1046,13 +1054,25 @@ function (app, FauxtonAPI, React, ReactDOM, Actions, Stores,
     },
 
     getDocContent: function () {
-      if (!_.isEmpty(this.props.docContent)) {
-        return (
-          <div className="doc-data">
-            <pre className="prettyprint">{this.props.docContent}</pre>
-          </div>
-        );
+      if (_.isEmpty(this.props.docContent)) {
+        return null;
+      }
+
+      // if need be, truncate the document
+      var content = this.props.docContent;
+      var isTruncated = false;
+      if (this.props.truncate) {
+        var result = Helpers.truncateDoc(this.props.docContent, this.props.maxRows);
+        isTruncated = result.isTruncated;
+        content = result.content;
       }
+
+      return (
+        <div className="doc-data">
+          <pre className="prettyprint">{content}</pre>
+          {isTruncated ? <div className="doc-content-truncated">(truncated)</div> : null}
+        </div>
+      );
     },
 
     render: function () {

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/b8c4554c/app/addons/components/tests/docSpec.react.jsx
----------------------------------------------------------------------
diff --git a/app/addons/components/tests/docSpec.react.jsx b/app/addons/components/tests/docSpec.react.jsx
index a013cb0..23e16da 100644
--- a/app/addons/components/tests/docSpec.react.jsx
+++ b/app/addons/components/tests/docSpec.react.jsx
@@ -23,6 +23,12 @@ define([
   describe('Document', function () {
     var container, el;
 
+    var doc = {};
+    _.times(1000, function (n) {
+      doc['prop' + n] = n;
+    });
+    var docContent = JSON.stringify(doc, null, '  ');
+
     beforeEach(function () {
       container = document.createElement('div');
     });
@@ -130,6 +136,39 @@ define([
       );
       assert.equal('"foo"', $(ReactDOM.findDOMNode(el)).find('.header-doc-id').text());
     });
+
+    it('small docs should not be truncated', function () {
+      el = TestUtils.renderIntoDocument(
+        <ReactComponents.Document header="foo" isDeletable={true} checked={true} docIdentifier="foo" docContent='{ "content": true }' />,
+        container
+      );
+      assert.equal($(ReactDOM.findDOMNode(el)).find('.doc-content-truncated').length, 0);
+    });
+
+    it('large docs should get truncated', function () {
+      el = TestUtils.renderIntoDocument(
+        <ReactComponents.Document header="foo" isDeletable={true} checked={true} docIdentifier="foo" docContent={docContent} />,
+        container
+      );
+      assert.equal($(ReactDOM.findDOMNode(el)).find('.doc-content-truncated').length, 1);
+    });
+
+    it('custom truncate value', function () {
+      el = TestUtils.renderIntoDocument(
+        <ReactComponents.Document header="foo" isDeletable={true} checked={true} docIdentifier="foo" docContent={docContent} maxRows={2000} />,
+        container
+      );
+      assert.equal($(ReactDOM.findDOMNode(el)).find('.doc-content-truncated').length, 0);
+    });
+
+    it('disabling truncation', function () {
+      el = TestUtils.renderIntoDocument(
+        <ReactComponents.Document header="foo" isDeletable={true} checked={true} docIdentifier="foo" docContent={docContent} truncate={false} />,
+        container
+      );
+      assert.equal($(ReactDOM.findDOMNode(el)).find('.doc-content-truncated').length, 0);
+    });
+
   });
 
 });

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/b8c4554c/app/addons/documents/helpers.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/helpers.js b/app/addons/documents/helpers.js
index 32fe4f2..c6a1da0 100644
--- a/app/addons/documents/helpers.js
+++ b/app/addons/documents/helpers.js
@@ -96,12 +96,28 @@ define([
     }];
   }
 
+  function truncateDoc (docString, maxRows) {
+    var lines = docString.split('\n');
+    var isTruncated = false;
+    if (lines.length > maxRows) {
+      isTruncated = true;
+      lines = lines.slice(0, maxRows);
+      docString = lines.join('\n');
+    }
+    return {
+      isTruncated: isTruncated,
+      content: docString
+    };
+  }
+
+
   return {
     getPreviousPageForDoc: getPreviousPageForDoc,
     getPreviousPage: getPreviousPage,
     getSeqNum: getSeqNum,
     getNewButtonLinks: getNewButtonLinks,
     getModifyDatabaseLinks: getModifyDatabaseLinks,
-    parseJSON: parseJSON
+    parseJSON: parseJSON,
+    truncateDoc: truncateDoc
   };
 });

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/b8c4554c/app/addons/documents/tests/helpersSpec.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/tests/helpersSpec.js b/app/addons/documents/tests/helpersSpec.js
index 0f2ba29..ccbdfad 100644
--- a/app/addons/documents/tests/helpersSpec.js
+++ b/app/addons/documents/tests/helpersSpec.js
@@ -26,6 +26,27 @@ define([
       });
     });
 
+    describe('truncateDoc', function () {
+      var sevenLineDoc = '{\n"line2": 2,\n"line3": 3,\n"line4": 4,\n"line5": 5,\n"line6": 6\n}';
+
+      it('does no truncation if maxRows set higher than doc', function () {
+        var result = Helpers.truncateDoc(sevenLineDoc, 10);
+        assert.equal(result.isTruncated, false);
+        assert.equal(result.content, result.content);
+      });
+
+      it('truncates by specified line count', function () {
+        var result = Helpers.truncateDoc(sevenLineDoc, 5);
+        assert.equal(result.isTruncated, true);
+        assert.equal(result.content, '{\n"line2": 2,\n"line3": 3,\n"line4": 4,\n"line5": 5,');
+
+        var result2 = Helpers.truncateDoc(sevenLineDoc, 2);
+        assert.equal(result2.isTruncated, true);
+        assert.equal(result2.content, '{\n"line2": 2,');
+      });
+
+    });
+
   });
 
 });