You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by ga...@apache.org on 2016/05/31 07:58:36 UTC
[08/27] fauxton commit: updated refs/heads/master to 0ca35da
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/0ca35da7/app/addons/documents/tests/resourcesSpec.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/tests/resourcesSpec.js b/app/addons/documents/tests/resourcesSpec.js
index 176d726..661209b 100644
--- a/app/addons/documents/tests/resourcesSpec.js
+++ b/app/addons/documents/tests/resourcesSpec.js
@@ -9,459 +9,456 @@
// 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([
- '../../../core/api',
- '../resources',
- '../../../../test/mocha/testUtils',
- '../base'
-], function (FauxtonAPI, Models, testUtils) {
- var assert = testUtils.assert;
-
- describe('IndexCollection', function () {
- var collection;
- beforeEach(function () {
- collection = new Models.IndexCollection([{
- id:'myId1',
- doc: 'num1'
- },
- {
- id:'myId2',
- doc: 'num2'
- }], {
- database: {id: 'databaseId', safeID: function () { return this.id; }},
- design: '_design/myDoc'
- });
+import FauxtonAPI from "../../../core/api";
+import Models from "../resources";
+import testUtils from "../../../../test/mocha/testUtils";
+import "../base";
+var assert = testUtils.assert;
+
+describe('IndexCollection', function () {
+ var collection;
+ beforeEach(function () {
+ collection = new Models.IndexCollection([{
+ id:'myId1',
+ doc: 'num1'
+ },
+ {
+ id:'myId2',
+ doc: 'num2'
+ }], {
+ database: {id: 'databaseId', safeID: function () { return this.id; }},
+ design: '_design/myDoc'
});
+ });
- it('creates the right api-url with an absolute url', function () {
- assert.ok(/file:/.test(collection.urlRef('apiurl')));
- });
+ it('creates the right api-url with an absolute url', function () {
+ assert.ok(/file:/.test(collection.urlRef('apiurl')));
+ });
+
+});
+describe('Document', function () {
+ var doc;
+ beforeEach(function () {
+ doc = new Models.Doc({}, {});
});
- describe('Document', function () {
- var doc;
- beforeEach(function () {
- doc = new Models.Doc({}, {});
+ it('does not remove an id attribute', function () {
+ var res = doc.parse({
+ _id: 'be31e531fe131bdf416b479ac1000484',
+ _rev: '4-3a1b9f4b988b413e9245cd250769da72',
+ id: 'foo'
});
+ assert.equal(res.id, 'foo');
+ });
- it('does not remove an id attribute', function () {
- var res = doc.parse({
- _id: 'be31e531fe131bdf416b479ac1000484',
- _rev: '4-3a1b9f4b988b413e9245cd250769da72',
- id: 'foo'
- });
- assert.equal(res.id, 'foo');
+ it('removes the id, if we create a document and get back an "id" instead of "_id"', function () {
+ // if we take the document {"_id": "mycustomid", "_rev": "18-9cdeb1b121137233e3466b06a1780c29", id: "foo"}
+ // and do a PUT request for an update, CouchDB will return:
+ // {"ok":true,"id":"mycustomid","rev":"18-9cdeb1b121137233e3466b06a1780c29"}
+ // and our Model will think it has the id "mycustomid" instead of "foo"
+ var res = doc.parse({
+ id: 'be31e531fe131bdf416b479ac1000484',
+ _rev: '4-3a1b9f4b988b413e9245cd250769da72',
+ ok: true
});
+ assert.notOk(res.id);
+ });
- it('removes the id, if we create a document and get back an "id" instead of "_id"', function () {
- // if we take the document {"_id": "mycustomid", "_rev": "18-9cdeb1b121137233e3466b06a1780c29", id: "foo"}
- // and do a PUT request for an update, CouchDB will return:
- // {"ok":true,"id":"mycustomid","rev":"18-9cdeb1b121137233e3466b06a1780c29"}
- // and our Model will think it has the id "mycustomid" instead of "foo"
- var res = doc.parse({
- id: 'be31e531fe131bdf416b479ac1000484',
- _rev: '4-3a1b9f4b988b413e9245cd250769da72',
- ok: true
- });
- assert.notOk(res.id);
+ it('can return the doc url, if id given', function () {
+ doc = new Models.Doc({_id: 'scholle'}, {
+ database: {id: 'blerg', safeID: function () { return this.id; }}
});
- it('can return the doc url, if id given', function () {
- doc = new Models.Doc({_id: 'scholle'}, {
- database: {id: 'blerg', safeID: function () { return this.id; }}
- });
+ assert.ok(/\/blerg/.test(doc.url('apiurl')));
+ });
- assert.ok(/\/blerg/.test(doc.url('apiurl')));
+ it('will return the API url to create a new doc, if no doc exists yet', function () {
+ doc = new Models.Doc({}, {
+ database: {id: 'blerg', safeID: function () { return this.id; }}
});
- it('will return the API url to create a new doc, if no doc exists yet', function () {
- doc = new Models.Doc({}, {
- database: {id: 'blerg', safeID: function () { return this.id; }}
- });
-
- assert.ok(/\/blerg/.test(doc.url('apiurl')));
- });
+ assert.ok(/\/blerg/.test(doc.url('apiurl')));
});
+});
- describe('MangoIndex', function () {
- var doc;
+describe('MangoIndex', function () {
+ var doc;
- it('is deleteable', function () {
- var index = {
- ddoc: null,
- name: '_all_docs',
- type: 'json',
- def: {fields: [{_id: 'asc'}]}
- };
- doc = new Models.MangoIndex(index, {});
+ it('is deleteable', function () {
+ var index = {
+ ddoc: null,
+ name: '_all_docs',
+ type: 'json',
+ def: {fields: [{_id: 'asc'}]}
+ };
+ doc = new Models.MangoIndex(index, {});
- assert.ok(doc.isDeletable());
- });
+ assert.ok(doc.isDeletable());
+ });
- it('special docs are not deleteable', function () {
- var index = {
- ddoc: null,
- name: '_all_docs',
- type: 'special',
- def: {fields: [{_id: 'asc'}]}
- };
- doc = new Models.MangoIndex(index, {});
+ it('special docs are not deleteable', function () {
+ var index = {
+ ddoc: null,
+ name: '_all_docs',
+ type: 'special',
+ def: {fields: [{_id: 'asc'}]}
+ };
+ doc = new Models.MangoIndex(index, {});
- assert.notOk(doc.isDeletable());
- });
+ assert.notOk(doc.isDeletable());
});
+});
- describe('MangoDocumentCollection', function () {
- var collection;
-
- it('gets 1 doc more to know if there are more than 20', function () {
- collection = new Models.MangoDocumentCollection([{
- name: 'myId1',
- doc: 'num1'
- },
- {
- name: 'myId2',
- doc: 'num2'
- }], {
- database: {id: 'databaseId', safeID: function () { return this.id; }},
- params: {limit: 20}
- });
- collection.setQuery({
- selector: '$foo',
- fields: 'bla'
- });
+describe('MangoDocumentCollection', function () {
+ var collection;
- assert.deepEqual({
- selector: '$foo',
- fields: 'bla',
- limit: 21,
- skip: undefined
- }, collection.getPaginatedQuery());
+ it('gets 1 doc more to know if there are more than 20', function () {
+ collection = new Models.MangoDocumentCollection([{
+ name: 'myId1',
+ doc: 'num1'
+ },
+ {
+ name: 'myId2',
+ doc: 'num2'
+ }], {
+ database: {id: 'databaseId', safeID: function () { return this.id; }},
+ params: {limit: 20}
});
-
- it('on next page, skips first 20', function () {
- collection = new Models.MangoDocumentCollection([{
- name: 'myId1',
- doc: 'num1'
- },
- {
- name: 'myId2',
- doc: 'num2'
- }], {
- database: {id: 'databaseId', safeID: function () { return this.id; }},
- params: {limit: 20}
- });
- collection.setQuery({
- selector: '$foo',
- fields: 'bla'
- });
- collection.next();
- assert.deepEqual({
- selector: '$foo',
- fields: 'bla',
- limit: 21,
- skip: 20
- }, collection.getPaginatedQuery());
+ collection.setQuery({
+ selector: '$foo',
+ fields: 'bla'
});
+ assert.deepEqual({
+ selector: '$foo',
+ fields: 'bla',
+ limit: 21,
+ skip: undefined
+ }, collection.getPaginatedQuery());
});
- describe('MangoDocumentCollection', function () {
- var collection;
-
- it('is not editable', function () {
- collection = new Models.MangoIndexCollection([{
- name: 'myId1',
- doc: 'num1'
- },
- {
- name: 'myId2',
- doc: 'num2'
- }], {
- database: {id: 'databaseId', safeID: function () { return this.id; }},
- params: {limit: 20}
- });
+ it('on next page, skips first 20', function () {
+ collection = new Models.MangoDocumentCollection([{
+ name: 'myId1',
+ doc: 'num1'
+ },
+ {
+ name: 'myId2',
+ doc: 'num2'
+ }], {
+ database: {id: 'databaseId', safeID: function () { return this.id; }},
+ params: {limit: 20}
+ });
+ collection.setQuery({
+ selector: '$foo',
+ fields: 'bla'
+ });
+ collection.next();
+ assert.deepEqual({
+ selector: '$foo',
+ fields: 'bla',
+ limit: 21,
+ skip: 20
+ }, collection.getPaginatedQuery());
+ });
- assert.notOk(collection.isEditable());
+});
+
+describe('MangoDocumentCollection', function () {
+ var collection;
+
+ it('is not editable', function () {
+ collection = new Models.MangoIndexCollection([{
+ name: 'myId1',
+ doc: 'num1'
+ },
+ {
+ name: 'myId2',
+ doc: 'num2'
+ }], {
+ database: {id: 'databaseId', safeID: function () { return this.id; }},
+ params: {limit: 20}
});
+
+ assert.notOk(collection.isEditable());
});
+});
- describe('IndexCollection', function () {
- var collection;
-
- it('design docs are editable', function () {
- collection = new Models.IndexCollection([{
- _id: 'myId1',
- doc: 'num1'
- },
- {
- _id: 'myId2',
- doc: 'num2'
- }], {
- database: {id: 'databaseId', safeID: function () { return this.id; }},
- params: {limit: 20},
- design: '_design/foobar'
- });
+describe('IndexCollection', function () {
+ var collection;
- assert.ok(collection.isEditable());
+ it('design docs are editable', function () {
+ collection = new Models.IndexCollection([{
+ _id: 'myId1',
+ doc: 'num1'
+ },
+ {
+ _id: 'myId2',
+ doc: 'num2'
+ }], {
+ database: {id: 'databaseId', safeID: function () { return this.id; }},
+ params: {limit: 20},
+ design: '_design/foobar'
});
- it('reduced design docs are NOT editable', function () {
- collection = new Models.IndexCollection([{
- _id: 'myId1',
- doc: 'num1'
- },
- {
- _id: 'myId2',
- doc: 'num2'
- }], {
- database: {id: 'databaseId', safeID: function () { return this.id; }},
- params: {limit: 20, reduce: true},
- design: '_design/foobar'
- });
+ assert.ok(collection.isEditable());
+ });
- assert.notOk(collection.isEditable());
+ it('reduced design docs are NOT editable', function () {
+ collection = new Models.IndexCollection([{
+ _id: 'myId1',
+ doc: 'num1'
+ },
+ {
+ _id: 'myId2',
+ doc: 'num2'
+ }], {
+ database: {id: 'databaseId', safeID: function () { return this.id; }},
+ params: {limit: 20, reduce: true},
+ design: '_design/foobar'
});
+
+ assert.notOk(collection.isEditable());
});
+});
- describe('AllDocs', function () {
- var collection;
-
- it('all-docs-list documents are always editable', function () {
- collection = new Models.AllDocs([{
- _id: 'myId1',
- doc: 'num1'
- },
- {
- _id: 'myId2',
- doc: 'num2'
- }], {
- database: {id: 'databaseId', safeID: function () { return this.id; }},
- params: {limit: 20}
- });
+describe('AllDocs', function () {
+ var collection;
- assert.ok(collection.isEditable());
+ it('all-docs-list documents are always editable', function () {
+ collection = new Models.AllDocs([{
+ _id: 'myId1',
+ doc: 'num1'
+ },
+ {
+ _id: 'myId2',
+ doc: 'num2'
+ }], {
+ database: {id: 'databaseId', safeID: function () { return this.id; }},
+ params: {limit: 20}
});
+
+ assert.ok(collection.isEditable());
});
+});
- describe('QueryParams', function () {
- describe('parse', function () {
- it('should not parse arbitrary parameters', function () {
- var params = {'foo': '[1]]'};
- var result = Models.QueryParams.parse(params);
+describe('QueryParams', function () {
+ describe('parse', function () {
+ it('should not parse arbitrary parameters', function () {
+ var params = {'foo': '[1]]'};
+ var result = Models.QueryParams.parse(params);
- assert.deepEqual(result, params);
- });
+ assert.deepEqual(result, params);
+ });
+
+ it('parses startkey, endkey', function () {
+ var params = {
+ 'startkey':'[\"a\",\"b\"]',
+ 'endkey':'[\"c\",\"d\"]'
+ };
+ var result = Models.QueryParams.parse(params);
- it('parses startkey, endkey', function () {
- var params = {
- 'startkey':'[\"a\",\"b\"]',
- 'endkey':'[\"c\",\"d\"]'
- };
- var result = Models.QueryParams.parse(params);
-
- assert.deepEqual(result, {
- 'startkey': ['a', 'b'],
- 'endkey': ['c', 'd']
- });
+ assert.deepEqual(result, {
+ 'startkey': ['a', 'b'],
+ 'endkey': ['c', 'd']
});
+ });
- it('parses key', function () {
- var params = {
- key:'[1,2]'
- };
- var result = Models.QueryParams.parse(params);
+ it('parses key', function () {
+ var params = {
+ key:'[1,2]'
+ };
+ var result = Models.QueryParams.parse(params);
- assert.deepEqual(result, {'key': [1, 2]});
- });
+ assert.deepEqual(result, {'key': [1, 2]});
+ });
- it('does not modify input', function () {
- var params = {
- key:'[\"a\",\"b\"]'
- };
- var clone = _.clone(params);
- var result = Models.QueryParams.parse(params);
+ it('does not modify input', function () {
+ var params = {
+ key:'[\"a\",\"b\"]'
+ };
+ var clone = _.clone(params);
+ var result = Models.QueryParams.parse(params);
- assert.deepEqual(params, clone);
- });
+ assert.deepEqual(params, clone);
});
+ });
- describe('stringify', function () {
- it('should not stringify arbitrary parameters', function () {
- var params = {'foo': [1, 2, 3]};
- var result = Models.QueryParams.stringify(params);
+ describe('stringify', function () {
+ it('should not stringify arbitrary parameters', function () {
+ var params = {'foo': [1, 2, 3]};
+ var result = Models.QueryParams.stringify(params);
- assert.deepEqual(result, params);
- });
+ assert.deepEqual(result, params);
+ });
- it('stringifies startkey, endkey', function () {
- var params = {
- 'startkey': ['a', 'b'],
- 'endkey': ['c', 'd']
- };
+ it('stringifies startkey, endkey', function () {
+ var params = {
+ 'startkey': ['a', 'b'],
+ 'endkey': ['c', 'd']
+ };
- var result = Models.QueryParams.stringify(params);
+ var result = Models.QueryParams.stringify(params);
- assert.deepEqual(result, {
- 'startkey':'[\"a\",\"b\"]',
- 'endkey':'[\"c\",\"d\"]'
- });
+ assert.deepEqual(result, {
+ 'startkey':'[\"a\",\"b\"]',
+ 'endkey':'[\"c\",\"d\"]'
});
+ });
- it('stringifies key', function () {
- var params = {'key':['a', 'b']};
- var result = Models.QueryParams.stringify(params);
+ it('stringifies key', function () {
+ var params = {'key':['a', 'b']};
+ var result = Models.QueryParams.stringify(params);
- assert.deepEqual(result, { 'key': '[\"a\",\"b\"]' });
- });
+ assert.deepEqual(result, { 'key': '[\"a\",\"b\"]' });
+ });
- it('does not modify input', function () {
- var params = {'key': ['a', 'b']};
- var clone = _.clone(params);
- var result = Models.QueryParams.stringify(params);
+ it('does not modify input', function () {
+ var params = {'key': ['a', 'b']};
+ var clone = _.clone(params);
+ var result = Models.QueryParams.stringify(params);
- assert.deepEqual(params, clone);
- });
+ assert.deepEqual(params, clone);
+ });
- it('is symmetrical with parse', function () {
- var params = {
- 'startkey': ['a', 'b'],
- 'endkey': ['c', 'd'],
- 'foo': '[1,2]',
- 'bar': 'abc'
- };
+ it('is symmetrical with parse', function () {
+ var params = {
+ 'startkey': ['a', 'b'],
+ 'endkey': ['c', 'd'],
+ 'foo': '[1,2]',
+ 'bar': 'abc'
+ };
- var clone = _.clone(params);
- var json = Models.QueryParams.stringify(params);
- var result = Models.QueryParams.parse(json);
+ var clone = _.clone(params);
+ var json = Models.QueryParams.stringify(params);
+ var result = Models.QueryParams.parse(json);
- assert.deepEqual(result, clone);
- });
+ assert.deepEqual(result, clone);
});
});
+});
- describe('Bulk Delete', function () {
- var databaseId = 'ente',
- collection,
- promise,
- values;
-
- values = [{
- _id: '1',
- _rev: '1234561',
- _deleted: true
- },
- {
- _id: '2',
- _rev: '1234562',
- _deleted: true
- },
- {
- _id: '3',
- _rev: '1234563',
- _deleted: true
- }];
-
- beforeEach(function () {
- collection = new Models.BulkDeleteDocCollection(values, {
- databaseId: databaseId
- });
-
- promise = FauxtonAPI.Deferred();
+describe('Bulk Delete', function () {
+ var databaseId = 'ente',
+ collection,
+ promise,
+ values;
+
+ values = [{
+ _id: '1',
+ _rev: '1234561',
+ _deleted: true
+ },
+ {
+ _id: '2',
+ _rev: '1234562',
+ _deleted: true
+ },
+ {
+ _id: '3',
+ _rev: '1234563',
+ _deleted: true
+ }];
+
+ beforeEach(function () {
+ collection = new Models.BulkDeleteDocCollection(values, {
+ databaseId: databaseId
});
- it('contains the models', function () {
- collection = new Models.BulkDeleteDocCollection(values, {
- databaseId: databaseId
- });
+ promise = FauxtonAPI.Deferred();
+ });
- assert.equal(collection.length, 3);
+ it('contains the models', function () {
+ collection = new Models.BulkDeleteDocCollection(values, {
+ databaseId: databaseId
});
- it('clears the memory if no errors happened', function () {
- collection.handleResponse([
- {'ok': true, 'id': '1', 'rev': '10-72cd2edbcc0d197ce96188a229a7af01'},
- {'ok': true, 'id': '2', 'rev': '6-da537822b9672a4b2f42adb1be04a5b1'}
- ], promise);
+ assert.equal(collection.length, 3);
+ });
- assert.equal(collection.length, 1);
- });
+ it('clears the memory if no errors happened', function () {
+ collection.handleResponse([
+ {'ok': true, 'id': '1', 'rev': '10-72cd2edbcc0d197ce96188a229a7af01'},
+ {'ok': true, 'id': '2', 'rev': '6-da537822b9672a4b2f42adb1be04a5b1'}
+ ], promise);
- it('triggers a removed event with all ids', function () {
- collection.listenToOnce(collection, 'removed', function (ids) {
- assert.deepEqual(ids, ['Deferred', 'DeskSet']);
- });
+ assert.equal(collection.length, 1);
+ });
- collection.handleResponse([
- {'ok': true, 'id': 'Deferred', 'rev':'10-72cd2edbcc0d197ce96188a229a7af01'},
- {'ok': true, 'id': 'DeskSet', 'rev':'6-da537822b9672a4b2f42adb1be04a5b1'}
- ], promise);
+ it('triggers a removed event with all ids', function () {
+ collection.listenToOnce(collection, 'removed', function (ids) {
+ assert.deepEqual(ids, ['Deferred', 'DeskSet']);
});
- it('triggers a error event with all errored ids', function () {
- collection.listenToOnce(collection, 'error', function (ids) {
- assert.deepEqual(ids, ['Deferred']);
- });
- collection.handleResponse([
- {'error':'conflict', 'id':'Deferred', 'rev':'10-72cd2edbcc0d197ce96188a229a7af01'},
- {'ok':true, 'id':'DeskSet', 'rev':'6-da537822b9672a4b2f42adb1be04a5b1'}
- ], promise);
- });
+ collection.handleResponse([
+ {'ok': true, 'id': 'Deferred', 'rev':'10-72cd2edbcc0d197ce96188a229a7af01'},
+ {'ok': true, 'id': 'DeskSet', 'rev':'6-da537822b9672a4b2f42adb1be04a5b1'}
+ ], promise);
+ });
- it('removes successfull deleted from the collection but keeps one with errors', function () {
- collection.handleResponse([
- {'error':'conflict', 'id':'1', 'rev':'10-72cd2edbcc0d197ce96188a229a7af01'},
- {'ok':true, 'id':'2', 'rev':'6-da537822b9672a4b2f42adb1be04a5b1'},
- {'error':'conflict', 'id':'3', 'rev':'6-da537822b9672a4b2f42adb1be04a5b1'}
- ], promise);
- assert.ok(collection.get('1'));
- assert.ok(collection.get('3'));
- assert.notOk(collection.get('2'));
+ it('triggers a error event with all errored ids', function () {
+ collection.listenToOnce(collection, 'error', function (ids) {
+ assert.deepEqual(ids, ['Deferred']);
});
+ collection.handleResponse([
+ {'error':'conflict', 'id':'Deferred', 'rev':'10-72cd2edbcc0d197ce96188a229a7af01'},
+ {'ok':true, 'id':'DeskSet', 'rev':'6-da537822b9672a4b2f42adb1be04a5b1'}
+ ], promise);
+ });
- it('triggers resolve for successful delete', function () {
- var spy = sinon.spy();
- promise.then(spy);
-
- collection.handleResponse([
- {'ok':true, 'id':'Deferred', 'rev':'10-72cd2edbcc0d197ce96188a229a7af01'},
- {'ok':true, 'id':'DeskSet', 'rev':'6-da537822b9672a4b2f42adb1be04a5b1'}
- ], promise);
+ it('removes successfull deleted from the collection but keeps one with errors', function () {
+ collection.handleResponse([
+ {'error':'conflict', 'id':'1', 'rev':'10-72cd2edbcc0d197ce96188a229a7af01'},
+ {'ok':true, 'id':'2', 'rev':'6-da537822b9672a4b2f42adb1be04a5b1'},
+ {'error':'conflict', 'id':'3', 'rev':'6-da537822b9672a4b2f42adb1be04a5b1'}
+ ], promise);
+ assert.ok(collection.get('1'));
+ assert.ok(collection.get('3'));
+ assert.notOk(collection.get('2'));
+ });
- assert.ok(spy.calledOnce);
+ it('triggers resolve for successful delete', function () {
+ var spy = sinon.spy();
+ promise.then(spy);
- });
+ collection.handleResponse([
+ {'ok':true, 'id':'Deferred', 'rev':'10-72cd2edbcc0d197ce96188a229a7af01'},
+ {'ok':true, 'id':'DeskSet', 'rev':'6-da537822b9672a4b2f42adb1be04a5b1'}
+ ], promise);
- it('triggers resolve for successful delete with errors as well', function () {
- var spy = sinon.spy();
- promise.then(spy);
- var ids = {
- errorIds: ['1'],
- successIds: ['Deferred', 'DeskSet']
- };
+ assert.ok(spy.calledOnce);
- collection.handleResponse([
- {'ok':true, 'id':'Deferred', 'rev':'10-72cd2edbcc0d197ce96188a229a7af01'},
- {'ok':true, 'id':'DeskSet', 'rev':'6-da537822b9672a4b2f42adb1be04a5b1'},
- {'error':'conflict', 'id':'1', 'rev':'10-72cd2edbcc0d197ce96188a229a7af01'},
- ], promise);
+ });
- assert.ok(spy.calledWith(ids));
- });
+ it('triggers resolve for successful delete with errors as well', function () {
+ var spy = sinon.spy();
+ promise.then(spy);
+ var ids = {
+ errorIds: ['1'],
+ successIds: ['Deferred', 'DeskSet']
+ };
+
+ collection.handleResponse([
+ {'ok':true, 'id':'Deferred', 'rev':'10-72cd2edbcc0d197ce96188a229a7af01'},
+ {'ok':true, 'id':'DeskSet', 'rev':'6-da537822b9672a4b2f42adb1be04a5b1'},
+ {'error':'conflict', 'id':'1', 'rev':'10-72cd2edbcc0d197ce96188a229a7af01'},
+ ], promise);
+
+ assert.ok(spy.calledWith(ids));
+ });
- it('triggers reject for failed delete', function () {
- var spy = sinon.spy();
- promise.fail(spy);
+ it('triggers reject for failed delete', function () {
+ var spy = sinon.spy();
+ promise.fail(spy);
- collection.handleResponse([
- {'error':'conflict', 'id':'1', 'rev':'10-72cd2edbcc0d197ce96188a229a7af01'}
- ], promise);
+ collection.handleResponse([
+ {'error':'conflict', 'id':'1', 'rev':'10-72cd2edbcc0d197ce96188a229a7af01'}
+ ], promise);
- assert.ok(spy.calledWith(['1']));
+ assert.ok(spy.calledWith(['1']));
- });
+ });
- });
});
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/0ca35da7/app/addons/documents/tests/routeSpec.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/tests/routeSpec.js b/app/addons/documents/tests/routeSpec.js
index 5807b02..57bf9aa 100644
--- a/app/addons/documents/tests/routeSpec.js
+++ b/app/addons/documents/tests/routeSpec.js
@@ -10,39 +10,36 @@
// License for the specific language governing permissions and limitations under
// the License.
-define([
- '../../../core/api',
- '../base',
- '../routes',
- '../header/header.actions',
- '../index-results/actions',
- '../../../../test/mocha/testUtils',
-], function (FauxtonAPI, Base, Documents, HeaderActions, IndexResultsActions, testUtils) {
- var assert = testUtils.assert;
- var DocumentRoute = Documents.RouteObjects[2];
-
- //commenting out for now. This test adds little value and is breaking the routeObjectSpecs
- describe('Documents Route', function () {
-
- /*it('the all-documents-list has a right header', function () {
- var routeObj = new DocumentRoute(null, null, ['test']);
-
- routeObj.allDocs('newdatabase', null);
- assert.equal(typeof routeObj.rightHeader, 'object');
-
- });*/
-
- });
-
- // until there is consensus on how to encode json responses
- // https://issues.apache.org/jira/browse/COUCHDB-2748
- // taking out this test for https://github.com/apache/couchdb-fauxton/pull/489
-
- //describe('Fauxton Urls', function () {
- // it('document app encodes document id', function () {
- // var id = "\foo";
- // var url = FauxtonAPI.urls('document', 'app', 'fake-db', id);
- // assert.deepEqual("/database/fake-db/%0Coo", url);
- // });
- //});
+import FauxtonAPI from "../../../core/api";
+import Base from "../base";
+import Documents from "../routes";
+import HeaderActions from "../header/header.actions";
+import IndexResultsActions from "../index-results/actions";
+import testUtils from "../../../../test/mocha/testUtils";
+var assert = testUtils.assert;
+var DocumentRoute = Documents.RouteObjects[2];
+
+//commenting out for now. This test adds little value and is breaking the routeObjectSpecs
+describe('Documents Route', function () {
+
+ /*it('the all-documents-list has a right header', function () {
+ var routeObj = new DocumentRoute(null, null, ['test']);
+
+ routeObj.allDocs('newdatabase', null);
+ assert.equal(typeof routeObj.rightHeader, 'object');
+
+ });*/
+
});
+
+// until there is consensus on how to encode json responses
+// https://issues.apache.org/jira/browse/COUCHDB-2748
+// taking out this test for https://github.com/apache/couchdb-fauxton/pull/489
+
+//describe('Fauxton Urls', function () {
+// it('document app encodes document id', function () {
+// var id = "\foo";
+// var url = FauxtonAPI.urls('document', 'app', 'fake-db', id);
+// assert.deepEqual("/database/fake-db/%0Coo", url);
+// });
+//});
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/0ca35da7/app/addons/documents/views.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/views.js b/app/addons/documents/views.js
index 6c46076..3b1ff67 100644
--- a/app/addons/documents/views.js
+++ b/app/addons/documents/views.js
@@ -10,95 +10,86 @@
// License for the specific language governing permissions and limitations under
// the License.
-define([
- "../../app",
- "../../core/api",
- "../fauxton/components",
- "./resources",
- "../databases/resources",
-
- // Views
- "./queryoptions/queryoptions.react",
- "./queryoptions/actions",
- './jumptodoc.react',
-
- //plugins
- "../../../assets/js/plugins/prettify"
-],
-
-function (app, FauxtonAPI, Components, Documents, Databases, QueryOptions, QueryActions, JumpToDoc) {
-
- var Views = {};
-
- function showError (msg) {
- FauxtonAPI.addNotification({
- msg: msg,
- type: 'error',
- clear: true
- });
- }
+import app from "../../app";
+import FauxtonAPI from "../../core/api";
+import Components from "../fauxton/components";
+import Documents from "./resources";
+import Databases from "../databases/resources";
+import QueryOptions from "./queryoptions/queryoptions.react";
+import QueryActions from "./queryoptions/actions";
+import JumpToDoc from "./jumptodoc.react";
+import "../../../assets/js/plugins/prettify";
+
+var Views = {};
+
+function showError (msg) {
+ FauxtonAPI.addNotification({
+ msg: msg,
+ type: 'error',
+ clear: true
+ });
+}
+
+Views.RightAllDocsHeader = FauxtonAPI.View.extend({
+ className: "header-right right-db-header flex-layout flex-row",
+ template: "addons/documents/templates/all_docs_header",
+ events: {
+ 'click .toggle-select-menu': 'selectAllMenu'
+ },
+
+ initialize: function (options) {
+ this.database = options.database;
+ this.params = options.params;
+
+ _.bindAll(this);
+ this.selectVisible = false;
+ FauxtonAPI.Events.on('success:bulkDelete', this.selectAllMenu);
+ },
+
+ afterRender: function () {
+ QueryOptions.render('#query-options');
+ JumpToDoc.render('#header-search', this.database, this.database.allDocs);
+ this.toggleQueryOptionsHeader(this.isHidden);
+ },
+
+ cleanup: function () {
+ FauxtonAPI.Events.unbind('success:bulkDelete');
+ },
+
+ selectAllMenu: function (e) {
+ FauxtonAPI.triggerRouteEvent("toggleSelectHeader");
+ FauxtonAPI.Events.trigger("documents:showSelectAll", this.selectVisible);
+ },
+
+ resetQueryOptions: function (options) {
+ QueryActions.reset(options);
+ },
+
+ hideQueryOptions: function () {
+ this.isHidden = true;
+ if (this.hasRendered) {
+ this.toggleQueryOptionsHeader(this.isHidden);
+ }
+ },
- Views.RightAllDocsHeader = FauxtonAPI.View.extend({
- className: "header-right right-db-header flex-layout flex-row",
- template: "addons/documents/templates/all_docs_header",
- events: {
- 'click .toggle-select-menu': 'selectAllMenu'
- },
-
- initialize: function (options) {
- this.database = options.database;
- this.params = options.params;
-
- _.bindAll(this);
- this.selectVisible = false;
- FauxtonAPI.Events.on('success:bulkDelete', this.selectAllMenu);
- },
-
- afterRender: function () {
- QueryOptions.render('#query-options');
- JumpToDoc.render('#header-search', this.database, this.database.allDocs);
+ showQueryOptions: function () {
+ this.isHidden = false;
+ if (this.hasRendered) {
this.toggleQueryOptionsHeader(this.isHidden);
- },
-
- cleanup: function () {
- FauxtonAPI.Events.unbind('success:bulkDelete');
- },
-
- selectAllMenu: function (e) {
- FauxtonAPI.triggerRouteEvent("toggleSelectHeader");
- FauxtonAPI.Events.trigger("documents:showSelectAll", this.selectVisible);
- },
-
- resetQueryOptions: function (options) {
- QueryActions.reset(options);
- },
-
- hideQueryOptions: function () {
- this.isHidden = true;
- if (this.hasRendered) {
- this.toggleQueryOptionsHeader(this.isHidden);
- }
- },
-
- showQueryOptions: function () {
- this.isHidden = false;
- if (this.hasRendered) {
- this.toggleQueryOptionsHeader(this.isHidden);
- }
- },
-
- toggleQueryOptionsHeader: function (hide) {
- $("#header-query-options").toggleClass("hide", hide);
- },
-
- serialize: function () {
- return {
- database: this.database.get('id')
- };
}
- });
+ },
- Documents.Views = Views;
+ toggleQueryOptionsHeader: function (hide) {
+ $("#header-query-options").toggleClass("hide", hide);
+ },
- return Documents;
+ serialize: function () {
+ return {
+ database: this.database.get('id')
+ };
+ }
});
+
+Documents.Views = Views;
+
+export default Documents;
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/0ca35da7/app/addons/fauxton/base.js
----------------------------------------------------------------------
diff --git a/app/addons/fauxton/base.js b/app/addons/fauxton/base.js
index 7d22bb1..a907c03 100644
--- a/app/addons/fauxton/base.js
+++ b/app/addons/fauxton/base.js
@@ -10,112 +10,106 @@
// License for the specific language governing permissions and limitations under
// the License.
-define([
- "../../app",
- "../../core/api",
- "./components",
- './notifications/notifications.react',
- './notifications/actions',
- "./navigation/components.react",
- "./navigation/actions",
- '../components/react-components.react',
- '../components/actions',
- './assets/less/fauxton.less'
-],
-
-function (app, FauxtonAPI, Components, NotificationComponents, Actions, NavbarReactComponents, NavigationActions,
- ReactComponents, ComponentActions) {
-
- var Fauxton = FauxtonAPI.addon();
- FauxtonAPI.addNotification = function (options) {
- options = _.extend({
- msg: 'Notification Event Triggered!',
- type: 'info',
- escape: true,
- clear: false
- }, options);
-
- // log all notifications in a store
- Actions.addNotification(options);
- };
-
- FauxtonAPI.UUID = FauxtonAPI.Model.extend({
- initialize: function (options) {
- options = _.extend({count: 1}, options);
- this.count = options.count;
- },
-
- url: function () {
- return app.host + "/_uuids?count=" + this.count;
- },
-
- next: function () {
- return this.get("uuids").pop();
- }
- });
-
+import app from "../../app";
+import FauxtonAPI from "../../core/api";
+import Components from "./components";
+import NotificationComponents from "./notifications/notifications.react";
+import Actions from "./notifications/actions";
+import NavbarReactComponents from "./navigation/components.react";
+import NavigationActions from "./navigation/actions";
+import ReactComponents from "../components/react-components.react";
+import ComponentActions from "../components/actions";
+import "./assets/less/fauxton.less";
+
+var Fauxton = FauxtonAPI.addon();
+FauxtonAPI.addNotification = function (options) {
+ options = _.extend({
+ msg: 'Notification Event Triggered!',
+ type: 'info',
+ escape: true,
+ clear: false
+ }, options);
+
+ // log all notifications in a store
+ Actions.addNotification(options);
+};
+
+FauxtonAPI.UUID = FauxtonAPI.Model.extend({
+ initialize: function (options) {
+ options = _.extend({count: 1}, options);
+ this.count = options.count;
+ },
+
+ url: function () {
+ return app.host + "/_uuids?count=" + this.count;
+ },
+
+ next: function () {
+ return this.get("uuids").pop();
+ }
+});
- Fauxton.initialize = function () {
- FauxtonAPI.RouteObject.on('beforeEstablish', function (routeObject) {
- NavigationActions.setNavbarActiveLink(_.result(routeObject, 'selectedHeader'));
+Fauxton.initialize = function () {
- // always attempt to render the API Bar. Even if it's hidden on initial load, it may be enabled later
- routeObject.setComponent('#api-navbar', ReactComponents.ApiBarController, {
- buttonVisible: true,
- contentVisible: false
- });
+ FauxtonAPI.RouteObject.on('beforeEstablish', function (routeObject) {
+ NavigationActions.setNavbarActiveLink(_.result(routeObject, 'selectedHeader'));
- if (routeObject.get('apiUrl')) {
- var apiAndDocs = routeObject.get('apiUrl');
-
- ComponentActions.updateAPIBar({
- buttonVisible: true,
- contentVisible: false,
- endpoint: apiAndDocs[0],
- docURL: apiAndDocs[1]
- });
- } else {
- ComponentActions.hideAPIBarButton();
- }
-
- if (!routeObject.get('hideNotificationCenter')) {
- routeObject.setComponent('#notification-center-btn', NotificationComponents.NotificationCenterButton);
- }
-
- if (routeObject.overrideBreadcrumbs) { return; }
-
- FauxtonAPI.masterLayout.removeView('#breadcrumbs');
- var crumbs = routeObject.get('crumbs');
-
- if (crumbs.length) {
- FauxtonAPI.masterLayout.setView('#breadcrumbs', new Components.Breadcrumbs({
- crumbs: crumbs
- }), true).render();
- }
+ // always attempt to render the API Bar. Even if it's hidden on initial load, it may be enabled later
+ routeObject.setComponent('#api-navbar', ReactComponents.ApiBarController, {
+ buttonVisible: true,
+ contentVisible: false
});
- var primaryNavBarEl = $('#primary-navbar')[0];
- if (primaryNavBarEl) {
- NavbarReactComponents.renderNavBar(primaryNavBarEl);
+ if (routeObject.get('apiUrl')) {
+ var apiAndDocs = routeObject.get('apiUrl');
+
+ ComponentActions.updateAPIBar({
+ buttonVisible: true,
+ contentVisible: false,
+ endpoint: apiAndDocs[0],
+ docURL: apiAndDocs[1]
+ });
+ } else {
+ ComponentActions.hideAPIBarButton();
}
- var notificationEl = $('#notifications')[0];
- if (notificationEl) {
- NotificationComponents.renderNotificationController(notificationEl);
+ if (!routeObject.get('hideNotificationCenter')) {
+ routeObject.setComponent('#notification-center-btn', NotificationComponents.NotificationCenterButton);
}
- var versionInfo = new Fauxton.VersionInfo();
- versionInfo.fetch().then(function () {
- NavigationActions.setNavbarVersionInfo(versionInfo.get("version"));
- });
- };
+ if (routeObject.overrideBreadcrumbs) { return; }
- Fauxton.VersionInfo = Backbone.Model.extend({
- url: function () {
- return app.host;
+ FauxtonAPI.masterLayout.removeView('#breadcrumbs');
+ var crumbs = routeObject.get('crumbs');
+
+ if (crumbs.length) {
+ FauxtonAPI.masterLayout.setView('#breadcrumbs', new Components.Breadcrumbs({
+ crumbs: crumbs
+ }), true).render();
}
});
- return Fauxton;
+ var primaryNavBarEl = $('#primary-navbar')[0];
+ if (primaryNavBarEl) {
+ NavbarReactComponents.renderNavBar(primaryNavBarEl);
+ }
+
+ var notificationEl = $('#notifications')[0];
+ if (notificationEl) {
+ NotificationComponents.renderNotificationController(notificationEl);
+ }
+ var versionInfo = new Fauxton.VersionInfo();
+
+ versionInfo.fetch().then(function () {
+ NavigationActions.setNavbarVersionInfo(versionInfo.get("version"));
+ });
+};
+
+Fauxton.VersionInfo = Backbone.Model.extend({
+ url: function () {
+ return app.host;
+ }
});
+
+export default Fauxton;
http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/0ca35da7/app/addons/fauxton/components.js
----------------------------------------------------------------------
diff --git a/app/addons/fauxton/components.js b/app/addons/fauxton/components.js
index 73402be..97db63a 100644
--- a/app/addons/fauxton/components.js
+++ b/app/addons/fauxton/components.js
@@ -10,580 +10,573 @@
// License for the specific language governing permissions and limitations under
// the License.
-define([
- "../../app",
- // Libs
- "../../core/api",
- "../../../assets/js/libs/spin.min",
- '../components/react-components.react',
- '../components/actions',
- '../documents/helpers',
-
- "velocity-animate/velocity.ui"
-],
-
-function (app, FauxtonAPI, spin, ReactComponents, ComponentsActions, Helpers) {
- var Components = FauxtonAPI.addon();
-
- // XXX: move to /addons/documents - component is tightly coupled to documents/alldocs
- Components.LeftHeader = FauxtonAPI.View.extend({
- className: "header-left",
- template: "addons/fauxton/templates/header_left",
+import app from "../../app";
+import FauxtonAPI from "../../core/api";
+import spin from "../../../assets/js/libs/spin.min";
+import ReactComponents from "../components/react-components.react";
+import ComponentsActions from "../components/actions";
+import Helpers from "../documents/helpers";
+import "velocity-animate/velocity.ui";
+var Components = FauxtonAPI.addon();
+
+// XXX: move to /addons/documents - component is tightly coupled to documents/alldocs
+Components.LeftHeader = FauxtonAPI.View.extend({
+ className: "header-left",
+ template: "addons/fauxton/templates/header_left",
+
+ initialize: function (options) {
+ this.lookaheadTrayOptions = options.lookaheadTrayOptions || null;
+ this.crumbs = options.crumbs || [];
+
+ this.dbName = options.databaseName;
+
+ // listen for breadcrumb clicks
+ this.listenTo(FauxtonAPI.Events, 'breadcrumb:click', this.toggleTray);
+ this.listenTo(FauxtonAPI.Events, 'lookaheadTray:close', this.unselectLastBreadcrumb);
+ },
+
+ updateCrumbs: function (crumbs) {
+
+ // if the breadcrumbs haven't changed, don't bother re-rendering the component
+ if (_.isEqual(this.crumbs, crumbs)) {
+ return;
+ }
- initialize: function (options) {
- this.lookaheadTrayOptions = options.lookaheadTrayOptions || null;
- this.crumbs = options.crumbs || [];
+ this.crumbs = crumbs;
+ this.breadcrumbs && this.breadcrumbs.update(crumbs);
+ },
- this.dbName = options.databaseName;
+ unselectLastBreadcrumb: function () {
+ this.breadcrumbs.unselectLastBreadcrumb();
+ },
- // listen for breadcrumb clicks
- this.listenTo(FauxtonAPI.Events, 'breadcrumb:click', this.toggleTray);
- this.listenTo(FauxtonAPI.Events, 'lookaheadTray:close', this.unselectLastBreadcrumb);
- },
+ toggleTray: function () {
+ if (this.lookaheadTray !== null) {
+ this.lookaheadTray.toggleTray();
+ }
+ },
- updateCrumbs: function (crumbs) {
+ beforeRender: function () {
+ this.setUpCrumbs();
+ this.setUpDropDownMenu();
- // if the breadcrumbs haven't changed, don't bother re-rendering the component
- if (_.isEqual(this.crumbs, crumbs)) {
- return;
- }
+ if (this.lookaheadTray !== null) {
+ this.setUpLookaheadTray();
+ }
+ },
+
+ setUpCrumbs: function () {
+ this.breadcrumbs = this.insertView("#header-breadcrumbs", new Components.Breadcrumbs({
+ crumbs: this.crumbs
+ }));
+ },
+
+ getModififyDbLinks: function () {
+ var onClickDelete = ComponentsActions.showDeleteDatabaseModal;
+ return Helpers.getModifyDatabaseLinks(this.dbName, onClickDelete);
+ },
+
+ setUpDropDownMenu: function () {
+ var dropdownMenuLinks = Helpers.getNewButtonLinks(this.dbName);
+
+ dropdownMenuLinks = this.getModififyDbLinks().concat(dropdownMenuLinks);
+
+ this.dropdown = this.insertView("#header-dropdown-menu", new Components.MenuDropDownReact({
+ links: dropdownMenuLinks,
+ }));
+ },
+
+ setUpLookaheadTray: function () {
+ var options = this.lookaheadTrayOptions,
+ dbNames = options.databaseCollection.getDatabaseNames(),
+ currentDBName = this.crumbs[1].name;
+
+ // remove the current database name from the list
+ dbNames = _.without(dbNames, currentDBName);
+
+ this.lookaheadTray = this.insertView("#header-lookahead", new Components.LookaheadTray({
+ data: dbNames,
+ toggleEventName: options.toggleEventName,
+ onUpdateEventName: options.onUpdateEventName,
+ placeholder: options.placeholder
+ }));
+ }
+});
- this.crumbs = crumbs;
- this.breadcrumbs && this.breadcrumbs.update(crumbs);
- },
+Components.MenuDropDownReact = FauxtonAPI.View.extend({
+ initialize: function (options) {
+ this.options = options;
+ },
- unselectLastBreadcrumb: function () {
- this.breadcrumbs.unselectLastBreadcrumb();
- },
+ afterRender: function () {
+ ReactComponents.renderMenuDropDown(this.el, this.options);
+ },
- toggleTray: function () {
- if (this.lookaheadTray !== null) {
- this.lookaheadTray.toggleTray();
- }
- },
+ cleanup: function () {
+ ReactComponents.removeMenuDropDown(this.el);
+ }
+});
+Components.Breadcrumbs = FauxtonAPI.View.extend({
+ className: "breadcrumb pull-left",
+ tagName: "ul",
+ template: "addons/fauxton/templates/breadcrumbs",
+
+ events: {
+ "click .js-lastelement": "toggleLastElement"
+ },
+
+ serialize: function () {
+ var crumbs = _.clone(this.crumbs);
+
+ // helper template function to determine when to insert a delimiter char
+ var nextCrumbHasLabel = function (crumb, index) {
+ var nextHasLabel = crumbs[index + 1].name !== "";
+ return index < crumbs.length && crumb.name && nextHasLabel;
+ };
+
+ return {
+ toggleDisabled: this.toggleDisabled,
+ crumbs: crumbs,
+ nextCrumbHasLabel: nextCrumbHasLabel
+ };
+ },
+
+ toggleLastElement: function (event) {
+ if (this.toggleDisabled) {
+ return;
+ }
+ this.$(event.currentTarget).toggleClass('js-enabled');
+ FauxtonAPI.Events.trigger('breadcrumb:click');
+ },
- beforeRender: function () {
- this.setUpCrumbs();
- this.setUpDropDownMenu();
+ unselectLastBreadcrumb: function () {
+ if (this.toggleDisabled) {
+ return;
+ }
+ this.$('.js-enabled').removeClass('js-enabled');
+ },
+
+ update: function (crumbs) {
+ this.crumbs = crumbs;
+ this.render();
+ },
+
+ initialize: function (options) {
+ this.crumbs = options.crumbs;
+ this.toggleDisabled = options.toggleDisabled || false;
+ }
+});
- if (this.lookaheadTray !== null) {
- this.setUpLookaheadTray();
- }
- },
-
- setUpCrumbs: function () {
- this.breadcrumbs = this.insertView("#header-breadcrumbs", new Components.Breadcrumbs({
- crumbs: this.crumbs
- }));
- },
-
- getModififyDbLinks: function () {
- var onClickDelete = ComponentsActions.showDeleteDatabaseModal;
- return Helpers.getModifyDatabaseLinks(this.dbName, onClickDelete);
- },
-
- setUpDropDownMenu: function () {
- var dropdownMenuLinks = Helpers.getNewButtonLinks(this.dbName);
-
- dropdownMenuLinks = this.getModififyDbLinks().concat(dropdownMenuLinks);
-
- this.dropdown = this.insertView("#header-dropdown-menu", new Components.MenuDropDownReact({
- links: dropdownMenuLinks,
- }));
- },
-
- setUpLookaheadTray: function () {
- var options = this.lookaheadTrayOptions,
- dbNames = options.databaseCollection.getDatabaseNames(),
- currentDBName = this.crumbs[1].name;
-
- // remove the current database name from the list
- dbNames = _.without(dbNames, currentDBName);
-
- this.lookaheadTray = this.insertView("#header-lookahead", new Components.LookaheadTray({
- data: dbNames,
- toggleEventName: options.toggleEventName,
- onUpdateEventName: options.onUpdateEventName,
- placeholder: options.placeholder
- }));
+/**
+ * Our generic Tray component. All trays should extend this guy - it offers some convenient boilerplate code for
+ * hiding/showing, event publishing and so on. The important functions that can be called on the child Views are:
+ * - hideTray
+ * - showTray
+ * - toggleTray
+ */
+Components.Tray = FauxtonAPI.View.extend({
+
+ // populated dynamically
+ events: {},
+
+ initTray: function (opts) {
+ this.toggleTrayBtnSelector = (_.has(opts, 'toggleTrayBtnSelector')) ? opts.toggleTrayBtnSelector : null;
+ this.onShowTray = (_.has(opts, 'onShowTray')) ? opts.onShowTray : null;
+
+ // if the component extending this one passed along the selector of the element that toggles the tray,
+ // add the appropriate events
+ if (!_.isNull(this.toggleTrayBtnSelector)) {
+ this.events['click ' + this.toggleTrayBtnSelector] = 'toggleTray';
}
- });
- Components.MenuDropDownReact = FauxtonAPI.View.extend({
- initialize: function (options) {
- this.options = options;
- },
+ _.bind(this.toggleTray, this);
+ _.bind(this.trayVisible, this);
+ _.bind(this.hideTray, this);
+ _.bind(this.showTray, this);
- afterRender: function () {
- ReactComponents.renderMenuDropDown(this.el, this.options);
- },
+ // a unique identifier for this tray
+ this.trayId = 'tray-' + this.cid;
- cleanup: function () {
- ReactComponents.removeMenuDropDown(this.el);
- }
- });
- Components.Breadcrumbs = FauxtonAPI.View.extend({
- className: "breadcrumb pull-left",
- tagName: "ul",
- template: "addons/fauxton/templates/breadcrumbs",
-
- events: {
- "click .js-lastelement": "toggleLastElement"
- },
-
- serialize: function () {
- var crumbs = _.clone(this.crumbs);
-
- // helper template function to determine when to insert a delimiter char
- var nextCrumbHasLabel = function (crumb, index) {
- var nextHasLabel = crumbs[index + 1].name !== "";
- return index < crumbs.length && crumb.name && nextHasLabel;
- };
-
- return {
- toggleDisabled: this.toggleDisabled,
- crumbs: crumbs,
- nextCrumbHasLabel: nextCrumbHasLabel
- };
- },
-
- toggleLastElement: function (event) {
- if (this.toggleDisabled) {
+ var that = this;
+ $('body').on('click.' + this.trayId, function (e) {
+ var $clickEl = $(e.target);
+
+ if (!that.trayVisible()) {
return;
}
- this.$(event.currentTarget).toggleClass('js-enabled');
- FauxtonAPI.Events.trigger('breadcrumb:click');
- },
-
- unselectLastBreadcrumb: function () {
- if (this.toggleDisabled) {
+ if (!_.isNull(that.toggleTrayBtnSelector) && $clickEl.closest(that.toggleTrayBtnSelector).length) {
return;
}
- this.$('.js-enabled').removeClass('js-enabled');
- },
+ if (!$clickEl.closest('.tray').length) {
+ that.hideTray();
+ }
+ });
+
+ FauxtonAPI.Events.on(FauxtonAPI.constants.EVENTS.TRAY_OPENED, this.onTrayOpenEvent, this);
+ },
- update: function (crumbs) {
- this.crumbs = crumbs;
- this.render();
- },
+ cleanup: function () {
+ $('body').off('click.' + this.trayId);
+ },
- initialize: function (options) {
- this.crumbs = options.crumbs;
- this.toggleDisabled = options.toggleDisabled || false;
+ // all trays publish a EVENTS.TRAY_OPENED event containing their unique ID. This listens for those events and
+ // closes the current tray if it's already open
+ onTrayOpenEvent: function (msg) {
+ if (!_.has(msg, 'trayId')) {
+ return;
}
- });
-
- /**
- * Our generic Tray component. All trays should extend this guy - it offers some convenient boilerplate code for
- * hiding/showing, event publishing and so on. The important functions that can be called on the child Views are:
- * - hideTray
- * - showTray
- * - toggleTray
- */
- Components.Tray = FauxtonAPI.View.extend({
-
- // populated dynamically
- events: {},
-
- initTray: function (opts) {
- this.toggleTrayBtnSelector = (_.has(opts, 'toggleTrayBtnSelector')) ? opts.toggleTrayBtnSelector : null;
- this.onShowTray = (_.has(opts, 'onShowTray')) ? opts.onShowTray : null;
-
- // if the component extending this one passed along the selector of the element that toggles the tray,
- // add the appropriate events
- if (!_.isNull(this.toggleTrayBtnSelector)) {
- this.events['click ' + this.toggleTrayBtnSelector] = 'toggleTray';
- }
+ if (msg.trayId !== this.trayId && this.trayVisible()) {
+ this.hideTray();
+ }
+ },
- _.bind(this.toggleTray, this);
- _.bind(this.trayVisible, this);
- _.bind(this.hideTray, this);
- _.bind(this.showTray, this);
+ toggleTray: function (e) {
+ e.preventDefault();
- // a unique identifier for this tray
- this.trayId = 'tray-' + this.cid;
+ if (this.trayVisible()) {
+ this.hideTray();
+ } else {
+ this.showTray();
+ }
+ },
- var that = this;
- $('body').on('click.' + this.trayId, function (e) {
- var $clickEl = $(e.target);
+ hideTray: function () {
+ var $tray = this.$('.tray');
+ $tray.velocity('reverse', FauxtonAPI.constants.MISC.TRAY_TOGGLE_SPEED, function () {
+ $tray.hide();
+ });
- if (!that.trayVisible()) {
- return;
- }
- if (!_.isNull(that.toggleTrayBtnSelector) && $clickEl.closest(that.toggleTrayBtnSelector).length) {
- return;
- }
- if (!$clickEl.closest('.tray').length) {
- that.hideTray();
- }
- });
+ if (!_.isNull(this.toggleTrayBtnSelector)) {
+ this.$(this.toggleTrayBtnSelector).removeClass('enabled');
+ }
+ },
- FauxtonAPI.Events.on(FauxtonAPI.constants.EVENTS.TRAY_OPENED, this.onTrayOpenEvent, this);
- },
+ showTray: function () {
+ this.$('.tray').velocity('transition.slideDownIn', FauxtonAPI.constants.MISC.TRAY_TOGGLE_SPEED);
+ if (!_.isNull(this.toggleTrayBtnSelector)) {
+ this.$(this.toggleTrayBtnSelector).addClass('enabled');
+ }
- cleanup: function () {
- $('body').off('click.' + this.trayId);
- },
+ if (!_.isNull(this.onShowTray)) {
+ this.onShowTray();
+ }
- // all trays publish a EVENTS.TRAY_OPENED event containing their unique ID. This listens for those events and
- // closes the current tray if it's already open
- onTrayOpenEvent: function (msg) {
- if (!_.has(msg, 'trayId')) {
- return;
- }
- if (msg.trayId !== this.trayId && this.trayVisible()) {
- this.hideTray();
- }
- },
+ FauxtonAPI.Events.trigger(FauxtonAPI.constants.EVENTS.TRAY_OPENED, { trayId: this.trayId });
+ },
- toggleTray: function (e) {
- e.preventDefault();
+ trayVisible: function () {
+ return this.$('.tray').is(':visible');
+ }
+});
- if (this.trayVisible()) {
- this.hideTray();
- } else {
- this.showTray();
- }
- },
- hideTray: function () {
- var $tray = this.$('.tray');
- $tray.velocity('reverse', FauxtonAPI.constants.MISC.TRAY_TOGGLE_SPEED, function () {
- $tray.hide();
- });
+Components.ModalView = FauxtonAPI.View.extend({
+ disableLoader: true,
- if (!_.isNull(this.toggleTrayBtnSelector)) {
- this.$(this.toggleTrayBtnSelector).removeClass('enabled');
- }
- },
+ initialize: function (options) {
+ _.bindAll(this);
+ },
- showTray: function () {
- this.$('.tray').velocity('transition.slideDownIn', FauxtonAPI.constants.MISC.TRAY_TOGGLE_SPEED);
- if (!_.isNull(this.toggleTrayBtnSelector)) {
- this.$(this.toggleTrayBtnSelector).addClass('enabled');
- }
+ afterRender: function () {
+ var that = this;
+ this.$('.modal').on('shown', function () {
+ that.$('input:text:visible:first').focus();
+ });
+ },
- if (!_.isNull(this.onShowTray)) {
- this.onShowTray();
- }
+ showModal: function () {
+ if (this._showModal) { this._showModal();}
+ this.clear_error_msg();
+ this.$('.modal').modal();
- FauxtonAPI.Events.trigger(FauxtonAPI.constants.EVENTS.TRAY_OPENED, { trayId: this.trayId });
- },
+ // hack to get modal visible
+ $('.modal-backdrop').css('z-index', FauxtonAPI.constants.MISC.MODAL_BACKDROP_Z_INDEX);
+ },
- trayVisible: function () {
- return this.$('.tray').is(':visible');
+ hideModal: function () {
+ this.$('.modal').modal('hide');
+ },
+
+ set_error_msg: function (msg) {
+ var text;
+ if (typeof(msg) == 'string') {
+ text = msg;
+ } else {
+ text = JSON.parse(msg.responseText).reason;
}
- });
-
-
- Components.ModalView = FauxtonAPI.View.extend({
- disableLoader: true,
-
- initialize: function (options) {
- _.bindAll(this);
- },
-
- afterRender: function () {
- var that = this;
- this.$('.modal').on('shown', function () {
- that.$('input:text:visible:first').focus();
- });
- },
-
- showModal: function () {
- if (this._showModal) { this._showModal();}
- this.clear_error_msg();
- this.$('.modal').modal();
-
- // hack to get modal visible
- $('.modal-backdrop').css('z-index', FauxtonAPI.constants.MISC.MODAL_BACKDROP_Z_INDEX);
- },
-
- hideModal: function () {
- this.$('.modal').modal('hide');
- },
-
- set_error_msg: function (msg) {
- var text;
- if (typeof(msg) == 'string') {
- text = msg;
- } else {
- text = JSON.parse(msg.responseText).reason;
- }
- this.$('#modal-error').text(text).removeClass('hide');
- },
+ this.$('#modal-error').text(text).removeClass('hide');
+ },
- clear_error_msg: function () {
- this.$('#modal-error').text(' ').addClass('hide');
- },
+ clear_error_msg: function () {
+ this.$('#modal-error').text(' ').addClass('hide');
+ },
- serialize: function () {
- if (this.model) {
- return this.model.toJSON();
- }
- return {};
+ serialize: function () {
+ if (this.model) {
+ return this.model.toJSON();
}
- });
+ return {};
+ }
+});
- Components.Typeahead = FauxtonAPI.View.extend({
+Components.Typeahead = FauxtonAPI.View.extend({
- initialize: function (options) {
- this.source = options.source;
- this.onUpdateEventName = options.onUpdateEventName;
- },
+ initialize: function (options) {
+ this.source = options.source;
+ this.onUpdateEventName = options.onUpdateEventName;
+ },
- afterRender: function () {
- var onUpdateEventName = this.onUpdateEventName;
+ afterRender: function () {
+ var onUpdateEventName = this.onUpdateEventName;
- this.$el.typeahead({
- source: this.source,
- updater: function (item) {
- FauxtonAPI.Events.trigger(onUpdateEventName, item);
- return item;
- }
- });
- }
- });
-
- Components.DbSearchTypeahead = Components.Typeahead.extend({
- initialize: function (options) {
- this.dbLimit = options.dbLimit || 30;
- if (options.filter) {
- this.resultFilter = options.resultFilter;
+ this.$el.typeahead({
+ source: this.source,
+ updater: function (item) {
+ FauxtonAPI.Events.trigger(onUpdateEventName, item);
+ return item;
}
- _.bindAll(this);
- },
-
- getURL: function (query, dbLimit) {
- query = encodeURIComponent(query);
- return [
- app.host,
- "/_all_dbs?startkey=%22",
- query,
- "%22&endkey=%22",
- query,
- encodeURIComponent("\u9999"),
- "%22&limit=",
- dbLimit
- ].join('');
- },
-
- source: function (query, process) {
- var url = this.getURL(query, this.dbLimit);
- var resultFilter = this.resultFilter;
-
- if (this.ajaxReq) { this.ajaxReq.abort(); }
-
- this.ajaxReq = $.ajax({
- cache: false,
- url: url,
- dataType: 'json',
- success: function (data) {
- if (resultFilter) {
- data = resultFilter(data);
- }
- process(data);
- }
- });
- }
- });
-
- Components.DocSearchTypeahead = Components.Typeahead.extend({
- initialize: function (options) {
- this.docLimit = options.docLimit || 30;
- this.database = options.database;
- _.bindAll(this);
- },
- source: function (id, process) {
- var query = '?' + $.param({
- startkey: JSON.stringify(id),
- endkey: JSON.stringify(id + "\u9999"),
- limit: this.docLimit
- });
-
- var url = FauxtonAPI.urls('allDocs', 'server', this.database.safeID(), query);
-
- if (this.ajaxReq) { this.ajaxReq.abort(); }
-
- this.ajaxReq = $.ajax({
- cache: false,
- url: url,
- dataType: 'json',
- success: function (data) {
- var ids = _.map(data.rows, function (row) {
- return row.id;
- });
- process(ids);
- }
- });
+ });
+ }
+});
+
+Components.DbSearchTypeahead = Components.Typeahead.extend({
+ initialize: function (options) {
+ this.dbLimit = options.dbLimit || 30;
+ if (options.filter) {
+ this.resultFilter = options.resultFilter;
}
- });
-
- Components.LookaheadTray = FauxtonAPI.View.extend({
- className: "lookahead-tray tray",
- template: "addons/fauxton/templates/lookahead_tray",
- placeholder: "Enter to search",
-
- events: {
- 'click #js-close-tray': 'closeTray',
- 'keyup': 'onKeyup'
- },
-
- serialize: function () {
- return {
- placeholder: this.placeholder
- };
- },
-
- initialize: function (opts) {
- this.data = opts.data;
- this.toggleEventName = opts.toggleEventName;
- this.onUpdateEventName = opts.onUpdateEventName;
-
- var trayIsVisible = _.bind(this.trayIsVisible, this);
- var closeTray = _.bind(this.closeTray, this);
- $("body").on("click.lookaheadTray", function (e) {
- if (!trayIsVisible()) { return; }
- if ($(e.target).closest(".lookahead-tray").length === 0 &&
- $(e.target).closest('.lookahead-tray-link').length === 0) {
- closeTray();
+ _.bindAll(this);
+ },
+
+ getURL: function (query, dbLimit) {
+ query = encodeURIComponent(query);
+ return [
+ app.host,
+ "/_all_dbs?startkey=%22",
+ query,
+ "%22&endkey=%22",
+ query,
+ encodeURIComponent("\u9999"),
+ "%22&limit=",
+ dbLimit
+ ].join('');
+ },
+
+ source: function (query, process) {
+ var url = this.getURL(query, this.dbLimit);
+ var resultFilter = this.resultFilter;
+
+ if (this.ajaxReq) { this.ajaxReq.abort(); }
+
+ this.ajaxReq = $.ajax({
+ cache: false,
+ url: url,
+ dataType: 'json',
+ success: function (data) {
+ if (resultFilter) {
+ data = resultFilter(data);
}
- });
- },
-
- afterRender: function () {
- var that = this;
- this.dbSearchTypeahead = new Components.Typeahead({
- el: 'input.search-autocomplete',
- source: that.data,
- onUpdateEventName: that.onUpdateEventName
- });
- this.dbSearchTypeahead.render();
- },
-
- clearValue: function () {
- this.$('.search-autocomplete').val('');
- },
-
- cleanup: function () {
- $("body").off("click.lookaheadTray");
- },
-
- trayIsVisible: function () {
- return this.$el.is(":visible");
- },
-
- toggleTray: function () {
- if (this.trayIsVisible()) {
- this.closeTray();
- } else {
- this.openTray();
+ process(data);
}
- },
-
- openTray: function () {
- var speed = FauxtonAPI.constants.MISC.TRAY_TOGGLE_SPEED;
- this.$el.velocity('transition.slideDownIn', speed, function () {
- this.$el.find('input').focus();
- }.bind(this));
- },
-
- closeTray: function () {
- var $tray = this.$el;
- $tray.velocity("reverse", FauxtonAPI.constants.MISC.TRAY_TOGGLE_SPEED, function () {
- $tray.hide();
- });
- FauxtonAPI.Events.trigger('lookaheadTray:close');
- },
-
- onKeyup: function (e) {
- if (e.which === 27) {
- this.closeTray();
- }
- }
- });
-
-
- //need to make this into a backbone view...
- var routeObjectSpinner;
-
- FauxtonAPI.RouteObject.on('beforeEstablish', function (routeObject) {
- if (!routeObject.disableLoader) {
- var opts = {
- lines: 16, // The number of lines to draw
- length: 8, // The length of each line
- width: 4, // The line thickness
- radius: 12, // The radius of the inner circle
- color: '#333', // #rbg or #rrggbb
- speed: 1, // Rounds per second
- trail: 10, // Afterglow percentage
- shadow: false // Whether to render a shadow
- };
-
- if (routeObjectSpinner) { return; }
-
- if (!$('.spinner').length) {
- $('<div class="spinner"></div>')
- .appendTo('#app-container');
+ });
+ }
+});
+
+Components.DocSearchTypeahead = Components.Typeahead.extend({
+ initialize: function (options) {
+ this.docLimit = options.docLimit || 30;
+ this.database = options.database;
+ _.bindAll(this);
+ },
+ source: function (id, process) {
+ var query = '?' + $.param({
+ startkey: JSON.stringify(id),
+ endkey: JSON.stringify(id + "\u9999"),
+ limit: this.docLimit
+ });
+
+ var url = FauxtonAPI.urls('allDocs', 'server', this.database.safeID(), query);
+
+ if (this.ajaxReq) { this.ajaxReq.abort(); }
+
+ this.ajaxReq = $.ajax({
+ cache: false,
+ url: url,
+ dataType: 'json',
+ success: function (data) {
+ var ids = _.map(data.rows, function (row) {
+ return row.id;
+ });
+ process(ids);
}
+ });
+ }
+});
- routeObjectSpinner = new Spinner(opts).spin();
- $('.spinner').append(routeObjectSpinner.el);
+Components.LookaheadTray = FauxtonAPI.View.extend({
+ className: "lookahead-tray tray",
+ template: "addons/fauxton/templates/lookahead_tray",
+ placeholder: "Enter to search",
+
+ events: {
+ 'click #js-close-tray': 'closeTray',
+ 'keyup': 'onKeyup'
+ },
+
+ serialize: function () {
+ return {
+ placeholder: this.placeholder
+ };
+ },
+
+ initialize: function (opts) {
+ this.data = opts.data;
+ this.toggleEventName = opts.toggleEventName;
+ this.onUpdateEventName = opts.onUpdateEventName;
+
+ var trayIsVisible = _.bind(this.trayIsVisible, this);
+ var closeTray = _.bind(this.closeTray, this);
+ $("body").on("click.lookaheadTray", function (e) {
+ if (!trayIsVisible()) { return; }
+ if ($(e.target).closest(".lookahead-tray").length === 0 &&
+ $(e.target).closest('.lookahead-tray-link').length === 0) {
+ closeTray();
+ }
+ });
+ },
+
+ afterRender: function () {
+ var that = this;
+ this.dbSearchTypeahead = new Components.Typeahead({
+ el: 'input.search-autocomplete',
+ source: that.data,
+ onUpdateEventName: that.onUpdateEventName
+ });
+ this.dbSearchTypeahead.render();
+ },
+
+ clearValue: function () {
+ this.$('.search-autocomplete').val('');
+ },
+
+ cleanup: function () {
+ $("body").off("click.lookaheadTray");
+ },
+
+ trayIsVisible: function () {
+ return this.$el.is(":visible");
+ },
+
+ toggleTray: function () {
+ if (this.trayIsVisible()) {
+ this.closeTray();
+ } else {
+ this.openTray();
}
- });
-
- var removeRouteObjectSpinner = function () {
- if (routeObjectSpinner) {
- routeObjectSpinner.stop();
- routeObjectSpinner = null;
- $('.spinner').remove();
+ },
+
+ openTray: function () {
+ var speed = FauxtonAPI.constants.MISC.TRAY_TOGGLE_SPEED;
+ this.$el.velocity('transition.slideDownIn', speed, function () {
+ this.$el.find('input').focus();
+ }.bind(this));
+ },
+
+ closeTray: function () {
+ var $tray = this.$el;
+ $tray.velocity("reverse", FauxtonAPI.constants.MISC.TRAY_TOGGLE_SPEED, function () {
+ $tray.hide();
+ });
+ FauxtonAPI.Events.trigger('lookaheadTray:close');
+ },
+
+ onKeyup: function (e) {
+ if (e.which === 27) {
+ this.closeTray();
}
- };
+ }
+});
- var removeViewSpinner = function (selector) {
- var viewSpinner = viewSpinners[selector];
- if (viewSpinner) {
- viewSpinner.stop();
- $(selector).find('.spinner').remove();
- delete viewSpinners[selector];
- }
- };
-
- var viewSpinners = {};
- FauxtonAPI.RouteObject.on('beforeRender', function (routeObject, view, selector) {
- removeRouteObjectSpinner();
-
- if (!view.disableLoader) {
- var opts = _.extend({
- lines: 16, // The number of lines to draw
- length: 8, // The length of each line
- width: 4, // The line thickness
- radius: 12, // The radius of the inner circle
- color: '#333', // #rbg or #rrggbb
- speed: 1, // Rounds per second
- trail: 10, // Afterglow percentage
- shadow: false // Whether to render a shadow
- }, view.loaderStyles);
-
- var viewSpinner = new Spinner(opts).spin();
- $('<div class="spinner"></div>')
- .appendTo(selector)
- .append(viewSpinner.el);
+//need to make this into a backbone view...
+var routeObjectSpinner;
- viewSpinners[selector] = viewSpinner;
+FauxtonAPI.RouteObject.on('beforeEstablish', function (routeObject) {
+ if (!routeObject.disableLoader) {
+ var opts = {
+ lines: 16, // The number of lines to draw
+ length: 8, // The length of each line
+ width: 4, // The line thickness
+ radius: 12, // The radius of the inner circle
+ color: '#333', // #rbg or #rrggbb
+ speed: 1, // Rounds per second
+ trail: 10, // Afterglow percentage
+ shadow: false // Whether to render a shadow
+ };
+
+ if (routeObjectSpinner) { return; }
+
+ if (!$('.spinner').length) {
+ $('<div class="spinner"></div>')
+ .appendTo('#app-container');
}
- });
- FauxtonAPI.RouteObject.on('afterRender', function (routeObject, view, selector) {
- removeViewSpinner(selector);
- });
+ routeObjectSpinner = new Spinner(opts).spin();
+ $('.spinner').append(routeObjectSpinner.el);
+ }
+});
- FauxtonAPI.RouteObject.on('viewHasRendered', function (view, selector) {
- removeViewSpinner(selector);
- removeRouteObjectSpinner();
- });
+var removeRouteObjectSpinner = function () {
+ if (routeObjectSpinner) {
+ routeObjectSpinner.stop();
+ routeObjectSpinner = null;
+ $('.spinner').remove();
+ }
+};
+
+var removeViewSpinner = function (selector) {
+ var viewSpinner = viewSpinners[selector];
+
+ if (viewSpinner) {
+ viewSpinner.stop();
+ $(selector).find('.spinner').remove();
+ delete viewSpinners[selector];
+ }
+};
+
+var viewSpinners = {};
+FauxtonAPI.RouteObject.on('beforeRender', function (routeObject, view, selector) {
+ removeRouteObjectSpinner();
+
+ if (!view.disableLoader) {
+ var opts = _.extend({
+ lines: 16, // The number of lines to draw
+ length: 8, // The length of each line
+ width: 4, // The line thickness
+ radius: 12, // The radius of the inner circle
+ color: '#333', // #rbg or #rrggbb
+ speed: 1, // Rounds per second
+ trail: 10, // Afterglow percentage
+ shadow: false // Whether to render a shadow
+ }, view.loaderStyles);
+
+ var viewSpinner = new Spinner(opts).spin();
+ $('<div class="spinner"></div>')
+ .appendTo(selector)
+ .append(viewSpinner.el);
+
+ viewSpinners[selector] = viewSpinner;
+ }
+});
+FauxtonAPI.RouteObject.on('afterRender', function (routeObject, view, selector) {
+ removeViewSpinner(selector);
+});
- return Components;
+FauxtonAPI.RouteObject.on('viewHasRendered', function (view, selector) {
+ removeViewSpinner(selector);
+ removeRouteObjectSpinner();
});
+
+
+export default Components;