You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@couchdb.apache.org by benkeen <gi...@git.apache.org> on 2016/02/19 23:27:31 UTC

[GitHub] couchdb-fauxton pull request: [WIP] Update Views

GitHub user benkeen opened a pull request:

    https://github.com/apache/couchdb-fauxton/pull/651

    [WIP] Update Views

    This is a big update to the Views pages.
    - now uses standard 2 panel layout for adding/editing/viewing
    Views (includes the sidebar)
    - New menu added to all Views, containing [Edit, Clone, Delete]
    options. Clone and Delete are their own modals. This modal is
    extensible, so can be used for different types of indexes added
    via extensions.
    - sidebar now properly selects views and highlights them to
    show current location + view.
    - Renaming a view no longer creates a second view, just renames
    it. The clone feature lets you copy/clone a View.
    - cog icon in header replaced with a 3-dot thing.
    
    N.B. the new menu uses React Bootstrap so it's very similar
    but not identical to our current menu dropdowns. The latter
    will be replaced in subsquent PRs.

You can merge this pull request into a Git repository by running:

    $ git pull https://github.com/benkeen/couchdb-fauxton view-updates

Alternatively you can review and apply these changes as the patch at:

    https://github.com/apache/couchdb-fauxton/pull/651.patch

To close this pull request, make a commit to your master/trunk branch
with (at least) the following in the commit message:

    This closes #651
    
----
commit 604b0d4b4550bc47acfc742b8c5b3e5a4f949b83
Author: Ben Keen <be...@gmail.com>
Date:   2016-02-18T01:10:42Z

    Update Views
    
    This is a big update to the Views pages.
    - now uses standard 2 panel layout for adding/editing/viewing
    Views (includes the sidebar)
    - New menu added to all Views, containing [Edit, Clone, Delete]
    options. Clone and Delete are their own modals. This modal is
    extensible, so can be used for different types of indexes added
    via extensions.
    - sidebar now properly selects views and highlights them to
    show current location + view.
    - Renaming a view no longer creates a second view, just renames
    it. The clone feature lets you copy/clone a View.
    - cog icon in header replaced with a 3-dot thing.
    
    N.B. the new menu uses React Bootstrap so it's very similar
    but not identical to our current menu dropdowns. The latter
    will be replaced in subsquent PRs.

----


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] couchdb-fauxton pull request: Update Views

Posted by robertkowalski <gi...@git.apache.org>.
Github user robertkowalski commented on a diff in the pull request:

    https://github.com/apache/couchdb-fauxton/pull/651#discussion_r55556388
  
    --- Diff: app/addons/documents/routes-index-editor.js ---
    @@ -28,40 +28,53 @@ define([
       'addons/documents/pagination/pagination.react',
       'addons/documents/header/header.react',
       'addons/documents/header/header.actions',
    +  'addons/documents/sidebar/actions'
     ],
     
     function (app, FauxtonAPI, Helpers, BaseRoute, Documents, IndexEditorComponents, ActionsIndexEditor,
               Databases, Components, IndexResultsStores, IndexResultsActions,
    -          IndexResultsComponents, ReactPagination, ReactHeader, ReactHeaderActions) {
    +          IndexResultsComponents, ReactPagination, ReactHeader, ReactHeaderActions, SidebarActions) {
     
     
       var IndexEditorAndResults = BaseRoute.extend({
    -    layout: 'two_pane',
    +    layout: 'with_tabs_sidebar',
         routes: {
    -      'database/:database/new_view': 'newViewEditor',
    -      'database/:database/new_view/:designDoc': 'newViewEditor',
    +      'database/:database/new_view': {
    +        route: 'createView',
    +        roles: ['fx_loggedIn']
    +      },
    +      'database/:database/new_view/:designDoc': {
    +        route: 'createView',
    +        roles: ['fx_loggedIn']
    +      },
           'database/:database/_design/:ddoc/_view/:view': {
    -        route: 'viewFn',
    +        route: 'showView',
    +        roles: ['fx_loggedIn']
    +      },
    +      'database/:database/_design/:ddoc/_view/:view/edit': {
    --- End diff --
    
    cool ok, makes sense


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] couchdb-fauxton pull request: Update Views

Posted by benkeen <gi...@git.apache.org>.
Github user benkeen commented on a diff in the pull request:

    https://github.com/apache/couchdb-fauxton/pull/651#discussion_r55598712
  
    --- Diff: app/addons/documents/sidebar/sidebar.react.jsx ---
    @@ -110,38 +120,92 @@ function (app, FauxtonAPI, React, ReactDOM, Stores, Actions,
             </ul>
           );
         }
    -
       });
     
    +
       var IndexSection = React.createClass({
     
         propTypes: {
           urlNamespace: React.PropTypes.string.isRequired,
    -      databaseName: React.PropTypes.string.isRequired,
    +      indexLabel: React.PropTypes.string.isRequired,
    +      database: React.PropTypes.object.isRequired,
           designDocName: React.PropTypes.string.isRequired,
           items: React.PropTypes.array.isRequired,
           isExpanded: React.PropTypes.bool.isRequired,
    -      selectedIndex: React.PropTypes.string.isRequired
    +      selectedIndex: React.PropTypes.string.isRequired,
    +      onDelete: React.PropTypes.func.isRequired,
    +      onClone: React.PropTypes.func.isRequired
         },
     
         createItems: function () {
    -      return _.map(this.props.items, function (index, key) {
    -        var href = FauxtonAPI.urls(this.props.urlNamespace, 'app', this.props.databaseName, this.props.designDocName);
    -        var className = (this.props.selectedIndex === index) ? 'active' : '';
    +
    +      // sort the indexes alphabetically
    +      var sortedItems = this.props.items.sort();
    +
    +      return _.map(sortedItems, function (indexName, index) {
    +        var href = FauxtonAPI.urls(this.props.urlNamespace, 'app', this.props.database.id, this.props.designDocName);
    +        var className = (this.props.selectedIndex === indexName) ? 'active' : '';
     
             return (
    -          <li className={className} key={key}>
    +          <li className={className} key={index}>
                 <a
    -              id={this.props.designDocName + '_' + index}
    -              href={"#/" + href + index}
    +              id={this.props.designDocName + '_' + indexName}
    +              href={"#/" + href + indexName}
                   className="toggle-view">
    -              {index}
    +              {indexName}
                 </a>
    +
    +            <OverlayTrigger
    +              ref="indexMenu"
    +              trigger="click"
    +              placement="bottom"
    +              rootClose={true}
    +              overlay={
    +                <Popover id="index-menu-component-popover">
    +                  <ul>
    +                    <li onClick={this.indexAction.bind(this, 'edit', { indexName: indexName, onEdit: this.props.onEdit })}>
    +                      <span className="fonticon fonticon-file-code-o"></span>
    +                      Edit
    +                    </li>
    +                    <li onClick={this.indexAction.bind(this, 'clone', { indexName: indexName, onClone: this.props.onClone })}>
    +                      <span className="fonticon fonticon-files-o"></span>
    +                      Clone
    +                    </li>
    +                    <li onClick={this.indexAction.bind(this, 'delete', { indexName: indexName, onDelete: this.props.onDelete })}>
    +                      <span className="fonticon fonticon-trash"></span>
    +                      Delete
    +                    </li>
    +                  </ul>
    +                </Popover>
    +              }>
    +              <span className="index-menu-toggle fonticon fonticon-wrench2"></span>
    +            </OverlayTrigger>
    +
               </li>
             );
           }, this);
         },
     
    +    indexAction: function (action, params, e) {
    +      e.preventDefault();
    +
    +      // bah. We need to close the overlay trigger whenever the user clicks on anything inside. The
    +      // component doesn't have that functionality, so we simulate a click outside of it :(
    +      $('body').trigger('click');
    --- End diff --
    
    Good grief, you're right. I swore I tried that, honest, guv'nor!


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] couchdb-fauxton pull request: Update Views

Posted by benkeen <gi...@git.apache.org>.
Github user benkeen commented on the pull request:

    https://github.com/apache/couchdb-fauxton/pull/651#issuecomment-194537278
  
    Thanks, @robertkowalski! All fixed up.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] couchdb-fauxton pull request: Update Views

Posted by benkeen <gi...@git.apache.org>.
Github user benkeen commented on the pull request:

    https://github.com/apache/couchdb-fauxton/pull/651#issuecomment-195535925
  
    Thanks, @robertkowalski! All fixed up. Turns out the workaround for toggling the location of the menu (top/bottom) wasn't anywhere near as hacky as I thought. It just examines the DOM node of the row to find out how close to the bottom of the page it is. Very smooth, actually. 


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] couchdb-fauxton pull request: Update Views

Posted by benkeen <gi...@git.apache.org>.
Github user benkeen commented on a diff in the pull request:

    https://github.com/apache/couchdb-fauxton/pull/651#discussion_r55554632
  
    --- Diff: app/addons/documents/routes-index-editor.js ---
    @@ -28,40 +28,53 @@ define([
       'addons/documents/pagination/pagination.react',
       'addons/documents/header/header.react',
       'addons/documents/header/header.actions',
    +  'addons/documents/sidebar/actions'
     ],
     
     function (app, FauxtonAPI, Helpers, BaseRoute, Documents, IndexEditorComponents, ActionsIndexEditor,
               Databases, Components, IndexResultsStores, IndexResultsActions,
    -          IndexResultsComponents, ReactPagination, ReactHeader, ReactHeaderActions) {
    +          IndexResultsComponents, ReactPagination, ReactHeader, ReactHeaderActions, SidebarActions) {
     
     
       var IndexEditorAndResults = BaseRoute.extend({
    -    layout: 'two_pane',
    +    layout: 'with_tabs_sidebar',
         routes: {
    -      'database/:database/new_view': 'newViewEditor',
    -      'database/:database/new_view/:designDoc': 'newViewEditor',
    +      'database/:database/new_view': {
    +        route: 'createView',
    +        roles: ['fx_loggedIn']
    +      },
    +      'database/:database/new_view/:designDoc': {
    +        route: 'createView',
    +        roles: ['fx_loggedIn']
    +      },
           'database/:database/_design/:ddoc/_view/:view': {
    -        route: 'viewFn',
    +        route: 'showView',
    +        roles: ['fx_loggedIn']
    +      },
    +      'database/:database/_design/:ddoc/_view/:view/edit': {
    --- End diff --
    
    Hmm, good point. How do you suggest handling this? The edit page are separate. I guess I can keep the same URL for both, and just handle routing exclusively in the JS... but having a way to link directly to it through a URL string alone is kinda convenient. (Query string param...? Seems klutzy). 


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] couchdb-fauxton pull request: Update Views

Posted by robertkowalski <gi...@git.apache.org>.
Github user robertkowalski commented on a diff in the pull request:

    https://github.com/apache/couchdb-fauxton/pull/651#discussion_r55552118
  
    --- Diff: app/addons/documents/index-editor/actions.js ---
    @@ -15,142 +15,282 @@ define([
       'api',
       'addons/documents/resources',
       'addons/documents/index-editor/actiontypes',
    -  'addons/documents/index-results/actions'
    +  'addons/documents/index-results/actions',
    +  'addons/documents/sidebar/actions',
    +  'addons/documents/sidebar/actiontypes'
     ],
    -function (app, FauxtonAPI, Documents, ActionTypes, IndexResultsActions) {
    +function (app, FauxtonAPI, Documents, ActionTypes, IndexResultsActions, SidebarActions, SidebarActionTypes) {
     
    -  var ActionHelpers = {
    -    findDesignDoc: function (designDocs, designDocId) {
    -      return _.find(designDocs, function (doc) {
    -        return doc.id === designDocId;
    -      }).dDocModel();
    -    }
    -  };
     
    +  function selectReduceChanged (reduceOption) {
    +    FauxtonAPI.dispatch({
    +      type: ActionTypes.SELECT_REDUCE_CHANGE,
    +      reduceSelectedOption: reduceOption
    +    });
    +  }
     
    -  return {
    -    //helpers are added here for use in testing actions
    -    helpers: ActionHelpers,
    +  function changeViewName (name) {
    +    FauxtonAPI.dispatch({
    +      type: ActionTypes.VIEW_NAME_CHANGE,
    +      name: name
    +    });
    +  }
     
    -    selectReduceChanged: function (reduceOption) {
    -      FauxtonAPI.dispatch({
    -        type: ActionTypes.SELECT_REDUCE_CHANGE,
    -        reduceSelectedOption: reduceOption
    -      });
    -    },
    +  function editIndex (options) {
    +    FauxtonAPI.dispatch({
    +      type: ActionTypes.EDIT_INDEX,
    +      options: options
    +    });
    +  }
     
    -    changeViewName: function (name) {
    -      FauxtonAPI.dispatch({
    -        type: ActionTypes.VIEW_NAME_CHANGE,
    -        name: name
    -      });
    -    },
    +  function clearIndex () {
    +    FauxtonAPI.dispatch({ type: ActionTypes.CLEAR_INDEX });
    +  }
     
    -    editIndex: function (options) {
    -      FauxtonAPI.dispatch({
    -        type: ActionTypes.EDIT_INDEX,
    -        options: options
    -      });
    -    },
    +  function fetchDesignDocsBeforeEdit (options) {
    +    options.designDocs.fetch({reset: true}).then(function () {
    +      this.editIndex(options);
    +    }.bind(this));
    +  }
     
    -    clearIndex: function () {
    -      FauxtonAPI.dispatch({ type: ActionTypes.CLEAR_INDEX });
    -    },
    +  function saveView (viewInfo) {
    +    var designDoc = viewInfo.designDoc;
    +    designDoc.setDdocView(viewInfo.viewName, viewInfo.map, viewInfo.reduce);
     
    -    fetchDesignDocsBeforeEdit: function (options) {
    -      options.designDocs.fetch({reset: true}).then(function () {
    -        this.editIndex(options);
    -      }.bind(this));
    -    },
    +    FauxtonAPI.addNotification({
    +      msg: 'Saving View...',
    +      type: 'info',
    +      clear: true
    +    });
     
    -    saveView: function (viewInfo) {
    -      var designDoc = viewInfo.designDoc;
    -      designDoc.setDdocView(viewInfo.viewName, viewInfo.map, viewInfo.reduce);
    +    // if the view name just changed and it's in the SAME design doc, remove the old one before saving the doc
    +    if (viewInfo.originalDesignDocName === viewInfo.designDocId && viewInfo.originalViewName !== viewInfo.viewName) {
    +      designDoc.removeDdocView(viewInfo.originalViewName);
    +    }
     
    +    designDoc.save().then(function () {
           FauxtonAPI.addNotification({
    -        msg:  "Saving View...",
    -        type: "info",
    +        msg: 'View Saved.',
    +        type: 'success',
             clear: true
           });
     
    -      designDoc.save().then(function () {
    -        FauxtonAPI.addNotification({
    -          msg:  "View Saved.",
    -          type: "success",
    -          clear: true
    -        });
    +      // if the user just saved the view to a different design doc, remove the view from the old design doc and
    +      // delete if it's empty
    +      if (viewInfo.originalDesignDocName !== viewInfo.designDocId) {
    +        var oldDesignDoc = findDesignDoc(viewInfo.designDocs, viewInfo.originalDesignDocName);
    +        safeDeleteView(oldDesignDoc, viewInfo.designDocs, viewInfo.database, viewInfo.originalViewName);
    +      }
     
    -        if (_.any([viewInfo.designDocChanged, viewInfo.hasViewNameChanged, viewInfo.newDesignDoc, viewInfo.newView])) {
    -          FauxtonAPI.dispatch({ type: ActionTypes.VIEW_SAVED });
    -          var fragment = FauxtonAPI.urls('view', 'showNewlySavedView', viewInfo.database.safeID(), designDoc.safeID(), app.utils.safeURLName(viewInfo.viewName));
    -          FauxtonAPI.navigate(fragment, { trigger: true });
    -        } else {
    -          this.updateDesignDoc(designDoc);
    -        }
    -
    -        // this can be removed after the Views are on their own page
    -        IndexResultsActions.reloadResultsList();
    -      }.bind(this));
    -    },
    +      if (viewInfo.designDocId === 'new-doc') {
    +        addDesignDoc(designDoc);
    +      }
     
    -    updateDesignDoc: function (designDoc) {
    -      FauxtonAPI.dispatch({
    -        type: ActionTypes.VIEW_UPDATE_DESIGN_DOC,
    -        designDoc: designDoc.toJSON()
    -      });
    -    },
    +      FauxtonAPI.dispatch({ type: ActionTypes.VIEW_SAVED });
    +      var fragment = FauxtonAPI.urls('view', 'showView', viewInfo.database.safeID(), designDoc.safeID(), app.utils.safeURLName(viewInfo.viewName));
    +      FauxtonAPI.navigate(fragment, { trigger: true });
    +    });
    +  }
     
    -    deleteView: function (options) {
    -      var viewName = options.viewName;
    -      var database = options.database;
    -      var designDoc = ActionHelpers.findDesignDoc(options.designDocs, options.designDocId);
    -      var promise;
    +  function addDesignDoc (designDoc) {
    +    FauxtonAPI.dispatch({
    +      type: ActionTypes.VIEW_ADD_DESIGN_DOC,
    +      designDoc: designDoc.toJSON()
    +    });
    +  }
     
    -      designDoc.removeDdocView(viewName);
    +  function deleteView (options) {
     
    -      if (designDoc.hasViews()) {
    -        promise = designDoc.save();
    -      } else {
    -        promise = designDoc.destroy();
    -      }
    +    var onSuccess = function () {
     
    -      promise.then(function () {
    -        var url = FauxtonAPI.urls('allDocs', 'app', database.safeID(), '?limit=' + FauxtonAPI.constants.DATABASES.DOCUMENT_LIMIT);
    +      // if the user was on the index that was just deleted, redirect them back to all docs
    +      if (options.isOnIndex) {
    +        var url = FauxtonAPI.urls('allDocs', 'app', options.database.safeID(), '?limit=' + FauxtonAPI.constants.DATABASES.DOCUMENT_LIMIT);
             FauxtonAPI.navigate(url);
    -        FauxtonAPI.triggerRouteEvent('reloadDesignDocs');
    -      });
    -    },
    +      }
    +
    +      FauxtonAPI.triggerRouteEvent('reloadDesignDocs');
     
    -    updateMapCode: function (code) {
    -      FauxtonAPI.dispatch({
    -        type: ActionTypes.VIEW_UPDATE_MAP_CODE,
    -        code: code
    +      FauxtonAPI.addNotification({
    +        msg: 'The <code>' + options.indexName + '</code> view has been deleted.',
    --- End diff --
    
    we need to escape `options.indexName` to make sure to open no XSS vector
    
    something like
    ```js
    'The <code>' + _.escape(options.indexName) + '</code> view has been deleted.',
    ```


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] couchdb-fauxton pull request: Update Views

Posted by robertkowalski <gi...@git.apache.org>.
Github user robertkowalski commented on the pull request:

    https://github.com/apache/couchdb-fauxton/pull/651#issuecomment-195316646
  
    https://cloudup.com/cAczX5u4-sD


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] couchdb-fauxton pull request: Update Views

Posted by benkeen <gi...@git.apache.org>.
Github user benkeen commented on a diff in the pull request:

    https://github.com/apache/couchdb-fauxton/pull/651#discussion_r55598756
  
    --- Diff: app/addons/documents/sidebar/sidebar.react.jsx ---
    @@ -110,38 +120,92 @@ function (app, FauxtonAPI, React, ReactDOM, Stores, Actions,
             </ul>
           );
         }
    -
       });
     
    +
       var IndexSection = React.createClass({
     
         propTypes: {
           urlNamespace: React.PropTypes.string.isRequired,
    -      databaseName: React.PropTypes.string.isRequired,
    +      indexLabel: React.PropTypes.string.isRequired,
    +      database: React.PropTypes.object.isRequired,
           designDocName: React.PropTypes.string.isRequired,
           items: React.PropTypes.array.isRequired,
           isExpanded: React.PropTypes.bool.isRequired,
    -      selectedIndex: React.PropTypes.string.isRequired
    +      selectedIndex: React.PropTypes.string.isRequired,
    +      onDelete: React.PropTypes.func.isRequired,
    +      onClone: React.PropTypes.func.isRequired
         },
     
         createItems: function () {
    -      return _.map(this.props.items, function (index, key) {
    -        var href = FauxtonAPI.urls(this.props.urlNamespace, 'app', this.props.databaseName, this.props.designDocName);
    -        var className = (this.props.selectedIndex === index) ? 'active' : '';
    +
    +      // sort the indexes alphabetically
    +      var sortedItems = this.props.items.sort();
    +
    +      return _.map(sortedItems, function (indexName, index) {
    +        var href = FauxtonAPI.urls(this.props.urlNamespace, 'app', this.props.database.id, this.props.designDocName);
    +        var className = (this.props.selectedIndex === indexName) ? 'active' : '';
     
             return (
    -          <li className={className} key={key}>
    +          <li className={className} key={index}>
                 <a
    -              id={this.props.designDocName + '_' + index}
    -              href={"#/" + href + index}
    +              id={this.props.designDocName + '_' + indexName}
    +              href={"#/" + href + indexName}
                   className="toggle-view">
    -              {index}
    +              {indexName}
                 </a>
    +
    +            <OverlayTrigger
    +              ref="indexMenu"
    +              trigger="click"
    +              placement="bottom"
    +              rootClose={true}
    +              overlay={
    +                <Popover id="index-menu-component-popover">
    +                  <ul>
    +                    <li onClick={this.indexAction.bind(this, 'edit', { indexName: indexName, onEdit: this.props.onEdit })}>
    +                      <span className="fonticon fonticon-file-code-o"></span>
    +                      Edit
    +                    </li>
    +                    <li onClick={this.indexAction.bind(this, 'clone', { indexName: indexName, onClone: this.props.onClone })}>
    +                      <span className="fonticon fonticon-files-o"></span>
    +                      Clone
    +                    </li>
    +                    <li onClick={this.indexAction.bind(this, 'delete', { indexName: indexName, onDelete: this.props.onDelete })}>
    +                      <span className="fonticon fonticon-trash"></span>
    +                      Delete
    +                    </li>
    +                  </ul>
    +                </Popover>
    +              }>
    +              <span className="index-menu-toggle fonticon fonticon-wrench2"></span>
    --- End diff --
    
    +1 agreed


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] couchdb-fauxton pull request: Update Views

Posted by benkeen <gi...@git.apache.org>.
Github user benkeen closed the pull request at:

    https://github.com/apache/couchdb-fauxton/pull/651


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] couchdb-fauxton pull request: Update Views

Posted by robertkowalski <gi...@git.apache.org>.
Github user robertkowalski commented on a diff in the pull request:

    https://github.com/apache/couchdb-fauxton/pull/651#discussion_r55556214
  
    --- Diff: app/addons/documents/sidebar/sidebar.react.jsx ---
    @@ -110,38 +120,92 @@ function (app, FauxtonAPI, React, ReactDOM, Stores, Actions,
             </ul>
           );
         }
    -
       });
     
    +
       var IndexSection = React.createClass({
     
         propTypes: {
           urlNamespace: React.PropTypes.string.isRequired,
    -      databaseName: React.PropTypes.string.isRequired,
    +      indexLabel: React.PropTypes.string.isRequired,
    +      database: React.PropTypes.object.isRequired,
           designDocName: React.PropTypes.string.isRequired,
           items: React.PropTypes.array.isRequired,
           isExpanded: React.PropTypes.bool.isRequired,
    -      selectedIndex: React.PropTypes.string.isRequired
    +      selectedIndex: React.PropTypes.string.isRequired,
    +      onDelete: React.PropTypes.func.isRequired,
    +      onClone: React.PropTypes.func.isRequired
         },
     
         createItems: function () {
    -      return _.map(this.props.items, function (index, key) {
    -        var href = FauxtonAPI.urls(this.props.urlNamespace, 'app', this.props.databaseName, this.props.designDocName);
    -        var className = (this.props.selectedIndex === index) ? 'active' : '';
    +
    +      // sort the indexes alphabetically
    +      var sortedItems = this.props.items.sort();
    +
    +      return _.map(sortedItems, function (indexName, index) {
    +        var href = FauxtonAPI.urls(this.props.urlNamespace, 'app', this.props.database.id, this.props.designDocName);
    +        var className = (this.props.selectedIndex === indexName) ? 'active' : '';
     
             return (
    -          <li className={className} key={key}>
    +          <li className={className} key={index}>
                 <a
    -              id={this.props.designDocName + '_' + index}
    -              href={"#/" + href + index}
    +              id={this.props.designDocName + '_' + indexName}
    +              href={"#/" + href + indexName}
                   className="toggle-view">
    -              {index}
    +              {indexName}
                 </a>
    +
    +            <OverlayTrigger
    +              ref="indexMenu"
    +              trigger="click"
    +              placement="bottom"
    +              rootClose={true}
    +              overlay={
    +                <Popover id="index-menu-component-popover">
    +                  <ul>
    +                    <li onClick={this.indexAction.bind(this, 'edit', { indexName: indexName, onEdit: this.props.onEdit })}>
    +                      <span className="fonticon fonticon-file-code-o"></span>
    +                      Edit
    +                    </li>
    +                    <li onClick={this.indexAction.bind(this, 'clone', { indexName: indexName, onClone: this.props.onClone })}>
    +                      <span className="fonticon fonticon-files-o"></span>
    +                      Clone
    +                    </li>
    +                    <li onClick={this.indexAction.bind(this, 'delete', { indexName: indexName, onDelete: this.props.onDelete })}>
    +                      <span className="fonticon fonticon-trash"></span>
    +                      Delete
    +                    </li>
    +                  </ul>
    +                </Popover>
    +              }>
    +              <span className="index-menu-toggle fonticon fonticon-wrench2"></span>
    --- End diff --
    
    can we make the hover-area a bit larger -- i am quite a web person but i have problems to hit the wrench icon in the sidebar from time to time


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] couchdb-fauxton pull request: Update Views

Posted by robertkowalski <gi...@git.apache.org>.
Github user robertkowalski commented on a diff in the pull request:

    https://github.com/apache/couchdb-fauxton/pull/651#discussion_r55816301
  
    --- Diff: app/addons/documents/tests/nightwatch/viewEdit.js ---
    @@ -12,32 +12,34 @@
     
     module.exports = {
     
    -  'Edits a design doc - set new index name': function (client) {
    -    /*jshint multistr: true */
    +  'Edits a design doc - renames index': function (client) {
         var waitTime = client.globals.maxWaitTime,
             newDatabaseName = client.globals.testDatabaseName,
             baseUrl = client.globals.test_settings.launch_url;
     
    -    var viewUrl = newDatabaseName + '/_design/testdesigndoc/_view/hasenindex5000?limit=6&reduce=false';
         client
    +      .deleteDatabase(newDatabaseName)
           .createDatabase(newDatabaseName)
           .populateDatabase(newDatabaseName)
           .loginToGUI()
    -      .url(baseUrl + '/#/database/' + newDatabaseName + '/_design/testdesigndoc/_view/stubview')
    -      .waitForElementPresent('.prettyprint', waitTime, false)
    -      .assert.containsText('.prettyprint', 'stub')
    +      .url(baseUrl + '/#/database/' + newDatabaseName + '/_design/testdesigndoc/_view/stubview/edit')
    +      .waitForElementPresent('.index-cancel-link', waitTime, true)
    +      .waitForElementNotPresent('.spinner', waitTime, true)
    +      .waitForElementNotPresent('.loading-lines', waitTime, true)
    +      .waitForElementVisible('#index-name', waitTime, true)
    +
    +      .pause(1000)
    --- End diff --
    
    debug leftover?


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] couchdb-fauxton pull request: Update Views

Posted by benkeen <gi...@git.apache.org>.
Github user benkeen commented on a diff in the pull request:

    https://github.com/apache/couchdb-fauxton/pull/651#discussion_r55846282
  
    --- Diff: app/addons/documents/index-editor/actions.js ---
    @@ -15,142 +15,287 @@ define([
       'api',
       'addons/documents/resources',
       'addons/documents/index-editor/actiontypes',
    -  'addons/documents/index-results/actions'
    +  'addons/documents/index-results/actions',
    +  'addons/documents/sidebar/actions',
    +  'addons/documents/sidebar/actiontypes'
     ],
    -function (app, FauxtonAPI, Documents, ActionTypes, IndexResultsActions) {
    +function (app, FauxtonAPI, Documents, ActionTypes, IndexResultsActions, SidebarActions, SidebarActionTypes) {
     
    -  var ActionHelpers = {
    -    findDesignDoc: function (designDocs, designDocId) {
    -      return _.find(designDocs, function (doc) {
    -        return doc.id === designDocId;
    -      }).dDocModel();
    -    }
    -  };
     
    +  function selectReduceChanged (reduceOption) {
    +    FauxtonAPI.dispatch({
    +      type: ActionTypes.SELECT_REDUCE_CHANGE,
    +      reduceSelectedOption: reduceOption
    +    });
    +  }
     
    -  return {
    -    //helpers are added here for use in testing actions
    -    helpers: ActionHelpers,
    +  function changeViewName (name) {
    +    FauxtonAPI.dispatch({
    +      type: ActionTypes.VIEW_NAME_CHANGE,
    +      name: name
    +    });
    +  }
     
    -    selectReduceChanged: function (reduceOption) {
    -      FauxtonAPI.dispatch({
    -        type: ActionTypes.SELECT_REDUCE_CHANGE,
    -        reduceSelectedOption: reduceOption
    -      });
    -    },
    +  function editIndex (options) {
    +    FauxtonAPI.dispatch({
    +      type: ActionTypes.EDIT_INDEX,
    +      options: options
    +    });
    +  }
     
    -    changeViewName: function (name) {
    -      FauxtonAPI.dispatch({
    -        type: ActionTypes.VIEW_NAME_CHANGE,
    -        name: name
    -      });
    -    },
    +  function clearIndex () {
    +    FauxtonAPI.dispatch({ type: ActionTypes.CLEAR_INDEX });
    +  }
     
    -    editIndex: function (options) {
    -      FauxtonAPI.dispatch({
    -        type: ActionTypes.EDIT_INDEX,
    -        options: options
    -      });
    -    },
    +  function fetchDesignDocsBeforeEdit (options) {
    +    options.designDocs.fetch({reset: true}).then(function () {
    +      this.editIndex(options);
    +    }.bind(this));
    +  }
     
    -    clearIndex: function () {
    -      FauxtonAPI.dispatch({ type: ActionTypes.CLEAR_INDEX });
    -    },
    +  function saveView (viewInfo) {
    +    var designDoc = viewInfo.designDoc;
    +    designDoc.setDdocView(viewInfo.viewName, viewInfo.map, viewInfo.reduce);
     
    -    fetchDesignDocsBeforeEdit: function (options) {
    -      options.designDocs.fetch({reset: true}).then(function () {
    -        this.editIndex(options);
    -      }.bind(this));
    -    },
    +    FauxtonAPI.addNotification({
    +      msg: 'Saving View...',
    +      type: 'info',
    +      clear: true
    +    });
     
    -    saveView: function (viewInfo) {
    -      var designDoc = viewInfo.designDoc;
    -      designDoc.setDdocView(viewInfo.viewName, viewInfo.map, viewInfo.reduce);
    +    // if the view name just changed and it's in the SAME design doc, remove the old one before saving the doc
    +    if (viewInfo.originalDesignDocName === viewInfo.designDocId && viewInfo.originalViewName !== viewInfo.viewName) {
    +      designDoc.removeDdocView(viewInfo.originalViewName);
    +    }
     
    +    designDoc.save().then(function () {
           FauxtonAPI.addNotification({
    -        msg:  "Saving View...",
    -        type: "info",
    +        msg: 'View Saved.',
    +        type: 'success',
             clear: true
           });
     
    -      designDoc.save().then(function () {
    -        FauxtonAPI.addNotification({
    -          msg:  "View Saved.",
    -          type: "success",
    -          clear: true
    +      // if the user just saved the view to a different design doc, remove the view from the old design doc and
    +      // delete if it's empty
    +      if (viewInfo.originalDesignDocName !== viewInfo.designDocId) {
    +        var oldDesignDoc = findDesignDoc(viewInfo.designDocs, viewInfo.originalDesignDocName);
    +        safeDeleteIndex(oldDesignDoc, viewInfo.designDocs, 'views', viewInfo.originalViewName, {
    +          onSuccess: function () {
    +            SidebarActions.updateDesignDocs(viewInfo.designDocs);
    +          }
             });
    +      }
     
    -        if (_.any([viewInfo.designDocChanged, viewInfo.hasViewNameChanged, viewInfo.newDesignDoc, viewInfo.newView])) {
    -          FauxtonAPI.dispatch({ type: ActionTypes.VIEW_SAVED });
    -          var fragment = FauxtonAPI.urls('view', 'showNewlySavedView', viewInfo.database.safeID(), designDoc.safeID(), app.utils.safeURLName(viewInfo.viewName));
    -          FauxtonAPI.navigate(fragment, { trigger: true });
    -        } else {
    -          this.updateDesignDoc(designDoc);
    -        }
    -
    -        // this can be removed after the Views are on their own page
    -        IndexResultsActions.reloadResultsList();
    -      }.bind(this));
    -    },
    +      if (viewInfo.designDocId === 'new-doc') {
    +        addDesignDoc(designDoc);
    +      }
     
    -    updateDesignDoc: function (designDoc) {
    -      FauxtonAPI.dispatch({
    -        type: ActionTypes.VIEW_UPDATE_DESIGN_DOC,
    -        designDoc: designDoc.toJSON()
    -      });
    -    },
    +      FauxtonAPI.dispatch({ type: ActionTypes.VIEW_SAVED });
    +      var fragment = FauxtonAPI.urls('view', 'showView', viewInfo.database.safeID(), designDoc.safeID(), app.utils.safeURLName(viewInfo.viewName));
    +      FauxtonAPI.navigate(fragment, { trigger: true });
    +    });
    +  }
     
    -    deleteView: function (options) {
    -      var viewName = options.viewName;
    -      var database = options.database;
    -      var designDoc = ActionHelpers.findDesignDoc(options.designDocs, options.designDocId);
    -      var promise;
    +  function addDesignDoc (designDoc) {
    +    FauxtonAPI.dispatch({
    +      type: ActionTypes.VIEW_ADD_DESIGN_DOC,
    +      designDoc: designDoc.toJSON()
    +    });
    +  }
     
    -      designDoc.removeDdocView(viewName);
    +  function deleteView (options) {
     
    -      if (designDoc.hasViews()) {
    -        promise = designDoc.save();
    -      } else {
    -        promise = designDoc.destroy();
    -      }
    +    function onSuccess () {
     
    -      promise.then(function () {
    -        var url = FauxtonAPI.urls('allDocs', 'app', database.safeID(), '?limit=' + FauxtonAPI.constants.DATABASES.DOCUMENT_LIMIT);
    +      // if the user was on the index that was just deleted, redirect them back to all docs
    +      if (options.isOnIndex) {
    +        var url = FauxtonAPI.urls('allDocs', 'app', options.database.safeID(), '?limit=' + FauxtonAPI.constants.DATABASES.DOCUMENT_LIMIT);
             FauxtonAPI.navigate(url);
    -        FauxtonAPI.triggerRouteEvent('reloadDesignDocs');
    -      });
    -    },
    +      }
    +
    +      SidebarActions.updateDesignDocs(options.designDocs);
     
    -    updateMapCode: function (code) {
    -      FauxtonAPI.dispatch({
    -        type: ActionTypes.VIEW_UPDATE_MAP_CODE,
    -        code: code
    +      FauxtonAPI.addNotification({
    +        msg: 'The <code>' + _.escape(options.indexName) + '</code> view has been deleted.',
    +        type: 'info',
    +        escape: false,
    +        clear: true
           });
    -    },
    +      FauxtonAPI.dispatch({ type: SidebarActionTypes.SIDEBAR_HIDE_DELETE_INDEX_MODAL });
    +    }
     
    -    updateReduceCode: function (code) {
    -      FauxtonAPI.dispatch({
    -        type: ActionTypes.VIEW_UPDATE_REDUCE_CODE,
    -        code: code
    +    safeDeleteIndex(options.designDoc, options.designDocs, 'views', options.indexName, { onSuccess: onSuccess });
    +  }
    +
    +  function cloneView (params) {
    +    var targetDesignDoc = getDesignDoc(params.designDocs, params.targetDesignDocName, params.newDesignDocName, params.database);
    +    var indexes = targetDesignDoc.get('views');
    +    if (indexes && _.has(indexes, params.newIndexName)) {
    +      FauxtonAPI.addNotification({
    +        msg: 'That index name is already used in this design doc. Please enter a new name.',
    +        type: 'error',
    +        clear: true
           });
    -    },
    +      return;
    +    }
    +    if (!indexes) {
    +      indexes = {};
    +    }
    +    var sourceDesignDoc = findDesignDoc(params.designDocs, '_design/' + params.sourceDesignDocName);
    +    var sourceDesignDocJSON = sourceDesignDoc.toJSON();
     
    -    selectDesignDoc: function (designDoc) {
    -      FauxtonAPI.dispatch({
    -        type: ActionTypes.DESIGN_DOC_CHANGE,
    -        options: {
    -          value: designDoc
    -        }
    +    // this sets whatever content is in the source index into the target design doc under the new index name
    +    indexes[params.newIndexName] = sourceDesignDocJSON.views[params.sourceIndexName];
    +    targetDesignDoc.set({ views: indexes });
    +
    +    targetDesignDoc.save().then(function () {
    +      params.onComplete();
    +      FauxtonAPI.addNotification({
    +        msg: 'The index has been cloned.',
    +        type: 'success',
    +        clear: true
           });
    +      SidebarActions.updateDesignDocs(params.designDocs);
         },
    -
    -    updateNewDesignDocName: function (designDocName) {
    -      FauxtonAPI.dispatch({
    -        type: ActionTypes.DESIGN_DOC_NEW_NAME_UPDATED,
    -        options: {
    -          value: designDocName
    -        }
    +    function (xhr) {
    +      params.onComplete();
    +      var responseText = JSON.parse(xhr.responseText).reason;
    +      FauxtonAPI.addNotification({
    +        msg: 'Clone failed: ' + responseText,
    +        type: 'error',
    +        clear: true
           });
    +    });
    +  }
    +
    +  function gotoEditViewPage (databaseName, designDocName, indexName) {
    +    FauxtonAPI.navigate('#' + FauxtonAPI.urls('view', 'edit', databaseName, designDocName, indexName));
    +  }
    +
    +  function updateMapCode (code) {
    +    FauxtonAPI.dispatch({
    +      type: ActionTypes.VIEW_UPDATE_MAP_CODE,
    +      code: code
    +    });
    +  }
    +
    +  function updateReduceCode (code) {
    +    FauxtonAPI.dispatch({
    +      type: ActionTypes.VIEW_UPDATE_REDUCE_CODE,
    +      code: code
    +    });
    +  }
    +
    +  function selectDesignDoc (designDoc) {
    +    FauxtonAPI.dispatch({
    +      type: ActionTypes.DESIGN_DOC_CHANGE,
    +      options: {
    +        value: designDoc
    +      }
    +    });
    +  }
    +
    +  function updateNewDesignDocName (designDocName) {
    +    FauxtonAPI.dispatch({
    +      type: ActionTypes.DESIGN_DOC_NEW_NAME_UPDATED,
    +      options: {
    +        value: designDocName
    +      }
    +    });
    +  }
    +
    +  // safely deletes an index of any type. It only deletes the actual design doc if there are no
    +  // other indexes of any type left in the doc
    +  function safeDeleteIndex (designDoc, designDocs, indexPropName, indexName, options) {
    +    var opts = _.extend({
    +      onSuccess: function () { },
    +      onError: function (xhr) {
    +        var responseText = JSON.parse(xhr.responseText).reason;
    +        FauxtonAPI.addNotification({
    +          msg: 'Delete failed: ' + responseText,
    +          type: 'error',
    +          clear: true
    +        });
    +      }
    +    }, options);
    +
    +    var indexes = designDoc.get(indexPropName) || {};
    +    delete indexes[indexName];
    +    var newIndexes = {};
    +    newIndexes[indexPropName] = indexes;
    +    designDoc.set(newIndexes);
    +
    +    // we either save the design doc with the now-removed index, or we remove it altogether if there are no indexes
    +    // of any type left in the design doc
    +    var indexTypePropNames = FauxtonAPI.getIndexTypePropNames();
    +    var hasRemainingIndex = _.some(indexTypePropNames, function (propName) {
    +      return designDoc.get(propName) && _.keys(designDoc.get(propName)).length > 0;
    +    });
    +
    +    var promise;
    +    var deleteDesignDoc = false;
    +    if (hasRemainingIndex) {
    +      promise = designDoc.save();
    +    } else {
    +      promise = designDoc.destroy();
    +      deleteDesignDoc = true;
         }
    +    promise.then(function () {
    +      if (deleteDesignDoc) {
    +        console.log("deleting?");
    --- End diff --
    
    Oops! Yup. 


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] couchdb-fauxton pull request: Update Views

Posted by robertkowalski <gi...@git.apache.org>.
Github user robertkowalski commented on a diff in the pull request:

    https://github.com/apache/couchdb-fauxton/pull/651#discussion_r55555303
  
    --- Diff: app/addons/documents/sidebar/sidebar.react.jsx ---
    @@ -110,38 +120,92 @@ function (app, FauxtonAPI, React, ReactDOM, Stores, Actions,
             </ul>
           );
         }
    -
       });
     
    +
       var IndexSection = React.createClass({
     
         propTypes: {
           urlNamespace: React.PropTypes.string.isRequired,
    -      databaseName: React.PropTypes.string.isRequired,
    +      indexLabel: React.PropTypes.string.isRequired,
    +      database: React.PropTypes.object.isRequired,
           designDocName: React.PropTypes.string.isRequired,
           items: React.PropTypes.array.isRequired,
           isExpanded: React.PropTypes.bool.isRequired,
    -      selectedIndex: React.PropTypes.string.isRequired
    +      selectedIndex: React.PropTypes.string.isRequired,
    +      onDelete: React.PropTypes.func.isRequired,
    +      onClone: React.PropTypes.func.isRequired
         },
     
         createItems: function () {
    -      return _.map(this.props.items, function (index, key) {
    -        var href = FauxtonAPI.urls(this.props.urlNamespace, 'app', this.props.databaseName, this.props.designDocName);
    -        var className = (this.props.selectedIndex === index) ? 'active' : '';
    +
    +      // sort the indexes alphabetically
    +      var sortedItems = this.props.items.sort();
    +
    +      return _.map(sortedItems, function (indexName, index) {
    +        var href = FauxtonAPI.urls(this.props.urlNamespace, 'app', this.props.database.id, this.props.designDocName);
    +        var className = (this.props.selectedIndex === indexName) ? 'active' : '';
     
             return (
    -          <li className={className} key={key}>
    +          <li className={className} key={index}>
                 <a
    -              id={this.props.designDocName + '_' + index}
    -              href={"#/" + href + index}
    +              id={this.props.designDocName + '_' + indexName}
    +              href={"#/" + href + indexName}
                   className="toggle-view">
    -              {index}
    +              {indexName}
                 </a>
    +
    +            <OverlayTrigger
    +              ref="indexMenu"
    +              trigger="click"
    +              placement="bottom"
    +              rootClose={true}
    +              overlay={
    +                <Popover id="index-menu-component-popover">
    +                  <ul>
    +                    <li onClick={this.indexAction.bind(this, 'edit', { indexName: indexName, onEdit: this.props.onEdit })}>
    +                      <span className="fonticon fonticon-file-code-o"></span>
    +                      Edit
    +                    </li>
    +                    <li onClick={this.indexAction.bind(this, 'clone', { indexName: indexName, onClone: this.props.onClone })}>
    +                      <span className="fonticon fonticon-files-o"></span>
    +                      Clone
    +                    </li>
    +                    <li onClick={this.indexAction.bind(this, 'delete', { indexName: indexName, onDelete: this.props.onDelete })}>
    +                      <span className="fonticon fonticon-trash"></span>
    +                      Delete
    +                    </li>
    +                  </ul>
    +                </Popover>
    +              }>
    +              <span className="index-menu-toggle fonticon fonticon-wrench2"></span>
    +            </OverlayTrigger>
    +
               </li>
             );
           }, this);
         },
     
    +    indexAction: function (action, params, e) {
    +      e.preventDefault();
    +
    +      // bah. We need to close the overlay trigger whenever the user clicks on anything inside. The
    +      // component doesn't have that functionality, so we simulate a click outside of it :(
    +      $('body').trigger('click');
    --- End diff --
    
    the overlay component has an interface.
    
    give it a `ref` and then you can call `hide` and `show` on it, example:
    
    https://github.com/apache/couchdb-fauxton/blob/0c07ddc432c12895310592b0c46729feaac958db/app/addons/components/react-components.react.jsx#L198-L206
    



---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] couchdb-fauxton pull request: Update Views

Posted by robertkowalski <gi...@git.apache.org>.
Github user robertkowalski commented on a diff in the pull request:

    https://github.com/apache/couchdb-fauxton/pull/651#discussion_r55553488
  
    --- Diff: app/addons/documents/routes-index-editor.js ---
    @@ -28,40 +28,53 @@ define([
       'addons/documents/pagination/pagination.react',
       'addons/documents/header/header.react',
       'addons/documents/header/header.actions',
    +  'addons/documents/sidebar/actions'
     ],
     
     function (app, FauxtonAPI, Helpers, BaseRoute, Documents, IndexEditorComponents, ActionsIndexEditor,
               Databases, Components, IndexResultsStores, IndexResultsActions,
    -          IndexResultsComponents, ReactPagination, ReactHeader, ReactHeaderActions) {
    +          IndexResultsComponents, ReactPagination, ReactHeader, ReactHeaderActions, SidebarActions) {
     
     
       var IndexEditorAndResults = BaseRoute.extend({
    -    layout: 'two_pane',
    +    layout: 'with_tabs_sidebar',
         routes: {
    -      'database/:database/new_view': 'newViewEditor',
    -      'database/:database/new_view/:designDoc': 'newViewEditor',
    +      'database/:database/new_view': {
    +        route: 'createView',
    +        roles: ['fx_loggedIn']
    +      },
    +      'database/:database/new_view/:designDoc': {
    +        route: 'createView',
    +        roles: ['fx_loggedIn']
    +      },
           'database/:database/_design/:ddoc/_view/:view': {
    -        route: 'viewFn',
    +        route: 'showView',
    +        roles: ['fx_loggedIn']
    +      },
    +      'database/:database/_design/:ddoc/_view/:view/edit': {
    --- End diff --
    
    hmm.. changing the route diverges us more from the couchdb routing:
    
    right now
    
    ```
    http://localhost:8000/#/database/blerg/_design/yxc/_view/new-view
    
    
               http://localhost:5984/blerg/_design/yxc/_view/new-view
    ```
    
    that makes it easy to copy / paste stuff around for debugging / development of applications that use couchdb views, i can click to the view in the fauxton ui and then copy the second part of the url 1:1 into my application code


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] couchdb-fauxton pull request: Update Views

Posted by robertkowalski <gi...@git.apache.org>.
Github user robertkowalski commented on the pull request:

    https://github.com/apache/couchdb-fauxton/pull/651#issuecomment-195317399
  
    click on existing view, choose "new document from dropdown", the form element looks misplaced:
    
    <img width="732" alt="bildschirmfoto 2016-03-11 um 10 46 27" src="https://cloud.githubusercontent.com/assets/298166/13700204/6b4b5166-e777-11e5-94f7-d1de467cd2d2.png">



---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] couchdb-fauxton pull request: Update Views

Posted by benkeen <gi...@git.apache.org>.
Github user benkeen commented on a diff in the pull request:

    https://github.com/apache/couchdb-fauxton/pull/651#discussion_r55597087
  
    --- Diff: app/addons/documents/routes-index-editor.js ---
    @@ -28,40 +28,53 @@ define([
       'addons/documents/pagination/pagination.react',
       'addons/documents/header/header.react',
       'addons/documents/header/header.actions',
    +  'addons/documents/sidebar/actions'
     ],
     
     function (app, FauxtonAPI, Helpers, BaseRoute, Documents, IndexEditorComponents, ActionsIndexEditor,
               Databases, Components, IndexResultsStores, IndexResultsActions,
    -          IndexResultsComponents, ReactPagination, ReactHeader, ReactHeaderActions) {
    +          IndexResultsComponents, ReactPagination, ReactHeader, ReactHeaderActions, SidebarActions) {
     
     
       var IndexEditorAndResults = BaseRoute.extend({
    -    layout: 'two_pane',
    +    layout: 'with_tabs_sidebar',
         routes: {
    -      'database/:database/new_view': 'newViewEditor',
    -      'database/:database/new_view/:designDoc': 'newViewEditor',
    +      'database/:database/new_view': {
    +        route: 'createView',
    +        roles: ['fx_loggedIn']
    +      },
    +      'database/:database/new_view/:designDoc': {
    +        route: 'createView',
    +        roles: ['fx_loggedIn']
    +      },
           'database/:database/_design/:ddoc/_view/:view': {
    -        route: 'viewFn',
    +        route: 'showView',
    +        roles: ['fx_loggedIn']
    +      },
    +      'database/:database/_design/:ddoc/_view/:view/edit': {
    --- End diff --
    
    Cool thanks. I've patched the API URL to be correct for the edit page. 


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] couchdb-fauxton pull request: Update Views

Posted by robertkowalski <gi...@git.apache.org>.
Github user robertkowalski commented on the pull request:

    https://github.com/apache/couchdb-fauxton/pull/651#issuecomment-194416271
  
    wow! really looking forward to land this! 
    
    :heart: :heart: :heart: 
    
    really cool that we improved our integration test coverage - this area is one of the most important parts of fauxton, good work!


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] couchdb-fauxton pull request: Update Views

Posted by benkeen <gi...@git.apache.org>.
Github user benkeen commented on the pull request:

    https://github.com/apache/couchdb-fauxton/pull/651#issuecomment-200130632
  
    Merged as 3ff6ff622bf22bc019a585b8285e03af94ec0650


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] couchdb-fauxton pull request: Update Views

Posted by robertkowalski <gi...@git.apache.org>.
Github user robertkowalski commented on the pull request:

    https://github.com/apache/couchdb-fauxton/pull/651#issuecomment-198482534
  
    great work, +1000! 



---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] couchdb-fauxton pull request: Update Views

Posted by robertkowalski <gi...@git.apache.org>.
Github user robertkowalski commented on a diff in the pull request:

    https://github.com/apache/couchdb-fauxton/pull/651#discussion_r55552484
  
    --- Diff: app/addons/documents/index-editor/actions.js ---
    @@ -15,142 +15,282 @@ define([
       'api',
       'addons/documents/resources',
       'addons/documents/index-editor/actiontypes',
    -  'addons/documents/index-results/actions'
    +  'addons/documents/index-results/actions',
    +  'addons/documents/sidebar/actions',
    +  'addons/documents/sidebar/actiontypes'
     ],
    -function (app, FauxtonAPI, Documents, ActionTypes, IndexResultsActions) {
    +function (app, FauxtonAPI, Documents, ActionTypes, IndexResultsActions, SidebarActions, SidebarActionTypes) {
     
    -  var ActionHelpers = {
    -    findDesignDoc: function (designDocs, designDocId) {
    -      return _.find(designDocs, function (doc) {
    -        return doc.id === designDocId;
    -      }).dDocModel();
    -    }
    -  };
     
    +  function selectReduceChanged (reduceOption) {
    +    FauxtonAPI.dispatch({
    +      type: ActionTypes.SELECT_REDUCE_CHANGE,
    +      reduceSelectedOption: reduceOption
    +    });
    +  }
     
    -  return {
    -    //helpers are added here for use in testing actions
    -    helpers: ActionHelpers,
    +  function changeViewName (name) {
    +    FauxtonAPI.dispatch({
    +      type: ActionTypes.VIEW_NAME_CHANGE,
    +      name: name
    +    });
    +  }
     
    -    selectReduceChanged: function (reduceOption) {
    -      FauxtonAPI.dispatch({
    -        type: ActionTypes.SELECT_REDUCE_CHANGE,
    -        reduceSelectedOption: reduceOption
    -      });
    -    },
    +  function editIndex (options) {
    +    FauxtonAPI.dispatch({
    +      type: ActionTypes.EDIT_INDEX,
    +      options: options
    +    });
    +  }
     
    -    changeViewName: function (name) {
    -      FauxtonAPI.dispatch({
    -        type: ActionTypes.VIEW_NAME_CHANGE,
    -        name: name
    -      });
    -    },
    +  function clearIndex () {
    +    FauxtonAPI.dispatch({ type: ActionTypes.CLEAR_INDEX });
    +  }
     
    -    editIndex: function (options) {
    -      FauxtonAPI.dispatch({
    -        type: ActionTypes.EDIT_INDEX,
    -        options: options
    -      });
    -    },
    +  function fetchDesignDocsBeforeEdit (options) {
    +    options.designDocs.fetch({reset: true}).then(function () {
    +      this.editIndex(options);
    +    }.bind(this));
    +  }
     
    -    clearIndex: function () {
    -      FauxtonAPI.dispatch({ type: ActionTypes.CLEAR_INDEX });
    -    },
    +  function saveView (viewInfo) {
    +    var designDoc = viewInfo.designDoc;
    +    designDoc.setDdocView(viewInfo.viewName, viewInfo.map, viewInfo.reduce);
     
    -    fetchDesignDocsBeforeEdit: function (options) {
    -      options.designDocs.fetch({reset: true}).then(function () {
    -        this.editIndex(options);
    -      }.bind(this));
    -    },
    +    FauxtonAPI.addNotification({
    +      msg: 'Saving View...',
    +      type: 'info',
    +      clear: true
    +    });
     
    -    saveView: function (viewInfo) {
    -      var designDoc = viewInfo.designDoc;
    -      designDoc.setDdocView(viewInfo.viewName, viewInfo.map, viewInfo.reduce);
    +    // if the view name just changed and it's in the SAME design doc, remove the old one before saving the doc
    +    if (viewInfo.originalDesignDocName === viewInfo.designDocId && viewInfo.originalViewName !== viewInfo.viewName) {
    +      designDoc.removeDdocView(viewInfo.originalViewName);
    +    }
     
    +    designDoc.save().then(function () {
           FauxtonAPI.addNotification({
    -        msg:  "Saving View...",
    -        type: "info",
    +        msg: 'View Saved.',
    +        type: 'success',
             clear: true
           });
     
    -      designDoc.save().then(function () {
    -        FauxtonAPI.addNotification({
    -          msg:  "View Saved.",
    -          type: "success",
    -          clear: true
    -        });
    +      // if the user just saved the view to a different design doc, remove the view from the old design doc and
    +      // delete if it's empty
    +      if (viewInfo.originalDesignDocName !== viewInfo.designDocId) {
    +        var oldDesignDoc = findDesignDoc(viewInfo.designDocs, viewInfo.originalDesignDocName);
    +        safeDeleteView(oldDesignDoc, viewInfo.designDocs, viewInfo.database, viewInfo.originalViewName);
    +      }
     
    -        if (_.any([viewInfo.designDocChanged, viewInfo.hasViewNameChanged, viewInfo.newDesignDoc, viewInfo.newView])) {
    -          FauxtonAPI.dispatch({ type: ActionTypes.VIEW_SAVED });
    -          var fragment = FauxtonAPI.urls('view', 'showNewlySavedView', viewInfo.database.safeID(), designDoc.safeID(), app.utils.safeURLName(viewInfo.viewName));
    -          FauxtonAPI.navigate(fragment, { trigger: true });
    -        } else {
    -          this.updateDesignDoc(designDoc);
    -        }
    -
    -        // this can be removed after the Views are on their own page
    -        IndexResultsActions.reloadResultsList();
    -      }.bind(this));
    -    },
    +      if (viewInfo.designDocId === 'new-doc') {
    +        addDesignDoc(designDoc);
    +      }
     
    -    updateDesignDoc: function (designDoc) {
    -      FauxtonAPI.dispatch({
    -        type: ActionTypes.VIEW_UPDATE_DESIGN_DOC,
    -        designDoc: designDoc.toJSON()
    -      });
    -    },
    +      FauxtonAPI.dispatch({ type: ActionTypes.VIEW_SAVED });
    +      var fragment = FauxtonAPI.urls('view', 'showView', viewInfo.database.safeID(), designDoc.safeID(), app.utils.safeURLName(viewInfo.viewName));
    +      FauxtonAPI.navigate(fragment, { trigger: true });
    +    });
    +  }
     
    -    deleteView: function (options) {
    -      var viewName = options.viewName;
    -      var database = options.database;
    -      var designDoc = ActionHelpers.findDesignDoc(options.designDocs, options.designDocId);
    -      var promise;
    +  function addDesignDoc (designDoc) {
    +    FauxtonAPI.dispatch({
    +      type: ActionTypes.VIEW_ADD_DESIGN_DOC,
    +      designDoc: designDoc.toJSON()
    +    });
    +  }
     
    -      designDoc.removeDdocView(viewName);
    +  function deleteView (options) {
     
    -      if (designDoc.hasViews()) {
    -        promise = designDoc.save();
    -      } else {
    -        promise = designDoc.destroy();
    -      }
    +    var onSuccess = function () {
    --- End diff --
    
    can we make this uniform and make this a named function, too?
    
    both ways to write a function have different scoping implications on `this`, keeping them all "named" makes it easier to scan them


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] couchdb-fauxton pull request: Update Views

Posted by benkeen <gi...@git.apache.org>.
Github user benkeen commented on a diff in the pull request:

    https://github.com/apache/couchdb-fauxton/pull/651#discussion_r55846494
  
    --- Diff: app/addons/documents/tests/nightwatch/viewEdit.js ---
    @@ -12,32 +12,34 @@
     
     module.exports = {
     
    -  'Edits a design doc - set new index name': function (client) {
    -    /*jshint multistr: true */
    +  'Edits a design doc - renames index': function (client) {
         var waitTime = client.globals.maxWaitTime,
             newDatabaseName = client.globals.testDatabaseName,
             baseUrl = client.globals.test_settings.launch_url;
     
    -    var viewUrl = newDatabaseName + '/_design/testdesigndoc/_view/hasenindex5000?limit=6&reduce=false';
         client
    +      .deleteDatabase(newDatabaseName)
           .createDatabase(newDatabaseName)
           .populateDatabase(newDatabaseName)
           .loginToGUI()
    -      .url(baseUrl + '/#/database/' + newDatabaseName + '/_design/testdesigndoc/_view/stubview')
    -      .waitForElementPresent('.prettyprint', waitTime, false)
    -      .assert.containsText('.prettyprint', 'stub')
    +      .url(baseUrl + '/#/database/' + newDatabaseName + '/_design/testdesigndoc/_view/stubview/edit')
    +      .waitForElementPresent('.index-cancel-link', waitTime, true)
    +      .waitForElementNotPresent('.spinner', waitTime, true)
    +      .waitForElementNotPresent('.loading-lines', waitTime, true)
    +      .waitForElementVisible('#index-name', waitTime, true)
    +
    +      .pause(1000)
    --- End diff --
    
    Yup. Shouldn't be there.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] couchdb-fauxton pull request: Update Views

Posted by robertkowalski <gi...@git.apache.org>.
Github user robertkowalski commented on a diff in the pull request:

    https://github.com/apache/couchdb-fauxton/pull/651#discussion_r55816325
  
    --- Diff: app/addons/documents/index-editor/actions.js ---
    @@ -15,142 +15,287 @@ define([
       'api',
       'addons/documents/resources',
       'addons/documents/index-editor/actiontypes',
    -  'addons/documents/index-results/actions'
    +  'addons/documents/index-results/actions',
    +  'addons/documents/sidebar/actions',
    +  'addons/documents/sidebar/actiontypes'
     ],
    -function (app, FauxtonAPI, Documents, ActionTypes, IndexResultsActions) {
    +function (app, FauxtonAPI, Documents, ActionTypes, IndexResultsActions, SidebarActions, SidebarActionTypes) {
     
    -  var ActionHelpers = {
    -    findDesignDoc: function (designDocs, designDocId) {
    -      return _.find(designDocs, function (doc) {
    -        return doc.id === designDocId;
    -      }).dDocModel();
    -    }
    -  };
     
    +  function selectReduceChanged (reduceOption) {
    +    FauxtonAPI.dispatch({
    +      type: ActionTypes.SELECT_REDUCE_CHANGE,
    +      reduceSelectedOption: reduceOption
    +    });
    +  }
     
    -  return {
    -    //helpers are added here for use in testing actions
    -    helpers: ActionHelpers,
    +  function changeViewName (name) {
    +    FauxtonAPI.dispatch({
    +      type: ActionTypes.VIEW_NAME_CHANGE,
    +      name: name
    +    });
    +  }
     
    -    selectReduceChanged: function (reduceOption) {
    -      FauxtonAPI.dispatch({
    -        type: ActionTypes.SELECT_REDUCE_CHANGE,
    -        reduceSelectedOption: reduceOption
    -      });
    -    },
    +  function editIndex (options) {
    +    FauxtonAPI.dispatch({
    +      type: ActionTypes.EDIT_INDEX,
    +      options: options
    +    });
    +  }
     
    -    changeViewName: function (name) {
    -      FauxtonAPI.dispatch({
    -        type: ActionTypes.VIEW_NAME_CHANGE,
    -        name: name
    -      });
    -    },
    +  function clearIndex () {
    +    FauxtonAPI.dispatch({ type: ActionTypes.CLEAR_INDEX });
    +  }
     
    -    editIndex: function (options) {
    -      FauxtonAPI.dispatch({
    -        type: ActionTypes.EDIT_INDEX,
    -        options: options
    -      });
    -    },
    +  function fetchDesignDocsBeforeEdit (options) {
    +    options.designDocs.fetch({reset: true}).then(function () {
    +      this.editIndex(options);
    +    }.bind(this));
    +  }
     
    -    clearIndex: function () {
    -      FauxtonAPI.dispatch({ type: ActionTypes.CLEAR_INDEX });
    -    },
    +  function saveView (viewInfo) {
    +    var designDoc = viewInfo.designDoc;
    +    designDoc.setDdocView(viewInfo.viewName, viewInfo.map, viewInfo.reduce);
     
    -    fetchDesignDocsBeforeEdit: function (options) {
    -      options.designDocs.fetch({reset: true}).then(function () {
    -        this.editIndex(options);
    -      }.bind(this));
    -    },
    +    FauxtonAPI.addNotification({
    +      msg: 'Saving View...',
    +      type: 'info',
    +      clear: true
    +    });
     
    -    saveView: function (viewInfo) {
    -      var designDoc = viewInfo.designDoc;
    -      designDoc.setDdocView(viewInfo.viewName, viewInfo.map, viewInfo.reduce);
    +    // if the view name just changed and it's in the SAME design doc, remove the old one before saving the doc
    +    if (viewInfo.originalDesignDocName === viewInfo.designDocId && viewInfo.originalViewName !== viewInfo.viewName) {
    +      designDoc.removeDdocView(viewInfo.originalViewName);
    +    }
     
    +    designDoc.save().then(function () {
           FauxtonAPI.addNotification({
    -        msg:  "Saving View...",
    -        type: "info",
    +        msg: 'View Saved.',
    +        type: 'success',
             clear: true
           });
     
    -      designDoc.save().then(function () {
    -        FauxtonAPI.addNotification({
    -          msg:  "View Saved.",
    -          type: "success",
    -          clear: true
    +      // if the user just saved the view to a different design doc, remove the view from the old design doc and
    +      // delete if it's empty
    +      if (viewInfo.originalDesignDocName !== viewInfo.designDocId) {
    +        var oldDesignDoc = findDesignDoc(viewInfo.designDocs, viewInfo.originalDesignDocName);
    +        safeDeleteIndex(oldDesignDoc, viewInfo.designDocs, 'views', viewInfo.originalViewName, {
    +          onSuccess: function () {
    +            SidebarActions.updateDesignDocs(viewInfo.designDocs);
    +          }
             });
    +      }
     
    -        if (_.any([viewInfo.designDocChanged, viewInfo.hasViewNameChanged, viewInfo.newDesignDoc, viewInfo.newView])) {
    -          FauxtonAPI.dispatch({ type: ActionTypes.VIEW_SAVED });
    -          var fragment = FauxtonAPI.urls('view', 'showNewlySavedView', viewInfo.database.safeID(), designDoc.safeID(), app.utils.safeURLName(viewInfo.viewName));
    -          FauxtonAPI.navigate(fragment, { trigger: true });
    -        } else {
    -          this.updateDesignDoc(designDoc);
    -        }
    -
    -        // this can be removed after the Views are on their own page
    -        IndexResultsActions.reloadResultsList();
    -      }.bind(this));
    -    },
    +      if (viewInfo.designDocId === 'new-doc') {
    +        addDesignDoc(designDoc);
    +      }
     
    -    updateDesignDoc: function (designDoc) {
    -      FauxtonAPI.dispatch({
    -        type: ActionTypes.VIEW_UPDATE_DESIGN_DOC,
    -        designDoc: designDoc.toJSON()
    -      });
    -    },
    +      FauxtonAPI.dispatch({ type: ActionTypes.VIEW_SAVED });
    +      var fragment = FauxtonAPI.urls('view', 'showView', viewInfo.database.safeID(), designDoc.safeID(), app.utils.safeURLName(viewInfo.viewName));
    +      FauxtonAPI.navigate(fragment, { trigger: true });
    +    });
    +  }
     
    -    deleteView: function (options) {
    -      var viewName = options.viewName;
    -      var database = options.database;
    -      var designDoc = ActionHelpers.findDesignDoc(options.designDocs, options.designDocId);
    -      var promise;
    +  function addDesignDoc (designDoc) {
    +    FauxtonAPI.dispatch({
    +      type: ActionTypes.VIEW_ADD_DESIGN_DOC,
    +      designDoc: designDoc.toJSON()
    +    });
    +  }
     
    -      designDoc.removeDdocView(viewName);
    +  function deleteView (options) {
     
    -      if (designDoc.hasViews()) {
    -        promise = designDoc.save();
    -      } else {
    -        promise = designDoc.destroy();
    -      }
    +    function onSuccess () {
     
    -      promise.then(function () {
    -        var url = FauxtonAPI.urls('allDocs', 'app', database.safeID(), '?limit=' + FauxtonAPI.constants.DATABASES.DOCUMENT_LIMIT);
    +      // if the user was on the index that was just deleted, redirect them back to all docs
    +      if (options.isOnIndex) {
    +        var url = FauxtonAPI.urls('allDocs', 'app', options.database.safeID(), '?limit=' + FauxtonAPI.constants.DATABASES.DOCUMENT_LIMIT);
             FauxtonAPI.navigate(url);
    -        FauxtonAPI.triggerRouteEvent('reloadDesignDocs');
    -      });
    -    },
    +      }
    +
    +      SidebarActions.updateDesignDocs(options.designDocs);
     
    -    updateMapCode: function (code) {
    -      FauxtonAPI.dispatch({
    -        type: ActionTypes.VIEW_UPDATE_MAP_CODE,
    -        code: code
    +      FauxtonAPI.addNotification({
    +        msg: 'The <code>' + _.escape(options.indexName) + '</code> view has been deleted.',
    +        type: 'info',
    +        escape: false,
    +        clear: true
           });
    -    },
    +      FauxtonAPI.dispatch({ type: SidebarActionTypes.SIDEBAR_HIDE_DELETE_INDEX_MODAL });
    +    }
     
    -    updateReduceCode: function (code) {
    -      FauxtonAPI.dispatch({
    -        type: ActionTypes.VIEW_UPDATE_REDUCE_CODE,
    -        code: code
    +    safeDeleteIndex(options.designDoc, options.designDocs, 'views', options.indexName, { onSuccess: onSuccess });
    +  }
    +
    +  function cloneView (params) {
    +    var targetDesignDoc = getDesignDoc(params.designDocs, params.targetDesignDocName, params.newDesignDocName, params.database);
    +    var indexes = targetDesignDoc.get('views');
    +    if (indexes && _.has(indexes, params.newIndexName)) {
    +      FauxtonAPI.addNotification({
    +        msg: 'That index name is already used in this design doc. Please enter a new name.',
    +        type: 'error',
    +        clear: true
           });
    -    },
    +      return;
    +    }
    +    if (!indexes) {
    +      indexes = {};
    +    }
    +    var sourceDesignDoc = findDesignDoc(params.designDocs, '_design/' + params.sourceDesignDocName);
    +    var sourceDesignDocJSON = sourceDesignDoc.toJSON();
     
    -    selectDesignDoc: function (designDoc) {
    -      FauxtonAPI.dispatch({
    -        type: ActionTypes.DESIGN_DOC_CHANGE,
    -        options: {
    -          value: designDoc
    -        }
    +    // this sets whatever content is in the source index into the target design doc under the new index name
    +    indexes[params.newIndexName] = sourceDesignDocJSON.views[params.sourceIndexName];
    +    targetDesignDoc.set({ views: indexes });
    +
    +    targetDesignDoc.save().then(function () {
    +      params.onComplete();
    +      FauxtonAPI.addNotification({
    +        msg: 'The index has been cloned.',
    +        type: 'success',
    +        clear: true
           });
    +      SidebarActions.updateDesignDocs(params.designDocs);
         },
    -
    -    updateNewDesignDocName: function (designDocName) {
    -      FauxtonAPI.dispatch({
    -        type: ActionTypes.DESIGN_DOC_NEW_NAME_UPDATED,
    -        options: {
    -          value: designDocName
    -        }
    +    function (xhr) {
    +      params.onComplete();
    +      var responseText = JSON.parse(xhr.responseText).reason;
    +      FauxtonAPI.addNotification({
    +        msg: 'Clone failed: ' + responseText,
    +        type: 'error',
    +        clear: true
           });
    +    });
    +  }
    +
    +  function gotoEditViewPage (databaseName, designDocName, indexName) {
    +    FauxtonAPI.navigate('#' + FauxtonAPI.urls('view', 'edit', databaseName, designDocName, indexName));
    +  }
    +
    +  function updateMapCode (code) {
    +    FauxtonAPI.dispatch({
    +      type: ActionTypes.VIEW_UPDATE_MAP_CODE,
    +      code: code
    +    });
    +  }
    +
    +  function updateReduceCode (code) {
    +    FauxtonAPI.dispatch({
    +      type: ActionTypes.VIEW_UPDATE_REDUCE_CODE,
    +      code: code
    +    });
    +  }
    +
    +  function selectDesignDoc (designDoc) {
    +    FauxtonAPI.dispatch({
    +      type: ActionTypes.DESIGN_DOC_CHANGE,
    +      options: {
    +        value: designDoc
    +      }
    +    });
    +  }
    +
    +  function updateNewDesignDocName (designDocName) {
    +    FauxtonAPI.dispatch({
    +      type: ActionTypes.DESIGN_DOC_NEW_NAME_UPDATED,
    +      options: {
    +        value: designDocName
    +      }
    +    });
    +  }
    +
    +  // safely deletes an index of any type. It only deletes the actual design doc if there are no
    +  // other indexes of any type left in the doc
    +  function safeDeleteIndex (designDoc, designDocs, indexPropName, indexName, options) {
    +    var opts = _.extend({
    +      onSuccess: function () { },
    +      onError: function (xhr) {
    +        var responseText = JSON.parse(xhr.responseText).reason;
    +        FauxtonAPI.addNotification({
    +          msg: 'Delete failed: ' + responseText,
    +          type: 'error',
    +          clear: true
    +        });
    +      }
    +    }, options);
    +
    +    var indexes = designDoc.get(indexPropName) || {};
    +    delete indexes[indexName];
    +    var newIndexes = {};
    +    newIndexes[indexPropName] = indexes;
    +    designDoc.set(newIndexes);
    +
    +    // we either save the design doc with the now-removed index, or we remove it altogether if there are no indexes
    +    // of any type left in the design doc
    +    var indexTypePropNames = FauxtonAPI.getIndexTypePropNames();
    +    var hasRemainingIndex = _.some(indexTypePropNames, function (propName) {
    +      return designDoc.get(propName) && _.keys(designDoc.get(propName)).length > 0;
    +    });
    +
    +    var promise;
    +    var deleteDesignDoc = false;
    +    if (hasRemainingIndex) {
    +      promise = designDoc.save();
    +    } else {
    +      promise = designDoc.destroy();
    +      deleteDesignDoc = true;
         }
    +    promise.then(function () {
    +      if (deleteDesignDoc) {
    +        console.log("deleting?");
    --- End diff --
    
    debug leftover?


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---