Repository: couchdb-fauxton Updated Branches: refs/heads/master b1e63328b -> 9d7cd4421
Convert Sidebar to React Converts Sidebar to React. Fixes COUCHDB-2703 Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/9d7cd442 Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/9d7cd442 Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/9d7cd442 Branch: refs/heads/master Commit: 9d7cd44213a56a0a84486048c105b5c9c62c04ee Parents: b1e6332 Author: Garren Smith <[email protected]> Authored: Mon May 25 17:16:33 2015 +0200 Committer: [email protected] <[email protected]> Committed: Thu Jun 11 18:02:11 2015 -0400 ---------------------------------------------------------------------- app/addons/compaction/routes.js | 2 +- .../nightwatch/compactAndCleanIsPresent.js | 2 +- .../components/react-components.react.jsx | 59 ++- app/addons/cors/assets/less/cors.less | 4 - .../databases/tests/nightwatch/zeroclipboard.js | 1 + app/addons/documents/assets/less/sidenav.less | 35 +- app/addons/documents/changes/actions.js | 4 +- app/addons/documents/routes-documents.js | 20 +- app/addons/documents/routes-mango.js | 10 +- app/addons/documents/shared-routes.js | 18 +- app/addons/documents/shared-views.js | 320 ------------- app/addons/documents/sidebar/actions.js | 52 +++ app/addons/documents/sidebar/actiontypes.js | 20 + app/addons/documents/sidebar/sidebar.react.jsx | 448 +++++++++++++++++++ app/addons/documents/sidebar/stores.js | 153 +++++++ .../sidebar/tests/sidebar.storesSpec.js | 79 ++++ .../documents/templates/design_doc_menu.html | 32 -- .../documents/templates/index_menu_item.html | 31 -- app/addons/documents/templates/sidebar.html | 50 --- .../switchDatabaseViaLookaheadTray.js | 3 +- .../documents/tests/nightwatch/viewCreate.js | 11 +- app/addons/documents/views.js | 5 +- assets/less/fauxton.less | 3 +- assets/less/templates.less | 5 +- 24 files changed, 890 insertions(+), 477 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/9d7cd442/app/addons/compaction/routes.js ---------------------------------------------------------------------- diff --git a/app/addons/compaction/routes.js b/app/addons/compaction/routes.js index ea6d54f..f098768 100644 --- a/app/addons/compaction/routes.js +++ b/app/addons/compaction/routes.js @@ -39,7 +39,7 @@ function (app, FauxtonAPI, Compaction, Actions, Databases, BaseRoute) { this.createDesignDocsCollection(); this.addLeftHeader(); - this.addSidebar('docLink_compact'); + this.addSidebar('compact'); }, onSelectDatabase: function (dbName) { http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/9d7cd442/app/addons/compaction/tests/nightwatch/compactAndCleanIsPresent.js ---------------------------------------------------------------------- diff --git a/app/addons/compaction/tests/nightwatch/compactAndCleanIsPresent.js b/app/addons/compaction/tests/nightwatch/compactAndCleanIsPresent.js index a9fb368..12f8c16 100644 --- a/app/addons/compaction/tests/nightwatch/compactAndCleanIsPresent.js +++ b/app/addons/compaction/tests/nightwatch/compactAndCleanIsPresent.js @@ -22,7 +22,7 @@ module.exports = { //navigate to 'Compact & Clean' view .clickWhenVisible('#dashboard-content a[href="#/database/' + newDatabaseName + '/_all_docs"]') - .clickWhenVisible('#docLink_compact') + .clickWhenVisible('#compact') .waitForElementVisible('#compact-db', waitTime, false) .waitForElementVisible('#cleanup-views', waitTime, false) .end(); http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/9d7cd442/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 9458b51..d543a09 100644 --- a/app/addons/components/react-components.react.jsx +++ b/app/addons/components/react-components.react.jsx @@ -620,6 +620,62 @@ function (app, FauxtonAPI, React, Components, ace, beautifyHelper) { } }); + var MenuDropDown = React.createClass({ + + getDefaultProps: function () { + return { + icon: 'fonticon-plus-circled' + }; + }, + + createSectionLinks: function (links) { + if (!links) { return null; } + return links.map(function (link, key) { + return ( + <li key={key}> + <a className={link.icon ? 'icon ' + link.icon : ''} + data-bypass={link.external ? 'true' : ''} + href={link.url} + target={link.external ? '_blank' : ''}> + {link.title} + </a> + </li> + ); + }); + }, + + createSectionTitle: function (title) { + if (!title) { + return null; + } + + return ( + <li className="header-label">{title}</li> + ); + }, + + createSection: function () { + return this.props.links.map(function (linkSection, key) { + return ( + <ul className="dropdown-menu arrow" key={key} role="menu" aria-labelledby="dLabel"> + {this.createSectionTitle(linkSection.title)} + {this.createSectionLinks(linkSection.links)} + </ul> + ); + }.bind(this)); + }, + + render: function () { + return ( + <div className="dropdown"> + <a className={"dropdown-toggle icon " + this.props.icon} data-toggle="dropdown" href="#" data-bypass="true"></a> + {this.createSection()} + </div> + ); + } + + }); + var ReactComponents = { ConfirmButton: ConfirmButton, ToggleHeaderButton: ToggleHeaderButton, @@ -629,7 +685,8 @@ function (app, FauxtonAPI, React, Components, ace, beautifyHelper) { Beautify: Beautify, PaddedBorderedBox: PaddedBorderedBox, Document: Document, - LoadLines: LoadLines + LoadLines: LoadLines, + MenuDropDown: MenuDropDown }; return ReactComponents; http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/9d7cd442/app/addons/cors/assets/less/cors.less ---------------------------------------------------------------------- diff --git a/app/addons/cors/assets/less/cors.less b/app/addons/cors/assets/less/cors.less index 259e247..59b5dda 100644 --- a/app/addons/cors/assets/less/cors.less +++ b/app/addons/cors/assets/less/cors.less @@ -14,10 +14,6 @@ @import "../../../../../assets/less/variables.less"; @import "../../../../../assets/less/bootstrap/mixins.less"; -#sidebar-content .nav-list li a span { - display: none; -} - #cors-header { margin: 18px 30px 0 30px; } http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/9d7cd442/app/addons/databases/tests/nightwatch/zeroclipboard.js ---------------------------------------------------------------------- diff --git a/app/addons/databases/tests/nightwatch/zeroclipboard.js b/app/addons/databases/tests/nightwatch/zeroclipboard.js index 8c0c282..bdfa1d3 100644 --- a/app/addons/databases/tests/nightwatch/zeroclipboard.js +++ b/app/addons/databases/tests/nightwatch/zeroclipboard.js @@ -36,6 +36,7 @@ module.exports = { .mouseButtonDown('left') .mouseButtonUp('left') .closeNotification() + .clickWhenVisible('.search-autocomplete', waitTime, false) .setValue('.search-autocomplete', '') .keys([controlOrCommandKey, 'v']) .assert.value('.search-autocomplete', 'http://localhost:8000/_all_dbs') http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/9d7cd442/app/addons/documents/assets/less/sidenav.less ---------------------------------------------------------------------- diff --git a/app/addons/documents/assets/less/sidenav.less b/app/addons/documents/assets/less/sidenav.less index e75a7f6..27aa406 100644 --- a/app/addons/documents/assets/less/sidenav.less +++ b/app/addons/documents/assets/less/sidenav.less @@ -10,7 +10,38 @@ // License for the specific language governing permissions and limitations under // the License. +#sidebar-content { + .loading-lines { + margin-top: 20px; + } +} + .sidenav{ + .sidebar-toggler { + top: 5px; + position: absolute; + right: 7px; + z-index: 100; + width: 60px; + height: 35px; + text-align: center; + line-height: 35px; + text-decoration: none; + .icon { + padding-right: 3px; + } + + &.sidebar-hidden { + &:hover { + background-color: rgba(153, 153, 153, 0.1); + } + width: 120px; + right: 210px; + } + } + .nav li + .nav-header { + margin-top: 0px; + } .nav-list > .active > a{ text-shadow: none; background-color: rgba(0, 0, 0, 0.05); @@ -159,7 +190,3 @@ } } } - - - - http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/9d7cd442/app/addons/documents/changes/actions.js ---------------------------------------------------------------------- diff --git a/app/addons/documents/changes/actions.js b/app/addons/documents/changes/actions.js index 447833c..167f13c 100644 --- a/app/addons/documents/changes/actions.js +++ b/app/addons/documents/changes/actions.js @@ -68,7 +68,9 @@ function (app, FauxtonAPI, ActionTypes, Stores, Helpers) { var query = $.param(params); var db = app.utils.safeURLName(changesStore.getDatabaseName()); - currentRequest = $.get('/' + db + '/_changes?' + query); + + var endpoint = FauxtonAPI.urls('changes', 'apiurl', db, ''); + currentRequest = $.get(endpoint); currentRequest.then(_.bind(this.updateChanges, this)); }, http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/9d7cd442/app/addons/documents/routes-documents.js ---------------------------------------------------------------------- diff --git a/app/addons/documents/routes-documents.js b/app/addons/documents/routes-documents.js index 3231c89..4d78aed 100644 --- a/app/addons/documents/routes-documents.js +++ b/app/addons/documents/routes-documents.js @@ -30,13 +30,14 @@ define([ 'addons/documents/pagination/pagination.react', 'addons/documents/header/header.react', 'addons/documents/header/header.actions', + 'addons/documents/sidebar/actions', 'addons/documents/designdocinfo/actions', 'addons/documents/designdocinfo/components.react' ], function (app, FauxtonAPI, BaseRoute, Documents, Changes, ChangesActions, DocEditor, Databases, Resources, Components, PaginationStores, IndexResultsActions, - IndexResultsComponents, ReactPagination, ReactHeader, ReactActions, + IndexResultsComponents, ReactPagination, ReactHeader, ReactActions, SidebarActions, DesignDocInfoActions, DesignDocInfoComponents) { var DocumentsRouteObject = BaseRoute.extend({ @@ -97,7 +98,8 @@ function (app, FauxtonAPI, BaseRoute, Documents, Changes, ChangesActions, DocEdi }); this.setComponent("#dashboard-lower-content", DesignDocInfoComponents.DesignDocInfo); - this.sidebar.setSelectedTab(app.utils.removeSpecialCharacters(ddoc) + "_metadata"); + SidebarActions.setSelectedTab(app.utils.removeSpecialCharacters(ddoc) + "_metadata"); + this.leftheader.updateCrumbs(this.getCrumbs(this.database)); this.rightHeader.hideQueryOptions(); @@ -125,12 +127,13 @@ function (app, FauxtonAPI, BaseRoute, Documents, Changes, ChangesActions, DocEdi this.database.buildAllDocs(docParams); collection = this.database.allDocs; + var tab = 'all-docs'; if (docParams.startkey && docParams.startkey.indexOf("_design") > -1) { - this.sidebar.setSelectedTab("design-docs"); - } else { - this.sidebar.setSelectedTab("all-docs"); + tab = 'design-docs'; } + SidebarActions.setSelectedTab(tab); + this.removeComponent('#dashboard-upper-content'); if (!docParams) { @@ -157,11 +160,10 @@ function (app, FauxtonAPI, BaseRoute, Documents, Changes, ChangesActions, DocEdi this.rightHeader.showQueryOptions(); }, + //TODO: REMOVE reloadDesignDocs: function (event) { - this.sidebar.forceRender(); - if (event && event.selectedTab) { - this.sidebar.setSelectedTab(event.selectedTab); + SidebarActions.setSelectedTab(event.selectedTab); } }, @@ -177,7 +179,7 @@ function (app, FauxtonAPI, BaseRoute, Documents, Changes, ChangesActions, DocEdi this.viewEditor && this.viewEditor.remove(); - this.sidebar.setSelectedTab('changes'); + SidebarActions.setSelectedTab('changes'); this.leftheader.updateCrumbs(this.getCrumbs(this.database)); this.rightHeader.hideQueryOptions(); http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/9d7cd442/app/addons/documents/routes-mango.js ---------------------------------------------------------------------- diff --git a/app/addons/documents/routes-mango.js b/app/addons/documents/routes-mango.js index a8301ab..e2d827e 100644 --- a/app/addons/documents/routes-mango.js +++ b/app/addons/documents/routes-mango.js @@ -31,15 +31,15 @@ define([ 'addons/documents/mango/mango.components.react', 'addons/documents/mango/mango.actions', 'addons/documents/mango/mango.stores', - 'addons/documents/index-results/index-results.components.react' - + 'addons/documents/index-results/index-results.components.react', + 'addons/documents/sidebar/actions', ], function (app, FauxtonAPI, Helpers, BaseRoute, Databases, Components, Resources, Documents, IndexResultsActions, PaginationStores, ReactHeader, ReactActions, ReactPagination, - MangoComponents, MangoActions, MangoStores, IndexResultsComponents) { + MangoComponents, MangoActions, MangoStores, IndexResultsComponents, SidebarActions) { var MangoIndexEditorAndQueryEditor = BaseRoute.extend({ layout: 'two_pane', @@ -63,7 +63,6 @@ function (app, FauxtonAPI, Helpers, BaseRoute, Databases, this.allDatabases = this.getAllDatabases(); this.createDesignDocsCollection(); this.addLeftHeader(); - this.addSidebar(); MangoActions.setDatabase({ database: this.database @@ -89,8 +88,7 @@ function (app, FauxtonAPI, Helpers, BaseRoute, Databases, ReactActions.resetHeaderController(); - // magic method - this.sidebar.setSelectedTab('mango-query'); + SidebarActions.setSelectedTab('mango-query'); this.setComponent('#react-headerbar', ReactHeader.HeaderBarController); this.setComponent('#footer', ReactPagination.Footer); http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/9d7cd442/app/addons/documents/shared-routes.js ---------------------------------------------------------------------- diff --git a/app/addons/documents/shared-routes.js b/app/addons/documents/shared-routes.js index 9a59afd..2bf52b4 100644 --- a/app/addons/documents/shared-routes.js +++ b/app/addons/documents/shared-routes.js @@ -17,8 +17,11 @@ define([ 'addons/databases/base', 'addons/fauxton/components', 'addons/documents/pagination/actions', - 'addons/documents/pagination/stores' -], function (app, FauxtonAPI, Documents, Databases, Components, PaginationActions, PaginationStores ) { + 'addons/documents/pagination/stores', + 'addons/documents/sidebar/sidebar.react', + 'addons/documents/sidebar/actions' +], function (app, FauxtonAPI, Documents, Databases, Components, PaginationActions, PaginationStores, + SidebarComponents, SidebarActions) { // The Documents section is built up a lot of different route object which share code. This contains @@ -99,14 +102,17 @@ define([ }, addSidebar: function (selectedTab) { - var params = { - collection: this.designDocs, + var options = { + designDocs: this.designDocs, database: this.database }; + if (selectedTab) { - params.selectedTab = selectedTab; + options.selectedTab = selectedTab; } - this.sidebar = this.setView("#sidebar-content", new Documents.Views.Sidebar(params)); + + SidebarActions.newOptions(options); + this.setComponent("#sidebar-content", SidebarComponents.SidebarController); }, getCrumbs: function (database) { http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/9d7cd442/app/addons/documents/shared-views.js ---------------------------------------------------------------------- diff --git a/app/addons/documents/shared-views.js b/app/addons/documents/shared-views.js deleted file mode 100644 index fa14731..0000000 --- a/app/addons/documents/shared-views.js +++ /dev/null @@ -1,320 +0,0 @@ -// 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([ - "app", - - "api", - "addons/fauxton/components", - - "addons/documents/resources", - "addons/databases/resources", - "css.escape" -], - -function (app, FauxtonAPI, Components, Documents, Databases) { - var Views = {}; - - Views.Sidebar = FauxtonAPI.View.extend({ - template: "addons/documents/templates/sidebar", - className: "sidenav", - tagName: "nav", - - initialize: function (options) { - this.database = options.database; - - if (options.ddocInfo) { - this.ddocID = options.ddocInfo.id; - this.currView = options.ddocInfo.currView; - } - - this.designDocList = []; - }, - - serialize: function () { - var docLinks = FauxtonAPI.getExtensions('docLinks'), - extensionList = FauxtonAPI.getExtensions('sidebar:list'), - safeDatabaseName = this.database.safeID(), - changesLink = '#' + FauxtonAPI.urls('changes', 'app', safeDatabaseName, ''), - permissionsLink = '#' + FauxtonAPI.urls('permissions', 'app', safeDatabaseName), - databaseUrl = FauxtonAPI.urls('allDocs', 'app', safeDatabaseName, ''), - db_url = FauxtonAPI.urls('allDocs', 'server', safeDatabaseName, ''), - base = '#' + FauxtonAPI.urls('base', 'app', safeDatabaseName); - - return { - changesUrl: changesLink, - permissionsUrl: permissionsLink, - docLinks: docLinks, - databaseUrl: databaseUrl, - base: base, - mangoQueryUrl: FauxtonAPI.urls('mango', 'query-app', safeDatabaseName), - runQueryWithMangoText: app.i18n.en_US['run-query-with-mango'] - }; - }, - - getNewButtonLinks: function () { //these are links for the sidebar '+' on All Docs and All Design Docs - var database = this.collection.database, - addLinks = FauxtonAPI.getExtensions('sidebar:links'), - databaseName = database.id, - newUrlPrefix = '#' + FauxtonAPI.urls('databaseBaseURL', 'app', databaseName); - - return _.reduce(addLinks, function (menuLinks, link) { - - menuLinks.push({ - title: link.title, - url: newUrlPrefix + '/' + link.url, - icon: 'fonticon-plus-circled' - }); - - return menuLinks; - }, [{ - title: 'New Doc', - url: newUrlPrefix + '/new', - icon: 'fonticon-plus-circled' - }, { - title: 'New View', - url: newUrlPrefix + '/new_view', - icon: 'fonticon-plus-circled' - }, this.getMangoLink()]); - }, - - getMangoLink: function () { - var database = this.collection.database, - databaseName = database.id, - newUrlPrefix = '#' + FauxtonAPI.urls('databaseBaseURL', 'app', databaseName); - - return { - title: app.i18n.en_US['new-mango-index'], - url: newUrlPrefix + '/_index', - icon: 'fonticon-plus-circled' - }; - }, - - beforeRender: function (manage) { - this.deleteDBModal = this.setView( - '#delete-db-modal', - new Views.DeleteDBModal({ - database: this.database, - isSystemDatabase: this.database.isSystemDatabase() - }) - ); - - var newLinks = [{ - title: 'Add new', - links: this.getNewButtonLinks() - }]; - - [ - '#new-all-docs-button', - '#new-design-docs-button' - ].forEach(function (id) { - this.setView(id, new Components.MenuDropDown({ - links: newLinks, - })); - }.bind(this)); - - this.setView('#mango-query-button', new Components.MenuDropDown({ - links: [{ - title: 'Add new', - links: [this.getMangoLink()] - }] - })); - - - _.each(this.designDocList, function (view) { view.remove(); view = undefined;}); - this.designDocList = []; - - this.collection.each(function (design) { - - if (design.get('doc').language === 'query') { - return; - } - - if (design.has('doc')) { - design.collection = this.collection; - var view = this.insertView(new Views.DdocSidenav({ - model: design, - collection: this.collection - })); - - this.designDocList.push(view); - } - }, this); - }, - - afterRender: function () { - if (this.selectedTab) { - this.setSelectedTab(this.selectedTab); - } - }, - - setSelectedTab: function (selectedTab) { - this.selectedTab = selectedTab; - var $selectedTab = this.$('#' + selectedTab); - - this.$('li').removeClass('active'); - $selectedTab.parent().addClass('active'); - - if ($selectedTab.parents(".accordion-body").length !== 0) { - $selectedTab - .parents(".accordion-body") - .addClass("in") - .parents(".nav-header") - .find(">.js-collapse-toggle").addClass("down"); - - this.$('.js-toggle-' + $selectedTab.data('ddoctype')).addClass("down"); - } - } - }); - - Views.DdocSidenav = FauxtonAPI.View.extend({ - tagName: "ul", - className: "nav nav-list", - template: "addons/documents/templates/design_doc_menu", - events: { - "click .js-collapse-toggle": "toggleArrow" - }, - - toggleArrow: function (e) { - var escapedId = window.CSS.escape(e.currentTarget.id), - $toggleElement = this.$('#' + escapedId).next(); - - this.$('#' + escapedId).toggleClass('down'); - $toggleElement.collapse('toggle'); - }, - - buildIndexList: function (designDocs, info) { - var design = this.model.id.replace(/^_design\//, ""); - var databaseId = this.model.database.id; - - if (_.isUndefined(designDocs[info.selector])) { return; } - - this.insertView(".accordion-body", new Views.IndexItem({ - selector: info.selector, - ddoc: design, - collection: designDocs[info.selector], - name: info.name, - database: databaseId - })); - }, - - serialize: function () { - var ddocName = this.model.id.replace(/^_design\//, ""), - escapedId = window.CSS.escape(ddocName), - docSafe = app.utils.safeURLName(ddocName), - databaseName = this.collection.database.safeID(); - - return { - designDocMetaUrl: FauxtonAPI.urls('designDocs', 'app', databaseName, docSafe), - designDoc: ddocName, - escapedId: escapedId - }; - }, - - getSidebarLinks: function () { //these are for each Design doc '+' links - var ddocName = this.model.id.replace(/^_design\//, ""), - docSafe = app.utils.safeURLName(ddocName), - databaseName = this.collection.database.id, - newUrlPrefix = FauxtonAPI.urls('databaseBaseURL', 'app', databaseName); - - - return _.reduce(FauxtonAPI.getExtensions('sidebar:links'), function (menuLinks, link) { - menuLinks.push({ - title: link.title, - url: '#' + newUrlPrefix + '/' + link.url + '/' + docSafe, - icon: 'fonticon-plus-circled' - }); - - return menuLinks; - }, [{ - title: 'New View', - url: '#' + FauxtonAPI.urls('new', 'addView', databaseName, docSafe), - icon: 'fonticon-plus-circled' - }]); - - }, - - renderIndexLists: function () { - var ddocDocs = this.model.get("doc"), - sidebarListTypes = FauxtonAPI.getExtensions('sidebar:list'); - - if (!ddocDocs) { return; } - - this.buildIndexList(ddocDocs, { - selector: "views", - name: 'Views' - }); - - _.each(sidebarListTypes, function (info) { - this.buildIndexList(ddocDocs, info); - }, this); - - }, - - beforeRender: function (manage) { - var sideBarMenuLinks = []; - - sideBarMenuLinks.push({ - title: 'Add new', - links: this.getSidebarLinks() - }); - - this.renderIndexLists(); - this.setView(".new-button", new Components.MenuDropDown({ - links: sideBarMenuLinks, - })); - } - }); - - Views.IndexItem = FauxtonAPI.View.extend({ - template: "addons/documents/templates/index_menu_item", - tagName: 'li', - - initialize: function (options) { - this.index = options.index; - this.ddoc = options.ddoc; - this.database = options.database; - this.selected = !! options.selected; - this.selector = options.selector; - this.name = options.name; - - this.indexTypeMap = { - views: { icon: 'fonticon-sidenav-map-reduce', urlFolder: '_view', type: 'view' }, - indexes: { icon: 'fonticon-sidenav-search', urlFolder: '_indexes', type: 'search' } - }; - }, - - serialize: function () { - return { - icon: this.indexTypeMap[this.selector].icon, - urlFolder: this.indexTypeMap[this.selector].urlFolder, - ddocType: this.selector, - name: this.name, - index: this.index, - ddoc: this.ddoc, - database: this.database, - selected: this.selected, - collection: this.collection, - href: FauxtonAPI.urls(this.indexTypeMap[this.selector].type, 'app', this.database, this.ddoc) - }; - }, - - afterRender: function () { - if (this.selected) { - $(".sidenav ul.nav-list li").removeClass("active"); - this.$el.addClass("active"); - } - } - }); - - return Views; -}); http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/9d7cd442/app/addons/documents/sidebar/actions.js ---------------------------------------------------------------------- diff --git a/app/addons/documents/sidebar/actions.js b/app/addons/documents/sidebar/actions.js new file mode 100644 index 0000000..ca84585 --- /dev/null +++ b/app/addons/documents/sidebar/actions.js @@ -0,0 +1,52 @@ +// 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([ + 'app', + 'api', + 'addons/documents/sidebar/actiontypes', + 'addons/documents/sidebar/stores' +], +function (app, FauxtonAPI, ActionTypes, Stores) { + var store = Stores.sidebarStore; + return { + newOptions: function (options) { + if (options.database.safeID() !== store.getDatabaseName()) { + FauxtonAPI.dispatch({ + type: ActionTypes.SIDEBAR_FETCHING + }); + } + + options.designDocs.fetch().then(function () { + FauxtonAPI.dispatch({ + type: ActionTypes.SIDEBAR_NEW_OPTIONS, + options: options + }); + }); + }, + + toggleContent: function (designDoc, index) { + FauxtonAPI.dispatch({ + type: ActionTypes.SIDEBAR_TOGGLE_CONTENT, + designDoc: designDoc, + index: index + }); + }, + + setSelectedTab: function (tab) { + FauxtonAPI.dispatch({ + type: ActionTypes.SIDEBAR_SET_SELECTED_TAB, + tab: tab + }); + } + }; +}); http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/9d7cd442/app/addons/documents/sidebar/actiontypes.js ---------------------------------------------------------------------- diff --git a/app/addons/documents/sidebar/actiontypes.js b/app/addons/documents/sidebar/actiontypes.js new file mode 100644 index 0000000..c1d6af5 --- /dev/null +++ b/app/addons/documents/sidebar/actiontypes.js @@ -0,0 +1,20 @@ +// 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([], function () { + return { + SIDEBAR_SET_SELECTED_TAB: 'SIDEBAR_SET_SELECTED_TAB', + SIDEBAR_NEW_OPTIONS: 'SIDEBAR_NEW_OPTIONS', + SIDEBAR_TOGGLE_DESIGN_DOC: 'SIDEBAR_TOGGLE_CONTENT', + SIDEBAR_FETCHING: 'SIDEBAR_FETCHING' + }; +}); http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/9d7cd442/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 new file mode 100644 index 0000000..70e4f53 --- /dev/null +++ b/app/addons/documents/sidebar/sidebar.react.jsx @@ -0,0 +1,448 @@ +// 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([ + 'app', + 'api', + 'react', + 'addons/documents/sidebar/stores', + 'addons/documents/sidebar/actions', + 'addons/components/react-components.react', + 'addons/documents/views', + + 'plugins/prettify' +], + +function (app, FauxtonAPI, React, Stores, Actions, Components, DocumentViews) { + var DeleteDBModal = DocumentViews.Views.DeleteDBModal; + var store = Stores.sidebarStore; + var LoadLines = Components.LoadLines; + + var SidebarToggle = React.createClass({ + getInitialState: function () { + return { + hidden: false + }; + }, + + toggle: function (e) { + e.preventDefault(); + var newHiddenState = !this.state.hidden; + this.setState({hidden: newHiddenState}); + var $dashboard = $('#dashboard-content'); + + if (newHiddenState) { + $dashboard.animate({left: '210px'}, 300); + } else { + $dashboard.animate({left: '550px'}, 300); + } + + }, + + render: function () { + return null; + } + + }); + + var MainSidebar = React.createClass({ + + getNewButtonLinks: function () { //these are links for the sidebar '+' on All Docs and All Design Docs + var addLinks = FauxtonAPI.getExtensions('sidebar:links'); + var databaseName = this.props.databaseName; + var newUrlPrefix = '#' + FauxtonAPI.urls('databaseBaseURL', 'app', databaseName); + + var addNewLinks = _.reduce(addLinks, function (menuLinks, link) { + menuLinks.push({ + title: link.title, + url: newUrlPrefix + '/' + link.url, + icon: 'fonticon-plus-circled' + }); + + return menuLinks; + }, [{ + title: 'New Doc', + url: newUrlPrefix + '/new', + icon: 'fonticon-plus-circled' + }, { + title: 'New View', + url: newUrlPrefix + '/new_view', + icon: 'fonticon-plus-circled' + }, this.getMangoLink()]); + + return [{ + title: 'Add new', + links: addNewLinks + }]; + }, + + getMangoLink: function () { + var databaseName = this.props.databaseName; + var newUrlPrefix = '#' + FauxtonAPI.urls('databaseBaseURL', 'app', databaseName); + + return { + title: app.i18n.en_US['new-mango-index'], + url: newUrlPrefix + '/_index', + icon: 'fonticon-plus-circled' + }; + }, + + buildDocLinks: function () { + var base = FauxtonAPI.urls('base', 'app', this.props.databaseName); + var isActive = this.props.isActive; + + return FauxtonAPI.getExtensions('docLinks').map(function (link) { + return ( + <li key={link.url} className={isActive(link.url)}> + <a id={link.url} href={base + link.url}>{link.title}</a> + </li> + ); + + }); + }, + + render: function () { + var isActive = this.props.isActive; + var docLinks = this.buildDocLinks(); + var changesUrl = '#' + FauxtonAPI.urls('changes', 'app', this.props.databaseName, ''); + var permissionsUrl = '#' + FauxtonAPI.urls('permissions', 'app', this.props.databaseName); + var databaseUrl = FauxtonAPI.urls('allDocs', 'app', this.props.databaseName, ''); + var mangoQueryUrl = FauxtonAPI.urls('mango', 'query-app', this.props.databaseName); + var runQueryWithMangoText = app.i18n.en_US['run-query-with-mango']; + var buttonLinks = this.getNewButtonLinks(); + + return ( + <ul className="nav nav-list"> + <li className={isActive('permissions')}> + <a id="permissions" href={permissionsUrl}>Permissions</a> + </li> + <li className={isActive('changes')}> + <a id="changes" href={changesUrl}>Changes</a> + </li> + {docLinks} + <li className={isActive('all-docs')}> + <a id="all-docs" + href={"#/" + databaseUrl} + className="toggle-view"> + All Documents + </a> + <div id="new-all-docs-button" className="add-dropdown"> + <Components.MenuDropDown links={buttonLinks} /> + </div> + </li> + <li className={isActive('mango-query')}> + <a + id="mango-query" + href={'#/' + mangoQueryUrl} + className="toggle-view"> + {runQueryWithMangoText} + </a> + <div id="mango-query-button" className="add-dropdown"> + <Components.MenuDropDown links={buttonLinks} /> + </div> + </li> + <li className={isActive('design-docs')}> + <a + id="design-docs" + href={"#/" + databaseUrl + '?startkey="_design"&endkey="_design0"'} + className="toggle-view"> + All Design Docs + </a> + <div id="new-design-docs-button" className="add-dropdown"> + <Components.MenuDropDown links={buttonLinks} /> + </div> + </li> + </ul> + ); + } + + }); + + var IndexSection = React.createClass({ + + getDefaultProps: function () { + return { + indexTypeMap: { + views: { icon: 'fonticon-sidenav-map-reduce', urlFolder: '_view', type: 'view' }, + indexes: { icon: 'fonticon-sidenav-search', urlFolder: '_indexes', type: 'search' } + } + }; + }, + + createItems: function () { + return _.map(this.props.items, function (index, key) { + var href = FauxtonAPI.urls(this.props.indexTypeMap[this.props.selector].type, 'app', this.props.databaseName, this.props.designDocName); + return ( + <li key={key}> + <a + id={this.props.designDocName + '_' + index} + href={"#/" + href + index} + className="toggle-view"> + {index} + </a> + </li> + ); + }, this); + }, + + toggle: function (e) { + e.preventDefault(); + var newToggleState = !this.props.contentVisible; + var state = newToggleState ? 'show' : 'hide'; + $(this.getDOMNode()).find('.accordion-body').collapse(state); + this.props.toggle(this.props.designDocName, this.props.title); + }, + + render: function () { + var toggleClassNames = 'accordion-header'; + var toggleBodyClassNames = 'accordion-body collapse'; + if (this.props.contentVisible) { + toggleClassNames += ' down'; + toggleBodyClassNames += ' in'; + } + + var title = this.props.title; + var icon = this.props.indexTypeMap[this.props.selector].icon; + var designDocName = this.props.designDocName; + var linkId = "nav-design-function-" + designDocName + this.props.selector; + return ( + <li id={linkId} onClick={this.toggle}> + <a className={toggleClassNames} data-toggle="collapse"> + <div className="fonticon-play"></div> + <span className={icon + " fonticon"}></span> + {title} + </a> + <ul className={toggleBodyClassNames}> + {this.createItems()} + </ul> + </li> + ); + } + + }); + + var DesignDoc = React.createClass({ + + createIndexList: function () { + var sidebarListTypes = FauxtonAPI.getExtensions('sidebar:list'); + + if (_.isEmpty(sidebarListTypes) || + (_.has(sidebarListTypes[0], 'selector') && sidebarListTypes[0].selector !== 'views')) { + sidebarListTypes.unshift({ + selector: 'views', + name: 'Views' + }); + } + + return _.map(sidebarListTypes, function (index, key) { + return <IndexSection + contentVisible={this.props.isVisible(this.props.designDocName, index.name)} + toggle={this.props.toggle} + databaseName={this.props.databaseName} + designDocName={this.props.designDocName} + key={key} + title={index.name} + selector={index.selector} + items={_.keys(this.props.designDoc[index.selector])} />; + }.bind(this)); + }, + + toggle: function (e) { + e.preventDefault(); + var newToggleState = !this.props.contentVisible; + var state = newToggleState ? 'show' : 'hide'; + $(this.getDOMNode()).find('#' + this.props.designDocName).collapse(state); + this.props.toggle(this.props.designDocName); + }, + + getNewButtonLinks: function () { + var databaseName = this.props.databaseName; + var newUrlPrefix = FauxtonAPI.urls('databaseBaseURL', 'app', databaseName); + var designDocName = this.props.designDocName; + + var addNewLinks = _.reduce(FauxtonAPI.getExtensions('sidebar:links'), function (menuLinks, link) { + menuLinks.push({ + title: link.title, + url: '#' + newUrlPrefix + '/' + link.url + '/' + designDocName, + icon: 'fonticon-plus-circled' + }); + + return menuLinks; + }, [{ + title: 'New View', + url: '#' + FauxtonAPI.urls('new', 'addView', databaseName, designDocName), + icon: 'fonticon-plus-circled' + }]); + + return [{ + title: 'Add new', + links: addNewLinks + }]; + }, + + render: function () { + var buttonLinks = this.getNewButtonLinks(); + var toggleClassNames = 'accordion-header'; + var toggleBodyClassNames = 'accordion-body collapse'; + + if (this.props.contentVisible) { + toggleClassNames += ' down'; + toggleBodyClassNames += ' in'; + } + var designDocName = this.props.designDocName; + var designDocMetaUrl = FauxtonAPI.urls('designDocs', 'app', this.props.databaseName, designDocName); + return ( + <li className="nav-header"> + + <div id={"sidebar-tab-" + designDocName} className={toggleClassNames}> + <div id={"nav-header-" + designDocName} onClick={this.toggle} className='accordion-list-item'> + <div className='fonticon-play'></div> + <p className='design-doc-name'> + <span title={'_design/' + designDocName}>{'_design/' + designDocName}</span> + </p> + </div> + <div className='new-button add-dropdown'> + <Components.MenuDropDown links={buttonLinks} /> + </div> + </div> + <ul className={toggleBodyClassNames} id={this.props.designDocName}> + <li> + <a href={"#/" + designDocMetaUrl} className="toggle-view accordion-header"> + <span className="fonticon-sidenav-info fonticon"></span> + Design Doc Metadata + </a> + </li> + {this.createIndexList()} + </ul> + </li> + ); + } + + }); + + var DesignDocList = React.createClass({ + createDesignDocs: function () { + return _.map(this.props.designDocs, function (designDoc, key) { + return <DesignDoc + toggle={this.props.toggle} + contentVisible={this.props.isVisible(designDoc.safeId)} + isVisible={this.props.isVisible} + key={key} + designDoc={designDoc} + designDocName={designDoc.safeId} + databaseName={this.props.databaseName} />; + }.bind(this)); + }, + + render: function () { + var designDocName = this.props.designDocName; + var designDocMetaUrl = FauxtonAPI.urls('designDocs', 'app', this.props.databaseName, designDocName); + + return ( + <ul className="nav nav-list"> + {this.createDesignDocs()} + </ul> + ); + } + + }); + + var DeleteDBModalWrapper = React.createClass({ + + componentDidMount: function () { + this.dbModal = new DeleteDBModal({ + database: this.props.database, + isSystemDatabase: (/^_/).test(this.props.database.id), + el: this.getDOMNode() + }); + + this.dbModal.render(); + }, + + componentWillUnmount: function () { + this.dbModal.remove(); + }, + + componentWillReceiveProps: function (newProps) { + this.dbModal.database = newProps.database; + this.dbModal.isSystemDatabase = newProps.database.isSystemDatabase(); + }, + + render: function () { + return <div id="delete-db-modal"> </div>; + } + + }); + + var SidebarController = React.createClass({ + getStoreState: function () { + return { + databaseName: store.getDatabaseName(), + selectedTab: store.getSelectedTab(), + designDocs: store.getDesignDocs(), + isVisible: _.bind(store.isVisible, store), + isLoading: store.isLoading(), + database: store.getDatabase() + }; + }, + + isActive: function (id) { + if (id === this.state.selectedTab) { + return 'active'; + } + + return ''; + }, + + getInitialState: function () { + return this.getStoreState(); + }, + + componentDidMount: function () { + store.on('change', this.onChange, this); + }, + + componentWillUnmount: function () { + store.off('change', this.onChange); + }, + + onChange: function () { + this.setState(this.getStoreState()); + }, + + + render: function () { + if (this.state.isLoading) { + return <LoadLines />; + } + + return ( + <nav className="sidenav"> + <SidebarToggle /> + <MainSidebar isActive={this.isActive} databaseName={this.state.databaseName} /> + <DesignDocList + toggle={Actions.toggleContent} + isVisible={this.state.isVisible} + designDocs={this.state.designDocs} + databaseName={this.state.databaseName} /> + <DeleteDBModalWrapper database={this.state.database}/> + </nav> + ); + } + }); + + var Views = { + SidebarController: SidebarController + }; + + return Views; +}); http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/9d7cd442/app/addons/documents/sidebar/stores.js ---------------------------------------------------------------------- diff --git a/app/addons/documents/sidebar/stores.js b/app/addons/documents/sidebar/stores.js new file mode 100644 index 0000000..0208257 --- /dev/null +++ b/app/addons/documents/sidebar/stores.js @@ -0,0 +1,153 @@ +// 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([ + 'app', + 'api', + 'addons/documents/sidebar/actiontypes' +], + +function (app, FauxtonAPI, ActionTypes) { + var Stores = {}; + + Stores.SidebarStore = FauxtonAPI.Store.extend({ + + initialize: function () { + this._selectedTab = 'all-docs'; + this._loading = true; + this._toggledSections = {}; + }, + + newOptions: function (options) { + this._database = options.database; + this._designDocs = options.designDocs; + this._loading = false; + + if (options.selectedTab) { + this.setSelectedTab(options.selectedTab); + } + }, + + isLoading: function () { + return this._loading; + }, + + getDatabase: function () { + if (this.isLoading()) {return {};} + + return this._database; + }, + + toggleContent: function (designDoc, index) { + if (!this._toggledSections[designDoc]) { + this._toggledSections[designDoc] = { + visible: true, + indexes: {} + }; + return; + } + + if (index) { + return this.toggleIndex(designDoc, index); + } + + this._toggledSections[designDoc].visible = !this._toggledSections[designDoc].visible; + }, + + toggleIndex: function (designDoc, indexName) { + var index = this._toggledSections[designDoc].indexes[indexName]; + + if (_.isUndefined(index)) { + this._toggledSections[designDoc].indexes[indexName] = true; + return; + } + + this._toggledSections[designDoc].indexes[indexName] = !index; + }, + + isVisible: function (designDoc, index) { + if (!this._toggledSections[designDoc]) { + return false; + } + + if (index) { + return this._toggledSections[designDoc].indexes[index]; + } + + return this._toggledSections[designDoc].visible; + }, + + setSelectedTab: function (tab) { + this._selectedTab = tab; + }, + + getDatabaseName: function () { + if (this.isLoading()) { return '';} + + return this._database.safeID(); + }, + + getDesignDocs: function () { + if (this.isLoading()) { return {};} + var docs = this._designDocs.toJSON(); + + docs = _.filter(docs, function (doc) { + if (_.has(doc.doc, 'language')) { + return doc.doc.language !== 'query'; + } + return true; + }); + + return docs.map(function (doc) { + doc.safeId = app.utils.safeURLName(doc._id.replace(/^_design\//, "")); + + return _.extend(doc, doc.doc); + }); + }, + + getSelectedTab: function () { + return this._selectedTab; + }, + + dispatch: function (action) { + switch (action.type) { + case ActionTypes.SIDEBAR_SET_SELECTED_TAB: + this.setSelectedTab(action.tab); + this.triggerChange(); + break; + case ActionTypes.SIDEBAR_NEW_OPTIONS: + this.newOptions(action.options); + this.triggerChange(); + break; + case ActionTypes.SIDEBAR_TOGGLE_CONTENT: + this.toggleContent(action.designDoc, action.index); + this.triggerChange(); + break; + case ActionTypes.SIDEBAR_FETCHING: + this._loading = true; + this.triggerChange(); + break; + default: + return; + // do nothing + } + } + + }); + + Stores.sidebarStore = new Stores.SidebarStore(); + + Stores.sidebarStore.dispatchToken = FauxtonAPI.dispatcher.register(Stores.sidebarStore.dispatch); + + return Stores; + +}); http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/9d7cd442/app/addons/documents/sidebar/tests/sidebar.storesSpec.js ---------------------------------------------------------------------- diff --git a/app/addons/documents/sidebar/tests/sidebar.storesSpec.js b/app/addons/documents/sidebar/tests/sidebar.storesSpec.js new file mode 100644 index 0000000..dbcbee2 --- /dev/null +++ b/app/addons/documents/sidebar/tests/sidebar.storesSpec.js @@ -0,0 +1,79 @@ +// 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/documents/sidebar/stores', + 'addons/documents/sidebar/actiontypes', + 'testUtils' +], function (FauxtonAPI, Stores, ActionTypes, testUtils) { + var assert = testUtils.assert; + var dispatchToken; + var store; + var opts; + + describe('Sidebar Store', function () { + beforeEach(function () { + store = new Stores.SidebarStore(); + dispatchToken = FauxtonAPI.dispatcher.register(store.dispatch); + }); + + afterEach(function () { + FauxtonAPI.dispatcher.unregister(dispatchToken); + }); + + describe('toggle state', function () { + + it('should not be visible if never toggled', function () { + assert.notOk(store.isVisible('designDoc')); + }); + + it('should be visible after being toggled', function () { + var designDoc = 'designDoc'; + store.toggleContent(designDoc); + assert.ok(store.isVisible(designDoc)); + }); + + it('should not be visible after being toggled twice', function () { + var designDoc = 'designDoc'; + store.toggleContent(designDoc); + store.toggleContent(designDoc); + assert.notOk(store.isVisible(designDoc)); + }); + + }); + + describe('toggle state for index', function () { + var designDoc = 'design-doc'; + + beforeEach(function () { + store.toggleContent(designDoc); + }); + + it('should be hidden if never toggled', function () { + assert.notOk(store.isVisible(designDoc, 'index')); + }); + + it('should be if toggled', function () { + store.toggleContent(designDoc, 'index'); + assert.ok(store.isVisible(designDoc, 'index')); + }); + + it('should be hidden after being toggled twice', function () { + store.toggleContent(designDoc, 'index'); + store.toggleContent(designDoc, 'index'); + assert.notOk(store.isVisible(designDoc, 'index')); + }); + + }); + }); +}); http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/9d7cd442/app/addons/documents/templates/design_doc_menu.html ---------------------------------------------------------------------- diff --git a/app/addons/documents/templates/design_doc_menu.html b/app/addons/documents/templates/design_doc_menu.html deleted file mode 100644 index 4a0b6a9..0000000 --- a/app/addons/documents/templates/design_doc_menu.html +++ /dev/null @@ -1,32 +0,0 @@ -<%/* -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. -*/%> -<li class="nav-header"> - -<div class="js-collapse-toggle accordion-header" id="nav-header-<%- escapedId %>" > - <div class="accordion-list-item"> - <div class="fonticon-play"></div> - <p class="design-doc-name"><span title="_design/<%- designDoc%>">_design/<%- designDoc%></span></p> - </div> - <div class="new-button add-dropdown"></div> -</div> -<ul class="accordion-body collapse <%- escapedId %>" id="<%- escapedId %>"> - <li> - <a id="<%- escapedId %>_metadata" href="#/<%- designDocMetaUrl %>" class="toggle-view accordion-header"> - <span class="fonticon-sidenav-info fonticon"></span> - Design Doc Metadata - </a> - </li> - -</ul> -</li> http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/9d7cd442/app/addons/documents/templates/index_menu_item.html ---------------------------------------------------------------------- diff --git a/app/addons/documents/templates/index_menu_item.html b/app/addons/documents/templates/index_menu_item.html deleted file mode 100644 index da055b8..0000000 --- a/app/addons/documents/templates/index_menu_item.html +++ /dev/null @@ -1,31 +0,0 @@ -<%/* -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. -*/%> -<a class="js-toggle-<%-ddocType%> accordion-header js-collapse-toggle" data-toggle="collapse" data-target="#<%- removeSpecialCharacters(ddoc) + ddocType %>" id="nav-design-function-<%= removeSpecialCharacters(ddoc) + ddocType %>"> - <div class="fonticon-play"></div> - <span class="<%- icon %> fonticon"></span> - <%- name %> - </a> - <ul class="accordion-body collapse" id="<%- removeSpecialCharacters(ddoc) + ddocType %>"> - <% _.each(collection, function (item, index) { %> - <li> - <a - data-ddoctype="<%- ddocType %>" - id="<%- removeSpecialCharacters(ddoc) %>_<%- removeSpecialCharacters(index) %>" - href="#/<%- href%><%- index%>" - class="toggle-view"> - <%- index %> - </a> - </li> - <% }); %> -</ul> http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/9d7cd442/app/addons/documents/templates/sidebar.html ---------------------------------------------------------------------- diff --git a/app/addons/documents/templates/sidebar.html b/app/addons/documents/templates/sidebar.html deleted file mode 100644 index 6d6a388..0000000 --- a/app/addons/documents/templates/sidebar.html +++ /dev/null @@ -1,50 +0,0 @@ -<%/* -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. -*/%> - -<ul class="nav nav-list"> - <li><a id="permissions" href="<%- permissionsUrl %>">Permissions</a><li> - <li><a id="changes" href="<%- changesUrl %>">Changes</a><li> - <% _.each(docLinks, function (link) { %> - <li><a id="docLink_<%-link.url%>" href="<%- base + link.url %>"><%- link.title %></a></li> - <% }); %> - <li class="active"> - <a - id="all-docs" - href="#/<%- databaseUrl %>" - class="toggle-view"> - All Documents - </a> - <div id="new-all-docs-button" class="add-dropdown"> </div> - </li> - <li> - <a - id="mango-query" - href='#/<%- mangoQueryUrl %>' - class="toggle-view"> - <%- runQueryWithMangoText %> - </a> - <div id="mango-query-button" class="add-dropdown"> </div> - </li> - <li> - <a - id="design-docs" - href='#/<%- databaseUrl %>?startkey="_design"&endkey="_design0"' - class="toggle-view"> - All Design Docs - </a> - <div id="new-design-docs-button" class="add-dropdown"> </div> - </li> -</ul> - -<div id="delete-db-modal"> </div> http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/9d7cd442/app/addons/documents/tests/nightwatch/switchDatabaseViaLookaheadTray.js ---------------------------------------------------------------------- diff --git a/app/addons/documents/tests/nightwatch/switchDatabaseViaLookaheadTray.js b/app/addons/documents/tests/nightwatch/switchDatabaseViaLookaheadTray.js index da297cf..5aa49fe 100644 --- a/app/addons/documents/tests/nightwatch/switchDatabaseViaLookaheadTray.js +++ b/app/addons/documents/tests/nightwatch/switchDatabaseViaLookaheadTray.js @@ -27,10 +27,11 @@ module.exports = { .url(baseUrl + '/#/database/' + newDatabaseName + '/_all_docs') .clickWhenVisible('#breadcrumbs .lookahead-tray-link') .setValue('#breadcrumbs .search-autocomplete', [secondDatabaseName, client.Keys.ENTER]) + .waitForElementVisible('#breadcrumbs .lookahead-tray-link', waitTime, false) .getText('body', function (result) { // check the breadcrumb title is now the second database name. That indicates a successful redirect - client.assert.containsText("#breadcrumbs .lookahead-tray-link", secondDatabaseName); + client.assert.containsText('#breadcrumbs .lookahead-tray-link', secondDatabaseName); }) .deleteDatabase(secondDatabaseName) http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/9d7cd442/app/addons/documents/tests/nightwatch/viewCreate.js ---------------------------------------------------------------------- diff --git a/app/addons/documents/tests/nightwatch/viewCreate.js b/app/addons/documents/tests/nightwatch/viewCreate.js index 2433e7c..bc6094e 100644 --- a/app/addons/documents/tests/nightwatch/viewCreate.js +++ b/app/addons/documents/tests/nightwatch/viewCreate.js @@ -93,7 +93,12 @@ module.exports = { var newDatabaseName = client.globals.testDatabaseName; /*jshint multistr: true */ - openDifferentDropdownsAndClick(client, '#nav-header-testdesigndoc') + client + .loginToGUI() + .populateDatabase(newDatabaseName) + .url(baseUrl + '/#/database/' + newDatabaseName + '/_all_docs') + .clickWhenVisible('#sidebar-tab-testdesigndoc a.dropdown-toggle.icon.fonticon-plus-circled', waitTime, false) + .clickWhenVisible('#sidebar-tab-testdesigndoc a[href*="new_view"]', waitTime, false) .waitForElementVisible('#index-name', waitTime, false) .clearValue('#index-name') .setValue('#index-name', 'test-new-view') @@ -111,8 +116,8 @@ module.exports = { //go back to all docs .url(baseUrl + '/#/database/' + newDatabaseName + '/_all_docs') .clickWhenVisible('#nav-header-testdesigndoc', waitTime, false) - .clickWhenVisible('[data-target="#testdesigndocviews"]', waitTime, false) - .clickWhenVisible('#testdesigndoc_testnewview', waitTime, false) + .clickWhenVisible('#nav-design-function-testdesigndocviews', waitTime, false) + .clickWhenVisible('#testdesigndoc_test-new-view', waitTime, false) .waitForElementPresent('.prettyprint', waitTime, false) .waitForElementNotPresent('.loading-lines', waitTime, false) .assert.containsText('.prettyprint', 'enteente') http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/9d7cd442/app/addons/documents/views.js ---------------------------------------------------------------------- diff --git a/app/addons/documents/views.js b/app/addons/documents/views.js index d0cdb5b..13aaeca 100644 --- a/app/addons/documents/views.js +++ b/app/addons/documents/views.js @@ -18,7 +18,6 @@ define([ "addons/databases/resources", // Views - "addons/documents/shared-views", "addons/documents/views-queryoptions", //plugins @@ -26,7 +25,9 @@ define([ ], function (app, FauxtonAPI, Components, Documents, - Databases, Views, QueryOptions) { + Databases, QueryOptions) { + + var Views = {}; function showError (msg) { FauxtonAPI.addNotification({ http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/9d7cd442/assets/less/fauxton.less ---------------------------------------------------------------------- diff --git a/assets/less/fauxton.less b/assets/less/fauxton.less index 4121f16..a51b783 100644 --- a/assets/less/fauxton.less +++ b/assets/less/fauxton.less @@ -231,8 +231,7 @@ table.databases { .divider { border: none; } - > li > a:hover, - > li > a:focus{ + > li > a:hover{ background-color: @linkColorHover; color: #fff; } http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/9d7cd442/assets/less/templates.less ---------------------------------------------------------------------- diff --git a/assets/less/templates.less b/assets/less/templates.less index 98f295f..7b3e887 100644 --- a/assets/less/templates.less +++ b/assets/less/templates.less @@ -320,7 +320,7 @@ with_tabs_sidebar.html display: block; } margin-top: 6px; - + .nav-list:last-child { margin-bottom: 30px; } @@ -453,8 +453,7 @@ with_tabs_sidebar.html .divider { border: none; } - > li > a:hover, - > li > a:focus { + > li > a:hover{ background-color: @linkColorHover; color: #fff; }
