Skip to content

Commit 2d8ea1a

Browse files
committed
feat(demo): add message meet widget to demo
1 parent b1b0a4c commit 2d8ea1a

File tree

10 files changed

+406
-3
lines changed

10 files changed

+406
-3
lines changed

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
"eslint": "eslint packages",
1818
"serve": "npm run start",
1919
"stylelint": "stylelint \"packages/node_modules/**/*.css\"",
20-
"start": "NODE_ENV=development webpack-dev-server --config scripts/webpack/webpack.dev.babel.js --hot --inline"
20+
"start": "NODE_ENV=development webpack-dev-server --config scripts/webpack/webpack.dev.babel.js --hot --inline --history-api-fallback"
2121
},
2222
"repository": {
2323
"type": "git",
@@ -38,6 +38,7 @@
3838
"@ciscospark/helper-html": "^0.7.34",
3939
"@ciscospark/plugin-avatar": "^0.7.31",
4040
"@ciscospark/plugin-conversation": "^0.7.31",
41+
"@ciscospark/plugin-encryption": "^0.7.31",
4142
"@ciscospark/plugin-flag": "^0.7.31",
4243
"@ciscospark/spark-core": "^0.7.31",
4344
"@ciscospark/storage-adapter-local-storage": "^0.7.31",

scripts/webpack/webpack.dev.babel.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ const plugins = [
1313
}),
1414
new webpack.EnvironmentPlugin([
1515
`CISCOSPARK_ACCESS_TOKEN`,
16+
`MESSAGE_DEMO_CLIENT_ID`,
17+
`MESSAGE_DEMO_CLIENT_SECRET`,
1618
`TO_PERSON_EMAIL`,
1719
`TO_PERSON_ID`
1820
])

src/components/test.js

Whitespace-only changes.

src/demo-widget-message-meet/index.js

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
/* eslint-disable react/no-set-state */
2+
import React, {Component} from 'react';
3+
import classNames from 'classnames';
4+
5+
import styles from './styles.css';
6+
7+
import SparkLogo from '@ciscospark/react-component-spark-logo';
8+
9+
import ExampleCode, {MODE_REACT, MODE_INLINE} from '../example-code';
10+
11+
import WidgetMessageMeet from '@ciscospark/widget-message-meet';
12+
import SparkOAuth from '../spark-oauth';
13+
14+
15+
class DemoWidgetMessageMeet extends Component {
16+
constructor() {
17+
super();
18+
const l = window.location;
19+
const redirectUri = `${l.protocol}//${l.host}${l.pathname}`.replace(/\/$/, ``);
20+
21+
this.state = {
22+
authenticate: false,
23+
mode: MODE_INLINE,
24+
accessToken: ``,
25+
toPersonEmail: ``,
26+
running: false,
27+
clientId: process.env.MESSAGE_DEMO_CLIENT_ID,
28+
clientSecret: process.env.MESSAGE_DEMO_CLIENT_SECRET,
29+
scope: `spark:kms spark:rooms_read spark:rooms_write spark:memberships_read spark:memberships_write spark:messages_read spark:messages_write`,
30+
redirectUri
31+
};
32+
this.handleSubmit = this.handleSubmit.bind(this);
33+
this.handleAccessTokenChange = this.handleAccessTokenChange.bind(this);
34+
this.handleEmailChange = this.handleEmailChange.bind(this);
35+
this.handleModeChange = this.handleModeChange.bind(this);
36+
this.handleLoginOAuth = this.handleLoginOAuth.bind(this);
37+
this.handleOnAuth = this.handleOnAuth.bind(this);
38+
}
39+
40+
shouldComponentUpdate() {
41+
return true;
42+
}
43+
44+
handleSubmit(e) {
45+
e.preventDefault();
46+
this.setState({running: true});
47+
}
48+
49+
handleAccessTokenChange(e) {
50+
return this.setState({accessToken: e.target.value});
51+
}
52+
53+
handleEmailChange(e) {
54+
return this.setState({toPersonEmail: e.target.value});
55+
}
56+
57+
handleModeChange(e) {
58+
return this.setState({mode: e.target.value});
59+
}
60+
61+
handleLoginOAuth(e) {
62+
e.preventDefault();
63+
this.setState({authenticate: true});
64+
}
65+
66+
handleOnAuth(token) {
67+
return this.setState({accessToken: token, authenticate: false});
68+
}
69+
70+
71+
createWidget(e) {
72+
e.preventDefault();
73+
return this.setState({running: true});
74+
}
75+
76+
render() {
77+
const loadButtonEnabled = this.state.accessToken && this.state.toPersonEmail;
78+
if (this.state.running) {
79+
return (
80+
<div className={classNames(`widget-component-container`, styles.widgetComponentContainer)}>
81+
<WidgetMessageMeet accessToken={this.state.accessToken} toPersonEmail={this.state.toPersonEmail} />
82+
</div>);
83+
}
84+
return (
85+
<div className={classNames(`demo-wrapper`, styles.demoWrapper)}>
86+
<div className={classNames(`logo`, styles.logo)}>
87+
<SparkLogo />
88+
</div>
89+
<form className={classNames(`demo-form`, styles.demoForm)}>
90+
<div className={classNames(`field-wrapper`, styles.fieldWrapper)}>
91+
<input
92+
className={classNames(`field-input`, styles.fieldInput)}
93+
onChange={this.handleEmailChange}
94+
placeholder="To User Email"
95+
type="text"
96+
value={this.state.toPersonEmail}
97+
/>
98+
</div>
99+
<div className={classNames(`field-wrapper`, styles.fieldWrapper)}>
100+
<input
101+
className={classNames(`field-input`, styles.fieldInput)}
102+
onChange={this.handleAccessTokenChange}
103+
placeholder="Your Access Token"
104+
type="text"
105+
value={this.state.accessToken}
106+
/>
107+
</div>
108+
<div className={classNames(`field-wrapper`, styles.fieldWrapper)}>
109+
<button
110+
className={classNames(`button-small`, styles.buttonSmall)}
111+
onClick={this.handleLoginOAuth}
112+
>
113+
{`Login with Spark`}
114+
</button>
115+
</div>
116+
<div className={classNames(`field-wrapper`, styles.fieldWrapper)}>
117+
<a href="http://developer.ciscospark.com">{`Get access token from developer.ciscospark.com`}</a>
118+
</div>
119+
<div className={classNames(`field-wrapper`, styles.fieldWrapper)}>
120+
<div className={classNames(`radio-group`, styles.radioGroup)}>
121+
<div className={classNames(`radio-item`, styles.radioItem)}>
122+
<input
123+
checked={this.state.mode === MODE_INLINE}
124+
id="radio_inline"
125+
onChange={this.handleModeChange}
126+
type="radio"
127+
value={MODE_INLINE}
128+
/>
129+
<label htmlFor="radio_inline">
130+
{`Inline Mode`}
131+
</label>
132+
</div>
133+
<div className={classNames(`radio-item`, styles.radioItem)}>
134+
<input
135+
checked={this.state.mode === MODE_REACT}
136+
id="radio_react"
137+
onChange={this.handleModeChange}
138+
type="radio"
139+
value={MODE_REACT}
140+
/>
141+
<label htmlFor="radio_react">
142+
{`React Component`}
143+
</label>
144+
</div>
145+
</div>
146+
</div>
147+
<div className={classNames(`example-code`, styles.exampleCode)}>
148+
<ExampleCode accessToken={this.state.accessToken} toPersonEmail={this.state.toPersonEmail} type={this.state.mode} />
149+
</div>
150+
<button
151+
className={classNames(`button`, styles.button)}
152+
disabled={!loadButtonEnabled}
153+
onClick={this.handleSubmit}
154+
>
155+
{`Load Widget`}
156+
</button>
157+
<SparkOAuth
158+
clientId={this.state.clientId}
159+
clientSecret={this.state.clientSecret}
160+
doAuth={this.state.authenticate}
161+
onAuth={this.handleOnAuth}
162+
redirectUri={this.state.redirectUri}
163+
scope={this.state.scope}
164+
/>
165+
</form>
166+
</div>
167+
);
168+
}
169+
}
170+
171+
DemoWidgetMessageMeet.title = `Widget Message Meet Demo`;
172+
DemoWidgetMessageMeet.path = `/wmm-demo`;
173+
174+
export default DemoWidgetMessageMeet;
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
.demo-wrapper {
2+
max-width: 500px;
3+
margin: 0 auto;
4+
}
5+
6+
.widget-component-container {
7+
position: absolute;
8+
right: 10px;
9+
bottom: 0;
10+
width: 500px;
11+
height: 600px;
12+
}
13+
14+
.widget-component-container > div {
15+
height: 100%;
16+
}
17+
18+
.logo {
19+
width: 30%;
20+
height: 120px;
21+
margin: auto;
22+
}
23+
24+
.demo-form {
25+
display: flex;
26+
padding: 10px;
27+
margin: 0 auto;
28+
font-family: 'CiscoSans TT Light';
29+
background: #fff;
30+
flex-direction: column;
31+
align-items: center;
32+
}
33+
34+
.field-wrapper {
35+
display: block;
36+
padding: 5px;
37+
}
38+
39+
.props-submit {
40+
margin: 0 auto;
41+
}
42+
43+
.field-label,
44+
.field-input {
45+
margin-right: 10px;
46+
}
47+
48+
.field-input {
49+
padding: 4px 5px;
50+
font-family: 'CiscoSans TT Light';
51+
font-size: 20px;
52+
}
53+
54+
.button {
55+
padding: 5px 20px;
56+
font-family: 'CiscoSans TT Light';
57+
font-size: 20px;
58+
color: #fff;
59+
cursor: pointer;
60+
background-color: rgb(0, 112, 210);
61+
border: 0;
62+
border-radius: 20px;
63+
}
64+
65+
.button:disabled {
66+
cursor: default;
67+
background-color: #808080;
68+
}
69+
70+
.button-small {
71+
padding: 2px 10px;
72+
font-family: 'CiscoSans TT Light';
73+
font-size: 12px;
74+
color: #fff;
75+
cursor: pointer;
76+
background-color: rgb(0, 112, 210);
77+
border: 0;
78+
border-radius: 10px;
79+
}
80+
81+
.radio-group {
82+
display: flex;
83+
flex-direction: column;
84+
}
85+
86+
.radio-item {
87+
display: flex;
88+
}
89+
90+
.example-code {
91+
width: 100%;
92+
padding: 5px;
93+
}

src/demo-wrapper/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React from 'react';
22
import {IndexLink, Link} from 'react-router';
33
import DemoHome from '../demo-home';
4+
import DemoWidgetMessageMeet from '../demo-widget-message-meet';
45
import Components from '../components';
56

67
const DemoWrapper = (props) => {
@@ -11,6 +12,7 @@ const DemoWrapper = (props) => {
1112
<ul>
1213
<li><IndexLink to={DemoHome.path}>{DemoHome.title}</IndexLink></li>
1314
<li><Link to={Components.path}>{Components.title}</Link></li>
15+
<li><Link to={DemoWidgetMessageMeet.path}>{DemoWidgetMessageMeet.title}</Link></li>
1416
</ul>
1517
{props.children}
1618
</div>

src/demo.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
11
import React from 'react';
22
import ReactDOM from 'react-dom';
3-
import {Router, Route, IndexRoute, hashHistory} from 'react-router';
3+
import {Router, Route, IndexRoute, browserHistory} from 'react-router';
44

55
import {IntlProvider} from 'react-intl';
66
import messages from './locales/en';
77

88
import DemoWrapper from './demo-wrapper';
9+
import DemoWidgetMessageMeet from './demo-widget-message-meet';
910
import DemoHome from './demo-home';
1011
import Components from './components';
1112

1213
ReactDOM.render(
1314
<IntlProvider locale={`en`} messages={messages}>
14-
<Router history={hashHistory}>
15+
<Router history={browserHistory}>
1516
<Route
1617
component={DemoWrapper}
1718
path="/"
@@ -21,6 +22,10 @@ ReactDOM.render(
2122
component={Components}
2223
path={Components.path}
2324
/>
25+
<Route
26+
component={DemoWidgetMessageMeet}
27+
path={DemoWidgetMessageMeet.path}
28+
/>
2429
</Route>
2530
</Router>
2631
</IntlProvider>,

src/example-code/index.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import React, {PropTypes} from 'react';
2+
3+
import classNames from 'classnames';
4+
5+
import styles from './styles.css';
6+
7+
export const MODE_REACT = `MODE_REACT`;
8+
export const MODE_INLINE = `MODE_INLINE`;
9+
10+
function ExampleCode(props) {
11+
let code;
12+
let label;
13+
if (props.type === MODE_REACT) {
14+
label = `React Component Example`;
15+
code = `<MessageMeetWidget accessToken="${props.accessToken}" toPersonEmail="${props.toPersonEmail}" />`;
16+
}
17+
else if (props.type === MODE_INLINE) {
18+
label = `Inline Container Example`;
19+
code = `<div data-toggle="spark-message-meet" data-access-token="${props.accessToken}" data-to-person-email="${props.toPersonEmail}" />`;
20+
}
21+
return (
22+
<div>
23+
<div className={classNames(`display`, styles.display)}>{label}</div>
24+
<div className={classNames(`code`, styles.code)}>
25+
<pre>
26+
{code}
27+
</pre>
28+
</div>
29+
</div>
30+
);
31+
}
32+
33+
ExampleCode.propTypes = {
34+
accessToken: PropTypes.string,
35+
toPersonEmail: PropTypes.string,
36+
type: PropTypes.string.isRequired
37+
};
38+
39+
ExampleCode.defaultProps = {
40+
accessToken: `YOUR_ACCESS_TOKEN`,
41+
toPersonEmail: `TARGET_USER_EMAIL`
42+
};
43+
44+
export default ExampleCode;

0 commit comments

Comments
 (0)