You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

DialInSummary.js 6.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. // @flow
  2. import React, { Component } from 'react';
  3. import { translate } from '../../../../base/i18n';
  4. import { doGetJSON } from '../../../../base/util';
  5. import ConferenceID from './ConferenceID';
  6. import NumbersList from './NumbersList';
  7. declare var config: Object;
  8. /**
  9. * The type of the React {@code Component} props of {@link DialInSummary}.
  10. */
  11. type Props = {
  12. /**
  13. * Additional CSS classnames to append to the root of the component.
  14. */
  15. className: string,
  16. /**
  17. * Whether or not numbers should include links with the telephone protocol.
  18. */
  19. clickableNumbers: boolean,
  20. /**
  21. * The name of the conference to show a conferenceID for.
  22. */
  23. room: string,
  24. /**
  25. * Invoked to obtain translated strings.
  26. */
  27. t: Function
  28. };
  29. /**
  30. * The type of the React {@code Component} state of {@link DialInSummary}.
  31. */
  32. type State = {
  33. /**
  34. * The numeric ID of the conference, used as a pin when dialing in.
  35. */
  36. conferenceID: ?string,
  37. /**
  38. * An error message to display.
  39. */
  40. error: string,
  41. /**
  42. * Whether or not the app is fetching data.
  43. */
  44. loading: boolean,
  45. /**
  46. * The dial-in numbers to be displayed.
  47. */
  48. numbers: ?Array<Object> | ?Object,
  49. /**
  50. * Whether or not dial-in is allowed.
  51. */
  52. numbersEnabled: ?boolean
  53. }
  54. /**
  55. * Displays a page listing numbers for dialing into a conference and pin to
  56. * the a specific conference.
  57. *
  58. * @extends Component
  59. */
  60. class DialInSummary extends Component<Props, State> {
  61. state = {
  62. conferenceID: null,
  63. error: '',
  64. loading: true,
  65. numbers: null,
  66. numbersEnabled: null
  67. };
  68. /**
  69. * Initializes a new {@code DialInSummary} instance.
  70. *
  71. * @param {Object} props - The read-only properties with which the new
  72. * instance is to be initialized.
  73. */
  74. constructor(props: Props) {
  75. super(props);
  76. // Bind event handlers so they are only bound once for every instance.
  77. this._onGetNumbersSuccess = this._onGetNumbersSuccess.bind(this);
  78. this._onGetConferenceIDSuccess
  79. = this._onGetConferenceIDSuccess.bind(this);
  80. this._setErrorMessage = this._setErrorMessage.bind(this);
  81. }
  82. /**
  83. * Implements {@link Component#componentDidMount()}. Invoked immediately
  84. * after this component is mounted.
  85. *
  86. * @inheritdoc
  87. * @returns {void}
  88. */
  89. componentDidMount() {
  90. const getNumbers = this._getNumbers()
  91. .then(this._onGetNumbersSuccess)
  92. .catch(this._setErrorMessage);
  93. const getID = this._getConferenceID()
  94. .then(this._onGetConferenceIDSuccess)
  95. .catch(this._setErrorMessage);
  96. Promise.all([ getNumbers, getID ])
  97. .then(() => {
  98. this.setState({ loading: false });
  99. });
  100. }
  101. /**
  102. * Implements React's {@link Component#render()}.
  103. *
  104. * @inheritdoc
  105. * @returns {ReactElement}
  106. */
  107. render() {
  108. let className = '';
  109. let contents;
  110. const { conferenceID, error, loading, numbersEnabled } = this.state;
  111. if (loading) {
  112. contents = '';
  113. } else if (numbersEnabled === false) {
  114. contents = this.props.t('info.dialInNotSupported');
  115. } else if (error) {
  116. contents = error;
  117. } else {
  118. className = 'has-numbers';
  119. contents = [
  120. conferenceID
  121. ? <ConferenceID
  122. conferenceID = { conferenceID }
  123. conferenceName = { this.props.room }
  124. key = 'conferenceID' />
  125. : null,
  126. <NumbersList
  127. clickableNumbers = { this.props.clickableNumbers }
  128. conferenceID = { conferenceID }
  129. key = 'numbers'
  130. numbers = { this.state.numbers } />
  131. ];
  132. }
  133. return (
  134. <div className = { `${this.props.className} ${className}` }>
  135. { contents }
  136. </div>
  137. );
  138. }
  139. /**
  140. * Creates an AJAX request for the conference ID.
  141. *
  142. * @private
  143. * @returns {Promise}
  144. */
  145. _getConferenceID() {
  146. const { room } = this.props;
  147. const { dialInConfCodeUrl, hosts } = config;
  148. const mucURL = hosts && hosts.muc;
  149. if (!dialInConfCodeUrl || !mucURL || !room) {
  150. return Promise.resolve();
  151. }
  152. return doGetJSON(`${dialInConfCodeUrl}?conference=${room}@${mucURL}`, true)
  153. .catch(() => Promise.reject(this.props.t('info.genericError')));
  154. }
  155. /**
  156. * Creates an AJAX request for dial-in numbers.
  157. *
  158. * @private
  159. * @returns {Promise}
  160. */
  161. _getNumbers() {
  162. const { room } = this.props;
  163. const { dialInNumbersUrl, hosts } = config;
  164. const mucURL = hosts && hosts.muc;
  165. let URLSuffix = '';
  166. if (!dialInNumbersUrl) {
  167. return Promise.reject(this.props.t('info.dialInNotSupported'));
  168. }
  169. // when room and mucURL are available
  170. // provide conference when looking up dial in numbers
  171. if (room && mucURL) {
  172. URLSuffix = `?conference=${room}@${mucURL}`;
  173. }
  174. return doGetJSON(`${dialInNumbersUrl}${URLSuffix}`, true)
  175. .catch(() => Promise.reject(this.props.t('info.genericError')));
  176. }
  177. _onGetConferenceIDSuccess: (Object) => void;
  178. /**
  179. * Callback invoked when fetching the conference ID succeeds.
  180. *
  181. * @param {Object} response - The response from fetching the conference ID.
  182. * @private
  183. * @returns {void}
  184. */
  185. _onGetConferenceIDSuccess(response = {}) {
  186. const { conference, id } = response;
  187. if (!conference || !id) {
  188. return;
  189. }
  190. this.setState({ conferenceID: id });
  191. }
  192. _onGetNumbersSuccess: (Object) => void;
  193. /**
  194. * Callback invoked when fetching dial-in numbers succeeds. Sets the
  195. * internal to show the numbers.
  196. *
  197. * @param {Array|Object} response - The response from fetching
  198. * dial-in numbers.
  199. * @param {Array|Object} response.numbers - The dial-in numbers.
  200. * @param {boolean} response.numbersEnabled - Whether or not dial-in is
  201. * enabled, old syntax that is deprecated.
  202. * @private
  203. * @returns {void}
  204. */
  205. _onGetNumbersSuccess(
  206. response: Array<Object> | { numbersEnabled?: boolean }) {
  207. this.setState({
  208. numbersEnabled:
  209. Array.isArray(response)
  210. ? response.length > 0 : response.numbersEnabled,
  211. numbers: response
  212. });
  213. }
  214. _setErrorMessage: (string) => void;
  215. /**
  216. * Sets an error message to display on the page instead of content.
  217. *
  218. * @param {string} error - The error message to display.
  219. * @private
  220. * @returns {void}
  221. */
  222. _setErrorMessage(error) {
  223. this.setState({
  224. error
  225. });
  226. }
  227. }
  228. export default translate(DialInSummary);