|
@@ -1,3 +1,5 @@
|
|
1
|
+// @flow
|
|
2
|
+
|
1
|
3
|
import Avatar from '@atlaskit/avatar';
|
2
|
4
|
import InlineMessage from '@atlaskit/inline-message';
|
3
|
5
|
import { Immutable } from 'nuclear-js';
|
|
@@ -8,8 +10,7 @@ import { connect } from 'react-redux';
|
8
|
10
|
import { getInviteURL } from '../../base/connection';
|
9
|
11
|
import { Dialog, hideDialog } from '../../base/dialog';
|
10
|
12
|
import { translate } from '../../base/i18n';
|
11
|
|
-import MultiSelectAutocomplete
|
12
|
|
- from '../../base/react/components/web/MultiSelectAutocomplete';
|
|
13
|
+import { MultiSelectAutocomplete } from '../../base/react';
|
13
|
14
|
|
14
|
15
|
import { invitePeople, inviteRooms, searchPeople } from '../functions';
|
15
|
16
|
|
|
@@ -67,6 +68,54 @@ class AddPeopleDialog extends Component {
|
67
|
68
|
t: PropTypes.func
|
68
|
69
|
};
|
69
|
70
|
|
|
71
|
+ _multiselect = null;
|
|
72
|
+
|
|
73
|
+ _resourceClient = {
|
|
74
|
+ makeQuery: text => {
|
|
75
|
+ const {
|
|
76
|
+ _jwt,
|
|
77
|
+ _peopleSearchQueryTypes,
|
|
78
|
+ _peopleSearchUrl
|
|
79
|
+ } = this.props; // eslint-disable-line no-invalid-this
|
|
80
|
+
|
|
81
|
+ return (
|
|
82
|
+ searchPeople(
|
|
83
|
+ _peopleSearchUrl,
|
|
84
|
+ _jwt,
|
|
85
|
+ text,
|
|
86
|
+ _peopleSearchQueryTypes));
|
|
87
|
+ },
|
|
88
|
+
|
|
89
|
+ parseResults: response => response.map(user => {
|
|
90
|
+ return {
|
|
91
|
+ content: user.name,
|
|
92
|
+ elemBefore: <Avatar
|
|
93
|
+ size = 'medium'
|
|
94
|
+ src = { user.avatar } />,
|
|
95
|
+ item: user,
|
|
96
|
+ value: user.id
|
|
97
|
+ };
|
|
98
|
+ })
|
|
99
|
+ };
|
|
100
|
+
|
|
101
|
+ state = {
|
|
102
|
+ /**
|
|
103
|
+ * Indicating that an error occurred when adding people to the call.
|
|
104
|
+ */
|
|
105
|
+ addToCallError: false,
|
|
106
|
+
|
|
107
|
+ /**
|
|
108
|
+ * Indicating that we're currently adding the new people to the
|
|
109
|
+ * call.
|
|
110
|
+ */
|
|
111
|
+ addToCallInProgress: false,
|
|
112
|
+
|
|
113
|
+ /**
|
|
114
|
+ * The list of invite items.
|
|
115
|
+ */
|
|
116
|
+ inviteItems: new Immutable.List()
|
|
117
|
+ };
|
|
118
|
+
|
70
|
119
|
/**
|
71
|
120
|
* Initializes a new {@code AddPeopleDialog} instance.
|
72
|
121
|
*
|
|
@@ -76,56 +125,7 @@ class AddPeopleDialog extends Component {
|
76
|
125
|
constructor(props) {
|
77
|
126
|
super(props);
|
78
|
127
|
|
79
|
|
- this.state = {
|
80
|
|
- /**
|
81
|
|
- * Indicating that an error occurred when adding people to the call.
|
82
|
|
- */
|
83
|
|
- addToCallError: false,
|
84
|
|
-
|
85
|
|
- /**
|
86
|
|
- * Indicating that we're currently adding the new people to the
|
87
|
|
- * call.
|
88
|
|
- */
|
89
|
|
- addToCallInProgress: false,
|
90
|
|
-
|
91
|
|
- /**
|
92
|
|
- * The list of invite items.
|
93
|
|
- */
|
94
|
|
- inviteItems: new Immutable.List()
|
95
|
|
- };
|
96
|
|
-
|
97
|
|
- this._multiselect = null;
|
98
|
|
- this._resourceClient = {
|
99
|
|
- makeQuery: text => {
|
100
|
|
- const {
|
101
|
|
- _jwt,
|
102
|
|
- _peopleSearchQueryTypes,
|
103
|
|
- _peopleSearchUrl
|
104
|
|
- } = this.props;
|
105
|
|
-
|
106
|
|
- return searchPeople(
|
107
|
|
- _peopleSearchUrl,
|
108
|
|
- _jwt,
|
109
|
|
- text,
|
110
|
|
- _peopleSearchQueryTypes
|
111
|
|
- );
|
112
|
|
- },
|
113
|
|
- parseResults: response => response.map(user => {
|
114
|
|
- const avatar = ( // eslint-disable-line no-extra-parens
|
115
|
|
- <Avatar
|
116
|
|
- size = 'medium'
|
117
|
|
- src = { user.avatar } />
|
118
|
|
- );
|
119
|
|
-
|
120
|
|
- return {
|
121
|
|
- content: user.name,
|
122
|
|
- value: user.id,
|
123
|
|
- elemBefore: avatar,
|
124
|
|
- item: user
|
125
|
|
- };
|
126
|
|
- })
|
127
|
|
- };
|
128
|
|
-
|
|
128
|
+ // Bind event handlers so they are only bound once per instance.
|
129
|
129
|
this._isAddDisabled = this._isAddDisabled.bind(this);
|
130
|
130
|
this._onSelectionChange = this._onSelectionChange.bind(this);
|
131
|
131
|
this._onSubmit = this._onSubmit.bind(this);
|
|
@@ -144,9 +144,9 @@ class AddPeopleDialog extends Component {
|
144
|
144
|
* invite.
|
145
|
145
|
*/
|
146
|
146
|
if (prevState.addToCallError
|
147
|
|
- && !this.state.addToCallInProgress
|
148
|
|
- && !this.state.addToCallError
|
149
|
|
- && this._multiselect) {
|
|
147
|
+ && !this.state.addToCallInProgress
|
|
148
|
+ && !this.state.addToCallError
|
|
149
|
+ && this._multiselect) {
|
150
|
150
|
this._multiselect.clear();
|
151
|
151
|
}
|
152
|
152
|
}
|
|
@@ -169,44 +169,22 @@ class AddPeopleDialog extends Component {
|
169
|
169
|
);
|
170
|
170
|
}
|
171
|
171
|
|
172
|
|
- /**
|
173
|
|
- * Renders the input form.
|
174
|
|
- *
|
175
|
|
- * @returns {ReactElement}
|
176
|
|
- * @private
|
177
|
|
- */
|
178
|
|
- _renderUserInputForm() {
|
179
|
|
- const { t } = this.props;
|
180
|
|
-
|
181
|
|
- return (
|
182
|
|
- <div className = 'add-people-form-wrap'>
|
183
|
|
- { this._renderErrorMessage() }
|
184
|
|
- <MultiSelectAutocomplete
|
185
|
|
- isDisabled
|
186
|
|
- = { this.state.addToCallInProgress || false }
|
187
|
|
- noMatchesFound = { t('addPeople.noResults') }
|
188
|
|
- onSelectionChange = { this._onSelectionChange }
|
189
|
|
- placeholder = { t('addPeople.searchPlaceholder') }
|
190
|
|
- ref = { this._setMultiSelectElement }
|
191
|
|
- resourceClient = { this._resourceClient }
|
192
|
|
- shouldFitContainer = { true }
|
193
|
|
- shouldFocus = { true } />
|
194
|
|
- </div>
|
195
|
|
- );
|
196
|
|
- }
|
|
172
|
+ _isAddDisabled: () => boolean;
|
197
|
173
|
|
198
|
174
|
/**
|
199
|
175
|
* Indicates if the Add button should be disabled.
|
200
|
176
|
*
|
|
177
|
+ * @private
|
201
|
178
|
* @returns {boolean} - True to indicate that the Add button should
|
202
|
179
|
* be disabled, false otherwise.
|
203
|
|
- * @private
|
204
|
180
|
*/
|
205
|
181
|
_isAddDisabled() {
|
206
|
182
|
return !this.state.inviteItems.length
|
207
|
183
|
|| this.state.addToCallInProgress;
|
208
|
184
|
}
|
209
|
185
|
|
|
186
|
+ _onSelectionChange: (Map<*, *>) => void;
|
|
187
|
+
|
210
|
188
|
/**
|
211
|
189
|
* Handles a selection change.
|
212
|
190
|
*
|
|
@@ -222,6 +200,8 @@ class AddPeopleDialog extends Component {
|
222
|
200
|
});
|
223
|
201
|
}
|
224
|
202
|
|
|
203
|
+ _onSubmit: () => void;
|
|
204
|
+
|
225
|
205
|
/**
|
226
|
206
|
* Handles the submit button action.
|
227
|
207
|
*
|
|
@@ -245,27 +225,28 @@ class AddPeopleDialog extends Component {
|
245
|
225
|
this.props._inviteUrl,
|
246
|
226
|
this.props._jwt,
|
247
|
227
|
this.state.inviteItems.filter(i => i.type === 'user'))
|
248
|
|
- .then(() => {
|
249
|
|
- this.setState({
|
250
|
|
- addToCallInProgress: false
|
|
228
|
+ .then(
|
|
229
|
+ /* onFulfilled */ () => {
|
|
230
|
+ this.setState({
|
|
231
|
+ addToCallInProgress: false
|
|
232
|
+ });
|
|
233
|
+
|
|
234
|
+ this.props.hideDialog();
|
|
235
|
+ },
|
|
236
|
+ /* onRejected */ () => {
|
|
237
|
+ this.setState({
|
|
238
|
+ addToCallInProgress: false,
|
|
239
|
+ addToCallError: true
|
|
240
|
+ });
|
251
|
241
|
});
|
252
|
|
-
|
253
|
|
- this.props.hideDialog();
|
254
|
|
- })
|
255
|
|
- .catch(() => {
|
256
|
|
- this.setState({
|
257
|
|
- addToCallInProgress: false,
|
258
|
|
- addToCallError: true
|
259
|
|
- });
|
260
|
|
- });
|
261
|
242
|
}
|
262
|
243
|
}
|
263
|
244
|
|
264
|
245
|
/**
|
265
|
246
|
* Renders the error message if the add doesn't succeed.
|
266
|
247
|
*
|
267
|
|
- * @returns {ReactElement|null}
|
268
|
248
|
* @private
|
|
249
|
+ * @returns {ReactElement|null}
|
269
|
250
|
*/
|
270
|
251
|
_renderErrorMessage() {
|
271
|
252
|
if (!this.state.addToCallError) {
|
|
@@ -304,6 +285,34 @@ class AddPeopleDialog extends Component {
|
304
|
285
|
);
|
305
|
286
|
}
|
306
|
287
|
|
|
288
|
+ /**
|
|
289
|
+ * Renders the input form.
|
|
290
|
+ *
|
|
291
|
+ * @private
|
|
292
|
+ * @returns {ReactElement}
|
|
293
|
+ */
|
|
294
|
+ _renderUserInputForm() {
|
|
295
|
+ const { t } = this.props;
|
|
296
|
+
|
|
297
|
+ return (
|
|
298
|
+ <div className = 'add-people-form-wrap'>
|
|
299
|
+ { this._renderErrorMessage() }
|
|
300
|
+ <MultiSelectAutocomplete
|
|
301
|
+ isDisabled
|
|
302
|
+ = { this.state.addToCallInProgress || false }
|
|
303
|
+ noMatchesFound = { t('addPeople.noResults') }
|
|
304
|
+ onSelectionChange = { this._onSelectionChange }
|
|
305
|
+ placeholder = { t('addPeople.searchPlaceholder') }
|
|
306
|
+ ref = { this._setMultiSelectElement }
|
|
307
|
+ resourceClient = { this._resourceClient }
|
|
308
|
+ shouldFitContainer = { true }
|
|
309
|
+ shouldFocus = { true } />
|
|
310
|
+ </div>
|
|
311
|
+ );
|
|
312
|
+ }
|
|
313
|
+
|
|
314
|
+ _setMultiSelectElement: (Object) => void;
|
|
315
|
+
|
307
|
316
|
/**
|
308
|
317
|
* Sets the instance variable for the multi select component
|
309
|
318
|
* element so it can be accessed directly.
|
|
@@ -338,13 +347,13 @@ function _mapStateToProps(state) {
|
338
|
347
|
|
339
|
348
|
return {
|
340
|
349
|
_conference: conference,
|
341
|
|
- _jwt: state['features/jwt'].jwt,
|
342
|
|
- _inviteUrl: getInviteURL(state),
|
343
|
350
|
_inviteServiceUrl: inviteServiceUrl,
|
|
351
|
+ _inviteUrl: getInviteURL(state),
|
|
352
|
+ _jwt: state['features/jwt'].jwt,
|
344
|
353
|
_peopleSearchQueryTypes: peopleSearchQueryTypes,
|
345
|
354
|
_peopleSearchUrl: peopleSearchUrl
|
346
|
355
|
};
|
347
|
356
|
}
|
348
|
357
|
|
349
|
|
-export default translate(
|
350
|
|
- connect(_mapStateToProps, { hideDialog })(AddPeopleDialog));
|
|
358
|
+export default translate(connect(_mapStateToProps, { hideDialog })(
|
|
359
|
+ AddPeopleDialog));
|