You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by ro...@apache.org on 2016/02/12 16:32:11 UTC
fauxton commit: updated refs/heads/master to 6379614
Repository: couchdb-fauxton
Updated Branches:
refs/heads/master 0c9fcb4c9 -> 63796145e
make dbs deletable from db list
offer a modal for comfortable deletion from the database list.
additionally factor out `isSystemDatabase` and test it.
PR: #632
PR-URL: https://github.com/apache/couchdb-fauxton/pull/632
Reviewed-By: Benjamin Keen <be...@gmail.com>
Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/63796145
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/63796145
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/63796145
Branch: refs/heads/master
Commit: 63796145e1a9abac8b5d7ace8e721b379d9e6431
Parents: 0c9fcb4
Author: Robert Kowalski <ro...@apache.org>
Authored: Tue Jan 26 18:24:09 2016 +0100
Committer: Robert Kowalski <ro...@apache.org>
Committed: Fri Feb 12 15:31:54 2016 +0000
----------------------------------------------------------------------
app/addons/components/actions.js | 36 +++++++
app/addons/components/actiontypes.js | 3 +-
.../components/react-components.react.jsx | 103 ++++++++++++++++++-
app/addons/components/stores.js | 38 +++++++
.../tests/deleteDatabaseModalSpec.react.jsx | 78 ++++++++++++++
app/addons/databases/assets/less/databases.less | 1 +
app/addons/databases/components.react.jsx | 49 +++++++--
app/addons/databases/resources.js | 2 +-
app/addons/databases/stores.js | 11 +-
.../databases/tests/componentsSpec.react.jsx | 22 +++-
.../tests/nightwatch/deletesDatabase.js | 21 ++++
app/addons/documents/routes-documents.js | 6 +-
app/addons/documents/sidebar/sidebar.react.jsx | 4 +-
app/core/tests/utilsSpec.js | 11 ++
app/core/utils.js | 4 +
15 files changed, 362 insertions(+), 27 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/63796145/app/addons/components/actions.js
----------------------------------------------------------------------
diff --git a/app/addons/components/actions.js b/app/addons/components/actions.js
index 390877c..ca12b5d 100644
--- a/app/addons/components/actions.js
+++ b/app/addons/components/actions.js
@@ -36,7 +36,43 @@ function (FauxtonAPI, ActionTypes) {
});
}
+ function showDeleteDatabaseModal (options) {
+ FauxtonAPI.dispatch({
+ type: ActionTypes.COMPONENTS_DATABASES_SHOWDELETE_MODAL,
+ options: options
+ });
+ }
+
+ function deleteDatabase (dbId) {
+ var url = FauxtonAPI.urls('databaseBaseURL', 'server', dbId, '');
+
+ $.ajax({
+ url: url,
+ dataType: 'json',
+ type: 'DELETE'
+ }).then(function () {
+ this.showDeleteDatabaseModal({ showModal: true });
+
+ FauxtonAPI.addNotification({
+ msg: 'The database <code>' + _.escape(dbId) + '</code> has been deleted.',
+ clear: true,
+ escape: false // beware of possible XSS when the message changes
+ });
+
+ Backbone.history.loadUrl(FauxtonAPI.urls('allDBs', 'app'));
+
+ }.bind(this)).fail(function (rsp, error, msg) {
+ FauxtonAPI.addNotification({
+ msg: 'Could not delete the database, reason ' + msg + '.',
+ type: 'error',
+ clear: true
+ });
+ });
+ }
+
return {
+ deleteDatabase: deleteDatabase,
+ showDeleteDatabaseModal: showDeleteDatabaseModal,
showAPIBar: showAPIBar,
hideAPIBar: hideAPIBar,
updateAPIBar: updateAPIBar
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/63796145/app/addons/components/actiontypes.js
----------------------------------------------------------------------
diff --git a/app/addons/components/actiontypes.js b/app/addons/components/actiontypes.js
index c8d8f80..28e608d 100644
--- a/app/addons/components/actiontypes.js
+++ b/app/addons/components/actiontypes.js
@@ -15,7 +15,8 @@ define([], function () {
return {
SHOW_API_BAR: 'SHOW_API_BAR',
HIDE_API_BAR: 'HIDE_API_BAR',
- UPDATE_API_BAR: 'UPDATE_API_BAR'
+ UPDATE_API_BAR: 'UPDATE_API_BAR',
+ COMPONENTS_DATABASES_SHOWDELETE_MODAL: 'COMPONENTS_DATABASES_SHOWDELETE_MODAL'
};
});
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/63796145/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 fac7570..c5e19cd 100644
--- a/app/addons/components/react-components.react.jsx
+++ b/app/addons/components/react-components.react.jsx
@@ -16,6 +16,8 @@ define([
'react',
'react-dom',
'addons/components/stores',
+ 'addons/components/actions',
+
'addons/fauxton/components.react',
'addons/documents/helpers',
'ace/ace',
@@ -23,7 +25,8 @@ define([
'libs/react-bootstrap'
],
-function (app, FauxtonAPI, React, ReactDOM, Stores, FauxtonComponents, Helpers, ace, beautifyHelper, ReactBootstrap) {
+function (app, FauxtonAPI, React, ReactDOM, Stores, Actions,
+ FauxtonComponents, Helpers, ace, beautifyHelper, ReactBootstrap) {
var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;
var componentStore = Stores.componentStore;
@@ -1366,6 +1369,101 @@ function (app, FauxtonAPI, React, ReactDOM, Stores, FauxtonComponents, Helpers,
}
});
+ var DeleteDatabaseModal = React.createClass({
+
+ getInitialState: function () {
+ return {
+ inputValue: '',
+ disableSubmit: true
+ };
+ },
+
+ propTypes: {
+ dbId: React.PropTypes.string,
+ showHide: React.PropTypes.func.isRequired
+ },
+
+ close: function () {
+ this.setState({
+ inputValue: '',
+ disableSubmit: true
+ });
+
+ this.props.showHide({showModal: false});
+ },
+
+ open: function () {
+ this.props.showHide({showModal: true});
+ },
+
+ onInputChange: function (e) {
+ this.setState({
+ inputValue: e.target.value
+ });
+
+ this.setState({
+ disableSubmit: e.target.value.trim() !== this.props.showModal.dbId.trim()
+ });
+ },
+
+ onDeleteClick: function (e) {
+ e.preventDefault();
+
+ Actions.deleteDatabase(this.props.showModal.dbId.trim());
+ },
+
+ onInputKeypress: function (e) {
+ if (e.keyCode === 13 && this.state.disableSubmit !== true) {
+ Actions.deleteDatabase(this.props.showModal.dbId.trim());
+ }
+ },
+
+ render: function () {
+ var isSystemDatabase = this.props.showModal.isSystemDatabase;
+ var showDeleteModal = this.props.showModal.showDeleteModal;
+ var dbId = this.props.showModal.dbId;
+ var errorMessage = this.state.errorMessage;
+
+ var warning = isSystemDatabase ? (
+ <p className="warning"><b>You are about to delete a system database, be careful!</b></p>
+ ) : null;
+
+ return (
+ <Modal dialogClassName="delete-db-modal" show={showDeleteModal} onHide={this.close}>
+ <Modal.Header closeButton={true}>
+ <Modal.Title>Delete Database</Modal.Title>
+ </Modal.Header>
+ <Modal.Body>
+ {warning}
+ <p>
+ Warning: This action will permanently delete <code>{dbId}</code>.
+ To confirm the deletion of the database and all of the
+ database's documents, you must enter the database's name.
+ </p>
+ <input
+ type="text"
+ className="input-block-level"
+ onKeyUp={this.onInputKeypress}
+ onChange={this.onInputChange} />
+
+ </Modal.Body>
+ <Modal.Footer>
+ <button onClick={this.close} className="btn cancel-button">
+ <i className="icon fonticon-cancel-circled"></i> Cancel
+ </button>
+ <button
+ disabled={this.state.disableSubmit}
+ onClick={this.onDeleteClick}
+ className="btn btn-danger delete"
+ >
+ <i className="icon fonticon-ok-circled"></i> Delete
+ </button>
+ </Modal.Footer>
+ </Modal>
+ );
+ }
+ });
+
return {
BadgeList: BadgeList,
Badge: Badge,
@@ -1385,14 +1483,13 @@ function (app, FauxtonAPI, React, ReactDOM, Stores, FauxtonComponents, Helpers,
Tray: Tray,
TrayContents: TrayContents,
ApiBarController: ApiBarController,
-
renderMenuDropDown: function (el, opts) {
ReactDOM.render(<MenuDropDown icon="fonticon-cog" links={opts.links} />, el);
},
-
removeMenuDropDown: function (el) {
ReactDOM.unmountComponentAtNode(el);
},
+ DeleteDatabaseModal: DeleteDatabaseModal
};
});
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/63796145/app/addons/components/stores.js
----------------------------------------------------------------------
diff --git a/app/addons/components/stores.js b/app/addons/components/stores.js
index d5ec7d5..eccb002 100644
--- a/app/addons/components/stores.js
+++ b/app/addons/components/stores.js
@@ -79,6 +79,44 @@ function (FauxtonAPI, app, ActionTypes) {
}
});
+ Stores.DeleteDbModalStore = FauxtonAPI.Store.extend({
+ initialize: function () {
+ this.reset();
+ },
+
+ reset: function () {
+ this._deleteModal = {showDeleteModal: false, dbId: '', isSystemDatabase: false};
+ },
+
+ setDeleteModal: function (options) {
+ options.isSystemDatabase = app.utils.isSystemDatabase(options.dbId);
+ this._deleteModal = options;
+ },
+
+ getShowDeleteDatabaseModal: function () {
+ return this._deleteModal;
+ },
+
+ dispatch: function (action) {
+ switch (action.type) {
+ case ActionTypes.COMPONENTS_DATABASES_SHOWDELETE_MODAL:
+ this.setDeleteModal(action.options);
+ break;
+
+ default:
+ return;
+ }
+
+ this.triggerChange();
+ }
+ });
+
+
+
+
+ Stores.deleteDbModalStore = new Stores.DeleteDbModalStore();
+ Stores.deleteDbModalStore.dispatchToken = FauxtonAPI.dispatcher.register(Stores.deleteDbModalStore.dispatch);
+
Stores.componentStore = new Stores.ComponentStore();
Stores.componentStore.dispatchToken = FauxtonAPI.dispatcher.register(Stores.componentStore.dispatch);
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/63796145/app/addons/components/tests/deleteDatabaseModalSpec.react.jsx
----------------------------------------------------------------------
diff --git a/app/addons/components/tests/deleteDatabaseModalSpec.react.jsx b/app/addons/components/tests/deleteDatabaseModalSpec.react.jsx
new file mode 100644
index 0000000..6b4d62a
--- /dev/null
+++ b/app/addons/components/tests/deleteDatabaseModalSpec.react.jsx
@@ -0,0 +1,78 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+define([
+ 'api',
+ 'addons/components/react-components.react',
+
+ 'testUtils',
+ 'libs/react-bootstrap',
+ 'react'
+], function (FauxtonAPI, ReactComponents, utils, ReactBootstrap, React) {
+
+ var assert = utils.assert;
+ var TestUtils = React.addons.TestUtils;
+ var Modal = ReactBootstrap.Modal;
+
+ function noop () {}
+
+ describe('DeleteDatabaseModal', function () {
+ var container, instance;
+ beforeEach(function () {
+ container = document.createElement('div');
+ });
+
+ afterEach(function () {
+ React.unmountComponentAtNode(container);
+ });
+
+ it('submitting is disabled when initially rendered', function () {
+ instance = TestUtils.renderIntoDocument(
+ <ReactComponents.DeleteDatabaseModal
+ showHide={noop}
+ showModal={{isSystemDatabase: false, showDeleteModal: true, dbId: 'fooo'}} />,
+ container
+ );
+
+ assert.ok($('body').find('.modal').find('button.delete').prop('disabled'));
+ });
+
+ it('submitting is disabled when garbage entered', function () {
+ instance = TestUtils.renderIntoDocument(
+ <ReactComponents.DeleteDatabaseModal
+ showHide={noop}
+ showModal={{isSystemDatabase: false, showDeleteModal: true, dbId: 'fooo'}} />,
+ container
+ );
+
+ var input = $('body').find('.modal').find('input')[0];
+
+ TestUtils.Simulate.change(input, {target: {value: 'Hello, world'}});
+ assert.ok($('body').find('.modal').find('button.delete').prop('disabled'));
+ });
+
+ it('submitting is enabled when same db name entered', function () {
+ instance = TestUtils.renderIntoDocument(
+ <ReactComponents.DeleteDatabaseModal
+ showHide={noop}
+ showModal={{isSystemDatabase: false, showDeleteModal: true, dbId: 'fooo'}} />,
+ container
+ );
+
+ var input = $('body').find('.modal').find('input')[0];
+
+ TestUtils.Simulate.change(input, {target: {value: 'fooo'}});
+ assert.notOk($('body').find('.modal').find('button.delete').prop('disabled'));
+ });
+
+
+ });
+});
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/63796145/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 58763a5..fbc1ca2 100644
--- a/app/addons/databases/assets/less/databases.less
+++ b/app/addons/databases/assets/less/databases.less
@@ -27,6 +27,7 @@
.border-radius(6px);
text-decoration: none;
font-size: 19px;
+ margin-left: 10px;
}
td {
vertical-align: middle;
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/63796145/app/addons/databases/components.react.jsx
----------------------------------------------------------------------
diff --git a/app/addons/databases/components.react.jsx b/app/addons/databases/components.react.jsx
index 05e4b45..0ff6923 100644
--- a/app/addons/databases/components.react.jsx
+++ b/app/addons/databases/components.react.jsx
@@ -16,22 +16,30 @@ define([
'react',
'react-dom',
'addons/components/react-components.react',
+ 'addons/components/stores',
+ 'addons/components/actions',
'addons/fauxton/components.react',
+
'addons/databases/stores',
'addons/databases/resources',
'addons/databases/actions',
'helpers'
-], function (app, FauxtonAPI, React, ReactDOM, Components, ComponentsReact, Stores, Resources, Actions, Helpers) {
+], function (app, FauxtonAPI, React, ReactDOM, Components, ComponentsStore, ComponentsActions, FauxtonComponentsReact,
+ Stores, Resources, Actions, Helpers) {
var ToggleHeaderButton = Components.ToggleHeaderButton;
var databasesStore = Stores.databasesStore;
+ var deleteDbModalStore = ComponentsStore.deleteDbModalStore;
+ var DeleteDatabaseModal = Components.DeleteDatabaseModal;
+
var DatabasesController = React.createClass({
getStoreState: function () {
return {
collection: databasesStore.getCollection(),
- loading: databasesStore.isLoading()
+ loading: databasesStore.isLoading(),
+ showDeleteDatabaseModal: deleteDbModalStore.getShowDeleteDatabaseModal()
};
},
@@ -41,10 +49,12 @@ define([
componentDidMount: function () {
databasesStore.on('change', this.onChange, this);
+ deleteDbModalStore.on('change', this.onChange, this);
},
componentWillUnmount: function () {
databasesStore.off('change', this.onChange, this);
+ deleteDbModalStore.off('change', this.onChange, this);
},
onChange: function () {
@@ -55,7 +65,10 @@ define([
var collection = this.state.collection;
var loading = this.state.loading;
return (
- <DatabaseTable body={collection} loading={loading} />
+ <DatabaseTable
+ showDeleteDatabaseModal={this.state.showDeleteDatabaseModal}
+ body={collection}
+ loading={loading} />
);
}
});
@@ -65,7 +78,9 @@ define([
createRows: function () {
return _.map(this.props.body, function (item, iteration) {
return (
- <DatabaseRow row={item} key={iteration} />
+ <DatabaseRow
+ row={item}
+ key={iteration} />
);
});
},
@@ -77,6 +92,12 @@ define([
});
},
+ showDeleteDatabaseModal: function (name) {
+ ComponentsActions.showDeleteDatabaseModal({
+ showDeleteModal: !this.props.showDeleteDatabaseModal.showDeleteModal
+ });
+ },
+
render: function () {
if (this.props.loading) {
return (
@@ -85,9 +106,13 @@ define([
</div>
);
}
+
var rows = this.createRows();
return (
<div className="view">
+ <DeleteDatabaseModal
+ showHide={this.showDeleteDatabaseModal}
+ showModal={this.props.showDeleteDatabaseModal} />
<table className="databases table table-striped">
<thead>
<tr>
@@ -131,6 +156,10 @@ define([
});
},
+ showDeleteDatabaseModal: function (name) {
+ ComponentsActions.showDeleteDatabaseModal({showDeleteModal: true, dbId: name});
+ },
+
render: function () {
var row = this.props.row;
var name = row.get("name");
@@ -160,10 +189,14 @@ define([
<a
className="db-actions btn fonticon-replicate set-replication-start"
title={"Replicate " + name}
- href={"#/replication/" + encoded}></a> 
+ href={"#/replication/" + encoded}></a>
<a
className="db-actions btn icon-lock set-permissions"
title={"Set permissions for " + name} href={"#/database/" + encoded + "/permissions"}></a>
+ <a
+ className="db-actions btn icon-trash"
+ onClick={this.showDeleteDatabaseModal.bind(this, name)}
+ title={'Delete ' + name} data-bypass="true"></a>
</td>
</tr>
);
@@ -241,11 +274,11 @@ define([
title="Create Database"
fonticon="fonticon-new-database"
text="Create Database" />
- <ComponentsReact.Tray ref="newDbTray" className="new-database-tray">
+ <FauxtonComponentsReact.Tray ref="newDbTray" className="new-database-tray">
<span className="add-on">Create Database</span>
<input id="js-new-database-name" type="text" onKeyUp={this.onKeyUpInInput} ref="newDbName" className="input-xxlarge" placeholder="Name of database" />
<a className="btn" id="js-create-database" onClick={this.onAddDatabase}>Create</a>
- </ComponentsReact.Tray>
+ </FauxtonComponentsReact.Tray>
</div>
);
}
@@ -349,7 +382,7 @@ define([
return (
<footer className="all-db-footer pagination-footer">
<div id="database-pagination">
- <ComponentsReact.Pagination page={page} total={total} urlPrefix={urlPrefix} />
+ <FauxtonComponentsReact.Pagination page={page} total={total} urlPrefix={urlPrefix} />
</div>
</footer>
);
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/63796145/app/addons/databases/resources.js
----------------------------------------------------------------------
diff --git a/app/addons/databases/resources.js b/app/addons/databases/resources.js
index 577f3f4..2af0a25 100644
--- a/app/addons/databases/resources.js
+++ b/app/addons/databases/resources.js
@@ -50,7 +50,7 @@ function (app, FauxtonAPI, Documents) {
},
isSystemDatabase: function () {
- return (/^_/).test(this.id);
+ return app.utils.isSystemDatabase(this.id);
},
url: function (context) {
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/63796145/app/addons/databases/stores.js
----------------------------------------------------------------------
diff --git a/app/addons/databases/stores.js b/app/addons/databases/stores.js
index cdae6df..0f73b52 100644
--- a/app/addons/databases/stores.js
+++ b/app/addons/databases/stores.js
@@ -94,32 +94,33 @@ define([
this.init(action.options.collection, action.options.backboneCollection);
this.setPage(action.options.page);
this.setLoading(false);
- this.triggerChange();
break;
case ActionTypes.DATABASES_SETPAGE:
this.setPage(action.options.page);
- this.triggerChange();
break;
case ActionTypes.DATABASES_SET_PROMPT_VISIBLE:
this.setPromptVisible(action.options.visible);
- this.triggerChange();
break;
case ActionTypes.DATABASES_STARTLOADING:
this.setLoading(true);
- this.triggerChange();
break;
case ActionTypes.DATABASES_LOADCOMPLETE:
this.setLoading(false);
- this.triggerChange();
+ break;
+
+ case ActionTypes.DATABASES_SHOWDELETE_MODAL:
+ this.setDeleteModal(action.options);
break;
default:
return;
}
+
+ this.triggerChange();
}
});
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/63796145/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 f57c5c2..d6540c1 100644
--- a/app/addons/databases/tests/componentsSpec.react.jsx
+++ b/app/addons/databases/tests/componentsSpec.react.jsx
@@ -100,7 +100,7 @@ define([
assert.equal("2.0 MB", dbEl.getDOMNode().getElementsByTagName('tr')[1].getElementsByTagName('td')[1].innerText.trim());
assert.equal("88", dbEl.getDOMNode().getElementsByTagName('tr')[1].getElementsByTagName('td')[2].innerText.trim());
assert.equal(0, dbEl.getDOMNode().getElementsByTagName('tr')[1].getElementsByTagName('td')[2].getElementsByTagName("i").length);
- assert.equal(2, dbEl.getDOMNode().getElementsByTagName('tr')[1].getElementsByTagName('td')[4].getElementsByTagName("a").length);
+ assert.equal(3, dbEl.getDOMNode().getElementsByTagName('tr')[1].getElementsByTagName('td')[4].getElementsByTagName("a").length);
assert.equal("db2", dbEl.getDOMNode().getElementsByTagName('tr')[2].getElementsByTagName('td')[0].innerText.trim());
assert.equal(1, dbEl.getDOMNode().getElementsByTagName('tr')[2].getElementsByTagName('td')[2].getElementsByTagName("i").length);
});
@@ -255,7 +255,10 @@ define([
FauxtonAPI.registerExtension('DatabaseTable:head', ColHeader2);
FauxtonAPI.registerExtension('DatabaseTable:head', ColHeader3);
- var table = TestUtils.renderIntoDocument(<Views.DatabaseTable loading={false} body={[]} />, container);
+ var table = TestUtils.renderIntoDocument(
+ <Views.DatabaseTable showDeleteDatabaseModal={{showModal: false}} loading={false} body={[]} />,
+ container
+ );
var cols = $(ReactDOM.findDOMNode(table)).find('th');
// (default # of rows is 5)
@@ -280,7 +283,10 @@ define([
isGraveYard: function () { return false; }
};
- var databaseRow = TestUtils.renderIntoDocument(<Views.DatabaseTable body={[row]} />, container);
+ var databaseRow = TestUtils.renderIntoDocument(
+ <Views.DatabaseTable showDeleteDatabaseModal={{showModal: false}} body={[row]} />,
+ container
+ );
var links = $(ReactDOM.findDOMNode(databaseRow)).find('td');
// (default # of rows is 5)
@@ -301,7 +307,10 @@ define([
isGraveYard: function () { return false; }
};
- var databaseRow = TestUtils.renderIntoDocument(<Views.DatabaseTable body={[row]} />, container);
+ var databaseRow = TestUtils.renderIntoDocument(
+ <Views.DatabaseTable showDeleteDatabaseModal={{showModal: false}} body={[row]} />,
+ container
+ );
assert.equal($(ReactDOM.findDOMNode(databaseRow)).find('.database-load-fail').length, 1);
});
@@ -315,7 +324,10 @@ define([
isGraveYard: function () { return false; }
};
- var databaseRow = TestUtils.renderIntoDocument(<Views.DatabaseTable body={[row]} />, container);
+ var databaseRow = TestUtils.renderIntoDocument(
+ <Views.DatabaseTable showDeleteDatabaseModal={{showModal: false}} body={[row]} />,
+ container
+ );
assert.equal($(ReactDOM.findDOMNode(databaseRow)).find('.database-load-fail').length, 0);
});
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/63796145/app/addons/databases/tests/nightwatch/deletesDatabase.js
----------------------------------------------------------------------
diff --git a/app/addons/databases/tests/nightwatch/deletesDatabase.js b/app/addons/databases/tests/nightwatch/deletesDatabase.js
index 4d05410..d3f7eea 100644
--- a/app/addons/databases/tests/nightwatch/deletesDatabase.js
+++ b/app/addons/databases/tests/nightwatch/deletesDatabase.js
@@ -31,5 +31,26 @@ module.exports = {
.checkForDatabaseDeleted(newDatabaseName, waitTime)
.end();
+ },
+
+ 'Deletes a database from the list': function (client) {
+ var waitTime = client.globals.maxWaitTime,
+ newDatabaseName = client.globals.testDatabaseName,
+ baseUrl = client.globals.test_settings.launch_url;
+
+ client
+ .createDatabase(newDatabaseName)
+ .loginToGUI()
+ .url(baseUrl + '/#/_all_dbs/')
+
+ .waitForElementPresent('a[href="#/database/' + newDatabaseName + '/_all_docs"]', waitTime, false)
+ .assert.elementPresent('a[href="#/database/' + newDatabaseName + '/_all_docs"]')
+ .clickWhenVisible('[title="Delete ' + newDatabaseName + '"]', waitTime, false)
+ .setValue('.delete-db-modal input[type="text"]', [newDatabaseName, client.Keys.ENTER])
+ .checkForDatabaseDeleted(newDatabaseName, waitTime)
+ .assert.elementNotPresent('a[href="#/database/' + newDatabaseName + '/_all_docs"]')
+
+
+ .end();
}
};
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/63796145/app/addons/documents/routes-documents.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/routes-documents.js b/app/addons/documents/routes-documents.js
index 17afb3e..3829981 100644
--- a/app/addons/documents/routes-documents.js
+++ b/app/addons/documents/routes-documents.js
@@ -30,12 +30,13 @@ define([
'addons/documents/header/header.actions',
'addons/documents/sidebar/actions',
'addons/documents/designdocinfo/actions',
- 'addons/documents/designdocinfo/components.react'
+ 'addons/documents/designdocinfo/components.react',
+ 'addons/components/actions',
],
function (app, FauxtonAPI, BaseRoute, Documents, Changes, ChangesActions, Databases, Resources, Components,
IndexResultStores, IndexResultsActions, IndexResultsComponents, ReactPagination, ReactHeader, ReactActions,
- SidebarActions, DesignDocInfoActions, DesignDocInfoComponents) {
+ SidebarActions, DesignDocInfoActions, DesignDocInfoComponents, ComponentsActions) {
var DocumentsRouteObject = BaseRoute.extend({
layout: "with_tabs_sidebar",
@@ -137,6 +138,7 @@ function (app, FauxtonAPI, BaseRoute, Documents, Changes, ChangesActions, Databa
}
SidebarActions.setSelectedTab(tab);
+ ComponentsActions.showDeleteDatabaseModal({showDeleteModal: false, dbId: ''});
this.removeComponent('#dashboard-upper-content');
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/63796145/app/addons/documents/sidebar/sidebar.react.jsx
----------------------------------------------------------------------
diff --git a/app/addons/documents/sidebar/sidebar.react.jsx b/app/addons/documents/sidebar/sidebar.react.jsx
index dd5abc2..471aeb6 100644
--- a/app/addons/documents/sidebar/sidebar.react.jsx
+++ b/app/addons/documents/sidebar/sidebar.react.jsx
@@ -325,8 +325,8 @@ function (app, FauxtonAPI, React, ReactDOM, Stores, Actions, Components, Documen
componentDidMount: function () {
this.dbModal = new DeleteDBModal({
database: this.props.database,
- isSystemDatabase: (/^_/).test(this.props.database.id),
- el: ReactDOM.findDOMNode(this)
+ el: ReactDOM.findDOMNode(this),
+ isSystemDatabase: app.utils.isSystemDatabase(this.props.database.id)
});
this.dbModal.render();
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/63796145/app/core/tests/utilsSpec.js
----------------------------------------------------------------------
diff --git a/app/core/tests/utilsSpec.js b/app/core/tests/utilsSpec.js
index c6e09af..a52cea5 100644
--- a/app/core/tests/utilsSpec.js
+++ b/app/core/tests/utilsSpec.js
@@ -49,6 +49,17 @@ define([
});
});
+ describe('isSystemDatabase', function () {
+
+ it('detects system databases', function () {
+ assert.ok(utils.isSystemDatabase('_replicator'));
+ });
+
+ it('ignores other dbs', function () {
+ assert.notOk(utils.isSystemDatabase('foo'));
+ });
+ });
+
describe('localStorage', function () {
it('Should get undefined when getting a non-existent key', function () {
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/63796145/app/core/utils.js
----------------------------------------------------------------------
diff --git a/app/core/utils.js b/app/core/utils.js
index 6948526..fe93802 100644
--- a/app/core/utils.js
+++ b/app/core/utils.js
@@ -84,6 +84,10 @@ function ($, _) {
return 'doc';
},
+ isSystemDatabase: function (id) {
+ return (/^_/).test(id);
+ },
+
// Need this to work around backbone router thinking _design/foo
// is a separate route. Alternatively, maybe these should be
// treated separately. For instance, we could default into the