1
- import React from "react" ;
1
+ import React , { useEffect } from "react" ;
2
2
import PT from "prop-types" ;
3
3
4
4
import Button from "../Button" ;
@@ -10,6 +10,7 @@ import { useAuth0 } from "../../react-auth0-spa";
10
10
import * as groupLib from "../../lib/groups" ;
11
11
12
12
import style from "./style.module.scss" ;
13
+ import Axios from "axios" ;
13
14
14
15
export default function AddToGroupModal ( { onCancel, updateUser, user } ) {
15
16
const apiClient = api ( ) ;
@@ -21,34 +22,50 @@ export default function AddToGroupModal({ onCancel, updateUser, user }) {
21
22
const [ updatingGroups , setUpdatingGroups ] = React . useState ( false ) ;
22
23
const [ userGroups , setUserGroups ] = React . useState ( user . groups ) ;
23
24
const [ creatingGroup , setCreatingGroup ] = React . useState ( false ) ;
25
+ const cancelTokenSource = Axios . CancelToken . source ( ) ;
26
+
27
+ /**
28
+ * Component unmount trigger
29
+ */
30
+ useEffect ( ( ) => {
31
+ return ( ) => {
32
+ cancelTokenSource . cancel ( ) ;
33
+ } ;
34
+ } ) ;
24
35
25
36
React . useEffect ( ( ) => {
26
37
if ( isLoading || ! isAuthenticated ) {
27
38
return ;
28
39
}
29
40
30
41
( async ( ) => {
31
- const groups = await groupLib . getGroups ( apiClient , auth0User . nickname ) ;
42
+ const groups = await groupLib . getGroups (
43
+ apiClient ,
44
+ auth0User . nickname ,
45
+ cancelTokenSource . token
46
+ ) ;
32
47
33
- groups . myGroups . forEach ( ( g , i , a ) => {
34
- userGroups . forEach ( ( ug , iug , aug ) => {
35
- if ( g . id === ug . id && ! ug . isDeleted ) {
36
- a [ i ] = { ...g , isSelected : true } ;
37
- }
48
+ if ( groups ) {
49
+ groups . myGroups . forEach ( ( g , i , a ) => {
50
+ userGroups . forEach ( ( ug , iug , aug ) => {
51
+ if ( g . id === ug . id && ! ug . isDeleted ) {
52
+ a [ i ] = { ...g , isSelected : true } ;
53
+ }
54
+ } ) ;
38
55
} ) ;
39
- } ) ;
40
56
41
- groups . otherGroups . forEach ( ( g , i , a ) => {
42
- userGroups . forEach ( ( ug , iug , aug ) => {
43
- if ( g . id === ug . id && ! ug . isDeleted ) {
44
- a [ i ] = { ...g , isSelected : true } ;
45
- }
57
+ groups . otherGroups . forEach ( ( g , i , a ) => {
58
+ userGroups . forEach ( ( ug , iug , aug ) => {
59
+ if ( g . id === ug . id && ! ug . isDeleted ) {
60
+ a [ i ] = { ...g , isSelected : true } ;
61
+ }
62
+ } ) ;
46
63
} ) ;
47
- } ) ;
48
64
49
- setMyGroups ( groups . myGroups ) ;
50
- setOtherGroups ( groups . otherGroups ) ;
51
- setIsLoadingGroups ( false ) ;
65
+ setMyGroups ( groups . myGroups ) ;
66
+ setOtherGroups ( groups . otherGroups ) ;
67
+ setIsLoadingGroups ( false ) ;
68
+ }
52
69
} ) ( ) ;
53
70
// eslint-disable-next-line react-hooks/exhaustive-deps
54
71
} , [ isLoading , isAuthenticated , auth0User ] ) ;
@@ -106,6 +123,14 @@ export default function AddToGroupModal({ onCancel, updateUser, user }) {
106
123
alert ( "Enter a group name" ) ;
107
124
return ;
108
125
}
126
+ if ( groupName . length < 3 ) {
127
+ alert ( "Group name must be more than three characters" ) ;
128
+ return ;
129
+ }
130
+ if ( groupName . length > 150 ) {
131
+ alert ( "Group name cannot exceed 150 characters" ) ;
132
+ return ;
133
+ }
109
134
110
135
setCreatingGroup ( true ) ;
111
136
@@ -131,59 +156,81 @@ export default function AddToGroupModal({ onCancel, updateUser, user }) {
131
156
} ;
132
157
133
158
return (
134
- < Modal onCancel = { onCancel } >
159
+ < Modal
160
+ onCancel = { onCancel }
161
+ className = { style . container }
162
+ overlayClassName = { style . overlay }
163
+ >
135
164
< h1 className = { style . title } > Add to Group</ h1 >
136
- < div className = { style . searchRow } >
137
- < ZoomIcon className = { style . zoomIcon } />
138
- < input
139
- className = { style . search }
140
- onChange = { ( { target } ) => {
141
- setFilter ( target . value ) ;
142
- setImmediate ( ( ) => target . focus ( ) ) ;
143
- } }
144
- placeholder = "Search or create group"
145
- value = { filter }
146
- disabled = { loadingGroups }
147
- />
148
- < Button
149
- className = { style . createButton }
150
- onClick = { createGroup }
151
- disabled = { creatingGroup }
152
- >
153
- { creatingGroup ? "Creating..." : "+ Create" }
154
- </ Button >
155
- </ div >
156
- < h3 className = { style . subTitle } >
157
- My groups{ loadingGroups && " (Loading...)" }
158
- </ h3 >
159
- < div className = { style . groups } >
160
- { ! loadingGroups &&
161
- myGroups
162
- . filter ( ( g ) => g . name . toLowerCase ( ) . includes ( filter . toLowerCase ( ) ) )
163
- . map ( ( g ) => (
164
- < Group
165
- checked = { g . isSelected === true }
166
- group = { g }
167
- key = { g . id }
168
- onSwitch = { ( ) => switchSelected ( g ) }
169
- />
170
- ) ) }
171
- </ div >
172
- < h3 className = { style . subTitle } >
173
- Other Groups{ loadingGroups && " (Loading...)" }
174
- </ h3 >
175
165
< div className = { style . groups } >
176
- { ! loadingGroups &&
177
- otherGroups
178
- . filter ( ( g ) => g . name . toLowerCase ( ) . includes ( filter . toLowerCase ( ) ) )
179
- . map ( ( g ) => (
180
- < Group
181
- checked = { g . isSelected === true }
182
- group = { g }
183
- key = { g . id }
184
- onSwitch = { ( ) => switchSelected ( g ) }
185
- />
186
- ) ) }
166
+ < div className = { style . searchRow } >
167
+ < ZoomIcon className = { style . zoomIcon } />
168
+ < input
169
+ className = { style . search }
170
+ onChange = { ( { target } ) => {
171
+ setFilter ( target . value ) ;
172
+ setImmediate ( ( ) => target . focus ( ) ) ;
173
+ } }
174
+ placeholder = "Search or create group"
175
+ value = { filter }
176
+ disabled = { loadingGroups }
177
+ />
178
+ < Button
179
+ className = { style . createButton }
180
+ onClick = { createGroup }
181
+ disabled = { creatingGroup }
182
+ >
183
+ { creatingGroup ? "Creating..." : "+ Create" }
184
+ </ Button >
185
+ </ div >
186
+ < h3 className = { style . subTitle } >
187
+ My groups{ loadingGroups && " (Loading...)" }
188
+ </ h3 >
189
+ < div >
190
+ { ! loadingGroups &&
191
+ myGroups
192
+ . filter ( ( g ) =>
193
+ g . name . toLowerCase ( ) . includes ( filter . toLowerCase ( ) )
194
+ )
195
+ . map ( ( g ) => (
196
+ < Group
197
+ checked = { g . isSelected === true }
198
+ group = { g }
199
+ key = { g . id }
200
+ onSwitch = { ( ) => switchSelected ( g ) }
201
+ />
202
+ ) ) }
203
+ </ div >
204
+ { myGroups . filter ( ( g ) =>
205
+ g . name . toLowerCase ( ) . includes ( filter . toLowerCase ( ) )
206
+ ) . length === 0 &&
207
+ ! loadingGroups && (
208
+ < div className = { style . message } > No results found</ div >
209
+ ) }
210
+ < h3 className = { style . subTitle } >
211
+ Other Groups{ loadingGroups && " (Loading...)" }
212
+ </ h3 >
213
+ < div >
214
+ { ! loadingGroups &&
215
+ otherGroups
216
+ . filter ( ( g ) =>
217
+ g . name . toLowerCase ( ) . includes ( filter . toLowerCase ( ) )
218
+ )
219
+ . map ( ( g ) => (
220
+ < Group
221
+ checked = { g . isSelected === true }
222
+ group = { g }
223
+ key = { g . id }
224
+ onSwitch = { ( ) => switchSelected ( g ) }
225
+ />
226
+ ) ) }
227
+ </ div >
228
+ { otherGroups . filter ( ( g ) =>
229
+ g . name . toLowerCase ( ) . includes ( filter . toLowerCase ( ) )
230
+ ) . length === 0 &&
231
+ ! loadingGroups && (
232
+ < div className = { style . message } > No results found</ div >
233
+ ) }
187
234
</ div >
188
235
< div className = { style . buttons } >
189
236
< Button onClick = { onCancel } disabled = { updatingGroups || creatingGroup } >
0 commit comments