-
Notifications
You must be signed in to change notification settings - Fork 3
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
17 changed files
with
401 additions
and
2 deletions.
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 |
---|---|---|
@@ -1,2 +1,50 @@ | ||
# flex-plugin-ts | ||
A base TypeScript template for Flex Plugins | ||
# Your custom Twilio Flex Plugin | ||
|
||
Twilio Flex Plugins allow you to customize the appearance and behavior of [Twilio Flex](https://www.twilio.com/flex). If you want to learn more about the capabilities and how to use the API, check out our [Flex documentation](https://www.twilio.com/docs/flex). | ||
|
||
## Setup | ||
|
||
Make sure you have [Node.js](https://nodejs.org) as well as [`npm`](https://npmjs.com) installed. | ||
|
||
Afterwards, install the dependencies by running `npm install`: | ||
|
||
```bash | ||
cd {{pluginFileName}} | ||
|
||
# If you use npm | ||
npm install | ||
``` | ||
|
||
## Development | ||
|
||
In order to develop locally, you can use the Webpack Dev Server by running: | ||
|
||
```bash | ||
npm start | ||
``` | ||
|
||
This will automatically start up the Webpack Dev Server and open the browser for you. Your app will run on `http://localhost:3000`. If you want to change that you can do this by setting the `PORT` environment variable: | ||
|
||
```bash | ||
PORT=3001 npm start | ||
``` | ||
|
||
When you make changes to your code, the browser window will be automatically refreshed. | ||
|
||
## Deploy | ||
|
||
When you are ready to deploy your plugin, in your terminal run: | ||
|
||
```bash | ||
npm run deploy | ||
``` | ||
|
||
This will publish your plugin as a Private Asset that is accessible by the Functions & Assets API. If you want to deploy your plugin as a Public Asset, you may pass --public to your deploy command: | ||
|
||
```bash | ||
npm run deploy --public | ||
``` | ||
|
||
For more details on deploying your plugin, refer to the [deploying your plugin guide](https://www.twilio.com/docs/flex/plugins#deploying-your-plugin). | ||
|
||
Note: Common packages like `React`, `ReactDOM`, `Redux` and `ReactRedux` are not bundled with the build because they are treated as external dependencies so the plugin will depend on Flex to provide them globally. |
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,12 @@ | ||
const config = require('craco-config-flex-plugin'); | ||
|
||
module.exports = { | ||
...config, | ||
plugins: [ | ||
// Customize app configuration (such as webpack, devServer, linter, etc) by creating a Craco plugin. | ||
// See https://github.com/sharegate/craco/tree/master/packages/craco#develop-a-plugin for more detail. | ||
// | ||
// Please note that Craco plugins have nothing to do with Flex plugins; it's just a naming coincidence. | ||
// Changes to this file are optional, you will not need to modify it for normal Flex Plugin development. | ||
] | ||
}; |
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,56 @@ | ||
{ | ||
"name": "{{name}}", | ||
"version": "0.0.0", | ||
"private": true, | ||
"scripts": { | ||
"bootstrap": "flex-plugin check-start", | ||
"prebuild": "rimraf build && npm run bootstrap", | ||
"build": "flex-plugin build", | ||
"clear": "flex-plugin clear", | ||
"predeploy": "npm run build", | ||
"deploy": "flex-plugin deploy", | ||
"eject": "flex-plugin eject", | ||
"info": "flex-plugin info", | ||
"postinstall": "npm run bootstrap", | ||
"list": "flex-plugin list", | ||
"remove": "flex-plugin remove", | ||
"prestart": "npm run bootstrap", | ||
"start": "flex-plugin start", | ||
"test": "flex-plugin test --env=jsdom" | ||
}, | ||
"dependencies": { | ||
"craco-config-flex-plugin": "^3", | ||
"flex-plugin": "^3", | ||
"flex-plugin-scripts": "^3", | ||
"react": "16.5.2", | ||
"react-dom": "16.5.2", | ||
"react-emotion": "9.2.6", | ||
"react-scripts": "3.4.1", | ||
"typescript": "^3.6.4" | ||
}, | ||
"devDependencies": { | ||
"@twilio/flex-ui": "^1", | ||
"@types/enzyme": "^3.10.3", | ||
"@types/jest": "^24.0.18", | ||
"@types/node": "^12.7.12", | ||
"@types/react": "^16.8.16", | ||
"@types/react-dom": "^16.8.4", | ||
"@types/react-redux": "^7.1.1", | ||
"babel-polyfill": "^6.26.0", | ||
"enzyme": "^3.10.0", | ||
"enzyme-adapter-react-16": "^1.14.0", | ||
"rimraf": "^3.0.0" | ||
}, | ||
"browserslist": { | ||
"production": [ | ||
">0.2%", | ||
"not dead", | ||
"not op_mini all" | ||
], | ||
"development": [ | ||
"last 1 chrome version", | ||
"last 1 firefox version", | ||
"last 1 safari version" | ||
] | ||
} | ||
} |
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,20 @@ | ||
// your account sid | ||
var accountSid = 'accountSid'; | ||
|
||
// set to /plugins.json for local dev | ||
// set to /plugins.local.build.json for testing your build | ||
// set to "" for the default live plugin loader | ||
var pluginServiceUrl = '/plugins.json'; | ||
|
||
var appConfig = { | ||
pluginService: { | ||
enabled: true, | ||
url: pluginServiceUrl, | ||
}, | ||
sso: { | ||
accountSid: accountSid | ||
}, | ||
ytica: false, | ||
logLevel: 'debug', | ||
showSupervisorDesktopView: true, | ||
}; |
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,18 @@ | ||
// your account sid | ||
var accountSid = '{{accountSid}}'; | ||
|
||
// set to /plugins.json for local dev | ||
// set to /plugins.local.build.json for testing your build | ||
// set to "" for the default live plugin loader | ||
var pluginServiceUrl = '/plugins.json'; | ||
|
||
var appConfig = { | ||
pluginService: { | ||
enabled: true, | ||
url: pluginServiceUrl, | ||
}, | ||
sso: { | ||
accountSid: accountSid | ||
}, | ||
logLevel: 'debug', | ||
}; |
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 @@ | ||
{{pluginJsonContent}} |
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,13 @@ | ||
[ | ||
{ | ||
"name": "{{pluginClassName}}", | ||
"version": "0.0.0", | ||
"class": "{{pluginClassName}}", | ||
"requires": [ | ||
{ | ||
"@twilio/flex-ui": "{{flexSdkVersion}}" | ||
} | ||
], | ||
"src": "http://127.0.0.1:8085" | ||
} | ||
] |
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,46 @@ | ||
import React from 'react'; | ||
import * as Flex from '@twilio/flex-ui'; | ||
import { FlexPlugin } from 'flex-plugin'; | ||
|
||
import CustomTaskListContainer from './components/CustomTaskList/CustomTaskList.Container'; | ||
import reducers, { namespace } from './states'; | ||
|
||
const PLUGIN_NAME = '{{pluginClassName}}'; | ||
|
||
export default class {{pluginClassName}} extends FlexPlugin { | ||
constructor() { | ||
super(PLUGIN_NAME); | ||
} | ||
|
||
/** | ||
* This code is run when your plugin is being started | ||
* Use this to modify any UI components or attach to the actions framework | ||
* | ||
* @param flex { typeof Flex } | ||
* @param manager { Flex.Manager } | ||
*/ | ||
init(flex: typeof Flex, manager: Flex.Manager) { | ||
this.registerReducers(manager); | ||
|
||
const options: Flex.ContentFragmentProps = { sortOrder: -1 }; | ||
flex.AgentDesktopView | ||
.Panel1 | ||
.Content | ||
.add(<CustomTaskListContainer key="demo-component" />, options); | ||
} | ||
|
||
/** | ||
* Registers the plugin reducers | ||
* | ||
* @param manager { Flex.Manager } | ||
*/ | ||
private registerReducers(manager: Flex.Manager) { | ||
if (!manager.store.addReducer) { | ||
// tslint: disable-next-line | ||
console.error(`You need FlexUI > 1.9.0 to use built-in redux; you are currently on ${Flex.VERSION}`); | ||
return; | ||
} | ||
|
||
manager.store.addReducer(namespace, reducers); | ||
} | ||
} |
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,24 @@ | ||
import { AppState } from '../../states'; | ||
import { connect } from 'react-redux'; | ||
import { bindActionCreators, Dispatch } from 'redux'; | ||
|
||
import { Actions } from '../../states/CustomTaskListState'; | ||
import CustomTaskList from './CustomTaskList'; | ||
|
||
export interface StateToProps { | ||
isOpen: boolean; | ||
} | ||
|
||
export interface DispatchToProps { | ||
dismissBar: () => void; | ||
} | ||
|
||
const mapStateToProps = (state: AppState): StateToProps => ({ | ||
isOpen: state['{{pluginNamespace}}'].customTaskList.isOpen, | ||
}); | ||
|
||
const mapDispatchToProps = (dispatch: Dispatch<any>): DispatchToProps => ({ | ||
dismissBar: bindActionCreators(Actions.dismissBar, dispatch), | ||
}); | ||
|
||
export default connect(mapStateToProps, mapDispatchToProps)(CustomTaskList); |
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,14 @@ | ||
import { default as styled } from 'react-emotion'; | ||
|
||
export const CustomTaskListComponentStyles = styled('div')` | ||
padding: 10px; | ||
margin: 0px; | ||
color: #fff; | ||
background: #000; | ||
.accented { | ||
color: red; | ||
cursor: pointer; | ||
float: right; | ||
} | ||
`; |
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,29 @@ | ||
import React from 'react'; | ||
|
||
import { CustomTaskListComponentStyles } from './CustomTaskList.Styles'; | ||
import { StateToProps, DispatchToProps } from './CustomTaskList.Container'; | ||
|
||
interface OwnProps { | ||
// Props passed directly to the component | ||
} | ||
|
||
// Props should be a combination of StateToProps, DispatchToProps, and OwnProps | ||
type Props = StateToProps & DispatchToProps & OwnProps; | ||
|
||
// It is recommended to keep components stateless and use redux for managing states | ||
const CustomTaskList = (props: Props) => { | ||
if (!props.isOpen) { | ||
return null; | ||
} | ||
|
||
return ( | ||
<CustomTaskListComponentStyles> | ||
This is a dismissible demo component | ||
<i className="accented" onClick={props.dismissBar}> | ||
close | ||
</i> | ||
</CustomTaskListComponentStyles> | ||
); | ||
}; | ||
|
||
export default CustomTaskList; |
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 @@ | ||
import React from 'react'; | ||
import { shallow } from 'enzyme'; | ||
|
||
import CustomTaskList from '../CustomTaskList/CustomTaskList'; | ||
|
||
describe('CustomTaskListComponent', () => { | ||
it('should render demo component', () => { | ||
const props = { | ||
isOpen: true, | ||
dismissBar: () => undefined, | ||
}; | ||
const wrapper = shallow(<CustomTaskList {...props}/>); | ||
expect(wrapper.render().text()).toMatch('This is a dismissible demo component'); | ||
}); | ||
}); |
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,4 @@ | ||
import * as FlexPlugin from 'flex-plugin'; | ||
import {{pluginClassName}} from './{{pluginClassName}}'; | ||
|
||
FlexPlugin.loadPlugin({{pluginClassName}}); |
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,8 @@ | ||
require('babel-polyfill'); | ||
|
||
import { configure } from 'enzyme/build'; | ||
import Adapter from 'enzyme-adapter-react-16/build'; | ||
|
||
configure({ | ||
adapter: new Adapter(), | ||
}); |
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,29 @@ | ||
import { Action } from './index'; | ||
|
||
const ACTION_DISMISS_BAR = 'DISMISS_BAR'; | ||
|
||
export interface CustomTaskListState { | ||
isOpen: boolean; | ||
} | ||
|
||
const initialState: CustomTaskListState = { | ||
isOpen: true, | ||
}; | ||
|
||
export class Actions { | ||
public static dismissBar = (): Action => ({ type: ACTION_DISMISS_BAR }); | ||
} | ||
|
||
export function reduce(state: CustomTaskListState = initialState, action: Action) { | ||
switch (action.type) { | ||
case ACTION_DISMISS_BAR: { | ||
return { | ||
...state, | ||
isOpen: false, | ||
}; | ||
} | ||
|
||
default: | ||
return state; | ||
} | ||
} |
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,26 @@ | ||
import { AppState as FlexAppState } from '@twilio/flex-ui'; | ||
import { combineReducers, Action as ReduxAction } from 'redux'; | ||
|
||
import { CustomTaskListState, reduce as CustomTaskListReducer } from './CustomTaskListState'; | ||
|
||
// Register your redux store under a unique namespace | ||
export const namespace = '{{pluginNamespace}}'; | ||
|
||
// Extend this payload to be of type that your ReduxAction is | ||
export interface Action extends ReduxAction { | ||
payload?: any; | ||
} | ||
|
||
// Register all component states under the namespace | ||
export interface AppState { | ||
flex: FlexAppState; | ||
'{{pluginNamespace}}': { | ||
customTaskList: CustomTaskListState; | ||
// Other states | ||
}; | ||
} | ||
|
||
// Combine the reducers | ||
export default combineReducers({ | ||
customTaskList: CustomTaskListReducer | ||
}); |
Oops, something went wrong.