You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@couchdb.apache.org by GitBox <gi...@apache.org> on 2018/10/09 03:21:56 UTC

[GitHub] Antonio-Maranhao closed pull request #1128: [partitioned-dbs] Partition key selector

Antonio-Maranhao closed pull request #1128: [partitioned-dbs] Partition key selector
URL: https://github.com/apache/couchdb-fauxton/pull/1128
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/app/addons/databases/actions.js b/app/addons/databases/actions.js
index 6b1c57040..1935491c1 100644
--- a/app/addons/databases/actions.js
+++ b/app/addons/databases/actions.js
@@ -199,12 +199,14 @@ export default {
   },
 
   setPartitionedDatabasesAvailable(available) {
-    FauxtonAPI.dispatch({
+    const action = {
       type: ActionTypes.DATABASES_PARTITIONED_DB_AVAILABLE,
       options: {
         available
       }
-    });
+    };
+    FauxtonAPI.dispatch(action);
+    FauxtonAPI.reduxDispatch(action);
   },
 
   checkPartitionedQueriesIsAvailable() {
diff --git a/app/addons/databases/base.js b/app/addons/databases/base.js
index 92f2e75a5..c4218d4f0 100644
--- a/app/addons/databases/base.js
+++ b/app/addons/databases/base.js
@@ -32,7 +32,7 @@ function checkPartitionedDatabaseFeature () {
   // Checks if the CouchDB server supports Partitioned Databases
   return get(Helpers.getServerUrl("/")).then((couchdb) => {
     //TODO: needs to be updated with the correct feature name
-    return couchdb.features && couchdb.features.includes('partitioned-dbs');
+    return couchdb.features && couchdb.features.includes('partitions');
   }).catch(() => {
     return false;
   });
diff --git a/app/addons/databases/reducers.js b/app/addons/databases/reducers.js
new file mode 100644
index 000000000..74da7c4ce
--- /dev/null
+++ b/app/addons/databases/reducers.js
@@ -0,0 +1,27 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+import ActionTypes from './actiontypes';
+const initialState = {
+  partitionedDatabasesAvailable: false
+};
+export default function databases(state = initialState, action) {
+  switch (action.type) {
+    case ActionTypes.DATABASES_PARTITIONED_DB_AVAILABLE:
+      return {
+        ...state,
+        partitionedDatabasesAvailable: action.options.available
+      };
+    default:
+      return state;
+  }
+}
diff --git a/app/addons/documents/__tests__/partition-key.js b/app/addons/documents/__tests__/partition-key.js
new file mode 100644
index 000000000..75005e912
--- /dev/null
+++ b/app/addons/documents/__tests__/partition-key.js
@@ -0,0 +1,122 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+import React from 'react';
+import ReactDOM from 'react-dom';
+import { shallow } from 'enzyme';
+import PartitionKeySelector from '../partition-key/PartitionKeySelector';
+import sinon from 'sinon';
+
+describe('PartitionKeySelector', () => {
+  // const props = {
+  //   includeDocs: false,
+  //   queryOptionsToggleIncludeDocs: () => {},
+  //   reduce: false,
+  //   contentVisible: true,
+  //   perPage: 10,
+  //   queryOptionsToggleStable: () => {},
+  //   queryOptionsChangeUpdate: () => {},
+  //   stable: false,
+  //   update: 'true'
+  // };
+
+  const defaultProps = {
+    selectorVisible: true,
+    partitionKey: '',
+    checkDbPartitioned: () => {},
+    onPartitionKeySelected: () => {}
+  };
+
+  it('is only rendered when selectorVisible is set to true', () => {
+    const wrapper = shallow(<PartitionKeySelector
+      {...defaultProps}
+      selectorVisible={false}
+    />);
+    expect(wrapper.find('div.partition-selector').exists()).toBe(false);
+
+    const wrapper2 = shallow(<PartitionKeySelector
+      {...defaultProps}
+      selectorVisible={true}
+    />);
+    expect(wrapper2.find('div.partition-selector').exists()).toBe(true);
+  });
+
+  it('uses global mode by default', () => {
+    const wrapper = shallow(<PartitionKeySelector
+      {...defaultProps}
+      partitionKey='part1'
+    />);
+
+    const btLabel = wrapper.find('div').text();
+    expect(btLabel).toMatch('No partition selected');
+  });
+
+  it('switches from global mode to partition mode when a key is already set', () => {
+    const spyOnKeySelected = sinon.spy();
+    const wrapper = shallow(<PartitionKeySelector
+      {...defaultProps}
+      partitionKey='part1'
+      globalMode={true}
+      onPartitionKeySelected={spyOnKeySelected}
+    />);
+
+    wrapper.find('button').simulate('click');
+    expect(spyOnKeySelected.calledOnce).toBe(true);
+  });
+
+  it('if a key is not set switching from global mode shows the text input', () => {
+    const spyOnKeySelected = sinon.spy();
+    const wrapper = shallow(<PartitionKeySelector
+      {...defaultProps}
+      partitionKey=''
+      globalMode={true}
+      onPartitionKeySelected={spyOnKeySelected}
+    />);
+
+    expect(wrapper.state().editMode).toBe(false);
+    wrapper.find('button').simulate('click');
+    expect(wrapper.state().editMode).toBe(true);
+    expect(spyOnKeySelected.calledOnce).toBe(false);
+  });
+
+  it('switches from partition mode to global mode', () => {
+    const spyOnGlobalSelected = sinon.spy();
+    const wrapper = shallow(<PartitionKeySelector
+      {...defaultProps}
+      partitionKey='part1'
+      globalMode={false}
+      onGlobalModeSelected={spyOnGlobalSelected}
+    />);
+
+    wrapper.find('button').simulate('click');
+    expect(spyOnGlobalSelected.calledOnce).toBe(true);
+  });
+
+  it('calls onPartitionKeySelected when a new value is set in the text input', () => {
+    const spyOnKeySelected = sinon.spy();
+    const wrapper = shallow(<PartitionKeySelector
+      {...defaultProps}
+      partitionKey=''
+      globalMode={true}
+      onPartitionKeySelected={spyOnKeySelected}
+    />);
+
+    // Start edit mode
+    wrapper.find('button').simulate('click');
+    expect(wrapper.state().editMode).toBe(true);
+    // Set new value
+    wrapper.find('input').simulate('change', { target: { value: 'new_part_key' } });
+    wrapper.find('input').simulate('keypress', {key: 'Enter'});
+    expect(spyOnKeySelected.calledOnce).toBe(true);
+  });
+
+});
diff --git a/app/addons/documents/assets/less/documents.less b/app/addons/documents/assets/less/documents.less
index be7f46084..c161e9bf3 100644
--- a/app/addons/documents/assets/less/documents.less
+++ b/app/addons/documents/assets/less/documents.less
@@ -22,6 +22,7 @@
 @import "header.less";
 @import "revision-browser.less";
 @import "header-docs-left.less";
+@import "partition-key.less";
 
 
 button.beautify {
diff --git a/app/addons/documents/assets/less/partition-key.less b/app/addons/documents/assets/less/partition-key.less
new file mode 100644
index 000000000..bf8d1a97a
--- /dev/null
+++ b/app/addons/documents/assets/less/partition-key.less
@@ -0,0 +1,52 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+@import "../../../../../assets/less/variables.less";
+
+.partition-selector {
+  display: flex;
+  align-items: center;
+  padding: 0;
+  min-height: 30px;
+}
+
+.partition-selector__switch {
+  background-color: transparent;
+  border: none;
+  color: #666;
+  font-size: 1rem;
+  .fonticon-filter {
+    font-size: 1.25rem;
+    padding-right: 6px;
+  }
+  &:hover {
+    color: @hoverHighlight;
+  }
+}
+
+.partition-selector__switch--active {
+  color: @brandHighlight;
+  padding-right: 0px;
+}
+
+.partition-selector__key {
+  flex: 1;
+  color: #666;
+}
+
+.partition-selector__key--active {
+  color: @brandHighlight;
+}
+
+.partition-selector__global {
+  color: #666;
+}
diff --git a/app/addons/documents/base.js b/app/addons/documents/base.js
index 144be20fd..6809d5ffb 100644
--- a/app/addons/documents/base.js
+++ b/app/addons/documents/base.js
@@ -17,6 +17,7 @@ import Documents from "./routes";
 import reducers from "./index-results/reducers";
 import mangoReducers from "./mango/mango.reducers";
 import sidebarReducers from "./sidebar/reducers";
+import partitionKeyReducers from "./partition-key/reducers";
 import revisionBrowserReducers from './rev-browser/reducers';
 import "./assets/less/documents.less";
 
@@ -24,7 +25,8 @@ FauxtonAPI.addReducers({
   indexResults: reducers,
   mangoQuery: mangoReducers,
   sidebar: sidebarReducers,
-  revisionBrowser: revisionBrowserReducers
+  revisionBrowser: revisionBrowserReducers,
+  partitionKey: partitionKeyReducers
 });
 
 function getQueryParam (query) {
@@ -49,6 +51,12 @@ FauxtonAPI.registerUrls('allDocs', {
   }
 });
 
+FauxtonAPI.registerUrls('partitioned_allDocs', {
+  app: function (databaseName, partitionKey, query) {
+    return 'database/' + databaseName + '/_partition/' + partitionKey + '/_all_docs' + getQueryParam(query);
+  }
+});
+
 FauxtonAPI.registerUrls('allDocsSanitized', {
   server: function (id, query) {
     id = encodeURIComponent(id);
@@ -124,6 +132,18 @@ FauxtonAPI.registerUrls('view', {
   }
 });
 
+FauxtonAPI.registerUrls('partitioned_view', {
+  server: function (database, partitionKey, designDoc, viewName) {
+    return Helpers.getServerUrl('/' + database + '/_partition/' + partitionKey + '/_design/' + designDoc + '/_view/' + viewName);
+  },
+  app: function (database, partitionKey, designDoc) {
+    return 'database/' + database + '/_partition/' + partitionKey + '/_design/' + designDoc + '/_view/';
+  },
+  apiurl: function (database, partitionKey, designDoc, viewName) {
+    return Helpers.getApiUrl('/' + database + '/_partition/' + partitionKey + '/_design/' + designDoc + '/_view/' + viewName);
+  }
+});
+
 FauxtonAPI.registerUrls('document', {
   server: function (database, doc, query) {
     if (_.isUndefined(query)) {
diff --git a/app/addons/documents/layouts.js b/app/addons/documents/layouts.js
index 8a0c05ca9..bd6f680a6 100644
--- a/app/addons/documents/layouts.js
+++ b/app/addons/documents/layouts.js
@@ -24,6 +24,7 @@ import IndexResultsContainer from './index-results/containers/IndexResultsContai
 import PaginationContainer from './index-results/containers/PaginationContainer';
 import ApiBarContainer from './index-results/containers/ApiBarContainer';
 import { queryAllDocs, queryMapReduceView } from './index-results/api';
+import PartitionKeySelectorContainer from './partition-key/container';
 import Constants from './constants';
 import Helpers from './helpers';
 
@@ -39,8 +40,21 @@ export const TabsSidebarHeader = ({
   fetchUrl,
   ddocsOnly,
   queryDocs,
-  selectedNavItem
+  selectedNavItem,
+  showPartitionKeySelector,
+  partitionKey,
+  onPartitionKeySelected,
+  onGlobalModeSelected,
+  globalMode
 }) => {
+  const partKeySelector = (<PartitionKeySelectorContainer
+    databaseName={dbName}
+    partitionKey={partitionKey}
+    onPartitionKeySelected={onPartitionKeySelected}
+    onGlobalModeSelected={onGlobalModeSelected}
+    globalMode={globalMode}/>
+  );
+
   return (
     <header className="two-panel-header">
       <div className="flex-layout flex-row">
@@ -51,6 +65,9 @@ export const TabsSidebarHeader = ({
           />
         </div>
         <div className="right-header-wrapper flex-layout flex-row flex-body">
+          <div style={{flex:1, padding: '18px 6px 12px 12px'}}>
+            {showPartitionKeySelector ? partKeySelector : null}
+          </div>
           <div id="right-header" className="flex-fill">
             <RightAllDocsHeader
               hideQueryOptions={hideQueryOptions}
@@ -81,11 +98,17 @@ TabsSidebarHeader.propTypes = {
   hideJumpToDoc: PropTypes.bool,
   database: PropTypes.object.isRequired,
   queryDocs: PropTypes.func,
-  selectedNavItem: PropTypes.object
+  selectedNavItem: PropTypes.object,
+  showPartitionKeySelector: PropTypes.bool,
+  partitionKey: PropTypes.string,
+  onPartitionKeySelected: PropTypes.func.isRequired,
+  onGlobalModeSelected: PropTypes.bool,
+  globalMode: PropTypes.bool
 };
 
 TabsSidebarHeader.defaultProps = {
-  hideHeaderBar: false
+  hideHeaderBar: false,
+  showPartitionKeySelector: false
 };
 
 export const TabsSidebarContent = ({
@@ -140,7 +163,11 @@ export const DocsTabsSidebarLayout = ({
   fetchUrl,
   ddocsOnly,
   deleteEnabled = true,
-  selectedNavItem
+  selectedNavItem,
+  partitionKey,
+  onPartitionKeySelected,
+  onGlobalModeSelected,
+  globalMode
 }) => {
   let queryDocs = (params) => { return queryAllDocs(fetchUrl, params); };
   if (Helpers.isViewSelected(selectedNavItem)) {
@@ -169,6 +196,11 @@ export const DocsTabsSidebarLayout = ({
         ddocsOnly={ddocsOnly}
         queryDocs={queryDocs}
         selectedNavItem={selectedNavItem}
+        showPartitionKeySelector={!ddocsOnly}
+        partitionKey={partitionKey}
+        onPartitionKeySelected={onPartitionKeySelected}
+        onGlobalModeSelected={onGlobalModeSelected}
+        globalMode={globalMode}
       />
       <TabsSidebarContent
         lowerContent={lowerContent}
diff --git a/app/addons/documents/partition-key/PartitionKeySelector.js b/app/addons/documents/partition-key/PartitionKeySelector.js
new file mode 100644
index 000000000..1bd8b5fde
--- /dev/null
+++ b/app/addons/documents/partition-key/PartitionKeySelector.js
@@ -0,0 +1,139 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+import PropTypes from 'prop-types';
+import React from "react";
+import ReactDOM from "react-dom";
+
+
+export default class PartitionKeySelector extends React.Component {
+
+  constructor(props) {
+    super(props);
+    this.state = {
+      editorValue: '',
+      editMode: false
+    };
+    this.onModeSwitchClick = this.onModeSwitchClick.bind(this);
+    this.onBlur = this.onBlur.bind(this);
+    this.startEdit = this.startEdit.bind(this);
+    this.onKeyPress = this.onKeyPress.bind(this);
+    this.onChange = this.onChange.bind(this);
+    this.props.checkDbPartitioned(this.props.databaseName);
+  }
+
+  onModeSwitchClick(e) {
+    if (e && e.preventDefault) {
+      e.preventDefault();
+    }
+    if (!this.props.globalMode && this.props.onGlobalModeSelected) {
+      this.props.onGlobalModeSelected();
+    } else if (this.props.partitionKey) {
+      this.props.onPartitionKeySelected(this.state.editorValue);
+    } else {
+      this.startEdit();
+    }
+  }
+
+  startEdit() {
+    this.setState({editMode: true, editorValue: this.props.partitionKey});
+    setTimeout(() => this.textInput.focus());
+  }
+
+  onBlur(e) {
+    if (e && e.preventDefault) {
+      e.preventDefault();
+    }
+    this.setState({editMode: false});
+  }
+
+  onKeyPress(e) {
+    if (e.key === 'Enter') {
+      this.setState({
+        editMode: false
+      });
+      this.props.onPartitionKeySelected(this.state.editorValue);
+    }
+  }
+
+  isPartitionSelected() {
+    return !this.state.global && (this.props.partitionKey.trim().length > 0);
+  }
+
+  onChange(e) {
+    this.setState({editorValue: e.target.value});
+  }
+
+  globalHeader() {
+    return (
+      <button onClick={this.onModeSwitchClick} title="Partition Key Selector" className="button partition-selector__switch">
+        <i className="fonticon-filter"></i>
+        No partition selected
+      </button>
+    );
+  }
+
+  partitionHeader() {
+    const editor = (
+      <input type="text"
+        style={{padding:2, fontSize:16, margin: 0, display: this.state.editMode ? 'block' : 'none'}}
+        onKeyPress={this.onKeyPress}
+        onChange={this.onChange}
+        onBlur={this.onBlur}
+        value={this.state.editorValue}
+        ref={(input) => { this.textInput = input; }} />
+    );
+    let partName = 'Click to select a partition';
+    let className = 'partition-selector__key';
+    if (this.props.partitionKey !== '') {
+      partName = this.props.partitionKey;
+      className += ' partition-selector__key--active';
+    }
+    return (
+      <React.Fragment>
+        <button onClick={this.onModeSwitchClick} title="Partition Key Selector" className="button partition-selector__switch button partition-selector__switch--active">
+          <i className="fonticon-filter"></i>
+        </button>
+        <div className={className}>
+          <span onClick={this.startEdit} style={{display: this.state.editMode ? 'none' : 'block'}}>{partName}</span>
+          {editor}
+        </div>
+      </React.Fragment>
+    );
+  }
+
+  render() {
+    if (!this.props.selectorVisible) {
+      return null;
+    }
+    const global = this.props.globalMode && !this.state.editMode;
+    return (
+      <div className="partition-selector" >
+        {global ? this.globalHeader() : this.partitionHeader()}
+      </div>
+    );
+  }
+}
+
+PartitionKeySelector.defaultProps = {
+  partitionKey: '',
+  globalMode: true
+};
+
+PartitionKeySelector.propTypes = {
+  selectorVisible: PropTypes.bool.isRequired,
+  partitionKey: PropTypes.string.isRequired,
+  checkDbPartitioned: PropTypes.func.isRequired,
+  onPartitionKeySelected: PropTypes.func.isRequired,
+  onGlobalModeSelected: PropTypes.func,
+  globalMode: PropTypes.bool
+};
diff --git a/app/addons/documents/partition-key/actions.js b/app/addons/documents/partition-key/actions.js
new file mode 100644
index 000000000..ebf076ca1
--- /dev/null
+++ b/app/addons/documents/partition-key/actions.js
@@ -0,0 +1,29 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+import * as API from './api';
+import ActionTypes from './actiontypes';
+
+export const checkDbPartitioned = (databaseName) => (dispatch) => {
+  //Reset visibility to false
+  dispatch({
+    type: ActionTypes.PARTITON_KEY_HIDE_SELECTOR
+  });
+
+  API.fetchDatabaseInfo(databaseName).then(dbInfo => {
+    if (dbInfo.props && dbInfo.props.partitioned === true) {
+      dispatch({
+        type: ActionTypes.PARTITON_KEY_SHOW_SELECTOR
+      });
+    }
+  });
+};
diff --git a/app/addons/documents/partition-key/actiontypes.js b/app/addons/documents/partition-key/actiontypes.js
new file mode 100644
index 000000000..76368ef6f
--- /dev/null
+++ b/app/addons/documents/partition-key/actiontypes.js
@@ -0,0 +1,15 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+export default {
+  PARTITON_KEY_SHOW_SELECTOR: 'PARTITON_KEY_SHOW_SELECTOR',
+  PARTITON_KEY_HIDE_SELECTOR: 'PARTITON_KEY_HIDE_SELECTOR'
+};
diff --git a/app/addons/documents/partition-key/api.js b/app/addons/documents/partition-key/api.js
new file mode 100644
index 000000000..720d69f45
--- /dev/null
+++ b/app/addons/documents/partition-key/api.js
@@ -0,0 +1,20 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+import '@webcomponents/url';
+import {get} from '../../../core/ajax';
+import Helpers from "../../../helpers";
+
+export const fetchDatabaseInfo = (databaseName) => {
+  const url = Helpers.getServerUrl("/" + encodeURIComponent(databaseName));
+  return get(url);
+};
diff --git a/app/addons/documents/partition-key/container.js b/app/addons/documents/partition-key/container.js
new file mode 100644
index 000000000..0a1d37351
--- /dev/null
+++ b/app/addons/documents/partition-key/container.js
@@ -0,0 +1,49 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+import PropTypes from 'prop-types';
+import { connect } from 'react-redux';
+import PartitionKeySelector from './PartitionKeySelector';
+import { checkDbPartitioned } from './actions';
+
+const mapStateToProps = ({ partitionKey }, ownProps) => {
+  return {
+    selectorVisible: partitionKey.selectorVisible,
+    databaseName: ownProps.databaseName,
+    partitionKey: ownProps.partitionKey,
+    onPartitionKeySelected: ownProps.onPartitionKeySelected,
+    globalMode: ownProps.globalMode
+  };
+};
+
+const mapDispatchToProps = (dispatch) => {
+  return {
+    checkDbPartitioned: (databaseName) => {
+      dispatch(checkDbPartitioned(databaseName));
+    }
+  };
+};
+
+const PartitionKeySelectorContainer = connect (
+  mapStateToProps,
+  mapDispatchToProps
+)(PartitionKeySelector);
+
+export default PartitionKeySelectorContainer;
+
+PartitionKeySelectorContainer.propTypes = {
+  databaseName: PropTypes.string.isRequired,
+  partitionKey: PropTypes.string.isRequired,
+  onPartitionKeySelected: PropTypes.func.isRequired,
+  onGlobalModeSelected: PropTypes.func.isRequired,
+  globalMode: PropTypes.bool
+};
diff --git a/app/addons/documents/partition-key/reducers.js b/app/addons/documents/partition-key/reducers.js
new file mode 100644
index 000000000..8da4ad3df
--- /dev/null
+++ b/app/addons/documents/partition-key/reducers.js
@@ -0,0 +1,37 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+import ActionTypes from './actiontypes';
+
+const initialState = {
+  selectorVisible: false
+};
+
+export default function partitionKey(state = initialState, action) {
+  switch (action.type) {
+
+    case ActionTypes.PARTITON_KEY_SHOW_SELECTOR:
+      return {
+        ...state,
+        selectorVisible: true
+      };
+
+    case ActionTypes.PARTITON_KEY_HIDE_SELECTOR:
+      return {
+        ...state,
+        selectorVisible: false
+      };
+
+    default:
+      return state;
+  }
+}
diff --git a/app/addons/documents/routes-documents.js b/app/addons/documents/routes-documents.js
index 453003a54..41c7493a3 100644
--- a/app/addons/documents/routes-documents.js
+++ b/app/addons/documents/routes-documents.js
@@ -23,8 +23,12 @@ import {DocsTabsSidebarLayout, ViewsTabsSidebarLayout, ChangesSidebarLayout} fro
 
 var DocumentsRouteObject = BaseRoute.extend({
   routes: {
+    "database/:database/_partition/:partitionkey/_all_docs": {
+      route: "partitionedAllDocs",
+      roles: ["fx_loggedIn"]
+    },
     "database/:database/_all_docs(:extra)": {
-      route: "allDocs",
+      route: "globalAllDocs",
       roles: ["fx_loggedIn"]
     },
     "database/:database/_design/:ddoc/_info": {
@@ -70,12 +74,20 @@ var DocumentsRouteObject = BaseRoute.extend({
     />;
   },
 
+  globalAllDocs: function (databaseName, options) {
+    return this.allDocs(databaseName, '', options);
+  },
+
+  partitionedAllDocs: function (databaseName, partitionKey) {
+    return this.allDocs(databaseName, partitionKey);
+  },
+
   /*
   * docParams are the options fauxton uses to fetch from the server
   * urlParams are what are shown in the url and to the user
   * They are not the same when paginating
   */
-  allDocs: function (databaseName, options) {
+  allDocs: function (databaseName, partitionKey, options) {
     const params = this.createParams(options),
           docParams = params.docParams;
 
@@ -95,7 +107,15 @@ var DocumentsRouteObject = BaseRoute.extend({
 
     const endpoint = this.database.allDocs.urlRef("apiurl", {});
     const docURL = FauxtonAPI.constants.DOC_URLS.GENERAL;
-
+    const navigateToPartitionedAllDocs = (partKey) => {
+      const baseUrl = FauxtonAPI.urls('partitioned_allDocs', 'app', encodeURIComponent(databaseName),
+        encodeURIComponent(partKey));
+      FauxtonAPI.navigate('#/' + baseUrl);
+    };
+    const navigateToGlobalAllDocs = () => {
+      const baseUrl = FauxtonAPI.urls('allDocs', 'app', encodeURIComponent(databaseName));
+      FauxtonAPI.navigate('#/' + baseUrl);
+    };
     const dropDownLinks = this.getCrumbs(this.database);
     return <DocsTabsSidebarLayout
       docURL={docURL}
@@ -107,6 +127,10 @@ var DocumentsRouteObject = BaseRoute.extend({
       fetchUrl={url}
       ddocsOnly={onlyShowDdocs}
       selectedNavItem={selectedNavItem}
+      partitionKey={partitionKey}
+      onPartitionKeySelected={navigateToPartitionedAllDocs}
+      onGlobalModeSelected={navigateToGlobalAllDocs}
+      globalMode={partitionKey === ''}
     />;
   },
 
diff --git a/app/addons/documents/routes-index-editor.js b/app/addons/documents/routes-index-editor.js
index 935ff4763..1485b56af 100644
--- a/app/addons/documents/routes-index-editor.js
+++ b/app/addons/documents/routes-index-editor.js
@@ -29,8 +29,12 @@ const IndexEditorAndResults = BaseRoute.extend({
       route: 'createView',
       roles: ['fx_loggedIn']
     },
+    'database/:database/_partition/:partitionkey/_design/:ddoc/_view/:view': {
+      route: 'showPartitionedView',
+      roles: ['fx_loggedIn']
+    },
     'database/:database/_design/:ddoc/_view/:view': {
-      route: 'showView',
+      route: 'showGlobalView',
       roles: ['fx_loggedIn']
     },
     'database/:database/_design/:ddoc/_view/:view/edit': {
@@ -47,8 +51,15 @@ const IndexEditorAndResults = BaseRoute.extend({
     this.addSidebar();
   },
 
-  showView: function (databaseName, ddoc, viewName) {
+  showGlobalView: function (databaseName, ddoc, viewName) {
+    return this.showView(databaseName, '', ddoc, viewName);
+  },
+
+  showPartitionedView: function (databaseName, partitionKey, ddoc, viewName) {
+    return this.showView(databaseName, partitionKey, ddoc, viewName);
+  },
 
+  showView: function (databaseName, partitionKey, ddoc, viewName) {
     viewName = viewName.replace(/\?.*$/, '');
 
     ActionsIndexEditor.clearIndex();
@@ -72,7 +83,11 @@ const IndexEditorAndResults = BaseRoute.extend({
     const endpoint = FauxtonAPI.urls('view', 'apiurl', encodeURIComponent(databaseName),
       encodeURIComponent(ddoc), encodeURIComponent(viewName));
     const docURL = FauxtonAPI.constants.DOC_URLS.GENERAL;
-
+    const navigateToPartitionedView = (partKey) => {
+      const baseUrl = FauxtonAPI.urls('partitioned_view', 'app', encodeURIComponent(databaseName),
+        encodeURIComponent(partKey), encodeURIComponent(ddoc));
+      FauxtonAPI.navigate('#/' + baseUrl + encodeURIComponent(viewName));
+    };
     const dropDownLinks = this.getCrumbs(this.database);
     return <DocsTabsSidebarLayout
       docURL={docURL}
@@ -84,6 +99,9 @@ const IndexEditorAndResults = BaseRoute.extend({
       ddocsOnly={false}
       deleteEnabled={false}
       selectedNavItem={selectedNavItem}
+      partitionKey={partitionKey}
+      onPartitionKeySelected={navigateToPartitionedView}
+      globalMode={partitionKey === ''}
     />;
   },
 


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services