@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.
Files changed (54) hide show
  1. package/README.md +0 -0
  2. package/babel.config.js +0 -0
  3. package/browser/telegenta.min.js +1 -1
  4. package/demos/add_phone_number.html +0 -0
  5. package/demos/calldata_available.html +0 -0
  6. package/demos/embedded_config.html +94 -94
  7. package/demos/event_client.html +225 -225
  8. package/demos/phone_client.html +557 -557
  9. package/demos/styles.css +0 -0
  10. package/demos/telegenta.min.js +1 -0
  11. package/docs/EventClient.html +1 -1
  12. package/docs/Phone.html +1 -1
  13. package/docs/Session.html +1 -1
  14. package/docs/fonts/OpenSans-Bold-webfont.eot +0 -0
  15. package/docs/fonts/OpenSans-Bold-webfont.svg +0 -0
  16. package/docs/fonts/OpenSans-Bold-webfont.woff +0 -0
  17. package/docs/fonts/OpenSans-BoldItalic-webfont.eot +0 -0
  18. package/docs/fonts/OpenSans-BoldItalic-webfont.svg +0 -0
  19. package/docs/fonts/OpenSans-BoldItalic-webfont.woff +0 -0
  20. package/docs/fonts/OpenSans-Italic-webfont.eot +0 -0
  21. package/docs/fonts/OpenSans-Italic-webfont.svg +0 -0
  22. package/docs/fonts/OpenSans-Italic-webfont.woff +0 -0
  23. package/docs/fonts/OpenSans-Light-webfont.eot +0 -0
  24. package/docs/fonts/OpenSans-Light-webfont.svg +0 -0
  25. package/docs/fonts/OpenSans-Light-webfont.woff +0 -0
  26. package/docs/fonts/OpenSans-LightItalic-webfont.eot +0 -0
  27. package/docs/fonts/OpenSans-LightItalic-webfont.svg +0 -0
  28. package/docs/fonts/OpenSans-LightItalic-webfont.woff +0 -0
  29. package/docs/fonts/OpenSans-Regular-webfont.eot +0 -0
  30. package/docs/fonts/OpenSans-Regular-webfont.svg +0 -0
  31. package/docs/fonts/OpenSans-Regular-webfont.woff +0 -0
  32. package/docs/global.html +1 -1
  33. package/docs/index.html +1 -1
  34. package/docs/scripts/linenumber.js +0 -0
  35. package/docs/scripts/prettify/Apache-License-2.0.txt +0 -0
  36. package/docs/scripts/prettify/lang-css.js +0 -0
  37. package/docs/scripts/prettify/prettify.js +0 -0
  38. package/docs/styles/jsdoc-default.css +0 -0
  39. package/docs/styles/prettify-jsdoc.css +0 -0
  40. package/docs/styles/prettify-tomorrow.css +0 -0
  41. package/embedded_client/embedded_phone.js +0 -0
  42. package/embedded_client/index.html +0 -0
  43. package/embedded_client/server.php +0 -0
  44. package/embedded_client/styles.css +0 -0
  45. package/embedded_client/tiny_rest_client.php +0 -0
  46. package/embedded_client/webphone_sprites.png +0 -0
  47. package/es5/event-client.js +175 -219
  48. package/es5/index.js +0 -0
  49. package/es5/phone-client.js +771 -1173
  50. package/package.json +1 -1
  51. package/src/event-client.js +1 -1
  52. package/src/index.js +0 -0
  53. package/src/phone-client.js +1 -1
  54. 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>
@@ -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>