diff --git a/.storybook/preview.js b/.storybook/preview.js
index 1d273c529..b03539917 100644
--- a/.storybook/preview.js
+++ b/.storybook/preview.js
@@ -42,13 +42,13 @@ export const parameters = {
[
'Webex Avatar',
'Webex Member Roster',
- 'Webex Member',
],
'Messaging',
[
'Webex Messaging',
'Webex Activity Stream',
'Webex Activity',
+ 'Webex Member',
],
'Meetings',
[
@@ -58,7 +58,8 @@ export const parameters = {
'Webex In-Meeting',
'Webex Local Media',
'Webex Remote Media',
- 'Webex Meeting Control'
+ 'Webex Meeting Control',
+ 'Webex Meeting Participant',
],
],
},
diff --git a/src/components/WebexMeetingParticipant/WebexMeetingParticipant.jsx b/src/components/WebexMeetingParticipant/WebexMeetingParticipant.jsx
new file mode 100644
index 000000000..e98ca0b80
--- /dev/null
+++ b/src/components/WebexMeetingParticipant/WebexMeetingParticipant.jsx
@@ -0,0 +1,89 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import {DestinationType} from '@webex/component-adapter-interfaces';
+import Spinner from '../generic/Spinner/Spinner';
+import Icon from '../generic/Icon/Icon';
+import {
+ useMembers,
+ useMe,
+ useOrganization,
+ usePerson,
+} from '../hooks';
+import WebexAvatar from '../WebexAvatar/WebexAvatar';
+import webexComponentClasses from '../helpers';
+
+/**
+ * Displays a webex meeting participant.
+ *
+ * @param {object} props Data passed to the component
+ * @param {string} props.className Custom CSS class to apply
+ * @param {string} props.meetingID ID of the meeting for which to get members
+ * @param {boolean} props.displayStatus Whether or not to display the user's status
+ * @param {string} props.personID ID of the member for which to display avatar
+ * @param {object} props.style Custom style to apply
+ * @returns {object} JSX of the component
+ *
+ */
+export default function WebexMeetingParticipant({
+ className,
+ meetingID,
+ displayStatus,
+ personID,
+ style,
+}) {
+ const {displayName, orgID, emails} = usePerson(personID);
+ const me = useMe();
+ const members = useMembers(meetingID, DestinationType.MEETING);
+ const member = members
+ .find((itemMember) => itemMember.ID === personID);
+ const organization = useOrganization(orgID);
+
+ const isMuted = member?.muted;
+ const isSpeaking = member?.speaking;
+ const isExternal = orgID !== undefined && me.orgID !== undefined && me.orgID !== orgID;
+ const isSharing = member?.sharing;
+ const isInMeeting = member?.inMeeting;
+ const showMe = me.ID === personID;
+ const isHost = member?.host;
+ const isGuest = member?.guest;
+
+ const roles = [
+ showMe && 'You',
+ isHost && 'Host',
+ isSharing && 'Presenter',
+ ].filter((role) => role);
+ const emailDomain = emails?.[0]?.split('@')[1] || Unknown organization;
+
+ const [cssClasses, sc] = webexComponentClasses('meeting-participant', className);
+
+ return (
+
+
+
+
+ {(displayName ?? ) || Name not available}
+ {isGuest && (Guest)}
+
+ {roles.length > 0 &&
{roles.join(', ')}
}
+ {isExternal &&
{organization.name || emailDomain}
}
+
+ {isInMeeting && isSharing &&
}
+ {isInMeeting && isSpeaking &&
}
+ {isInMeeting && isMuted &&
}
+
+ );
+}
+
+WebexMeetingParticipant.propTypes = {
+ className: PropTypes.string,
+ meetingID: PropTypes.string.isRequired,
+ displayStatus: PropTypes.bool,
+ personID: PropTypes.string.isRequired,
+ style: PropTypes.shape(),
+};
+
+WebexMeetingParticipant.defaultProps = {
+ className: '',
+ displayStatus: false,
+ style: undefined,
+};
diff --git a/src/components/WebexMeetingParticipant/WebexMeetingParticipant.scss b/src/components/WebexMeetingParticipant/WebexMeetingParticipant.scss
new file mode 100644
index 000000000..0024d3942
--- /dev/null
+++ b/src/components/WebexMeetingParticipant/WebexMeetingParticipant.scss
@@ -0,0 +1,55 @@
+$C: #{$WEBEX_COMPONENTS_CLASS_PREFIX}-meeting-participant;
+
+.#{$C} {
+ display: flex;
+ align-items: center;
+ color: var(--wxc-text-color);
+
+ .#{$C}__avatar {
+ height: 2rem;
+ width: 2rem;
+ margin-top: 0.5rem;
+ margin-bottom: 0.5rem;
+ }
+
+ .#{$C}__details {
+ flex: 1;
+ min-width: 0;
+ margin-left: 0.75rem;
+ }
+
+ .#{$C}__name {
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ margin-top: 0.063rem;
+
+ .#{$C}__guest {
+ color: var(--wxc-secondary-text-color);
+ }
+ }
+
+ .#{$C}__roles {
+ font-size: 0.875rem;
+ line-height: 1rem;
+ color: var(--wxc-secondary-text-color);
+ }
+
+ .#{$C}__organization {
+ font-size: 0.875rem;
+ line-height: 1rem;
+ color: var(--wxc-warning-color);
+ }
+
+ .#{$C}__sharing {
+ margin-right: 2.5rem;
+ }
+
+ .#{$C}__speaking {
+ color: var(--wxc-speaking-color);
+ }
+
+ .#{$C}__muted {
+ color: var(--wxc-muted-color);
+ }
+}
diff --git a/src/components/WebexMeetingParticipant/WebexMeetingParticipant.stories.js b/src/components/WebexMeetingParticipant/WebexMeetingParticipant.stories.js
new file mode 100644
index 000000000..4a53f7200
--- /dev/null
+++ b/src/components/WebexMeetingParticipant/WebexMeetingParticipant.stories.js
@@ -0,0 +1,34 @@
+import React from 'react';
+import WebexMeetingParticipant from './WebexMeetingParticipant';
+
+export default {
+ title: 'Meetings/Webex Meeting Participant',
+ component: WebexMeetingParticipant,
+ decorators: [(Story) =>
],
+};
+
+const Template = (args) => ;
+
+export const Muted = Template.bind({});
+Muted.args = {
+ meetingID: 'meeting2',
+ personID: 'user2',
+};
+
+export const Host = Template.bind({});
+Host.args = {
+ meetingID: 'meeting2',
+ personID: 'user4',
+};
+
+export const Guest = Template.bind({});
+Guest.args = {
+ meetingID: 'meeting2',
+ personID: 'user6',
+};
+
+export const ScreenSharing = Template.bind({});
+ScreenSharing.args = {
+ meetingID: 'meeting2',
+ personID: 'user3',
+};
diff --git a/src/components/WebexMeetingParticipant/__snapshots__/WebexMeetingParticipant.stories.storyshot b/src/components/WebexMeetingParticipant/__snapshots__/WebexMeetingParticipant.stories.storyshot
new file mode 100644
index 000000000..f08f74248
--- /dev/null
+++ b/src/components/WebexMeetingParticipant/__snapshots__/WebexMeetingParticipant.stories.storyshot
@@ -0,0 +1,383 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Storyshots Meetings/Webex Meeting Participant Guest 1`] = `
+Array [
+
+
+
+
+
+
+
+
+
+
+ Maria Rossi
+
+ (Guest)
+
+
+
+ Gmail.com
+
+
+
+
,
+ ,
+ ,
+]
+`;
+
+exports[`Storyshots Meetings/Webex Meeting Participant Host 1`] = `
+Array [
+
+
+
+
+
+
+
+
+
+
+ Simon Damiano
+
+
+ Host
+
+
+
+
+
,
+ ,
+ ,
+]
+`;
+
+exports[`Storyshots Meetings/Webex Meeting Participant Muted 1`] = `
+Array [
+
+
+
+
+
+
+
+
+
+
+
+
,
+ ,
+ ,
+]
+`;
+
+exports[`Storyshots Meetings/Webex Meeting Participant Screen Sharing 1`] = `
+Array [
+
+
+
+
+
+
+
+
+
+
+ Brenda Song
+
+
+ Presenter
+
+
+
+
+
+
,
+ ,
+ ,
+]
+`;
diff --git a/src/components/WebexMember/WebexMember.jsx b/src/components/WebexMember/WebexMember.jsx
index 56032c5d4..ece8719fa 100644
--- a/src/components/WebexMember/WebexMember.jsx
+++ b/src/components/WebexMember/WebexMember.jsx
@@ -3,7 +3,6 @@ import PropTypes from 'prop-types';
import {DestinationType} from '@webex/component-adapter-interfaces';
import Spinner from '../generic/Spinner/Spinner';
-import Icon from '../generic/Icon/Icon';
import {
useMembers,
useMe,
@@ -18,8 +17,7 @@ import webexComponentClasses from '../helpers';
*
* @param {object} props Data passed to the component
* @param {string} props.className Custom CSS class to apply
- * @param {string} props.destinationID ID of the destination for which to get members
- * @param {string} props.destinationType Type of destination of the membership roster
+ * @param {string} props.roomID ID of the room for which to get members
* @param {boolean} props.displayStatus Whether or not to display the user's status
* @param {string} props.personID ID of the person for which to display avatar
* @param {object} props.style Custom style to apply
@@ -28,59 +26,43 @@ import webexComponentClasses from '../helpers';
*/
export default function WebexMember({
className,
- destinationID,
- destinationType,
+ roomID,
displayStatus,
personID,
style,
}) {
const {displayName, orgID, emails} = usePerson(personID);
const me = useMe();
- const members = useMembers(destinationID, destinationType);
+ const members = useMembers(roomID, DestinationType.ROOM);
const member = members
.find((itemMember) => itemMember.ID === personID);
const organization = useOrganization(orgID);
- const isMuted = member?.muted;
- const isSpeaking = member?.speaking;
const isExternal = orgID !== undefined && me.orgID !== undefined && me.orgID !== orgID;
- const isSharing = member?.sharing;
- const isInMeeting = member?.inMeeting;
- const showMe = me.ID === personID && destinationType === DestinationType.MEETING;
- const isHost = member?.host;
- const isGuest = member?.guest;
- const roles = [
- showMe && 'You',
- isHost && 'Host',
- isSharing && 'Presenter',
- ].filter((role) => role);
const emailDomain = emails?.[0]?.split('@')[1] || Unknown organization;
-
const [cssClasses, sc] = webexComponentClasses('member', className);
+ if (!member) {
+ return null;
+ }
+
return (
{(displayName ?? ) || Name not available}
- {isGuest && (Guest)}
- {roles.length > 0 &&
{roles.join(', ')}
}
{isExternal &&
{organization.name || emailDomain}
}
- {isInMeeting && isSharing &&
}
- {isInMeeting && isSpeaking &&
}
- {isInMeeting && isMuted &&
}
);
}
WebexMember.propTypes = {
className: PropTypes.string,
- destinationID: PropTypes.string.isRequired,
- destinationType: PropTypes.string.isRequired,
+ roomID: PropTypes.string.isRequired,
displayStatus: PropTypes.bool,
personID: PropTypes.string.isRequired,
style: PropTypes.shape(),
diff --git a/src/components/WebexMember/WebexMember.scss b/src/components/WebexMember/WebexMember.scss
index 8aba8d294..c658a9d65 100644
--- a/src/components/WebexMember/WebexMember.scss
+++ b/src/components/WebexMember/WebexMember.scss
@@ -29,27 +29,9 @@ $C: #{$WEBEX_COMPONENTS_CLASS_PREFIX}-member;
}
}
- .#{$C}__roles {
- font-size: 0.875rem;
- line-height: 1rem;
- color: var(--wxc-secondary-text-color);
- }
-
.#{$C}__organization {
font-size: 0.875rem;
line-height: 1rem;
color: var(--wxc-warning-color);
}
-
- .#{$C}__sharing {
- margin-right: 2.5rem;
- }
-
- .#{$C}__speaking {
- color: var(--wxc-speaking-color);
- }
-
- .#{$C}__muted {
- color: var(--wxc-muted-color);
- }
}
diff --git a/src/components/WebexMember/WebexMember.stories.js b/src/components/WebexMember/WebexMember.stories.js
index f2432c72f..e4d1e4108 100644
--- a/src/components/WebexMember/WebexMember.stories.js
+++ b/src/components/WebexMember/WebexMember.stories.js
@@ -2,7 +2,7 @@ import React from 'react';
import WebexMember from './WebexMember';
export default {
- title: 'Platform/Webex Member',
+ title: 'Messaging/Webex Member',
component: WebexMember,
decorators: [(Story) =>
],
};
@@ -11,50 +11,19 @@ const Template = (args) => ;
export const Space = Template.bind({});
Space.args = {
- destinationType: 'room',
- destinationID: 'room1',
+ roomID: 'room1',
personID: 'user1',
};
export const StatusEnabled = Template.bind({});
StatusEnabled.args = {
- destinationType: 'room',
- destinationID: 'room1',
+ roomID: 'room1',
personID: 'user1',
displayStatus: true,
};
-export const Muted = Template.bind({});
-Muted.args = {
- destinationType: 'meeting',
- destinationID: 'meeting2',
- personID: 'user2',
-};
-
export const ExternalOrganization = Template.bind({});
ExternalOrganization.args = {
- destinationType: 'room',
- destinationID: 'room2',
+ roomID: 'room2',
personID: 'user5',
};
-
-export const Host = Template.bind({});
-Host.args = {
- destinationType: 'meeting',
- destinationID: 'meeting2',
- personID: 'user4',
-};
-
-export const Guest = Template.bind({});
-Guest.args = {
- destinationType: 'meeting',
- destinationID: 'meeting2',
- personID: 'user6',
-};
-
-export const ScreenSharing = Template.bind({});
-ScreenSharing.args = {
- destinationType: 'meeting',
- destinationID: 'meeting2',
- personID: 'user3',
-};
diff --git a/src/components/WebexMember/__snapshots__/WebexMember.stories.storyshot b/src/components/WebexMember/__snapshots__/WebexMember.stories.storyshot
index 9032b3ba1..d52de09b5 100644
--- a/src/components/WebexMember/__snapshots__/WebexMember.stories.storyshot
+++ b/src/components/WebexMember/__snapshots__/WebexMember.stories.storyshot
@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`Storyshots Platform/Webex Member External Organization 1`] = `
+exports[`Storyshots Messaging/Webex Member External Organization 1`] = `
Array [
-
-
-
-
-
-
-
-
-
- Maria Rossi
-
- (Guest)
-
-
-
- Gmail.com
-
-
-
-
,
- ,
- ,
-]
-`;
-
-exports[`Storyshots Platform/Webex Member Host 1`] = `
-Array [
-
-
-
-
-
-
-
-
-
-
- Simon Damiano
-
-
- Host
-
-
-
-
-
,
- ,
- ,
-]
-`;
-
-exports[`Storyshots Platform/Webex Member Muted 1`] = `
-Array [
-
-
-
-
-
-
-
-
-
-
-
-
,
- ,
- ,
-]
-`;
-
-exports[`Storyshots Platform/Webex Member Screen Sharing 1`] = `
-Array [
-
-
-
-
-
-
-
-
-
-
- Brenda Song
-
-
- Presenter
-
-
-
-
-
-
,
- ,
- ,
-]
-`;
-
-exports[`Storyshots Platform/Webex Member Space 1`] = `
+exports[`Storyshots Messaging/Webex Member Space 1`] = `
Array [