diff --git a/react/features/base/react/components/web/MultiSelectAutocomplete.js b/react/features/base/react/components/web/MultiSelectAutocomplete.js index 1312d38f6..1641fff35 100644 --- a/react/features/base/react/components/web/MultiSelectAutocomplete.js +++ b/react/features/base/react/components/web/MultiSelectAutocomplete.js @@ -6,6 +6,8 @@ import React, { Component } from 'react'; import InlineDialogFailure from './InlineDialogFailure'; +const logger = require('jitsi-meet-logger').getLogger(__filename); + /** * A MultiSelect that is also auto-completing. */ @@ -290,7 +292,9 @@ class MultiSelectAutocomplete extends Component { error: false }); }) - .catch(() => { + .catch(error => { + logger.error('MultiSelectAutocomplete error in query', error); + this.setState({ error: true, loading: false, diff --git a/react/features/base/util/httpUtils.js b/react/features/base/util/httpUtils.js new file mode 100644 index 000000000..91c10616e --- /dev/null +++ b/react/features/base/util/httpUtils.js @@ -0,0 +1,28 @@ +const logger = require('jitsi-meet-logger').getLogger(__filename); + +/** + * Wrapper around fetch GET requests to handle json-ifying the response + * and logging errors. + * + * @param {string} url - The URL to perform a GET against. + * @returns {Promise} The response body, in JSON format, will be + * through the Promise. + */ +export function doGetJSON(url) { + return fetch(url) + .then(response => { + const jsonify = response.json(); + + if (response.ok) { + return jsonify; + } + + return jsonify + .then(result => Promise.reject(result)); + }) + .catch(error => { + logger.error('Error performing get:', url, error); + + return Promise.reject(error); + }); +} diff --git a/react/features/base/util/index.js b/react/features/base/util/index.js index 1a4ad8b91..0e99d5372 100644 --- a/react/features/base/util/index.js +++ b/react/features/base/util/index.js @@ -1,4 +1,5 @@ export * from './helpers'; +export * from './httpUtils'; export * from './loadScript'; export * from './randomUtil'; export * from './uri'; diff --git a/react/features/invite/actions.js b/react/features/invite/actions.js index 71bd3bcca..2dde00b2f 100644 --- a/react/features/invite/actions.js +++ b/react/features/invite/actions.js @@ -5,8 +5,7 @@ import { UPDATE_DIAL_IN_NUMBERS_FAILED, UPDATE_DIAL_IN_NUMBERS_SUCCESS } from './actionTypes'; - -declare var $: Function; +import { getDialInConferenceID, getDialInNumbers } from './functions'; /** * Opens the inline conference info dialog. @@ -48,12 +47,10 @@ export function updateDialInNumbers() { } const { room } = state['features/base/conference']; - const conferenceIDURL - = `${dialInConfCodeUrl}?conference=${room}@${mucURL}`; Promise.all([ - $.getJSON(dialInNumbersUrl), - $.getJSON(conferenceIDURL) + getDialInNumbers(dialInNumbersUrl), + getDialInConferenceID(dialInConfCodeUrl, room, mucURL) ]) .then(([ dialInNumbers, { conference, id, message } ]) => { if (!conference || !id) { diff --git a/react/features/invite/components/AddPeopleDialog.web.js b/react/features/invite/components/AddPeopleDialog.web.js index 29a86dcdb..eb5304223 100644 --- a/react/features/invite/components/AddPeopleDialog.web.js +++ b/react/features/invite/components/AddPeopleDialog.web.js @@ -568,7 +568,7 @@ class AddPeopleDialog extends Component<*, *> { let peopleSearchPromise; - if (this.props.enableAddPeople) { + if (this.props.enableAddPeople && text) { peopleSearchPromise = searchDirectory( _peopleSearchUrl, _jwt, diff --git a/react/features/invite/functions.js b/react/features/invite/functions.js index cb216399d..6dbe95203 100644 --- a/react/features/invite/functions.js +++ b/react/features/invite/functions.js @@ -1,8 +1,44 @@ // @flow +import { doGetJSON } from '../base/util'; + declare var $: Function; declare var interfaceConfig: Object; +const logger = require('jitsi-meet-logger').getLogger(__filename); + +/** + * Sends a GET request to obtain the conference ID necessary for identifying + * which conference to join after diaing the dial-in service. + * + * @param {string} baseUrl - The url for obtaining the conference ID (pin) for + * dialing into a conference. + * @param {string} roomName - The conference name to find the associated + * conference ID. + * @param {string} mucURL - In which MUC the conference exists. + * @returns {Promise} - The promise created by the request. + */ +export function getDialInConferenceID( + baseUrl: string, + roomName: string, + mucURL: string): Promise { + const conferenceIDURL = `${baseUrl}?conference=${roomName}@${mucURL}`; + + return doGetJSON(conferenceIDURL); +} + +/** + * Sends a GET request for phone numbers used to dial into a conference. + * + * @param {string} url - The service that returns confernce dial-in numbers. + * @returns {Promise} - The promise created by the request. The returned numbers + * may be an array of numbers or an object with countries as keys and arrays of + * phone number strings. + */ +export function getDialInNumbers(url: string): Promise<*> { + return doGetJSON(url); +} + /** * Get the position of the invite option in the interfaceConfig.INVITE_OPTIONS * list. @@ -78,13 +114,24 @@ export function searchDirectory( // eslint-disable-line max-params ): Promise> { const queryTypesString = JSON.stringify(queryTypes); - return new Promise((resolve, reject) => { - $.getJSON( - `${serviceUrl}?query=${encodeURIComponent(text)}&queryTypes=${ - queryTypesString}&jwt=${jwt}`, - resolve) - .catch((jqxhr, textStatus, error) => reject(error)); - }); + return fetch(`${serviceUrl}?query=${encodeURIComponent(text)}&queryTypes=${ + queryTypesString}&jwt=${jwt}`) + .then(response => { + const jsonify = response.json(); + + if (response.ok) { + return jsonify; + } + + return jsonify + .then(result => Promise.reject(result)); + }) + .catch(error => { + logger.error( + 'Error searching directory:', error); + + return Promise.reject(error); + }); } /** diff --git a/webpack.config.js b/webpack.config.js index 301c590e3..dfc12a74f 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -139,8 +139,9 @@ module.exports = [ entry: { 'app.bundle': [ - // XXX Required by at least IE11 at the time of this writing. + // babel-polyfill and fetch polyfill are required for IE11. 'babel-polyfill', + 'whatwg-fetch', './app.js' ],