Files
jitsi-meet/react/features/invite/components/InviteButton.web.js
virtuacoplenny e47802538e ref(invite): remove InviteDialog (#2483)
* ref(invite): remove InviteDialog

InviteDialog functionality has been moved into InfoDialog.
The InviteButton has been temporarily hacked to show one
of its dropdown options instead as the button. Future
work will bring in a redesigned InviteModal that the button
will open.

* squash: filter invalid options and map valid options

* squash: update strings
2018-02-17 13:53:39 -06:00

229 lines
7.0 KiB
JavaScript

/* global interfaceConfig */
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { connect } from 'react-redux';
import Button from '@atlaskit/button';
import DropdownMenu from '@atlaskit/dropdown-menu';
import { translate } from '../../base/i18n';
import { getLocalParticipant, PARTICIPANT_ROLE } from '../../base/participants';
import { openDialog } from '../../base/dialog';
import { AddPeopleDialog } from '.';
import { DialOutDialog } from '../../dial-out';
import { isInviteOptionEnabled } from '../functions';
const DIAL_OUT_OPTION = 'dialout';
const ADD_TO_CALL_OPTION = 'addtocall';
/**
* The button that provides different invite options.
*/
class InviteButton extends Component {
/**
* {@code InviteButton}'s property types.
*
* @static
*/
static propTypes = {
/**
* Indicates if the "Add to call" feature is available.
*/
_isAddToCallAvailable: PropTypes.bool,
/**
* Indicates if the "Dial out" feature is available.
*/
_isDialOutAvailable: PropTypes.bool,
/**
* The function opening the dialog.
*/
openDialog: PropTypes.func,
/**
* Invoked to obtain translated strings.
*/
t: PropTypes.func
};
/**
* Initializes a new {@code InviteButton} instance.
*
* @param {Object} props - The read-only properties with which the new
* instance is to be initialized.
*/
constructor(props) {
super(props);
this._onInviteOptionSelected = this._onInviteOptionSelected.bind(this);
this._updateInviteItems = this._updateInviteItems.bind(this);
this._updateInviteItems(this.props);
}
/**
* Implements React's {@link Component#componentWillReceiveProps()}.
*
* @inheritdoc
* @param {Object} nextProps - The read-only props which this Component will
* receive.
* @returns {void}
*/
componentWillReceiveProps(nextProps) {
if (this.props._isDialOutAvailable !== nextProps._isDialOutAvailable
|| this.props._isAddToCallAvailable
!== nextProps._isAddToCallAvailable) {
this._updateInviteItems(nextProps);
}
}
/**
* Renders the content of this component.
*
* @returns {ReactElement}
*/
render() {
// HACK ALERT: Normally children should not be controlling their own
// visibility; parents should control that. However, this component is
// in a transitionary state while the Invite Dialog is being redone.
// This hack will go away when the Invite Dialog is back.
if (!this.state.buttonOption) {
return null;
}
const { VERTICAL_FILMSTRIP } = interfaceConfig;
return (
<div className = 'filmstrip__invite'>
<div className = 'invite-button-group'>
<Button
// eslint-disable-next-line react/jsx-handler-names
onClick = { this.state.buttonOption.action }
shouldFitContainer = { true }>
{ this.state.buttonOption.content }
</Button>
{ this.state.inviteOptions[0].items.length
? <DropdownMenu
items = { this.state.inviteOptions }
onItemActivated = { this._onInviteOptionSelected }
position = { VERTICAL_FILMSTRIP
? 'bottom right'
: 'top right' }
shouldFlip = { true }
triggerType = 'button' />
: null }
</div>
</div>
);
}
/**
* Handles selection of the invite options.
*
* @param { Object } option - The invite option that has been selected from
* the dropdown menu.
* @private
* @returns {void}
*/
_onInviteOptionSelected(option) {
this.state.inviteOptions[0].items.forEach(item => {
if (item.content === option.item.content) {
item.action();
}
});
}
/**
* Updates the invite items list depending on the availability of the
* features.
*
* @param {Object} props - The read-only properties of the component.
* @private
* @returns {void}
*/
_updateInviteItems(props) {
const { INVITE_OPTIONS = [] } = interfaceConfig;
const validOptions = INVITE_OPTIONS.filter(option =>
(option === DIAL_OUT_OPTION && props._isDialOutAvailable)
|| (option === ADD_TO_CALL_OPTION && props._isAddToCallAvailable));
/* eslint-disable array-callback-return */
const inviteItems = validOptions.map(option => {
switch (option) {
case DIAL_OUT_OPTION:
return {
content: this.props.t('dialOut.dialOut'),
action: () => this.props.openDialog(DialOutDialog)
};
case ADD_TO_CALL_OPTION:
return {
content: interfaceConfig.ADD_PEOPLE_APP_NAME,
action: () => this.props.openDialog(AddPeopleDialog)
};
}
});
/* eslint-enable array-callback-return */
const buttonOption = inviteItems[0];
const dropdownOptions = inviteItems.splice(1, inviteItems.length);
const nextState = {
/**
* The configuration for how the invite button should display and
* behave on click.
*/
buttonOption,
/**
* The list of invite options in the dropdown.
*/
inviteOptions: [
{
items: dropdownOptions
}
]
};
if (this.state) {
this.setState(nextState);
} else {
// eslint-disable-next-line react/no-direct-mutation-state
this.state = nextState;
}
}
}
/**
* Maps (parts of) the Redux state to the associated {@code InviteButton}'s
* props.
*
* @param {Object} state - The Redux state.
* @private
* @returns {{
* _isAddToCallAvailable: boolean,
* _isDialOutAvailable: boolean
* }}
*/
function _mapStateToProps(state) {
const { conference } = state['features/base/conference'];
const { enableUserRolesBasedOnToken } = state['features/base/config'];
const { isGuest } = state['features/base/jwt'];
return {
_isAddToCallAvailable:
!isGuest && isInviteOptionEnabled(ADD_TO_CALL_OPTION),
_isDialOutAvailable:
getLocalParticipant(state).role === PARTICIPANT_ROLE.MODERATOR
&& conference && conference.isSIPCallingSupported()
&& isInviteOptionEnabled(DIAL_OUT_OPTION)
&& (!enableUserRolesBasedOnToken || !isGuest)
};
}
export default translate(connect(_mapStateToProps, { openDialog })(
InviteButton));