You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by ga...@apache.org on 2018/03/05 09:15:39 UTC

[couchdb-fauxton] branch master updated: Add support for stable and update parameter for views (#1046)

This is an automated email from the ASF dual-hosted git repository.

garren pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/couchdb-fauxton.git


The following commit(s) were added to refs/heads/master by this push:
     new 5e81931  Add support for stable and update parameter for views (#1046)
5e81931 is described below

commit 5e81931386d2487b32b611232094e50ea5e3421b
Author: Alexis Côté <po...@users.noreply.github.com>
AuthorDate: Mon Mar 5 04:15:37 2018 -0500

    Add support for stable and update parameter for views (#1046)
    
    * Add stale and stable view options
    
    * Replace stale param for update
---
 .../documents/__tests__/main-fields-view.test.js   | 30 ++++++++++
 .../documents/__tests__/query-options.test.js      |  2 +
 .../__tests__/queryoptions-actions.test.js         | 18 ++++++
 .../index-results/actions/queryoptions.js          | 12 ++++
 .../components/queryoptions/MainFieldsView.js      | 70 +++++++++++++++++-----
 .../components/queryoptions/QueryOptions.js        | 17 ++++--
 .../containers/QueryOptionsContainer.js            | 14 ++++-
 app/addons/documents/index-results/reducers.js     | 22 +++++--
 8 files changed, 159 insertions(+), 26 deletions(-)

diff --git a/app/addons/documents/__tests__/main-fields-view.test.js b/app/addons/documents/__tests__/main-fields-view.test.js
index 80b0c45..d6fe8aa 100644
--- a/app/addons/documents/__tests__/main-fields-view.test.js
+++ b/app/addons/documents/__tests__/main-fields-view.test.js
@@ -88,4 +88,34 @@ describe('MainFieldsView', () => {
     wrapper.find('#qoReduce').simulate('change');
     expect(spy.calledOnce).toBe(true);
   });
+
+  it('calls toggleStable', () => {
+    const spy = sinon.spy();
+    const wrapper = mount(<MainFieldsView
+      includeDocs={false}
+      showReduce={false}
+      reduce={false}
+      toggleIncludeDocs={() => {}}
+      toggleStable={spy}
+      docURL={docURL}
+    />);
+
+    wrapper.find('#qoStable').simulate('change');
+    expect(spy.calledOnce).toBe(true);
+  });
+
+  it('calls changeUpdateField', () => {
+    const spy = sinon.spy();
+    const wrapper = mount(<MainFieldsView
+      includeDocs={false}
+      showReduce={false}
+      reduce={false}
+      toggleIncludeDocs={() => {}}
+      changeUpdateField={spy}
+      docURL={docURL}
+    />);
+
+    wrapper.find('#qoUpdate').simulate('change');
+    expect(spy.calledOnce).toBe(true);
+  });
 });
diff --git a/app/addons/documents/__tests__/query-options.test.js b/app/addons/documents/__tests__/query-options.test.js
index d7b203d..10e9552 100644
--- a/app/addons/documents/__tests__/query-options.test.js
+++ b/app/addons/documents/__tests__/query-options.test.js
@@ -126,6 +126,7 @@ describe('QueryOptions', () => {
 
     const wrapper = shallow(<QueryOptions
       ddocsOnly={true}
+      update='true'
       queryOptionsRemoveFilterOnlyDdocs={() => {}}
       queryOptionsApplyFilterOnlyDdocs={() => {}}
       queryOptionsExecute={() => {}}
@@ -280,6 +281,7 @@ describe('QueryOptions', () => {
     };
     const wrapper = shallow(<QueryOptions
       ddocsOnly={true}
+      update='true'
       queryOptionsRemoveFilterOnlyDdocs={() => {}}
       queryOptionsApplyFilterOnlyDdocs={() => {}}
       queryOptionsExecute={() => {}}
diff --git a/app/addons/documents/__tests__/queryoptions-actions.test.js b/app/addons/documents/__tests__/queryoptions-actions.test.js
index 7072617..7ed4a62 100644
--- a/app/addons/documents/__tests__/queryoptions-actions.test.js
+++ b/app/addons/documents/__tests__/queryoptions-actions.test.js
@@ -156,4 +156,22 @@ describe('Docs Query Options API', () => {
       }
     });
   });
+
+  it('queryOptionsToggleStable returns the proper event to dispatch', () => {
+    expect(Actions.queryOptionsToggleStable(true)).toEqual({
+      type: ActionTypes.INDEX_RESULTS_REDUX_NEW_QUERY_OPTIONS,
+      options: {
+        stable: false
+      }
+    });
+  });
+
+  it('queryOptionsChangeUpdate returns the proper event to dispatch', () => {
+    expect(Actions.queryOptionsChangeUpdate('lazy')).toEqual({
+      type: ActionTypes.INDEX_RESULTS_REDUX_NEW_QUERY_OPTIONS,
+      options: {
+        update: 'lazy'
+      }
+    });
+  });
 });
diff --git a/app/addons/documents/index-results/actions/queryoptions.js b/app/addons/documents/index-results/actions/queryoptions.js
index 60d21f7..fc3c60a 100644
--- a/app/addons/documents/index-results/actions/queryoptions.js
+++ b/app/addons/documents/index-results/actions/queryoptions.js
@@ -127,3 +127,15 @@ export const queryOptionsRemoveFilterOnlyDdocs = () => {
     showByKeys: false
   });
 };
+
+export const queryOptionsToggleStable = previous => {
+  return updateQueryOptions({
+    stable: !previous
+  });
+};
+
+export const queryOptionsChangeUpdate = value => {
+  return updateQueryOptions({
+    update: value.toString()
+  });
+};
diff --git a/app/addons/documents/index-results/components/queryoptions/MainFieldsView.js b/app/addons/documents/index-results/components/queryoptions/MainFieldsView.js
index 7b3fedf..9b6cad0 100644
--- a/app/addons/documents/index-results/components/queryoptions/MainFieldsView.js
+++ b/app/addons/documents/index-results/components/queryoptions/MainFieldsView.js
@@ -11,31 +11,43 @@
 // the License.
 
 import PropTypes from 'prop-types';
-
 import React from 'react';
 
 export default class MainFieldsView extends React.Component {
   constructor(props) {
     super(props);
+    this.toggleStable = this.toggleStable.bind(this);
+    this.onUpdateChange = this.onUpdateChange.bind(this);
+
+    this.updateOptions = [
+      {value: 'true', label: 'true'},
+      {value: 'lazy', label: 'lazy'},
+      {value: 'false', label: 'false'}
+    ];
   }
 
-  toggleIncludeDocs () {
+  toggleIncludeDocs() {
     this.props.toggleIncludeDocs(this.props.includeDocs);
   }
 
-  groupLevelChange (e) {
+  onUpdateChange(e) {
+    this.props.changeUpdateField(e.target.value);
+  }
+
+  groupLevelChange(e) {
     this.props.updateGroupLevel(e.target.value);
   }
 
-  groupLevel () {
+  groupLevel() {
     if (!this.props.reduce) {
       return null;
     }
 
     return (
       <label className="drop-down inline" id="qoGroupLevelGroup">
-        Group Level
-        <select onChange={this.groupLevelChange.bind(this)} id="qoGroupLevel" value={this.props.groupLevel} name="group_level" className="input-small">
+          Group Level
+        <select onChange={this.groupLevelChange.bind(this)} id="qoGroupLevel" value={this.props.groupLevel}
+          name="group_level" className="input-small">
           <option value="0">None</option>
           <option value="1">1</option>
           <option value="2">2</option>
@@ -52,11 +64,15 @@ export default class MainFieldsView extends React.Component {
     );
   }
 
-  toggleReduce () {
+  toggleReduce() {
     this.props.toggleReduce(this.props.reduce);
   }
 
-  reduce () {
+  toggleStable() {
+    this.props.toggleStable(this.props.stable);
+  }
+
+  reduce() {
     if (!this.props.showReduce) {
       return null;
     }
@@ -64,7 +80,8 @@ export default class MainFieldsView extends React.Component {
     return (
       <span>
         <div className="checkbox inline">
-          <input id="qoReduce" name="reduce" onChange={this.toggleReduce.bind(this)} type="checkbox" checked={this.props.reduce} />
+          <input id="qoReduce" name="reduce" onChange={this.toggleReduce.bind(this)} type="checkbox"
+            checked={this.props.reduce}/>
           <label htmlFor="qoReduce">Reduce</label>
         </div>
         {this.groupLevel()}
@@ -72,25 +89,44 @@ export default class MainFieldsView extends React.Component {
     );
   }
 
-  render () {
-    var includeDocs = this.props.includeDocs;
+  getUpdateOptions() {
+    return this.updateOptions.map(option => <option key={option.value} value={option.value}>{option.label}</option>);
+  }
+
+  render() {
+    let {includeDocs, stable, update} = this.props;
     return (
       <div className="query-group" id="query-options-main-fields">
         <span className="add-on">
           Query Options
           <a className="help-link" href={this.props.docURL} target="_blank" data-bypass="true">
-            <i className="icon-question-sign" />
+            <i className="icon-question-sign"/>
           </a>
         </span>
         <div className="controls-group qo-main-fields-row">
           <div className="row-fluid fieldsets">
             <div className="checkbox inline">
               <input disabled={this.props.reduce} onChange={this.toggleIncludeDocs.bind(this)} id="qoIncludeDocs"
-                name="include_docs" type="checkbox" checked={includeDocs} />
-              <label className={this.props.reduce ? 'disabled' : ''} htmlFor="qoIncludeDocs" id="qoIncludeDocsLabel">Include Docs</label>
+                name="include_docs" type="checkbox" checked={includeDocs}/>
+              <label className={this.props.reduce ? 'disabled' : ''} htmlFor="qoIncludeDocs" id="qoIncludeDocsLabel">Include
+                  Docs</label>
             </div>
             {this.reduce()}
           </div>
+          <div className="row-fluid fieldsets">
+            <div className="checkbox inline">
+              <input onChange={this.toggleStable} id="qoStable"
+                name="include_docs" type="checkbox" checked={stable}/>
+              <label htmlFor="qoStable" id="qoStableLabel">Stable</label>
+            </div>
+            <div className="dropdown inline">
+              <label className="drop-down">Update
+              <select className="input-small" id="qoUpdate" value={update} onChange={this.onUpdateChange}>
+                {this.getUpdateOptions()}
+              </select>
+              </label>
+            </div>
+          </div>
         </div>
       </div>
     );
@@ -104,5 +140,9 @@ MainFieldsView.propTypes = {
   reduce: PropTypes.bool.isRequired,
   toggleReduce: PropTypes.func,
   updateGroupLevel: PropTypes.func,
-  docURL: PropTypes.string.isRequired
+  docURL: PropTypes.string.isRequired,
+  stable: PropTypes.bool.isRequired,
+  toggleStable: PropTypes.func.isRequired,
+  update: PropTypes.string.isRequired,
+  changeUpdateField: PropTypes.func.isRequired
 };
diff --git a/app/addons/documents/index-results/components/queryoptions/QueryOptions.js b/app/addons/documents/index-results/components/queryoptions/QueryOptions.js
index 0727cd9..8b65e46 100644
--- a/app/addons/documents/index-results/components/queryoptions/QueryOptions.js
+++ b/app/addons/documents/index-results/components/queryoptions/QueryOptions.js
@@ -112,7 +112,12 @@ export default class QueryOptions extends React.Component {
             toggleReduce={this.props.queryOptionsToggleReduce}
             groupLevel={this.props.groupLevel}
             updateGroupLevel={this.props.queryOptionsUpdateGroupLevel}
-            docURL={FauxtonAPI.constants.DOC_URLS.GENERAL} />
+            docURL={FauxtonAPI.constants.DOC_URLS.GENERAL}
+            stable={this.props.stable}
+            toggleStable={this.props.queryOptionsToggleStable}
+            update={this.props.update}
+            changeUpdateField={this.props.queryOptionsChangeUpdate}
+          />
           <KeySearchFields
             key={1}
             showByKeys={this.props.showByKeys}
@@ -137,9 +142,9 @@ export default class QueryOptions extends React.Component {
   }
 
   showAsActive() {
-    const { reduce, betweenKeys, byKeys, descending, skip, limit } = this.props;
+    const { reduce, betweenKeys, byKeys, descending, skip, limit, stable, update } = this.props;
     return !!((betweenKeys && betweenKeys.startkey) ||
-      byKeys || (limit && limit != 'none') || skip || reduce || descending);
+      byKeys || (limit && limit != 'none') || skip || reduce || descending || stable || update !== 'true');
   }
 
   render () {
@@ -173,5 +178,9 @@ QueryOptions.propTypes = {
   resetPagination: PropTypes.func.isRequired,
   selectedLayout: PropTypes.string.isRequired,
   changeLayout: PropTypes.func.isRequired,
-  queryOptionsToggleVisibility: PropTypes.func.isRequired
+  queryOptionsToggleVisibility: PropTypes.func.isRequired,
+  queryOptionsToggleStable: PropTypes.func.isRequired,
+  queryOptionsChangeUpdate: PropTypes.func.isRequired,
+  stable: PropTypes.bool.isRequired,
+  update: PropTypes.string.isRequired
 };
diff --git a/app/addons/documents/index-results/containers/QueryOptionsContainer.js b/app/addons/documents/index-results/containers/QueryOptionsContainer.js
index 179f67e..0052577 100644
--- a/app/addons/documents/index-results/containers/QueryOptionsContainer.js
+++ b/app/addons/documents/index-results/containers/QueryOptionsContainer.js
@@ -30,7 +30,9 @@ import {
   queryOptionsToggleIncludeDocs,
   queryOptionsToggleVisibility,
   queryOptionsFilterOnlyDdocs,
-  queryOptionsRemoveFilterOnlyDdocs
+  queryOptionsRemoveFilterOnlyDdocs,
+  queryOptionsToggleStable,
+  queryOptionsChangeUpdate,
 } from '../actions/queryoptions';
 import {
   getQueryOptionsPanel,
@@ -59,6 +61,8 @@ const mapStateToProps = ({indexResults, sidebar}, ownProps) => {
     descending: queryOptionsPanel.descending,
     skip: queryOptionsPanel.skip,
     limit: queryOptionsPanel.limit,
+    stable: queryOptionsPanel.stable,
+    update: queryOptionsPanel.update,
     fetchParams: getFetchParams(indexResults),
     queryOptionsParams: getQueryOptionsParams(indexResults),
     perPage: getPerPage(indexResults),
@@ -114,6 +118,14 @@ const mapDispatchToProps = (dispatch, ownProps) => {
     queryOptionsRemoveFilterOnlyDdocs: () => {
       dispatch(queryOptionsRemoveFilterOnlyDdocs());
     },
+
+    queryOptionsToggleStable: previous =>{
+      dispatch(queryOptionsToggleStable(previous));
+    },
+
+    queryOptionsChangeUpdate: stale => {
+      dispatch(queryOptionsChangeUpdate(stale));
+    },
     changeLayout: (newLayout) => {
       dispatch(changeLayout(newLayout));
     },
diff --git a/app/addons/documents/index-results/reducers.js b/app/addons/documents/index-results/reducers.js
index 426a7da..22d984b 100644
--- a/app/addons/documents/index-results/reducers.js
+++ b/app/addons/documents/index-results/reducers.js
@@ -13,9 +13,9 @@
 import app from "../../../app";
 import ActionTypes from './actiontypes';
 import Constants from '../constants';
-import { getJsonViewData } from './helpers/json-view';
-import { getTableViewData } from './helpers/table-view';
-import { getDefaultPerPage, getDocId, isJSONDocBulkDeletable } from './helpers/shared-helpers';
+import {getJsonViewData} from './helpers/json-view';
+import {getTableViewData} from './helpers/table-view';
+import {getDefaultPerPage, getDocId, isJSONDocBulkDeletable} from './helpers/shared-helpers';
 
 const initialState = {
   docs: [],  // raw documents returned from couch
@@ -55,7 +55,9 @@ const initialState = {
     limit: 'none',
     reduce: false,
     groupLevel: 'exact',
-    showReduce: false
+    showReduce: false,
+    stable: false,
+    update: 'true'
   }
 };
 
@@ -182,7 +184,7 @@ export const removeGeneratedMangoDocs = (doc) => {
 
 // transform the docs in to a state ready for rendering on the page
 export const getDataForRendering = (state, databaseName, deleteEnabled = true) => {
-  const { docs } = state;
+  const {docs} = state;
   const options = {
     databaseName: databaseName,
     selectedLayout: state.selectedLayout,
@@ -276,7 +278,7 @@ export const getDisplayedFields = (state, databaseName) => {
 };
 
 export const getQueryOptionsParams = (state) => {
-  const { queryOptionsPanel } = state;
+  const {queryOptionsPanel} = state;
   const params = {};
 
   if (queryOptionsPanel.includeDocs) {
@@ -320,6 +322,14 @@ export const getQueryOptionsParams = (state) => {
     }
   }
 
+  if (queryOptionsPanel.update !== undefined) {
+    params.update = queryOptionsPanel.update;
+  }
+
+  if (typeof queryOptionsPanel.stable === 'boolean') {
+    params.stable = queryOptionsPanel.stable;
+  }
+
   return params;
 };
 

-- 
To stop receiving notification emails like this one, please contact
garren@apache.org.