You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@couchdb.apache.org by benkeen <gi...@git.apache.org> on 2015/02/11 02:05:39 UTC

[GitHub] couchdb-fauxton pull request: Changes page Filters tab moved to Re...

GitHub user benkeen opened a pull request:

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

    Changes page Filters tab moved to React

    This updates the Filter tab and filter on the Changes page
    to use React. It also ports over Components.FilterView and
    Components.FilterViewItem found in fauxton/components.js
    
    - There are no tests yet. I wanted to confirm I'm not barking
    up the wrong tree with any of this first.
    - I was thinking it would be cleaner to move the two
    fauxton/components (FilterView/FilterViewItem) into their own
    folder, along with their own store, actions and action types?
    More files, but it feels a bit weird to just load up those files
    with unrelated events.

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

    $ git pull https://github.com/benkeen/couchdb-fauxton changes-page-react

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

    https://github.com/apache/couchdb-fauxton/pull/265.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 #265
    
----
commit 3cd53b3a690b68523d1200baf2c375d49a8fceac
Author: Ben Keen <be...@gmail.com>
Date:   2015-02-11T01:04:23Z

    Changes page Filters tab moved to React
    
    This updates the Filter tab and content on the Changes page
    to use React. It also ports over Components.FilterView and
    Components.FilterViewItem found in fauxton/components
    
    - There are no tests yet. I wanted to confirm I'm not barking
    up the wrong tree with any of this first.
    - I was thinking it would be cleaner to move the two
    fauxton/components (FilterView/FilterViewItem) into their own
    folder, along with their own store, actions and action types.
    More files, but it feels a bit weird to just load up those files
    with unrelated events.

----


---
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: Changes page Filters tab moved to Re...

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

    https://github.com/apache/couchdb-fauxton/pull/265#issuecomment-74901031
  
    All fixed except for the last React error you spotted. I'll fix that up now. The code shouldn't allow adding the same item multiple times as it does right now; I spoke to Sean and I'm going to add an flash effect on the input field to indicate there's a problem. This is very much a fringe case, so that form of error should be sufficient.


---
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: Changes page Filters tab moved to Re...

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/265#discussion_r24685901
  
    --- Diff: app/addons/documents/changes/changes-header.react.jsx ---
    @@ -0,0 +1,236 @@
    +// Licensed under the Apache License, Version 2.0 (the "License"); you may not
    +// use this file except in compliance with the License. You may obtain a copy of
    +// the License at
    +//
    +//   http://www.apache.org/licenses/LICENSE-2.0
    +//
    +// Unless required by applicable law or agreed to in writing, software
    +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
    +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
    +// License for the specific language governing permissions and limitations under
    +// the License.
    +
    +define([
    +  'react',
    +  'addons/documents/changes/actions',
    +  'addons/documents/changes/stores'
    +], function (React, Actions, Stores) {
    +
    +  var changesFilterStore = Stores.changesFilterStore;
    +  var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;
    +
    +
    +  var ChangesHeader = React.createClass({
    +    getInitialState: function () {
    +      return {
    +        showTabContent: changesFilterStore.isTabVisible()
    +      };
    +    },
    +
    +    componentDidMount: function () {
    +      changesFilterStore.on('change', this.onChange, this);
    +    },
    +
    +    onChange: function () {
    +      this.setState({
    +        showTabContent: changesFilterStore.isTabVisible()
    +      });
    +    },
    +
    +    toggleFilterSection: function () {
    +      Actions.toggleTabVisibility();
    +    },
    +
    +    render: function () {
    +      var tabContent = '';
    +
    +      if (this.state.showTabContent) {
    +        tabContent = <ChangesHeaderTabContent key="changesFilterSection" />;
    +      }
    +
    +      return (
    +        <div className="changes-header-section">
    +          <ChangesHeaderTab onToggle={this.toggleFilterSection} />
    +          <ReactCSSTransitionGroup transitionName="toggleChangesFilter" component="div" className="changes-tab-content">
    +            {tabContent}
    +          </ReactCSSTransitionGroup>
    +        </div>
    +      );
    +    }
    +  });
    +
    +  var ChangesHeaderTab = React.createClass({
    +    propTypes: {
    +      onToggle: React.PropTypes.func.isRequired
    +    },
    +
    +    render: function () {
    +      return (
    +        <div className="dashboard-upper-menu">
    +          <ul className="nav nav-tabs" id="db-views-tabs-nav">
    +            <li>
    +              <a href="#filter" onClick={this.props.onToggle} data-bypass="true" data-toggle="tab">
    +                <i className="fonticon fonticon-plus"></i> Filter
    +              </a>
    +            </li>
    +          </ul>
    +        </div>
    +      );
    +    }
    +  });
    +
    +  var ChangesHeaderTabContent = React.createClass({
    +    render: function () {
    +      return (
    +        <div className="tab-content">
    +          <div className="tab-pane active" ref="filterTab">
    +            <div className="changes-header js-filter">
    +              <ChangesFilter />
    +            </div>
    +          </div>
    +        </div>
    +      );
    +    }
    +  });
    +
    +  var ChangesFilter = React.createClass({
    +    getStoreState: function () {
    +      return {
    +        filters: changesFilterStore.getFilters()
    +      };
    +    },
    +
    +    onChange: function () {
    +      this.setState(this.getStoreState());
    +    },
    +
    +    // props belong to the parent, so these aren't stored in the related store
    +    getDefaultProps: function () {
    +      return {
    +        addItemPlaceholder: 'Type a filter',
    +        helpText: 'e.g. debug or <1.4.1> or any regex',
    +        tooltip: ''
    +      };
    +    },
    +
    +    getInitialState: function () {
    +      return this.getStoreState();
    +    },
    +
    +    submitForm: function (e) {
    +      e.preventDefault();
    +      e.stopPropagation();
    +
    +
    +      var filter = this.refs.addItem.getDOMNode().value.trim();
    +      if (!filter) {
    +        return;
    +      }
    +
    +      Actions.addFilterViewItem(filter);
    +      this.refs.addItem.getDOMNode().value = '';
    --- End diff --
    
    Thanks, guys. I gave this one some thought and I'm kind of on the fence. I'm more than happy making to the change, but it seems to add a lot of complexity just to make it more idiomatic.
    
    If I understand it properly, I'd need to do the following:
    - new onChange handler to DOM element
    - handler which passing work to actions.js
    - new event added in actiontypes.js
    - state of input field value stored in the store
    - a handler in the store to update the value as 
    
    vs. what is it right now:
    - one line within the react view setting the input value to ''.
    
    I'm all for keeping the code as React-y as possible, but for me, this crosses the line. Ultimately, whole need to add in an onchange handler feels like a workaround to ensure state gets modified and that we can reset the value.
    
    [Perfectly happy being overruled, here. Just my 2 cents :)]


---
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: Changes page Filters tab moved to Re...

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

    https://github.com/apache/couchdb-fauxton/pull/265#discussion_r24658179
  
    --- Diff: app/addons/documents/changes/changes-header.react.jsx ---
    @@ -0,0 +1,236 @@
    +// Licensed under the Apache License, Version 2.0 (the "License"); you may not
    +// use this file except in compliance with the License. You may obtain a copy of
    +// the License at
    +//
    +//   http://www.apache.org/licenses/LICENSE-2.0
    +//
    +// Unless required by applicable law or agreed to in writing, software
    +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
    +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
    +// License for the specific language governing permissions and limitations under
    +// the License.
    +
    +define([
    +  'react',
    +  'addons/documents/changes/actions',
    +  'addons/documents/changes/stores'
    +], function (React, Actions, Stores) {
    +
    +  var changesFilterStore = Stores.changesFilterStore;
    +  var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;
    +
    +
    +  var ChangesHeader = React.createClass({
    +    getInitialState: function () {
    +      return {
    +        showTabContent: changesFilterStore.isTabVisible()
    +      };
    +    },
    +
    +    componentDidMount: function () {
    +      changesFilterStore.on('change', this.onChange, this);
    +    },
    +
    +    onChange: function () {
    +      this.setState({
    +        showTabContent: changesFilterStore.isTabVisible()
    +      });
    +    },
    +
    +    toggleFilterSection: function () {
    +      Actions.toggleTabVisibility();
    +    },
    +
    +    render: function () {
    +      var tabContent = '';
    +
    +      if (this.state.showTabContent) {
    +        tabContent = <ChangesHeaderTabContent key="changesFilterSection" />;
    +      }
    +
    +      return (
    +        <div className="changes-header-section">
    +          <ChangesHeaderTab onToggle={this.toggleFilterSection} />
    +          <ReactCSSTransitionGroup transitionName="toggleChangesFilter" component="div" className="changes-tab-content">
    +            {tabContent}
    +          </ReactCSSTransitionGroup>
    +        </div>
    +      );
    +    }
    +  });
    +
    +  var ChangesHeaderTab = React.createClass({
    +    propTypes: {
    +      onToggle: React.PropTypes.func.isRequired
    +    },
    +
    +    render: function () {
    +      return (
    +        <div className="dashboard-upper-menu">
    +          <ul className="nav nav-tabs" id="db-views-tabs-nav">
    +            <li>
    +              <a href="#filter" onClick={this.props.onToggle} data-bypass="true" data-toggle="tab">
    +                <i className="fonticon fonticon-plus"></i> Filter
    +              </a>
    +            </li>
    +          </ul>
    +        </div>
    +      );
    +    }
    +  });
    +
    +  var ChangesHeaderTabContent = React.createClass({
    +    render: function () {
    +      return (
    +        <div className="tab-content">
    +          <div className="tab-pane active" ref="filterTab">
    +            <div className="changes-header js-filter">
    +              <ChangesFilter />
    +            </div>
    +          </div>
    +        </div>
    +      );
    +    }
    +  });
    +
    +  var ChangesFilter = React.createClass({
    +    getStoreState: function () {
    +      return {
    +        filters: changesFilterStore.getFilters()
    +      };
    +    },
    +
    +    onChange: function () {
    +      this.setState(this.getStoreState());
    +    },
    +
    +    // props belong to the parent, so these aren't stored in the related store
    +    getDefaultProps: function () {
    --- End diff --
    
    I don't think we need these as props since they are never changed by the parent.


---
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: Changes page Filters tab moved to Re...

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

    https://github.com/apache/couchdb-fauxton/pull/265#discussion_r24658263
  
    --- Diff: app/addons/documents/changes/stores.js ---
    @@ -0,0 +1,73 @@
    +// Licensed under the Apache License, Version 2.0 (the "License"); you may not
    +// use this file except in compliance with the License. You may obtain a copy of
    +// the License at
    +//
    +//   http://www.apache.org/licenses/LICENSE-2.0
    +//
    +// Unless required by applicable law or agreed to in writing, software
    +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
    +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
    +// License for the specific language governing permissions and limitations under
    +// the License.
    +
    +define([
    +  'api',
    +  'addons/documents/changes/actiontypes'
    +], function (FauxtonAPI, ActionTypes) {
    +
    +
    +  var FilterViewStore = FauxtonAPI.Store.extend({
    +    initialize: function () {
    +      this.reset();
    +    },
    +
    +    reset: function () {
    +      this.filters = [];
    --- End diff --
    
    All internal variables for stores must be prefixed with an `_`. e.g `this._filters.


---
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: Changes page Filters tab moved to Re...

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/265#discussion_r24679844
  
    --- Diff: app/addons/documents/changes/changes-header.react.jsx ---
    @@ -0,0 +1,236 @@
    +// Licensed under the Apache License, Version 2.0 (the "License"); you may not
    +// use this file except in compliance with the License. You may obtain a copy of
    +// the License at
    +//
    +//   http://www.apache.org/licenses/LICENSE-2.0
    +//
    +// Unless required by applicable law or agreed to in writing, software
    +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
    +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
    +// License for the specific language governing permissions and limitations under
    +// the License.
    +
    +define([
    +  'react',
    +  'addons/documents/changes/actions',
    +  'addons/documents/changes/stores'
    +], function (React, Actions, Stores) {
    +
    +  var changesFilterStore = Stores.changesFilterStore;
    +  var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;
    +
    +
    +  var ChangesHeader = React.createClass({
    +    getInitialState: function () {
    +      return {
    +        showTabContent: changesFilterStore.isTabVisible()
    +      };
    +    },
    +
    +    componentDidMount: function () {
    +      changesFilterStore.on('change', this.onChange, this);
    +    },
    +
    +    onChange: function () {
    +      this.setState({
    +        showTabContent: changesFilterStore.isTabVisible()
    +      });
    +    },
    +
    +    toggleFilterSection: function () {
    +      Actions.toggleTabVisibility();
    +    },
    +
    +    render: function () {
    +      var tabContent = '';
    +
    +      if (this.state.showTabContent) {
    +        tabContent = <ChangesHeaderTabContent key="changesFilterSection" />;
    +      }
    +
    +      return (
    +        <div className="changes-header-section">
    +          <ChangesHeaderTab onToggle={this.toggleFilterSection} />
    +          <ReactCSSTransitionGroup transitionName="toggleChangesFilter" component="div" className="changes-tab-content">
    +            {tabContent}
    +          </ReactCSSTransitionGroup>
    +        </div>
    +      );
    +    }
    +  });
    +
    +  var ChangesHeaderTab = React.createClass({
    +    propTypes: {
    +      onToggle: React.PropTypes.func.isRequired
    +    },
    +
    +    render: function () {
    +      return (
    +        <div className="dashboard-upper-menu">
    +          <ul className="nav nav-tabs" id="db-views-tabs-nav">
    +            <li>
    +              <a href="#filter" onClick={this.props.onToggle} data-bypass="true" data-toggle="tab">
    +                <i className="fonticon fonticon-plus"></i> Filter
    +              </a>
    +            </li>
    +          </ul>
    +        </div>
    +      );
    +    }
    +  });
    +
    +  var ChangesHeaderTabContent = React.createClass({
    +    render: function () {
    +      return (
    +        <div className="tab-content">
    +          <div className="tab-pane active" ref="filterTab">
    +            <div className="changes-header js-filter">
    +              <ChangesFilter />
    +            </div>
    +          </div>
    +        </div>
    +      );
    +    }
    +  });
    +
    +  var ChangesFilter = React.createClass({
    +    getStoreState: function () {
    +      return {
    +        filters: changesFilterStore.getFilters()
    +      };
    +    },
    +
    +    onChange: function () {
    +      this.setState(this.getStoreState());
    +    },
    +
    +    // props belong to the parent, so these aren't stored in the related store
    +    getDefaultProps: function () {
    --- End diff --
    
    True. I just thought it would be good to design it in a generic way so that those could be easily changed down the road. But I guess I can remove 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: Changes page Filters tab moved to Re...

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

    https://github.com/apache/couchdb-fauxton/pull/265#discussion_r24658101
  
    --- Diff: app/addons/documents/changes/changes-header.react.jsx ---
    @@ -0,0 +1,236 @@
    +// Licensed under the Apache License, Version 2.0 (the "License"); you may not
    +// use this file except in compliance with the License. You may obtain a copy of
    +// the License at
    +//
    +//   http://www.apache.org/licenses/LICENSE-2.0
    +//
    +// Unless required by applicable law or agreed to in writing, software
    +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
    +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
    +// License for the specific language governing permissions and limitations under
    +// the License.
    +
    +define([
    +  'react',
    +  'addons/documents/changes/actions',
    +  'addons/documents/changes/stores'
    +], function (React, Actions, Stores) {
    +
    +  var changesFilterStore = Stores.changesFilterStore;
    +  var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;
    +
    +
    +  var ChangesHeader = React.createClass({
    +    getInitialState: function () {
    +      return {
    +        showTabContent: changesFilterStore.isTabVisible()
    +      };
    +    },
    +
    +    componentDidMount: function () {
    +      changesFilterStore.on('change', this.onChange, this);
    +    },
    +
    +    onChange: function () {
    +      this.setState({
    +        showTabContent: changesFilterStore.isTabVisible()
    +      });
    +    },
    +
    +    toggleFilterSection: function () {
    +      Actions.toggleTabVisibility();
    +    },
    +
    +    render: function () {
    +      var tabContent = '';
    +
    +      if (this.state.showTabContent) {
    +        tabContent = <ChangesHeaderTabContent key="changesFilterSection" />;
    +      }
    +
    +      return (
    +        <div className="changes-header-section">
    +          <ChangesHeaderTab onToggle={this.toggleFilterSection} />
    +          <ReactCSSTransitionGroup transitionName="toggleChangesFilter" component="div" className="changes-tab-content">
    +            {tabContent}
    +          </ReactCSSTransitionGroup>
    +        </div>
    +      );
    +    }
    +  });
    +
    +  var ChangesHeaderTab = React.createClass({
    +    propTypes: {
    +      onToggle: React.PropTypes.func.isRequired
    +    },
    +
    +    render: function () {
    +      return (
    +        <div className="dashboard-upper-menu">
    +          <ul className="nav nav-tabs" id="db-views-tabs-nav">
    +            <li>
    +              <a href="#filter" onClick={this.props.onToggle} data-bypass="true" data-toggle="tab">
    +                <i className="fonticon fonticon-plus"></i> Filter
    +              </a>
    +            </li>
    +          </ul>
    +        </div>
    +      );
    +    }
    +  });
    +
    +  var ChangesHeaderTabContent = React.createClass({
    +    render: function () {
    +      return (
    +        <div className="tab-content">
    +          <div className="tab-pane active" ref="filterTab">
    +            <div className="changes-header js-filter">
    +              <ChangesFilter />
    +            </div>
    +          </div>
    +        </div>
    +      );
    +    }
    +  });
    +
    +  var ChangesFilter = React.createClass({
    +    getStoreState: function () {
    +      return {
    +        filters: changesFilterStore.getFilters()
    +      };
    +    },
    +
    +    onChange: function () {
    +      this.setState(this.getStoreState());
    +    },
    +
    +    // props belong to the parent, so these aren't stored in the related store
    +    getDefaultProps: function () {
    +      return {
    +        addItemPlaceholder: 'Type a filter',
    +        helpText: 'e.g. debug or <1.4.1> or any regex',
    +        tooltip: ''
    +      };
    +    },
    +
    +    getInitialState: function () {
    +      return this.getStoreState();
    +    },
    +
    +    submitForm: function (e) {
    +      e.preventDefault();
    +      e.stopPropagation();
    +
    +
    +      var filter = this.refs.addItem.getDOMNode().value.trim();
    +      if (!filter) {
    +        return;
    +      }
    +
    +      Actions.addFilterViewItem(filter);
    +      this.refs.addItem.getDOMNode().value = '';
    --- End diff --
    
    Here are two examples of how we have worked with inputs using React:
    [Index Editor](https://github.com/apache/couchdb-fauxton/blob/master/app/addons/documents/index-editor/components.react.jsx#L64)
    [Cors](https://github.com/apache/couchdb-fauxton/blob/master/app/addons/cors/components.react.jsx#L76)


---
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: Changes page Filters tab moved to Re...

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

    https://github.com/apache/couchdb-fauxton/pull/265#discussion_r24657816
  
    --- Diff: app/addons/documents/changes/changes-header.react.jsx ---
    @@ -0,0 +1,236 @@
    +// Licensed under the Apache License, Version 2.0 (the "License"); you may not
    +// use this file except in compliance with the License. You may obtain a copy of
    +// the License at
    +//
    +//   http://www.apache.org/licenses/LICENSE-2.0
    +//
    +// Unless required by applicable law or agreed to in writing, software
    +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
    +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
    +// License for the specific language governing permissions and limitations under
    +// the License.
    +
    +define([
    +  'react',
    +  'addons/documents/changes/actions',
    +  'addons/documents/changes/stores'
    +], function (React, Actions, Stores) {
    +
    +  var changesFilterStore = Stores.changesFilterStore;
    +  var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;
    +
    +
    +  var ChangesHeader = React.createClass({
    +    getInitialState: function () {
    +      return {
    +        showTabContent: changesFilterStore.isTabVisible()
    +      };
    +    },
    +
    +    componentDidMount: function () {
    +      changesFilterStore.on('change', this.onChange, this);
    +    },
    +
    +    onChange: function () {
    +      this.setState({
    +        showTabContent: changesFilterStore.isTabVisible()
    +      });
    +    },
    +
    +    toggleFilterSection: function () {
    +      Actions.toggleTabVisibility();
    +    },
    +
    +    render: function () {
    +      var tabContent = '';
    +
    +      if (this.state.showTabContent) {
    +        tabContent = <ChangesHeaderTabContent key="changesFilterSection" />;
    +      }
    +
    +      return (
    +        <div className="changes-header-section">
    +          <ChangesHeaderTab onToggle={this.toggleFilterSection} />
    +          <ReactCSSTransitionGroup transitionName="toggleChangesFilter" component="div" className="changes-tab-content">
    +            {tabContent}
    +          </ReactCSSTransitionGroup>
    +        </div>
    +      );
    +    }
    +  });
    +
    +  var ChangesHeaderTab = React.createClass({
    +    propTypes: {
    +      onToggle: React.PropTypes.func.isRequired
    +    },
    +
    +    render: function () {
    +      return (
    +        <div className="dashboard-upper-menu">
    +          <ul className="nav nav-tabs" id="db-views-tabs-nav">
    +            <li>
    +              <a href="#filter" onClick={this.props.onToggle} data-bypass="true" data-toggle="tab">
    +                <i className="fonticon fonticon-plus"></i> Filter
    +              </a>
    +            </li>
    +          </ul>
    +        </div>
    +      );
    +    }
    +  });
    +
    +  var ChangesHeaderTabContent = React.createClass({
    +    render: function () {
    +      return (
    +        <div className="tab-content">
    +          <div className="tab-pane active" ref="filterTab">
    +            <div className="changes-header js-filter">
    +              <ChangesFilter />
    +            </div>
    +          </div>
    +        </div>
    +      );
    +    }
    +  });
    +
    +  var ChangesFilter = React.createClass({
    +    getStoreState: function () {
    +      return {
    +        filters: changesFilterStore.getFilters()
    +      };
    +    },
    +
    +    onChange: function () {
    +      this.setState(this.getStoreState());
    +    },
    +
    +    // props belong to the parent, so these aren't stored in the related store
    +    getDefaultProps: function () {
    +      return {
    +        addItemPlaceholder: 'Type a filter',
    +        helpText: 'e.g. debug or <1.4.1> or any regex',
    +        tooltip: ''
    +      };
    +    },
    +
    +    getInitialState: function () {
    +      return this.getStoreState();
    +    },
    +
    +    submitForm: function (e) {
    +      e.preventDefault();
    +      e.stopPropagation();
    +
    +
    +      var filter = this.refs.addItem.getDOMNode().value.trim();
    +      if (!filter) {
    +        return;
    +      }
    +
    +      Actions.addFilterViewItem(filter);
    +      this.refs.addItem.getDOMNode().value = '';
    --- End diff --
    
    @robertkowalski is correct. This could be simplified to how we assigned a value from onChange


---
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: Changes page Filters tab moved to Re...

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/265#discussion_r24656033
  
    --- Diff: app/addons/documents/changes/changes-header.react.jsx ---
    @@ -0,0 +1,236 @@
    +// Licensed under the Apache License, Version 2.0 (the "License"); you may not
    +// use this file except in compliance with the License. You may obtain a copy of
    +// the License at
    +//
    +//   http://www.apache.org/licenses/LICENSE-2.0
    +//
    +// Unless required by applicable law or agreed to in writing, software
    +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
    +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
    +// License for the specific language governing permissions and limitations under
    +// the License.
    +
    +define([
    +  'react',
    +  'addons/documents/changes/actions',
    +  'addons/documents/changes/stores'
    +], function (React, Actions, Stores) {
    +
    +  var changesFilterStore = Stores.changesFilterStore;
    +  var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;
    +
    +
    +  var ChangesHeader = React.createClass({
    +    getInitialState: function () {
    +      return {
    +        showTabContent: changesFilterStore.isTabVisible()
    +      };
    +    },
    +
    +    componentDidMount: function () {
    +      changesFilterStore.on('change', this.onChange, this);
    +    },
    +
    +    onChange: function () {
    +      this.setState({
    +        showTabContent: changesFilterStore.isTabVisible()
    +      });
    +    },
    +
    +    toggleFilterSection: function () {
    +      Actions.toggleTabVisibility();
    +    },
    +
    +    render: function () {
    +      var tabContent = '';
    +
    +      if (this.state.showTabContent) {
    +        tabContent = <ChangesHeaderTabContent key="changesFilterSection" />;
    +      }
    +
    +      return (
    +        <div className="changes-header-section">
    +          <ChangesHeaderTab onToggle={this.toggleFilterSection} />
    +          <ReactCSSTransitionGroup transitionName="toggleChangesFilter" component="div" className="changes-tab-content">
    +            {tabContent}
    +          </ReactCSSTransitionGroup>
    +        </div>
    +      );
    +    }
    +  });
    +
    +  var ChangesHeaderTab = React.createClass({
    +    propTypes: {
    +      onToggle: React.PropTypes.func.isRequired
    +    },
    +
    +    render: function () {
    +      return (
    +        <div className="dashboard-upper-menu">
    +          <ul className="nav nav-tabs" id="db-views-tabs-nav">
    +            <li>
    +              <a href="#filter" onClick={this.props.onToggle} data-bypass="true" data-toggle="tab">
    +                <i className="fonticon fonticon-plus"></i> Filter
    +              </a>
    +            </li>
    +          </ul>
    +        </div>
    +      );
    +    }
    +  });
    +
    +  var ChangesHeaderTabContent = React.createClass({
    +    render: function () {
    +      return (
    +        <div className="tab-content">
    +          <div className="tab-pane active" ref="filterTab">
    +            <div className="changes-header js-filter">
    +              <ChangesFilter />
    +            </div>
    +          </div>
    +        </div>
    +      );
    +    }
    +  });
    +
    +  var ChangesFilter = React.createClass({
    +    getStoreState: function () {
    +      return {
    +        filters: changesFilterStore.getFilters()
    +      };
    +    },
    +
    +    onChange: function () {
    +      this.setState(this.getStoreState());
    +    },
    +
    +    // props belong to the parent, so these aren't stored in the related store
    +    getDefaultProps: function () {
    +      return {
    +        addItemPlaceholder: 'Type a filter',
    +        helpText: 'e.g. debug or <1.4.1> or any regex',
    +        tooltip: ''
    +      };
    +    },
    +
    +    getInitialState: function () {
    +      return this.getStoreState();
    +    },
    +
    +    submitForm: function (e) {
    +      e.preventDefault();
    +      e.stopPropagation();
    +
    +
    +      var filter = this.refs.addItem.getDOMNode().value.trim();
    +      if (!filter) {
    +        return;
    +      }
    +
    +      Actions.addFilterViewItem(filter);
    +      this.refs.addItem.getDOMNode().value = '';
    --- End diff --
    
    You are still directly accessing the DOM from an event handler?
    
    Shouldn't we use an action connected to a store which then updates the element like this:
    
    ```
    <input type="text" ref="addItem" placeholder={this.props.addItemPlaceholder} value="{this.state.addItemValue}" />
    ```


---
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: Changes page Filters tab moved to Re...

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

    https://github.com/apache/couchdb-fauxton/pull/265#issuecomment-74468883
  
    @benkeen making good progress. As I mentioned in the previous comment, the way the filter is added needs to be a controlled component.


---
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: Changes page Filters tab moved to Re...

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

    https://github.com/apache/couchdb-fauxton/pull/265#issuecomment-75569421
  
    Merged as 392dc52


---
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: Changes page Filters tab moved to Re...

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

    https://github.com/apache/couchdb-fauxton/pull/265#issuecomment-73994744
  
    Thanks, @robertkowalski! Just working on the tests now & ran into some trouble. I'll commit what I have, but I'll have questions tomorrow. Basically I'm unable to confirm that after entering text into the filter it gets added to the DOM. No matter how I try it, I can't find the elements in the updated DOM (possibly my assert() runs prior to the DOM being updated?). Committing now. 


---
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: Changes page Filters tab moved to Re...

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/265#discussion_r24656340
  
    --- Diff: app/addons/documents/changes/changes-header.react.jsx ---
    @@ -0,0 +1,236 @@
    +// Licensed under the Apache License, Version 2.0 (the "License"); you may not
    +// use this file except in compliance with the License. You may obtain a copy of
    +// the License at
    +//
    +//   http://www.apache.org/licenses/LICENSE-2.0
    +//
    +// Unless required by applicable law or agreed to in writing, software
    +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
    +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
    +// License for the specific language governing permissions and limitations under
    +// the License.
    +
    +define([
    +  'react',
    +  'addons/documents/changes/actions',
    +  'addons/documents/changes/stores'
    +], function (React, Actions, Stores) {
    +
    +  var changesFilterStore = Stores.changesFilterStore;
    +  var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;
    +
    +
    +  var ChangesHeader = React.createClass({
    +    getInitialState: function () {
    +      return {
    +        showTabContent: changesFilterStore.isTabVisible()
    +      };
    +    },
    +
    +    componentDidMount: function () {
    +      changesFilterStore.on('change', this.onChange, this);
    +    },
    +
    +    onChange: function () {
    +      this.setState({
    +        showTabContent: changesFilterStore.isTabVisible()
    +      });
    +    },
    +
    +    toggleFilterSection: function () {
    +      Actions.toggleTabVisibility();
    +    },
    +
    +    render: function () {
    +      var tabContent = '';
    +
    +      if (this.state.showTabContent) {
    +        tabContent = <ChangesHeaderTabContent key="changesFilterSection" />;
    +      }
    +
    +      return (
    +        <div className="changes-header-section">
    +          <ChangesHeaderTab onToggle={this.toggleFilterSection} />
    +          <ReactCSSTransitionGroup transitionName="toggleChangesFilter" component="div" className="changes-tab-content">
    +            {tabContent}
    +          </ReactCSSTransitionGroup>
    +        </div>
    +      );
    +    }
    +  });
    +
    +  var ChangesHeaderTab = React.createClass({
    +    propTypes: {
    +      onToggle: React.PropTypes.func.isRequired
    +    },
    +
    +    render: function () {
    +      return (
    +        <div className="dashboard-upper-menu">
    +          <ul className="nav nav-tabs" id="db-views-tabs-nav">
    +            <li>
    +              <a href="#filter" onClick={this.props.onToggle} data-bypass="true" data-toggle="tab">
    +                <i className="fonticon fonticon-plus"></i> Filter
    +              </a>
    +            </li>
    +          </ul>
    +        </div>
    +      );
    +    }
    +  });
    +
    +  var ChangesHeaderTabContent = React.createClass({
    +    render: function () {
    +      return (
    +        <div className="tab-content">
    +          <div className="tab-pane active" ref="filterTab">
    +            <div className="changes-header js-filter">
    +              <ChangesFilter />
    +            </div>
    +          </div>
    +        </div>
    +      );
    +    }
    +  });
    +
    +  var ChangesFilter = React.createClass({
    +    getStoreState: function () {
    +      return {
    +        filters: changesFilterStore.getFilters()
    +      };
    +    },
    +
    +    onChange: function () {
    +      this.setState(this.getStoreState());
    +    },
    +
    +    // props belong to the parent, so these aren't stored in the related store
    +    getDefaultProps: function () {
    +      return {
    +        addItemPlaceholder: 'Type a filter',
    +        helpText: 'e.g. debug or <1.4.1> or any regex',
    +        tooltip: ''
    +      };
    +    },
    +
    +    getInitialState: function () {
    +      return this.getStoreState();
    +    },
    +
    +    submitForm: function (e) {
    +      e.preventDefault();
    +      e.stopPropagation();
    +
    +
    +      var filter = this.refs.addItem.getDOMNode().value.trim();
    +      if (!filter) {
    +        return;
    +      }
    +
    +      Actions.addFilterViewItem(filter);
    +      this.refs.addItem.getDOMNode().value = '';
    --- End diff --
    
    How does that relate to Flux? Should we always directly access the DOM instead of using the roundtrip using actions and stores?


---
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: Changes page Filters tab moved to Re...

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

    https://github.com/apache/couchdb-fauxton/pull/265#issuecomment-74130532
  
    Alrighty! Tests added. I think this is good to go. 


---
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: Changes page Filters tab moved to Re...

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

    https://github.com/apache/couchdb-fauxton/pull/265#discussion_r24885676
  
    --- Diff: app/addons/documents/tests/changes.componentsSpec.react.jsx ---
    @@ -0,0 +1,215 @@
    +// Licensed under the Apache License, Version 2.0 (the "License"); you may not
    +// use this file except in compliance with the License. You may obtain a copy of
    +// the License at
    +//
    +//   http://www.apache.org/licenses/LICENSE-2.0
    +//
    +// Unless required by applicable law or agreed to in writing, software
    +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
    +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
    +// License for the specific language governing permissions and limitations under
    +// the License.
    +
    +define([
    +  'app',
    +  'api',
    +  'react',
    +  'addons/documents/changes/components.react',
    +  'addons/documents/changes/stores',
    +  'addons/documents/changes/actions',
    +  'testUtils'
    +], function (app, FauxtonAPI, React, Changes, Stores, Actions, utils) {
    +  FauxtonAPI.router = new FauxtonAPI.Router([]);
    +
    +  var assert = utils.assert;
    +  var TestUtils = React.addons.TestUtils;
    +
    +
    +  describe('ChangesHeader', function () {
    +    var container, tab, spy;
    +
    +    describe('Testing DOM', function () {
    +      beforeEach(function () {
    +        spy = sinon.spy(Actions, 'toggleTabVisibility');
    +        container = document.createElement('div');
    +        tab = TestUtils.renderIntoDocument(<Changes.ChangesHeader />, container);
    +      });
    +
    +      afterEach(function () {
    +        Stores.changesFilterStore.reset();
    +        React.unmountComponentAtNode(container);
    +      });
    +
    +      // similar as previous, except it confirms that the action gets fired, not the custom toggle func
    +      it('calls toggleTabVisibility action on selecting a tab', function () {
    +        TestUtils.Simulate.click($(tab.getDOMNode()).find('a')[0]);
    +        assert.ok(spy.calledOnce);
    +      });
    +    });
    +
    +    it('toggleTabVisibility() changes state in store', function() {
    +      assert.ok(Stores.changesHeaderStore.isTabVisible() === false);
    +      Stores.changesHeaderStore.toggleTabVisibility();
    +      assert.ok(Stores.changesHeaderStore.isTabVisible() === true);
    +    });
    +
    +    it('reset() changes tab visiblity to hidden', function() {
    +      Stores.changesHeaderStore.toggleTabVisibility();
    +      Stores.changesHeaderStore.reset();
    +      assert.ok(Stores.changesHeaderStore.isTabVisible() === false);
    +    });
    +
    +//    reset: function () {
    --- End diff --
    
    You can probably just remove these


---
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: Changes page Filters tab moved to Re...

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

    https://github.com/apache/couchdb-fauxton/pull/265#discussion_r24658378
  
    --- Diff: app/addons/fauxton/components.react.jsx ---
    @@ -20,6 +20,7 @@ define([
     function(FauxtonAPI, React, Stores, Actions) {
       var navBarStore = Stores.navBarStore;
     
    +
    --- End diff --
    
    This is unrelated to the changes filter. I'm guessing this was by accident.


---
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: Changes page Filters tab moved to Re...

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

    https://github.com/apache/couchdb-fauxton/pull/265#issuecomment-73863175
  
    When running the code I get:
    
    ```
    Linting app/addons/documents/changes/changes-header.react.js ...ERROR
    [L27:C8] W033: Missing semicolon.
    ```


---
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: Changes page Filters tab moved to Re...

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

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


---
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: Changes page Filters tab moved to Re...

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

    https://github.com/apache/couchdb-fauxton/pull/265#discussion_r24885710
  
    --- Diff: app/addons/documents/tests/changes.componentsSpec.react.jsx ---
    @@ -0,0 +1,215 @@
    +// Licensed under the Apache License, Version 2.0 (the "License"); you may not
    +// use this file except in compliance with the License. You may obtain a copy of
    +// the License at
    +//
    +//   http://www.apache.org/licenses/LICENSE-2.0
    +//
    +// Unless required by applicable law or agreed to in writing, software
    +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
    +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
    +// License for the specific language governing permissions and limitations under
    +// the License.
    +
    +define([
    +  'app',
    +  'api',
    +  'react',
    +  'addons/documents/changes/components.react',
    +  'addons/documents/changes/stores',
    +  'addons/documents/changes/actions',
    +  'testUtils'
    +], function (app, FauxtonAPI, React, Changes, Stores, Actions, utils) {
    +  FauxtonAPI.router = new FauxtonAPI.Router([]);
    +
    +  var assert = utils.assert;
    +  var TestUtils = React.addons.TestUtils;
    +
    +
    +  describe('ChangesHeader', function () {
    +    var container, tab, spy;
    +
    +    describe('Testing DOM', function () {
    +      beforeEach(function () {
    +        spy = sinon.spy(Actions, 'toggleTabVisibility');
    +        container = document.createElement('div');
    +        tab = TestUtils.renderIntoDocument(<Changes.ChangesHeader />, container);
    +      });
    +
    +      afterEach(function () {
    +        Stores.changesFilterStore.reset();
    +        React.unmountComponentAtNode(container);
    +      });
    +
    +      // similar as previous, except it confirms that the action gets fired, not the custom toggle func
    +      it('calls toggleTabVisibility action on selecting a tab', function () {
    +        TestUtils.Simulate.click($(tab.getDOMNode()).find('a')[0]);
    +        assert.ok(spy.calledOnce);
    +      });
    +    });
    +
    +    it('toggleTabVisibility() changes state in store', function() {
    --- End diff --
    
    Can you move the store tests into their own stores test file. It doesn't make sense to have them in the components test file.


---
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: Changes page Filters tab moved to Re...

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

    https://github.com/apache/couchdb-fauxton/pull/265#issuecomment-74832238
  
    @benkeen this is looking better. Two components just need to be more self contained. I also picked up some bugs while testing. 
    
    * Once I add a filter it doesn't clean the input field
    * If I remove a fliter it doesn't regenerate the changes list without that filter
    * Everytime I click on add I get this error `Warning: flattenChildren(...): Encountered two children with the same key, `.$hello`. Child keys must be unique; when two children share a key, only the first child will be used.`


---
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: Changes page Filters tab moved to Re...

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

    https://github.com/apache/couchdb-fauxton/pull/265#issuecomment-74534191
  
    Thanks @garrensmith. I think the input field was all set up properly - I just wasn't grabbing the current value from the store here. Updated. 


---
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: Changes page Filters tab moved to Re...

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

    https://github.com/apache/couchdb-fauxton/pull/265#issuecomment-74913629
  
    k, here we go. Had to do a hack to get the error highlight blink to work, but it was between two evils: using jQuery or plain CSS, so I vouched for the latter. 


---
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: Changes page Filters tab moved to Re...

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

    https://github.com/apache/couchdb-fauxton/pull/265#discussion_r24885896
  
    --- Diff: app/addons/documents/changes/components.react.jsx ---
    @@ -0,0 +1,244 @@
    +// Licensed under the Apache License, Version 2.0 (the "License"); you may not
    +// use this file except in compliance with the License. You may obtain a copy of
    +// the License at
    +//
    +//   http://www.apache.org/licenses/LICENSE-2.0
    +//
    +// Unless required by applicable law or agreed to in writing, software
    +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
    +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
    +// License for the specific language governing permissions and limitations under
    +// the License.
    +
    +define([
    +  'react',
    +  'addons/documents/changes/actions',
    +  'addons/documents/changes/stores'
    +], function (React, Actions, Stores) {
    +
    +  var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;
    +
    +
    +  // the top-level component for the Changes Filter section. Handles hiding/showing
    +  var ChangesHeader = React.createClass({
    +    getInitialState: function () {
    +      return {
    +        showTabContent: Stores.changesHeaderStore.isTabVisible()
    +      };
    +    },
    +
    +    onChange: function () {
    +      this.setState({
    +        showTabContent: Stores.changesHeaderStore.isTabVisible()
    +      });
    +    },
    +
    +    componentDidMount: function () {
    +      Stores.changesHeaderStore.on('change', this.onChange, this);
    +    },
    +
    +    componentWillUnmount: function () {
    +      Stores.changesHeaderStore.off('change', this.onChange);
    +    },
    +
    +    toggleFilterSection: function () {
    +      Actions.toggleTabVisibility();
    +    },
    +
    +    render: function () {
    +      var tabContent = '';
    +      if (this.state.showTabContent) {
    +        tabContent = <ChangesFilter key="changesFilterSection" />;
    +      }
    +
    +      return (
    +        <div className="changes-header-section">
    +          <ChangesHeaderTab onToggle={this.toggleFilterSection} />
    +          <ReactCSSTransitionGroup transitionName="toggleChangesFilter" component="div" className="changes-tab-content">
    +            {tabContent}
    +          </ReactCSSTransitionGroup>
    +        </div>
    +      );
    +    }
    +  });
    +
    +
    +  var ChangesHeaderTab = React.createClass({
    +    propTypes: {
    +      onToggle: React.PropTypes.func.isRequired
    +    },
    +
    +    render: function () {
    +      return (
    +        <div className="dashboard-upper-menu">
    +          <ul className="nav nav-tabs" id="db-views-tabs-nav">
    +            <li>
    +              <a href="#filter" onClick={this.props.onToggle} data-bypass="true" data-toggle="tab">
    +                <i className="fonticon fonticon-plus"></i> Filter
    +              </a>
    +            </li>
    +          </ul>
    +        </div>
    +      );
    +    }
    +  });
    +
    +
    +  var ChangesFilter = React.createClass({
    +    getStoreState: function () {
    +      return {
    +        filters: Stores.changesFilterStore.getFilters()
    +      };
    +    },
    +
    +    onChange: function () {
    +      this.setState(this.getStoreState());
    +    },
    +
    +    componentDidMount: function () {
    +      Stores.changesFilterStore.on('change', this.onChange, this);
    +    },
    +
    +    componentWillUnmount: function () {
    +      Stores.changesFilterStore.off('change', this.onChange);
    +    },
    +
    +    getInitialState: function () {
    +      return this.getStoreState();
    +    },
    +
    +    getFilters: function () {
    +      return _.map(this.state.filters, function (filter) {
    +        return <Filter key={filter} label={filter} />;
    +      }, this);
    +    },
    +
    +    render: function () {
    +      var filters = this.getFilters();
    +
    +      return (
    +        <div className="tab-content">
    +          <div className="tab-pane active" ref="filterTab">
    +            <div className="changes-header js-filter">
    +              <AddFilterForm tooltip={this.props.tooltip} filter={this.state.filter} onSubmit={this.submitForm} />
    +              <ul className="filter-list">{filters}</ul>
    +            </div>
    +          </div>
    +        </div>
    +      );
    +    }
    +  });
    +
    +
    +  var AddFilterForm = React.createClass({
    +    getInitialState: function () {
    +      return {
    +        filter: ''
    +      };
    +    },
    +
    +    getDefaultProps: function () {
    +      return {
    +        tooltip: ''
    +      };
    +    },
    +
    +    submitForm: function (e) {
    +      e.preventDefault();
    +      e.stopPropagation();
    +      if (_.isEmpty(this.state.filter)) {
    +        return;
    +      }
    +      Actions.addFilter(this.state.filter);
    +    },
    +
    +    componentDidMount: function () {
    +      this.focusFilterField();
    +    },
    +
    +    componentDidUpdate: function () {
    +      this.focusFilterField();
    +    },
    +
    +    focusFilterField: function () {
    +      this.refs.addItem.getDOMNode().focus();
    +    },
    +
    +    onChangeFilter: function (e) {
    +      this.setState({ filter: e.target.value });
    +    },
    +
    +    render: function () {
    +      return (
    +        <form className="form-inline js-filter-form" onSubmit={this.submitForm}>
    +          <fieldset>
    +            <input type="text" ref="addItem" className="js-changes-filter-field" placeholder="Type a filter"
    +              onChange={this.onChangeFilter} value={this.state.filter} />
    +            <button type="submit" className="btn btn-primary">Filter</button>
    +            <div className="help-block">
    +              <strong ref="helpText">e.g. _design or document ID</strong>
    +              {' '}
    +              <FilterTooltip tooltip={this.props.tooltip} />
    +            </div>
    +          </fieldset>
    +        </form>
    +      );
    +    }
    +  });
    +
    +
    +  var FilterTooltip = React.createClass({
    +    componentDidMount: function () {
    +      if (this.props.tooltip) {
    +        $(this.refs.tooltip.getDOMNode()).tooltip();
    +      }
    +    },
    +
    +    render: function () {
    +      if (!this.props.tooltip) {
    +        return false;
    +      }
    +      return (
    +        <i ref="tooltip" className="icon icon-question-sign js-filter-tooltip" data-toggle="tooltip"
    +          data-original-title={this.props.tooltip}></i>
    +      );
    +    }
    +  });
    +
    +
    +  var Filter = React.createClass({
    +    propTypes: {
    +      label: React.PropTypes.string.isRequired
    +    },
    +
    +    remove: function (e) {
    +      e.preventDefault();
    +      Actions.removeFilter(this.props.label);
    --- End diff --
    
    The `<Filter />` component should be "dumb" and not call an action directly but call a callback passed to it from its controller component.


---
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: Changes page Filters tab moved to Re...

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

    https://github.com/apache/couchdb-fauxton/pull/265#issuecomment-74738123
  
    Thanks for all your help, @garrensmith! All updated.
    - actions + store tests added
    - form moved back to a single component
    - dropped third unnecessary store just to track the blank state of the AddFilterForm


---
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: Changes page Filters tab moved to Re...

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/265#discussion_r24515318
  
    --- Diff: app/addons/fauxton/components.react.jsx ---
    @@ -150,12 +151,133 @@ function(FauxtonAPI, React, Stores, Actions) {
       });
     
     
    +  var FilterView = React.createClass({
    +    propTypes: {
    +      namespace: React.PropTypes.string.isRequired
    +    },
    +
    +    getStoreState: function () {
    +      if (!this.filterViewStore) {
    +        this.initFilterViewStore();
    +      }
    +      return {
    +        filters: this.filterViewStore.getFilters()
    +      };
    +    },
    +
    +    // each instance of FilterView has its own store
    +    initFilterViewStore: function () {
    +      this.filterViewStore = new Stores.FilterViewStore(this.props.namespace);
    +      this.filterViewStore.dispatchToken = FauxtonAPI.dispatcher.register(this.filterViewStore.dispatch);
    +    },
    +
    +    onChange: function () {
    +      this.setState(this.getStoreState());
    +    },
    +
    +    // props belong to the parent, so these aren't stored in the related store
    +    getDefaultProps: function () {
    +      return {
    +        addItemPlaceholder: 'Type a filter',
    +        helpText: 'e.g. debug or <1.4.1> or any regex',
    +        namespace: '',
    +        tooltip: ''
    +      };
    +    },
    +
    +    getInitialState: function () {
    +      return this.getStoreState();
    +    },
    +
    +    submitForm: function (e) {
    +      e.preventDefault();
    +      e.stopPropagation();
    +
    +      var filter = this.refs.addItem.getDOMNode().value.trim();
    --- End diff --
    
    Check this.


---
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: Changes page Filters tab moved to Re...

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

    https://github.com/apache/couchdb-fauxton/pull/265#discussion_r24658385
  
    --- Diff: app/addons/fauxton/stores.js ---
    @@ -185,6 +185,7 @@ function(app, FauxtonAPI, ActionTypes) {
       Stores.navBarStore = new Stores.NavBarStore();
       Stores.navBarStore.dispatchToken = FauxtonAPI.dispatcher.register(Stores.navBarStore.dispatch);
     
    +
    --- End diff --
    
    This is unrelated to the changes filter. I'm guessing this was by accident.



---
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: Changes page Filters tab moved to Re...

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

    https://github.com/apache/couchdb-fauxton/pull/265#discussion_r24657971
  
    --- Diff: app/addons/documents/changes/changes-header.react.jsx ---
    @@ -0,0 +1,236 @@
    +// Licensed under the Apache License, Version 2.0 (the "License"); you may not
    +// use this file except in compliance with the License. You may obtain a copy of
    +// the License at
    +//
    +//   http://www.apache.org/licenses/LICENSE-2.0
    +//
    +// Unless required by applicable law or agreed to in writing, software
    +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
    +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
    +// License for the specific language governing permissions and limitations under
    +// the License.
    +
    +define([
    +  'react',
    +  'addons/documents/changes/actions',
    +  'addons/documents/changes/stores'
    +], function (React, Actions, Stores) {
    +
    +  var changesFilterStore = Stores.changesFilterStore;
    +  var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;
    +
    +
    +  var ChangesHeader = React.createClass({
    +    getInitialState: function () {
    +      return {
    +        showTabContent: changesFilterStore.isTabVisible()
    +      };
    +    },
    +
    +    componentDidMount: function () {
    +      changesFilterStore.on('change', this.onChange, this);
    +    },
    +
    +    onChange: function () {
    +      this.setState({
    +        showTabContent: changesFilterStore.isTabVisible()
    +      });
    +    },
    +
    +    toggleFilterSection: function () {
    +      Actions.toggleTabVisibility();
    +    },
    +
    +    render: function () {
    +      var tabContent = '';
    +
    +      if (this.state.showTabContent) {
    +        tabContent = <ChangesHeaderTabContent key="changesFilterSection" />;
    +      }
    +
    +      return (
    +        <div className="changes-header-section">
    +          <ChangesHeaderTab onToggle={this.toggleFilterSection} />
    +          <ReactCSSTransitionGroup transitionName="toggleChangesFilter" component="div" className="changes-tab-content">
    +            {tabContent}
    +          </ReactCSSTransitionGroup>
    +        </div>
    +      );
    +    }
    +  });
    +
    +  var ChangesHeaderTab = React.createClass({
    +    propTypes: {
    +      onToggle: React.PropTypes.func.isRequired
    +    },
    +
    +    render: function () {
    +      return (
    +        <div className="dashboard-upper-menu">
    +          <ul className="nav nav-tabs" id="db-views-tabs-nav">
    +            <li>
    +              <a href="#filter" onClick={this.props.onToggle} data-bypass="true" data-toggle="tab">
    +                <i className="fonticon fonticon-plus"></i> Filter
    +              </a>
    +            </li>
    +          </ul>
    +        </div>
    +      );
    +    }
    +  });
    +
    +  var ChangesHeaderTabContent = React.createClass({
    +    render: function () {
    +      return (
    +        <div className="tab-content">
    +          <div className="tab-pane active" ref="filterTab">
    +            <div className="changes-header js-filter">
    +              <ChangesFilter />
    +            </div>
    +          </div>
    +        </div>
    +      );
    +    }
    +  });
    +
    +  var ChangesFilter = React.createClass({
    +    getStoreState: function () {
    +      return {
    +        filters: changesFilterStore.getFilters()
    +      };
    +    },
    +
    +    onChange: function () {
    +      this.setState(this.getStoreState());
    +    },
    +
    +    // props belong to the parent, so these aren't stored in the related store
    +    getDefaultProps: function () {
    +      return {
    +        addItemPlaceholder: 'Type a filter',
    +        helpText: 'e.g. debug or <1.4.1> or any regex',
    --- End diff --
    
    Could you add a better helpText. Why would anyone filter the changes feed with <1.4.1>?


---
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: Changes page Filters tab moved to Re...

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

    https://github.com/apache/couchdb-fauxton/pull/265#discussion_r24886051
  
    --- Diff: app/addons/documents/changes/components.react.jsx ---
    @@ -0,0 +1,244 @@
    +// Licensed under the Apache License, Version 2.0 (the "License"); you may not
    +// use this file except in compliance with the License. You may obtain a copy of
    +// the License at
    +//
    +//   http://www.apache.org/licenses/LICENSE-2.0
    +//
    +// Unless required by applicable law or agreed to in writing, software
    +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
    +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
    +// License for the specific language governing permissions and limitations under
    +// the License.
    +
    +define([
    +  'react',
    +  'addons/documents/changes/actions',
    +  'addons/documents/changes/stores'
    +], function (React, Actions, Stores) {
    +
    +  var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;
    +
    +
    +  // the top-level component for the Changes Filter section. Handles hiding/showing
    +  var ChangesHeader = React.createClass({
    +    getInitialState: function () {
    +      return {
    +        showTabContent: Stores.changesHeaderStore.isTabVisible()
    +      };
    +    },
    +
    +    onChange: function () {
    +      this.setState({
    +        showTabContent: Stores.changesHeaderStore.isTabVisible()
    +      });
    +    },
    +
    +    componentDidMount: function () {
    +      Stores.changesHeaderStore.on('change', this.onChange, this);
    +    },
    +
    +    componentWillUnmount: function () {
    +      Stores.changesHeaderStore.off('change', this.onChange);
    +    },
    +
    +    toggleFilterSection: function () {
    +      Actions.toggleTabVisibility();
    +    },
    +
    +    render: function () {
    +      var tabContent = '';
    +      if (this.state.showTabContent) {
    +        tabContent = <ChangesFilter key="changesFilterSection" />;
    +      }
    +
    +      return (
    +        <div className="changes-header-section">
    +          <ChangesHeaderTab onToggle={this.toggleFilterSection} />
    +          <ReactCSSTransitionGroup transitionName="toggleChangesFilter" component="div" className="changes-tab-content">
    +            {tabContent}
    +          </ReactCSSTransitionGroup>
    +        </div>
    +      );
    +    }
    +  });
    +
    +
    +  var ChangesHeaderTab = React.createClass({
    +    propTypes: {
    +      onToggle: React.PropTypes.func.isRequired
    +    },
    +
    +    render: function () {
    +      return (
    +        <div className="dashboard-upper-menu">
    +          <ul className="nav nav-tabs" id="db-views-tabs-nav">
    +            <li>
    +              <a href="#filter" onClick={this.props.onToggle} data-bypass="true" data-toggle="tab">
    +                <i className="fonticon fonticon-plus"></i> Filter
    +              </a>
    +            </li>
    +          </ul>
    +        </div>
    +      );
    +    }
    +  });
    +
    +
    +  var ChangesFilter = React.createClass({
    +    getStoreState: function () {
    +      return {
    +        filters: Stores.changesFilterStore.getFilters()
    +      };
    +    },
    +
    +    onChange: function () {
    +      this.setState(this.getStoreState());
    +    },
    +
    +    componentDidMount: function () {
    +      Stores.changesFilterStore.on('change', this.onChange, this);
    +    },
    +
    +    componentWillUnmount: function () {
    +      Stores.changesFilterStore.off('change', this.onChange);
    +    },
    +
    +    getInitialState: function () {
    +      return this.getStoreState();
    +    },
    +
    +    getFilters: function () {
    +      return _.map(this.state.filters, function (filter) {
    +        return <Filter key={filter} label={filter} />;
    +      }, this);
    +    },
    +
    +    render: function () {
    +      var filters = this.getFilters();
    +
    +      return (
    +        <div className="tab-content">
    +          <div className="tab-pane active" ref="filterTab">
    +            <div className="changes-header js-filter">
    +              <AddFilterForm tooltip={this.props.tooltip} filter={this.state.filter} onSubmit={this.submitForm} />
    --- End diff --
    
    You don't have a `submitForm` method in this component.


---
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: Changes page Filters tab moved to Re...

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

    https://github.com/apache/couchdb-fauxton/pull/265#discussion_r24734807
  
    --- Diff: app/addons/documents/changes/components.react.jsx ---
    @@ -0,0 +1,238 @@
    +// Licensed under the Apache License, Version 2.0 (the "License"); you may not
    +// use this file except in compliance with the License. You may obtain a copy of
    +// the License at
    +//
    +//   http://www.apache.org/licenses/LICENSE-2.0
    +//
    +// Unless required by applicable law or agreed to in writing, software
    +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
    +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
    +// License for the specific language governing permissions and limitations under
    +// the License.
    +
    +define([
    +  'react',
    +  'addons/documents/changes/actions',
    +  'addons/documents/changes/stores'
    +], function (React, Actions, Stores) {
    +
    +  var changesFilterStore = Stores.changesFilterStore;
    +  var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;
    +
    +
    +  var ChangesHeader = React.createClass({
    +    getInitialState: function () {
    +      return {
    +        showTabContent: changesFilterStore.isTabVisible()
    +      };
    +    },
    +
    +    componentDidMount: function () {
    +      changesFilterStore.on('change', this.onChange, this);
    +    },
    +
    +    onChange: function () {
    +      this.setState({
    +        showTabContent: changesFilterStore.isTabVisible()
    +      });
    +    },
    +
    +    toggleFilterSection: function () {
    +      Actions.toggleTabVisibility();
    +    },
    +
    +    render: function () {
    +      var tabContent = '';
    +
    +      if (this.state.showTabContent) {
    +        tabContent = <ChangesHeaderTabContent key="changesFilterSection" />;
    +      }
    +
    +      return (
    +        <div className="changes-header-section">
    +          <ChangesHeaderTab onToggle={this.toggleFilterSection} />
    +          <ReactCSSTransitionGroup transitionName="toggleChangesFilter" component="div" className="changes-tab-content">
    +            {tabContent}
    +          </ReactCSSTransitionGroup>
    +        </div>
    +      );
    +    }
    +  });
    +
    +  var ChangesHeaderTab = React.createClass({
    +    propTypes: {
    +      onToggle: React.PropTypes.func.isRequired
    +    },
    +
    +    render: function () {
    +      return (
    +        <div className="dashboard-upper-menu">
    +          <ul className="nav nav-tabs" id="db-views-tabs-nav">
    +            <li>
    +              <a href="#filter" onClick={this.props.onToggle} data-bypass="true" data-toggle="tab">
    +                <i className="fonticon fonticon-plus"></i> Filter
    +              </a>
    +            </li>
    +          </ul>
    +        </div>
    +      );
    +    }
    +  });
    +
    +  var ChangesHeaderTabContent = React.createClass({
    +    render: function () {
    +      return (
    +        <div className="tab-content">
    +          <div className="tab-pane active" ref="filterTab">
    +            <div className="changes-header js-filter">
    +              <ChangesFilter />
    +            </div>
    +          </div>
    +        </div>
    +      );
    +    }
    +  });
    +
    +  var ChangesFilter = React.createClass({
    +    getStoreState: function () {
    +      return {
    +        currentFilter: changesFilterStore.getCurrentFilter(),
    +        filters: changesFilterStore.getFilters()
    +      };
    +    },
    +
    +    onChange: function () {
    +      this.setState(this.getStoreState());
    +    },
    +
    +    // props belong to the parent, so these aren't stored in the related store
    +    getDefaultProps: function () {
    +      return {
    +        tooltip: ''
    +      };
    +    },
    +
    +    getInitialState: function () {
    +      return this.getStoreState();
    +    },
    +
    +    submitForm: function (e) {
    +      e.preventDefault();
    +      e.stopPropagation();
    +
    +      var filter = this.refs.addItem.getDOMNode().value.trim();
    --- End diff --
    
    This needs to change to a [controlled controller](http://facebook.github.io/react/docs/forms.html)


---
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: Changes page Filters tab moved to Re...

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/265#discussion_r24515523
  
    --- Diff: app/addons/fauxton/components.react.jsx ---
    @@ -150,12 +151,133 @@ function(FauxtonAPI, React, Stores, Actions) {
       });
     
     
    +  var FilterView = React.createClass({
    +    propTypes: {
    +      namespace: React.PropTypes.string.isRequired
    +    },
    +
    +    getStoreState: function () {
    +      if (!this.filterViewStore) {
    +        this.initFilterViewStore();
    +      }
    +      return {
    +        filters: this.filterViewStore.getFilters()
    +      };
    +    },
    +
    +    // each instance of FilterView has its own store
    +    initFilterViewStore: function () {
    +      this.filterViewStore = new Stores.FilterViewStore(this.props.namespace);
    +      this.filterViewStore.dispatchToken = FauxtonAPI.dispatcher.register(this.filterViewStore.dispatch);
    +    },
    +
    +    onChange: function () {
    +      this.setState(this.getStoreState());
    +    },
    +
    +    // props belong to the parent, so these aren't stored in the related store
    +    getDefaultProps: function () {
    +      return {
    +        addItemPlaceholder: 'Type a filter',
    +        helpText: 'e.g. debug or <1.4.1> or any regex',
    +        namespace: '',
    +        tooltip: ''
    +      };
    +    },
    +
    +    getInitialState: function () {
    +      return this.getStoreState();
    +    },
    +
    +    submitForm: function (e) {
    +      e.preventDefault();
    +      e.stopPropagation();
    +
    +      var filter = this.refs.addItem.getDOMNode().value.trim();
    +      if (!filter) {
    +        return;
    +      }
    +
    +      Actions.addFilterViewItem(this.props.namespace, filter);
    +      this.refs.addItem.getDOMNode().value = '';
    +    },
    +
    +    componentDidMount: function () {
    +      this.filterViewStore.on('change', this.onChange, this);
    +      if (this.props.tooltip) {
    +        $(this.refs.tooltip.getDOMNode()).tooltip();
    +      }
    +    },
    +
    +    componentWillUnmount: function() {
    +      this.filterViewStore.off('change', this.onChange);
    +    },
    +
    +    render: function () {
    +      var tooltip = '';
    +      if (this.props.tooltip) {
    +        tooltip = '<i ref="tooltip" className="icon icon-question-sign" data-toggle="tooltip" data-original-title=' +
    +          this.props.tooltipText + '></i>';
    +      }
    +
    +      var filters = _.map(this.state.filters, function (filter) {
    +        return <FilterViewItem namespace={this.props.namespace} key={filter} label={filter} />;
    +      }, this);
    +
    --- End diff --
    
    also move to helper


---
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: Changes page Filters tab moved to Re...

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

    https://github.com/apache/couchdb-fauxton/pull/265#issuecomment-73861608
  
    looks promising!
    
     - we will need tests in order to merge it, one test could be that adding a filter adds it to the react wrapper component
    
     - I think you can delete the `Components.FilterView`
    
    I'll add some other comments next to the 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: Changes page Filters tab moved to Re...

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

    https://github.com/apache/couchdb-fauxton/pull/265#issuecomment-73864471
  
    stopping here for now - @garrensmith will talk to you later


---
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: Changes page Filters tab moved to Re...

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

    https://github.com/apache/couchdb-fauxton/pull/265#issuecomment-73817956
  
    Hey @robertkowalski, @garrensmith - my first foray into React. Woot!
    
    I largely copied the structure etc. from the code that was already there, but I'm sure there's plenty to criticize. Mind taking a glance if you get any time today? Thanks!
    



---
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: Changes page Filters tab moved to Re...

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

    https://github.com/apache/couchdb-fauxton/pull/265#discussion_r24885981
  
    --- Diff: app/addons/documents/changes/components.react.jsx ---
    @@ -0,0 +1,244 @@
    +// Licensed under the Apache License, Version 2.0 (the "License"); you may not
    +// use this file except in compliance with the License. You may obtain a copy of
    +// the License at
    +//
    +//   http://www.apache.org/licenses/LICENSE-2.0
    +//
    +// Unless required by applicable law or agreed to in writing, software
    +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
    +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
    +// License for the specific language governing permissions and limitations under
    +// the License.
    +
    +define([
    +  'react',
    +  'addons/documents/changes/actions',
    +  'addons/documents/changes/stores'
    +], function (React, Actions, Stores) {
    +
    +  var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;
    +
    +
    +  // the top-level component for the Changes Filter section. Handles hiding/showing
    +  var ChangesHeader = React.createClass({
    +    getInitialState: function () {
    +      return {
    +        showTabContent: Stores.changesHeaderStore.isTabVisible()
    +      };
    +    },
    +
    +    onChange: function () {
    +      this.setState({
    +        showTabContent: Stores.changesHeaderStore.isTabVisible()
    +      });
    +    },
    +
    +    componentDidMount: function () {
    +      Stores.changesHeaderStore.on('change', this.onChange, this);
    +    },
    +
    +    componentWillUnmount: function () {
    +      Stores.changesHeaderStore.off('change', this.onChange);
    +    },
    +
    +    toggleFilterSection: function () {
    +      Actions.toggleTabVisibility();
    +    },
    +
    +    render: function () {
    +      var tabContent = '';
    +      if (this.state.showTabContent) {
    +        tabContent = <ChangesFilter key="changesFilterSection" />;
    +      }
    +
    +      return (
    +        <div className="changes-header-section">
    +          <ChangesHeaderTab onToggle={this.toggleFilterSection} />
    +          <ReactCSSTransitionGroup transitionName="toggleChangesFilter" component="div" className="changes-tab-content">
    +            {tabContent}
    +          </ReactCSSTransitionGroup>
    +        </div>
    +      );
    +    }
    +  });
    +
    +
    +  var ChangesHeaderTab = React.createClass({
    +    propTypes: {
    +      onToggle: React.PropTypes.func.isRequired
    +    },
    +
    +    render: function () {
    +      return (
    +        <div className="dashboard-upper-menu">
    +          <ul className="nav nav-tabs" id="db-views-tabs-nav">
    +            <li>
    +              <a href="#filter" onClick={this.props.onToggle} data-bypass="true" data-toggle="tab">
    +                <i className="fonticon fonticon-plus"></i> Filter
    +              </a>
    +            </li>
    +          </ul>
    +        </div>
    +      );
    +    }
    +  });
    +
    +
    +  var ChangesFilter = React.createClass({
    +    getStoreState: function () {
    +      return {
    +        filters: Stores.changesFilterStore.getFilters()
    +      };
    +    },
    +
    +    onChange: function () {
    +      this.setState(this.getStoreState());
    +    },
    +
    +    componentDidMount: function () {
    +      Stores.changesFilterStore.on('change', this.onChange, this);
    +    },
    +
    +    componentWillUnmount: function () {
    +      Stores.changesFilterStore.off('change', this.onChange);
    +    },
    +
    +    getInitialState: function () {
    +      return this.getStoreState();
    +    },
    +
    +    getFilters: function () {
    +      return _.map(this.state.filters, function (filter) {
    +        return <Filter key={filter} label={filter} />;
    +      }, this);
    +    },
    +
    +    render: function () {
    +      var filters = this.getFilters();
    +
    +      return (
    +        <div className="tab-content">
    +          <div className="tab-pane active" ref="filterTab">
    +            <div className="changes-header js-filter">
    +              <AddFilterForm tooltip={this.props.tooltip} filter={this.state.filter} onSubmit={this.submitForm} />
    +              <ul className="filter-list">{filters}</ul>
    +            </div>
    +          </div>
    +        </div>
    +      );
    +    }
    +  });
    +
    +
    +  var AddFilterForm = React.createClass({
    +    getInitialState: function () {
    +      return {
    +        filter: ''
    +      };
    +    },
    +
    +    getDefaultProps: function () {
    +      return {
    +        tooltip: ''
    +      };
    +    },
    +
    +    submitForm: function (e) {
    +      e.preventDefault();
    +      e.stopPropagation();
    +      if (_.isEmpty(this.state.filter)) {
    +        return;
    +      }
    +      Actions.addFilter(this.state.filter);
    --- End diff --
    
    This should also be a dumb component that just calls a callback on a submit form and not an action directly.


---
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: Changes page Filters tab moved to Re...

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

    https://github.com/apache/couchdb-fauxton/pull/265#issuecomment-74310883
  
    Alrighty! *This* time it's totally good to go. ;) All suggested changes made.


---
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: Changes page Filters tab moved to Re...

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

    https://github.com/apache/couchdb-fauxton/pull/265#issuecomment-75555100
  
    +1. This is great work @benkeen. Merge it.


---
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: Changes page Filters tab moved to Re...

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

    https://github.com/apache/couchdb-fauxton/pull/265#issuecomment-74579976
  
    Hey @garrensmith, I confess I was getting a bit confused about some things so I thought I'd just experiment a bit and organize things in what I regard as a logical manner. We can just revert it if I'm barking up the wrong tree.
    
    Structure (pretty much the same):
    
    ```xml
    <ChangesHeader />
    	<ChangesHeaderTab />
    	<ChangesFilter />
    		<Filter /> (list of N components)
    		<AddFilterForm />
    			<AddFilterFormContent />
    				<FilterTooltip />
    ```
    
    Testing: these would be the key components, like before:
    `<ChangesHeaderTab />` - test the hide/show of the tab
    `<ChangesFilter />` - test the add/remove filters, tooltip content
    
    Comments:
    
    - It seemed weird that the components were all nice and discrete but shared the same store, so I split it into three: one for the header to track its hide/show state, one for the changes filter to track the list of visible filters, and one for the AddFilterForm to track the state of the text field. [Maybe a bit overengineered now?] I like the new arrangement because looking at a component you can see by checking its store what data is related to it. Before, I was losing track of what piece of state is associated with which component.
    - I added a fauxton/mixins.js file to cut down on boilerplate code - namely the this.store.on('change', callback) assignment and destruction.
    - I moved as much code relating to a particular component to the component itself, and stopped passing stuff down the chain. e.g. `<Filter />` now handles its own onRemove event and just fires an action. I'm not sure this is in keeping with the "dumb component" idea, but I find this way there's less dependencies between components and code is where I expect to find it.
    - I'm still hazy on the need to separate `AddFilterForm` and the form content (`AddFilterFormContent`). They seem so functionally entwined, it feels a bit unnecessary - I'll have to get you to explain that one to me again.



---
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: Changes page Filters tab moved to Re...

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

    https://github.com/apache/couchdb-fauxton/pull/265#issuecomment-75491870
  
    Commits squashed. The failing unit test was unrelated to this ticket. Let's see what Travis says this 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: Changes page Filters tab moved to Re...

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/265#discussion_r24515498
  
    --- Diff: app/addons/fauxton/components.react.jsx ---
    @@ -150,12 +151,133 @@ function(FauxtonAPI, React, Stores, Actions) {
       });
     
     
    +  var FilterView = React.createClass({
    +    propTypes: {
    +      namespace: React.PropTypes.string.isRequired
    +    },
    +
    +    getStoreState: function () {
    +      if (!this.filterViewStore) {
    +        this.initFilterViewStore();
    +      }
    +      return {
    +        filters: this.filterViewStore.getFilters()
    +      };
    +    },
    +
    +    // each instance of FilterView has its own store
    +    initFilterViewStore: function () {
    +      this.filterViewStore = new Stores.FilterViewStore(this.props.namespace);
    +      this.filterViewStore.dispatchToken = FauxtonAPI.dispatcher.register(this.filterViewStore.dispatch);
    +    },
    +
    +    onChange: function () {
    +      this.setState(this.getStoreState());
    +    },
    +
    +    // props belong to the parent, so these aren't stored in the related store
    +    getDefaultProps: function () {
    +      return {
    +        addItemPlaceholder: 'Type a filter',
    +        helpText: 'e.g. debug or <1.4.1> or any regex',
    +        namespace: '',
    +        tooltip: ''
    +      };
    +    },
    +
    +    getInitialState: function () {
    +      return this.getStoreState();
    +    },
    +
    +    submitForm: function (e) {
    +      e.preventDefault();
    +      e.stopPropagation();
    +
    +      var filter = this.refs.addItem.getDOMNode().value.trim();
    +      if (!filter) {
    +        return;
    +      }
    +
    +      Actions.addFilterViewItem(this.props.namespace, filter);
    +      this.refs.addItem.getDOMNode().value = '';
    +    },
    +
    +    componentDidMount: function () {
    +      this.filterViewStore.on('change', this.onChange, this);
    +      if (this.props.tooltip) {
    +        $(this.refs.tooltip.getDOMNode()).tooltip();
    +      }
    +    },
    +
    +    componentWillUnmount: function() {
    +      this.filterViewStore.off('change', this.onChange);
    +    },
    +
    +    render: function () {
    +      var tooltip = '';
    +      if (this.props.tooltip) {
    +        tooltip = '<i ref="tooltip" className="icon icon-question-sign" data-toggle="tooltip" data-original-title=' +
    +          this.props.tooltipText + '></i>';
    --- End diff --
    
    move to helper


---
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: Changes page Filters tab moved to Re...

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

    https://github.com/apache/couchdb-fauxton/pull/265#issuecomment-73994457
  
    @benkeen this looks a lot better, we will need tests to merge this, examples:
    
    - `ChangesHeader `: the element shows/removes the subcomponent conditionally if the state changes / actions are fired
    
    - test what happens on `onToggle={this.toggleFilterSection}`
    
    - are filters really removed after clicking on the remove button



---
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: Changes page Filters tab moved to Re...

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

    https://github.com/apache/couchdb-fauxton/pull/265#discussion_r24658328
  
    --- Diff: app/addons/documents/tests/changesHeader.componentsSpec.react.jsx ---
    @@ -0,0 +1,138 @@
    +// Licensed under the Apache License, Version 2.0 (the "License"); you may not
    +// use this file except in compliance with the License. You may obtain a copy of
    +// the License at
    +//
    +//   http://www.apache.org/licenses/LICENSE-2.0
    +//
    +// Unless required by applicable law or agreed to in writing, software
    +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
    +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
    +// License for the specific language governing permissions and limitations under
    +// the License.
    +
    +define([
    +  'app',
    +  'api',
    +  'react',
    +  'addons/documents/changes/changes-header.react',
    +  'addons/documents/changes/stores',
    +  'testUtils'
    +], function (app, FauxtonAPI, React, ChangesHeader, Stores, utils) {
    +  FauxtonAPI.router = new FauxtonAPI.Router([]);
    +
    +  var assert = utils.assert;
    +  var TestUtils = React.addons.TestUtils;
    +
    +  describe('ChangesHeader', function () {
    +    describe('Toggle tab content button', function () {
    +      var container, tab, toggleTabVisibility;
    +
    +      beforeEach(function () {
    +        toggleTabVisibility = sinon.spy();
    +        container = document.createElement('div');
    +        tab = TestUtils.renderIntoDocument(<ChangesHeader.ChangesHeaderTab onToggle={toggleTabVisibility} />, container);
    +      });
    +
    +      afterEach(function () {
    +        Stores.changesFilterStore.reset();
    +        React.unmountComponentAtNode(container);
    +      });
    +
    +      it('should call toggle function on clicking tab', function () {
    +        TestUtils.Simulate.click($(tab.getDOMNode()).find('a')[0]);
    +        assert.ok(toggleTabVisibility.calledOnce);
    +      });
    +    });
    +  });
    +
    +
    +  describe('ChangesFilter', function () {
    +    var container, changesFilterEl;
    +
    +    beforeEach(function () {
    +      container = document.createElement('div');
    +      changesFilterEl = TestUtils.renderIntoDocument(<ChangesHeader.ChangesFilter />, container);
    +    });
    +
    +    afterEach(function () {
    +      Stores.changesFilterStore.reset();
    +      React.unmountComponentAtNode(container);
    +    });
    +
    +    it('should add filter markup', function () {
    +      var $el = $(changesFilterEl.getDOMNode()),
    --- End diff --
    
    This is cool. I like how you have broken the selecting of the DOM here. Makes the test a lot more readable.


---
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.
---