couchdb-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From gar...@apache.org
Subject [6/7] Fauxton: Split less files and rename mixin.js
Date Mon, 06 Jan 2014 14:16:35 GMT
http://git-wip-us.apache.org/repos/asf/couchdb/blob/752819c1/src/fauxton/app/addons/documents/views.js
----------------------------------------------------------------------
diff --cc src/fauxton/app/addons/documents/views.js
index 52070af,0000000..bbf5d8a
mode 100644,000000..100644
--- a/src/fauxton/app/addons/documents/views.js
+++ b/src/fauxton/app/addons/documents/views.js
@@@ -1,1805 -1,0 +1,1805 @@@
 +// 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",
 +       "addons/pouchdb/base",
 +
 +       // Libs
 +       "resizeColumns",
 +
 +       // Plugins
 +       "plugins/prettify"
 +
 +],
 +
 +function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColumns) {
 +  var Views = {};
 +
 +  // Views.Tabs = FauxtonAPI.View.extend({
 +  //   template: "templates/documents/tabs",
 +  //   initialize: function(options){
 +  //     this.collection = options.collection;
 +  //     this.database = options.database;
 +  //     this.active_id = options.active_id;
 +  //   },
 +
 +  //   events: {
 +  //     "click #delete-database": "delete_database"
 +  //   },
 +
 +  //   serialize: function () {
 +  //     return {
 +  //       // TODO make this not hard coded here
 +  //       changes_url: '#' + this.database.url('changes'),
 +  //       db_url: '#' + this.database.url('index') + '?limit=' + Databases.DocLimit,
 +  //     };
 +  //   },
 +
 +  //   beforeRender: function(manage) {
 +  //     this.insertView("#search", new Views.SearchBox({
 +  //       collection: this.collection,
 +  //       database: this.database.id
 +  //     }));
 +  //   },
 +
 +  //   afterRender: function () {
 +  //     if (this.active_id) {
 +  //       this.$('.active').removeClass('active');
 +  //       this.$('#'+this.active_id).addClass('active');
 +  //     }
 +  //   },
 +
 +  //   delete_database: function (event) {
 +  //     event.preventDefault();
 +
 +  //     var result = confirm("Are you sure you want to delete this database?");
 +
 +  //     if (!result) { return; }
 +  //     FauxtonAPI.addNotification({
 +  //       msg: "Deleting your database...",
 +  //       type: "error"
 +  //     });
 +  //     return this.database.destroy().done(function () {
 +  //       app.router.navigate('#/_all_dbs', {trigger: true});
 +  //     });
 +  //   }
 +  // });
 +
 +  Views.SearchBox = FauxtonAPI.View.extend({
 +    template: "templates/documents/search",
 +    tagName: "form",
 +    initialize: function(options){
 +      this.collection = options.collection;
 +      this.database = options.database;
 +    },
 +    afterRender: function(){
 +      var collection = this.collection;
 +      var form = this.$el;
 +      var searchbox = form.find("input#searchbox");
 +      var database = this.database;
 +
 +      form.submit(function(evt){
 +        evt.preventDefault();
 +        var viewname = form.find("input#view").val().split('/');
 +        var url = "#database/" + database + "/_design/";
 +        url += viewname[0] + "/_view/" + viewname[1];
 +        if (searchbox.val() !== ""){
 +          // TODO: this'll need to work when val() is a number etc.
 +          url += '?startkey="' + searchbox.val() + '"';
 +        }
 +        FauxtonAPI.navigate(url);
 +      });
 +
 +      searchbox.typeahead({
 +        source: function(query, process) {
 +          // TODO: include _all_docs and view keys somehow
 +          var views = _.map(collection.pluck('doc'), function(d){
 +            return _.map(_.keys(d.views), function(view){
 +              return d._id.split('/')[1] + "/" + view;
 +            });
 +          });
 +          return _.flatten(views);
 +        },
 +        minLength: 3,
 +        updater: function(item){
 +          // TODO: some way to return the original search box
 +          this.$element.removeClass('span12');
 +          this.$element.addClass('span6');
 +          this.$element.attr('placeholder', 'Search by view key');
 +          $('<span class="add-on span6">' + item +'</span>').insertBefore(this.$element);
 +          $('<input type="hidden" id="view" value="' + item +'"/>').insertBefore(this.$element);
 +          // Remove the type ahead for now
 +          $('.typehead').unbind();
 +        }
 +      });
 +    }
 +  });
 +
 +  Views.UploadModal = FauxtonAPI.View.extend({
 +    template: "templates/documents/upload_modal",
 +
 +    disableLoader: true,
 +    
 +    initialize: function (options) {
 +      _.bindAll(this);
 +    },
 +
 +    events: {
 +      "click a#upload-btn": "uploadFile"
 +    },
 +
 +    uploadFile: function (event) {
 +      event.preventDefault();
 +
 +      var docRev = this.model.get('_rev'),
 +          that = this,
 +          $form = this.$('#file-upload');
 +
 +      if (!docRev) {
 +        return this.set_error_msg('The document needs to be saved before adding an attachment.');
 +      }
 +
 +      if ($('input[type="file"]')[0].files.length === 0) {
 +        return this.set_error_msg('Selected a file to be uploaded.');
 +      }
 +
 +      this.$('#_rev').val(docRev);
 +
 +      $form.ajaxSubmit({
 +        url: this.model.url(),
 +        type: 'POST',
 +        beforeSend: this.beforeSend,
 +        uploadProgress: this.uploadProgress,
 +        success: this.success,
 +        error: function (resp) {
 +          console.log('ERR on upload', resp);
 +          return that.set_error_msg('Could not upload document: ' + JSON.parse(resp.responseText).reason);
 +        }
 +      });
 +    },
 +
 +    success: function (resp) {
 +      var hideModal = this.hideModal,
 +          $form = this.$('#file-upload');
 +
 +      FauxtonAPI.triggerRouteEvent('reRenderDoc');
 +      //slight delay to make this transistion a little more fluid and less jumpy
 +      setTimeout(function () {
 +        $form.clearForm();
 +        hideModal();
 +        $('.modal-backdrop').remove();
 +      }, 1000);
 +    },
 +
 +    uploadProgress: function(event, position, total, percentComplete) {
 +      this.$('.bar').css({width: percentComplete + '%'});
 +    },
 +
 +    beforeSend: function () {
 +      this.$('.progress').removeClass('hide');
 +    },
 +
 +    showModal: function () {
 +      this.$('.bar').css({width: '0%'});
 +      this.$('.progress').addClass('hide');
 +      this.clear_error_msg();
 +      this.$('.modal').modal();
 +      // hack to get modal visible 
 +      $('.modal-backdrop').css('z-index',1025);
 +    },
 +
 +    hideModal: function () {
 +      this.$('.modal').modal('hide');
 +    },
 +
 +    set_error_msg: function (msg) {
 +      var text;
 +      if (typeof(msg) == 'string') {
 +        text = msg;
 +      } else {
 +        text = JSON.parse(msg.responseText).reason;
 +      }
 +      this.$('#modal-error').text(text).removeClass('hide');
 +    },
 +
 +    clear_error_msg: function () {
 +      this.$('#modal-error').text(' ').addClass('hide');
 +    },
 +
 +    serialize: function () {
 +      return this.model.toJSON();
 +    }
 +  });
 +
 +  Views.DuplicateDocModal = FauxtonAPI.View.extend({
 +    template: "templates/documents/duplicate_doc_modal",
 +
 +    initialize: function () {
 +      _.bindAll(this);
 +    },
 +
 +    events: {
 +      "click #duplicate-btn":"duplicate"
 +
 +    },
 +
 +    duplicate: function (event) {
 +      event.preventDefault();
 +      var newId = this.$('#dup-id').val(),
-           encodedID = app.mixins.safeURLName(newId);
++          encodedID = app.utils.safeURLName(newId);
 +
 +      this.hideModal();
 +      FauxtonAPI.triggerRouteEvent('duplicateDoc', encodedID);
 +    },
 +
 +    _showModal: function () {
 +      this.$('.bar').css({width: '0%'});
 +      this.$('.progress').addClass('hide');
 +      this.clear_error_msg();
 +      this.$('.modal').modal();
 +      // hack to get modal visible 
 +      $('.modal-backdrop').css('z-index',1025);
 +    },
 +
 +    showModal: function () {
 +      var showModal = this._showModal,
 +          setDefaultIdValue = this.setDefaultIdValue,
 +          uuid = new FauxtonAPI.UUID();
 +
 +      uuid.fetch().then(function () {
 +        setDefaultIdValue(uuid.next());
 +        showModal();
 +      });
 +    },
 +
 +    setDefaultIdValue: function (id) {
 +      this.$('#dup-id').val(id);
 +    },
 +
 +    hideModal: function () {
 +      this.$('.modal').modal('hide');
 +    },
 +
 +    set_error_msg: function (msg) {
 +      var text;
 +      if (typeof(msg) == 'string') {
 +        text = msg;
 +      } else {
 +        text = JSON.parse(msg.responseText).reason;
 +      }
 +      this.$('#modal-error').text(text).removeClass('hide');
 +    },
 +
 +    clear_error_msg: function () {
 +      this.$('#modal-error').text(' ').addClass('hide');
 +    },
 +
 +    serialize: function () {
 +      return this.model.toJSON();
 +    }
 +
 +  });
 +
 +  Views.FieldEditorTabs = FauxtonAPI.View.extend({
 +    template: "templates/documents/doc_field_editor_tabs",
 +    disableLoader: true,
 +    initialize: function(options) {
 +      this.selected = options.selected;
 +    },
 +
 +    events: {
 +    },
 +    updateSelected: function (selected) {
 +      this.selected = selected;
 +      this.$('.active').removeClass('active');
 +      this.$('#'+this.selected).addClass('active');
 +    },
 +
 +    serialize: function() {
 +      var selected = this.selected;
 +      return {
 +        doc: this.model,
 +        isNewDoc: this.model.isNewDoc(),
 +        isSelectedClass: function(item) {
 +          return item && item === selected ? "active" : "";
 +        }
 +      };
 +    },
 +
 +    establish: function() {
 +      return [this.model.fetch()];
 +    }
 +  });
 +
 +  Views.Document = FauxtonAPI.View.extend({
 +    template: "templates/documents/all_docs_item",
 +    tagName: "tr",
 +    className: "all-docs-item",
 +
 +    events: {
 +      "click button.delete": "destroy",
 +      "dblclick pre.prettyprint": "edit"
 +    },
 +
 +    attributes: function() {
 +      return {
 +        "data-id": this.model.id
 +      };
 +    },
 +
 +    serialize: function() {
 +      return {
 +        doc: this.model
 +      };
 +    },
 +
 +    establish: function() {
 +      return [this.model.fetch()];
 +    },
 +
 +    edit: function(event) {
 +      event.preventDefault();
 +      FauxtonAPI.navigate("#" + this.model.url('app'));
 +    },
 +
 +    destroy: function(event) {
 +      event.preventDefault();
 +      var that = this;
 +
 +      if (!window.confirm("Are you sure you want to delete this doc?")) {
 +        return false;
 +      }
 +
 +      this.model.destroy().then(function(resp) {
 +        FauxtonAPI.addNotification({
 +          msg: "Succesfully destroyed your doc"
 +        });
 +        that.$el.fadeOut(function () {
 +          that.remove();
 +        });
 +
 +        that.model.collection.remove(that.model.id);
 +        if (!!that.model.id.match('_design')) {
 +          FauxtonAPI.triggerRouteEvent('reloadDesignDocs');
 +        }
 +      }, function(resp) {
 +        FauxtonAPI.addNotification({
 +          msg: "Failed to destroy your doc!",
 +          type: "error"
 +        });
 +      });
 +    }
 +  });
 +
 +  Views.Row = FauxtonAPI.View.extend({
 +    template: "templates/documents/index_row_docular",
 +    tagName: "tr",
 +
 +    events: {
 +      "click button.delete": "destroy"
 +    },
 +
 +    destroy: function (event) {
 +      event.preventDefault(); 
 +      
 +      window.alert('Cannot delete a document generated from a view.');
 +    },
 +
 +    serialize: function() {
 +      return {
 +        doc: this.model
 +      };
 +    }
 +  });
 +
 +  Views.IndexItem = FauxtonAPI.View.extend({
 +    template: "templates/documents/index_menu_item",
 +    tagName: "li",
 +
 +    initialize: function(options){
 +      this.index = options.index;
 +      this.ddoc = options.ddoc;
 +      this.database = options.database;
 +      this.selected = !! options.selected;
 +    },
 +
 +    serialize: function() {
 +      return {
 +        index: this.index,
 +        ddoc: this.ddoc,
 +        database: this.database,
-         index_clean: app.mixins.removeSpecialCharacters(this.index),
-         ddoc_clean: app.mixins.removeSpecialCharacters(this.ddoc), 
-         index_encoded: app.mixins.safeURLName(this.index),
-         ddoc_encoded: app.mixins.safeURLName(this.ddoc),
-         database_encoded: app.mixins.safeURLName(this.database),
++        index_clean: app.utils.removeSpecialCharacters(this.index),
++        ddoc_clean: app.utils.removeSpecialCharacters(this.ddoc), 
++        index_encoded: app.utils.safeURLName(this.index),
++        ddoc_encoded: app.utils.safeURLName(this.ddoc),
++        database_encoded: app.utils.safeURLName(this.database),
 +        selected: this.selected
 +      };
 +    },
 +
 +    afterRender: function() {
 +      if (this.selected) {
 +        $("#sidenav ul.nav-list li").removeClass("active");
 +        this.$el.addClass("active");
 +      }
 +    }
 +  });
 +
 +  Views.AllDocsNumber = FauxtonAPI.View.extend({
 +    template: "templates/documents/all_docs_number",
 +
 +    initialize: function (options) {
 +      this.newView = options.newView || false;
 +      
 +      this.listenTo(this.collection, 'totalRows:decrement', this.render);
 +    },
 +
 +    serialize: function () {
 +       var totalRows = 0,
 +          recordStart = 0,
 +          updateSeq = false;
 +
 +      if (!this.newView) {
 +        totalRows = this.collection.totalRows();
 +        updateSeq = this.collection.updateSeq();
 +      }
 +
 +      recordStart = this.collection.recordStart();
 +
 +      return {
-         database: app.mixins.safeURLName(this.collection.database.id),
++        database: app.utils.safeURLName(this.collection.database.id),
 +        updateSeq: updateSeq,
 +        offset: recordStart,
 +        totalRows: totalRows,
 +        numModels: this.collection.models.length + recordStart - 1,
 +      };
 +    }
 +
 +  });
 +
 +  Views.AllDocsLayout = FauxtonAPI.View.extend({
 +    template: "templates/documents/all_docs_layout",
 +    className: "row",
 +
 +    initialize: function (options) {
 +      this.database = options.database;
 +      this.params = options.params;
 +    },
 +
 +    events: {
 +      'click #toggle-query': "toggleQuery"
 +    },
 +
 +    toggleQuery: function (event) {
 +      this.$('#query').toggle('fast');
 +    },
 +
 +    beforeRender: function () {
 +      this.advancedOptions = this.insertView('#query', new Views.AdvancedOptions({
 +        updateViewFn: this.updateView,
 +        previewFn: this.previewView,
 +        hasReduce: false,
 +        showPreview: false,
 +        database: this.database
 +      }));
 +
 +      this.$('#query').hide();
 +    },
 +
 +    afterRender: function () {
 +      if (this.params) {
 +        this.advancedOptions.updateFromParams(this.params);
 +      }
 +
 +    },
 +
 +    updateView: function (event, paramInfo) {
 +      event.preventDefault();
 +
 +      var errorParams = paramInfo.errorParams,
 +          params = paramInfo.params;
 +
 +      if (_.any(errorParams)) {
 +        _.map(errorParams, function(param) {
 +
 +          // TODO: Where to add this error?
 +          // bootstrap wants the error on a control-group div, but we're not using that
 +          //$('form.view-query-update input[name='+param+'], form.view-query-update select[name='+param+']').addClass('error');
 +          return FauxtonAPI.addNotification({
 +            msg: "JSON Parse Error on field: "+param.name,
 +            type: "error",
 +            selector: ".advanced-options .errors-container"
 +          });
 +        });
 +        FauxtonAPI.addNotification({
 +          msg: "Make sure that strings are properly quoted and any other values are valid JSON structures",
 +          type: "warning",
 +          selector: ".advanced-options .errors-container"
 +        });
 +
 +        return false;
 +      }
 +
 +      var fragment = window.location.hash.replace(/\?.*$/, '');
 +      fragment = fragment + '?' + $.param(params);
 +      FauxtonAPI.navigate(fragment, {trigger: false});
 +
 +      FauxtonAPI.triggerRouteEvent('updateAllDocs', {allDocs: true});
 +    },
 +
 +    previewView: function (event) {
 +      event.preventDefault();
 +    }
 +
 +  });
 +
 +  // TODO: Rename to reflect that this is a list of rows or documents
 +  Views.AllDocsList = FauxtonAPI.View.extend({
 +    template: "templates/documents/all_docs_list",
 +    events: {
 +      "click button.all": "selectAll",
 +      "click button.bulk-delete": "bulkDelete",
 +      "click #collapse": "collapse",
 +      "change .row-select":"toggleTrash"
 +    },
 +
 +    toggleTrash: function () {
 +      if (this.$('.row-select:checked').length > 0) {
 +        this.$('.bulk-delete').removeClass('disabled');
 +      } else {
 +        this.$('.bulk-delete').addClass('disabled');
 +      }
 +    },
 +
 +    initialize: function(options){
 +      this.nestedView = options.nestedView || Views.Document;
 +      this.rows = {};
 +      this.viewList = !! options.viewList;
 +      this.database = options.database;
 +      if (options.ddocInfo) {
 +        this.designDocs = options.ddocInfo.designDocs;
 +        this.ddocID = options.ddocInfo.id;
 +      }
 +      this.newView = options.newView || false;
 +      this.expandDocs = true;
 +      this.addPagination();
 +    },
 +
 +    establish: function() {
 +      if (this.newView) { return null; }
 +
 +      return this.collection.fetch({reset: true}).fail(function() {
 +        // TODO: handle error requests that slip through
 +        // This should just throw a notification, not break the page
 +        console.log("ERROR: ", arguments);
 +      });
 +    },
 +
 +    selectAll: function(evt){
 +      $("input:checkbox").prop('checked', !$(evt.target).hasClass('active')).trigger('change');
 +    },
 +
 +    serialize: function() {
 +      var requestDuration = false;
 +
 +      if (this.collection.requestDurationInString) {
 +        requestDuration = this.collection.requestDurationInString();
 +      }
 +
 +      return {
 +        viewList: this.viewList,
 +        requestDuration: requestDuration,
 +        expandDocs: this.expandDocs
 +      };
 +    },
 +
 +    collapse: function (event) {
 +      event.preventDefault();
 +
 +      if (this.expandDocs) {
 +        this.expandDocs = false;
 +      } else {
 +        this.expandDocs = true;
 +      }
 +
 +      this.render();
 +    },
 +
 +    /*
 +     * TODO: this should be reconsidered
 +     * This currently performs delete operations on the model level,
 +     * when we could be using bulk docs with _deleted = true. Using
 +     * individual models is cleaner from a backbone standpoint, but
 +     * not from the couchdb api.
 +     * Also, the delete method is naive and leaves the body intact,
 +     * when we should switch the doc to only having id/rev/deleted.
 +     */
 +    bulkDelete: function() {
 +      var that = this;
 +      // yuck, data binding ftw?
 +      var eles = this.$el.find("input.row-select:checked")
 +                         .parents("tr.all-docs-item")
 +                         .map(function(e) { return $(this).attr("data-id"); })
 +                         .get();
 +
 +      if (eles.length === 0 || !window.confirm("Are you sure you want to delete these " + eles.length + " docs?")) {
 +        return false;
 +      }
 +
 +      _.each(eles, function(ele) {
 +        var model = this.collection.get(ele);
 +
 +        model.destroy().then(function(resp) {
 +          that.rows[ele].$el.fadeOut(function () {
 +            $(this).remove();
 +          });
 +
 +          model.collection.remove(model.id);
 +          console.log(model.id.match('_design'), !!model.id.match('_design'));
 +          if (!!model.id.match('_design')) { 
 +            FauxtonAPI.triggerRouteEvent('reloadDesignDocs');
 +          }
 +          that.$('.bulk-delete').addClass('disabled');
 +        }, function(resp) {
 +          FauxtonAPI.addNotification({
 +            msg: "Failed to destroy your doc!",
 +            type: "error"
 +          });
 +        });
 +      }, this);
 +    },
 +
 +    addPagination: function () {
 +      var collection = this.collection;
 +
 +      this.pagination = new Components.IndexPagination({
 +        collection: this.collection,
 +        scrollToSelector: '#dashboard-content',
 +        previousUrlfn: function () {
 +          return collection.urlPreviousPage(20, this.previousIds.pop());
 +        },
 +        canShowPreviousfn: function () {
 +          if (collection.viewMeta.offset === 0) {
 +            return false;
 +          }
 +
 +          return true;
 +        },
 +        canShowNextfn: function () {
 +          if (collection.length === 0 || (collection.viewMeta.offset + collection.length + 2) >= collection.viewMeta.total_rows) {
 +            return false;
 +          }
 +
 +          return true;
 +        },
 +        
 +        nextUrlfn: function () {
 +          return collection.urlNextPage(20);
 +        }
 +      });
 +    },
 +
 +    beforeRender: function() {
 +      this.allDocsNumber = this.setView('#item-numbers', new Views.AllDocsNumber({
 +        collection: this.collection,
 +        newView: this.newView
 +      }));
 +
 +      this.insertView('#documents-pagination', this.pagination);
 +      var docs = this.expandDocs ? this.collection : this.collection.simple();
 +
 +      docs.each(function(doc) {
 +        this.rows[doc.id] = this.insertView("table.all-docs tbody", new this.nestedView({
 +          model: doc
 +        }));
 +      }, this);
 +    },
 +
 +    afterRender: function(){
 +      prettyPrint();
 +    }
 +  });
 +
 +  Views.Doc = FauxtonAPI.View.extend({
 +    template: "templates/documents/doc",
 +    events: {
 +      "click button.save-doc": "saveDoc",
 +      "click button.delete": "destroy",
 +      "click button.duplicate": "duplicate",
 +      "click button.upload": "upload",
 +      "click button.cancel-button": "goback"
 +    },
 +    disableLoader: true,
 +    initialize: function (options) {
 +      this.database = options.database;
 +      _.bindAll(this);
 +    },
 +    goback: function(){
 +      FauxtonAPI.navigate(this.database.url("index") + "?limit=100");
 +    },
 +    destroy: function(event) {
 +      if (this.model.isNewDoc()) {
 +        FauxtonAPI.addNotification({
 +          msg: 'This document has not been saved yet.',
 +          type: 'warning'
 +        });
 +        return;
 +      }
 +
 +      if (!window.confirm("Are you sure you want to delete this doc?")) {
 +        return false;
 +      }
 +
 +      var database = this.model.database;
 +
 +      this.model.destroy().then(function(resp) {
 +        FauxtonAPI.addNotification({
 +          msg: "Succesfully destroyed your doc"
 +        });
 +        FauxtonAPI.navigate(database.url("index"));
 +      }, function(resp) {
 +        FauxtonAPI.addNotification({
 +          msg: "Failed to destroy your doc!",
 +          type: "error"
 +        });
 +      });
 +    },
 +
 +    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}));
 +      this.duplicateModal.render();
 +    },
 +
 +    upload: function (event) {
 +      event.preventDefault();
 +      if (this.model.isNewDoc()) {
 +        FauxtonAPI.addNotification({
 +          msg: 'Please save the document before uploading an attachment.',
 +          type: 'warning'
 +        });
 +        return;
 +      }
 +      this.uploadModal.showModal();
 +    },
 +
 +    duplicate: function(event) {
 +      if (this.model.isNewDoc()) {
 +        FauxtonAPI.addNotification({
 +          msg: 'Please save the document before duplicating it.',
 +          type: 'warning'
 +        });
 +        return;
 +      }
 +      event.preventDefault();
 +      this.duplicateModal.showModal();
 +    },
 +
 +    updateValues: function() {
 +      var notification;
 +      if (this.model.changedAttributes()) {
 +        notification = FauxtonAPI.addNotification({
 +          msg: "Document saved successfully.",
 +          type: "success",
 +          clear: true
 +        });
 +        this.editor.setValue(this.model.prettyJSON());
 +      }
 +    },
 +
 +    establish: function() {
 +      var promise = this.model.fetch(),
 +          databaseId = this.database.safeID(),
 +          deferred = $.Deferred(),
 +          that = this;
 +
 +      promise.then(function () {
 +        deferred.resolve();
 +      }, function (xhr, reason, msg) {
 +        if (xhr.status === 404) {
 +          FauxtonAPI.addNotification({
 +            msg: 'The document does not exist',
 +            type: 'error',
 +            clear: true
 +          });
 +          that.goback();
 +        }
 +        deferred.reject();
 +     });
 +      
 +      return deferred;
 +    },
 +
 +    saveDoc: function(event) {
 +      var json, notification, 
 +      that = this,
 +      editor = this.editor,
 +      validDoc = this.getDocFromEditor();
 +
 +      if (validDoc) {
 +        this.getDocFromEditor();
 +
 +        notification = FauxtonAPI.addNotification({msg: "Saving document."});
 +
 +        this.model.save().then(function () {
 +          editor.editSaved();
 +          FauxtonAPI.navigate('/database/' + that.database.safeID() + '/' + that.model.id);
 +        }).fail(function(xhr) {
 +          var responseText = JSON.parse(xhr.responseText).reason;
 +          notification = FauxtonAPI.addNotification({
 +            msg: "Save failed: " + responseText,
 +            type: "error",
 +            clear: true,
 +            selector: "#doc .errors-container"
 +          });
 +        });
 +      } else if(this.model.validationError && this.model.validationError === 'Cannot change a documents id.') {
 +          notification = FauxtonAPI.addNotification({
 +            msg: "Cannot save: " + 'Cannot change a documents _id, try Duplicate doc instead!',
 +            type: "error",
 +            selector: "#doc .errors-container"
 +          });
 +        delete this.model.validationError;
 +      } else {
 +        notification = FauxtonAPI.addNotification({
 +          msg: "Please fix the JSON errors and try again.",
 +          type: "error",
 +          selector: "#doc .errors-container"
 +        });
 +      }
 +    },
 +
 +    getDocFromEditor: function () {
 +      if (!this.hasValidCode()) {
 +        return false;
 +      }
 +
 +      json = JSON.parse(this.editor.getValue());
 +
 +      this.model.clear().set(json, {validate: true});
 +      if (this.model.validationError) {
 +        return false;
 +      }
 +
 +      return this.model;
 +    },
 +
 +    hasValidCode: function() {
 +      var errors = this.editor.getAnnotations();
 +      return errors.length === 0;
 +    },
 +
 +    serialize: function() {
 +      return {
 +        doc: this.model,
 +        attachments: this.getAttachments()
 +      };
 +    },
 +
 +    getAttachments: function () {
 +      var attachments = this.model.get('_attachments');
 +
 +      if (!attachments) { return false; }
 +
 +      return _.map(attachments, function (att, key) {
 +        return {
 +          fileName: key,
 +          size: att.length,
 +          contentType: att.content_type,
 +          url: this.model.url() + '/' + key
 +        };
 +      }, this);
 +    },
 +
 +    afterRender: function() {
 +      var saveDoc = this.saveDoc;
 +
 +      this.editor = new Components.Editor({
 +        editorId: "editor-container",
 +        commands: [{
 +          name: 'save',
 +          bindKey: {win: 'Ctrl-S',  mac: 'Ctrl-S'},
 +          exec: function(editor) {
 +            saveDoc();
 +          },
 +          readOnly: true // false if this command should not apply in readOnly mode
 +        }]
 +      });
 +      this.editor.render();
 +      this.model.on("sync", this.updateValues, this);
 +    },
 +
 +    cleanup: function () {
 +      if (this.editor) this.editor.remove();
 +    }
 +  });
 +
 +  Views.DocFieldEditor = FauxtonAPI.View.extend({
 +    template: "templates/documents/doc_field_editor",
 +    disableLoader: true,
 +    events: {
 +      "click button.save": "saveDoc"
 +    },
 +
 +    saveDoc: function(event) {
 +      FauxtonAPI.addNotification({
 +        type: "warning",
 +        msg: "Save functionality coming soon."
 +      });
 +    },
 +
 +    serialize: function() {
 +      return {
 +        doc: this.getModelWithoutAttachments(),
 +        attachments: this.getAttachments()
 +      };
 +    },
 +
 +    getModelWithoutAttachments: function() {
 +      var model = this.model.toJSON();
 +      delete model._attachments;
 +      return model;
 +    },
 +
 +    getAttachments: function () {
 +      var attachments = this.model.get('_attachments');
 +
 +      if (!attachments) { return []; }
 +
 +      return _.map(attachments, function (att, key) {
 +        return {
 +          fileName: key,
 +          size: att.length,
 +          contentType: att.content_type,
 +          url: this.model.url() + '/' + key
 +        };
 +      }, this);
 +    },
 +
 +    establish: function() {
 +      return [this.model.fetch()];
 +    }
 +  });
 +
 +  Views.AdvancedOptions = FauxtonAPI.View.extend({
 +    template: "templates/documents/advanced_options",
 +    className: "advanced-options well",
 +
 +    initialize: function (options) {
 +      this.database = options.database;
 +      this.ddocName = options.ddocName;
 +      this.viewName = options.viewName;
 +      this.updateViewFn = options.updateViewFn;
 +      this.previewFn = options.previewFn;
 +      //this.hadReduce = options.hasReduce || true;
 +
 +      if (typeof(options.hasReduce) === 'undefined') {
 +        this.hasReduce = true;
 +      } else {
 +        this.hasReduce = options.hasReduce;
 +      }
 +
 +      if (typeof(options.showPreview) === 'undefined') {
 +        this.showPreview = true;
 +      } else {
 +        this.showPreview = options.showPreview;
 +      }
 +    },
 +
 +    events: {
 +      "change form.view-query-update input": "updateFilters",
 +      "change form.view-query-update select": "updateFilters",
 +      "submit form.view-query-update": "updateView",
 +      "click button.preview": "previewView"
 +    },
 +
 +    beforeRender: function () {
 +      if (this.viewName && this.ddocName) {
 +        var buttonViews = FauxtonAPI.getExtensions('advancedOptions:ViewButton');
 +        _.each(buttonViews, function (view) {
 +          this.insertView('#button-options', view);
 +          view.update(this.database, this.ddocName, this.viewName);
 +        }, this);
 +      }
 +    },
 +
 +    renderOnUpdatehasReduce: function (hasReduce) {
 +      this.hasReduce = hasReduce;
 +      this.render();
 +    },
 +
 +    queryParams: function () {
 +      var $form = this.$(".view-query-update");
 +      // Ignore params without a value
 +      var params = _.filter($form.serializeArray(), function(param) {
 +        return param.value;
 +      });
 +
 +      // Validate *key* params to ensure they're valid JSON
 +      var keyParams = ["key","keys","startkey","endkey"];
 +      var errorParams = _.filter(params, function(param) {
 +        if (_.contains(keyParams, param.name)) {
 +          try {
 +            JSON.parse(param.value);
 +            return false;
 +          } catch(e) {
 +            return true;
 +          }
 +        } else {
 +          return false;
 +        }
 +      });
 +
 +      return {params: params, errorParams: errorParams};
 +    },
 +
 +    updateFilters: function(event) {
 +      event.preventDefault();
 +      var $ele = $(event.currentTarget);
 +      var name = $ele.attr('name');
 +      this.updateFiltersFor(name, $ele);
 +    },
 +
 +    updateFiltersFor: function(name, $ele) {
 +      var $form = $ele.parents("form.view-query-update:first");
 +      switch (name) {
 +        // Reduce constraints
 +        //   - Can't include_docs for reduce=true
 +        //   - can't include group_level for reduce=false
 +        case "reduce":
 +          if ($ele.prop('checked') === true) {
 +          if ($form.find("input[name=include_docs]").prop("checked") === true) {
 +            $form.find("input[name=include_docs]").prop("checked", false);
 +            var notification = FauxtonAPI.addNotification({
 +              msg: "include_docs has been disabled as you cannot include docs on a reduced view",
 +              type: "warn",
 +              selector: ".view.show .all-docs-list.errors-container"
 +            });
 +          }
 +          $form.find("input[name=include_docs]").prop("disabled", true);
 +          $form.find("select[name=group_level]").prop("disabled", false);
 +        } else {
 +          $form.find("select[name=group_level]").prop("disabled", true);
 +          $form.find("input[name=include_docs]").prop("disabled", false);
 +        }
 +        break;
 +        case "include_docs":
 +          break;
 +      }
 +    },
 +
 +    updateFromParams: function (params) {
 +      var $form = this.$el.find("form.view-query-update");
 +      _.each(params, function(val, key) {
 +        var $ele;
 +        switch (key) {
 +          case "limit":
 +            case "group_level":
 +            $form.find("select[name='"+key+"']").val(val);
 +          break;
 +          case "include_docs":
 +            case "stale":
 +            case "descending":
 +            case "inclusive_end":
 +            $form.find("input[name='"+key+"']").prop('checked', true);
 +          break;
 +          case "reduce":
 +            $ele = $form.find("input[name='"+key+"']");
 +          if (val == "true") {
 +            $ele.prop('checked', true);
 +          }
 +          this.updateFiltersFor(key, $ele);
 +          break;
 +          default:
 +            $form.find("input[name='"+key+"']").val(val);
 +          break;
 +        }
 +      }, this);
 +    },
 +
 +    updateView: function (event) {
 +      this.updateViewFn(event, this.queryParams());
 +    },
 +
 +    previewView: function (event) {
 +      this.previewFn(event, this.queryParams());
 +    },
 +
 +    serialize: function () {
 +      return {
 +        hasReduce: this.hasReduce,
 +        showPreview: this.showPreview
 +      };
 +    }
 +  });
 +
 +  Views.DesignDocSelector = FauxtonAPI.View.extend({
 +    template: "templates/documents/design_doc_selector",
 +
 +    events: {
 +      "change select#ddoc": "updateDesignDoc"
 +    },
 +
 +    initialize: function (options) {
 +      this.ddocName = options.ddocName;
 +      this.database = options.database;
 +      this.listenTo(this.collection, 'add', this.ddocAdded);
 +      this.DocModel = options.DocModel || Documents.Doc;
 +    },
 +
 +    ddocAdded: function (ddoc) {
 +      this.ddocName = ddoc.id;
 +      this.render();
 +    },
 +
 +    serialize: function () {
 +      return {
 +        ddocName: this.ddocName,
 +        ddocs: this.collection
 +      };
 +    },
 +
 +    updateDesignDoc: function () {
 +      if (this.newDesignDoc()) {
 +        this.$('#new-ddoc-section').show();
 +      } else {
 +        this.$('#new-ddoc-section').hide();
 +      }
 +    },
 +
 +    newDesignDoc: function () {
 +
 +      return this.$('#ddoc').val() === 'new-doc';
 +    },
 +
 +    newDocValidation: function(){
 +      return this.newDesignDoc() && this.$('#new-ddoc').val()==="";
 +    },
 +    getCurrentDesignDoc: function () {
 +      if (this.newDesignDoc()) {
 +        var doc = {
 +          _id: '_design/' + this.$('#new-ddoc').val(),
 +          views: {},
 +          language: "javascript"
 +        };
 +        var ddoc = new this.DocModel(doc, {database: this.database});
 +        //this.collection.add(ddoc);
 +        return ddoc;
 +      } else if ( !this.newDesignDoc() ) {
 +        var ddocName = this.$('#ddoc').val();
 +        return this.collection.find(function (ddoc) {
 +          return ddoc.id === ddocName;
 +        }).dDocModel();
 +      }
 +    }
 +  });
 +
 +  Views.ViewEditor = FauxtonAPI.View.extend({
 +    template: "templates/documents/view_editor",
 +    builtinReduces: ['_sum', '_count', '_stats'],
 +
 +    events: {
 +      "click button.save": "saveView",
 +      "click button.delete": "deleteView",
 +      "change select#reduce-function-selector": "updateReduce",
 +      "click button.preview": "previewView",
 +      "click #db-views-tabs-nav": 'toggleIndexNav'
 +    },
 +
 +    langTemplates: {
 +      "javascript": {
 +        map: "function(doc) {\n  emit(doc._id, 1);\n}",
 +        reduce: "function(keys, values, rereduce){\n  if (rereduce){\n    return sum(values);\n  } else {\n    return values.length;\n  }\n}"
 +      }
 +    },
 +
 +    defaultLang: "javascript",
 +
 +    initialize: function(options) {
 +      this.newView = options.newView || false;
 +      this.ddocs = options.ddocs;
 +      this.params = options.params;
 +      this.database = options.database;
 +      if (this.newView) {
 +        this.viewName = 'newView';
 +      } else {
 +        this.ddocID = options.ddocInfo.id;
 +        this.viewName = options.viewName;
 +        this.ddocInfo = new Documents.DdocInfo({_id: this.ddocID},{database: this.database});
 +      }
 +
 +      this.showIndex = false;
 +      _.bindAll(this);
 +    },
 +
 +    establish: function () {
 +      if (this.ddocInfo) {
 +        return this.ddocInfo.fetch();
 +      }
 +    },
 +
 +    updateValues: function() {
 +      var notification;
 +      if (this.model.changedAttributes()) {
 +        notification = FauxtonAPI.addNotification({
 +          msg: "Document saved successfully.",
 +          type: "success",
 +          clear: true
 +        });
 +        this.editor.setValue(this.model.prettyJSON());
 +      }
 +    },
 +
 +    updateReduce: function(event) {
 +      var $ele = $("#reduce-function-selector");
 +      var $reduceContainer = $(".control-group.reduce-function");
 +      if ($ele.val() == "CUSTOM") {
 +        this.createReduceEditor();
 +        this.reduceEditor.setValue(this.langTemplates.javascript.reduce);
 +        $reduceContainer.show();
 +      } else {
 +        $reduceContainer.hide();
 +      }
 +    },
 +
 +    deleteView: function (event) {
 +      event.preventDefault();
 +
 +      if (this.newView) { return alert('Cannot delete a new view.'); }
 +      if (!confirm('Are you sure you want to delete this view?')) {return;}
 +
 +      var that = this,
 +          promise,
 +          viewName = this.$('#index-name').val(),
 +          ddocName = this.$('#ddoc :selected').val(),
 +          ddoc = this.getCurrentDesignDoc();
 +
 +      ddoc.removeDdocView(viewName);
 +
 +      if (ddoc.hasViews()) {
 +        promise = ddoc.save(); 
 +      } else {
 +        promise = ddoc.destroy();
 +      }
 +
 +      promise.then(function () {
 +        FauxtonAPI.navigate('/database/' + that.database.safeID() + '/_all_docs?limit=' + Databases.DocLimit);
 +        FauxtonAPI.triggerRouteEvent('reloadDesignDocs');
 +      });
 +    },
 +
 +    saveView: function(event) {
 +      var json, notification,
 +      that = this;
 +
 +      if (event) { event.preventDefault();}
 +
 +      if (this.hasValidCode() && this.$('#new-ddoc:visible').val() !=="") {
 +        var mapVal = this.mapEditor.getValue(), 
 +        reduceVal = this.reduceVal(),
 +        viewName = this.$('#index-name').val(),
 +        ddoc = this.getCurrentDesignDoc(),
 +        ddocName = ddoc.id;
 +
 +        this.viewName = viewName;
 +
 +        notification = FauxtonAPI.addNotification({
 +          msg: "Saving document.",
 +          selector: "#define-view .errors-container"
 +        });
 +
 +        ddoc.setDdocView(viewName, mapVal, reduceVal);
 +
 +        ddoc.save().then(function () {
 +          that.ddocs.add(ddoc);
 +
 +          that.mapEditor.editSaved();
 +          that.reduceEditor && that.reduceEditor.editSaved();
 +
 +          FauxtonAPI.addNotification({
 +            msg: "View has been saved.",
 +            type: "success",
 +            selector: "#define-view .errors-container"
 +          });
 +
 +          if (that.newView) {
-             var fragment = '/database/' + that.database.safeID() +'/' + ddoc.safeID() + '/_view/' + app.mixins.safeURLName(viewName); 
++            var fragment = '/database/' + that.database.safeID() +'/' + ddoc.safeID() + '/_view/' + app.utils.safeURLName(viewName); 
 +
 +            FauxtonAPI.navigate(fragment, {trigger: false});
 +            that.newView = false;
 +            that.ddocID = ddoc.safeID();
 +            that.viewName = viewName;
 +            that.ddocInfo = ddoc;
 +            that.showIndex = true;
 +            that.render();
 +            FauxtonAPI.triggerRouteEvent('reloadDesignDocs', {
-               selectedTab: app.mixins.removeSpecialCharacters(ddocName.replace(/_design\//,'')) + '_' + app.mixins.removeSpecialCharacters(viewName)
++              selectedTab: app.utils.removeSpecialCharacters(ddocName.replace(/_design\//,'')) + '_' + app.utils.removeSpecialCharacters(viewName)
 +            });
 +          }
 +
 +          if (that.reduceFunStr !== reduceVal) {
 +            that.reduceFunStr = reduceVal;
 +            that.advancedOptions.renderOnUpdatehasReduce(that.hasReduce()); 
 +          }
 +
 +          FauxtonAPI.triggerRouteEvent('updateAllDocs', {ddoc: ddocName, view: viewName});
 +
 +        }, function(xhr) {
 +          var responseText = JSON.parse(xhr.responseText).reason;
 +          notification = FauxtonAPI.addNotification({
 +            msg: "Save failed: " + responseText,
 +            type: "error",
 +            clear: true
 +          });
 +        });
 +      } else {
 +        var errormessage = (this.$('#new-ddoc:visible').val() ==="")?"Enter a design doc name":"Please fix the Javascript errors and try again.";
 +        notification = FauxtonAPI.addNotification({
 +          msg: errormessage,
 +          type: "error",
 +          selector: "#define-view .errors-container"
 +        });
 +      }
 +    },
 +
 +    updateView: function(event, paramInfo) {
 +       event.preventDefault();
 + 
 +       if (this.newView) { return alert('Please save this new view before querying it.'); }
 + 
 +       var errorParams = paramInfo.errorParams,
 +           params = paramInfo.params;
 + 
 +       if (_.any(errorParams)) {
 +         _.map(errorParams, function(param) {
 + 
 +           // TODO: Where to add this error?
 +           // bootstrap wants the error on a control-group div, but we're not using that
 +           //$('form.view-query-update input[name='+param+'], form.view-query-update select[name='+param+']').addClass('error');
 +           return FauxtonAPI.addNotification({
 +             msg: "JSON Parse Error on field: "+param.name,
 +             type: "error",
 +             selector: ".advanced-options .errors-container"
 +           });
 +         });
 +         FauxtonAPI.addNotification({
 +           msg: "Make sure that strings are properly quoted and any other values are valid JSON structures",
 +           type: "warning",
 +           selector: ".advanced-options .errors-container"
 +         });
 + 
 +         return false;
 +      }
 + 
 +       var fragment = window.location.hash.replace(/\?.*$/, '');
 +       fragment = fragment + '?' + $.param(params);
 +       FauxtonAPI.navigate(fragment, {trigger: false});
 + 
 +       FauxtonAPI.triggerRouteEvent('updateAllDocs', {ddoc: this.ddocID, view: this.viewName});
 +    },
 +
 +
 +    previewView: function(event, paramsInfo) {
 +      event.preventDefault();
 +      var that = this,
 +      mapVal = this.mapVal(),
 +      reduceVal = this.reduceVal(),
 +      paramsArr = [];
 +
 +      if (paramsInfo && paramsInfo.params) {
 +        paramsArr = paramsInfo.params;
 +      }
 +
 +      var params = _.reduce(paramsArr, function (params, param) {
 +        params[param.name] = param.value;
 +        return params;
 +      }, {reduce: false});
 +
 +      event.preventDefault();
 +
 +      FauxtonAPI.addNotification({
 +        msg: "<strong>Warning!</strong> Preview executes the Map/Reduce functions in your browser, and may behave differently from CouchDB.",
 +        type: "warning",
 +        selector: ".advanced-options .errors-container",
 +        fade: true
 +      });
 +
 +      var promise = FauxtonAPI.Deferred();
 +
 +      if (!this.database.allDocs) {
 +        this.database.buildAllDocs({limit: Databases.DocLimit.toString(), include_docs: true});
 +        promise = this.database.allDocs.fetch();
 +      } else {
 +        promise.resolve();
 +      }
 +
 +      promise.then(function () {
 +        params.docs = that.database.allDocs.map(function (model) { return model.get('doc');}); 
 +
 +        var queryPromise = pouchdb.runViewQuery({map: mapVal, reduce: reduceVal}, params);
 +        queryPromise.then(function (results) {
 +          FauxtonAPI.triggerRouteEvent('updatePreviewDocs', {rows: results.rows, ddoc: that.getCurrentDesignDoc().id, view: that.viewName});
 +        });
 +      });
 +    },
 +
 +    getCurrentDesignDoc: function () {
 +      return this.designDocSelector.getCurrentDesignDoc();
 +    },
 +    
 +    isCustomReduceEnabled: function() {
 +      return $("#reduce-function-selector").val() == "CUSTOM";
 +    },
 +
 +    mapVal: function () {
 +      if (this.mapEditor) {
 +        return this.mapEditor.getValue();
 +      }
 +
 +      return this.$('#map-function').text();
 +    },
 +
 +    reduceVal: function() {
 +      var reduceOption = this.$('#reduce-function-selector :selected').val(),
 +      reduceVal = "";
 +
 +      if (reduceOption === 'CUSTOM') {
 +        reduceVal = this.reduceEditor.getValue();
 +      } else if ( reduceOption !== 'NONE') {
 +        reduceVal = reduceOption;
 +      }
 +
 +      return reduceVal;
 +    },
 +
 +
 +    hasValidCode: function() {
 +      return _.every(["mapEditor", "reduceEditor"], function(editorName) {
 +        var editor = this[editorName];
 +        if (editorName === "reduceEditor" && ! this.isCustomReduceEnabled()) {
 +          return true;
 +        } 
 +        return editor.hadValidCode();
 +      }, this);
 +    },
 +
 +    toggleIndexNav: function (event) {
 +      var $targetId = this.$(event.target).attr('id'),
 +          $previousTab = this.$(this.$('li.active a').attr('href')),
 +          $targetTab = this.$(this.$(event.target).attr('href'));
 +
 +      if ($targetTab.attr('id') !== $previousTab.attr('id')) {
 +        $previousTab.removeAttr('style');
 +      }
 +
 +      if ($targetId === 'index-nav') {
 +        if (this.newView) { return; }
 +        var that = this;
 +        $targetTab.toggle('slow', function(){
 +           that.showEditors();
 +        });
 +      } else {
 +        $targetTab.toggle('slow');
 +      }
 +    },
 +
 +    serialize: function() {
 +      return {
 +        ddocs: this.ddocs,
 +        ddoc: this.model,
 +        ddocName: this.model.id,
 +        viewName: this.viewName,
 +        reduceFunStr: this.reduceFunStr,
 +        isCustomReduce: this.hasCustomReduce(),
 +        newView: this.newView,
 +        langTemplates: this.langTemplates.javascript
 +      };
 +    },
 +
 +    hasCustomReduce: function() {
 +      return this.reduceFunStr && ! _.contains(this.builtinReduces, this.reduceFunStr);
 +    },
 +
 +    hasReduce: function () {
 +      return this.reduceFunStr || false;
 +    },
 +
 +    createReduceEditor: function () {
 +      if (this.reduceEditor) {
 +        this.reduceEditor.remove();
 +      }
 +
 +      this.reduceEditor = new Components.Editor({
 +        editorId: "reduce-function",
 +        mode: "javascript",
 +        couchJSHINT: true
 +      });
 +      this.reduceEditor.render();
 +    },
 +
 +    beforeRender: function () {
 +
 +      if (this.newView) {
 +        this.reduceFunStr = '_sum';
 +        if (this.ddocs.length === 0) {
 +          this.model = new Documents.Doc(null, {database: this.database});
 +        } else {
 +          this.model = this.ddocs.first().dDocModel();
 +        }
 +        this.ddocID = this.model.id;
 +      } else {
 +        this.model = this.ddocs.get(this.ddocID).dDocModel();
 +        this.reduceFunStr = this.model.viewHasReduce(this.viewName);
 +        this.setView('#ddoc-info', new Views.DdocInfo({model: this.ddocInfo }));
 +      }
 +
 +      this.designDocSelector = this.setView('.design-doc-group', new Views.DesignDocSelector({
 +        collection: this.ddocs,
 +        ddocName: this.model.id,
 +        database: this.database
 +      }));
 +      
 +      this.advancedOptions = this.insertView('#query', new Views.AdvancedOptions({
 +        updateViewFn: this.updateView,
 +        previewFn: this.previewView,
 +        database: this.database,
 +        viewName: this.viewName,
 +        ddocName: this.model.id,
 +        hasReduce: this.hasReduce()
 +      }));
 +    },
 +
 +    afterRender: function() {
 +      if (this.params) {
 +        this.advancedOptions.updateFromParams(this.params);
 +      }
 +
 +      this.designDocSelector.updateDesignDoc();
 +      if (this.newView || this.showIndex) {
 +        this.showEditors();
 +        this.showIndex = false;
 +      } else {
 +        this.$('#index').hide();
 +        this.$('#index-nav').parent().removeClass('active');
 +      }
 +    },
 +
 +    showEditors: function () {
 +      this.mapEditor = new Components.Editor({
 +        editorId: "map-function",
 +        mode: "javascript",
 +        couchJSHINT: true
 +      });
 +      this.mapEditor.render();
 +
 +      if (this.hasCustomReduce()) {
 +        this.createReduceEditor();
 +      } else {
 +        $(".control-group.reduce-function").hide();
 +      }
 +
 +      if (this.newView) {
 +        this.mapEditor.setValue(this.langTemplates[this.defaultLang].map);
 +        //Use a built in view by default
 +        //this.reduceEditor.setValue(this.langTemplates[this.defaultLang].reduce);
 +      } 
 +
 +      this.mapEditor.editSaved();
 +      this.reduceEditor && this.reduceEditor.editSaved();
 +    },
 +
 +    cleanup: function () {
 +      this.mapEditor && this.mapEditor.remove();
 +      this.reduceEditor && this.reduceEditor.remove();
 +    }
 +  });
 +
 +  Views.JumpToDoc = FauxtonAPI.View.extend({
 +    template: "templates/documents/jumpdoc",
 +
 +    initialize: function (options) {
 +      this.database = options.database;
 +    },
 +
 +    events: {
 +      "submit #jump-to-doc": "jumpToDoc"
 +    },
 +
 +    jumpToDoc: function (event) {
 +      event.preventDefault();
 +      var docId = this.$('#jump-to-doc-id').val().trim();
-       FauxtonAPI.navigate('/database/' + app.mixins.safeURLName(this.database.id) +'/' + app.mixins.safeURLName(docId), {trigger: true});
++      FauxtonAPI.navigate('/database/' + app.utils.safeURLName(this.database.id) +'/' + app.utils.safeURLName(docId), {trigger: true});
 +    },
 +
 +    afterRender: function () {
 +     this.typeAhead = new Components.DocSearchTypeahead({el: '#jump-to-doc-id', database: this.database});
 +     this.typeAhead.render();
 +    }
 +  });
 +
 +  Views.Sidebar = FauxtonAPI.View.extend({
 +    template: "templates/documents/sidebar",
 +    events: {
 +      "click button#delete-database": "deleteDatabase"
 +    },
 +
 +    initialize: function(options) {
 +      this.database = options.database;
 +      if (options.ddocInfo) {
 +        this.ddocID = options.ddocInfo.id;
 +        this.currView = options.ddocInfo.currView;
 +      }
 +    },
 +
 +    deleteDatabase: function (event) {
 +      event.preventDefault();
 +
 +      var result = confirm('Are you sure you want to delete this database?');
 +
 +      if (!result) { return; }
 +      var databaseName = this.database.id;
 +      FauxtonAPI.addNotification({
 +        msg: "Deleting your database...",
 +        type: "error",
 +        clear: true
 +      });
 +
 +      this.database.destroy().then(function () {
 +        FauxtonAPI.navigate('#/_all_dbs');
 +        FauxtonAPI.addNotification({
 +          msg: 'The database ' + databaseName + ' has been deleted.',
 +          clear: true
 +        });
 +      }).fail(function (rsp, error, msg) {
 +        FauxtonAPI.addNotification({
 +          msg: 'Could not delete the database, reason ' + msg + '.',
 +          type: 'error',
 +          clear: true
 +        });
 +      });
 +    },
 +
 +    serialize: function() {
 +      var docLinks = FauxtonAPI.getExtensions('docLinks'),
 +          newLinks = FauxtonAPI.getExtensions('sidebar:newLinks'),
 +          addLinks = FauxtonAPI.getExtensions('sidebar:links'),
 +          extensionList = FauxtonAPI.getExtensions('sidebar:list');
 +      return {
 +        changes_url: '#' + this.database.url('changes'),
 +        permissions_url: '#' + this.database.url('app') + '/permissions',
 +        db_url: '#' + this.database.url('index') + '?limit=' + Databases.DocLimit,
 +        database: this.collection.database,
 +        database_url: '#' + this.database.url('app'), 
 +        docLinks: docLinks,
 +        docLimit: Databases.DocLimit,
 +        addLinks: addLinks,
 +        newLinks: newLinks,
 +        extensionList: extensionList > 0
 +      };
 +    },
 +
 +    buildIndexList: function(collection, selector, design){
 +      _.each(_.keys(collection), function(key){
 +        var selected = this.ddocID == "_design/"+design;
 +        this.insertView("ul.nav." + selector, new Views.IndexItem({
 +          ddoc: design,
 +          index: key,
 +          database: this.collection.database.id,
 +          selected: selected && key == this.currView
 +        }));
 +      }, this);
 +    },
 +
 +    beforeRender: function(manage) {
 +
 +      var sidebarListViews = FauxtonAPI.getExtensions('sidebar:list');
 +      _.each(sidebarListViews, function (view) {
 +        var extension = this.insertView('#extension-navs', view);
 +        extension.update(this.database, this.collection, this.viewName);
 +        extension.render();
 +      }, this);
 +
 +
 +      this.collection.each(function(design) {
 +        if (design.has('doc')){
 +          var ddoc = design.id.replace(/^_design\//,"");
 +          if (design.get('doc').views){
 +            this.buildIndexList(design.get('doc').views, "views", ddoc);
 +          }
 +        }
 +      }, this);
 +    },
 +
 +    afterRender: function () {
 +      if (this.selectedTab) {
 +        this.setSelectedTab(this.selectedTab);
 +      }
 +    },
 +
 +    setSelectedTab: function (selectedTab) {
 +      this.selectedTab = selectedTab;
 +      this.$('li').removeClass('active');
 +      this.$('#' + selectedTab).parent().addClass('active');
 +    }
 +  });
 +
 +  Views.Indexed = FauxtonAPI.View.extend({});
 +
 +  Views.Changes = FauxtonAPI.View.extend({
 +    template: "templates/documents/changes",
 +
 +    establish: function() {
 +      return [ this.model.changes.fetch()];
 +    },
 +
 +    serialize: function () {
 +      return {
 +        changes: this.model.changes.toJSON(),
 +        database: this.model
 +      };
 +    },
 +
 +    afterRender: function(){
 +      prettyPrint();
 +    }
 +  });
 +
 +  Views.DdocInfo = FauxtonAPI.View.extend({
 +    template: "templates/documents/ddoc_info",
 +
 +    initialize: function (options) {
 +      this.refreshTime = options.refreshTime || 5000;
 +      this.listenTo(this.model, 'change', this.render);
 +    },
 +
 +    serialize: function () {
 +      return {
 +        view_index: this.model.get('view_index')
 +      };
 +    },
 +
 +    afterRender: function () {
 +      this.startRefreshInterval();
 +    },
 +
 +    startRefreshInterval: function () {
 +      var model = this.model;
 +
 +      // Interval already set
 +      if (this.intervalId) { return ; }
 +
 +      this.intervalId = setInterval(function () {
 +        model.fetch();
 +      }, this.refreshTime);
 +    },
 +
 +    stopRefreshInterval: function () {
 +      clearInterval(this.intervalId);
 +    },
 +
 +    cleanup: function () {
 +      this.stopRefreshInterval();
 +    }
 +  });
 +
 +  Documents.Views = Views;
 +  return Documents;
 +});

http://git-wip-us.apache.org/repos/asf/couchdb/blob/752819c1/src/fauxton/app/addons/logs/assets/less/logs.less
----------------------------------------------------------------------
diff --cc src/fauxton/app/addons/logs/assets/less/logs.less
index 0000000,0000000..e50f903
new file mode 100644
--- /dev/null
+++ b/src/fauxton/app/addons/logs/assets/less/logs.less
@@@ -1,0 -1,0 +1,24 @@@
++/*  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.
++ */
++
++#log-sidebar {
++  
++  ul {
++    margin-left: 0px;
++    list-style: none;
++  }
++
++  .remove-filter {
++     opacity: 0.2;
++  }
++}

http://git-wip-us.apache.org/repos/asf/couchdb/blob/752819c1/src/fauxton/app/addons/verifyinstall/resources.js
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/couchdb/blob/752819c1/src/fauxton/app/api.js
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/couchdb/blob/752819c1/src/fauxton/app/app.js
----------------------------------------------------------------------
diff --cc src/fauxton/app/app.js
index 9ac5bc2,98714ab..5325f77
--- a/src/fauxton/app/app.js
+++ b/src/fauxton/app/app.js
@@@ -18,22 -15,18 +18,22 @@@ define(
    "jquery",
    "lodash",
    "backbone",
 +  "bootstrap",
  
    "helpers",
--  "mixins",
++  "utils",
 +  // Modules
 +  "resizeColumns",
  
 -  // Plugins.
 +   // Plugins.
    "plugins/backbone.layoutmanager",
    "plugins/jquery.form"
 +
  ],
  
- function(app, $, _, Backbone, Bootstrap, Helpers, Mixins, resizeColumns) {
 -function($, _, Backbone, Helpers, Mixins) {
++function(app, $, _, Backbone, Bootstrap, Helpers, Utils, resizeColumns) {
  
 -  // Make sure we have a console.log
 +   // Make sure we have a console.log
    if (typeof console == "undefined") {
      console = {
        log: function(){}
@@@ -41,51 -34,23 +41,51 @@@
    }
  
    // Provide a global location to place configuration settings and module
 -  // creation.
 -  var app = {
 -    // The root path to run the application.
 -    root: "/",
 -    version: "0.0.1",
 -    mixins: Mixins,
 -    // move this to here otherwise every once in a while,
 -    // the footer fails to configure as the url for it is not configured.
 -    // Having the host declared here fixes it
 -    host: "../.."
 -  };
 -  
 -  // Kind of hacky - add this in so that Fauxton still works as a couchapp,
 -  // we should look at moving the app.host configuration to grunt
 -  if (window.location.href.match(/_design/)) {
 -    app.host = window.location.protocol + "//" + window.location.host;
 -  }
 +  // creation also mix in Backbone.Events
 +  _.extend(app, Backbone.Events, {
-     mixins: Mixins,
++    utils: Utils,
 +
 +    renderView: function(baseView, selector, view, options, callback) {
 +      baseView.setView(selector, new view(options)).render().then(callback);
 +    },
 +
 +    // Create a custom object with a nested Views object.
 +    module: function(additionalProps) {
 +      return _.extend({ Views: {} }, additionalProps);
 +    },
 +
 +    // Thanks to: http://stackoverflow.com/a/2880929
 +    getParams: function(queryString) {
 +      if (queryString) {
 +        // I think this could be combined into one if
 +        if (queryString.substring(0,1) === "?") {
 +          queryString = queryString.substring(1);
 +        } else if (queryString.indexOf('?') > -1) {
 +          queryString = queryString.split('?')[1];
 +        }
 +      }
 +      var hash = window.location.hash.split('?')[1];
 +      queryString = queryString || hash || window.location.search.substring(1);
 +      var match,
 +      urlParams = {},
 +      pl     = /\+/g,  // Regex for replacing addition symbol with a space
 +      search = /([^&=]+)=?([^&]*)/g,
 +      decode = function (s) { return decodeURIComponent(s.replace(pl, " ")); },
 +      query  = queryString;
 +
 +      if (queryString) {
 +        while ((match = search.exec(query))) {
 +          urlParams[decode(match[1])] = decode(match[2]);
 +        }
 +      }
 +
 +      return urlParams;
 +    }
 +  });
 +
 +  //resizeAnimation
 +  app.resizeColumns = new resizeColumns({});
 +  app.resizeColumns.onResizeHandler();
  
    // Localize or create a new JavaScript Template object.
    var JST = window.JST = window.JST || {};

http://git-wip-us.apache.org/repos/asf/couchdb/blob/752819c1/src/fauxton/app/mixins.js
----------------------------------------------------------------------
diff --cc src/fauxton/app/mixins.js
index 15af3ee,b17e15c..0000000
deleted file mode 100644,100644
--- a/src/fauxton/app/mixins.js
+++ /dev/null
@@@ -1,65 -1,56 +1,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.
--
--
--// This file creates a set of helper functions that will be loaded for all html
--// templates. These functions should be self contained and not rely on any 
--// external dependencies as they are loaded prior to the application. We may
--// want to change this later, but for now this should be thought of as a
--// "purely functional" helper system.
--
--
--define([
--  "jquery",
--  "lodash"
--],
--
--function($, _ ) {
--
--  var mixins = {};
--
--  var onWindowResize = {};
--   
--  mixins.addWindowResize = function(fun, key){
--    onWindowResize[key]=fun;
--    // You shouldn't need to call it here. Just define it at startup and each time it will loop 
--    // through all the functions in the hash.
--    //app.initWindowResize();
--  };
--   
--  mixins.removeWindowResize = function(key){
--    delete onWindowResize[key];
--    mixins.initWindowResize();
--  };
--   
--  mixins.initWindowResize = function(){
--  //when calling this it should be overriding what was called previously
--    window.onresize = function(e) {
--       // could do this instead of the above for loop
--      _.each(onWindowResize, function (fn) {
--        fn();
--      });
--    };
--  };
--
-   mixins.removeSpecialCharacters = function(name){
-     return name.replace(/[^\w\s]/gi,"");
-   };
- 
-   mixins.safeURLName = function(name){
-     var checkforBad = name.match(/[\$\-/_,+-]/g);
-     return (checkforBad !== null)?encodeURIComponent(name):name;
-   };
- 
--  return mixins;
--});
--

http://git-wip-us.apache.org/repos/asf/couchdb/blob/752819c1/src/fauxton/app/resizeColumns.js
----------------------------------------------------------------------
diff --cc src/fauxton/app/resizeColumns.js
index 9cf7115,9cf7115..bb50767
--- a/src/fauxton/app/resizeColumns.js
+++ b/src/fauxton/app/resizeColumns.js
@@@ -18,10 -18,10 +18,10 @@@
  // "purely functional" helper system.
  
  define([
--  "mixins"
++  "utils"
  ],
  
--function(mixins) {
++function(utils) {
  
    var Resize = function(options){
      this.options = options;
@@@ -42,8 -42,8 +42,8 @@@
        var that = this;
        //add throttler :) 
        this.lazyLayout = _.debounce(that.onResizeHandler, 300).bind(this);
--      mixins.addWindowResize(this.lazyLayout,"animation");
--      mixins.initWindowResize();
++      utils.addWindowResize(this.lazyLayout,"animation");
++      utils.initWindowResize();
        this.onResizeHandler();
      },
      updateOptions:function(options){
@@@ -52,7 -52,7 +52,7 @@@
        this.options.selectorElements = options.selectorElements || ".window-resizeable";
      },
      turnOff:function(){
--      mixins.removeWindowResize("animation");
++      utils.removeWindowResize("animation");
      },
      cleanupCallback: function(){
        this.callback = null;

http://git-wip-us.apache.org/repos/asf/couchdb/blob/752819c1/src/fauxton/app/utils.js
----------------------------------------------------------------------
diff --cc src/fauxton/app/utils.js
index 0000000,0000000..3b91906
new file mode 100644
--- /dev/null
+++ b/src/fauxton/app/utils.js
@@@ -1,0 -1,0 +1,65 @@@
++// 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.
++
++
++// This file creates a set of helper functions that will be loaded for all html
++// templates. These functions should be self contained and not rely on any 
++// external dependencies as they are loaded prior to the application. We may
++// want to change this later, but for now this should be thought of as a
++// "purely functional" helper system.
++
++
++define([
++  "jquery",
++  "lodash"
++],
++
++function($, _ ) {
++
++  var utils = {};
++
++  var onWindowResize = {};
++   
++  utils.addWindowResize = function(fun, key){
++    onWindowResize[key]=fun;
++    // You shouldn't need to call it here. Just define it at startup and each time it will loop 
++    // through all the functions in the hash.
++    //app.initWindowResize();
++  };
++   
++  utils.removeWindowResize = function(key){
++    delete onWindowResize[key];
++    utils.initWindowResize();
++  };
++   
++  utils.initWindowResize = function(){
++  //when calling this it should be overriding what was called previously
++    window.onresize = function(e) {
++       // could do this instead of the above for loop
++      _.each(onWindowResize, function (fn) {
++        fn();
++      });
++    };
++  };
++
++  utils.removeSpecialCharacters = function(name){
++    return name.replace(/[^\w\s]/gi,"");
++  };
++
++  utils.safeURLName = function(name){
++    var checkforBad = name.match(/[\$\-/_,+-]/g);
++    return (checkforBad !== null)?encodeURIComponent(name):name;
++  };
++
++  return utils;
++});
++

http://git-wip-us.apache.org/repos/asf/couchdb/blob/752819c1/src/fauxton/assets/less/config.less
----------------------------------------------------------------------
diff --cc src/fauxton/assets/less/config.less
index fe03796,fe03796..0000000
deleted file mode 100644,100644
--- a/src/fauxton/assets/less/config.less
+++ /dev/null
@@@ -1,46 -1,46 +1,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.
-- */
--
--.config-item {
--  height: 41px;
--
--  .edit-button {
--    float: right;
--    .btn;
--    .btn-mini;
--    display:none;
--  }
--
--  td:hover .edit-button {
--    display: block;
--  }
--
--  .value-input {
--    width: 98%;
--  }
--
--  #delete-value {
--    cursor: pointer;
--  }
--}
--
--.button-margin {
--  margin-bottom: 15px;
--}
--
--#add-section-modal {
--  width: 400px;
--}
--
--
--

http://git-wip-us.apache.org/repos/asf/couchdb/blob/752819c1/src/fauxton/assets/less/database.less
----------------------------------------------------------------------
diff --cc src/fauxton/assets/less/database.less
index 377b136,6f2ae92..0000000
deleted file mode 100644,100644
--- a/src/fauxton/assets/less/database.less
+++ /dev/null
@@@ -1,245 -1,238 +1,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.
-- */
--
--/* =database
--   ---------------------------------------------------------------------- */
--#db-tools {
--    position: absolute;
--    top: -7px;
--    right: 0;
--    width: 390px;
--
--    .btn-group {
--        position: absolute;
--        left: 0;
--        top: 6px;
--    }
--
--    form {
--        position: absolute;
--        right: 0;
--        top: 0;
--    }
--}
--
--.tools .nav {
--    margin-bottom: 10px;
--}
--
--#sidenav {
--    padding-top: 10px;
--
--    h3 {
--        margin: 10px 0;
--    }
--
--    li a span.divider {
--        background: none;
--        color: #ccc;
--        padding: 0 2px;
--    }
--
--    li.nav-header a {
--        display: inline
--    }
--
--    div.btn-group {
--        display: inline-block;
--    }
--
--    li.nav-header, #sidenav li a {
--        padding-left: 4px;
--    }
--
--    li.active a {
--        background-color: #ddd;
--        color: #333;
--        text-shadow: none;
--    }
--}
--
--.edit {
--    display: none;
--
--    form {
--        margin-bottom: 0;
--    }
--
--    h3 {
--        border-bottom: 1px solid #ccc;
--        font-size: 100%;
--        line-height: 1;
--        margin-bottom: 18px;
--    }
--
--    textarea {
--        height: 100px;
--        width: 95%;
--    }
--
--    .btn-toolbar {
--        margin-bottom: 0;
--    }
--
--    .preview {
--        width: 100px;
--    }
--
--    .save {
--    }
--}
--
--#new-view-index {
--    .confirm {
--        display: none;
--    }
--
--    .confirm .progress {
--        display: none;
--        margin: 20px;
--    }
--
--    textarea {
--        height: 100px;
--        width: 95%;
--    }
--}
--
--.view {
--    display: none;
--
--    .result-tools {
--        float: left;
--        width: 100%;
--        margin-bottom: 10px;
--    }
--
--    table td div  {
--        position: relative;
--    }
--
--    table td div div {
--        display: none;
--        line-height: 1;
--        position: absolute;
--        right: 4px;
--        top: 4px;
--    }
--
--    table td div:hover div a.edits {
--        padding-left: 16px;
--        padding-right: 16px;
--    }
--
--    table td div:hover div {
--        display: block;
--    }
--
--}
--.view.show {
--    display: block;
--}
--.view.show.hidden-by-params {
--    display: none;
--}
--#database .view table tr td {
--    padding: 0;
--}
--
--.loading {display: none;}
--
--.view-request-duration {
--  padding-right: 10px;
--  float: right;
--}
--
--table.active-tasks{
--    th {
--        cursor: pointer;
--    }
--}
--
--.well{
--    .row-fluid{
--        margin: 0;
--    }
--    .row-fluid .row-fluid:last-child .well-item {
--        border: none;
--    }
--    .well-item{
--        color: #666;
--        font-size: 12px;
--        border-bottom: 1px solid #e5e5e5;
--        padding: 8px 4px;
--        strong {
--            font-size: 16px;
--        }  
--    } 
--}
--
--
--#doc {
--    .dropdown-menu{
--        width: auto;
--    }
--}
--// #tabs {
--//     height: 40px;
--// }
--
--.databases{
--    a.db-actions,
--    a.db-actions:visited{
--        color: @red; 
--        border: 1px solid #e3e3e3;
--        padding: 5px 7px;
--        .border-radius(6px);
--        text-decoration: none;
--        font-size: 19px;
--    }
--}
--.btn-group{
--    ul.dropdown-menu li a:before{
--        margin-right: 10px;
--    }
--}
--
--.design-doc-group{
--    .span3 { margin: 0;}
--    #new-ddoc-section {
--        margin-top: 10px;
--        label{ width: 100px}
--        .controls{
--            margin-left: 100px;
--        }
--    }
--}
--table#changes-table {
--
--  #changes {
--    width: 50%;
--  }
--
--  #seq, #deleted {
--    width: 5%;
--  }
--
--}
--
- .doc-editor-buttons {
-     margin-bottom: 15px;
-     a.button.btn-large.gray {
-         padding: 9px 10px;
-         vertical-align: middle;
-     }
- }

http://git-wip-us.apache.org/repos/asf/couchdb/blob/752819c1/src/fauxton/assets/less/fauxton.less
----------------------------------------------------------------------
diff --cc src/fauxton/assets/less/fauxton.less
index 510c3c1,252391e..d41780a
--- a/src/fauxton/assets/less/fauxton.less
+++ b/src/fauxton/assets/less/fauxton.less
@@@ -19,10 -19,10 +19,7 @@@
  @import "bootstrap/bootstrap.less";
  @import "bootstrap/mixins.less";
  @import "variables.less";
--@import "config.less";
--@import "logs.less";
  @import "prettyprint.less";
--@import "database.less";
  @import "icons.less";
  
  

http://git-wip-us.apache.org/repos/asf/couchdb/blob/752819c1/src/fauxton/assets/less/logs.less
----------------------------------------------------------------------
diff --cc src/fauxton/assets/less/logs.less
index e50f903,e50f903..0000000
deleted file mode 100644,100644
--- a/src/fauxton/assets/less/logs.less
+++ /dev/null
@@@ -1,24 -1,24 +1,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.
-- */
--
--#log-sidebar {
--  
--  ul {
--    margin-left: 0px;
--    list-style: none;
--  }
--
--  .remove-filter {
--     opacity: 0.2;
--  }
--}


Mime
View raw message