couchdb-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From benk...@apache.org
Subject fauxton commit: updated refs/heads/master to a34579a
Date Tue, 14 Apr 2015 20:09:57 GMT
Repository: couchdb-fauxton
Updated Branches:
  refs/heads/master df5010b3c -> a34579ad8


Changes auto-update option added

This PR adds a "Auto-update changes list" option on the Changes
page, within the Filters tab. When enabled, it will automatically
update the page with whatever changes occur on the database.


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

Branch: refs/heads/master
Commit: a34579ad82476849de2dcaaad3a64b3cfef64d87
Parents: df5010b
Author: Ben Keen <ben.keen@gmail.com>
Authored: Thu Apr 2 12:10:25 2015 -0700
Committer: Ben Keen <ben.keen@gmail.com>
Committed: Tue Apr 14 13:12:40 2015 -0700

----------------------------------------------------------------------
 app/addons/documents/assets/less/changes.less   | 17 ++++-
 app/addons/documents/changes/actions.js         | 67 ++++++++++++++++---
 app/addons/documents/changes/actiontypes.js     |  6 +-
 .../documents/changes/components.react.jsx      | 33 +++++++---
 app/addons/documents/changes/stores.js          | 69 ++++++++++++++++----
 app/addons/documents/helpers.js                 |  6 ++
 app/addons/documents/routes-documents.js        | 10 +--
 .../tests/changes.componentsSpec.react.jsx      | 41 ++++++------
 .../documents/tests/changes.storesSpec.js       | 32 +++++----
 .../documents/tests/nightwatch/changes.js       | 31 +++++++++
 assets/less/animations.less                     | 18 ++++-
 assets/less/variables.less                      |  1 +
 12 files changed, 256 insertions(+), 75 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/a34579ad/app/addons/documents/assets/less/changes.less
----------------------------------------------------------------------
diff --git a/app/addons/documents/assets/less/changes.less b/app/addons/documents/assets/less/changes.less
index 37fcad1..9c883c8 100644
--- a/app/addons/documents/assets/less/changes.less
+++ b/app/addons/documents/assets/less/changes.less
@@ -70,7 +70,7 @@
 
 .keyframes(slideDownChangesFilter, {
   opacity: 0;
-  height: 0px;
+  height: 0;
 },
 {
   opacity: 1;
@@ -83,7 +83,7 @@
 },
 {
   opacity: 0;
-  height: 0px;
+  height: 0;
 });
 
 .toggle-changes-filter-enter {
@@ -106,3 +106,16 @@
   margin-left: 20px;
 }
 
+.changes-polling {
+  float: right;
+  input {
+    margin: 0 8px 1px;
+  }
+  label {
+    display: inline-block;
+  }
+}
+
+.new-change-row {
+  -webkit-animation: slideDown 1.5s both, highlight-element 2.0s 1;
+}

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/a34579ad/app/addons/documents/changes/actions.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/changes/actions.js b/app/addons/documents/changes/actions.js
index d94da66..447833c 100644
--- a/app/addons/documents/changes/actions.js
+++ b/app/addons/documents/changes/actions.js
@@ -13,9 +13,16 @@
 define([
   'app',
   'api',
-  'addons/documents/changes/actiontypes'
+  'addons/documents/changes/actiontypes',
+  'addons/documents/changes/stores',
+  'addons/documents/helpers'
 ],
-function (app, FauxtonAPI, ActionTypes) {
+function (app, FauxtonAPI, ActionTypes, Stores, Helpers) {
+
+  var changesStore = Stores.changesStore;
+  var pollingTimeout = 60000;
+  var currentRequest;
+
 
   return {
     toggleTabVisibility: function () {
@@ -38,18 +45,60 @@ function (app, FauxtonAPI, ActionTypes) {
       });
     },
 
-    setChanges: function (options) {
+    initChanges: function (options) {
       FauxtonAPI.dispatch({
-        type: ActionTypes.SET_CHANGES,
+        type: ActionTypes.INIT_CHANGES,
         options: options
       });
+      currentRequest = null;
+      this.getLatestChanges();
+    },
+
+    getLatestChanges: function () {
+      var params = {
+        limit: 100
+      };
+
+      // after the first request for the changes list has been made, switch to longpoll
+      if (currentRequest) {
+        params.since = changesStore.getLastSeqNum();
+        params.timeout = pollingTimeout;
+        params.feed = 'longpoll';
+      }
+
+      var query = $.param(params);
+      var db = app.utils.safeURLName(changesStore.getDatabaseName());
+      currentRequest = $.get('/' + db + '/_changes?' + query);
+      currentRequest.then(_.bind(this.updateChanges, this));
     },
 
-    fetchChanges: function (options) {
-      var changes = options.changes;
-      changes.fetch().then(function () {
-        this.setChanges(options);
-      }.bind(this));
+    updateChanges: function (resp) {
+      var json = JSON.parse(resp);
+
+      // only bother updating the list of changes if the seq num has changed
+      var latestSeqNum = Helpers.getSeqNum(json.last_seq);
+      if (latestSeqNum !== changesStore.getLastSeqNum()) {
+        FauxtonAPI.dispatch({
+          type: ActionTypes.UPDATE_CHANGES,
+          changes: json.results,
+          seqNum: latestSeqNum
+        });
+      }
+
+      if (changesStore.pollingEnabled()) {
+        this.getLatestChanges();
+      }
+    },
+
+    togglePolling: function () {
+      FauxtonAPI.dispatch({ type: ActionTypes.TOGGLE_CHANGES_POLLING });
+
+      // the user just enabled polling. Start 'er up
+      if (changesStore.pollingEnabled()) {
+        this.getLatestChanges();
+      } else {
+        currentRequest.abort();
+      }
     }
   };
 

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/a34579ad/app/addons/documents/changes/actiontypes.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/changes/actiontypes.js b/app/addons/documents/changes/actiontypes.js
index 7f91ae6..edca4b9 100644
--- a/app/addons/documents/changes/actiontypes.js
+++ b/app/addons/documents/changes/actiontypes.js
@@ -12,11 +12,13 @@
 
 define([], function () {
   return {
-    SET_CHANGES: 'SET_CHANGES',
+    INIT_CHANGES: 'INIT_CHANGES',
+    UPDATE_CHANGES: 'UPDATE_CHANGES',
     TOGGLE_CHANGES_TAB_VISIBILITY: 'TOGGLE_CHANGES_TAB_VISIBILITY',
     ADD_CHANGES_FILTER_ITEM: 'ADD_CHANGES_FILTER_ITEM',
     REMOVE_CHANGES_FILTER_ITEM: 'REMOVE_CHANGES_FILTER_ITEM',
     UPDATE_CHANGES_FILTER: 'UPDATE_CHANGES_FILTER',
-    TOGGLE_CHANGES_CODE_VISIBILITY: 'TOGGLE_CHANGES_CODE_VISIBILITY'
+    TOGGLE_CHANGES_CODE_VISIBILITY: 'TOGGLE_CHANGES_CODE_VISIBILITY',
+    TOGGLE_CHANGES_POLLING: 'TOGGLE_CHANGES_POLLING'
   };
 });

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/a34579ad/app/addons/documents/changes/components.react.jsx
----------------------------------------------------------------------
diff --git a/app/addons/documents/changes/components.react.jsx b/app/addons/documents/changes/components.react.jsx
index 69ca6f7..c440e71 100644
--- a/app/addons/documents/changes/components.react.jsx
+++ b/app/addons/documents/changes/components.react.jsx
@@ -54,7 +54,7 @@ define([
     render: function () {
       var tabContent = '';
       if (this.state.showTabContent) {
-        tabContent = <ChangesFilter key="changesFilterSection" />;
+        tabContent = <ChangesTabContent key="changesFilterSection" />;
       }
 
       return (
@@ -90,10 +90,11 @@ define([
   });
 
 
-  var ChangesFilter = React.createClass({
+  var ChangesTabContent = React.createClass({
     getStoreState: function () {
       return {
-        filters: changesStore.getFilters()
+        filters: changesStore.getFilters(),
+        pollingEnabled: changesStore.pollingEnabled()
       };
     },
 
@@ -134,15 +135,30 @@ define([
       return changesStore.hasFilter(filter);
     },
 
+    togglePolling: function () {
+      Actions.togglePolling();
+    },
+
     render: function () {
       return (
         <div className="tab-content">
           <div className="tab-pane active" ref="filterTab">
             <div className="changes-header js-filter">
+              <div className="changes-polling">
+                <input
+                  type="checkbox"
+                  id="changes-toggle-polling"
+                  checked={this.state.pollingEnabled}
+                  onChange={this.togglePolling}
+                />
+                <label htmlFor="changes-toggle-polling">Auto-update changes list</label>
+              </div>
               <AddFilterForm tooltip={this.props.tooltip} filter={this.state.filter} addFilter={this.addFilter}
                 hasFilter={this.hasFilter} />
               <ul className="filter-list">{this.getFilters()}</ul>
             </div>
+            <div className="changes-auto-update">
+            </div>
           </div>
         </div>
       );
@@ -308,7 +324,8 @@ define([
 
     getRows: function () {
       return _.map(this.state.changes, function (change) {
-        return <ChangeRow change={change} key={change.id} databaseName={this.state.databaseName}
/>;
+        var key = change.id + '-' + change.seq;
+        return <ChangeRow change={change} key={key} databaseName={this.state.databaseName}
/>;
       }, this);
     },
 
@@ -358,10 +375,11 @@ define([
     },
 
     render: function () {
-      var jsonBtnClasses = "btn btn-small " + (this.state.codeVisible ? 'btn-secondary' :
'btn-primary');
+      var jsonBtnClasses = 'btn btn-small' + (this.state.codeVisible ? ' btn-secondary' :
' btn-primary');
+      var wrapperClass = 'change-wrapper' + (this.props.change.isNew ? ' new-change-row'
: '');
 
       return (
-        <div className="change-wrapper">
+        <div className={wrapperClass}>
           <div className="change-box" data-id={this.props.change.id}>
             <div className="row-fluid">
               <div className="span2">seq</div>
@@ -432,10 +450,9 @@ define([
       React.unmountComponentAtNode(el);
     },
 
-    // exposed for testing purposes only
     ChangesHeaderController: ChangesHeaderController,
     ChangesHeaderTab: ChangesHeaderTab,
-    ChangesFilter: ChangesFilter,
+    ChangesTabContent: ChangesTabContent,
     ChangesController: ChangesController,
     ChangeRow: ChangeRow
   };

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/a34579ad/app/addons/documents/changes/stores.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/changes/stores.js b/app/addons/documents/changes/stores.js
index 301e8c0..397854b 100644
--- a/app/addons/documents/changes/stores.js
+++ b/app/addons/documents/changes/stores.js
@@ -12,8 +12,9 @@
 
 define([
   'api',
-  'addons/documents/changes/actiontypes'
-], function (FauxtonAPI, ActionTypes) {
+  'addons/documents/changes/actiontypes',
+  'addons/documents/helpers'
+], function (FauxtonAPI, ActionTypes, Helpers) {
 
 
   var ChangesStore = FauxtonAPI.Store.extend({
@@ -28,20 +29,41 @@ define([
       this._databaseName = '';
       this._maxChangesListed = 100;
       this._showingSubset = false;
+      this._pollingEnabled = false;
+      this._lastSequenceNum = null;
     },
 
-    setChanges: function (options) {
-      this._filters = options.filters;
+    initChanges: function (options) {
+      this.reset();
       this._databaseName = options.databaseName;
-      this._changes = _.map(options.changes.models, function (change) {
+    },
+
+    updateChanges: function (seqNum, changes) {
+
+      // make a note of the most recent sequence number. This is used for a point of reference
for polling for new changes
+      this._lastSequenceNum = seqNum;
+
+      // mark any additional changes that come after first page load as "new" so we can add
a nice highlight effect
+      // when the new row is rendered
+      var firstBatch = this._changes.length === 0;
+      _.each(this._changes, function (change) {
+        change.isNew = false;
+      });
+
+      var newChanges = _.map(changes, function (change) {
+        var seq = Helpers.getSeqNum(change.seq);
         return {
-          id: change.get('id'),
-          seq: change.get('seq'),
-          deleted: change.get('deleted') ? change.get('deleted') : false,
-          changes: change.get('changes'),
-          doc: change.get('doc') // only populated with ?include_docs=true
+          id: change.id,
+          seq: seq,
+          deleted: _.has(change, 'deleted') ? change.deleted : false,
+          changes: change.changes,
+          doc: change.doc, // only populated with ?include_docs=true
+          isNew: !firstBatch
         };
       });
+
+      // add the new changes to the start of the list
+      this._changes = newChanges.concat(this._changes);
     },
 
     getChanges: function () {
@@ -102,10 +124,29 @@ define([
       this._maxChangesListed = num;
     },
 
+    togglePolling: function () {
+      this._pollingEnabled = !this._pollingEnabled;
+
+      // if polling was just enabled, reset the last sequence num to 'now' so only future
changes will appear
+      this._lastSequenceNum = 'now';
+    },
+
+    pollingEnabled: function () {
+      return this._pollingEnabled;
+    },
+
+    getLastSeqNum: function () {
+      return this._lastSequenceNum;
+    },
+
     dispatch: function (action) {
       switch (action.type) {
-        case ActionTypes.SET_CHANGES:
-          this.setChanges(action.options);
+        case ActionTypes.INIT_CHANGES:
+          this.initChanges(action.options);
+          this.triggerChange();
+        break;
+        case ActionTypes.UPDATE_CHANGES:
+          this.updateChanges(action.seqNum, action.changes);
           this.triggerChange();
         break;
         case ActionTypes.TOGGLE_CHANGES_TAB_VISIBILITY:
@@ -120,6 +161,10 @@ define([
           this.removeFilter(action.filter);
           this.triggerChange();
         break;
+        case ActionTypes.TOGGLE_CHANGES_POLLING:
+          this.togglePolling();
+          this.triggerChange();
+        break;
       }
     }
   });

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/a34579ad/app/addons/documents/helpers.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/helpers.js b/app/addons/documents/helpers.js
index 9197bf8..e04e3b4 100644
--- a/app/addons/documents/helpers.js
+++ b/app/addons/documents/helpers.js
@@ -33,5 +33,11 @@ define([
     return previousPage;
   };
 
+
+  // sequence info is an array in couchdb2 with two indexes. On couch 1.x, it's just a string
/ number
+  Helpers.getSeqNum = function (val) {
+    return _.isArray(val) ? val[1] : val;
+  };
+
   return Helpers;
 });

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/a34579ad/app/addons/documents/routes-documents.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/routes-documents.js b/app/addons/documents/routes-documents.js
index 652025e..695d991 100644
--- a/app/addons/documents/routes-documents.js
+++ b/app/addons/documents/routes-documents.js
@@ -160,17 +160,11 @@ function (app, FauxtonAPI, BaseRoute, Documents, Changes, ChangesActions,
DocEdi
       },
 
       changes: function () {
-        var docParams = app.getParams();
-        this.database.buildChanges(docParams);
-
-        ChangesActions.fetchChanges({
-          changes: this.database.changes,
-          filters: [],
+        ChangesActions.initChanges({
           databaseName: this.database.id
         });
-
-        this.setComponent("#dashboard-lower-content", Changes.ChangesController);
         this.setComponent('#dashboard-upper-content', Changes.ChangesHeaderController);
+        this.setComponent("#dashboard-lower-content", Changes.ChangesController);
 
         this.footer && this.footer.remove();
         this.toolsView && this.toolsView.remove();

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/a34579ad/app/addons/documents/tests/changes.componentsSpec.react.jsx
----------------------------------------------------------------------
diff --git a/app/addons/documents/tests/changes.componentsSpec.react.jsx b/app/addons/documents/tests/changes.componentsSpec.react.jsx
index ecfb8bb..ecf3f35 100644
--- a/app/addons/documents/tests/changes.componentsSpec.react.jsx
+++ b/app/addons/documents/tests/changes.componentsSpec.react.jsx
@@ -78,12 +78,12 @@ define([
   });
 
 
-  describe('ChangesFilter', function () {
+  describe('ChangesTabContent', function () {
     var container, changesFilterEl;
 
     beforeEach(function () {
       container = document.createElement('div');
-      changesFilterEl = TestUtils.renderIntoDocument(<Changes.ChangesFilter />, container);
+      changesFilterEl = TestUtils.renderIntoDocument(<Changes.ChangesTabContent />,
container);
     });
 
     afterEach(function () {
@@ -195,24 +195,25 @@ define([
   describe('ChangesController', function () {
     var containerEl, headerEl, $headerEl, changesEl, $changesEl;
 
-    var changesCollection = new Backbone.Collection([
+    var results = [
       { id: 'doc_1', seq: 4, deleted: false, changes: { code: 'here' } },
       { id: 'doc_2', seq: 1, deleted: false, changes: { code: 'here' } },
       { id: 'doc_3', seq: 6, deleted: true, changes: { code: 'here' } },
       { id: 'doc_4', seq: 7, deleted: false, changes: { code: 'here' } },
       { id: 'doc_5', seq: 1, deleted: true, changes: { code: 'here' } }
-    ]);
+    ];
+    var changesResponse = JSON.stringify({
+      last_seq: 123,
+      'results': results
+    });
 
     beforeEach(function () {
-      Actions.setChanges({
-        changes: changesCollection,
-        filters: [],
-        databaseName: 'testDatabase'
-      });
+      Actions.initChanges({ databaseName: 'testDatabase' });
       headerEl  = TestUtils.renderIntoDocument(<Changes.ChangesHeaderController />,
containerEl);
       $headerEl = $(headerEl.getDOMNode());
       changesEl = TestUtils.renderIntoDocument(<Changes.ChangesController />, containerEl);
       $changesEl = $(changesEl.getDOMNode());
+      Actions.updateChanges(changesResponse);
     });
 
     afterEach(function () {
@@ -222,7 +223,7 @@ define([
 
 
     it('should list the right number of changes', function () {
-      assert.equal(changesCollection.length, $changesEl.find('.change-box').length);
+      assert.equal(results.length, $changesEl.find('.change-box').length);
     });
 
 
@@ -293,20 +294,22 @@ define([
 
     beforeEach(function () {
 
-      // to keep the test speedy, override the default value (1000)
-      Stores.changesStore.setMaxChanges(maxChanges);
-
       var changes = [];
       _.times(maxChanges + 10, function (i) {
-        changes.push(new Backbone.Model({ id: 'doc_' + i, seq: 1, changes: { code: 'here'
} }));
+        changes.push({ id: 'doc_' + i, seq: 1, changes: { code: 'here' } });
       });
-      var changesCollection = new Backbone.Collection(changes);
 
-      Actions.setChanges({
-        changes: changesCollection,
-        filters: [],
-        databaseName: 'test'
+      var response = JSON.stringify({
+        last_seq: 1,
+        results: changes
       });
+
+      Actions.initChanges({ databaseName: 'test' });
+
+      // to keep the test speedy, override the default value (1000)
+      Stores.changesStore.setMaxChanges(maxChanges);
+
+      Actions.updateChanges(response);
       changesEl = TestUtils.renderIntoDocument(<Changes.ChangesController />, containerEl);
     });
 

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/a34579ad/app/addons/documents/tests/changes.storesSpec.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/tests/changes.storesSpec.js b/app/addons/documents/tests/changes.storesSpec.js
index 36b313e..fedfb13 100644
--- a/app/addons/documents/tests/changes.storesSpec.js
+++ b/app/addons/documents/tests/changes.storesSpec.js
@@ -23,8 +23,6 @@ define([
 
   describe('ChangesStore', function () {
 
-    var collection = new Backbone.Collection();
-
     afterEach(function () {
       Stores.changesStore.reset();
     });
@@ -67,10 +65,9 @@ define([
       assert.ok(Stores.changesStore.hasFilter(filter) === true);
     });
 
-
     it('getDatabaseName() returns database name', function () {
       var dbName = 'hoopoes';
-      Stores.changesStore.setChanges({ databaseName: dbName, changes: collection });
+      Stores.changesStore.initChanges({ databaseName: dbName });
       assert.equal(Stores.changesStore.getDatabaseName(), dbName);
 
       Stores.changesStore.reset();
@@ -79,23 +76,32 @@ define([
 
     it("getChanges() should return a subset if there are a lot of changes", function () {
 
-      // to keep the test speedy, override the default max value
+      // to keep the test speedy, we override the default max value
       var maxChanges = 10;
-      Stores.changesStore.setMaxChanges(maxChanges);
-
       var changes = [];
       _.times(maxChanges + 10, function (i) {
-        changes.push(new Backbone.Model({ id: 'doc_' + i, seq: 1, changes: { } }));
-      });
-      var changesCollection = new Backbone.Collection(changes);
-      Stores.changesStore.setChanges({
-        changes: changesCollection,
-        databaseName: "test"
+        changes.push({ id: 'doc_' + i, seq: 1, changes: {}});
       });
+      Stores.changesStore.initChanges({ databaseName: "test" });
+      Stores.changesStore.setMaxChanges(maxChanges);
+
+      var seqNum = 123;
+      Stores.changesStore.updateChanges(seqNum, changes);
 
       var results = Stores.changesStore.getChanges();
       assert.equal(maxChanges, results.length);
     });
+
+    it("tracks last sequence number", function () {
+      assert.equal(null, Stores.changesStore.getLastSeqNum());
+
+      var seqNum = 123;
+      Stores.changesStore.updateChanges(seqNum, []);
+
+      // confirm it's been stored
+      assert.equal(seqNum, Stores.changesStore.getLastSeqNum());
+    });
+
   });
 
 });

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/a34579ad/app/addons/documents/tests/nightwatch/changes.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/tests/nightwatch/changes.js b/app/addons/documents/tests/nightwatch/changes.js
index 49c1527..41000d4 100644
--- a/app/addons/documents/tests/nightwatch/changes.js
+++ b/app/addons/documents/tests/nightwatch/changes.js
@@ -11,6 +11,7 @@
 // the License.
 
 module.exports = {
+
   'Does not display the Select-all-button': function (client) {
     var waitTime = client.globals.maxWaitTime,
         newDatabaseName = client.globals.testDatabaseName,
@@ -42,5 +43,35 @@ module.exports = {
       .click('.js-doc-link')
       .waitForElementPresent('#doc-editor-actions-panel', waitTime, false)
       .end();
+  },
+
+  'Check auto-update feature': function (client) {
+    var waitTime = client.globals.maxWaitTime,
+        newDatabaseName = client.globals.testDatabaseName,
+        newDocName = 'totally-new-doc',
+        baseUrl = client.globals.test_settings.launch_url;
+
+    client
+      .loginToGUI()
+
+      // create a single document
+      .createDocument('doc_1', newDatabaseName)
+
+      // go to the changes page and enable the auto-update feature
+      .url(baseUrl + '/#/database/' + newDatabaseName + '/_changes')
+
+      .clickWhenVisible('#db-views-tabs-nav a', waitTime, false)
+      .waitForElementPresent('#changes-toggle-polling', waitTime, false)
+      .clickWhenVisible('#changes-toggle-polling', waitTime, false)
+
+      // now add a new item behind the scenes with nano. Before it's added, confirm it's
not already in the page
+      .waitForElementNotPresent('.change-box[data-id="' + newDocName + '"]', waitTime, false)
+      .createDocument(newDocName, newDatabaseName)
+
+      .waitForElementPresent('.change-box[data-id="' + newDocName + '"]', waitTime, false)
+
+      // we win!
+      .end();
   }
+
 };

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/a34579ad/assets/less/animations.less
----------------------------------------------------------------------
diff --git a/assets/less/animations.less b/assets/less/animations.less
index a4fc7d9..9ad0a3c 100644
--- a/assets/less/animations.less
+++ b/assets/less/animations.less
@@ -48,7 +48,7 @@
 /* a generic slide-up/down effect that looks smooth for items with unknown heights */
 .keyframes(slideDown, {
   opacity: 0;
-  max-height: 0px;
+  max-height: 0;
 },
 {
   opacity: 1;
@@ -60,6 +60,20 @@
   opacity: 1;
 },
 {
-  max-height: 0px;
+  max-height: 0;
   opacity: 0;
 });
+
+.highlight {
+  -webkit-animation: highlight-element 2.5s 1;
+  -moz-animation: highlight-element 2.5s 1;
+}
+
+@-webkit-keyframes highlight-element {
+  0% { background-color: @highlightEffectColor; }
+  100% { background-color: #f1f1f1; }
+}
+@-moz-keyframes highlight-element {
+  0% { background-color: @highlightEffectColor; }
+  100% { background-color: #f1f1f1; }
+}

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/a34579ad/assets/less/variables.less
----------------------------------------------------------------------
diff --git a/assets/less/variables.less b/assets/less/variables.less
index 45dfc0f..be45dd4 100644
--- a/assets/less/variables.less
+++ b/assets/less/variables.less
@@ -102,6 +102,7 @@
 /* animation */
 @transitionSpeed: .25s;
 @transitionEaseType: linear;
+@highlightEffectColor: #bbbbbb;
 
 /* breakpoints */
 @collapsedNavWidth: 64px;


Mime
View raw message