|
| 1 | +import React from 'react'; |
| 2 | +import PropTypes from 'prop-types'; |
| 3 | +import {DestinationType} from '@webex/component-adapter-interfaces'; |
| 4 | +import Spinner from '../generic/Spinner/Spinner'; |
| 5 | +import Icon from '../generic/Icon/Icon'; |
| 6 | +import { |
| 7 | + useMembers, |
| 8 | + useMe, |
| 9 | + useOrganization, |
| 10 | + usePerson, |
| 11 | +} from '../hooks'; |
| 12 | +import WebexAvatar from '../WebexAvatar/WebexAvatar'; |
| 13 | +import webexComponentClasses from '../helpers'; |
| 14 | + |
| 15 | +/** |
| 16 | + * Displays a webex meeting participant. |
| 17 | + * |
| 18 | + * @param {object} props Data passed to the component |
| 19 | + * @param {string} props.className Custom CSS class to apply |
| 20 | + * @param {string} props.meetingID ID of the meeting for which to get members |
| 21 | + * @param {boolean} props.displayStatus Whether or not to display the user's status |
| 22 | + * @param {string} props.personID ID of the member for which to display avatar |
| 23 | + * @param {object} props.style Custom style to apply |
| 24 | + * @returns {object} JSX of the component |
| 25 | + * |
| 26 | + */ |
| 27 | +export default function WebexMeetingParticipant({ |
| 28 | + className, |
| 29 | + meetingID, |
| 30 | + displayStatus, |
| 31 | + personID, |
| 32 | + style, |
| 33 | +}) { |
| 34 | + const {displayName, orgID, emails} = usePerson(personID); |
| 35 | + const me = useMe(); |
| 36 | + const members = useMembers(meetingID, DestinationType.MEETING); |
| 37 | + const member = members |
| 38 | + .find((itemMember) => itemMember.ID === personID); |
| 39 | + const organization = useOrganization(orgID); |
| 40 | + |
| 41 | + const isMuted = member?.muted; |
| 42 | + const isSpeaking = member?.speaking; |
| 43 | + const isExternal = orgID !== undefined && me.orgID !== undefined && me.orgID !== orgID; |
| 44 | + const isSharing = member?.sharing; |
| 45 | + const isInMeeting = member?.inMeeting; |
| 46 | + const showMe = me.ID === personID; |
| 47 | + const isHost = member?.host; |
| 48 | + const isGuest = member?.guest; |
| 49 | + |
| 50 | + const roles = [ |
| 51 | + showMe && 'You', |
| 52 | + isHost && 'Host', |
| 53 | + isSharing && 'Presenter', |
| 54 | + ].filter((role) => role); |
| 55 | + const emailDomain = emails?.[0]?.split('@')[1] || <i>Unknown organization</i>; |
| 56 | + |
| 57 | + const [cssClasses, sc] = webexComponentClasses('meeting-participant', className); |
| 58 | + |
| 59 | + return ( |
| 60 | + <div className={cssClasses} style={style}> |
| 61 | + <WebexAvatar personID={personID} displayStatus={displayStatus} className={sc('avatar')} /> |
| 62 | + <div className={sc('details')}> |
| 63 | + <div className={sc('name')}> |
| 64 | + {(displayName ?? <Spinner size={18} />) || <i>Name not available</i>} |
| 65 | + {isGuest && <span className={sc('guest')}> (Guest)</span>} |
| 66 | + </div> |
| 67 | + {roles.length > 0 && <div className={sc('roles')}>{roles.join(', ')}</div>} |
| 68 | + {isExternal && <div className={sc('organization')}>{organization.name || emailDomain}</div>} |
| 69 | + </div> |
| 70 | + {isInMeeting && isSharing && <Icon name="content-share" size={16} className={sc('sharing')} />} |
| 71 | + {isInMeeting && isSpeaking && <Icon name="microphone" size={16} className={sc('speaking')} />} |
| 72 | + {isInMeeting && isMuted && <Icon name="microphone-muted" size={16} className={sc('muted')} />} |
| 73 | + </div> |
| 74 | + ); |
| 75 | +} |
| 76 | + |
| 77 | +WebexMeetingParticipant.propTypes = { |
| 78 | + className: PropTypes.string, |
| 79 | + meetingID: PropTypes.string.isRequired, |
| 80 | + displayStatus: PropTypes.bool, |
| 81 | + personID: PropTypes.string.isRequired, |
| 82 | + style: PropTypes.shape(), |
| 83 | +}; |
| 84 | + |
| 85 | +WebexMeetingParticipant.defaultProps = { |
| 86 | + className: '', |
| 87 | + displayStatus: false, |
| 88 | + style: undefined, |
| 89 | +}; |
0 commit comments