From a1e83bcb05f9cafe2fb88acdea486d07076d2f69 Mon Sep 17 00:00:00 2001 From: Garren Smith Date: Thu, 28 Aug 2014 11:17:47 +0200 Subject: [PATCH 1/4] New Documents header This is the start of the new documents header. Initial work by and Jenn Schiffer . --- app/addons/documents/routes-doc-editor.js | 128 +++++ app/addons/documents/routes-documents.js | 495 ++++++++++++++++ app/addons/documents/routes.js | 542 +----------------- .../documents/templates/header_alldocs.html | 31 + app/addons/documents/tests/routeSpec.js | 8 - app/addons/documents/views-doceditor.js | 106 ++-- app/addons/documents/views.js | 114 ++++ app/addons/fauxton/components.js | 61 +- app/addons/fauxton/templates/header_left.html | 17 + .../fauxton/templates/menu_dropdown.html | 8 +- app/core/api.js | 2 + app/templates/layouts/with_tabs_sidebar.html | 15 +- assets/less/fauxton.less | 2 +- 13 files changed, 919 insertions(+), 610 deletions(-) create mode 100644 app/addons/documents/routes-doc-editor.js create mode 100644 app/addons/documents/routes-documents.js create mode 100644 app/addons/documents/templates/header_alldocs.html create mode 100644 app/addons/fauxton/templates/header_left.html diff --git a/app/addons/documents/routes-doc-editor.js b/app/addons/documents/routes-doc-editor.js new file mode 100644 index 000000000..57f61c4ce --- /dev/null +++ b/app/addons/documents/routes-doc-editor.js @@ -0,0 +1,128 @@ +// 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", + + // Modules + //views + "addons/documents/views", + "addons/documents/views-doceditor", + "addons/databases/base", +], + +function(app, FauxtonAPI, Documents, DocEditor, Databases) { + + var DocEditorRouteObject = FauxtonAPI.RouteObject.extend({ + layout: "one_pane", + disableLoader: true, + selectedHeader: "Databases", + initialize: function(route, masterLayout, options) { + var databaseName = options[0]; + this.docID = options[1]||'new'; + + this.database = this.database || new Databases.Model({id: databaseName}); + this.doc = new Documents.Doc({ + _id: this.docID + }, { + database: this.database + }); + }, + + routes: { + "database/:database/:doc/code_editor": "code_editor", + "database/:database/:doc": "code_editor" + }, + + events: { + "route:reRenderDoc": "reRenderDoc", + "route:duplicateDoc": "duplicateDoc" + }, + + crumbs: function() { + return [ + {"name": this.database.id, "link": Databases.databaseUrl(this.database)} + //{"name": this.docID, "link": "#"} + ]; + }, + + code_editor: function (database, doc) { + this.docView = this.setView("#dashboard-content", new DocEditor.CodeEditor({ + model: this.doc, + database: this.database + })); + }, + + reRenderDoc: function () { + this.docView.forceRender(); + }, + + duplicateDoc: function (newId) { + var doc = this.doc, + docView = this.docView, + database = this.database; + this.docID = newId; + + doc.copy(newId).then(function () { + doc.set({_id: newId}); + docView.forceRender(); + FauxtonAPI.navigate('/database/' + database.safeID() + '/' + app.utils.safeURLName(newId), {trigger: true}); + FauxtonAPI.addNotification({ + msg: "Document has been duplicated." + }); + + }, function (error) { + var errorMsg = "Could not duplicate document, reason: " + error.responseText + "."; + FauxtonAPI.addNotification({ + msg: errorMsg, + type: "error" + }); + }); + }, + + apiUrl: function() { + return [this.doc.url("apiurl"), this.doc.documentation()]; + } + }); + + var NewDocEditorRouteObject = DocEditorRouteObject.extend({ + initialize: function (route, masterLayout, options) { + var databaseName = options[0]; + + this.database = this.database || new Databases.Model({id: databaseName}); + this.doc = new Documents.NewDoc(null,{ + database: this.database + }); + + }, + crumbs: function() { + return [ + {"name": this.database.id, "link": Databases.databaseUrl(this.database)}, + {"name": "New", "link": "#"} + ]; + }, + routes: { + "database/:database/new": "code_editor" + }, + selectedHeader: "Databases", + + }); + + + return { + NewDocEditorRouteObject: NewDocEditorRouteObject, + DocEditorRouteObject: DocEditorRouteObject + }; +}); + diff --git a/app/addons/documents/routes-documents.js b/app/addons/documents/routes-documents.js new file mode 100644 index 000000000..8571256d1 --- /dev/null +++ b/app/addons/documents/routes-documents.js @@ -0,0 +1,495 @@ +// 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", + + // Modules + //views + "addons/documents/views", + "addons/documents/views-changes", + "addons/documents/views-index", + "addons/documents/views-doceditor", + + "addons/databases/base", + "addons/documents/resources", + "addons/fauxton/components" +], + +function(app, FauxtonAPI, Documents, Changes, Index, DocEditor, Databases, Resources, Components) { + + var crumbs = { + allDocs: function (database) { + return [ + {"name": "", "className": "fonticon-left-open", "link": "/_all_dbs"}, + {"name": database.id, "link": Databases.databaseUrl(database)} + ]; + }, + + changes: function (database) { + return [ + {"name": "", "className": "fonticon-left-open", "link": "/_all_dbs"}, + {"name": database.id, "link": Databases.databaseUrl(database)}, + {"name": "_changes", "link": "/_changes"} + ]; + } + + }; + + var DocumentsRouteObject = FauxtonAPI.RouteObject.extend({ + layout: "with_tabs_sidebar", + selectedHeader: "Databases", + routes: { + + "database/:database/_all_docs(:extra)": { + route: "allDocs", + roles: ["_reader","_writer","_admin"] + }, + "database/:database/_design/:ddoc/_views/:view": { + route: "viewFn", + roles: ['_admin'] + }, + "database/:database/_design/:ddoc/_lists/:fn": { + route: "tempFn", + roles: ['_admin'] + }, + "database/:database/_design/:ddoc/_filters/:fn": { + route: "tempFn", + roles: ['_admin'] + }, + "database/:database/_design/:ddoc/_show/:fn": { + route: "tempFn", + roles: ['_admin'] + }, + "database/:database/_design/:ddoc/metadata": { + route: "designDocMetadata", + roles: ['_admin'] + }, + "database/:database/new_view": "newViewEditor", + "database/:database/new_view/:designDoc": "newViewEditor", + "database/:database/_changes(:params)": "changes" + }, + + events: { + "route:updateAllDocs": "updateAllDocsFromView", + "route:reloadDesignDocs": "reloadDesignDocs", + "route:paginate": "paginate", + "route:perPageChange": "perPageChange", + "route:changesFilterAdd": "addFilter", + "route:changesFilterRemove": "removeFilter" + }, + + initialize: function (route, masterLayout, options) { + this.databaseName = options[0]; + + this.database = new Databases.Model({id:this.databaseName}); + + this.designDocs = new Documents.AllDocs(null, { + database: this.database, + paging: { + pageSize: 500 + }, + params: { + startkey: '_design/', + endkey: '_design0', + include_docs: true, + limit: 500 + } + }); + + this.rightHeader = this.setView("#api-navbar", new Documents.Views.RightAllDocsHeader({ + database: this.database + })); + + this.leftheader = this.setView("#breadcrumbs", new Components.LeftHeader({ + crumbs: crumbs.allDocs(this.database), + dropdownMenu: this.setUpDropdown() + })); + + this.sidebar = this.setView("#sidebar-content", new Documents.Views.Sidebar({ + collection: this.designDocs, + database: this.database + })); + + }, + + setUpDropdown: function(){ + var defaultMenuLinks = [{ + links: [{ + title: 'Replicate Database', + icon: 'fonticon-replicate', + url: '#/replication/'+this.databaseName + },{ + title: 'Delete', + icon: 'fonticon-trash', + trigger: 'database:delete' + }] + }]; + + defaultMenuLinks.push({ + title: 'Add new', + links: this.getExtensionLinks() + }); + + return defaultMenuLinks; + }, + + getExtensionLinks: function () { + var database = this.database, + newurlPrefix = "#" + database.url('app'); + + var menuLinks = [{ + title: 'New Doc', + url: newurlPrefix + '/new', + icon: 'fonticon-plus-circled' + },{ + title: 'New View', + url: newurlPrefix + '/new_view', + icon: 'fonticon-plus-circled' + }]; + + return _.reduce(FauxtonAPI.getExtensions('sidebar:links'), function (menuLinks, link) { + + menuLinks.push({ + title: link.title, + url: newurlPrefix + "/" + link.url, + icon: 'fonticon-plus-circled' + }); + + return menuLinks; + }, menuLinks); + + }, + + designDocMetadata: function(database, ddoc){ + this.toolsView && this.toolsView.remove(); + this.viewEditor && this.viewEditor.remove(); + + var designDocInfo = new Resources.DdocInfo({_id: "_design/"+ddoc},{database: this.database }); + + this.setView("#dashboard-lower-content", new Documents.Views.DdocInfo({ + ddocName: ddoc, + model: designDocInfo + })); + + this.sidebar.setSelectedTab(app.utils.removeSpecialCharacters(ddoc)+"_metadata"); + + this.crumbs = function () { + return [ + {"name": this.database.id, "link": Databases.databaseUrl(this.database)}, + ]; + }; + + this.apiUrl = [designDocInfo.url('apiurl'), designDocInfo.documentation() ]; + + }, + tempFn: function(databaseName, ddoc, fn){ + this.setView("#dashboard-upper-content", new Documents.Views.temp({})); + this.crumbs = function () { + return [ + {"name": this.database.id, "link": Databases.databaseUrl(this.database)}, + ]; + }; + + }, + + establish: function () { + return this.designDocs.fetch({reset: true}); + }, + + createParams: function (options) { + var urlParams = app.getParams(options); + var params = Documents.QueryParams.parse(urlParams); + + return { + urlParams: urlParams, + docParams: _.extend(params, {limit: this.getDocPerPageLimit(params, 20)}) + }; + }, + + /* + * docParams are the options collection uses to fetch from the server + * urlParams are what are shown in the url and to the user + * They are not the same when paginating + */ + allDocs: function(databaseName, options) { + var params = this.createParams(options), + urlParams = params.urlParams, + docParams = params.docParams; + + if (this.eventAllDocs) { + this.eventAllDocs = false; + return; + } + + this.leftheader.updateCrumbs(crumbs.allDocs(this.database)); + this.database.buildAllDocs(docParams); + + if (docParams.startkey && docParams.startkey.indexOf('_design') > -1) { + this.sidebar.setSelectedTab('design-docs'); + } else { + this.sidebar.setSelectedTab('all-docs'); + } + + this.viewEditor && this.viewEditor.remove(); + + this.database.allDocs.paging.pageSize = this.getDocPerPageLimit(urlParams, parseInt(docParams.limit, 10)); + + this.viewEditor = this.setView("#dashboard-upper-content", new Documents.Views.AllDocsLayout({ + database: this.database, + collection: this.database.allDocs, + params: urlParams, + docParams: docParams + })); + + this.documentsView = this.setView("#dashboard-lower-content", new Documents.Views.AllDocsList({ + database: this.database, + collection: this.database.allDocs, + docParams: docParams, + params: urlParams, + bulkDeleteDocsCollection: new Documents.BulkDeleteDocCollection([], {databaseId: this.database.get('id')}) + })); + + this.rightHeader.updateApiUrl([this.database.allDocs.urlRef("apiurl", urlParams), this.database.allDocs.documentation()]); + }, + + viewFn: function (databaseName, ddoc, view) { + var params = this.createParams(), + urlParams = params.urlParams, + docParams = params.docParams, + decodeDdoc = decodeURIComponent(ddoc); + + view = view.replace(/\?.*$/,''); + + this.indexedDocs = new Documents.IndexCollection(null, { + database: this.database, + design: decodeDdoc, + view: view, + params: docParams, + paging: { + pageSize: this.getDocPerPageLimit(urlParams, parseInt(docParams.limit, 10)) + } + }); + + this.viewEditor = this.setView("#dashboard-upper-content", new Index.ViewEditor({ + model: this.database, + ddocs: this.designDocs, + viewName: view, + params: urlParams, + newView: false, + database: this.database, + ddocInfo: this.ddocInfo(decodeDdoc, this.designDocs, view) + })); + + this.toolsView && this.toolsView.remove(); + + this.documentsView = this.createViewDocumentsView({ + designDoc: decodeDdoc, + docParams: docParams, + urlParams: urlParams, + database: this.database, + indexedDocs: this.indexedDocs, + designDocs: this.designDocs, + view: view + }); + + this.sidebar.setSelectedTab(app.utils.removeSpecialCharacters(ddoc) + '_' + app.utils.removeSpecialCharacters(view)); + + this.rightHeader.updateApiUrl([this.indexedDocs.urlRef("apiurl", urlParams), "docs"]); + }, + + ddocInfo: function (designDoc, designDocs, view) { + return { + id: "_design/" + designDoc, + currView: view, + designDocs: designDocs + }; + }, + + createViewDocumentsView: function (options) { + + return this.setView("#dashboard-lower-content", new Documents.Views.AllDocsList({ + database: options.database, + collection: options.indexedDocs, + nestedView: Documents.Views.Row, + viewList: true, + ddocInfo: this.ddocInfo(options.designDoc, options.designDocs, options.view), + docParams: options.docParams, + params: options.urlParams + })); + }, + + newViewEditor: function (database, designDoc) { + var params = app.getParams(); + + this.toolsView && this.toolsView.remove(); + this.documentsView && this.documentsView.remove(); + + this.viewEditor = this.setView("#dashboard-upper-content", new Index.ViewEditor({ + currentddoc: "_design/"+designDoc || "", + ddocs: this.designDocs, + params: params, + database: this.database, + newView: true + })); + + this.sidebar.setSelectedTab('new-view'); + this.crumbs = function () { + return [ + {"name": this.database.id, "link": Databases.databaseUrl(this.database)}, + ]; + }; + }, + + updateAllDocsFromView: function (event) { + var view = event.view, + params = this.createParams(), + urlParams = params.urlParams, + docParams = params.docParams, + ddoc = event.ddoc, + pageSize, + collection; + + var defaultPageSize = _.isUndefined(this.documentsView) ? 20 : this.documentsView.perPage(); + docParams.limit = pageSize = this.getDocPerPageLimit(urlParams, defaultPageSize); + + if (event.allDocs) { + this.eventAllDocs = true; // this is horrible. But I cannot get the trigger not to fire the route! + this.database.buildAllDocs(docParams); + collection = this.database.allDocs; + collection.paging.pageSize = pageSize; + + } else { + collection = this.indexedDocs = new Documents.IndexCollection(null, { + database: this.database, + design: ddoc, + view: view, + params: docParams, + paging: { + pageSize: pageSize + } + }); + + if (!this.documentsView) { + this.documentsView = this.createViewDocumentsView({ + designDoc: ddoc, + docParams: docParams, + urlParams: urlParams, + database: this.database, + indexedDocs: this.indexedDocs, + designDocs: this.designDocs, + view: view + }); + } + } + + this.documentsView.setCollection(collection); + this.documentsView.setParams(docParams, urlParams); + this.documentsView.forceRender(); + + this.apiUrl = [collection.urlRef("apiurl", urlParams), "docs"]; + }, + + perPageChange: function (perPage) { + // We need to restore the collection parameters to the defaults (1st page) + // and update the page size + this.perPage = perPage; + this.documentsView.forceRender(); + this.documentsView.collection.pageSizeReset(perPage, {fetch: false}); + this.setDocPerPageLimit(perPage); + }, + + paginate: function (options) { + var collection = this.documentsView.collection; + + this.documentsView.forceRender(); + collection.paging.pageSize = options.perPage; + var promise = collection[options.direction]({fetch: false}); + }, + + reloadDesignDocs: function (event) { + this.sidebar.forceRender(); + + if (event && event.selectedTab) { + this.sidebar.setSelectedTab(event.selectedTab); + } + }, + + setDocPerPageLimit: function (perPage) { + window.localStorage.setItem('fauxton:perpage', perPage); + }, + + + getDocPerPageLimit: function (urlParams, perPage) { + var storedPerPage = perPage; + + if (window.localStorage) { + storedPerPage = window.localStorage.getItem('fauxton:perpage'); + + if (!storedPerPage) { + this.setDocPerPageLimit(perPage); + storedPerPage = perPage; + } else { + storedPerPage = parseInt(storedPerPage, 10); + } + } + + if (!urlParams.limit || urlParams.limit > storedPerPage) { + return parseInt(storedPerPage, 10); + } else { + return parseInt(urlParams.limit, 10); + } + }, + + changes: function () { + var docParams = app.getParams(); + this.database.buildChanges(docParams); + + this.changesView = this.setView("#dashboard-lower-content", new Changes.Changes({ + model: this.database + })); + + this.filterView = new Components.FilterView({ + eventNamespace: "changes" + }); + + this.headerView = this.setView("#dashboard-upper-content", new Changes.ChangesHeader({ + filterView: this.filterView + })); + + this.toolsView && this.toolsView.remove(); + this.viewEditor && this.viewEditor.remove(); + + this.sidebar.setSelectedTab('changes'); + + this.leftheader.updateCrumbs(crumbs.changes(this.database)); + this.leftheader.forceRender(); + this.rightHeader.updateApiUrl([this.database.url("changes-apiurl"), this.database.documentation()]); + }, + + addFilter: function (filter) { + this.changesView.filters.push(filter); + this.changesView.render(); + }, + + removeFilter: function (filter) { + this.changesView.filters.splice(this.changesView.filters.indexOf(filter), 1); + this.changesView.render(); + }, + + }); + + return DocumentsRouteObject; +}); + diff --git a/app/addons/documents/routes.js b/app/addons/documents/routes.js index c17611675..02106c849 100644 --- a/app/addons/documents/routes.js +++ b/app/addons/documents/routes.js @@ -11,544 +11,18 @@ // the License. define([ - "app", - - "api", - - // Modules - //views "addons/documents/views", - "addons/documents/views-changes", - "addons/documents/views-index", - "addons/documents/views-doceditor", - - "addons/databases/base", - "addons/documents/resources", - "addons/fauxton/components" + "addons/documents/routes-documents", + "addons/documents/routes-doc-editor", ], -function(app, FauxtonAPI, Documents, Changes, Index, DocEditor, Databases, Resources, Components) { - - var DocEditorRouteObject = FauxtonAPI.RouteObject.extend({ - layout: "one_pane", - disableLoader: true, - selectedHeader: "Databases", - initialize: function(route, masterLayout, options) { - var databaseName = options[0]; - this.docID = options[1]||'new'; - - this.database = this.database || new Databases.Model({id: databaseName}); - this.doc = new Documents.Doc({ - _id: this.docID - }, { - database: this.database - }); - }, - - routes: { - "database/:database/:doc/code_editor": "code_editor", - "database/:database/:doc": "code_editor" - }, - - events: { - "route:reRenderDoc": "reRenderDoc", - "route:duplicateDoc": "duplicateDoc" - }, - - crumbs: function() { - return [ - {"name": this.database.id, "link": Databases.databaseUrl(this.database)}, - {"name": this.docID, "link": "#"} - ]; - }, - - code_editor: function (database, doc) { - - this.docView = this.setView("#dashboard-content", new DocEditor.CodeEditor({ - model: this.doc, - database: this.database - })); - }, - - reRenderDoc: function () { - this.docView.forceRender(); - }, - - duplicateDoc: function (newId) { - var doc = this.doc, - docView = this.docView, - database = this.database; - this.docID = newId; - - doc.copy(newId).then(function () { - doc.set({_id: newId}); - docView.forceRender(); - FauxtonAPI.navigate('/database/' + database.safeID() + '/' + app.utils.safeURLName(newId), {trigger: true}); - FauxtonAPI.addNotification({ - msg: "Document has been duplicated." - }); - - }, function (error) { - var errorMsg = "Could not duplicate document, reason: " + error.responseText + "."; - FauxtonAPI.addNotification({ - msg: errorMsg, - type: "error" - }); - }); - }, - - apiUrl: function() { - return [this.doc.url("apiurl"), this.doc.documentation()]; - } - }); - - var NewDocEditorRouteObject = DocEditorRouteObject.extend({ - initialize: function (route, masterLayout, options) { - var databaseName = options[0]; - - this.database = this.database || new Databases.Model({id: databaseName}); - this.doc = new Documents.NewDoc(null,{ - database: this.database - }); - - }, - crumbs: function() { - return [ - {"name": this.database.id, "link": Databases.databaseUrl(this.database)}, - {"name": "New", "link": "#"} - ]; - }, - routes: { - "database/:database/new": "code_editor" - }, - selectedHeader: "Databases", - - }); - - var DocumentsRouteObject = FauxtonAPI.RouteObject.extend({ - layout: "with_tabs_sidebar", - selectedHeader: "Databases", - routes: { - - "database/:database/_all_docs(:extra)": { - route: "allDocs", - roles: ["_reader","_writer","_admin"] - }, - "database/:database/_design/:ddoc/_views/:view": { - route: "viewFn", - roles: ['_admin'] - }, - "database/:database/_design/:ddoc/_lists/:fn": { - route: "tempFn", - roles: ['_admin'] - }, - "database/:database/_design/:ddoc/_filters/:fn": { - route: "tempFn", - roles: ['_admin'] - }, - "database/:database/_design/:ddoc/_show/:fn": { - route: "tempFn", - roles: ['_admin'] - }, - "database/:database/_design/:ddoc/metadata": { - route: "designDocMetadata", - roles: ['_admin'] - }, - "database/:database/new_view": "newViewEditor", - "database/:database/new_view/:designDoc": "newViewEditor", - "database/:database/_changes(:params)": "changes" - }, - - events: { - "route:updateAllDocs": "updateAllDocsFromView", - "route:updatePreviewDocs": "updateAllDocsFromPreview", - "route:reloadDesignDocs": "reloadDesignDocs", - "route:paginate": "paginate", - "route:perPageChange": "perPageChange", - "route:changesFilterAdd": "addFilter", - "route:changesFilterRemove": "removeFilter" - }, - - initialize: function (route, masterLayout, options) { - this.databaseName = options[0]; - - this.data = { - database: new Databases.Model({id:this.databaseName}) - }; - - this.data.designDocs = new Documents.AllDocs(null, { - database: this.data.database, - paging: { - pageSize: 500 - }, - params: { - startkey: '_design/', - endkey: '_design0', - include_docs: true, - limit: 500 - } - }); - - this.sidebar = this.setView("#sidebar-content", new Documents.Views.Sidebar({ - collection: this.data.designDocs, - database: this.data.database - })); - - }, - designDocMetadata: function(database, ddoc){ - this.toolsView && this.toolsView.remove(); - this.viewEditor && this.viewEditor.remove(); - - var designDocInfo = new Resources.DdocInfo({_id: "_design/"+ddoc},{database: this.data.database }); - - this.setView("#dashboard-lower-content", new Documents.Views.DdocInfo({ - ddocName: ddoc, - model: designDocInfo - })); - - this.sidebar.setSelectedTab(app.utils.removeSpecialCharacters(ddoc)+"_metadata"); - - this.crumbs = function () { - return [ - {"name": this.data.database.id, "link": Databases.databaseUrl(this.data.database)}, - ]; - }; - - this.apiUrl = [designDocInfo.url('apiurl'), designDocInfo.documentation() ]; - - }, - tempFn: function(databaseName, ddoc, fn){ - this.setView("#dashboard-upper-content", new Documents.Views.temp({})); - this.crumbs = function () { - return [ - {"name": this.data.database.id, "link": Databases.databaseUrl(this.data.database)}, - ]; - }; - - }, - - establish: function () { - return this.data.designDocs.fetch({reset: true}); - }, - - createParams: function (options) { - var urlParams = app.getParams(options); - var params = Documents.QueryParams.parse(urlParams); - - return { - urlParams: urlParams, - docParams: _.extend(params, {limit: this.getDocPerPageLimit(params, 20)}) - }; - }, - - /* - * docParams are the options collection uses to fetch from the server - * urlParams are what are shown in the url and to the user - * They are not the same when paginating - */ - allDocs: function(databaseName, options) { - var params = this.createParams(options), - urlParams = params.urlParams, - docParams = params.docParams; - - if (this.eventAllDocs) { - this.eventAllDocs = false; - return; - } - - this.data.database.buildAllDocs(docParams); - - if (docParams.startkey && docParams.startkey.indexOf('_design') > -1) { - this.sidebar.setSelectedTab('design-docs'); - } else { - this.sidebar.setSelectedTab('all-docs'); - } - - this.viewEditor && this.viewEditor.remove(); - - this.data.database.allDocs.paging.pageSize = this.getDocPerPageLimit(urlParams, parseInt(docParams.limit, 10)); - - this.viewEditor = this.setView("#dashboard-upper-content", new Documents.Views.AllDocsLayout({ - database: this.data.database, - collection: this.data.database.allDocs, - params: urlParams, - docParams: docParams - })); - - this.documentsView = this.setView("#dashboard-lower-content", new Documents.Views.AllDocsList({ - database: this.data.database, - collection: this.data.database.allDocs, - docParams: docParams, - params: urlParams, - bulkDeleteDocsCollection: new Documents.BulkDeleteDocCollection([], {databaseId: this.data.database.get('id')}) - })); - - this.crumbs = [ - {"name": this.data.database.id, "link": Databases.databaseUrl(this.data.database)} - ]; - - this.apiUrl = [this.data.database.allDocs.urlRef("apiurl", urlParams), this.data.database.allDocs.documentation() ]; - }, - - viewFn: function (databaseName, ddoc, view) { - var params = this.createParams(), - urlParams = params.urlParams, - docParams = params.docParams, - decodeDdoc = decodeURIComponent(ddoc); - - view = view.replace(/\?.*$/,''); - - this.data.indexedDocs = new Documents.IndexCollection(null, { - database: this.data.database, - design: decodeDdoc, - view: view, - params: docParams, - paging: { - pageSize: this.getDocPerPageLimit(urlParams, parseInt(docParams.limit, 10)) - } - }); - - this.viewEditor = this.setView("#dashboard-upper-content", new Index.ViewEditor({ - model: this.data.database, - ddocs: this.data.designDocs, - viewName: view, - params: urlParams, - newView: false, - database: this.data.database, - ddocInfo: this.ddocInfo(decodeDdoc, this.data.designDocs, view) - })); - - this.toolsView && this.toolsView.remove(); - - this.documentsView = this.createViewDocumentsView({ - designDoc: decodeDdoc, - docParams: docParams, - urlParams: urlParams, - database: this.data.database, - indexedDocs: this.data.indexedDocs, - designDocs: this.data.designDocs, - view: view - }); - - this.sidebar.setSelectedTab(app.utils.removeSpecialCharacters(ddoc) + '_' + app.utils.removeSpecialCharacters(view)); - - this.crumbs = function () { - return [ - {"name": this.data.database.id, "link": Databases.databaseUrl(this.data.database)}, - ]; - }; - - this.apiUrl = [this.data.indexedDocs.urlRef("apiurl", urlParams), "docs"]; - }, - - ddocInfo: function (designDoc, designDocs, view) { - return { - id: "_design/" + designDoc, - currView: view, - designDocs: designDocs - }; - }, - - createViewDocumentsView: function (options) { - - return this.setView("#dashboard-lower-content", new Documents.Views.AllDocsList({ - database: options.database, - collection: options.indexedDocs, - nestedView: Documents.Views.Row, - viewList: true, - ddocInfo: this.ddocInfo(options.designDoc, options.designDocs, options.view), - docParams: options.docParams, - params: options.urlParams - })); - }, - - newViewEditor: function (database, designDoc) { - var params = app.getParams(); - - this.toolsView && this.toolsView.remove(); - this.documentsView && this.documentsView.remove(); - - this.viewEditor = this.setView("#dashboard-upper-content", new Index.ViewEditor({ - currentddoc: "_design/"+designDoc || "", - ddocs: this.data.designDocs, - params: params, - database: this.data.database, - newView: true - })); - - this.sidebar.setSelectedTab('new-view'); - this.crumbs = function () { - return [ - {"name": this.data.database.id, "link": Databases.databaseUrl(this.data.database)}, - ]; - }; - }, - - updateAllDocsFromView: function (event) { - var view = event.view, - params = this.createParams(), - urlParams = params.urlParams, - docParams = params.docParams, - ddoc = event.ddoc, - pageSize, - collection; - - var defaultPageSize = _.isUndefined(this.documentsView) ? 20 : this.documentsView.perPage(); - docParams.limit = pageSize = this.getDocPerPageLimit(urlParams, defaultPageSize); - - if (event.allDocs) { - this.eventAllDocs = true; // this is horrible. But I cannot get the trigger not to fire the route! - this.data.database.buildAllDocs(docParams); - collection = this.data.database.allDocs; - collection.paging.pageSize = pageSize; - - } else { - collection = this.data.indexedDocs = new Documents.IndexCollection(null, { - database: this.data.database, - design: ddoc, - view: view, - params: docParams, - paging: { - pageSize: pageSize - } - }); - - if (!this.documentsView) { - this.documentsView = this.createViewDocumentsView({ - designDoc: ddoc, - docParams: docParams, - urlParams: urlParams, - database: this.data.database, - indexedDocs: this.indexedDocs, - designDocs: this.data.designDocs, - view: view - }); - } - } - - this.documentsView.setCollection(collection); - this.documentsView.setParams(docParams, urlParams); - this.documentsView.forceRender(); - - this.apiUrl = [collection.urlRef("apiurl", urlParams), "docs"]; - }, - - updateAllDocsFromPreview: function (event) { - var view = event.view, - rows = event.rows, - ddoc = event.ddoc; - - this.data.indexedDocs = new Documents.PouchIndexCollection(null, { - database: this.data.database, - design: ddoc, - view: view, - rows: rows - }); - - this.documentsView = this.setView("#dashboard-lower-content", new Documents.Views.AllDocsList({ - database: this.data.database, - collection: this.data.indexedDocs, - nestedView: Documents.Views.Row, - viewList: true - })); - }, - - perPageChange: function (perPage) { - // We need to restore the collection parameters to the defaults (1st page) - // and update the page size - this.perPage = perPage; - this.documentsView.forceRender(); - this.documentsView.collection.pageSizeReset(perPage, {fetch: false}); - this.setDocPerPageLimit(perPage); - }, - - paginate: function (options) { - var collection = this.documentsView.collection; - - this.documentsView.forceRender(); - collection.paging.pageSize = options.perPage; - var promise = collection[options.direction]({fetch: false}); - }, - - reloadDesignDocs: function (event) { - this.sidebar.forceRender(); - - if (event && event.selectedTab) { - this.sidebar.setSelectedTab(event.selectedTab); - } - }, - - setDocPerPageLimit: function (perPage) { - window.localStorage.setItem('fauxton:perpage', perPage); - }, - - - getDocPerPageLimit: function (urlParams, perPage) { - var storedPerPage = perPage; - - if (window.localStorage) { - storedPerPage = window.localStorage.getItem('fauxton:perpage'); - - if (!storedPerPage) { - this.setDocPerPageLimit(perPage); - storedPerPage = perPage; - } else { - storedPerPage = parseInt(storedPerPage, 10); - } - } - - if (!urlParams.limit || urlParams.limit > storedPerPage) { - return parseInt(storedPerPage, 10); - } else { - return parseInt(urlParams.limit, 10); - } - }, - - changes: function () { - var docParams = app.getParams(); - this.data.database.buildChanges(docParams); - - this.changesView = this.setView("#dashboard-lower-content", new Changes.Changes({ - model: this.data.database - })); - - this.filterView = new Components.FilterView({ - eventNamespace: "changes" - }); - this.headerView = this.setView("#dashboard-upper-content", new Changes.ChangesHeader({ - filterView: this.filterView - })); - - this.toolsView && this.toolsView.remove(); - this.viewEditor && this.viewEditor.remove(); - - this.sidebar.setSelectedTab('changes'); - - this.crumbs = function () { - return [ - {"name": this.data.database.id, "link": Databases.databaseUrl(this.data.database)}, - {"name": "_changes", "link": "/_changes"} - ]; - }; - - this.apiUrl = function() { - return [this.data.database.url("changes-apiurl"), this.data.database.documentation()]; - }; - }, - - addFilter: function (filter) { - this.changesView.filters.push(filter); - this.changesView.render(); - }, - - removeFilter: function (filter) { - this.changesView.filters.splice(this.changesView.filters.indexOf(filter), 1); - this.changesView.render(); - }, - - }); +function(Documents, DocumentsRouteObject, docEditor) { - Documents.RouteObjects = [DocEditorRouteObject, NewDocEditorRouteObject, DocumentsRouteObject]; + Documents.RouteObjects = [ + docEditor.DocEditorRouteObject, + docEditor.NewDocEditorRouteObject, + DocumentsRouteObject + ]; return Documents; }); diff --git a/app/addons/documents/templates/header_alldocs.html b/app/addons/documents/templates/header_alldocs.html new file mode 100644 index 000000000..b353d89c1 --- /dev/null +++ b/app/addons/documents/templates/header_alldocs.html @@ -0,0 +1,31 @@ + + + + +
+ + + + + + + + + + diff --git a/app/addons/documents/tests/routeSpec.js b/app/addons/documents/tests/routeSpec.js index e2eaca874..2927845bd 100644 --- a/app/addons/documents/tests/routeSpec.js +++ b/app/addons/documents/tests/routeSpec.js @@ -19,14 +19,6 @@ define([ describe('Documents Route', function () { describe('changes route', function () { - - it('Should set correct changes api url', function () { - var docRoute = new DocumentRoute('changes', {}, ['fakeDB']); - docRoute.changes(); - - assert.ok(/\/database\/fakeDB\/_changes\?descending=true&limit=100&include_docs=true/.test(docRoute.apiUrl()[0])); - }); - }); }); diff --git a/app/addons/documents/views-doceditor.js b/app/addons/documents/views-doceditor.js index e05b8f424..d1cc85c3a 100644 --- a/app/addons/documents/views-doceditor.js +++ b/app/addons/documents/views-doceditor.js @@ -26,13 +26,10 @@ define([ "plugins/prettify" ], -function(app, FauxtonAPI, Components, Documents, Databases, - resizeColumns, prettify) { +function(app, FauxtonAPI, Components, Documents, Databases, resizeColumns, prettify) { var Views = {}; - /* Attachments upload modal */ - Views.UploadModal = Components.ModalView.extend({ template: "addons/documents/templates/upload_modal", @@ -141,19 +138,20 @@ function(app, FauxtonAPI, Components, Documents, Databases, editorId: "string-editor-container", mode: "plain" }); - this.subEditor.render(); + + this.subEditor.render().promise().then(function () { /* optimize by disabling auto sizing (35 is the lines fitting into the pop-up) */ - this.subEditor.configureFixedHeightEditor(35); + this.subEditor.configureFixedHeightEditor(35); + }.bind(this)); } }, cleanup: function () { - if (this.subEditor) this.subEditor.remove(); + if (this.subEditor) { this.subEditor.remove(); } } }); - /* Doc Duplication modal */ Views.DuplicateDocModal = Components.ModalView.extend({ template: "addons/documents/templates/duplicate_doc_modal", @@ -232,16 +230,15 @@ function(app, FauxtonAPI, Components, Documents, Databases, var selEnd = this.editor.getSelectionEnd().row; /* one JS(ON) string can't span more than one line - we edit one string, so ensure we don't select several lines */ if (selStart >=0 && selEnd >= 0 && selStart === selEnd && this.editor.isRowExpanded(selStart)) { - var editLine = this.editor.getLine(selStart); - var editMatch = editLine.match(/^([ \t]*)("[a-zA-Z0-9_]*": )?(".*",?[ \t]*)$/); - if (editMatch) { + var editLine = this.editor.getLine(selStart), + editMatch = editLine.match(/^([ \t]*)("[a-zA-Z0-9_]*": )?(".*",?[ \t]*)$/); + + if (editMatch) { return editMatch; - } else { - return null; - } - } else { - return null; - } + } + } + + return null; }, showHideEditDocString: function (event) { @@ -312,14 +309,10 @@ function(app, FauxtonAPI, Components, Documents, Databases, beforeRender: function () { this.uploadModal = this.setView('#upload-modal', new Views.UploadModal({model: this.model})); - this.uploadModal.render(); - this.duplicateModal = this.setView('#duplicate-modal', new Views.DuplicateDocModal({model: this.model})); /* initialization is automatic - and make sure ONCE */ this.stringEditModal = this.stringEditModal || this.setView('#string-edit-modal', new Views.StringEditModal()); - /* this.stringEditModal.render(); */ - this.duplicateModal.render(); }, upload: function (event) { @@ -473,6 +466,8 @@ function(app, FauxtonAPI, Components, Documents, Databases, editor, model; + this.listenTo(this.model, "sync", this.updateValues); + this.editor = new Components.Editor({ editorId: "editor-container", forceMissingId: true, @@ -485,46 +480,51 @@ function(app, FauxtonAPI, Components, Documents, Databases, readOnly: true // false if this command should not apply in readOnly mode }] }); + this.editor.render(); editor = this.editor; model = this.model; + //only start listening to editor once it has been rendered + this.editor.promise().then(function () { + + this.listenTo(editor.editor, "change", function (event) { + var changedDoc; + try { + changedDoc = JSON.parse(editor.getValue()); + } catch(exception) { + //not complete doc. Cannot work with it + return; + } + + var keyChecked = ["_id"]; + if (model.get("_rev")) { keyChecked.push("_rev");} + + //check the changedDoc has all the required standard keys + if (_.isEmpty(_.difference(keyChecked, _.keys(changedDoc)))) { return; } + + editor.setReadOnly(true); + setTimeout(function () { editor.setReadOnly(false);}, 400); + // use extend so that _id stays at the top of the object with displaying the doc + changedDoc = _.extend({_id: model.id, _rev: model.get("_rev")}, changedDoc); + editor.setValue(JSON.stringify(changedDoc, null, " ")); + FauxtonAPI.addNotification({ + type: "error", + msg: "Cannot remove a documents Id or Revision.", + clear: true + }); + }); - this.listenTo(this.model, "sync", this.updateValues); - this.listenTo(editor.editor, "change", function (event) { - var changedDoc; - try { - changedDoc = JSON.parse(editor.getValue()); - } catch(exception) { - //not complete doc. Cannot work with it - return; - } - - var keyChecked = ["_id"]; - if (model.get("_rev")) { keyChecked.push("_rev");} - - //check the changedDoc has all the required standard keys - if (_.isEmpty(_.difference(keyChecked, _.keys(changedDoc)))) { return; } + var showHideEditDocString = _.bind(this.showHideEditDocString, this); - editor.setReadOnly(true); - setTimeout(function () { editor.setReadOnly(false);}, 400); - // use extend so that _id stays at the top of the object with displaying the doc - changedDoc = _.extend({_id: model.id, _rev: model.get("_rev")}, changedDoc); - editor.setValue(JSON.stringify(changedDoc, null, " ")); - FauxtonAPI.addNotification({ - type: "error", - msg: "Cannot remove a documents Id or Revision.", - clear: true + this.listenTo(editor.editor, "changeSelection", function (event) { + showHideEditDocString(event); + }); + this.listenTo(editor.editor.session, "changeBackMarker", function (event) { + showHideEditDocString(event); }); - }); - var that = this; - this.listenTo(editor.editor, "changeSelection", function (event) { - that.showHideEditDocString(event); - }); - this.listenTo(editor.editor.session, "changeBackMarker", function (event) { - that.showHideEditDocString(event); - }); + }.bind(this)); }, cleanup: function () { diff --git a/app/addons/documents/views.js b/app/addons/documents/views.js index 185c975d0..c6a6bf956 100644 --- a/app/addons/documents/views.js +++ b/app/addons/documents/views.js @@ -38,6 +38,120 @@ function(app, FauxtonAPI, Components, Documents, Databases, Views, QueryOptions, }); } + Views.RightAllDocsHeader = FauxtonAPI.View.extend({ + className: "header-right", + template: "addons/documents/templates/header_alldocs", + events: { + 'click .toggle-select-menu': 'selectAllMenu' + }, + + initialize: function(options){ + //adding the database to the object + this.database = options.database; + _.bindAll(this); + this.selectVisible = false; + FauxtonAPI.Events.on('advancedOptions:updateView', this.updateAllDocs); + FauxtonAPI.Events.on('success:bulkDelete', this.selectAllMenu); + }, + + cleanup:function(){ + FauxtonAPI.Events.unbind('advancedOptions:updateView'); + FauxtonAPI.Events.unbind('success:bulkDelete'); + }, + + selectAllMenu: function(e){ + FauxtonAPI.triggerRouteEvent("toggleSelectHeader"); + FauxtonAPI.Events.trigger("documents:showSelectAll",this.selectVisible); + }, + + addAllDocsMenu: function(){ + //search docs + this.headerSearch = this.insertView("#header-search", new Views.JumpToDoc({ + database: this.database, + collection: this.database.allDocs + })); + //insert queryoptions + //that file is included in require() above and the argument is QueryOptions + // and it wants all these params: + /* Sooooo I searched this file for where Advanced options was originally inserted to see what the hell + is happening. and it's in AllDocsLayout. So I'm going to move some of those functions over here + + These are required: + this.database = options.database; + this.updateViewFn = options.updateViewFn; + this.previewFn = options.previewFn; + + these are booleans: + this.showStale = _.isUndefined(options.showStale) ? false : options.showStale; + this.hasReduce = _.isUndefined(options.hasReduce) ? true : options.hasReduce; + + these you only need for view indexes, not all docs because they are about + specific views and design docs (ddocs, also views live inside a ddoc): + this.viewName = options.viewName; + this.ddocName = options.ddocName; + */ + + /*this.queryOptions = this.insertView("#query-options", new QueryOptions.AdvancedOptions({ + database: this.database, + hasReduce: false, + showPreview: false, + }));*/ + + //Moved the apibar view into the components file so you can include it in your views + this.apiBar = this.insertView("#header-api-bar", new Components.ApiBar({})); + }, + + updateApiUrl: function(api){ + //this will update the api bar when the route changes + //you can find the method that updates it in components.js Components.ApiBar() + this.apiBar && this.apiBar.update(api); + }, + + serialize: function() { + //basically if you want something in a template, You can define it here + return { + database: this.database.get('id') + }; + }, + + beforeRender:function(){ + this.addAllDocsMenu(); + }, + + //moved from alldocs layout + updateAllDocs: function (event, paramInfo) { + event.preventDefault(); + + var errorParams = paramInfo.errorParams, + params = paramInfo.params; + + if (_.any(errorParams)) { + _.map(errorParams, function(param) { + return FauxtonAPI.addNotification({ + msg: "JSON Parse Error on field: "+param.name, + type: "error", + clear: true + }); + }); + FauxtonAPI.addNotification({ + msg: "Make sure that strings are properly quoted and any other values are valid JSON structures", + type: "warning", + clear: true + }); + + return false; + } + + var fragment = window.location.hash.replace(/\?.*$/, ''); + + if (!_.isEmpty(params)) { + fragment = fragment + '?' + $.param(params); + } + + FauxtonAPI.navigate(fragment, {trigger: false}); + FauxtonAPI.triggerRouteEvent('updateAllDocs', {allDocs: true}); + } + }); Views.DeleteDBModal = Components.ModalView.extend({ template: "addons/documents/templates/delete_database_modal", diff --git a/app/addons/fauxton/components.js b/app/addons/fauxton/components.js index a58de198c..20873943b 100644 --- a/app/addons/fauxton/components.js +++ b/app/addons/fauxton/components.js @@ -35,6 +35,43 @@ define([ function(app, FauxtonAPI, ace, spin, ZeroClipboard) { var Components = FauxtonAPI.addon(); + //setting up the left header with the backbutton used in Views and All docs + Components.LeftHeader = FauxtonAPI.View.extend({ + className: "header-left", + template: "addons/fauxton/templates/header_left", + initialize:function(options){ + this.dropdownEvents = options.dropdownEvents; + this.dropdownMenuLinks = options.dropdownMenu; + this.crumbs = options.crumbs || []; + }, + updateCrumbs: function(crumbs){ + this.crumbs = crumbs; + this.breadcrumbs && this.breadcrumbs.update(crumbs); + }, + updateDropdown: function(menuLinks){ + this.dropdownMenuLinks = menuLinks; + this.dropdown && this.dropdown.update(menuLinks); + }, + beforeRender: function(){ + this.setUpCrumbs(); + this.setUpDropDownMenu(); + }, + setUpCrumbs: function(){ + this.breadcrumbs = this.insertView("#header-breadcrumbs", new Components.Breadcrumbs({ + crumbs: this.crumbs + })); + }, + setUpDropDownMenu: function(){ + if (this.dropdownMenuLinks){ + this.dropdown = this.insertView("#header-dropdown-menu", new Components.MenuDropDown({ + icon: 'fonticon-cog', + links: this.dropdownMenuLinks, + events: this.dropdownEvents + })); + } + } + }); + Components.Breadcrumbs = FauxtonAPI.View.extend({ className: "breadcrumb pull-left", tagName: "ul", @@ -742,11 +779,31 @@ function(app, FauxtonAPI, ace, spin, ZeroClipboard) { className: "dropdown", initialize: function(options){ this.links = options.links; + this.icon = options.icon || "fonticon-plus-circled"; + this.setUpEvents(); + }, + setUpEvents: function(){ + this.events = {}; + _.each(this.links, function (parentLink) { + _.each(parentLink.links, function (link) { + if (!link.trigger) { return; } + this.events['click .' + link.icon] = "triggerEvent"; + }, this); + }, this); + }, + triggerEvent: function(e){ + e.preventDefault(); + var eventTrigger = $(e.currentTarget).attr('triggerEvent'); + FauxtonAPI.Events.trigger(eventTrigger); + }, + update: function(links){ + this.links = links; + this.render(); }, serialize: function(){ - var sidebarItem = FauxtonAPI.getExtensions('sidebar:links'); return { - links: this.links + links: this.links, + icon: this.icon }; } }); diff --git a/app/addons/fauxton/templates/header_left.html b/app/addons/fauxton/templates/header_left.html new file mode 100644 index 000000000..420b90b12 --- /dev/null +++ b/app/addons/fauxton/templates/header_left.html @@ -0,0 +1,17 @@ + + +
+ +
diff --git a/app/addons/fauxton/templates/menu_dropdown.html b/app/addons/fauxton/templates/menu_dropdown.html index ddef34389..ba7379328 100644 --- a/app/addons/fauxton/templates/menu_dropdown.html +++ b/app/addons/fauxton/templates/menu_dropdown.html @@ -12,7 +12,7 @@ the License. --> - + + diff --git a/app/core/api.js b/app/core/api.js index 1b21dca62..900719511 100644 --- a/app/core/api.js +++ b/app/core/api.js @@ -26,6 +26,8 @@ function(FauxtonAPI, Layout, Router, RouteObject, utils) { utils: utils }); + FauxtonAPI.Events = _.extend({}, Backbone.Events); + FauxtonAPI.navigate = function(url, _opts) { var options = _.extend({trigger: true}, _opts ); FauxtonAPI.router.navigate(url,options); diff --git a/app/templates/layouts/with_tabs_sidebar.html b/app/templates/layouts/with_tabs_sidebar.html index 3d8613047..125f75c11 100644 --- a/app/templates/layouts/with_tabs_sidebar.html +++ b/app/templates/layouts/with_tabs_sidebar.html @@ -13,22 +13,18 @@ -->
-
- -
- +
+
+
+
-
+
- -
-
-
@@ -39,3 +35,4 @@
+ diff --git a/assets/less/fauxton.less b/assets/less/fauxton.less index efd861371..c9c3f8a55 100644 --- a/assets/less/fauxton.less +++ b/assets/less/fauxton.less @@ -595,7 +595,7 @@ table.databases { .closeMenu & { left: @collapsedNavWidth; } - border-bottom: 5px solid @breadcrumbBorder; + //border-bottom: 5px solid @breadcrumbBorder; .box-shadow(0 4px 6px -2px #808080); z-index: 100; .one-pane & { From c3230a435b66212cb9be90c40e7d0049ba6c2371 Mon Sep 17 00:00:00 2001 From: Garren Smith Date: Tue, 2 Sep 2014 14:02:22 +0200 Subject: [PATCH 2/4] PR review fixes --- app/addons/documents/routes-documents.js | 10 +++++----- assets/less/fauxton.less | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/addons/documents/routes-documents.js b/app/addons/documents/routes-documents.js index 8571256d1..9ab69b361 100644 --- a/app/addons/documents/routes-documents.js +++ b/app/addons/documents/routes-documents.js @@ -185,11 +185,9 @@ function(app, FauxtonAPI, Documents, Changes, Index, DocEditor, Databases, Resou this.sidebar.setSelectedTab(app.utils.removeSpecialCharacters(ddoc)+"_metadata"); - this.crumbs = function () { - return [ - {"name": this.database.id, "link": Databases.databaseUrl(this.database)}, - ]; - }; + + this.leftheader.updateCrumbs(crumbs.allDocs(this.database)); + this.leftheader.forceRender(); this.apiUrl = [designDocInfo.url('apiurl'), designDocInfo.documentation() ]; @@ -234,6 +232,7 @@ function(app, FauxtonAPI, Documents, Changes, Index, DocEditor, Databases, Resou } this.leftheader.updateCrumbs(crumbs.allDocs(this.database)); + this.leftheader.forceRender(); this.database.buildAllDocs(docParams); if (docParams.startkey && docParams.startkey.indexOf('_design') > -1) { @@ -307,6 +306,7 @@ function(app, FauxtonAPI, Documents, Changes, Index, DocEditor, Databases, Resou this.sidebar.setSelectedTab(app.utils.removeSpecialCharacters(ddoc) + '_' + app.utils.removeSpecialCharacters(view)); this.rightHeader.updateApiUrl([this.indexedDocs.urlRef("apiurl", urlParams), "docs"]); + this.leftheader.forceRender(); }, ddocInfo: function (designDoc, designDocs, view) { diff --git a/assets/less/fauxton.less b/assets/less/fauxton.less index c9c3f8a55..52e3e35d5 100644 --- a/assets/less/fauxton.less +++ b/assets/less/fauxton.less @@ -1147,7 +1147,7 @@ div.add-dropdown { position: relative; #header-dropdown-menu { position: absolute; - right: 0; + right: 5px; top: 0; .dropdown-toggle { color: #666666; From bb8625b91d5471d82e935393f204b395fc97679b Mon Sep 17 00:00:00 2001 From: Garren Smith Date: Tue, 2 Sep 2014 14:38:57 +0200 Subject: [PATCH 3/4] Fix sidebar width --- assets/less/fauxton.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/less/fauxton.less b/assets/less/fauxton.less index 52e3e35d5..18dadcbe1 100644 --- a/assets/less/fauxton.less +++ b/assets/less/fauxton.less @@ -1101,7 +1101,7 @@ div.add-dropdown { #breadcrumbs { height: 60px; - width: @sidebarWidth - 4; + width: @sidebarWidth - 1; /* these styles are for the new header*/ .header-left{ > div{ From fdbd20ca5220fc7f6e0fd6bf744eebab6e067b1a Mon Sep 17 00:00:00 2001 From: Garren Smith Date: Tue, 2 Sep 2014 14:47:02 +0200 Subject: [PATCH 4/4] sidebar width --- assets/less/fauxton.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/less/fauxton.less b/assets/less/fauxton.less index 18dadcbe1..86b2147f4 100644 --- a/assets/less/fauxton.less +++ b/assets/less/fauxton.less @@ -1101,7 +1101,7 @@ div.add-dropdown { #breadcrumbs { height: 60px; - width: @sidebarWidth - 1; + width: @sidebarWidth; /* these styles are for the new header*/ .header-left{ > div{