Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions AppExamples/side-pane-example/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# production
/build

# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local

npm-debug.log*
yarn-debug.log*
yarn-error.log*

package-lock.json
yarn.lock
105 changes: 105 additions & 0 deletions AppExamples/side-pane-example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# Basic ECP explicit mode example with React

## Context

The aim of this application is to show how to use ECP in a React environment. This very simple application only adds an email input field and an "open" button to open an ECP chat window with the given user.
It uses the ECP explicit rendering mode so it can keep ECP up and running in a "master" window even though the actual chat window (child) is not created yet or has been closed. For demo purposes, again, the master window will remain open at the bottom left of the screen to show that this one is not used and is only meant to keep the ECP logic running. Then, everytime the user clicks on the open button, we create a new div that will embed a new child chat with the given user.

## HOWTO

This application has been done in very few steps that we resume below:

- Create the application using the Create React App script (see reference at the end of this file)
- Add the main ECP container in the index.html file so it's always on screen (you can of course hide in a real application):
```HTML
<div class="ecp-main-hidden-frame symphony-ecm" data-ecp-login-popup="true" id="symphony-ecm"></div>
```
- Load the ECP SDK, in index.tsx, before even rendering the React application:
```Typescript
const loadSdk = (
): Promise<void> => {
return new Promise<void>((resolve) => {
const sdkScriptNode = document.createElement('script');
sdkScriptNode.src = `https://${DEFAULT_ORIGIN}/embed/sdk.js`;
sdkScriptNode.id = 'symphony-ecm-sdk';
sdkScriptNode.setAttribute('render', 'explicit');
(window as any).renderRoom = () => {
(window as any).symphony
.render('symphony-ecm', {
// Add initial ECP parameters here
showTitle: false,
ecpLoginPopup: true
}).then(resolve);
};
sdkScriptNode.setAttribute('data-onload', 'renderRoom'); // Will call window.renderRoom once initialized
document.body.appendChild(sdkScriptNode);
});
};

root.render(
<React.StrictMode>
<App chatReady={loadSdk()}/>
</React.StrictMode>
);
```
Here the `loadSdk` function returns a `Promise` that resolves when ECP is ready to be displayed (When the SDK `render` function resolves). This promise is passed to the `App` component as `Props` in case the app want to know when the chat is ready to be displayed. This is not mandatory and we don't use in our App component in this example.
- Add your logic to know when to open the chat, where and with which options (streamId / userIds)
In our case, it's just a simple input and an open button. The input button lets the user enter an email address, the open button opens the side panel containing the chat.
See the details if needed in the `App` component in `App.tsx`.
- The `Chat` component in the `App.tsx` file holds the logic to open the chat:
```Typescript
export interface ChatProps {
userIds: string[];
}

export const Chat = (props: ChatProps) => {
const [chatId, setChatId] = React.useState(`pane-chat-${Date.now()}`);
React.useEffect(() => {
(window as any).symphony.startRoom(props.userIds, `#${chatId}`)
}, [chatId]);
return (
<div className="panel-container">
<h3>Symphony chat with {props.userIds.join(',')}</h3>
<div className="symphony-pane-chat" id={chatId}></div>
</div>
)
}
```
As you can see, the component is very simple. All it does is adding a div to the DOM that will contain the ECP chat window. **ECP will keep track of all the containers you pass it, so if you give ECP an existing container, it will not create the iframe but just update its content**. In our case the container is deleted everytime the panel is closed, so we need to create a unique ID so ECP recreated an iframe everytime we open a panel: `pane-chat` suffixed with the timestamp.
Once our div is ready, all we need to do is to tell ECP to `startRoom` with the given userIds:
```Typescript
window.symphony.startRoom(props.userIds, `#${chatId}`)
```


## Getting Started with Create React App

This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).

### Available Scripts

In the project directory, you can run:

#### `yarn start`

Runs the app in the development mode.\
Open [http://localhost:3000](http://localhost:3000) to view it in the browser.

The page will reload if you make edits.\
You will also see any lint errors in the console.

#### `yarn build`

Builds the app for production to the `build` folder.\
It correctly bundles React in production mode and optimizes the build for the best performance.

The build is minified and the filenames include the hashes.\
Your app is ready to be deployed!

See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.

### Learn More

You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).

To learn React, check out the [React documentation](https://reactjs.org/).
44 changes: 44 additions & 0 deletions AppExamples/side-pane-example/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
"name": "side-pane-example",
"version": "0.1.0",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"@types/jest": "^27.5.2",
"@types/node": "^16.18.3",
"@types/react": "^18.0.25",
"@types/react-dom": "^18.0.9",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1",
"react-side-pane": "^2.4.6",
"typescript": "^4.9.3",
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
Binary file added AppExamples/side-pane-example/public/favicon.ico
Binary file not shown.
44 changes: 44 additions & 0 deletions AppExamples/side-pane-example/public/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.

Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<div class="ecp-main-hidden-frame symphony-ecm" data-ecp-login-popup="true" id="symphony-ecm"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.

You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.

To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>
Binary file added AppExamples/side-pane-example/public/logo192.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added AppExamples/side-pane-example/public/logo512.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
25 changes: 25 additions & 0 deletions AppExamples/side-pane-example/public/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"short_name": "React App",
"name": "Create React App Sample",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "logo192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "logo512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}
3 changes: 3 additions & 0 deletions AppExamples/side-pane-example/public/robots.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:
50 changes: 50 additions & 0 deletions AppExamples/side-pane-example/src/App.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
.App {
text-align: center;
}

.App-logo {
height: 40vmin;
pointer-events: none;
}

@media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-spin infinite 20s linear;
}
}

.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}

.App-link {
color: #61dafb;
}

@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}

.symphony-pane-chat {
height: 100%;
flex: 1;
}

.panel-container {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
}
60 changes: 60 additions & 0 deletions AppExamples/side-pane-example/src/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import React from 'react';
import logo from './logo.svg';
import './App.css';
import { SidePane } from "react-side-pane";

export interface AppProps {
chatReady: Promise<any>;
}

export const App = (props: AppProps) => {
const [open, dispatchOpen] = React.useReducer((_open) => !_open, false);
const [name, setName] = React.useState('');
const handleNameChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setName(event.target.value)
}
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.tsx</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
<input type="text" value={name} onChange={handleNameChange}/>
<button onClick={dispatchOpen}>Open pane</button>
</header>
<SidePane open={open} width={33} onClose={dispatchOpen}>
<>
<Chat userIds={[name]}></Chat>
</>
</SidePane>
</div>
);
}

export interface ChatProps {
userIds: string[];
}

export const Chat = (props: ChatProps) => {
const [chatId, setChatId] = React.useState(`pane-chat-${Date.now()}`);
React.useEffect(() => {
(window as any).symphony.startRoom(props.userIds, `#${chatId}`)
}, [chatId]);
return (
<div className="panel-container">
<h3>Symphony chat with {props.userIds.join(',')}</h3>
<div className="symphony-pane-chat" id={chatId}></div>
</div>
)
}

export default App;
22 changes: 22 additions & 0 deletions AppExamples/side-pane-example/src/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}

code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
}


.ecp-main-hidden-frame {
position: fixed;
height: 33vh;
left: 0px;
bottom: 0;
width: 33vw;
}
Loading