Skip to content

Commit

Permalink
feat(WebexMeetingInfo): add component
Browse files Browse the repository at this point in the history
  • Loading branch information
adamweeks committed Nov 7, 2019
1 parent c8a02c4 commit b66411c
Show file tree
Hide file tree
Showing 7 changed files with 267 additions and 0 deletions.
60 changes: 60 additions & 0 deletions src/components/WebexMeetingInfo/WebexMeetingInfo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import React from 'react';
import PropTypes from 'prop-types';
import {format} from 'date-fns';
import {Spinner} from '@momentum-ui/react';

import {useMeeting} from '../hooks';

import './WebexMeetingInfo.scss';

/**
* Formats a start and end date to a readable string.
* Example: "5:00 PM - 6:00 PM"
*
* @export
* @param {Date} startDate
* @param {Date} endDate
* @returns {String} formatted time range
*/
export function formatMeetingTime(startDate, endDate) {
const formattedStartTime = format(startDate, 'p');
const formattedEndTime = format(endDate, 'p');

return `${formattedStartTime} - ${formattedEndTime}`;
}

/**
* Webex Meeting Info component displays the information associated with
* a given meetingID.
*
* @param {object} props
* @returns {object} JSX of the component
*/
export default function WebexMeetingInfo({meetingID}) {
const {ID, startTime, endTime, title} = useMeeting(meetingID);
let infoComponent;

if (ID) {
const meetingTime = startTime ? <h3>{formatMeetingTime(new Date(startTime), new Date(endTime))}</h3> : null;
const displayTitle = title || 'No Meeting Information';

infoComponent = (
<React.Fragment>
<h2>{displayTitle}</h2>
{meetingTime}
</React.Fragment>
);
} else {
infoComponent = (
<React.Fragment>
<Spinner />
</React.Fragment>
);
}

return <div className="meeting-info">{infoComponent}</div>;
}

WebexMeetingInfo.propTypes = {
meetingID: PropTypes.string.isRequired,
};
19 changes: 19 additions & 0 deletions src/components/WebexMeetingInfo/WebexMeetingInfo.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
.meeting-info {
display: flex;
height: 100%;
width: 100%;
align-items: center;
justify-content: center;
flex-direction: column;
text-align: center;
}

.meeting-info h2 {
font-size: 28px;
font-family: $brand-font-extra-light;
color: $md-gray-100;
}

.meeting-info h3 {
font-family: $brand-font-extra-light;
}
51 changes: 51 additions & 0 deletions src/components/WebexMeetingInfo/WebexMeetingInfo.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import React from 'react';
import {storiesOf} from '@storybook/react';

import jsonData from '../../data';
import {WebexJSONAdapter} from '../../adapters';
import {WebexMeetingInfo, WebexDataProvider} from '../';

// Setup for the stories
const stories = storiesOf('Webex Meeting Info', module);
const webexAdapter = new WebexJSONAdapter(jsonData);
const wrapperStyle = {height: '150px', width: '500px', border: '1px solid black'};

stories.add('scheduled meeting', () => (
<div style={wrapperStyle}>
<WebexDataProvider adapter={webexAdapter}>
<WebexMeetingInfo meetingID="scheduledMeeting" />
</WebexDataProvider>
</div>
));

stories.add('1:1 meeting', () => (
<div style={wrapperStyle}>
<WebexDataProvider adapter={webexAdapter}>
<WebexMeetingInfo meetingID="oneOnOneMeeting" />
</WebexDataProvider>
</div>
));

stories.add('space meeting', () => (
<div style={wrapperStyle}>
<WebexDataProvider adapter={webexAdapter}>
<WebexMeetingInfo meetingID="spaceMeeting" />
</WebexDataProvider>
</div>
));

stories.add('no meeting information', () => (
<div style={wrapperStyle}>
<WebexDataProvider adapter={webexAdapter}>
<WebexMeetingInfo meetingID="noMeetingTitle" />
</WebexDataProvider>
</div>
));

stories.add('loading', () => (
<div style={wrapperStyle}>
<WebexDataProvider adapter={webexAdapter}>
<WebexMeetingInfo meetingID="loadingMeeting" />
</WebexDataProvider>
</div>
));
38 changes: 38 additions & 0 deletions src/components/WebexMeetingInfo/WebexMeetingInfo.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React from 'react';

import WebexMeetingInfo, {formatMeetingTime} from './WebexMeetingInfo';

jest.mock('../hooks/useMeeting');

describe('Webex Meeting Info component', () => {
describe('snapshot', () => {
test('matches snapshot of scheduled meeting', () => {
expect(shallow(<WebexMeetingInfo meetingID="scheduledMeeting" />)).toMatchSnapshot();
});

test('matches snapshot of one on one meeting', () => {
expect(shallow(<WebexMeetingInfo meetingID="oneOnOneMeeting" />)).toMatchSnapshot();
});

test('matches snapshot of space meeting', () => {
expect(shallow(<WebexMeetingInfo meetingID="spaceMeeting" />)).toMatchSnapshot();
});

test('matches snapshot of no meeting title', () => {
expect(shallow(<WebexMeetingInfo meetingID="noMeetingTitle" />)).toMatchSnapshot();
});

test('matches snapshot of loading', () => {
expect(shallow(<WebexMeetingInfo meetingID="loadingMeeting" />)).toMatchSnapshot();
});
});

describe('formatMeetingTime() returns', () => {
test('a formatted start and end time string', () => {
const startTime = new Date('2019-08-20T21:00:00.000Z');
const endTime = new Date('2019-08-20T22:00:00.000Z');

expect(formatMeetingTime(startTime, endTime)).toEqual('9:00 PM - 10:00 PM');
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Webex Meeting Info component snapshot matches snapshot of loading 1`] = `
<div
className="meeting-info"
>
<Spinner
className=""
color="black"
percentage={null}
showCheck={false}
showPercentage={false}
size={36}
/>
</div>
`;

exports[`Webex Meeting Info component snapshot matches snapshot of no meeting title 1`] = `
<div
className="meeting-info"
>
<h2>
No Meeting Information
</h2>
</div>
`;

exports[`Webex Meeting Info component snapshot matches snapshot of one on one meeting 1`] = `
<div
className="meeting-info"
>
<h2>
Jackie Tester's Personal Room
</h2>
</div>
`;

exports[`Webex Meeting Info component snapshot matches snapshot of scheduled meeting 1`] = `
<div
className="meeting-info"
>
<h2>
Our Scheduled Meeting
</h2>
<h3>
9:00 PM - 10:00 PM
</h3>
</div>
`;

exports[`Webex Meeting Info component snapshot matches snapshot of space meeting 1`] = `
<div
className="meeting-info"
>
<h2>
Ad Hoc Meeting Space
</h2>
</div>
`;
1 change: 1 addition & 0 deletions src/components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export {default as WebexAvatar} from './WebexAvatar/WebexAvatar';
export {default as WebexActivity} from './WebexActivity/WebexActivity';
export {default as WebexActivityStream} from './WebexActivityStream/WebexActivityStream';
export {default as WebexDataProvider, AdapterContext} from './WebexDataProvider/WebexDataProvider';
export {default as WebexMeetingInfo} from './WebexMeetingInfo/WebexMeetingInfo';
39 changes: 39 additions & 0 deletions src/data/meetings.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
{
"loadingMeeting" : {
"ID": null
},
"scheduledMeeting": {
"ID": "scheduledMeeting",
"title": "Our Scheduled Meeting",
Expand All @@ -10,5 +13,41 @@
"remoteAudio": {},
"localShare": {},
"remoteShare": {}
},
"oneOnOneMeeting": {
"ID": "oneOnOneMeeting",
"title": "Jackie Tester's Personal Room",
"startTime": "",
"endTime": "",
"localVideo": {},
"remoteVideo": {},
"localAudio": {},
"remoteAudio": {},
"localShare": {},
"remoteShare": {}
},
"spaceMeeting": {
"ID": "spaceMeeting",
"title": "Ad Hoc Meeting Space",
"startTime": "",
"endTime": "",
"localVideo": {},
"remoteVideo": {},
"localAudio": {},
"remoteAudio": {},
"localShare": {},
"remoteShare": {}
},
"noMeetingTitle": {
"ID": "noMeetingTitle",
"title": "",
"startTime": "",
"endTime": "",
"localVideo": {},
"remoteVideo": {},
"localAudio": {},
"remoteAudio": {},
"localShare": {},
"remoteShare": {}
}
}

0 comments on commit b66411c

Please sign in to comment.