Browse Source

feat: Add multi select component for owner dropdown(#8043)

We'll deprecate select2 in favor of react-select
Lyn Nagara 7 years ago
parent
commit
e6088e1f2c

+ 1 - 0
package.json

@@ -73,6 +73,7 @@
     "react-lazy-load": "3.0.13",
     "react-mentions": "^1.2.0",
     "react-router": "3.2.0",
+    "react-select": "^1.2.1",
     "react-sparklines": "1.7.0",
     "reflux": "0.4.1",
     "scroll-to-element": "^2.0.0",

+ 78 - 0
src/sentry/static/sentry/app/components/forms/multiSelectField.jsx

@@ -0,0 +1,78 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import Select from 'react-select';
+import styled from 'react-emotion';
+
+import InputField from './inputField';
+
+export default class MultiSelectField extends InputField {
+  static propTypes = {
+    options: PropTypes.array.isRequired,
+    onChange: PropTypes.func,
+    value: PropTypes.any,
+  };
+
+  constructor(props) {
+    super(props);
+    this.state = {
+      values: [],
+    };
+  }
+
+  handleChange = value => {
+    this.setState({values: value}, () => {
+      if (typeof this.props.onChange === 'function') {
+        this.props.onChange(value);
+      }
+    });
+  };
+
+  renderArrow = () => {
+    return <span className="icon-arrow-down" />;
+  };
+
+  render() {
+    return (
+      <MultiSelect
+        id={this.getId()}
+        onChange={this.handleChange}
+        value={this.state.values}
+        multi={true}
+        arrowRenderer={this.renderArrow}
+        style={{width: 200, zIndex: 100, overflow: 'visible'}}
+        {...this.props}
+      />
+    );
+  }
+}
+
+const MultiSelect = styled(Select)`
+  font-size: 15px;
+  .Select-control {
+    overflow: visible;
+  }
+  .Select-input {
+    height: 37px;
+    input {
+      padding: 10px 0;
+    }
+  }
+
+  .Select-placeholder,
+  .Select--single > .Select-control .Select-value {
+    height: 37px;
+    &:focus {
+      border: 1px solid ${p => p.theme.gray};
+    }
+  }
+
+  .Select-option.is-focused {
+    color: white;
+    background-color: ${p => p.theme.purple};
+  }
+  .Select-multi-value-wrapper {
+    > a {
+      margin-left: 4px;
+    }
+  }
+`;

+ 0 - 2
src/sentry/static/sentry/app/utils.jsx

@@ -224,8 +224,6 @@ export function sortProjects(projects) {
 export const buildUserId = id => `user:${id}`;
 export const buildTeamId = id => `team:${id}`;
 
-export const actorEquality = (a, b) => a.type === b.type && a.id === b.id;
-
 // re-export under utils
 export {parseLinkHeader, deviceNameMapper, Collection, PendingChangeQueue, CursorPoller};
 

+ 14 - 81
src/sentry/static/sentry/app/views/settings/project/projectOwnership/ruleBuilder.jsx

@@ -2,7 +2,6 @@ import PropTypes from 'prop-types';
 import React from 'react';
 import styled from 'react-emotion';
 import {Flex} from 'grid-emotion';
-
 import memberListStore from '../../../../stores/memberListStore';
 import ProjectsStore from '../../../../stores/projectsStore';
 import Button from '../../../../components/buttons/button';
@@ -10,14 +9,10 @@ import SelectInput from '../../../../components/selectInput';
 import TextOverflow from '../../../../components/textOverflow';
 import InlineSvg from '../../../../components/inlineSvg';
 import Input from '../../../../views/settings/components/forms/controls/input';
-import DropdownAutoComplete from '../../../../components/dropdownAutoComplete';
-import DropdownButton from '../../../../components/dropdownButton';
-import ActorAvatar from '../../../../components/actorAvatar';
 import SentryTypes from '../../../../proptypes';
-import {buildUserId, buildTeamId, actorEquality} from '../../../../utils';
+import {buildUserId, buildTeamId} from '../../../../utils';
 import {addErrorMessage} from '../../../../actionCreators/indicator';
-
-import {t} from '../../../../locale';
+import SelectOwners from './selectOwners';
 
 const initialState = {
   text: '',
@@ -79,21 +74,10 @@ class RuleBuilder extends React.Component {
     this.setState({text: e.target.value});
   };
 
-  onAddActor = ({actor}) => {
-    this.setState(({owners}) => {
-      if (!owners.find(i => actorEquality(i, actor))) {
-        return {owners: [...owners, actor]};
-      } else return {};
-    });
+  handleChangeOwners = owners => {
+    this.setState({owners});
   };
 
-  handleRemoveActor(toRemove, e) {
-    this.setState(({owners}) => ({
-      owners: owners.filter(actor => !actorEquality(actor, toRemove)),
-    }));
-    e.stopPropagation();
-  }
-
   handleAddRule = () => {
     let {type, text, owners} = this.state;
 
@@ -104,10 +88,10 @@ class RuleBuilder extends React.Component {
 
     let ownerText = owners
       .map(
-        actor =>
-          actor.type == 'team'
-            ? `#${actor.name}`
-            : memberListStore.getById(actor.id).email
+        owner =>
+          owner.actor.type === 'team'
+            ? `#${owner.actor.name}`
+            : memberListStore.getById(owner.actor.id).email
       )
       .join(' ');
 
@@ -160,38 +144,12 @@ class RuleBuilder extends React.Component {
             placeholder={type === 'path' ? 'src/example/*' : 'example.com/settings/*'}
           />
           <Divider src="icon-chevron-right" />
-          <Flex flex="1" align="center">
-            <DropdownAutoComplete
-              items={[
-                {
-                  value: 'team',
-                  label: 'Teams',
-                  items: this.mentionableTeams(),
-                },
-                {
-                  value: 'user',
-                  label: 'Users',
-                  items: this.mentionableUsers(),
-                },
-              ]}
-              onSelect={this.onAddActor}
-            >
-              {({isOpen, selectedItem}) => (
-                <BuilderDropdownButton isOpen={isOpen} size="zero">
-                  <Owners>
-                    {owners.map(owner => (
-                      <span
-                        key={`${owner.type}-${owner.id}`}
-                        onClick={this.handleRemoveActor.bind(this, owner)}
-                      >
-                        <ActorAvatar actor={owner} />
-                      </span>
-                    ))}
-                  </Owners>
-                  <div>{t('Add Owners')}</div>
-                </BuilderDropdownButton>
-              )}
-            </DropdownAutoComplete>
+          <Flex flex="1" align="center" mr={1}>
+            <SelectOwners
+              options={[...this.mentionableTeams(), ...this.mentionableUsers()]}
+              value={owners}
+              onChange={this.handleChangeOwners}
+            />
           </Flex>
 
           <RuleAddButton
@@ -261,31 +219,6 @@ const Divider = styled(InlineSvg)`
   margin-right: 5px;
 `;
 
-const Owners = styled.div`
-  justify-content: flex-end;
-  display: flex;
-  padding: 3px;
-  span {
-    margin-right: 2px;
-  }
-
-  .avatar {
-    width: 28px;
-    height: 28px;
-  }
-`;
-
-const BuilderDropdownButton = styled(DropdownButton)`
-  margin-right: 5px;
-  padding-right: 8px !important;
-  padding-left: 3px !important;
-
-  flex: 1;
-  white-space: nowrap;
-  height: 37px;
-  color: ${p => p.theme.gray3} !important;
-`;
-
 const RuleAddButton = styled(Button)`
   width: 37px;
   height: 37px;

+ 48 - 0
src/sentry/static/sentry/app/views/settings/project/projectOwnership/selectOwners.jsx

@@ -0,0 +1,48 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+
+import MultiSelectField from '../../../../components/forms/multiSelectField';
+import ActorAvatar from '../../../../components/actorAvatar';
+
+import {t} from '../../../../locale';
+
+class ValueComponent extends React.Component {
+  static propTypes = {
+    value: PropTypes.object,
+    onRemove: PropTypes.func,
+  };
+
+  handleClick = () => {
+    this.props.onRemove(this.props.value);
+  };
+
+  render() {
+    return (
+      <a onClick={this.handleClick}>
+        <ActorAvatar actor={this.props.value.actor} size={28} />
+      </a>
+    );
+  }
+}
+
+export default class SelectOwners extends React.Component {
+  static propTypes = {
+    options: PropTypes.array.isRequired,
+    value: PropTypes.array,
+    onChange: PropTypes.func,
+  };
+
+  render() {
+    return (
+      <MultiSelectField
+        options={this.props.options}
+        multi={true}
+        style={{width: 200}}
+        valueComponent={ValueComponent}
+        placeholder={t('Add Owners')}
+        onChange={this.props.onChange}
+        value={this.props.value}
+      />
+    );
+  }
+}

+ 451 - 0
src/sentry/static/sentry/less/includes/react-select.less

@@ -0,0 +1,451 @@
+/**
+ * React Select
+ * ============
+ * Created by Jed Watson and Joss Mackison for KeystoneJS, http://www.keystonejs.com/
+ * https://twitter.com/jedwatson https://twitter.com/jossmackison https://twitter.com/keystonejs
+ * MIT License: https://github.com/JedWatson/react-select
+*/
+.Select {
+  position: relative;
+}
+.Select input::-webkit-contacts-auto-fill-button,
+.Select input::-webkit-credentials-auto-fill-button {
+  display: none !important;
+}
+.Select input::-ms-clear {
+  display: none !important;
+}
+.Select input::-ms-reveal {
+  display: none !important;
+}
+.Select,
+.Select div,
+.Select input,
+.Select span {
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
+}
+.Select.is-disabled .Select-arrow-zone {
+  cursor: default;
+  pointer-events: none;
+  opacity: 0.35;
+}
+.Select.is-disabled > .Select-control {
+  background-color: #f9f9f9;
+}
+.Select.is-disabled > .Select-control:hover {
+  box-shadow: none;
+}
+.Select.is-open > .Select-control {
+  border-bottom-right-radius: 0;
+  border-bottom-left-radius: 0;
+  background: #fff;
+  border-color: #b3b3b3 #ccc #d9d9d9;
+}
+.Select.is-open > .Select-control .Select-arrow {
+  top: -2px;
+  border-color: transparent transparent #999;
+  border-width: 0 5px 5px;
+}
+.Select.is-searchable.is-open > .Select-control {
+  cursor: text;
+}
+.Select.is-searchable.is-focused:not(.is-open) > .Select-control {
+  cursor: text;
+}
+.Select.is-focused > .Select-control {
+  background: #fff;
+}
+.Select.is-focused:not(.is-open) > .Select-control {
+  border-color: #007eff;
+  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 0 3px rgba(0, 126, 255, 0.1);
+  background: #fff;
+}
+.Select.has-value.is-clearable.Select--single > .Select-control .Select-value {
+  padding-right: 42px;
+}
+.Select.has-value.Select--single > .Select-control .Select-value .Select-value-label,
+.Select.has-value.is-pseudo-focused.Select--single
+  > .Select-control
+  .Select-value
+  .Select-value-label {
+  color: #333;
+}
+.Select.has-value.Select--single > .Select-control .Select-value a.Select-value-label,
+.Select.has-value.is-pseudo-focused.Select--single
+  > .Select-control
+  .Select-value
+  a.Select-value-label {
+  cursor: pointer;
+  text-decoration: none;
+}
+.Select.has-value.Select--single
+  > .Select-control
+  .Select-value
+  a.Select-value-label:hover,
+.Select.has-value.is-pseudo-focused.Select--single
+  > .Select-control
+  .Select-value
+  a.Select-value-label:hover,
+.Select.has-value.Select--single
+  > .Select-control
+  .Select-value
+  a.Select-value-label:focus,
+.Select.has-value.is-pseudo-focused.Select--single
+  > .Select-control
+  .Select-value
+  a.Select-value-label:focus {
+  color: #007eff;
+  outline: none;
+  text-decoration: underline;
+}
+.Select.has-value.Select--single
+  > .Select-control
+  .Select-value
+  a.Select-value-label:focus,
+.Select.has-value.is-pseudo-focused.Select--single
+  > .Select-control
+  .Select-value
+  a.Select-value-label:focus {
+  background: #fff;
+}
+.Select.has-value.is-pseudo-focused .Select-input {
+  opacity: 0;
+}
+.Select.is-open .Select-arrow,
+.Select .Select-arrow-zone:hover > .Select-arrow {
+  border-top-color: #666;
+}
+.Select.Select--rtl {
+  direction: rtl;
+  text-align: right;
+}
+.Select-control {
+  background-color: #fff;
+  border-color: #d9d9d9 #ccc #b3b3b3;
+  border-radius: 4px;
+  border: 1px solid #ccc;
+  color: #333;
+  cursor: default;
+  display: table;
+  border-spacing: 0;
+  border-collapse: separate;
+  height: 36px;
+  outline: none;
+  overflow: hidden;
+  position: relative;
+  width: 100%;
+}
+.Select-control:hover {
+  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.06);
+}
+.Select-control .Select-input:focus {
+  outline: none;
+  background: #fff;
+}
+.Select-placeholder,
+.Select--single > .Select-control .Select-value {
+  bottom: 0;
+  color: #aaa;
+  left: 0;
+  line-height: 34px;
+  padding-left: 10px;
+  padding-right: 10px;
+  position: absolute;
+  right: 0;
+  top: 0;
+  max-width: 100%;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+.Select-input {
+  height: 34px;
+  padding-left: 10px;
+  padding-right: 10px;
+  vertical-align: middle;
+}
+.Select-input > input {
+  width: 100%;
+  background: none transparent;
+  border: 0 none;
+  box-shadow: none;
+  cursor: default;
+  display: inline-block;
+  font-family: inherit;
+  font-size: inherit;
+  margin: 0;
+  outline: none;
+  line-height: 17px;
+  /* For IE 8 compatibility */
+  padding: 8px 0 12px;
+  /* For IE 8 compatibility */
+  -webkit-appearance: none;
+}
+.is-focused .Select-input > input {
+  cursor: text;
+}
+.has-value.is-pseudo-focused .Select-input {
+  opacity: 0;
+}
+.Select-control:not(.is-searchable) > .Select-input {
+  outline: none;
+}
+.Select-loading-zone {
+  cursor: pointer;
+  display: table-cell;
+  position: relative;
+  text-align: center;
+  vertical-align: middle;
+  width: 16px;
+}
+.Select-loading {
+  -webkit-animation: Select-animation-spin 400ms infinite linear;
+  -o-animation: Select-animation-spin 400ms infinite linear;
+  animation: Select-animation-spin 400ms infinite linear;
+  width: 16px;
+  height: 16px;
+  box-sizing: border-box;
+  border-radius: 50%;
+  border: 2px solid #ccc;
+  border-right-color: #333;
+  display: inline-block;
+  position: relative;
+  vertical-align: middle;
+}
+.Select-clear-zone {
+  -webkit-animation: Select-animation-fadeIn 200ms;
+  -o-animation: Select-animation-fadeIn 200ms;
+  animation: Select-animation-fadeIn 200ms;
+  color: #999;
+  cursor: pointer;
+  display: table-cell;
+  position: relative;
+  text-align: center;
+  vertical-align: middle;
+  width: 17px;
+}
+.Select-clear-zone:hover {
+  color: #d0021b;
+}
+.Select-clear {
+  display: inline-block;
+  font-size: 18px;
+  line-height: 1;
+}
+.Select--multi .Select-clear-zone {
+  width: 17px;
+}
+.Select-arrow-zone {
+  cursor: pointer;
+  display: table-cell;
+  position: relative;
+  text-align: center;
+  vertical-align: middle;
+  width: 25px;
+  padding-right: 5px;
+}
+.Select--rtl .Select-arrow-zone {
+  padding-right: 0;
+  padding-left: 5px;
+}
+.Select-arrow {
+  border-color: #999 transparent transparent;
+  border-style: solid;
+  border-width: 5px 5px 2.5px;
+  display: inline-block;
+  height: 0;
+  width: 0;
+  position: relative;
+}
+.Select-control > *:last-child {
+  padding-right: 5px;
+}
+.Select--multi .Select-multi-value-wrapper {
+  display: inline-block;
+}
+.Select .Select-aria-only {
+  position: absolute;
+  display: inline-block;
+  height: 1px;
+  width: 1px;
+  margin: -1px;
+  clip: rect(0, 0, 0, 0);
+  overflow: hidden;
+  float: left;
+}
+@-webkit-keyframes Select-animation-fadeIn {
+  from {
+    opacity: 0;
+  }
+  to {
+    opacity: 1;
+  }
+}
+@keyframes Select-animation-fadeIn {
+  from {
+    opacity: 0;
+  }
+  to {
+    opacity: 1;
+  }
+}
+.Select-menu-outer {
+  border-bottom-right-radius: 4px;
+  border-bottom-left-radius: 4px;
+  background-color: #fff;
+  border: 1px solid #ccc;
+  border-top-color: #e6e6e6;
+  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.06);
+  box-sizing: border-box;
+  margin-top: -1px;
+  max-height: 200px;
+  position: absolute;
+  left: 0;
+  top: 100%;
+  width: 100%;
+  z-index: 1;
+  -webkit-overflow-scrolling: touch;
+}
+.Select-menu {
+  max-height: 198px;
+  overflow-y: auto;
+}
+.Select-option {
+  box-sizing: border-box;
+  background-color: #fff;
+  color: #666666;
+  cursor: pointer;
+  display: block;
+  padding: 8px 10px;
+}
+.Select-option:last-child {
+  border-bottom-right-radius: 4px;
+  border-bottom-left-radius: 4px;
+}
+.Select-option.is-selected {
+  background-color: #f5faff;
+  /* Fallback color for IE 8 */
+  background-color: rgba(0, 126, 255, 0.04);
+  color: #333;
+}
+.Select-option.is-focused {
+  background-color: #ebf5ff;
+  /* Fallback color for IE 8 */
+  background-color: rgba(0, 126, 255, 0.08);
+  color: #333;
+}
+.Select-option.is-disabled {
+  color: #cccccc;
+  cursor: default;
+}
+.Select-noresults {
+  box-sizing: border-box;
+  color: #999999;
+  cursor: default;
+  display: block;
+  padding: 8px 10px;
+}
+.Select--multi .Select-input {
+  vertical-align: middle;
+  margin-left: 10px;
+  padding: 0;
+}
+.Select--multi.Select--rtl .Select-input {
+  margin-left: 0;
+  margin-right: 10px;
+}
+.Select--multi.has-value .Select-input {
+  margin-left: 5px;
+}
+.Select--multi .Select-value {
+  background-color: #ebf5ff;
+  /* Fallback color for IE 8 */
+  background-color: rgba(0, 126, 255, 0.08);
+  border-radius: 2px;
+  border: 1px solid #c2e0ff;
+  /* Fallback color for IE 8 */
+  border: 1px solid rgba(0, 126, 255, 0.24);
+  color: #007eff;
+  display: inline-block;
+  font-size: 0.9em;
+  line-height: 1.4;
+  margin-left: 5px;
+  margin-top: 5px;
+  vertical-align: top;
+}
+.Select--multi .Select-value-icon,
+.Select--multi .Select-value-label {
+  display: inline-block;
+  vertical-align: middle;
+}
+.Select--multi .Select-value-label {
+  border-bottom-right-radius: 2px;
+  border-top-right-radius: 2px;
+  cursor: default;
+  padding: 2px 5px;
+}
+.Select--multi a.Select-value-label {
+  color: #007eff;
+  cursor: pointer;
+  text-decoration: none;
+}
+.Select--multi a.Select-value-label:hover {
+  text-decoration: underline;
+}
+.Select--multi .Select-value-icon {
+  cursor: pointer;
+  border-bottom-left-radius: 2px;
+  border-top-left-radius: 2px;
+  border-right: 1px solid #c2e0ff;
+  /* Fallback color for IE 8 */
+  border-right: 1px solid rgba(0, 126, 255, 0.24);
+  padding: 1px 5px 3px;
+}
+.Select--multi .Select-value-icon:hover,
+.Select--multi .Select-value-icon:focus {
+  background-color: #d8eafd;
+  /* Fallback color for IE 8 */
+  background-color: rgba(0, 113, 230, 0.08);
+  color: #0071e6;
+}
+.Select--multi .Select-value-icon:active {
+  background-color: #c2e0ff;
+  /* Fallback color for IE 8 */
+  background-color: rgba(0, 126, 255, 0.24);
+}
+.Select--multi.Select--rtl .Select-value {
+  margin-left: 0;
+  margin-right: 5px;
+}
+.Select--multi.Select--rtl .Select-value-icon {
+  border-right: none;
+  border-left: 1px solid #c2e0ff;
+  /* Fallback color for IE 8 */
+  border-left: 1px solid rgba(0, 126, 255, 0.24);
+}
+.Select--multi.is-disabled .Select-value {
+  background-color: #fcfcfc;
+  border: 1px solid #e3e3e3;
+  color: #333;
+}
+.Select--multi.is-disabled .Select-value-icon {
+  cursor: not-allowed;
+  border-right: 1px solid #e3e3e3;
+}
+.Select--multi.is-disabled .Select-value-icon:hover,
+.Select--multi.is-disabled .Select-value-icon:focus,
+.Select--multi.is-disabled .Select-value-icon:active {
+  background-color: #fcfcfc;
+}
+@keyframes Select-animation-spin {
+  to {
+    transform: rotate(1turn);
+  }
+}
+@-webkit-keyframes Select-animation-spin {
+  to {
+    -webkit-transform: rotate(1turn);
+  }
+}

+ 1 - 0
src/sentry/static/sentry/less/sentry.less

@@ -10,6 +10,7 @@
 @import url('./includes/typeahead.less');
 @import url('./includes/animate.less');
 @import url('./includes/tooltips.less');
+@import url('./includes/react-select.less');
 @import '~platformicons/platformicons/platformicons.css';
 
 // App Components

+ 196 - 156
tests/js/spec/views/__snapshots__/ownershipInput.spec.jsx.snap

@@ -89,7 +89,7 @@ exports[`ProjectTeamsSettings render() renders 1`] = `
   >
     <BuilderBar>
       <div
-        className="css-1rsoebt-BuilderBar css-wiuq245"
+        className="css-1rsoebt-BuilderBar css-1r9wn455"
       >
         <BuilderSelect
           onChange={[Function]}
@@ -97,7 +97,7 @@ exports[`ProjectTeamsSettings render() renders 1`] = `
           value="path"
         >
           <SelectInput
-            className="css-1eslqkc-BuilderSelect css-wiuq246"
+            className="css-1eslqkc-BuilderSelect css-1r9wn456"
             disabled={false}
             multiple={false}
             onChange={[Function]}
@@ -107,7 +107,7 @@ exports[`ProjectTeamsSettings render() renders 1`] = `
             value="path"
           >
             <select
-              className="css-1eslqkc-BuilderSelect css-wiuq246"
+              className="css-1eslqkc-BuilderSelect css-1r9wn456"
               disabled={false}
               multiple={false}
               onChange={[Function]}
@@ -135,7 +135,7 @@ exports[`ProjectTeamsSettings render() renders 1`] = `
           value=""
         >
           <input
-            className="css-1t4syiu-Input-BuilderInput css-wiuq247"
+            className="css-1t4syiu-Input-BuilderInput css-1r9wn457"
             onChange={[Function]}
             placeholder="src/example/*"
             value=""
@@ -145,17 +145,17 @@ exports[`ProjectTeamsSettings render() renders 1`] = `
           src="icon-chevron-right"
         >
           <InlineSvg
-            className="css-a4tn6s-Divider css-wiuq248"
+            className="css-a4tn6s-Divider css-1r9wn458"
             src="icon-chevron-right"
           >
             <StyledSvg
-              className="css-a4tn6s-Divider css-wiuq248"
+              className="css-a4tn6s-Divider css-1r9wn458"
               height="1em"
               viewBox={Object {}}
               width="1em"
             >
               <svg
-                className="css-wiuq248 css-5e2rei-StyledSvg css-adkcw30"
+                className="css-1r9wn458 css-5e2rei-StyledSvg css-adkcw30"
                 height="1em"
                 viewBox={Object {}}
                 width="1em"
@@ -171,171 +171,211 @@ exports[`ProjectTeamsSettings render() renders 1`] = `
         <Flex
           align="center"
           flex="1"
+          mr={1}
         >
           <Base
             align="center"
-            className="css-1yrw3fm"
+            className="css-1q48dzo"
             flex="1"
+            mr={1}
           >
             <div
-              className="css-1yrw3fm"
+              className="css-1q48dzo"
               is={null}
             >
-              <DropdownAutoComplete
-                alignMenu="right"
-                items={
-                  Array [
-                    Object {
-                      "items": Array [],
-                      "label": "Teams",
-                      "value": "team",
-                    },
-                    Object {
-                      "items": Array [],
-                      "label": "Users",
-                      "value": "user",
-                    },
-                  ]
-                }
-                onSelect={[Function]}
+              <SelectOwners
+                onChange={[Function]}
+                options={Array []}
+                value={Array []}
               >
-                <DropdownAutoCompleteMenu
-                  alignMenu="right"
-                  blendCorner={true}
-                  items={
-                    Array [
-                      Object {
-                        "items": Array [],
-                        "label": "Teams",
-                        "value": "team",
-                      },
-                      Object {
-                        "items": Array [],
-                        "label": "Users",
-                        "value": "user",
-                      },
-                    ]
+                <MultiSelectField
+                  disabled={false}
+                  hideErrorMessage={false}
+                  multi={true}
+                  onChange={[Function]}
+                  options={Array []}
+                  placeholder="Add Owners"
+                  required={false}
+                  style={
+                    Object {
+                      "width": 200,
+                    }
                   }
-                  onSelect={[Function]}
+                  value={Array []}
+                  valueComponent={[Function]}
                 >
-                  <AutoComplete
-                    itemToString={[Function]}
-                    onSelect={[Function]}
+                  <MultiSelect
+                    arrowRenderer={[Function]}
+                    disabled={false}
+                    hideErrorMessage={false}
+                    id="id-undefined"
+                    multi={true}
+                    onChange={[Function]}
+                    options={Array []}
+                    placeholder="Add Owners"
+                    required={false}
+                    style={
+                      Object {
+                        "width": 200,
+                      }
+                    }
+                    value={Array []}
+                    valueComponent={[Function]}
                   >
-                    <DropdownMenu
-                      isOpen={false}
-                      keepMenuOpen={false}
-                      onClickOutside={[Function]}
+                    <Select
+                      arrowRenderer={[Function]}
+                      autosize={true}
+                      backspaceRemoves={true}
+                      backspaceToRemoveMessage="Press backspace to remove {label}"
+                      className="css-1yznv6y-MultiSelect css-12eevnk0"
+                      clearAllText="Clear all"
+                      clearRenderer={[Function]}
+                      clearValueText="Clear value"
+                      clearable={true}
+                      closeOnSelect={true}
+                      deleteRemoves={true}
+                      delimiter=","
+                      disabled={false}
+                      escapeClearsValue={true}
+                      filterOptions={[Function]}
+                      hideErrorMessage={false}
+                      id="id-undefined"
+                      ignoreAccents={true}
+                      ignoreCase={true}
+                      inputProps={Object {}}
+                      isLoading={false}
+                      joinValues={false}
+                      labelKey="label"
+                      matchPos="any"
+                      matchProp="any"
+                      menuBuffer={0}
+                      menuRenderer={[Function]}
+                      multi={true}
+                      noResultsText="No results found"
+                      onBlurResetsInput={true}
+                      onChange={[Function]}
+                      onCloseResetsInput={true}
+                      onSelectResetsInput={true}
+                      openOnClick={true}
+                      optionComponent={[Function]}
+                      options={Array []}
+                      pageSize={5}
+                      placeholder="Add Owners"
+                      removeSelected={true}
+                      required={false}
+                      rtl={false}
+                      scrollMenuIntoView={true}
+                      searchable={true}
+                      simpleValue={false}
+                      style={
+                        Object {
+                          "width": 200,
+                        }
+                      }
+                      tabSelectsValue={true}
+                      trimFilter={true}
+                      value={Array []}
+                      valueComponent={[Function]}
+                      valueKey="value"
                     >
-                      <AutoCompleteRoot>
-                        <Component
-                          className="css-6v04yn-AutoCompleteRoot css-1w01jf00"
+                      <div
+                        className="Select css-1yznv6y-MultiSelect css-12eevnk0 is-clearable is-searchable Select--multi"
+                      >
+                        <div
+                          className="Select-control"
+                          onKeyDown={[Function]}
+                          onMouseDown={[Function]}
+                          onTouchEnd={[Function]}
+                          onTouchMove={[Function]}
+                          onTouchStart={[Function]}
+                          style={
+                            Object {
+                              "width": 200,
+                            }
+                          }
                         >
-                          <div
-                            className="css-6v04yn-AutoCompleteRoot css-1w01jf00"
+                          <span
+                            className="Select-multi-value-wrapper"
+                            id="react-select-2--value"
                           >
                             <div
-                              onClick={[Function]}
-                              onMouseEnter={[Function]}
-                              onMouseLeave={[Function]}
-                              role="button"
+                              className="Select-placeholder"
                             >
-                              <BuilderDropdownButton
-                                isOpen={false}
-                                size="zero"
-                              >
-                                <DropdownButton
-                                  className="css-agp1qb-BuilderDropdownButton css-wiuq2410"
-                                  isOpen={false}
-                                  size="zero"
-                                >
-                                  <StyledButton
-                                    className="css-agp1qb-BuilderDropdownButton css-wiuq2410"
-                                    isOpen={false}
-                                    size="zero"
-                                  >
-                                    <Component
-                                      className="css-wiuq2410 css-vx22y2-StyledButton css-1pig06q1"
-                                      isOpen={false}
-                                      size="zero"
-                                    >
-                                      <Button
-                                        className="css-wiuq2410 css-vx22y2-StyledButton css-1pig06q1"
-                                        disabled={false}
-                                        size="zero"
-                                      >
-                                        <button
-                                          className="css-wiuq2410 css-vx22y2-StyledButton css-1pig06q1 button button-default button-zero"
-                                          disabled={false}
-                                          onClick={[Function]}
-                                          role="button"
-                                        >
-                                          <Flex
-                                            align="center"
-                                            className="button-label"
-                                          >
-                                            <Base
-                                              align="center"
-                                              className="button-label css-5ipae5"
-                                            >
-                                              <div
-                                                className="button-label css-5ipae5"
-                                                is={null}
-                                              >
-                                                <Owners>
-                                                  <div
-                                                    className="css-1t34ifm-Owners css-wiuq249"
-                                                  />
-                                                </Owners>
-                                                <div>
-                                                  Add Owners
-                                                </div>
-                                                <StyledChevronDown>
-                                                  <Component
-                                                    className="css-17v3tc-StyledChevronDown css-1pig06q0"
-                                                  >
-                                                    <InlineSvg
-                                                      className="css-17v3tc-StyledChevronDown css-1pig06q0"
-                                                      src="icon-chevron-down"
-                                                    >
-                                                      <StyledSvg
-                                                        className="css-17v3tc-StyledChevronDown css-1pig06q0"
-                                                        height="1em"
-                                                        viewBox={Object {}}
-                                                        width="1em"
-                                                      >
-                                                        <svg
-                                                          className="css-1pig06q0 css-1vk3ljv-StyledSvg css-adkcw30"
-                                                          height="1em"
-                                                          viewBox={Object {}}
-                                                          width="1em"
-                                                        >
-                                                          <use
-                                                            href="#test"
-                                                            xlinkHref="#test"
-                                                          />
-                                                        </svg>
-                                                      </StyledSvg>
-                                                    </InlineSvg>
-                                                  </Component>
-                                                </StyledChevronDown>
-                                              </div>
-                                            </Base>
-                                          </Flex>
-                                        </button>
-                                      </Button>
-                                    </Component>
-                                  </StyledButton>
-                                </DropdownButton>
-                              </BuilderDropdownButton>
+                              Add Owners
                             </div>
-                          </div>
-                        </Component>
-                      </AutoCompleteRoot>
-                    </DropdownMenu>
-                  </AutoComplete>
-                </DropdownAutoCompleteMenu>
-              </DropdownAutoComplete>
+                            <AutosizeInput
+                              aria-activedescendant="react-select-2--value"
+                              aria-expanded="false"
+                              aria-haspopup="false"
+                              aria-owns=""
+                              className="Select-input"
+                              id="id-undefined"
+                              injectStyles={true}
+                              minWidth="5"
+                              onBlur={[Function]}
+                              onChange={[Function]}
+                              onFocus={[Function]}
+                              required={false}
+                              role="combobox"
+                              value=""
+                            >
+                              <div
+                                className="Select-input"
+                                style={
+                                  Object {
+                                    "display": "inline-block",
+                                  }
+                                }
+                              >
+                                <input
+                                  aria-activedescendant="react-select-2--value"
+                                  aria-expanded="false"
+                                  aria-haspopup="false"
+                                  aria-owns=""
+                                  id="id-undefined"
+                                  onBlur={[Function]}
+                                  onChange={[Function]}
+                                  onFocus={[Function]}
+                                  required={false}
+                                  role="combobox"
+                                  style={
+                                    Object {
+                                      "boxSizing": "content-box",
+                                      "width": "5px",
+                                    }
+                                  }
+                                  value=""
+                                />
+                                <div
+                                  style={
+                                    Object {
+                                      "height": 0,
+                                      "left": 0,
+                                      "overflow": "scroll",
+                                      "position": "absolute",
+                                      "top": 0,
+                                      "visibility": "hidden",
+                                      "whiteSpace": "pre",
+                                    }
+                                  }
+                                />
+                              </div>
+                            </AutosizeInput>
+                          </span>
+                          <span
+                            className="Select-arrow-zone"
+                            onMouseDown={[Function]}
+                          >
+                            <span
+                              className="icon-arrow-down"
+                            />
+                          </span>
+                        </div>
+                      </div>
+                    </Select>
+                  </MultiSelect>
+                </MultiSelectField>
+              </SelectOwners>
             </div>
           </Base>
         </Flex>
@@ -346,7 +386,7 @@ exports[`ProjectTeamsSettings render() renders 1`] = `
           size="zero"
         >
           <Button
-            className="css-3daogo-RuleAddButton css-wiuq2411"
+            className="css-3daogo-RuleAddButton css-1r9wn459"
             disabled={false}
             icon="icon-circle-add"
             onClick={[Function]}
@@ -354,7 +394,7 @@ exports[`ProjectTeamsSettings render() renders 1`] = `
             size="zero"
           >
             <button
-              className="css-3daogo-RuleAddButton css-wiuq2411 button button-primary button-zero"
+              className="css-3daogo-RuleAddButton css-1r9wn459 button button-primary button-zero"
               disabled={false}
               onClick={[Function]}
               role="button"

File diff suppressed because it is too large
+ 673 - 399
tests/js/spec/views/__snapshots__/ruleBuilder.spec.jsx.snap


+ 6 - 8
tests/js/spec/views/ruleBuilder.spec.jsx

@@ -64,10 +64,9 @@ describe('RuleBuilder', function() {
       add.simulate('click');
       expect(handleAdd).not.toHaveBeenCalled();
 
-      let openDropdown = wrapper.find('BuilderDropdownButton');
-      openDropdown.simulate('click');
-      let user = wrapper.find('AutoCompleteItem').first();
-      user.simulate('click');
+      // Simulate select first element via down arrow / enter
+      wrapper.find('.Select-control').simulate('keyDown', {keyCode: 40});
+      wrapper.find('.Select-control').simulate('keyDown', {keyCode: 13});
 
       add.simulate('click');
       expect(handleAdd).toHaveBeenCalled();
@@ -90,10 +89,9 @@ describe('RuleBuilder', function() {
         TestStubs.routerContext()
       );
 
-      let openDropdown = wrapper.find('BuilderDropdownButton');
-      openDropdown.simulate('click');
-      let user = wrapper.find('AutoCompleteItem').first();
-      user.simulate('click');
+      // Simulate select first element via down arrow / enter
+      wrapper.find('.Select-control').simulate('keyDown', {keyCode: 40});
+      wrapper.find('.Select-control').simulate('keyDown', {keyCode: 13});
 
       let ruleCandidate = wrapper.find('RuleCandidate').first();
       ruleCandidate.simulate('click');

Some files were not shown because too many files changed in this diff