@twilio/create-flex-plugin 5.0.1-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +132 -0
- package/bin/create-flex-plugin +10 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/cli.d.ts +26 -0
- package/dist/lib/cli.js +128 -0
- package/dist/lib/cli.js.map +1 -0
- package/dist/lib/commands.d.ts +22 -0
- package/dist/lib/commands.js +128 -0
- package/dist/lib/commands.js.map +1 -0
- package/dist/lib/create-flex-plugin.d.ts +28 -0
- package/dist/lib/create-flex-plugin.js +176 -0
- package/dist/lib/create-flex-plugin.js.map +1 -0
- package/dist/prints/finalMessage.d.ts +7 -0
- package/dist/prints/finalMessage.js +20 -0
- package/dist/prints/finalMessage.js.map +1 -0
- package/dist/utils/github.d.ts +77 -0
- package/dist/utils/github.js +222 -0
- package/dist/utils/github.js.map +1 -0
- package/dist/utils/validators.d.ts +19 -0
- package/dist/utils/validators.js +103 -0
- package/dist/utils/validators.js.map +1 -0
- package/package.json +58 -0
- package/templates/core/README.md +31 -0
- package/templates/core/_.gitignore +66 -0
- package/templates/core/jest.config.js +8 -0
- package/templates/core/public/appConfig.example.js +9 -0
- package/templates/core/public/appConfig.js +7 -0
- package/templates/core/webpack.config.js +8 -0
- package/templates/core/webpack.dev.js +8 -0
- package/templates/js/package.json +18 -0
- package/templates/js/src/DemoPlugin.js +43 -0
- package/templates/js/src/components/CustomTaskList/CustomTaskList.Container.js +15 -0
- package/templates/js/src/components/CustomTaskList/CustomTaskList.Styles.js +14 -0
- package/templates/js/src/components/CustomTaskList/CustomTaskList.jsx +29 -0
- package/templates/js/src/components/__tests__/CustomTaskListComponent.spec.jsx +15 -0
- package/templates/js/src/index.js +5 -0
- package/templates/js/src/states/CustomTaskListState.js +24 -0
- package/templates/js/src/states/index.js +11 -0
- package/templates/ts/package.json +19 -0
- package/templates/ts/src/DemoPlugin.tsx +43 -0
- package/templates/ts/src/components/CustomTaskList/CustomTaskList.Container.ts +24 -0
- package/templates/ts/src/components/CustomTaskList/CustomTaskList.Styles.ts +14 -0
- package/templates/ts/src/components/CustomTaskList/CustomTaskList.tsx +31 -0
- package/templates/ts/src/components/__tests__/CustomTaskListComponent.spec.tsx +15 -0
- package/templates/ts/src/index.ts +5 -0
- package/templates/ts/src/states/CustomTaskListState.ts +30 -0
- package/templates/ts/src/states/index.ts +26 -0
- package/templates/ts/tsconfig.json +36 -0
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@twilio/create-flex-plugin",
|
|
3
|
+
"version": "5.0.1-beta.0",
|
|
4
|
+
"description": "Toolkit to create a new Twilio Flex plugin",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"flex",
|
|
7
|
+
"plugin",
|
|
8
|
+
"twilio"
|
|
9
|
+
],
|
|
10
|
+
"homepage": "https://github.com/twilio/flex-plugin-builder",
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/twilio/flex-plugin-builder/issues"
|
|
13
|
+
},
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "git+https://github.com/twilio/flex-plugin-builder.git"
|
|
17
|
+
},
|
|
18
|
+
"license": "MIT",
|
|
19
|
+
"author": "Flex Runtime <flex-runtime@twilio.com>",
|
|
20
|
+
"main": "dist/index.js",
|
|
21
|
+
"types": "dist/index.d.ts",
|
|
22
|
+
"bin": {
|
|
23
|
+
"create-flex-plugin": "bin/create-flex-plugin"
|
|
24
|
+
},
|
|
25
|
+
"directories": {
|
|
26
|
+
"lib": "src",
|
|
27
|
+
"bin": "bin",
|
|
28
|
+
"test": "__tests__"
|
|
29
|
+
},
|
|
30
|
+
"files": [
|
|
31
|
+
"bin",
|
|
32
|
+
"dist",
|
|
33
|
+
"templates"
|
|
34
|
+
],
|
|
35
|
+
"scripts": {
|
|
36
|
+
"prebuild": "npm run clean",
|
|
37
|
+
"build": "cd ../.. && tsc -p \"packages/create-flex-plugin/tsconfig.json\"",
|
|
38
|
+
"clean": "rm -rf dist",
|
|
39
|
+
"lint": "eslint --ext ts src/",
|
|
40
|
+
"lint:fix": "npm run lint -- --fix",
|
|
41
|
+
"test": "cd ../.. && jest packages/create-flex-plugin --color",
|
|
42
|
+
"test:watch": "cd ../.. && jest packages/create-flex-plugin --watch --color"
|
|
43
|
+
},
|
|
44
|
+
"dependencies": {
|
|
45
|
+
"@twilio/flex-dev-utils": "5.0.1-beta.0",
|
|
46
|
+
"esm": "^3.2.25",
|
|
47
|
+
"tmp": "^0.2.1",
|
|
48
|
+
"yargs": "^16.2.0"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@twilio/flex-plugin": "5.0.1-beta.0",
|
|
52
|
+
"@twilio/flex-plugin-scripts": "5.0.1-beta.0",
|
|
53
|
+
"@twilio/flex-ui": "^1",
|
|
54
|
+
"@types/tmp": "^0.2.1",
|
|
55
|
+
"@types/yargs": "^16.0.4"
|
|
56
|
+
},
|
|
57
|
+
"gitHead": "571e0bacce5ffa6b790362a9f9b9968fe095e3e8"
|
|
58
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Your custom Twilio Flex Plugin
|
|
2
|
+
|
|
3
|
+
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).
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
Make sure you have [Node.js](https://nodejs.org) as well as [`npm`](https://npmjs.com). We support Node >= 10.12 (and recommend the _even_ versions of Node). Afterwards, install the dependencies by running `npm install`:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
cd {{pluginFileName}}
|
|
11
|
+
|
|
12
|
+
# If you use npm
|
|
13
|
+
npm install
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Next, please install the [Twilio CLI](https://www.twilio.com/docs/twilio-cli/quickstart) by running:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
brew tap twilio/brew && brew install twilio
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Finally, install the [Flex Plugin extension](https://github.com/twilio-labs/plugin-flex/tree/v1-beta) for the Twilio CLI:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
twilio plugins:install @twilio-labs/plugin-flex
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Development
|
|
29
|
+
|
|
30
|
+
Run `twilio flex:plugins --help` to see all the commands we currently support. For further details on Flex Plugins refer to our documentation on the [Twilio Docs](https://www.twilio.com/docs/flex/developer/plugins/cli) page.
|
|
31
|
+
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# Logs
|
|
2
|
+
logs
|
|
3
|
+
*.log
|
|
4
|
+
npm-debug.log*
|
|
5
|
+
yarn-debug.log*
|
|
6
|
+
yarn-error.log*
|
|
7
|
+
|
|
8
|
+
# Runtime data
|
|
9
|
+
pids
|
|
10
|
+
*.pid
|
|
11
|
+
*.seed
|
|
12
|
+
*.pid.lock
|
|
13
|
+
|
|
14
|
+
# Directory for instrumented libs generated by jscoverage/JSCover
|
|
15
|
+
lib-cov
|
|
16
|
+
|
|
17
|
+
# Coverage directory used by tools like istanbul
|
|
18
|
+
coverage
|
|
19
|
+
|
|
20
|
+
# nyc test coverage
|
|
21
|
+
.nyc_output
|
|
22
|
+
|
|
23
|
+
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
|
|
24
|
+
.grunt
|
|
25
|
+
|
|
26
|
+
# Bower dependency directory (https://bower.io/)
|
|
27
|
+
bower_components
|
|
28
|
+
|
|
29
|
+
# node-waf configuration
|
|
30
|
+
.lock-wscript
|
|
31
|
+
|
|
32
|
+
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
|
33
|
+
build/Release
|
|
34
|
+
|
|
35
|
+
# Dependency directories
|
|
36
|
+
node_modules/
|
|
37
|
+
jspm_packages/
|
|
38
|
+
|
|
39
|
+
# TypeScript v1 declaration files
|
|
40
|
+
typings/
|
|
41
|
+
|
|
42
|
+
# Optional npm cache directory
|
|
43
|
+
.npm
|
|
44
|
+
|
|
45
|
+
# Optional eslint cache
|
|
46
|
+
.eslintcache
|
|
47
|
+
|
|
48
|
+
# Optional REPL history
|
|
49
|
+
.node_repl_history
|
|
50
|
+
|
|
51
|
+
# Output of 'npm pack'
|
|
52
|
+
*.tgz
|
|
53
|
+
|
|
54
|
+
# Yarn Integrity file
|
|
55
|
+
.yarn-integrity
|
|
56
|
+
|
|
57
|
+
# dotenv environment variables file
|
|
58
|
+
.env
|
|
59
|
+
|
|
60
|
+
# next.js build output
|
|
61
|
+
.next
|
|
62
|
+
|
|
63
|
+
# Flex related ignore
|
|
64
|
+
appConfig.js
|
|
65
|
+
pluginsService.js
|
|
66
|
+
build/
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{name}}",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"scripts": {
|
|
6
|
+
"postinstall": "flex-plugin pre-script-check"
|
|
7
|
+
},
|
|
8
|
+
"dependencies": {
|
|
9
|
+
"@twilio/flex-plugin-scripts": "{{pluginScriptsVersion}}",
|
|
10
|
+
"react": "16.5.2",
|
|
11
|
+
"react-dom": "16.5.2",
|
|
12
|
+
"react-emotion": "9.2.12"
|
|
13
|
+
},
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"@twilio/flex-ui": "{{flexSdkVersion}}",
|
|
16
|
+
"react-test-renderer": "16.5.2"
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { VERSION } from '@twilio/flex-ui';
|
|
3
|
+
import { FlexPlugin } from '@twilio/flex-plugin';
|
|
4
|
+
|
|
5
|
+
import CustomTaskListContainer from './components/CustomTaskList/CustomTaskList.Container';
|
|
6
|
+
import reducers, { namespace } from './states';
|
|
7
|
+
|
|
8
|
+
const PLUGIN_NAME = '{{pluginClassName}}';
|
|
9
|
+
|
|
10
|
+
export default class {{pluginClassName}} extends FlexPlugin {
|
|
11
|
+
constructor() {
|
|
12
|
+
super(PLUGIN_NAME);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* This code is run when your plugin is being started
|
|
17
|
+
* Use this to modify any UI components or attach to the actions framework
|
|
18
|
+
*
|
|
19
|
+
* @param flex { typeof import('@twilio/flex-ui') }
|
|
20
|
+
* @param manager { import('@twilio/flex-ui').Manager }
|
|
21
|
+
*/
|
|
22
|
+
async init(flex, manager) {
|
|
23
|
+
this.registerReducers(manager);
|
|
24
|
+
|
|
25
|
+
const options = { sortOrder: -1 };
|
|
26
|
+
flex.AgentDesktopView.Panel1.Content.add(<CustomTaskListContainer key="{{pluginClassName}}-component" />, options);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Registers the plugin reducers
|
|
31
|
+
*
|
|
32
|
+
* @param manager { Flex.Manager }
|
|
33
|
+
*/
|
|
34
|
+
registerReducers(manager) {
|
|
35
|
+
if (!manager.store.addReducer) {
|
|
36
|
+
// eslint-disable-next-line
|
|
37
|
+
console.error(`You need FlexUI > 1.9.0 to use built-in redux; you are currently on ${VERSION}`);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
manager.store.addReducer(namespace, reducers);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { connect } from 'react-redux';
|
|
2
|
+
import { bindActionCreators } from 'redux';
|
|
3
|
+
|
|
4
|
+
import { Actions } from '../../states/CustomTaskListState';
|
|
5
|
+
import CustomTaskList from './CustomTaskList';
|
|
6
|
+
|
|
7
|
+
const mapStateToProps = (state) => ({
|
|
8
|
+
isOpen: state['{{pluginNamespace}}'].customTaskList.isOpen,
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
const mapDispatchToProps = (dispatch) => ({
|
|
12
|
+
dismissBar: bindActionCreators(Actions.dismissBar, dispatch),
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
export default connect(mapStateToProps, mapDispatchToProps)(CustomTaskList);
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
|
|
4
|
+
import { CustomTaskListComponentStyles } from './CustomTaskList.Styles';
|
|
5
|
+
|
|
6
|
+
// It is recommended to keep components stateless and use redux for managing states
|
|
7
|
+
const CustomTaskList = (props) => {
|
|
8
|
+
if (!props.isOpen) {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
return (
|
|
13
|
+
<CustomTaskListComponentStyles>
|
|
14
|
+
This is a dismissible demo component
|
|
15
|
+
<i className="accented" onClick={props.dismissBar} aria-hidden="true">
|
|
16
|
+
close
|
|
17
|
+
</i>
|
|
18
|
+
</CustomTaskListComponentStyles>
|
|
19
|
+
);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
CustomTaskList.displayName = 'CustomTaskList';
|
|
23
|
+
|
|
24
|
+
CustomTaskList.propTypes = {
|
|
25
|
+
isOpen: PropTypes.bool.isRequired,
|
|
26
|
+
dismissBar: PropTypes.func.isRequired,
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export default CustomTaskList;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { shallow } from 'enzyme';
|
|
3
|
+
|
|
4
|
+
import CustomTaskList from '../CustomTaskList/CustomTaskList';
|
|
5
|
+
|
|
6
|
+
describe('CustomTaskListComponent', () => {
|
|
7
|
+
it('should render demo component', () => {
|
|
8
|
+
const props = {
|
|
9
|
+
isOpen: true,
|
|
10
|
+
dismissBar: () => undefined,
|
|
11
|
+
};
|
|
12
|
+
const wrapper = shallow(<CustomTaskList {...props} />);
|
|
13
|
+
expect(wrapper.render().text()).toMatch('This is a dismissible demo component');
|
|
14
|
+
});
|
|
15
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
const ACTION_DISMISS_BAR = 'DISMISS_BAR';
|
|
2
|
+
|
|
3
|
+
const initialState = {
|
|
4
|
+
isOpen: true,
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
export class Actions {
|
|
8
|
+
static dismissBar = () => ({ type: ACTION_DISMISS_BAR });
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function reduce(state = initialState, action) {
|
|
12
|
+
// eslint-disable-next-line sonarjs/no-small-switch
|
|
13
|
+
switch (action.type) {
|
|
14
|
+
case ACTION_DISMISS_BAR: {
|
|
15
|
+
return {
|
|
16
|
+
...state,
|
|
17
|
+
isOpen: false,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
default:
|
|
22
|
+
return state;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { combineReducers } from 'redux';
|
|
2
|
+
|
|
3
|
+
import { reduce as CustomTaskListReducer } from './CustomTaskListState';
|
|
4
|
+
|
|
5
|
+
// Register your redux store under a unique namespace
|
|
6
|
+
export const namespace = '{{pluginNamespace}}';
|
|
7
|
+
|
|
8
|
+
// Combine the reducers
|
|
9
|
+
export default combineReducers({
|
|
10
|
+
customTaskList: CustomTaskListReducer,
|
|
11
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{name}}",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"scripts": {
|
|
6
|
+
"postinstall": "flex-plugin pre-script-check"
|
|
7
|
+
},
|
|
8
|
+
"dependencies": {
|
|
9
|
+
"@twilio/flex-plugin-scripts": "{{pluginScriptsVersion}}",
|
|
10
|
+
"react": "16.5.2",
|
|
11
|
+
"react-dom": "16.5.2",
|
|
12
|
+
"react-emotion": "9.2.12"
|
|
13
|
+
},
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"@twilio/flex-ui": "{{flexSdkVersion}}",
|
|
16
|
+
"react-test-renderer": "16.5.2",
|
|
17
|
+
"typescript": "^4"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import * as Flex from '@twilio/flex-ui';
|
|
3
|
+
import { FlexPlugin } from '@twilio/flex-plugin';
|
|
4
|
+
|
|
5
|
+
import CustomTaskListContainer from './components/CustomTaskList/CustomTaskList.Container';
|
|
6
|
+
import reducers, { namespace } from './states';
|
|
7
|
+
|
|
8
|
+
const PLUGIN_NAME = '{{pluginClassName}}';
|
|
9
|
+
|
|
10
|
+
export default class {{pluginClassName}} extends FlexPlugin {
|
|
11
|
+
constructor() {
|
|
12
|
+
super(PLUGIN_NAME);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* This code is run when your plugin is being started
|
|
17
|
+
* Use this to modify any UI components or attach to the actions framework
|
|
18
|
+
*
|
|
19
|
+
* @param flex { typeof Flex }
|
|
20
|
+
* @param manager { Flex.Manager }
|
|
21
|
+
*/
|
|
22
|
+
async init(flex: typeof Flex, manager: Flex.Manager): Promise<void> {
|
|
23
|
+
this.registerReducers(manager);
|
|
24
|
+
|
|
25
|
+
const options: Flex.ContentFragmentProps = { sortOrder: -1 };
|
|
26
|
+
flex.AgentDesktopView.Panel1.Content.add(<CustomTaskListContainer key="{{pluginClassName}}-component" />, options);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Registers the plugin reducers
|
|
31
|
+
*
|
|
32
|
+
* @param manager { Flex.Manager }
|
|
33
|
+
*/
|
|
34
|
+
private registerReducers(manager: Flex.Manager) {
|
|
35
|
+
if (!manager.store.addReducer) {
|
|
36
|
+
// eslint-disable-next-line
|
|
37
|
+
console.error(`You need FlexUI > 1.9.0 to use built-in redux; you are currently on ${Flex.VERSION}`);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
manager.store.addReducer(namespace, reducers);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { connect } from 'react-redux';
|
|
2
|
+
import { bindActionCreators, Dispatch } from 'redux';
|
|
3
|
+
|
|
4
|
+
import { AppState } from '../../states';
|
|
5
|
+
import { Actions } from '../../states/CustomTaskListState';
|
|
6
|
+
import CustomTaskList from './CustomTaskList';
|
|
7
|
+
|
|
8
|
+
export interface StateToProps {
|
|
9
|
+
isOpen: boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface DispatchToProps {
|
|
13
|
+
dismissBar: () => void;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const mapStateToProps = (state: AppState): StateToProps => ({
|
|
17
|
+
isOpen: state['{{pluginNamespace}}'].customTaskList.isOpen,
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const mapDispatchToProps = (dispatch: Dispatch<any>): DispatchToProps => ({
|
|
21
|
+
dismissBar: bindActionCreators(Actions.dismissBar, dispatch),
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
export default connect(mapStateToProps, mapDispatchToProps)(CustomTaskList);
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import { CustomTaskListComponentStyles } from './CustomTaskList.Styles';
|
|
4
|
+
import { StateToProps, DispatchToProps } from './CustomTaskList.Container';
|
|
5
|
+
|
|
6
|
+
interface OwnProps {
|
|
7
|
+
// Props passed directly to the component
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// Props should be a combination of StateToProps, DispatchToProps, and OwnProps
|
|
11
|
+
type Props = StateToProps & DispatchToProps & OwnProps;
|
|
12
|
+
|
|
13
|
+
// It is recommended to keep components stateless and use redux for managing states
|
|
14
|
+
const CustomTaskList: React.FunctionComponent<Props> = (props: Props) => {
|
|
15
|
+
if (!props.isOpen) {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<CustomTaskListComponentStyles>
|
|
21
|
+
This is a dismissible demo component
|
|
22
|
+
<i className="accented" onClick={props.dismissBar} aria-hidden="true">
|
|
23
|
+
close
|
|
24
|
+
</i>
|
|
25
|
+
</CustomTaskListComponentStyles>
|
|
26
|
+
);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
CustomTaskList.displayName = 'foo';
|
|
30
|
+
|
|
31
|
+
export default CustomTaskList;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { shallow } from 'enzyme';
|
|
3
|
+
|
|
4
|
+
import CustomTaskList from '../CustomTaskList/CustomTaskList';
|
|
5
|
+
|
|
6
|
+
describe('CustomTaskListComponent', () => {
|
|
7
|
+
it('should render demo component', () => {
|
|
8
|
+
const props = {
|
|
9
|
+
isOpen: true,
|
|
10
|
+
dismissBar: () => undefined,
|
|
11
|
+
};
|
|
12
|
+
const wrapper = shallow(<CustomTaskList {...props} />);
|
|
13
|
+
expect(wrapper.render().text()).toMatch('This is a dismissible demo component');
|
|
14
|
+
});
|
|
15
|
+
});
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Action } from '.';
|
|
2
|
+
|
|
3
|
+
const ACTION_DISMISS_BAR = 'DISMISS_BAR';
|
|
4
|
+
|
|
5
|
+
export interface CustomTaskListState {
|
|
6
|
+
isOpen: boolean;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const initialState: CustomTaskListState = {
|
|
10
|
+
isOpen: true,
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export class Actions {
|
|
14
|
+
public static dismissBar = (): Action => ({ type: ACTION_DISMISS_BAR });
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function reduce(state: CustomTaskListState = initialState, action: Action): CustomTaskListState {
|
|
18
|
+
// eslint-disable-next-line sonarjs/no-small-switch
|
|
19
|
+
switch (action.type) {
|
|
20
|
+
case ACTION_DISMISS_BAR: {
|
|
21
|
+
return {
|
|
22
|
+
...state,
|
|
23
|
+
isOpen: false,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
default:
|
|
28
|
+
return state;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { AppState as FlexAppState } from '@twilio/flex-ui';
|
|
2
|
+
import { combineReducers, Action as ReduxAction } from 'redux';
|
|
3
|
+
|
|
4
|
+
import { CustomTaskListState, reduce as CustomTaskListReducer } from './CustomTaskListState';
|
|
5
|
+
|
|
6
|
+
// Register your redux store under a unique namespace
|
|
7
|
+
export const namespace = '{{pluginNamespace}}';
|
|
8
|
+
|
|
9
|
+
// Extend this payload to be of type that your ReduxAction is
|
|
10
|
+
export interface Action extends ReduxAction {
|
|
11
|
+
payload?: any;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// Register all component states under the namespace
|
|
15
|
+
export interface AppState {
|
|
16
|
+
flex: FlexAppState;
|
|
17
|
+
'{{pluginNamespace}}': {
|
|
18
|
+
customTaskList: CustomTaskListState;
|
|
19
|
+
// Other states
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Combine the reducers
|
|
24
|
+
export default combineReducers({
|
|
25
|
+
customTaskList: CustomTaskListReducer,
|
|
26
|
+
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"baseUrl": "src",
|
|
4
|
+
"rootDir": ".",
|
|
5
|
+
"outDir": "build",
|
|
6
|
+
"target": "es5",
|
|
7
|
+
"lib": [
|
|
8
|
+
"dom",
|
|
9
|
+
"dom.iterable",
|
|
10
|
+
"esnext"
|
|
11
|
+
],
|
|
12
|
+
"allowJs": true,
|
|
13
|
+
"skipLibCheck": true,
|
|
14
|
+
"esModuleInterop": true,
|
|
15
|
+
"allowSyntheticDefaultImports": true,
|
|
16
|
+
"strict": true,
|
|
17
|
+
"forceConsistentCasingInFileNames": true,
|
|
18
|
+
"module": "esnext",
|
|
19
|
+
"moduleResolution": "node",
|
|
20
|
+
"resolveJsonModule": true,
|
|
21
|
+
"isolatedModules": true,
|
|
22
|
+
"noEmit": true,
|
|
23
|
+
"jsx": "preserve",
|
|
24
|
+
"noUnusedLocals": false,
|
|
25
|
+
"noUnusedParameters": false
|
|
26
|
+
},
|
|
27
|
+
"include": [
|
|
28
|
+
"./src/**/*"
|
|
29
|
+
],
|
|
30
|
+
"exclude": [
|
|
31
|
+
"./**/*.test.ts",
|
|
32
|
+
"./**/*.test.tsx",
|
|
33
|
+
"./**/__mocks__/*.ts",
|
|
34
|
+
"./**/__mocks__/*.tsx"
|
|
35
|
+
]
|
|
36
|
+
}
|