-
Notifications
You must be signed in to change notification settings - Fork 53
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
279 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
# Webex Meeting Component | ||
|
||
Webex Meeting component displays the complete, default Webex meeting experience. | ||
|
||
<p align="center"> | ||
<img src="./WebexMeeting.gif" alt="Default Webex Meeting" /> | ||
</p> | ||
|
||
## Preview | ||
|
||
To see all the different possible states of the Webex Meeting component, you can run our Storybook: | ||
|
||
```shell | ||
npm start | ||
``` | ||
|
||
## Embed | ||
|
||
1. Create a component adapter from which the data will be retrieved (See [adapters](../../adapters)). For instance: | ||
|
||
```js | ||
const jsonAdapter = new WebexJSONAdapter(jsonData); | ||
``` | ||
|
||
2. Create a component instance by passing the meeting ID as a string and an optional function that returns an array | ||
of control names for the meeting. The default control names are set to `['mute-audio', 'mute-video', 'join-meeting]` if the meeting is inactive and `['mute-audio', 'mute-video', 'leave-meeting']` otherwise. Ensure that the control names match with the adapter implementation of the controls. You then need to | ||
enclose it within [a data provider](../WebexDataProvider/WebexDataProvider.js) | ||
that takes the [component data adapter](../../adapters/WebexJSONAdapter.js) that we created previously | ||
|
||
```js | ||
const controls = (isActive) => isActive ? ['join-meeting'] : ['leave-meeting']; | ||
|
||
<WebexDataProvider adapter={jsonAdapter}> | ||
<WebexMeeting meetingDestination="meetingDestination" controls?={controls}/> | ||
</WebexDataProvider> | ||
``` | ||
The component knows how to manage its data. If anything changes in the data source that the adapter manages, the component will also update on its own. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
.meeting { | ||
display: flex; | ||
position: relative; | ||
justify-content: center; | ||
align-items: center; | ||
height: 100%; | ||
width: 100%; | ||
} | ||
|
||
.meeting .controls { | ||
display: flex; | ||
position: absolute; | ||
align-self: flex-end; | ||
bottom: 3rem; | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import React, {Fragment} from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import {Spinner} from '@momentum-ui/react'; | ||
|
||
import {useMeeting} from '../hooks'; | ||
|
||
import {WebexInMeeting, WebexInterstitialMeeting, WebexMeetingControl, WebexMeetingControls} from '..'; | ||
|
||
import './WebexMeeting.css'; | ||
|
||
/** | ||
* Webex Meeting component displays the default Webex meeting experience. | ||
* | ||
* @param {object} props | ||
* @returns {object} JSX of the component | ||
*/ | ||
export default function WebexMeeting({meetingDestination, controls}) { | ||
const {ID} = useMeeting(null, meetingDestination); | ||
// Subscribe to meeting updates after meeting creation | ||
const {remoteVideo} = useMeeting(ID); | ||
const isActive = remoteVideo !== null; | ||
const meetingControls = controls(isActive).map((key) => <WebexMeetingControl key={key} type={key} />); | ||
|
||
return ( | ||
<div className="meeting"> | ||
{ID ? ( | ||
<Fragment> | ||
{isActive ? <WebexInMeeting meetingID={ID} /> : <WebexInterstitialMeeting meetingID={ID} />} | ||
<WebexMeetingControls meetingID={ID}>{meetingControls}</WebexMeetingControls> | ||
</Fragment> | ||
) : ( | ||
<Spinner /> | ||
)} | ||
</div> | ||
); | ||
} | ||
|
||
WebexMeeting.propTypes = { | ||
meetingDestination: PropTypes.string.isRequired, | ||
controls: PropTypes.func, | ||
}; | ||
|
||
WebexMeeting.defaultProps = { | ||
/** | ||
* A function that returns an array of control names for the meeting. | ||
* Control name must match with the adapter implementation of the control. | ||
* | ||
* @param {boolean} isActive Whether or not the meeting is active | ||
*/ | ||
// eslint-disable-next-line no-confusing-arrow | ||
controls: (isActive) => | ||
isActive ? ['mute-audio', 'mute-video', 'leave-meeting'] : ['mute-audio', 'mute-video', 'join-meeting'], | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import React from 'react'; | ||
import {storiesOf} from '@storybook/react'; | ||
|
||
import jsonData from '../../data'; | ||
import {WebexJSONAdapter} from '../../adapters'; | ||
|
||
import {WebexMeeting, WebexDataProvider} from '..'; | ||
|
||
// Setup for the stories | ||
const stories = storiesOf('Webex Meeting', module); | ||
const webexAdapter = new WebexJSONAdapter(jsonData); | ||
const wrapperStyle = {height: '500px', width: '800px', border: '1px solid black'}; | ||
|
||
stories.add('in session', () => ( | ||
<div style={wrapperStyle}> | ||
<WebexDataProvider adapter={webexAdapter}> | ||
<WebexMeeting meetingDestination="localMedia" /> | ||
</WebexDataProvider> | ||
</div> | ||
)); | ||
|
||
stories.add('in session with optional controls', () => { | ||
const controls = (isActive) => (isActive ? ['leave-meeting'] : ['join-meeting']); | ||
|
||
return ( | ||
<div style={wrapperStyle}> | ||
<WebexDataProvider adapter={webexAdapter}> | ||
<WebexMeeting meetingDestination="localMedia" controls={controls} /> | ||
</WebexDataProvider> | ||
</div> | ||
); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import React from 'react'; | ||
|
||
import WebexMeeting from './WebexMeeting'; | ||
|
||
jest.mock('../hooks/useMeeting'); | ||
|
||
describe('Webex Meeting component', () => { | ||
describe('snapshot', () => { | ||
let controls; | ||
|
||
beforeAll(() => { | ||
controls = (isActive) => (isActive ? ['leave-meeting'] : ['join-meeting']); | ||
}); | ||
|
||
test('matches snapshot of loading while meeting is created', () => { | ||
expect(shallow(<WebexMeeting meetingDestination="" />)).toMatchSnapshot(); | ||
}); | ||
|
||
test('matches snapshot of a user waiting to join a meeting', () => { | ||
expect(shallow(<WebexMeeting meetingDestination="localMedia" />)).toMatchSnapshot(); | ||
}); | ||
|
||
test('matches snapshot of a user that has joined a meeting', () => { | ||
expect(shallow(<WebexMeeting meetingDestination="remoteMedia" />)).toMatchSnapshot(); | ||
}); | ||
|
||
test('matches snapshot of a user waiting to join a meeting with optional controls', () => { | ||
expect(shallow(<WebexMeeting meetingDestination="localMedia" controls={controls} />)).toMatchSnapshot(); | ||
}); | ||
|
||
test('matches snapshot of a user that has joined a meeting with optional controls', () => { | ||
expect(shallow(<WebexMeeting meetingDestination="remoteMedia" controls={controls} />)).toMatchSnapshot(); | ||
}); | ||
}); | ||
}); |
104 changes: 104 additions & 0 deletions
104
src/components/WebexMeeting/__snapshots__/WebexMeeting.test.js.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`Webex Meeting component snapshot matches snapshot of a user that has joined a meeting 1`] = ` | ||
<div | ||
className="meeting" | ||
> | ||
<WebexInMeeting | ||
meetingID="remoteMedia" | ||
/> | ||
<WebexMeetingControls | ||
meetingID="remoteMedia" | ||
> | ||
<WebexMeetingControl | ||
key="mute-audio" | ||
type="mute-audio" | ||
/> | ||
<WebexMeetingControl | ||
key="mute-video" | ||
type="mute-video" | ||
/> | ||
<WebexMeetingControl | ||
key="leave-meeting" | ||
type="leave-meeting" | ||
/> | ||
</WebexMeetingControls> | ||
</div> | ||
`; | ||
|
||
exports[`Webex Meeting component snapshot matches snapshot of a user that has joined a meeting with optional controls 1`] = ` | ||
<div | ||
className="meeting" | ||
> | ||
<WebexInMeeting | ||
meetingID="remoteMedia" | ||
/> | ||
<WebexMeetingControls | ||
meetingID="remoteMedia" | ||
> | ||
<WebexMeetingControl | ||
key="leave-meeting" | ||
type="leave-meeting" | ||
/> | ||
</WebexMeetingControls> | ||
</div> | ||
`; | ||
|
||
exports[`Webex Meeting component snapshot matches snapshot of a user waiting to join a meeting 1`] = ` | ||
<div | ||
className="meeting" | ||
> | ||
<WebexInterstitialMeeting | ||
meetingID="localMedia" | ||
/> | ||
<WebexMeetingControls | ||
meetingID="localMedia" | ||
> | ||
<WebexMeetingControl | ||
key="mute-audio" | ||
type="mute-audio" | ||
/> | ||
<WebexMeetingControl | ||
key="mute-video" | ||
type="mute-video" | ||
/> | ||
<WebexMeetingControl | ||
key="join-meeting" | ||
type="join-meeting" | ||
/> | ||
</WebexMeetingControls> | ||
</div> | ||
`; | ||
|
||
exports[`Webex Meeting component snapshot matches snapshot of a user waiting to join a meeting with optional controls 1`] = ` | ||
<div | ||
className="meeting" | ||
> | ||
<WebexInterstitialMeeting | ||
meetingID="localMedia" | ||
/> | ||
<WebexMeetingControls | ||
meetingID="localMedia" | ||
> | ||
<WebexMeetingControl | ||
key="join-meeting" | ||
type="join-meeting" | ||
/> | ||
</WebexMeetingControls> | ||
</div> | ||
`; | ||
|
||
exports[`Webex Meeting component snapshot matches snapshot of loading while meeting is created 1`] = ` | ||
<div | ||
className="meeting" | ||
> | ||
<Spinner | ||
className="" | ||
color="black" | ||
percentage={null} | ||
showCheck={false} | ||
showPercentage={false} | ||
size={36} | ||
/> | ||
</div> | ||
`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters