Skip to content
This repository was archived by the owner on Mar 13, 2025. It is now read-only.

Commit 3819b56

Browse files
committed
Updated to use react-select's AsyncCreatableSelect for getting suggestions in AddModal
- Removed CreatableSelect from ReactSelect component - Created new AsyncSelect component - Decoupled suggestion state from redux - Allow AsyncSelect to handle its own state
1 parent 7130123 commit 3819b56

File tree

7 files changed

+220
-123
lines changed

7 files changed

+220
-123
lines changed

package-lock.json

+35
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/components/AsyncSelect/index.jsx

+111
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/**
2+
* AsyncSelect
3+
*
4+
* A wrapper for react-select's AsyncCreatableSelect.
5+
*/
6+
import React from "react";
7+
import PT from "prop-types";
8+
import AsyncCreatableSelect from "react-select/async-creatable";
9+
import "./styles.module.scss";
10+
11+
const AsyncSelect = (props) => {
12+
const customStyles = {
13+
control: (provided, state) => ({
14+
...provided,
15+
minHeight: "40px",
16+
border: "1px solid #aaaaab",
17+
borderColor: state.isFocused ? "#55a5ff" : "#aaaaab",
18+
boxShadow: state.isFocused ? "0 0 2px 1px #cee6ff" : provided.boxShadow,
19+
}),
20+
menu: (provided) => ({
21+
...provided,
22+
minHeight: "40px",
23+
zIndex: 10,
24+
}),
25+
valueContainer: (provided) => ({
26+
...provided,
27+
padding: "2px 6px",
28+
}),
29+
input: (provided) => ({
30+
...provided,
31+
margin: "0px",
32+
height: "auto",
33+
padding: "0",
34+
}),
35+
indicatorSeparator: () => ({
36+
display: "none",
37+
}),
38+
indicatorsContainer: (provided) => ({
39+
...provided,
40+
height: "auto",
41+
}),
42+
option: (provided) => ({
43+
...provided,
44+
minHeight: "32px",
45+
}),
46+
placeholder: (provided) => ({
47+
...provided,
48+
color: "#AAAAAA",
49+
fontFamily: "Roboto",
50+
fontSize: "14px",
51+
lineHeight: "22px",
52+
textAlign: "left",
53+
fontWeight: "400",
54+
}),
55+
multiValue: (provided) => ({
56+
...provided,
57+
margin: "3px 3px",
58+
color: "#AAAAAA",
59+
fontFamily: "Roboto",
60+
fontSize: "14px",
61+
lineHeight: "22px",
62+
textAlign: "left",
63+
borderRadius: "5px",
64+
}),
65+
dropdownIndicator: () => ({
66+
display: "none",
67+
}),
68+
};
69+
70+
return (
71+
<div styleName="select-wrapper">
72+
<AsyncCreatableSelect
73+
value={props.value}
74+
styles={customStyles}
75+
onChange={props.onChange}
76+
styleName={props.error ? "error" : ""}
77+
isMulti={props.isMulti}
78+
onBlur={props.onBlur}
79+
onFocus={props.onFocus}
80+
placeholder={props.placeholder}
81+
onInputChange={props.onInputChange}
82+
noOptionsMessage={() => props.noOptionsText}
83+
loadingMessage={() => props.loadingText}
84+
isDisabled={props.disabled}
85+
cacheOptions={props.cacheOptions}
86+
loadOptions={props.loadOptions}
87+
defaultOptions={props.defaultOptions}
88+
/>
89+
</div>
90+
)
91+
}
92+
93+
AsyncSelect.propTypes = {
94+
value: PT.string,
95+
onChange: PT.func,
96+
placeholder: PT.string,
97+
error: PT.string,
98+
isMulti: PT.bool,
99+
onBlur: PT.func,
100+
onFocus: PT.func,
101+
onInputChange: PT.func,
102+
cacheOptions: PT.bool,
103+
onInputChange: PT.func,
104+
noOptionsText: PT.string,
105+
loadingText: PT.string,
106+
loadOptions: PT.func,
107+
defaultOptions: PT.bool || PT.array,
108+
disabled: PT.bool,
109+
}
110+
111+
export default AsyncSelect;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
.error {
2+
:first-child {
3+
border-color: #ff5b52;
4+
}
5+
}
6+
7+
.select-wrapper {
8+
input {
9+
border: none !important;
10+
box-shadow: none !important;
11+
transition: none !important;
12+
height: 28px;
13+
}
14+
}
15+
16+
.react-select__option {
17+
min-height: 32px;
18+
}

src/components/ReactSelect/index.jsx

+14-33
Original file line numberDiff line numberDiff line change
@@ -70,38 +70,20 @@ const ReactSelect = (props) => {
7070

7171
return (
7272
<div styleName="select-wrapper">
73-
{props.isCreatable ? (
74-
<CreatableSelect
75-
value={props.value}
76-
styles={customStyles}
77-
onChange={props.onChange}
78-
options={props.options}
79-
styleName={props.error ? "error" : ""}
80-
isMulti={props.isMulti}
81-
onBlur={props.onBlur}
82-
onFocus={props.onFocus}
83-
placeholder={props.placeholder}
84-
onInputChange={props.onInputChange}
85-
noOptionsMessage={() => props.noOptionsText}
86-
createOptionPosition="first"
87-
isDisabled={props.disabled}
88-
/>
89-
) : (
90-
<Select
91-
value={props.value}
92-
styles={customStyles}
93-
onChange={props.onChange}
94-
options={props.options}
95-
styleName={props.error ? "error" : ""}
96-
isMulti={props.isMulti}
97-
onBlur={props.onBlur}
98-
onFocus={props.onFocus}
99-
placeholder={props.placeholder}
100-
onInputChange={props.onInputChange}
101-
noOptionsMessage={() => props.noOptionsText}
102-
isDisabled={props.disabled}
103-
/>
104-
)}
73+
<Select
74+
value={props.value}
75+
styles={customStyles}
76+
onChange={props.onChange}
77+
options={props.options}
78+
styleName={props.error ? "error" : ""}
79+
isMulti={props.isMulti}
80+
onBlur={props.onBlur}
81+
onFocus={props.onFocus}
82+
placeholder={props.placeholder}
83+
onInputChange={props.onInputChange}
84+
noOptionsMessage={() => props.noOptionsText}
85+
isDisabled={props.disabled}
86+
/>
10587
</div>
10688
);
10789
};
@@ -121,7 +103,6 @@ ReactSelect.propTypes = {
121103
label: PT.string.isRequired,
122104
}).isRequired
123105
),
124-
isCreatable: PT.bool,
125106
noOptionsText: PT.string,
126107
disabled: PT.bool,
127108
};

src/routes/TeamAccess/actions/index.js

-26
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import {
66
getTeamMembers,
77
getTeamInvitees,
88
deleteTeamMember,
9-
getMemberSuggestions,
109
postMembers,
1110
} from "services/teams";
1211
import { ACTION_TYPE } from "constants";
@@ -74,31 +73,6 @@ export const removeTeamMember = (teamId, memberId) => ({
7473
},
7574
});
7675

77-
/**
78-
* Loads suggestions for invites
79-
*
80-
* @param {string} fragment
81-
*
82-
* @returns {Promise<object[]>} list of suggestions or error
83-
*/
84-
export const loadSuggestions = (fragment) => ({
85-
type: ACTION_TYPE.LOAD_MEMBERS_SUGGESTIONS,
86-
payload: async () => {
87-
const res = await getMemberSuggestions(fragment);
88-
return res.data.result.content;
89-
},
90-
meta: {
91-
fragment,
92-
},
93-
});
94-
95-
/**
96-
* Clears invite suggestions
97-
*/
98-
export const clearSuggestions = () => ({
99-
type: ACTION_TYPE.CLEAR_MEMBERS_SUGGESTIONS,
100-
});
101-
10276
/**
10377
* Adds members to team
10478
*

0 commit comments

Comments
 (0)