Repository: couchdb-fauxton Updated Branches: refs/heads/master 42b9fa406 -> 852d6ae59
Improve db page error handling This PR fixes an old bug with the databases page where if one database query fails, the remaining responses that haven't been returned don't get populated and the database table has a lot of incomplete rows. Now the individual failed database rows don't affect the others and show a "This database failed to load" message to make it clear to the user. The actions.js refactor code was needed due to the following. FauxtonAPI.when() behaves in an unexpected way: when passed an array of promises it fires the .always() in two conditions: 1. When all promises are resolved, or, 2. When ONE fails What was happening was that when a db request failed, it didn't fire any of the remainder requests, which is why the table would appear partly empty. Closes COUCHDB-2243 Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/852d6ae5 Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/852d6ae5 Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/852d6ae5 Branch: refs/heads/master Commit: 852d6ae59b294ccc7dbbca3304ec13c479bcd9fd Parents: 42b9fa4 Author: Ben Keen <ben.k...@gmail.com> Authored: Tue Sep 29 10:14:50 2015 -0700 Committer: Ben Keen <ben.k...@gmail.com> Committed: Tue Oct 20 10:55:51 2015 -0700 ---------------------------------------------------------------------- app/addons/databases/actions.js | 30 +++++++++++++----- app/addons/databases/assets/less/databases.less | 5 +++ app/addons/databases/components.react.jsx | 15 +++++++++ app/addons/databases/resources.js | 6 ++++ .../databases/tests/componentsSpec.react.jsx | 32 ++++++++++++++++++++ 5 files changed, 81 insertions(+), 7 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/852d6ae5/app/addons/databases/actions.js ---------------------------------------------------------------------- diff --git a/app/addons/databases/actions.js b/app/addons/databases/actions.js index aa814e4..423c62a 100644 --- a/app/addons/databases/actions.js +++ b/app/addons/databases/actions.js @@ -26,20 +26,36 @@ function (app, FauxtonAPI, Stores, ActionTypes, Resources) { this.setStartLoading(); FauxtonAPI.when(databases.fetch({ cache: false })).then(function () { - FauxtonAPI.when(databases.paginated(page, perPage).map(function (database) { - return database.status.fetchOnce(); - })).always(function () { - //make this always so that even if a user is not allowed access to a database - //they will still see a list of all databases + + // if there are no databases, publish the init message anyway + if (!databases.paginated(page, perPage).length) { FauxtonAPI.dispatch({ type: ActionTypes.DATABASES_INIT, options: { - collection: databases.paginated(page, perPage), + collection: [], backboneCollection: databases, page: page } }); - }.bind(this)); + } + + var numComplete = 0; + _.each(databases.paginated(page, perPage), function (db) { + db.status.fetchOnce().always(function () { + numComplete++; + if (numComplete < databases.paginated(page, perPage).length) { + return; + } + FauxtonAPI.dispatch({ + type: ActionTypes.DATABASES_INIT, + options: { + collection: databases.paginated(page, perPage), + backboneCollection: databases, + page: page + } + }); + }); + }); }.bind(this)); }, http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/852d6ae5/app/addons/databases/assets/less/databases.less ---------------------------------------------------------------------- diff --git a/app/addons/databases/assets/less/databases.less b/app/addons/databases/assets/less/databases.less index 652530b..e21b8ef 100644 --- a/app/addons/databases/assets/less/databases.less +++ b/app/addons/databases/assets/less/databases.less @@ -62,3 +62,8 @@ #database-pagination { float: right; } + +.database-load-fail { + color: #999999; + height: 49px; +} http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/852d6ae5/app/addons/databases/components.react.jsx ---------------------------------------------------------------------- diff --git a/app/addons/databases/components.react.jsx b/app/addons/databases/components.react.jsx index c3e8e7f..998c805 100644 --- a/app/addons/databases/components.react.jsx +++ b/app/addons/databases/components.react.jsx @@ -107,6 +107,10 @@ define([ var DatabaseRow = React.createClass({ + propTypes: { + row: React.PropTypes.object + }, + renderGraveyard: function (row) { if (row.status.isGraveYard()) { return ( @@ -127,8 +131,19 @@ define([ render: function () { var row = this.props.row; var name = row.get("name"); + + // if the row status failed to load, inform the user + if (!row.status.loadSuccess) { + return ( + <tr> + <td>{name}</td> + <td colSpan="4" className="database-load-fail">This database failed to load.</td> + </tr> + ); + } var encoded = app.utils.safeURLName(name); var size = Helpers.formatSize(row.status.dataSize()); + return ( <tr> <td> http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/852d6ae5/app/addons/databases/resources.js ---------------------------------------------------------------------- diff --git a/app/addons/databases/resources.js b/app/addons/databases/resources.js index 5034c84..577f3f4 100644 --- a/app/addons/databases/resources.js +++ b/app/addons/databases/resources.js @@ -123,6 +123,7 @@ function (app, FauxtonAPI, Documents) { initialize: function (options) { this.database = options.database; + this.loadSuccess = false; }, numDocs: function () { @@ -160,6 +161,11 @@ function (app, FauxtonAPI, Documents) { } }, + parse: function (resp) { + this.loadSuccess = true; + return resp; + }, + // a sure-fire way to know when the DB size info is actually available; dataSize() may return 0 before or after // the data has been loaded hasDataSize: function () { http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/852d6ae5/app/addons/databases/tests/componentsSpec.react.jsx ---------------------------------------------------------------------- diff --git a/app/addons/databases/tests/componentsSpec.react.jsx b/app/addons/databases/tests/componentsSpec.react.jsx index 099ab91..2669b46 100644 --- a/app/addons/databases/tests/componentsSpec.react.jsx +++ b/app/addons/databases/tests/componentsSpec.react.jsx @@ -40,6 +40,7 @@ define([ } }, "status": { + "loadSuccess": true, "dataSize": function () { return 2 * 1024 * 1024; }, @@ -63,6 +64,7 @@ define([ } }, "status": { + "loadSuccess": true, "dataSize": function () { return 1024; }, @@ -270,6 +272,7 @@ define([ var row = new Backbone.Model({ name: 'db name' }); row.status = { + loadSuccess: true, dataSize: function () { return 0; }, numDocs: function () { return 0; }, updateSeq: function () { return 0; }, @@ -287,6 +290,35 @@ define([ Stores.databasesStore.reset(); }); + it('shows error message if row marked as failed to load', function () { + var row = new Backbone.Model({ name: 'db name' }); + row.status = { + loadSuccess: false, + dataSize: function () { return 0; }, + numDocs: function () { return 0; }, + updateSeq: function () { return 0; }, + isGraveYard: function () { return false; } + }; + + var databaseRow = TestUtils.renderIntoDocument(<Views.DatabaseTable body={[row]} />, container); + assert.equal($(databaseRow.getDOMNode()).find('.database-load-fail').length, 1); + }); + + it('shows no error if row marked as loaded', function () { + var row = new Backbone.Model({ name: 'db name' }); + row.status = { + loadSuccess: true, + dataSize: function () { return 0; }, + numDocs: function () { return 0; }, + updateSeq: function () { return 0; }, + isGraveYard: function () { return false; } + }; + + var databaseRow = TestUtils.renderIntoDocument(<Views.DatabaseTable body={[row]} />, container); + + assert.equal($(databaseRow.getDOMNode()).find('.database-load-fail').length, 0); + }); + }); });