diff --git a/.storybook/preview.js b/.storybook/preview.js
index b03539917..b8b1368d8 100644
--- a/.storybook/preview.js
+++ b/.storybook/preview.js
@@ -41,7 +41,6 @@ export const parameters = {
'Platform',
[
'Webex Avatar',
- 'Webex Member Roster',
],
'Messaging',
[
@@ -49,6 +48,7 @@ export const parameters = {
'Webex Activity Stream',
'Webex Activity',
'Webex Member',
+ 'Webex Member Roster',
],
'Meetings',
[
@@ -60,6 +60,7 @@ export const parameters = {
'Webex Remote Media',
'Webex Meeting Control',
'Webex Meeting Participant',
+ 'Webex Meeting Roster',
],
],
},
diff --git a/src/components/WebexMeetingRoster/WebexMeetingRoster.jsx b/src/components/WebexMeetingRoster/WebexMeetingRoster.jsx
new file mode 100644
index 000000000..827f46d4e
--- /dev/null
+++ b/src/components/WebexMeetingRoster/WebexMeetingRoster.jsx
@@ -0,0 +1,107 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import {DestinationType} from '@webex/component-adapter-interfaces';
+import webexComponentClasses from '../helpers';
+
+import Button from '../generic/Button/Button';
+import Icon from '../generic/Icon/Icon';
+import Title from '../generic/Title/Title';
+import useMembers from '../hooks/useMembers';
+import {useMe} from '../hooks';
+import WebexMeetingParticipant from '../WebexMeetingParticipant/WebexMeetingParticipant';
+
+// TODO: Figure out how to import JS Doc definitions and remove duplication.
+/**
+ * Enum for types of destinations.
+ *
+ * @external DestinationType
+ * @see {@link https://github.com/webex/component-adapter-interfaces/blob/master/src/MembershipsAdapter.js#L21}
+ */
+
+/**
+ * Displays the roster of Webex meeting.
+ *
+ * @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 {object} props.style Custom style to apply
+ * @param {Function} props.onClose Action to close the roster
+ * @returns {object} JSX of the component
+ *
+ */
+export default function WebexMeetingRoster({
+ className,
+ meetingID,
+ style,
+ onClose,
+}) {
+ const members = useMembers(meetingID, DestinationType.MEETING);
+ const {orgID} = useMe();
+
+ const [cssClasses, sc] = webexComponentClasses('meeting-roster', className);
+
+ const renderMembers = (data) => data.map(
+ ({ID}) => (
+
+ ),
+ );
+
+ const renderSection = (data, title) => data.length > 0 && (
+ <>
+
{title}
+ {renderMembers(data)}
+ >
+ );
+
+ const warningExternalMembers = members.some(
+ (member) => member.orgID !== undefined && orgID !== undefined && member.orgID !== orgID,
+ ) && (
+
+
+
People outside your company are included in this space
+
+ );
+
+ return (
+
+
+
+ Participants (
+ {members ? members.length : loading... }
+ )
+
+
+
+
+
+ {warningExternalMembers}
+
+ {renderSection(members.filter((member) => member.inMeeting), 'In the meeting')}
+ {renderSection(members.filter((member) => !member.inMeeting), 'Not in the meeting')}
+
+
+ );
+}
+
+WebexMeetingRoster.propTypes = {
+ className: PropTypes.string,
+ meetingID: PropTypes.string.isRequired,
+ style: PropTypes.shape(),
+ onClose: PropTypes.func,
+};
+
+WebexMeetingRoster.defaultProps = {
+ className: '',
+ style: undefined,
+ onClose: undefined,
+};
diff --git a/src/components/WebexMeetingRoster/WebexMeetingRoster.scss b/src/components/WebexMeetingRoster/WebexMeetingRoster.scss
new file mode 100644
index 000000000..ba2cd08c3
--- /dev/null
+++ b/src/components/WebexMeetingRoster/WebexMeetingRoster.scss
@@ -0,0 +1,66 @@
+$C: #{$WEBEX_COMPONENTS_CLASS_PREFIX}-meeting-roster;
+
+.#{$C} {
+ display: flex;
+ flex-direction: column;
+
+ color: var(--wxc-text-color);
+ background: var(--wxc-secondary-background);
+ border-radius: 0.5rem 0 0 0;
+ padding: 0.625rem 0 0.625rem 0.75rem;
+
+
+ .#{$C}__section-title {
+ color: var(--wxc-secondary-text-color);
+ font-size: 0.875rem;
+ line-height: 1.375rem;
+ margin: 0;
+ letter-spacing: normal;
+ padding: 0.438rem 0 0.188rem 0;
+ }
+
+ .#{$C}__external-user-warning {
+ color: var(--wxc-warning-color);
+ display: flex;
+ align-items: flex-start;
+ font-size: 0.875rem;
+ line-height: 1.375rem;
+ margin-top: 0.75rem;
+
+ .#{$C}__external-user-icon {
+ margin-right: 0.578rem;
+ }
+
+ .#{$C}__external-user-message {
+ flex: 1;
+ }
+ }
+
+ .#{$C}__header {
+ display: flex;
+ align-items: center;
+ padding-right: 0.375rem;
+
+ .#{$C}__title {
+ font-family: $brand-font-bold;
+ margin: 0;
+ flex: 1;
+ }
+ }
+
+ .#{$C}__members {
+ overflow-y: auto;
+ flex: 1;
+ padding-right: 1.25rem;
+ scrollbar-width: thin; //works only for Firefox
+ }
+
+ ::-webkit-scrollbar {
+ width: 1rem;
+ }
+
+ ::-webkit-scrollbar-thumb {
+ background: var(--wxc-scrollbar--thumb);
+ border-radius: 1rem;
+ }
+}
diff --git a/src/components/WebexMeetingRoster/WebexMeetingRoster.stories.js b/src/components/WebexMeetingRoster/WebexMeetingRoster.stories.js
new file mode 100644
index 000000000..e72f3851d
--- /dev/null
+++ b/src/components/WebexMeetingRoster/WebexMeetingRoster.stories.js
@@ -0,0 +1,23 @@
+import React from 'react';
+import WebexMeetingRoster from './WebexMeetingRoster';
+
+export default {
+ title: 'Meetings/Webex Meeting Roster',
+ component: WebexMeetingRoster,
+};
+
+const Template = (args) => {
+ const style = {
+ width: '23.25rem',
+ maxHeight: '100%',
+ ...args.style,
+ };
+ const props = {...args, style};
+
+ return ;
+};
+
+export const Meeting = Template.bind({});
+Meeting.args = {
+ meetingID: 'meeting2',
+};
diff --git a/src/components/WebexMeetingRoster/__snapshots__/WebexMeetingRoster.stories.storyshot b/src/components/WebexMeetingRoster/__snapshots__/WebexMeetingRoster.stories.storyshot
new file mode 100644
index 000000000..7cdebf408
--- /dev/null
+++ b/src/components/WebexMeetingRoster/__snapshots__/WebexMeetingRoster.stories.storyshot
@@ -0,0 +1,475 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Storyshots Meetings/Webex Meeting Roster Meeting 1`] = `
+Array [
+
+
+
+ Participants (
+ 6
+ )
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ People outside your company are included in this space
+
+
+
+
+ In the meeting
+
+
+
+
+
+
+ BG
+
+
+
+
+
+
+
+ Barbara German
+
+
+ You
+
+
+
+
+
+
+
+
+
+
+
+
+ GE
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ BS
+
+
+
+
+
+
+
+ Brenda Song
+
+
+ Presenter
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SD
+
+
+
+
+
+
+
+ Simon Damiano
+
+
+ Host
+
+
+
+
+
+
+
+
+
+
+
+
+ BS
+
+
+
+
+
+
+
+ Brandon Seeger
+
+ (Guest)
+
+
+
+ Gmail.com
+
+
+
+
+ Not in the meeting
+
+
+
+
+
+
+ MR
+
+
+
+
+
+
+
+ Maria Rossi
+
+ (Guest)
+
+
+
+ Gmail.com
+
+
+
+
+
,
+ ,
+ ,
+]
+`;
diff --git a/src/components/WebexMemberRoster/WebexMemberRoster.jsx b/src/components/WebexMemberRoster/WebexMemberRoster.jsx
index b134bc7a3..4c7103637 100644
--- a/src/components/WebexMemberRoster/WebexMemberRoster.jsx
+++ b/src/components/WebexMemberRoster/WebexMemberRoster.jsx
@@ -23,8 +23,7 @@ import WebexMember from '../WebexMember/WebexMember';
*
* @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 {object} props.style Custom style to apply
* @param {Function} props.onClose Action to close the roster
* @returns {object} JSX of the component
@@ -32,12 +31,11 @@ import WebexMember from '../WebexMember/WebexMember';
*/
export default function WebexMemberRoster({
className,
- destinationID,
- destinationType,
+ roomID,
style,
onClose,
}) {
- const members = useMembers(destinationID, destinationType);
+ const members = useMembers(roomID, DestinationType.ROOM);
const {orgID} = useMe();
const [cssClasses, sc] = webexComponentClasses('member-roster', className);
@@ -45,21 +43,13 @@ export default function WebexMemberRoster({
const renderMembers = (data) => data.map(
({ID}) => (
),
);
- const renderSection = (data, title) => data.length > 0 && (
- <>
- {title}
- {renderMembers(data)}
- >
- );
-
const warningExternalMembers = members.some(
(member) => member.orgID !== undefined && orgID !== undefined && member.orgID !== orgID,
) && (
@@ -89,14 +79,7 @@ export default function WebexMemberRoster({
{warningExternalMembers}
- {destinationType !== DestinationType.MEETING
- ? renderMembers(members)
- : (
- <>
- {renderSection(members.filter((member) => member.inMeeting), 'In the meeting')}
- {renderSection(members.filter((member) => !member.inMeeting), 'Not in the meeting')}
- >
- )}
+ {renderMembers(members)}
);
@@ -104,8 +87,7 @@ export default function WebexMemberRoster({
WebexMemberRoster.propTypes = {
className: PropTypes.string,
- destinationID: PropTypes.string.isRequired,
- destinationType: PropTypes.string.isRequired,
+ roomID: PropTypes.string.isRequired,
style: PropTypes.shape(),
onClose: PropTypes.func,
};
diff --git a/src/components/WebexMemberRoster/WebexMemberRoster.stories.js b/src/components/WebexMemberRoster/WebexMemberRoster.stories.js
index 6be392989..413203027 100644
--- a/src/components/WebexMemberRoster/WebexMemberRoster.stories.js
+++ b/src/components/WebexMemberRoster/WebexMemberRoster.stories.js
@@ -2,7 +2,7 @@ import React from 'react';
import WebexMemberRoster from './WebexMemberRoster';
export default {
- title: 'Platform/Webex Member Roster',
+ title: 'Messaging/Webex Member Roster',
component: WebexMemberRoster,
};
@@ -19,18 +19,10 @@ const Template = (args) => {
export const Space = Template.bind({});
Space.args = {
- destinationID: 'room1',
- destinationType: 'room',
-};
-
-export const Meeting = Template.bind({});
-Meeting.args = {
- destinationID: 'meeting2',
- destinationType: 'meeting',
+ roomID: 'room1',
};
export const ExternalMember = Template.bind({});
ExternalMember.args = {
- destinationID: 'room2',
- destinationType: 'room',
+ roomID: 'room2',
};
diff --git a/src/components/WebexMemberRoster/__snapshots__/WebexMemberRoster.stories.storyshot b/src/components/WebexMemberRoster/__snapshots__/WebexMemberRoster.stories.storyshot
index e4aa8a589..3947a981c 100644
--- a/src/components/WebexMemberRoster/__snapshots__/WebexMemberRoster.stories.storyshot
+++ b/src/components/WebexMemberRoster/__snapshots__/WebexMemberRoster.stories.storyshot
@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`Storyshots Platform/Webex Member Roster External Member 1`] = `
+exports[`Storyshots Messaging/Webex Member Roster External Member 1`] = `
Array [
-
-
- Participants (
- 6
- )
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- People outside your company are included in this space
-
-
-
-
- In the meeting
-
-
-
-
-
-
- BG
-
-
-
-
-
-
-
- Barbara German
-
-
- You
-
-
-
-
-
-
-
-
-
-
-
-
- GE
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- BS
-
-
-
-
-
-
-
- Brenda Song
-
-
- Presenter
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- SD
-
-
-
-
-
-
-
- Simon Damiano
-
-
- Host
-
-
-
-
-
-
-
-
-
-
-
-
- BS
-
-
-
-
-
-
-
- Brandon Seeger
-
- (Guest)
-
-
-
- Gmail.com
-
-
-
-
- Not in the meeting
-
-
-
-
-
-
- MR
-
-
-
-
-
-
-
- Maria Rossi
-
- (Guest)
-
-
-
- Gmail.com
-
-
-
-
-
,
- ,
- ,
-]
-`;
-
-exports[`Storyshots Platform/Webex Member Roster Space 1`] = `
+exports[`Storyshots Messaging/Webex Member Roster Space 1`] = `
Array [