2019-05-07 14:50:57 +00:00
|
|
|
// @flow
|
2018-10-30 05:02:23 +00:00
|
|
|
|
2018-02-13 19:46:47 +00:00
|
|
|
import React, { Component } from 'react';
|
|
|
|
|
2019-05-07 14:50:57 +00:00
|
|
|
import { translate } from '../../../../base/i18n';
|
2021-06-17 12:16:58 +00:00
|
|
|
import { Icon, IconSip } from '../../../../base/icons';
|
2018-02-13 19:46:47 +00:00
|
|
|
|
2018-10-30 05:02:23 +00:00
|
|
|
type Props = {
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Whether or not numbers should include links with the telephone protocol.
|
|
|
|
*/
|
|
|
|
clickableNumbers: boolean,
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The conference ID for dialing in.
|
|
|
|
*/
|
|
|
|
conferenceID: number,
|
|
|
|
|
|
|
|
/**
|
2019-02-26 13:32:46 +00:00
|
|
|
* The phone numbers to display. Can be an array of number Objects or an
|
|
|
|
* object with countries as keys and an array of numbers as values.
|
2018-10-30 05:02:23 +00:00
|
|
|
*/
|
2019-02-26 13:32:46 +00:00
|
|
|
numbers: { [string]: Array<string> } | Array<Object>,
|
2018-10-30 05:02:23 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Invoked to obtain translated strings.
|
|
|
|
*/
|
|
|
|
t: Function
|
|
|
|
}
|
|
|
|
|
2018-02-13 19:46:47 +00:00
|
|
|
/**
|
|
|
|
* Displays a table with phone numbers to dial in to a conference.
|
|
|
|
*
|
2021-11-04 21:10:43 +00:00
|
|
|
* @augments Component
|
2018-02-13 19:46:47 +00:00
|
|
|
*/
|
2018-10-30 05:02:23 +00:00
|
|
|
class NumbersList extends Component<Props> {
|
2018-02-13 19:46:47 +00:00
|
|
|
/**
|
|
|
|
* Implements React's {@link Component#render()}.
|
|
|
|
*
|
|
|
|
* @inheritdoc
|
|
|
|
* @returns {ReactElement}
|
|
|
|
*/
|
|
|
|
render() {
|
2019-02-26 13:32:46 +00:00
|
|
|
const { numbers } = this.props;
|
|
|
|
|
|
|
|
return this._renderWithCountries(numbers);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Renders rows of countries and associated phone numbers.
|
|
|
|
*
|
|
|
|
* @param {Object|Array<Object>} numbersMapping - An object with country
|
|
|
|
* names as keys and values as arrays of phone numbers.
|
|
|
|
* @private
|
|
|
|
* @returns {ReactElement[]}
|
|
|
|
*/
|
|
|
|
_renderWithCountries(
|
|
|
|
numbersMapping: { numbers: Array<string> } | Array<Object>) {
|
|
|
|
const { t } = this.props;
|
|
|
|
let hasFlags = false, numbers;
|
|
|
|
|
|
|
|
if (Array.isArray(numbersMapping)) {
|
|
|
|
hasFlags = true;
|
|
|
|
numbers = numbersMapping.reduce(
|
|
|
|
(resultNumbers, number) => {
|
2020-04-06 08:57:58 +00:00
|
|
|
// The i18n-iso-countries package insists on upper case.
|
|
|
|
const countryCode = number.countryCode.toUpperCase();
|
2021-10-01 13:38:00 +00:00
|
|
|
|
|
|
|
let countryName;
|
|
|
|
|
|
|
|
if (countryCode === 'SIP') {
|
|
|
|
countryName = t('info.sip');
|
|
|
|
} else {
|
|
|
|
countryName = t(`countries:countries.${countryCode}`);
|
|
|
|
|
|
|
|
// Some countries have multiple names as US ['United States of America', 'USA']
|
|
|
|
// choose the first one if that is the case
|
|
|
|
if (!countryName) {
|
|
|
|
countryName = t(`countries:countries.${countryCode}.0`);
|
|
|
|
}
|
|
|
|
}
|
2019-02-26 13:32:46 +00:00
|
|
|
|
|
|
|
if (resultNumbers[countryName]) {
|
|
|
|
resultNumbers[countryName].push(number);
|
|
|
|
} else {
|
|
|
|
resultNumbers[countryName] = [ number ];
|
|
|
|
}
|
|
|
|
|
|
|
|
return resultNumbers;
|
|
|
|
}, {});
|
|
|
|
} else {
|
|
|
|
numbers = {};
|
|
|
|
|
|
|
|
for (const [ country, numbersArray ]
|
|
|
|
of Object.entries(numbersMapping.numbers)) {
|
|
|
|
|
|
|
|
if (Array.isArray(numbersArray)) {
|
|
|
|
/* eslint-disable arrow-body-style */
|
|
|
|
const formattedNumbers = numbersArray.map(number => ({
|
|
|
|
formattedNumber: number
|
|
|
|
}));
|
|
|
|
/* eslint-enable arrow-body-style */
|
|
|
|
|
|
|
|
numbers[country] = formattedNumbers;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const rows = [];
|
|
|
|
|
|
|
|
Object.keys(numbers).forEach((countryName: string) => {
|
|
|
|
const numbersArray = numbers[countryName];
|
|
|
|
|
|
|
|
rows.push(
|
|
|
|
<tr
|
|
|
|
className = 'number-group'
|
|
|
|
key = { countryName }>
|
|
|
|
{ this._renderFlag(numbersArray[0].countryCode) }
|
|
|
|
<td className = 'country' >{ countryName }</td>
|
|
|
|
<td className = 'numbers-list-column'>
|
|
|
|
{ this._renderNumbersList(numbersArray) }
|
|
|
|
</td>
|
|
|
|
<td className = 'toll-free-list-column' >
|
|
|
|
{ this._renderNumbersTollFreeList(numbersArray) }
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
);
|
|
|
|
});
|
2018-02-13 19:46:47 +00:00
|
|
|
|
|
|
|
return (
|
|
|
|
<table className = 'dial-in-numbers-list'>
|
|
|
|
<thead>
|
|
|
|
<tr>
|
2019-02-26 13:32:46 +00:00
|
|
|
{ hasFlags ? <th /> : null}
|
|
|
|
<th>{ t('info.country') }</th>
|
2018-02-13 19:46:47 +00:00
|
|
|
<th>{ t('info.numbers') }</th>
|
2019-02-26 13:32:46 +00:00
|
|
|
<th />
|
2018-02-13 19:46:47 +00:00
|
|
|
</tr>
|
|
|
|
</thead>
|
2018-02-21 01:25:22 +00:00
|
|
|
<tbody className = 'dial-in-numbers-body'>
|
2019-02-26 13:32:46 +00:00
|
|
|
{ rows }
|
2018-02-13 19:46:47 +00:00
|
|
|
</tbody>
|
2019-02-26 13:32:46 +00:00
|
|
|
</table>
|
|
|
|
);
|
2018-02-13 19:46:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2019-02-27 15:52:19 +00:00
|
|
|
* Renders a div container for a flag for the country of the phone number.
|
2018-02-13 19:46:47 +00:00
|
|
|
*
|
2019-02-27 15:52:19 +00:00
|
|
|
* @param {string} countryCode - The country code flag to display.
|
2018-02-13 19:46:47 +00:00
|
|
|
* @private
|
2019-02-26 13:32:46 +00:00
|
|
|
* @returns {ReactElement}
|
2018-02-13 19:46:47 +00:00
|
|
|
*/
|
2019-02-26 13:32:46 +00:00
|
|
|
_renderFlag(countryCode) {
|
|
|
|
if (countryCode) {
|
2019-02-27 15:52:19 +00:00
|
|
|
return (
|
|
|
|
<td className = 'flag-cell'>
|
2021-06-17 12:16:58 +00:00
|
|
|
{countryCode === 'SIP'
|
|
|
|
? <Icon src = { IconSip } />
|
|
|
|
: <i className = { `flag iti-flag ${countryCode}` } />
|
|
|
|
}
|
2019-02-27 15:52:19 +00:00
|
|
|
</td>);
|
2018-02-13 19:46:47 +00:00
|
|
|
}
|
|
|
|
|
2019-02-26 13:32:46 +00:00
|
|
|
return null;
|
2018-02-13 19:46:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2019-02-26 13:32:46 +00:00
|
|
|
* Renders a div container for a phone number.
|
2018-02-13 19:46:47 +00:00
|
|
|
*
|
2019-02-26 13:32:46 +00:00
|
|
|
* @param {Array} numbers - The phone number to display.
|
2018-02-13 19:46:47 +00:00
|
|
|
* @private
|
|
|
|
* @returns {ReactElement[]}
|
|
|
|
*/
|
2019-02-26 13:32:46 +00:00
|
|
|
_renderNumbersList(numbers) {
|
|
|
|
const numbersListItems = numbers.map(number =>
|
|
|
|
(<li
|
|
|
|
className = 'dial-in-number'
|
|
|
|
key = { number.formattedNumber }>
|
|
|
|
{ this._renderNumberLink(number.formattedNumber) }
|
|
|
|
</li>));
|
|
|
|
|
2018-02-13 19:46:47 +00:00
|
|
|
return (
|
2019-02-26 13:32:46 +00:00
|
|
|
<ul className = 'numbers-list'>
|
|
|
|
{ numbersListItems }
|
|
|
|
</ul>
|
2018-02-13 19:46:47 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2019-02-26 13:32:46 +00:00
|
|
|
* Renders list with a toll free text on the position where there is a
|
|
|
|
* number marked as toll free.
|
2018-02-13 19:46:47 +00:00
|
|
|
*
|
2019-02-26 13:32:46 +00:00
|
|
|
* @param {Array} numbers - The phone number that are displayed.
|
2018-02-13 19:46:47 +00:00
|
|
|
* @private
|
|
|
|
* @returns {ReactElement[]}
|
|
|
|
*/
|
2019-02-26 13:32:46 +00:00
|
|
|
_renderNumbersTollFreeList(numbers) {
|
|
|
|
const { t } = this.props;
|
|
|
|
|
|
|
|
const tollNumbersListItems = numbers.map(number =>
|
|
|
|
(<li
|
|
|
|
className = 'toll-free'
|
|
|
|
key = { number.formattedNumber }>
|
|
|
|
{ number.tollFree ? t('info.dialInTollFree') : '' }
|
|
|
|
</li>));
|
|
|
|
|
2018-02-13 19:46:47 +00:00
|
|
|
return (
|
2019-02-26 13:32:46 +00:00
|
|
|
<ul className = 'toll-free-list'>
|
|
|
|
{ tollNumbersListItems }
|
|
|
|
</ul>
|
2018-02-13 19:46:47 +00:00
|
|
|
);
|
|
|
|
}
|
2018-02-21 01:25:22 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Renders a ReactElement for displaying a telephone number. If the
|
|
|
|
* component prop {@code clickableNumbers} is true, then the number will
|
|
|
|
* have a link with the telephone protocol.
|
|
|
|
*
|
|
|
|
* @param {string} number - The phone number to display.
|
|
|
|
* @private
|
|
|
|
* @returns {ReactElement}
|
|
|
|
*/
|
|
|
|
_renderNumberLink(number) {
|
|
|
|
if (this.props.clickableNumbers) {
|
2019-02-26 13:32:46 +00:00
|
|
|
// Url encode # to %23, Android phone was cutting the # after
|
|
|
|
// clicking it.
|
|
|
|
// Seems that using ',' and '%23' works on iOS and Android.
|
2018-02-21 01:25:22 +00:00
|
|
|
return (
|
|
|
|
<a
|
2019-02-26 13:32:46 +00:00
|
|
|
href = { `tel:${number},${this.props.conferenceID}%23` }
|
2018-02-21 01:25:22 +00:00
|
|
|
key = { number } >
|
|
|
|
{ number }
|
|
|
|
</a>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
return number;
|
|
|
|
}
|
|
|
|
|
2018-02-13 19:46:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
export default translate(NumbersList);
|