@telegenta/webclient 2.0.10 → 2.0.12
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/README.md +0 -0
- package/babel.config.js +0 -0
- package/browser/telegenta.min.js +1 -1
- package/demos/add_phone_number.html +0 -0
- package/demos/calldata_available.html +0 -0
- package/demos/embedded_config.html +94 -94
- package/demos/event_client.html +225 -225
- package/demos/phone_client.html +557 -557
- package/demos/styles.css +0 -0
- package/demos/telegenta.min.js +1 -0
- package/docs/EventClient.html +1 -1
- package/docs/Phone.html +1 -1
- package/docs/Session.html +1 -1
- package/docs/fonts/OpenSans-Bold-webfont.eot +0 -0
- package/docs/fonts/OpenSans-Bold-webfont.svg +0 -0
- package/docs/fonts/OpenSans-Bold-webfont.woff +0 -0
- package/docs/fonts/OpenSans-BoldItalic-webfont.eot +0 -0
- package/docs/fonts/OpenSans-BoldItalic-webfont.svg +0 -0
- package/docs/fonts/OpenSans-BoldItalic-webfont.woff +0 -0
- package/docs/fonts/OpenSans-Italic-webfont.eot +0 -0
- package/docs/fonts/OpenSans-Italic-webfont.svg +0 -0
- package/docs/fonts/OpenSans-Italic-webfont.woff +0 -0
- package/docs/fonts/OpenSans-Light-webfont.eot +0 -0
- package/docs/fonts/OpenSans-Light-webfont.svg +0 -0
- package/docs/fonts/OpenSans-Light-webfont.woff +0 -0
- package/docs/fonts/OpenSans-LightItalic-webfont.eot +0 -0
- package/docs/fonts/OpenSans-LightItalic-webfont.svg +0 -0
- package/docs/fonts/OpenSans-LightItalic-webfont.woff +0 -0
- package/docs/fonts/OpenSans-Regular-webfont.eot +0 -0
- package/docs/fonts/OpenSans-Regular-webfont.svg +0 -0
- package/docs/fonts/OpenSans-Regular-webfont.woff +0 -0
- package/docs/global.html +1 -1
- package/docs/index.html +1 -1
- package/docs/scripts/linenumber.js +0 -0
- package/docs/scripts/prettify/Apache-License-2.0.txt +0 -0
- package/docs/scripts/prettify/lang-css.js +0 -0
- package/docs/scripts/prettify/prettify.js +0 -0
- package/docs/styles/jsdoc-default.css +0 -0
- package/docs/styles/prettify-jsdoc.css +0 -0
- package/docs/styles/prettify-tomorrow.css +0 -0
- package/embedded_client/embedded_phone.js +0 -0
- package/embedded_client/index.html +0 -0
- package/embedded_client/server.php +0 -0
- package/embedded_client/styles.css +0 -0
- package/embedded_client/tiny_rest_client.php +0 -0
- package/embedded_client/webphone_sprites.png +0 -0
- package/es5/event-client.js +175 -219
- package/es5/index.js +0 -0
- package/es5/phone-client.js +771 -1173
- package/package.json +1 -1
- package/src/event-client.js +1 -1
- package/src/index.js +0 -0
- package/src/phone-client.js +1 -1
- package/webpack.config.js +0 -0
|
File without changes
|
|
File without changes
|
|
@@ -1,95 +1,95 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8">
|
|
5
|
-
<title>Telegenta embedded config page demo</title>
|
|
6
|
-
<link rel="stylesheet" type="text/css" href="styles.css">
|
|
7
|
-
</head>
|
|
8
|
-
|
|
9
|
-
<body>
|
|
10
|
-
<!-- Logo -->
|
|
11
|
-
<div id="Telegenta"></div>
|
|
12
|
-
<!-- Logo end -->
|
|
13
|
-
|
|
14
|
-
<h2>Telegenta Event Client Demo</h2>
|
|
15
|
-
<div class="groupelements">
|
|
16
|
-
<H3>Input API Key</H3>
|
|
17
|
-
<div class="inputelements">
|
|
18
|
-
<label for="api_key">API Key</label>
|
|
19
|
-
<input type="text" size="40" id="api_key" placeholder="Enter API Key" value="">
|
|
20
|
-
<label for="impersonate_id">Impersonate ID (empty = no impersonation)</label>
|
|
21
|
-
<input type="text" size="40" id="impersonate_id" placeholder="Enter customer id for impersonation" value="">
|
|
22
|
-
<button onclick="getConfigToken()">Get config token</button>
|
|
23
|
-
</div>
|
|
24
|
-
</div>
|
|
25
|
-
<div class="groupelements">
|
|
26
|
-
<div>
|
|
27
|
-
<button onclick="openConfigPage('call-routing')">Manage phone numbers</button>
|
|
28
|
-
<button onclick="openConfigPage('call-flow')">Manage call flows</button>
|
|
29
|
-
<button onclick="openConfigPage('media')">Media files</button>
|
|
30
|
-
<button onclick="openConfigPage('simple-call-dist')">Call groups</button>
|
|
31
|
-
</div>
|
|
32
|
-
</div>
|
|
33
|
-
<div class="groupelements">
|
|
34
|
-
<div>
|
|
35
|
-
<iframe id='config_frame' height="800" width="100%" frameborder="0"></iframe>
|
|
36
|
-
</div>
|
|
37
|
-
</div>
|
|
38
|
-
|
|
39
|
-
<!-- Javascript stuff -->
|
|
40
|
-
<script>
|
|
41
|
-
let configToken;
|
|
42
|
-
|
|
43
|
-
function getConfigToken() {
|
|
44
|
-
jsonApiGetRequest('/get-config-session').then(function (data) {
|
|
45
|
-
console.debug(data);
|
|
46
|
-
configToken = data.config_token;
|
|
47
|
-
}, function (reason) {
|
|
48
|
-
console.error(`Request failed ${reason}`);
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// Open embedded page
|
|
53
|
-
function openConfigPage(page) {
|
|
54
|
-
if (!configToken) {
|
|
55
|
-
console.error('Must get config token first')
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
document.getElementById('config_frame').src = `https://stage-admin.telegenta.com/${page}?embed=${configToken}`;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// Perform authenticated ajax request to api server and return json payload on success
|
|
63
|
-
function jsonApiGetRequest(path) {
|
|
64
|
-
const xhr = new XMLHttpRequest();
|
|
65
|
-
const url = 'https://stage-api.telegenta.com/api' + path;
|
|
66
|
-
xhr.open('GET', url, true);
|
|
67
|
-
xhr.responseType = 'json';
|
|
68
|
-
const apiToken = document.getElementById('api_key').value;
|
|
69
|
-
xhr.setRequestHeader('Authorization', 'Bearer ' + apiToken);
|
|
70
|
-
xhr.setRequestHeader('Accept', 'application/json');
|
|
71
|
-
|
|
72
|
-
const impersonate_id = document.getElementById('impersonate_id').value;
|
|
73
|
-
if (impersonate_id) {
|
|
74
|
-
console.debug('Impersonating ID '+impersonate_id);
|
|
75
|
-
xhr.setRequestHeader('X-USE-CUSTOMER-ID', impersonate_id);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
return new Promise(function (resolve, reject) {
|
|
79
|
-
xhr.onreadystatechange = function () {
|
|
80
|
-
if (xhr.readyState === 4) {
|
|
81
|
-
if (xhr.status !== 200) {
|
|
82
|
-
reject(xhr.status + ' ' + xhr.statusText);
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
|
-
resolve(xhr.response);
|
|
86
|
-
}
|
|
87
|
-
};
|
|
88
|
-
console.debug(`API Request: ${url}`);
|
|
89
|
-
xhr.send();
|
|
90
|
-
})
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
</script>
|
|
94
|
-
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<title>Telegenta embedded config page demo</title>
|
|
6
|
+
<link rel="stylesheet" type="text/css" href="styles.css">
|
|
7
|
+
</head>
|
|
8
|
+
|
|
9
|
+
<body>
|
|
10
|
+
<!-- Logo -->
|
|
11
|
+
<div id="Telegenta"></div>
|
|
12
|
+
<!-- Logo end -->
|
|
13
|
+
|
|
14
|
+
<h2>Telegenta Event Client Demo</h2>
|
|
15
|
+
<div class="groupelements">
|
|
16
|
+
<H3>Input API Key</H3>
|
|
17
|
+
<div class="inputelements">
|
|
18
|
+
<label for="api_key">API Key</label>
|
|
19
|
+
<input type="text" size="40" id="api_key" placeholder="Enter API Key" value="">
|
|
20
|
+
<label for="impersonate_id">Impersonate ID (empty = no impersonation)</label>
|
|
21
|
+
<input type="text" size="40" id="impersonate_id" placeholder="Enter customer id for impersonation" value="">
|
|
22
|
+
<button onclick="getConfigToken()">Get config token</button>
|
|
23
|
+
</div>
|
|
24
|
+
</div>
|
|
25
|
+
<div class="groupelements">
|
|
26
|
+
<div>
|
|
27
|
+
<button onclick="openConfigPage('call-routing')">Manage phone numbers</button>
|
|
28
|
+
<button onclick="openConfigPage('call-flow')">Manage call flows</button>
|
|
29
|
+
<button onclick="openConfigPage('media')">Media files</button>
|
|
30
|
+
<button onclick="openConfigPage('simple-call-dist')">Call groups</button>
|
|
31
|
+
</div>
|
|
32
|
+
</div>
|
|
33
|
+
<div class="groupelements">
|
|
34
|
+
<div>
|
|
35
|
+
<iframe id='config_frame' height="800" width="100%" frameborder="0"></iframe>
|
|
36
|
+
</div>
|
|
37
|
+
</div>
|
|
38
|
+
|
|
39
|
+
<!-- Javascript stuff -->
|
|
40
|
+
<script>
|
|
41
|
+
let configToken;
|
|
42
|
+
|
|
43
|
+
function getConfigToken() {
|
|
44
|
+
jsonApiGetRequest('/get-config-session').then(function (data) {
|
|
45
|
+
console.debug(data);
|
|
46
|
+
configToken = data.config_token;
|
|
47
|
+
}, function (reason) {
|
|
48
|
+
console.error(`Request failed ${reason}`);
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Open embedded page
|
|
53
|
+
function openConfigPage(page) {
|
|
54
|
+
if (!configToken) {
|
|
55
|
+
console.error('Must get config token first')
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
document.getElementById('config_frame').src = `https://stage-admin.telegenta.com/${page}?embed=${configToken}`;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Perform authenticated ajax request to api server and return json payload on success
|
|
63
|
+
function jsonApiGetRequest(path) {
|
|
64
|
+
const xhr = new XMLHttpRequest();
|
|
65
|
+
const url = 'https://stage-api.telegenta.com/api' + path;
|
|
66
|
+
xhr.open('GET', url, true);
|
|
67
|
+
xhr.responseType = 'json';
|
|
68
|
+
const apiToken = document.getElementById('api_key').value;
|
|
69
|
+
xhr.setRequestHeader('Authorization', 'Bearer ' + apiToken);
|
|
70
|
+
xhr.setRequestHeader('Accept', 'application/json');
|
|
71
|
+
|
|
72
|
+
const impersonate_id = document.getElementById('impersonate_id').value;
|
|
73
|
+
if (impersonate_id) {
|
|
74
|
+
console.debug('Impersonating ID '+impersonate_id);
|
|
75
|
+
xhr.setRequestHeader('X-USE-CUSTOMER-ID', impersonate_id);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return new Promise(function (resolve, reject) {
|
|
79
|
+
xhr.onreadystatechange = function () {
|
|
80
|
+
if (xhr.readyState === 4) {
|
|
81
|
+
if (xhr.status !== 200) {
|
|
82
|
+
reject(xhr.status + ' ' + xhr.statusText);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
resolve(xhr.response);
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
console.debug(`API Request: ${url}`);
|
|
89
|
+
xhr.send();
|
|
90
|
+
})
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
</script>
|
|
94
|
+
|
|
95
95
|
</html>
|
package/demos/event_client.html
CHANGED
|
@@ -1,226 +1,226 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8">
|
|
5
|
-
<title>Telegenta Event Client Demo</title>
|
|
6
|
-
<script src="telegenta.min.js"></script>
|
|
7
|
-
<link rel="stylesheet" type="text/css" href="styles.css">
|
|
8
|
-
</head>
|
|
9
|
-
|
|
10
|
-
<body>
|
|
11
|
-
<!-- Logo -->
|
|
12
|
-
<div id="Telegenta"></div>
|
|
13
|
-
<!-- Logo end -->
|
|
14
|
-
|
|
15
|
-
<h2>Telegenta Event Client Demo</h2>
|
|
16
|
-
<div class="groupelements">
|
|
17
|
-
<H3>Input API Key</H3>
|
|
18
|
-
<div class="inputelements">
|
|
19
|
-
<span class="smallright"><small>Use partner context:</small>
|
|
20
|
-
<input type="checkbox" id="is_partner">
|
|
21
|
-
</span>
|
|
22
|
-
|
|
23
|
-
<label for="api_key">API Key / OAuth2 token</label>
|
|
24
|
-
<input type="text" size="40" id="api_key" placeholder="Enter API Key" value="">
|
|
25
|
-
<button onclick="subscribe()">Subscribe</button>
|
|
26
|
-
<button onclick="unsubscribe()">Unsubscribe</button>
|
|
27
|
-
</div>
|
|
28
|
-
</div>
|
|
29
|
-
|
|
30
|
-
<h3>Live active calls</h3>
|
|
31
|
-
<table id="channel_tabel">
|
|
32
|
-
<tr>
|
|
33
|
-
<th>Customer</th>
|
|
34
|
-
<th>Start time</th>
|
|
35
|
-
<th>Answer time</th>
|
|
36
|
-
<th>Hangup time</th>
|
|
37
|
-
<th>Caller ID number</th>
|
|
38
|
-
<th>Privacy</th>
|
|
39
|
-
<th>Destination number</th>
|
|
40
|
-
<th>Destination name</th>
|
|
41
|
-
<th>Direction</th>
|
|
42
|
-
<th>State</th>
|
|
43
|
-
<th>Listen key</th>
|
|
44
|
-
</tr>
|
|
45
|
-
</table>
|
|
46
|
-
<small>Tip: Use browser console to see additional information</small>
|
|
47
|
-
</body>
|
|
48
|
-
|
|
49
|
-
<!-- Javascript stuff -->
|
|
50
|
-
<script>
|
|
51
|
-
let logger;
|
|
52
|
-
let eventClient;
|
|
53
|
-
let subscriptionId = null;
|
|
54
|
-
|
|
55
|
-
// Start when DOM is ready
|
|
56
|
-
window.onload = function () {
|
|
57
|
-
// Create event client instance
|
|
58
|
-
logger = new Telegenta.Logger.LogHandler(Telegenta.Logger.LOGLVL.INFO);
|
|
59
|
-
eventClient = new Telegenta.EventClient(logger);
|
|
60
|
-
|
|
61
|
-
// Connect to event server
|
|
62
|
-
eventClient.connect('wss://api.telegenta.com/es/').then(function () {
|
|
63
|
-
console.info(`Connected to server`);
|
|
64
|
-
}, function (reason) {
|
|
65
|
-
console.error(`Unable to connect to event service: ${reason}`);
|
|
66
|
-
});
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
/*
|
|
70
|
-
* BUTTON HANDLERS
|
|
71
|
-
*/
|
|
72
|
-
function subscribe() {
|
|
73
|
-
let eventSpec = {
|
|
74
|
-
event_name: 'resource_changed',
|
|
75
|
-
resource_name: 'activecall',
|
|
76
|
-
access_token: document.getElementById('api_key').value,
|
|
77
|
-
|
|
78
|
-
// If partner see events for all customers belonging to partner
|
|
79
|
-
context: (document.getElementById('is_partner').checked) ? 'partner' : 'customer'
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
// First fetch current calls
|
|
84
|
-
|
|
85
|
-
// If partner context use partner api url
|
|
86
|
-
const self = this;
|
|
87
|
-
const activeCallUrl = (document.getElementById('is_partner').checked) ? '/partner-active-calls' : '/active-calls';
|
|
88
|
-
|
|
89
|
-
jsonApiGetRequest(activeCallUrl).then(function (data) {
|
|
90
|
-
console.info(`Fetched ${data.results.length} calls`);
|
|
91
|
-
console.debug(data);
|
|
92
|
-
|
|
93
|
-
// Now populate table with calls
|
|
94
|
-
for (const call of data.results) {
|
|
95
|
-
insertTableRow({id: call.id, instance: call});
|
|
96
|
-
}
|
|
97
|
-
}, function (reason) {
|
|
98
|
-
console.error(`Request failed ${reason}`);
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
eventClient.subscribe(eventSpec, function (data) {
|
|
102
|
-
try {
|
|
103
|
-
// Based on event type we either create, update or delete table row
|
|
104
|
-
switch (data.operation) {
|
|
105
|
-
case 'CREATE':
|
|
106
|
-
insertTableRow(data);
|
|
107
|
-
return;
|
|
108
|
-
case 'UPDATE':
|
|
109
|
-
updateTableRow(data);
|
|
110
|
-
return;
|
|
111
|
-
case 'DELETE':
|
|
112
|
-
// Self destruct after 3 secs
|
|
113
|
-
setTimeout(function () {
|
|
114
|
-
deleteTableRow(data)
|
|
115
|
-
}, 5000);
|
|
116
|
-
return;
|
|
117
|
-
default:
|
|
118
|
-
console.error('Unknown operation');
|
|
119
|
-
}
|
|
120
|
-
} catch (e) {
|
|
121
|
-
console.error(e);
|
|
122
|
-
}
|
|
123
|
-
}).then(function (subscriptionId) {
|
|
124
|
-
self.subscriptionId = subscriptionId;
|
|
125
|
-
console.info(`Subscription successful ID = ${subscriptionId}`);
|
|
126
|
-
}, function (reason) {
|
|
127
|
-
console.error(`Subscribe failed: ${reason}`);
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
function unsubscribe() {
|
|
132
|
-
const self = this;
|
|
133
|
-
eventClient.unsubscribe(this.subscriptionId).then(function () {
|
|
134
|
-
console.info(`Unsubscribed successfully ID = ${self.subscriptionId}`);
|
|
135
|
-
}, function (reason) {
|
|
136
|
-
console.error(`Unsubscribe FAILED: ${reason}`);
|
|
137
|
-
})
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/*
|
|
141
|
-
* UI Helper functions
|
|
142
|
-
*/
|
|
143
|
-
|
|
144
|
-
function insertTableRow(data) {
|
|
145
|
-
const table = document.getElementById("channel_tabel");
|
|
146
|
-
const newRow = table.insertRow();
|
|
147
|
-
newRow.id = `instance_${data.id}`;
|
|
148
|
-
newRow.instance = data.instance;
|
|
149
|
-
for (let i = 0; i < table.rows[0].cells.length; i++)
|
|
150
|
-
newRow.insertCell();
|
|
151
|
-
|
|
152
|
-
updateTableRow(newRow);
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
function updateTableRow(data) {
|
|
156
|
-
const di = data.instance;
|
|
157
|
-
const row = document.getElementById(`instance_${data.instance.id}`);
|
|
158
|
-
if (row) {
|
|
159
|
-
row.cells[0].innerText = di.customer_str;
|
|
160
|
-
row.cells[1].innerText = prettyDate(di.create_time);
|
|
161
|
-
row.cells[2].innerText = prettyDate(di.answer_time);
|
|
162
|
-
row.cells[3].innerText = prettyDate(di.hangup_time);
|
|
163
|
-
|
|
164
|
-
// Use effective cid if possible (outbound)
|
|
165
|
-
if (di.effective_cid) {
|
|
166
|
-
row.cells[4].innerText = '+' + di.effective_cid_number;
|
|
167
|
-
} else {
|
|
168
|
-
row.cells[4].innerText = di.caller_id_number;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
row.cells[5].innerText = di.using_privacy;
|
|
172
|
-
row.cells[6].innerText = '+' + di.destination_number;
|
|
173
|
-
row.cells[7].innerText = di.rate_destination_str;
|
|
174
|
-
row.cells[8].innerText = di.direction_str;
|
|
175
|
-
row.cells[9].innerText = di.state_str;
|
|
176
|
-
// Set class on state column
|
|
177
|
-
row.cells[9].className = 'state_' + di.state_str.toLowerCase();
|
|
178
|
-
row.cells[10].innerText = di.listen_key;
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
function deleteTableRow(data) {
|
|
183
|
-
const row = document.getElementById(`instance_${data.id}`);
|
|
184
|
-
if (row) {
|
|
185
|
-
row.parentNode.removeChild(row);
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
// Pretty print datetime (vanilla style)
|
|
190
|
-
function prettyDate(dateString) {
|
|
191
|
-
if (!dateString) return '';
|
|
192
|
-
const d = new Date(dateString);
|
|
193
|
-
const h = d.getHours();
|
|
194
|
-
const m = d.getMinutes();
|
|
195
|
-
const s = d.getSeconds();
|
|
196
|
-
return '' + (h < 10 ? '0' + h : h) + ':' + (m < 10 ? '0' + m : m) + ':' + (s < 10 ? '0' + s : s);
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
// Perform authenticated ajax request to api server and return json payload on success
|
|
200
|
-
function jsonApiGetRequest(path) {
|
|
201
|
-
const xhr = new XMLHttpRequest();
|
|
202
|
-
const url = 'https://api.telegenta.com/api' + path;
|
|
203
|
-
xhr.open('GET', url, true);
|
|
204
|
-
xhr.responseType = 'json';
|
|
205
|
-
const apiToken = document.getElementById('api_key').value;
|
|
206
|
-
xhr.setRequestHeader('Authorization', 'Bearer ' + apiToken);
|
|
207
|
-
xhr.setRequestHeader('Accept', 'application/json');
|
|
208
|
-
|
|
209
|
-
return new Promise(function (resolve, reject) {
|
|
210
|
-
xhr.onreadystatechange = function () {
|
|
211
|
-
if (xhr.readyState === 4) {
|
|
212
|
-
if (xhr.status !== 200) {
|
|
213
|
-
reject(xhr.status + ' ' + xhr.statusText);
|
|
214
|
-
return;
|
|
215
|
-
}
|
|
216
|
-
resolve(xhr.response);
|
|
217
|
-
}
|
|
218
|
-
};
|
|
219
|
-
console.debug(`API Request: ${url}`);
|
|
220
|
-
xhr.send();
|
|
221
|
-
})
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
</script>
|
|
225
|
-
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<title>Telegenta Event Client Demo</title>
|
|
6
|
+
<script src="telegenta.min.js"></script>
|
|
7
|
+
<link rel="stylesheet" type="text/css" href="styles.css">
|
|
8
|
+
</head>
|
|
9
|
+
|
|
10
|
+
<body>
|
|
11
|
+
<!-- Logo -->
|
|
12
|
+
<div id="Telegenta"></div>
|
|
13
|
+
<!-- Logo end -->
|
|
14
|
+
|
|
15
|
+
<h2>Telegenta Event Client Demo</h2>
|
|
16
|
+
<div class="groupelements">
|
|
17
|
+
<H3>Input API Key</H3>
|
|
18
|
+
<div class="inputelements">
|
|
19
|
+
<span class="smallright"><small>Use partner context:</small>
|
|
20
|
+
<input type="checkbox" id="is_partner">
|
|
21
|
+
</span>
|
|
22
|
+
|
|
23
|
+
<label for="api_key">API Key / OAuth2 token</label>
|
|
24
|
+
<input type="text" size="40" id="api_key" placeholder="Enter API Key" value="">
|
|
25
|
+
<button onclick="subscribe()">Subscribe</button>
|
|
26
|
+
<button onclick="unsubscribe()">Unsubscribe</button>
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
<h3>Live active calls</h3>
|
|
31
|
+
<table id="channel_tabel">
|
|
32
|
+
<tr>
|
|
33
|
+
<th>Customer</th>
|
|
34
|
+
<th>Start time</th>
|
|
35
|
+
<th>Answer time</th>
|
|
36
|
+
<th>Hangup time</th>
|
|
37
|
+
<th>Caller ID number</th>
|
|
38
|
+
<th>Privacy</th>
|
|
39
|
+
<th>Destination number</th>
|
|
40
|
+
<th>Destination name</th>
|
|
41
|
+
<th>Direction</th>
|
|
42
|
+
<th>State</th>
|
|
43
|
+
<th>Listen key</th>
|
|
44
|
+
</tr>
|
|
45
|
+
</table>
|
|
46
|
+
<small>Tip: Use browser console to see additional information</small>
|
|
47
|
+
</body>
|
|
48
|
+
|
|
49
|
+
<!-- Javascript stuff -->
|
|
50
|
+
<script>
|
|
51
|
+
let logger;
|
|
52
|
+
let eventClient;
|
|
53
|
+
let subscriptionId = null;
|
|
54
|
+
|
|
55
|
+
// Start when DOM is ready
|
|
56
|
+
window.onload = function () {
|
|
57
|
+
// Create event client instance
|
|
58
|
+
logger = new Telegenta.Logger.LogHandler(Telegenta.Logger.LOGLVL.INFO);
|
|
59
|
+
eventClient = new Telegenta.EventClient(logger);
|
|
60
|
+
|
|
61
|
+
// Connect to event server
|
|
62
|
+
eventClient.connect('wss://api.telegenta.com/es/').then(function () {
|
|
63
|
+
console.info(`Connected to server`);
|
|
64
|
+
}, function (reason) {
|
|
65
|
+
console.error(`Unable to connect to event service: ${reason}`);
|
|
66
|
+
});
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
/*
|
|
70
|
+
* BUTTON HANDLERS
|
|
71
|
+
*/
|
|
72
|
+
function subscribe() {
|
|
73
|
+
let eventSpec = {
|
|
74
|
+
event_name: 'resource_changed',
|
|
75
|
+
resource_name: 'activecall',
|
|
76
|
+
access_token: document.getElementById('api_key').value,
|
|
77
|
+
|
|
78
|
+
// If partner see events for all customers belonging to partner
|
|
79
|
+
context: (document.getElementById('is_partner').checked) ? 'partner' : 'customer'
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
// First fetch current calls
|
|
84
|
+
|
|
85
|
+
// If partner context use partner api url
|
|
86
|
+
const self = this;
|
|
87
|
+
const activeCallUrl = (document.getElementById('is_partner').checked) ? '/partner-active-calls' : '/active-calls';
|
|
88
|
+
|
|
89
|
+
jsonApiGetRequest(activeCallUrl).then(function (data) {
|
|
90
|
+
console.info(`Fetched ${data.results.length} calls`);
|
|
91
|
+
console.debug(data);
|
|
92
|
+
|
|
93
|
+
// Now populate table with calls
|
|
94
|
+
for (const call of data.results) {
|
|
95
|
+
insertTableRow({id: call.id, instance: call});
|
|
96
|
+
}
|
|
97
|
+
}, function (reason) {
|
|
98
|
+
console.error(`Request failed ${reason}`);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
eventClient.subscribe(eventSpec, function (data) {
|
|
102
|
+
try {
|
|
103
|
+
// Based on event type we either create, update or delete table row
|
|
104
|
+
switch (data.operation) {
|
|
105
|
+
case 'CREATE':
|
|
106
|
+
insertTableRow(data);
|
|
107
|
+
return;
|
|
108
|
+
case 'UPDATE':
|
|
109
|
+
updateTableRow(data);
|
|
110
|
+
return;
|
|
111
|
+
case 'DELETE':
|
|
112
|
+
// Self destruct after 3 secs
|
|
113
|
+
setTimeout(function () {
|
|
114
|
+
deleteTableRow(data)
|
|
115
|
+
}, 5000);
|
|
116
|
+
return;
|
|
117
|
+
default:
|
|
118
|
+
console.error('Unknown operation');
|
|
119
|
+
}
|
|
120
|
+
} catch (e) {
|
|
121
|
+
console.error(e);
|
|
122
|
+
}
|
|
123
|
+
}).then(function (subscriptionId) {
|
|
124
|
+
self.subscriptionId = subscriptionId;
|
|
125
|
+
console.info(`Subscription successful ID = ${subscriptionId}`);
|
|
126
|
+
}, function (reason) {
|
|
127
|
+
console.error(`Subscribe failed: ${reason}`);
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function unsubscribe() {
|
|
132
|
+
const self = this;
|
|
133
|
+
eventClient.unsubscribe(this.subscriptionId).then(function () {
|
|
134
|
+
console.info(`Unsubscribed successfully ID = ${self.subscriptionId}`);
|
|
135
|
+
}, function (reason) {
|
|
136
|
+
console.error(`Unsubscribe FAILED: ${reason}`);
|
|
137
|
+
})
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/*
|
|
141
|
+
* UI Helper functions
|
|
142
|
+
*/
|
|
143
|
+
|
|
144
|
+
function insertTableRow(data) {
|
|
145
|
+
const table = document.getElementById("channel_tabel");
|
|
146
|
+
const newRow = table.insertRow();
|
|
147
|
+
newRow.id = `instance_${data.id}`;
|
|
148
|
+
newRow.instance = data.instance;
|
|
149
|
+
for (let i = 0; i < table.rows[0].cells.length; i++)
|
|
150
|
+
newRow.insertCell();
|
|
151
|
+
|
|
152
|
+
updateTableRow(newRow);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function updateTableRow(data) {
|
|
156
|
+
const di = data.instance;
|
|
157
|
+
const row = document.getElementById(`instance_${data.instance.id}`);
|
|
158
|
+
if (row) {
|
|
159
|
+
row.cells[0].innerText = di.customer_str;
|
|
160
|
+
row.cells[1].innerText = prettyDate(di.create_time);
|
|
161
|
+
row.cells[2].innerText = prettyDate(di.answer_time);
|
|
162
|
+
row.cells[3].innerText = prettyDate(di.hangup_time);
|
|
163
|
+
|
|
164
|
+
// Use effective cid if possible (outbound)
|
|
165
|
+
if (di.effective_cid) {
|
|
166
|
+
row.cells[4].innerText = '+' + di.effective_cid_number;
|
|
167
|
+
} else {
|
|
168
|
+
row.cells[4].innerText = di.caller_id_number;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
row.cells[5].innerText = di.using_privacy;
|
|
172
|
+
row.cells[6].innerText = '+' + di.destination_number;
|
|
173
|
+
row.cells[7].innerText = di.rate_destination_str;
|
|
174
|
+
row.cells[8].innerText = di.direction_str;
|
|
175
|
+
row.cells[9].innerText = di.state_str;
|
|
176
|
+
// Set class on state column
|
|
177
|
+
row.cells[9].className = 'state_' + di.state_str.toLowerCase();
|
|
178
|
+
row.cells[10].innerText = di.listen_key;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function deleteTableRow(data) {
|
|
183
|
+
const row = document.getElementById(`instance_${data.id}`);
|
|
184
|
+
if (row) {
|
|
185
|
+
row.parentNode.removeChild(row);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Pretty print datetime (vanilla style)
|
|
190
|
+
function prettyDate(dateString) {
|
|
191
|
+
if (!dateString) return '';
|
|
192
|
+
const d = new Date(dateString);
|
|
193
|
+
const h = d.getHours();
|
|
194
|
+
const m = d.getMinutes();
|
|
195
|
+
const s = d.getSeconds();
|
|
196
|
+
return '' + (h < 10 ? '0' + h : h) + ':' + (m < 10 ? '0' + m : m) + ':' + (s < 10 ? '0' + s : s);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// Perform authenticated ajax request to api server and return json payload on success
|
|
200
|
+
function jsonApiGetRequest(path) {
|
|
201
|
+
const xhr = new XMLHttpRequest();
|
|
202
|
+
const url = 'https://api.telegenta.com/api' + path;
|
|
203
|
+
xhr.open('GET', url, true);
|
|
204
|
+
xhr.responseType = 'json';
|
|
205
|
+
const apiToken = document.getElementById('api_key').value;
|
|
206
|
+
xhr.setRequestHeader('Authorization', 'Bearer ' + apiToken);
|
|
207
|
+
xhr.setRequestHeader('Accept', 'application/json');
|
|
208
|
+
|
|
209
|
+
return new Promise(function (resolve, reject) {
|
|
210
|
+
xhr.onreadystatechange = function () {
|
|
211
|
+
if (xhr.readyState === 4) {
|
|
212
|
+
if (xhr.status !== 200) {
|
|
213
|
+
reject(xhr.status + ' ' + xhr.statusText);
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
resolve(xhr.response);
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
console.debug(`API Request: ${url}`);
|
|
220
|
+
xhr.send();
|
|
221
|
+
})
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
</script>
|
|
225
|
+
|
|
226
226
|
</html>
|