@telegenta/webclient 3.0.0 → 3.0.1
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/demos/event_client.html +225 -210
- package/demos/phone_client.html +539 -519
- package/dist/telegenta.js +326 -290
- package/dist/telegenta.min.js +1 -1
- package/docs/EventClient.html +1 -1
- package/docs/EventServiceNotConnected.html +3 -0
- package/docs/InvalidMediaDevice.html +1 -1
- package/docs/InvalidOptions.html +1 -1
- package/docs/InvalidParameter.html +1 -1
- package/docs/LogHandler.html +2 -2
- package/docs/MediaNotPrepared.html +1 -1
- package/docs/NoActiveSession.html +1 -1
- package/docs/NotAllowed.html +1 -1
- package/docs/NotReady.html +1 -1
- package/docs/Phone.html +2 -2
- package/docs/Request.html +1 -1
- package/docs/Requestor.html +1 -1
- package/docs/Session.html +1 -1
- package/docs/UnableToConnect.html +1 -1
- package/docs/data/search.json +1 -1
- package/docs/event-client.js.html +44 -38
- package/docs/exceptions.js.html +12 -2
- package/docs/global.html +3 -3
- package/docs/index.html +1 -1
- package/docs/logger.js.html +2 -2
- package/docs/phone-client.js.html +284 -264
- package/docs/requestor.js.html +3 -3
- package/package.json +45 -45
package/demos/phone_client.html
CHANGED
|
@@ -1,564 +1,584 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
2
|
<html lang="en">
|
|
3
|
-
|
|
4
|
-
<meta name="
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
<
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
<div>
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
3
|
+
<meta name="keywords" content="telegenta, phone client, webrtc, demo" />
|
|
4
|
+
<meta name="description" content="Telegenta Phone client demo application using telegenta client library" />
|
|
5
|
+
|
|
6
|
+
<head>
|
|
7
|
+
<meta charset="UTF-8" />
|
|
8
|
+
<title>Telegenta Phone client Demo</title>
|
|
9
|
+
<script src="../dist/telegenta.min.js"></script>
|
|
10
|
+
<link rel="stylesheet" type="text/css" href="styles.css" />
|
|
11
|
+
</head>
|
|
12
|
+
|
|
13
|
+
<body>
|
|
14
|
+
<!-- Logo -->
|
|
15
|
+
<div class="groupelementsnoline" id="Telegenta"></div>
|
|
16
|
+
<!-- Logo end -->
|
|
17
|
+
<div>
|
|
18
|
+
<div class="groupelementsnoline">
|
|
19
|
+
<h2>Telegenta Phone Client Demo</h2>
|
|
20
|
+
</div>
|
|
21
|
+
<div class="groupelements">
|
|
22
|
+
<h3>STEP 1: Get account list</h3>
|
|
23
|
+
<div class="inputelements">
|
|
24
|
+
<label for="api_key">API Key</label>
|
|
25
|
+
<input type="text" size="40" id="api_key" placeholder="Enter API Key" value="" />
|
|
26
|
+
<button onclick="populateSelectElements()">Get sip accounts</button>
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
<div class="groupelements">
|
|
31
|
+
<h3>STEP 2: Start phone</h3>
|
|
32
|
+
<div class="inputelements">
|
|
33
|
+
<label for="account_selector">SIP Accounts</label
|
|
34
|
+
><span class="smallright"
|
|
35
|
+
><small>Connection: <span id="conn_status">DISCONNECTED</span></small></span
|
|
36
|
+
>
|
|
37
|
+
<select id="account_selector">
|
|
38
|
+
<option value="" disabled selected>Waiting for SIP accounts</option>
|
|
39
|
+
</select>
|
|
40
|
+
<button onclick="startPhoneClient()">Start phone and use selected account</button>
|
|
41
|
+
<button onclick="stopPhoneClient()">Stop the phone client</button>
|
|
42
|
+
</div>
|
|
43
|
+
</div>
|
|
44
|
+
|
|
45
|
+
<div class="groupelements">
|
|
46
|
+
<h3>STEP 3: Add a new call</h3>
|
|
47
|
+
<div class="inputelements">
|
|
48
|
+
<label for="destination_number">Number to call</label
|
|
49
|
+
><span class="smallright"
|
|
50
|
+
><small
|
|
51
|
+
>Status: <span id="call_status">IDLE</span> | Duration:
|
|
52
|
+
<span id="call_duration">-</span></small
|
|
53
|
+
></span
|
|
54
|
+
>
|
|
55
|
+
<input type="text" size="40" id="destination_number" placeholder="Enter phone number" value="" />
|
|
56
|
+
<button onclick="makeCall()">Call number now</button>
|
|
57
|
+
</div>
|
|
58
|
+
</div>
|
|
59
|
+
|
|
60
|
+
<div class="groupelements">
|
|
61
|
+
<h3>Transfer call</h3>
|
|
62
|
+
|
|
63
|
+
<div class="inputelements">
|
|
64
|
+
<h3 id="transfer_from"></h3>
|
|
65
|
+
<label for="transfer_selector">Select call: </label>
|
|
66
|
+
<select id="transfer_selector">
|
|
67
|
+
<option value="" disabled selected>No call to transfer</option>
|
|
68
|
+
</select>
|
|
69
|
+
|
|
70
|
+
<button onclick="doCallTransfer()">Transfer call</button>
|
|
71
|
+
</div>
|
|
72
|
+
</div>
|
|
73
|
+
|
|
74
|
+
<div class="groupelements">
|
|
75
|
+
<h3>Listen call</h3>
|
|
76
|
+
|
|
77
|
+
<div class="inputelements">
|
|
78
|
+
<h3>Listen to another call</h3>
|
|
79
|
+
<label for="listen_key">Call listen key</label>
|
|
80
|
+
<input type="text" size="40" id="listen_key" placeholder="Enter call listen key" value="" />
|
|
81
|
+
<button onclick="doListen()">Listen now</button>
|
|
82
|
+
</div>
|
|
83
|
+
</div>
|
|
84
|
+
|
|
85
|
+
<div class="groupelements">
|
|
86
|
+
<h3>Playback</h3>
|
|
87
|
+
<div class="inputelements">
|
|
88
|
+
<label for="media_file_selector">Media files</label>
|
|
89
|
+
<select id="media_file_selector">
|
|
90
|
+
<option value="" disabled selected>Select media file</option>
|
|
91
|
+
</select>
|
|
92
|
+
</div>
|
|
93
|
+
</div>
|
|
94
|
+
|
|
95
|
+
<div class="groupelementsnoline">
|
|
96
|
+
<h3>Active calls</h3>
|
|
97
|
+
<table id="session_table">
|
|
98
|
+
<tr>
|
|
99
|
+
<th>Direction</th>
|
|
100
|
+
<th>Destination number</th>
|
|
101
|
+
<th>State</th>
|
|
102
|
+
<th>Duration</th>
|
|
103
|
+
<th>Quality metrics</th>
|
|
104
|
+
<th>Mic muted</th>
|
|
105
|
+
<th>Recording</th>
|
|
106
|
+
<th>On hold</th>
|
|
107
|
+
<th>Actions</th>
|
|
108
|
+
</tr>
|
|
109
|
+
</table>
|
|
110
|
+
</div>
|
|
111
|
+
<div class="groupelementsnoline">
|
|
112
|
+
<small>Tip: Press F12 (developer console) to get additional information</small>
|
|
113
|
+
</div>
|
|
53
114
|
</div>
|
|
54
|
-
</
|
|
115
|
+
</body>
|
|
116
|
+
|
|
117
|
+
<!-- Javascript stuff -->
|
|
118
|
+
<script>
|
|
119
|
+
const API_URL = 'https://api.telegenta.com/api';
|
|
120
|
+
let phoneClient = null;
|
|
121
|
+
let logger;
|
|
122
|
+
let transferSession;
|
|
123
|
+
|
|
124
|
+
// Start when DOM is ready
|
|
125
|
+
window.onload = function () {
|
|
126
|
+
// Create phone instance first
|
|
127
|
+
logger = new Telegenta.LogHandler(Telegenta.LOGLVL.DEBUG);
|
|
128
|
+
phoneClient = new Telegenta.Phone(logger);
|
|
129
|
+
|
|
130
|
+
// Check browser is supported first
|
|
131
|
+
if (!phoneClient.browserSupported) {
|
|
132
|
+
console.error('Your browser is not supported');
|
|
133
|
+
} else {
|
|
134
|
+
console.info('Your browser is supported');
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
/*
|
|
139
|
+
* STEP 1: Get a list of sip accounts from API server and populate select box with these accounts
|
|
140
|
+
*/
|
|
141
|
+
function populateSelectElements() {
|
|
142
|
+
// SIP Accounts
|
|
143
|
+
jsonApiGetRequest('/sip-trunks/').then(
|
|
144
|
+
function (data) {
|
|
145
|
+
console.info(`Fetched ${data.results.length} sip accounts:`);
|
|
146
|
+
console.debug(data);
|
|
147
|
+
|
|
148
|
+
// Now reset and populate select box with accounts
|
|
149
|
+
document.getElementById('account_selector').innerHTML = '';
|
|
150
|
+
for (const account of data.results) {
|
|
151
|
+
document.getElementById('account_selector').appendChild(new Option(account.name, account.id));
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
function (reason) {
|
|
155
|
+
console.error(`Request failed ${reason}`);
|
|
156
|
+
},
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
// Media files
|
|
160
|
+
jsonApiGetRequest('/media-files/').then(
|
|
161
|
+
function (data) {
|
|
162
|
+
console.info(`Fetched ${data.results.length} media files:`);
|
|
163
|
+
console.debug(data);
|
|
164
|
+
|
|
165
|
+
// Now reset and populate select box with accounts
|
|
166
|
+
document.getElementById('media_file_selector').innerHTML = '';
|
|
167
|
+
for (const mfile of data.results) {
|
|
168
|
+
document.getElementById('media_file_selector').appendChild(new Option(mfile.name, mfile.id));
|
|
169
|
+
}
|
|
170
|
+
},
|
|
171
|
+
function (reason) {
|
|
172
|
+
console.error(`Request failed ${reason}`);
|
|
173
|
+
},
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/*
|
|
178
|
+
* STEP 2: Get a new call_token from API and start phone client with account chosen in select box
|
|
179
|
+
*/
|
|
180
|
+
function startPhoneClient() {
|
|
181
|
+
const accountId = document.getElementById('account_selector').value;
|
|
182
|
+
console.info(`Starting phone client with account id ${accountId}`);
|
|
183
|
+
|
|
184
|
+
// Create call session and get provision token
|
|
185
|
+
jsonApiGetRequest(`/get-call-session/?id=${accountId}`).then(
|
|
186
|
+
function (data) {
|
|
187
|
+
console.info('Fetched a new call session');
|
|
188
|
+
console.debug(data);
|
|
189
|
+
|
|
190
|
+
// Now prepare media and get access to microphone
|
|
191
|
+
phoneClient.prepareMedia().then(
|
|
192
|
+
function () {
|
|
193
|
+
// Media was prepared, now hook up events to display whats going on
|
|
194
|
+
|
|
195
|
+
// Connection state shows the client connection to the phone services
|
|
196
|
+
phoneClient.on('connectionStateChange', function (event) {
|
|
197
|
+
console.info(`Phone connection is now: ${event.state}`);
|
|
198
|
+
document.getElementById('conn_status').innerHTML = event.state;
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
// Get local information about call after it has ended
|
|
202
|
+
phoneClient.on('callEnded', function (data) {
|
|
203
|
+
console.info('Call ended event:');
|
|
204
|
+
console.info(data);
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
// Get remote information about call after it has ended
|
|
208
|
+
phoneClient.on('callDataInfo', function (data) {
|
|
209
|
+
console.info('Call data info event:');
|
|
210
|
+
console.info(data);
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
// New session created
|
|
214
|
+
phoneClient.on('sessionCreated', function (data) {
|
|
215
|
+
newSession(data.session);
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
// Session removed
|
|
219
|
+
phoneClient.on('sessionRemoved', function (data) {
|
|
220
|
+
console.log(data);
|
|
221
|
+
removeSession(data.session);
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
// Show incoming call
|
|
225
|
+
phoneClient.on('incomingCall', function (data) {
|
|
226
|
+
console.log(`Incoming call from ${data.originatingNumber}`);
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
// Now start phone with the following options
|
|
230
|
+
const opts = {
|
|
231
|
+
// Enable event client
|
|
232
|
+
connectEventService: true,
|
|
233
|
+
|
|
234
|
+
// Subscribe to detailed information about call after processing
|
|
235
|
+
useCallDataInfoEvent: true,
|
|
236
|
+
|
|
237
|
+
// Enable incoming calls (you must set a phone number to call the account also)
|
|
238
|
+
register: true,
|
|
239
|
+
|
|
240
|
+
// Configure client with provision token
|
|
241
|
+
provisionToken: data.provision_token,
|
|
242
|
+
|
|
243
|
+
// Enable signal tones (busy, invalid, etc)
|
|
244
|
+
playSignalTones: true,
|
|
245
|
+
|
|
246
|
+
// Enable call initialized tone
|
|
247
|
+
playCallInitializedTone: true,
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
try {
|
|
251
|
+
phoneClient.start(opts);
|
|
252
|
+
console.info('Media prepared and phone started');
|
|
253
|
+
} catch (e) {
|
|
254
|
+
console.error('Unable to start phone');
|
|
255
|
+
console.error(e);
|
|
256
|
+
}
|
|
257
|
+
},
|
|
258
|
+
function (reason) {
|
|
259
|
+
console.error('Unable to get media permission: ' + reason);
|
|
260
|
+
},
|
|
261
|
+
);
|
|
262
|
+
},
|
|
263
|
+
function (reason) {
|
|
264
|
+
console.error(`Request failed ${reason}`);
|
|
265
|
+
},
|
|
266
|
+
);
|
|
267
|
+
}
|
|
55
268
|
|
|
56
|
-
|
|
57
|
-
|
|
269
|
+
// Stop phone client
|
|
270
|
+
function stopPhoneClient() {
|
|
271
|
+
phoneClient.stop();
|
|
272
|
+
}
|
|
58
273
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
274
|
+
/*
|
|
275
|
+
* STEP 3: Make a test call
|
|
276
|
+
*/
|
|
277
|
+
function makeCall() {
|
|
278
|
+
const destination_number = document.getElementById('destination_number').value;
|
|
279
|
+
phoneClient.call(destination_number, {
|
|
280
|
+
// Change this to number of days to keep recording (enables recording)
|
|
281
|
+
record: 0,
|
|
65
282
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
</div>
|
|
283
|
+
// Change this maximum amount in customer currency the call must cost before hanging up (0 = no checking)
|
|
284
|
+
maximumCallCost: 0,
|
|
69
285
|
|
|
70
|
-
|
|
71
|
-
|
|
286
|
+
// Include this to force a specific caller id (use id of phone number from api service)
|
|
287
|
+
// explicitCallerId: 35,
|
|
72
288
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
<label for="listen_key">Call listen key</label>
|
|
76
|
-
<input type="text" size="40" id="listen_key" placeholder="Enter call listen key" value="">
|
|
77
|
-
<button onclick="doListen()">Listen now</button>
|
|
78
|
-
</div>
|
|
79
|
-
</div>
|
|
80
|
-
|
|
81
|
-
<div class="groupelements">
|
|
82
|
-
<h3>Playback</h3>
|
|
83
|
-
<div class="inputelements">
|
|
84
|
-
<label for="media_file_selector">Media files</label>
|
|
85
|
-
<select id="media_file_selector">
|
|
86
|
-
<option value="" disabled selected>Select media file</option>
|
|
87
|
-
</select>
|
|
88
|
-
</div>
|
|
89
|
-
</div>
|
|
90
|
-
|
|
91
|
-
<div class="groupelementsnoline">
|
|
92
|
-
<h3>Active calls</h3>
|
|
93
|
-
<table id="session_table">
|
|
94
|
-
<tr>
|
|
95
|
-
<th>Direction</th>
|
|
96
|
-
<th>Destination number</th>
|
|
97
|
-
<th>State</th>
|
|
98
|
-
<th>Duration</th>
|
|
99
|
-
<th>Quality metrics</th>
|
|
100
|
-
<th>Mic muted</th>
|
|
101
|
-
<th>Recording</th>
|
|
102
|
-
<th>On hold</th>
|
|
103
|
-
<th>Actions</th>
|
|
104
|
-
</tr>
|
|
105
|
-
</table>
|
|
106
|
-
</div>
|
|
107
|
-
<div class="groupelementsnoline">
|
|
108
|
-
<small>Tip: Press F12 (developer console) to get additional information</small>
|
|
109
|
-
</div>
|
|
110
|
-
</div>
|
|
111
|
-
</body>
|
|
112
|
-
|
|
113
|
-
<!-- Javascript stuff -->
|
|
114
|
-
<script>
|
|
115
|
-
const API_URL = 'https://api.telegenta.com/api';
|
|
116
|
-
let phoneClient = null;
|
|
117
|
-
let logger;
|
|
118
|
-
let transferSession;
|
|
119
|
-
|
|
120
|
-
// Start when DOM is ready
|
|
121
|
-
window.onload = function () {
|
|
122
|
-
// Create phone instance first
|
|
123
|
-
logger = new Telegenta.LogHandler(Telegenta.LOGLVL.DEBUG);
|
|
124
|
-
phoneClient = new Telegenta.Phone(logger);
|
|
125
|
-
|
|
126
|
-
// Check browser is supported first
|
|
127
|
-
if (!phoneClient.browserSupported) {
|
|
128
|
-
console.error('Your browser is not supported');
|
|
129
|
-
} else {
|
|
130
|
-
console.info('Your browser is supported');
|
|
131
|
-
}
|
|
132
|
-
};
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
/*
|
|
136
|
-
* STEP 1: Get a list of sip accounts from API server and populate select box with these accounts
|
|
137
|
-
*/
|
|
138
|
-
function populateSelectElements() {
|
|
139
|
-
// SIP Accounts
|
|
140
|
-
jsonApiGetRequest('/sip-trunks/').then(function (data) {
|
|
141
|
-
console.info(`Fetched ${data.results.length} sip accounts:`);
|
|
142
|
-
console.debug(data);
|
|
143
|
-
|
|
144
|
-
// Now reset and populate select box with accounts
|
|
145
|
-
document.getElementById('account_selector').innerHTML = '';
|
|
146
|
-
for (const account of data.results) {
|
|
147
|
-
document.getElementById('account_selector').appendChild(new Option(account.name, account.id));
|
|
148
|
-
}
|
|
149
|
-
}, function (reason) {
|
|
150
|
-
console.error(`Request failed ${reason}`);
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
// Media files
|
|
154
|
-
jsonApiGetRequest('/media-files/').then(function (data) {
|
|
155
|
-
console.info(`Fetched ${data.results.length} media files:`);
|
|
156
|
-
console.debug(data);
|
|
157
|
-
|
|
158
|
-
// Now reset and populate select box with accounts
|
|
159
|
-
document.getElementById('media_file_selector').innerHTML = '';
|
|
160
|
-
for (const mfile of data.results) {
|
|
161
|
-
document.getElementById('media_file_selector').appendChild(new Option(mfile.name, mfile.id));
|
|
162
|
-
}
|
|
163
|
-
}, function (reason) {
|
|
164
|
-
console.error(`Request failed ${reason}`);
|
|
165
|
-
});
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
/*
|
|
169
|
-
* STEP 2: Get a new call_token from API and start phone client with account chosen in select box
|
|
170
|
-
*/
|
|
171
|
-
function startPhoneClient() {
|
|
172
|
-
const accountId = document.getElementById('account_selector').value;
|
|
173
|
-
console.info(`Starting phone client with account id ${accountId}`);
|
|
174
|
-
|
|
175
|
-
// Create call session and get provision token
|
|
176
|
-
jsonApiGetRequest(`/get-call-session/?id=${accountId}`).then(function (data) {
|
|
177
|
-
console.info('Fetched a new call session');
|
|
178
|
-
console.debug(data);
|
|
179
|
-
|
|
180
|
-
// Now prepare media and get access to microphone
|
|
181
|
-
phoneClient.prepareMedia().then(function () {
|
|
182
|
-
// Media was prepared, now hook up events to display whats going on
|
|
183
|
-
|
|
184
|
-
// Connection state shows the client connection to the phone services
|
|
185
|
-
phoneClient.on('connectionStateChange', function (event) {
|
|
186
|
-
console.info(`Phone connection is now: ${event.state}`);
|
|
187
|
-
document.getElementById('conn_status').innerHTML = event.state;
|
|
188
|
-
});
|
|
189
|
-
|
|
190
|
-
// Get local information about call after it has ended
|
|
191
|
-
phoneClient.on('callEnded', function (data) {
|
|
192
|
-
console.info('Call ended event:');
|
|
193
|
-
console.info(data);
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
// Get remote information about call after it has ended
|
|
197
|
-
phoneClient.on('callDataInfo', function (data) {
|
|
198
|
-
console.info('Call data info event:');
|
|
199
|
-
console.info(data);
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
// New session created
|
|
203
|
-
phoneClient.on('sessionCreated', function (data) {
|
|
204
|
-
newSession(data.session);
|
|
205
|
-
});
|
|
206
|
-
|
|
207
|
-
// Session removed
|
|
208
|
-
phoneClient.on('sessionRemoved', function (data) {
|
|
209
|
-
console.log(data);
|
|
210
|
-
removeSession(data.session);
|
|
211
|
-
});
|
|
212
|
-
|
|
213
|
-
// Show incoming call
|
|
214
|
-
phoneClient.on('incomingCall', function (data) {
|
|
215
|
-
console.log(`Incoming call from ${data.originatingNumber}`);
|
|
216
|
-
});
|
|
217
|
-
|
|
218
|
-
// Now start phone with the following options
|
|
219
|
-
const opts = {
|
|
220
|
-
// Enable event client
|
|
221
|
-
connectEventService: true,
|
|
222
|
-
|
|
223
|
-
// Subscribe to detailed information about call after processing
|
|
224
|
-
useCallDataInfoEvent: true,
|
|
225
|
-
|
|
226
|
-
// Enable incoming calls (you must set a phone number to call the account also)
|
|
227
|
-
register: true,
|
|
228
|
-
|
|
229
|
-
// Configure client with provision token
|
|
230
|
-
provisionToken: data.provision_token,
|
|
231
|
-
|
|
232
|
-
// Enable signal tones (busy, invalid, etc)
|
|
233
|
-
playSignalTones: true,
|
|
234
|
-
|
|
235
|
-
// Enable call initialized tone
|
|
236
|
-
playCallInitializedTone: true
|
|
237
|
-
};
|
|
289
|
+
// Include this to force a specific smart cid (use id of shot-cid from api service)
|
|
290
|
+
// explicitShortCallerId: 1,
|
|
238
291
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
}
|
|
246
|
-
}, function (reason) {
|
|
247
|
-
console.error('Unable to get media permission: ' + reason);
|
|
292
|
+
// Configure answer call timeout
|
|
293
|
+
answerCallTimeout: 0,
|
|
294
|
+
|
|
295
|
+
// Add meta info to call
|
|
296
|
+
metaInfo:
|
|
297
|
+
'You can add up to 256 bytes of meta info for your call (including json like {"type": "json"})',
|
|
248
298
|
});
|
|
249
|
-
}, function (reason) {
|
|
250
|
-
console.error(`Request failed ${reason}`);
|
|
251
|
-
});
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
// Stop phone client
|
|
255
|
-
function stopPhoneClient() {
|
|
256
|
-
phoneClient.stop();
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
/*
|
|
260
|
-
* STEP 3: Make a test call
|
|
261
|
-
*/
|
|
262
|
-
function makeCall() {
|
|
263
|
-
const destination_number = document.getElementById('destination_number').value;
|
|
264
|
-
phoneClient.call(destination_number, {
|
|
265
|
-
// Change this to number of days to keep recording (enables recording)
|
|
266
|
-
record: 0,
|
|
267
|
-
|
|
268
|
-
// Change this maximum amount in customer currency the call must cost before hanging up (0 = no checking)
|
|
269
|
-
maximumCallCost: 0,
|
|
270
|
-
|
|
271
|
-
// Include this to force a specific caller id (use id of phone number from api service)
|
|
272
|
-
// explicitCallerId: 35,
|
|
273
|
-
|
|
274
|
-
// Include this to force a specific smart cid (use id of shot-cid from api service)
|
|
275
|
-
// explicitShortCallerId: 1,
|
|
276
|
-
|
|
277
|
-
// Configure answer call timeout
|
|
278
|
-
answerCallTimeout: 0,
|
|
279
|
-
|
|
280
|
-
// Add meta info to call
|
|
281
|
-
metaInfo: 'You can add up to 256 bytes of meta info for your call (including json like {"type": "json"})'
|
|
282
|
-
});
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
// Set the source of call transfer and populate transfer destination selector
|
|
286
|
-
function setTransferSession(session) {
|
|
287
|
-
transferSession = session;
|
|
288
|
-
|
|
289
|
-
var otherSessions = session.getOtherSessions();
|
|
290
|
-
if (otherSessions.length < 1) {
|
|
291
|
-
document.getElementById('transfer_from').innerHTML = 'Requires two active sessions to perform transfer!';
|
|
292
|
-
return;
|
|
293
299
|
}
|
|
294
300
|
|
|
295
|
-
//
|
|
296
|
-
|
|
301
|
+
// Set the source of call transfer and populate transfer destination selector
|
|
302
|
+
function setTransferSession(session) {
|
|
303
|
+
transferSession = session;
|
|
297
304
|
|
|
298
|
-
|
|
299
|
-
|
|
305
|
+
var otherSessions = session.getOtherSessions();
|
|
306
|
+
if (otherSessions.length < 1) {
|
|
307
|
+
document.getElementById('transfer_from').innerHTML =
|
|
308
|
+
'Requires two active sessions to perform transfer!';
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
300
311
|
|
|
301
|
-
|
|
302
|
-
document.getElementById('
|
|
303
|
-
}
|
|
304
|
-
}
|
|
312
|
+
// Show source call destination number
|
|
313
|
+
document.getElementById('transfer_from').innerHTML = session.destinationNumber + ' => ';
|
|
305
314
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
if (!transferSession) {
|
|
309
|
-
console.error('No session selected');
|
|
310
|
-
return;
|
|
311
|
-
}
|
|
315
|
+
// Add all other sessions to transfer selector
|
|
316
|
+
document.getElementById('transfer_selector').innerHTML = '';
|
|
312
317
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
// Create listen session
|
|
321
|
-
function doListen() {
|
|
322
|
-
phoneClient.listen(document.getElementById('listen_key').value);
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
// Playback message
|
|
326
|
-
function playback(session) {
|
|
327
|
-
const hangup_after = false;
|
|
328
|
-
session.playback(document.getElementById('media_file_selector').value, hangup_after).then(() => {
|
|
329
|
-
console.info('Playback started');
|
|
330
|
-
})
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
/*
|
|
334
|
-
* Helper functions
|
|
335
|
-
*/
|
|
336
|
-
|
|
337
|
-
// Create new session
|
|
338
|
-
// Add table row for session using session_<uuid> as element id,
|
|
339
|
-
// (We do this so we can find and remove row when session ends)
|
|
340
|
-
function newSession(session) {
|
|
341
|
-
const rowId = `session_${session.uuid}`;
|
|
342
|
-
|
|
343
|
-
// Create row in table for session
|
|
344
|
-
const table = document.getElementById("session_table");
|
|
345
|
-
const newRow = table.insertRow();
|
|
346
|
-
newRow.id = rowId;
|
|
347
|
-
for (let i = 0; i < table.rows[0].cells.length; i++)
|
|
348
|
-
newRow.insertCell();
|
|
349
|
-
|
|
350
|
-
// Set cells
|
|
351
|
-
newRow.cells[0].innerText = session.direction;
|
|
352
|
-
|
|
353
|
-
// Show name of local number called for inbound
|
|
354
|
-
if (session.localNumberName) {
|
|
355
|
-
newRow.cells[1].innerText = session.destinationNumber + ' (' + session.localNumberName + ')';
|
|
356
|
-
} else {
|
|
357
|
-
newRow.cells[1].innerText = session.destinationNumber;
|
|
318
|
+
for (const tSession of otherSessions) {
|
|
319
|
+
document
|
|
320
|
+
.getElementById('transfer_selector')
|
|
321
|
+
.appendChild(new Option(tSession.destinationNumber, tSession.uuid));
|
|
322
|
+
}
|
|
358
323
|
}
|
|
359
324
|
|
|
360
|
-
//
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
// Add failure cause
|
|
366
|
-
if (event.state === 'FAILED') {
|
|
367
|
-
newRow.cells[2].innerHTML = newRow.cells[2].innerHTML + ` (${event.cause})`;
|
|
325
|
+
// Transfer call from "transferSession" to item in transfer_selector
|
|
326
|
+
function doCallTransfer() {
|
|
327
|
+
if (!transferSession) {
|
|
328
|
+
console.error('No session selected');
|
|
329
|
+
return;
|
|
368
330
|
}
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
console.info(`Recording state changed to ${data.state}`);
|
|
376
|
-
newRow.cells[6].innerHTML = data.state;
|
|
377
|
-
});
|
|
378
|
-
|
|
379
|
-
// Get mute state events
|
|
380
|
-
newRow.cells[5].innerHTML = session.isMuted;
|
|
381
|
-
session.on('muteStateChange', function (data) {
|
|
382
|
-
console.info(`Microphone mute state changed to ${data.state}`);
|
|
383
|
-
newRow.cells[5].innerHTML = data.state;
|
|
384
|
-
});
|
|
385
|
-
|
|
386
|
-
// Get hold state events
|
|
387
|
-
newRow.cells[7].innerHTML = session.isOnHold;
|
|
388
|
-
session.on('holdStateChange', function (data) {
|
|
389
|
-
console.info(`Call hold state changed to ${data.state}`);
|
|
390
|
-
newRow.cells[7].innerHTML = data.state;
|
|
391
|
-
});
|
|
392
|
-
|
|
393
|
-
// Get call duration update events
|
|
394
|
-
session.on('callDurationUpdate', function (data) {
|
|
395
|
-
newRow.cells[3].innerHTML = `${data.durationStr} (${data.activeDurationStr})`;
|
|
396
|
-
});
|
|
397
|
-
|
|
398
|
-
// Get call duration update events
|
|
399
|
-
session.on('callQualityReportUpdate', function (data) {
|
|
400
|
-
console.info('Call quality report:');
|
|
401
|
-
console.info(data);
|
|
402
|
-
newRow.cells[4].innerHTML = `${data.delta.effectiveLatency.toFixed(1)} ms (${data.delta.rFactor.toFixed(1)} R)`;
|
|
403
|
-
});
|
|
404
|
-
|
|
405
|
-
// Get local information about call after it has ended
|
|
406
|
-
session.on('callEnded', function (data) {
|
|
407
|
-
console.info('Call ended event:');
|
|
408
|
-
console.debug(data);
|
|
409
|
-
});
|
|
410
|
-
|
|
411
|
-
session.on('whisperModeChange', function (data) {
|
|
412
|
-
console.info('Whisper mode: ' + data.mode);
|
|
413
|
-
});
|
|
414
|
-
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
// Remove table row for session
|
|
418
|
-
function removeSession(session) {
|
|
419
|
-
const row = document.getElementById(`session_${session.uuid}`);
|
|
420
|
-
if (row) {
|
|
421
|
-
row.parentNode.removeChild(row);
|
|
331
|
+
|
|
332
|
+
// Use session uuid from selectbox and get session object
|
|
333
|
+
const dstSession = phoneClient.getSessionByUUID(document.getElementById('transfer_selector').value);
|
|
334
|
+
|
|
335
|
+
// Now do transfer
|
|
336
|
+
transferSession.transfer(dstSession);
|
|
422
337
|
}
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
// Remove all buttons first
|
|
428
|
-
let e = element.firstElementChild;
|
|
429
|
-
while (e) {
|
|
430
|
-
e.remove();
|
|
431
|
-
e = element.firstElementChild;
|
|
338
|
+
|
|
339
|
+
// Create listen session
|
|
340
|
+
function doListen() {
|
|
341
|
+
phoneClient.listen(document.getElementById('listen_key').value);
|
|
432
342
|
}
|
|
433
343
|
|
|
434
|
-
//
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
btn.innerHTML = 'Hangup';
|
|
441
|
-
btn.onclick = function () {
|
|
442
|
-
this.parentNode._session.hangup();
|
|
443
|
-
};
|
|
444
|
-
element.appendChild(btn)
|
|
344
|
+
// Playback message
|
|
345
|
+
function playback(session) {
|
|
346
|
+
const hangup_after = false;
|
|
347
|
+
session.playback(document.getElementById('media_file_selector').value, hangup_after).then(() => {
|
|
348
|
+
console.info('Playback started');
|
|
349
|
+
});
|
|
445
350
|
}
|
|
446
351
|
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
352
|
+
/*
|
|
353
|
+
* Helper functions
|
|
354
|
+
*/
|
|
355
|
+
|
|
356
|
+
// Create new session
|
|
357
|
+
// Add table row for session using session_<uuid> as element id,
|
|
358
|
+
// (We do this so we can find and remove row when session ends)
|
|
359
|
+
function newSession(session) {
|
|
360
|
+
const rowId = `session_${session.uuid}`;
|
|
361
|
+
|
|
362
|
+
// Create row in table for session
|
|
363
|
+
const table = document.getElementById('session_table');
|
|
364
|
+
const newRow = table.insertRow();
|
|
365
|
+
newRow.id = rowId;
|
|
366
|
+
for (let i = 0; i < table.rows[0].cells.length; i++) newRow.insertCell();
|
|
367
|
+
|
|
368
|
+
// Set cells
|
|
369
|
+
newRow.cells[0].innerText = session.direction;
|
|
370
|
+
|
|
371
|
+
// Show name of local number called for inbound
|
|
372
|
+
if (session.localNumberName) {
|
|
373
|
+
newRow.cells[1].innerText = session.destinationNumber + ' (' + session.localNumberName + ')';
|
|
374
|
+
} else {
|
|
375
|
+
newRow.cells[1].innerText = session.destinationNumber;
|
|
376
|
+
}
|
|
458
377
|
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
378
|
+
// Hookup events
|
|
379
|
+
// Session state show the current calling state
|
|
380
|
+
session.on('sessionStateChange', function (event) {
|
|
381
|
+
console.info(`Phone session is now: ${event.state}`);
|
|
382
|
+
newRow.cells[2].innerHTML = event.state;
|
|
383
|
+
// Add failure cause
|
|
384
|
+
if (event.state === 'FAILED') {
|
|
385
|
+
newRow.cells[2].innerHTML = newRow.cells[2].innerHTML + ` (${event.cause})`;
|
|
386
|
+
}
|
|
387
|
+
updateButtons(newRow.cells[8], session);
|
|
388
|
+
});
|
|
465
389
|
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
390
|
+
// Get record state events
|
|
391
|
+
newRow.cells[6].innerHTML = session.isRecording;
|
|
392
|
+
session.on('recordingStateChange', function (data) {
|
|
393
|
+
console.info(`Recording state changed to ${data.state}`);
|
|
394
|
+
newRow.cells[6].innerHTML = data.state;
|
|
395
|
+
});
|
|
472
396
|
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
397
|
+
// Get mute state events
|
|
398
|
+
newRow.cells[5].innerHTML = session.isMuted;
|
|
399
|
+
session.on('muteStateChange', function (data) {
|
|
400
|
+
console.info(`Microphone mute state changed to ${data.state}`);
|
|
401
|
+
newRow.cells[5].innerHTML = data.state;
|
|
402
|
+
});
|
|
479
403
|
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
404
|
+
// Get hold state events
|
|
405
|
+
newRow.cells[7].innerHTML = session.isOnHold;
|
|
406
|
+
session.on('holdStateChange', function (data) {
|
|
407
|
+
console.info(`Call hold state changed to ${data.state}`);
|
|
408
|
+
newRow.cells[7].innerHTML = data.state;
|
|
409
|
+
});
|
|
486
410
|
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
};
|
|
492
|
-
element.appendChild(btn6);
|
|
411
|
+
// Get call duration update events
|
|
412
|
+
session.on('callDurationUpdate', function (data) {
|
|
413
|
+
newRow.cells[3].innerHTML = `${data.durationStr} (${data.activeDurationStr})`;
|
|
414
|
+
});
|
|
493
415
|
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
416
|
+
// Get call duration update events
|
|
417
|
+
session.on('callQualityReportUpdate', function (data) {
|
|
418
|
+
console.info('Call quality report:');
|
|
419
|
+
console.info(data);
|
|
420
|
+
newRow.cells[4].innerHTML = `${data.delta.effectiveLatency.toFixed(1)} ms (${data.delta.rFactor.toFixed(
|
|
421
|
+
1,
|
|
422
|
+
)} R)`;
|
|
423
|
+
});
|
|
424
|
+
|
|
425
|
+
// Get local information about call after it has ended
|
|
426
|
+
session.on('callEnded', function (data) {
|
|
427
|
+
console.info('Call ended event:');
|
|
428
|
+
console.debug(data);
|
|
429
|
+
});
|
|
430
|
+
|
|
431
|
+
session.on('whisperModeChange', function (data) {
|
|
432
|
+
console.info('Whisper mode: ' + data.mode);
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
// Remove table row for session
|
|
437
|
+
function removeSession(session) {
|
|
438
|
+
const row = document.getElementById(`session_${session.uuid}`);
|
|
439
|
+
if (row) {
|
|
440
|
+
row.parentNode.removeChild(row);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
// Add buttons based on session state on element (the table row)
|
|
445
|
+
function updateButtons(element, session) {
|
|
446
|
+
// Remove all buttons first
|
|
447
|
+
let e = element.firstElementChild;
|
|
448
|
+
while (e) {
|
|
449
|
+
e.remove();
|
|
450
|
+
e = element.firstElementChild;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
// Put session on TD element, so buttons can use it
|
|
454
|
+
element._session = session;
|
|
455
|
+
|
|
456
|
+
// NON TERMINATED/INCOMING/FAILED BUTTONS
|
|
457
|
+
if (session.state !== 'TERMINATED' && session.state !== 'INCOMING' && session.state !== 'FAILED') {
|
|
458
|
+
const btn = document.createElement('BUTTON');
|
|
459
|
+
btn.innerHTML = 'Hangup';
|
|
460
|
+
btn.onclick = function () {
|
|
461
|
+
this.parentNode._session.hangup();
|
|
498
462
|
};
|
|
499
|
-
element.appendChild(
|
|
463
|
+
element.appendChild(btn);
|
|
500
464
|
}
|
|
501
465
|
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
466
|
+
if (session.direction === 'OUTBOUND' || session.direction === 'INBOUND') {
|
|
467
|
+
// ACTIVE CALL BUTTONS
|
|
468
|
+
if (session.state === 'ACTIVE' || session.state === 'ON_HOLD') {
|
|
469
|
+
const btn = document.createElement('BUTTON');
|
|
470
|
+
btn.innerHTML = 'Play tone';
|
|
471
|
+
btn.onclick = function () {
|
|
472
|
+
phoneClient.playTone(1000, 440, 880, function () {
|
|
473
|
+
console.info('Play tone complete!');
|
|
474
|
+
});
|
|
475
|
+
};
|
|
476
|
+
element.appendChild(btn);
|
|
477
|
+
|
|
478
|
+
const btn2 = document.createElement('BUTTON');
|
|
479
|
+
btn2.innerHTML = 'Send DTMF 1';
|
|
480
|
+
btn2.onclick = function () {
|
|
481
|
+
this.parentNode._session.sendDTMF(1);
|
|
482
|
+
};
|
|
483
|
+
element.appendChild(btn2);
|
|
484
|
+
|
|
485
|
+
const btn3 = document.createElement('BUTTON');
|
|
486
|
+
btn3.innerHTML = 'Toggle mute mic';
|
|
487
|
+
btn3.onclick = function () {
|
|
488
|
+
this.parentNode._session.toggleMute();
|
|
489
|
+
};
|
|
490
|
+
element.appendChild(btn3);
|
|
491
|
+
|
|
492
|
+
const btn4 = document.createElement('BUTTON');
|
|
493
|
+
btn4.innerHTML = 'Toggle recording';
|
|
494
|
+
btn4.onclick = function () {
|
|
495
|
+
this.parentNode._session.toggleRecording();
|
|
496
|
+
};
|
|
497
|
+
element.appendChild(btn4);
|
|
498
|
+
|
|
499
|
+
const btn5 = document.createElement('BUTTON');
|
|
500
|
+
btn5.innerHTML = 'Toggle hold';
|
|
501
|
+
btn5.onclick = function () {
|
|
502
|
+
this.parentNode._session.toggleHold();
|
|
503
|
+
};
|
|
504
|
+
element.appendChild(btn5);
|
|
505
|
+
|
|
506
|
+
const btn6 = document.createElement('BUTTON');
|
|
507
|
+
btn6.innerHTML = 'Transfer';
|
|
508
|
+
btn6.onclick = function () {
|
|
509
|
+
setTransferSession(this.parentNode._session);
|
|
510
|
+
};
|
|
511
|
+
element.appendChild(btn6);
|
|
512
|
+
|
|
513
|
+
const btn7 = document.createElement('BUTTON');
|
|
514
|
+
btn7.innerHTML = 'Playback';
|
|
515
|
+
btn7.onclick = function () {
|
|
516
|
+
playback(this.parentNode._session);
|
|
517
|
+
};
|
|
518
|
+
element.appendChild(btn7);
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
// INCOMING BUTTONS
|
|
522
|
+
if (session.state === 'INCOMING') {
|
|
523
|
+
const btn = document.createElement('BUTTON');
|
|
524
|
+
btn.innerHTML = 'Answer';
|
|
525
|
+
btn.onclick = function () {
|
|
526
|
+
this.parentNode._session.answer(
|
|
527
|
+
(metaInfo = 'When answering calls you can add meta info as well'),
|
|
528
|
+
);
|
|
529
|
+
};
|
|
530
|
+
element.appendChild(btn);
|
|
531
|
+
|
|
532
|
+
const btn2 = document.createElement('BUTTON');
|
|
533
|
+
btn2.innerHTML = 'Reject';
|
|
534
|
+
btn2.onclick = function () {
|
|
535
|
+
this.parentNode._session.reject();
|
|
536
|
+
};
|
|
537
|
+
element.appendChild(btn2);
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
// LISTEN BUTTONS
|
|
542
|
+
if (session.direction === 'LISTEN' && session.state === 'ACTIVE') {
|
|
543
|
+
const btn = document.createElement('BUTTON');
|
|
544
|
+
btn.innerHTML = 'Start whisper';
|
|
506
545
|
btn.onclick = function () {
|
|
507
|
-
this.parentNode._session.
|
|
546
|
+
this.parentNode._session.setWhisperMode(1);
|
|
508
547
|
};
|
|
509
548
|
element.appendChild(btn);
|
|
510
549
|
|
|
511
|
-
const btn2 = document.createElement(
|
|
512
|
-
btn2.innerHTML = '
|
|
550
|
+
const btn2 = document.createElement('BUTTON');
|
|
551
|
+
btn2.innerHTML = 'End whisper';
|
|
513
552
|
btn2.onclick = function () {
|
|
514
|
-
this.parentNode._session.
|
|
553
|
+
this.parentNode._session.setWhisperMode(0);
|
|
515
554
|
};
|
|
516
555
|
element.appendChild(btn2);
|
|
517
556
|
}
|
|
518
557
|
}
|
|
519
558
|
|
|
520
|
-
//
|
|
521
|
-
|
|
522
|
-
const
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
// Perform authenticated ajax request to api server and return json payload on success
|
|
539
|
-
function jsonApiGetRequest(path) {
|
|
540
|
-
const xhr = new XMLHttpRequest();
|
|
541
|
-
const url = API_URL + path;
|
|
542
|
-
xhr.open('GET', url, true);
|
|
543
|
-
xhr.responseType = 'json';
|
|
544
|
-
const apiToken = document.getElementById('api_key').value;
|
|
545
|
-
xhr.setRequestHeader('Authorization', 'Bearer ' + apiToken);
|
|
546
|
-
xhr.setRequestHeader('Accept', 'application/json');
|
|
547
|
-
|
|
548
|
-
return new Promise(function (resolve, reject) {
|
|
549
|
-
xhr.onreadystatechange = function () {
|
|
550
|
-
if (xhr.readyState === 4) {
|
|
551
|
-
if (xhr.status !== 200) {
|
|
552
|
-
reject(xhr.status + ' ' + xhr.statusText);
|
|
553
|
-
return;
|
|
559
|
+
// Perform authenticated ajax request to api server and return json payload on success
|
|
560
|
+
function jsonApiGetRequest(path) {
|
|
561
|
+
const xhr = new XMLHttpRequest();
|
|
562
|
+
const url = API_URL + path;
|
|
563
|
+
xhr.open('GET', url, true);
|
|
564
|
+
xhr.responseType = 'json';
|
|
565
|
+
const apiToken = document.getElementById('api_key').value;
|
|
566
|
+
xhr.setRequestHeader('Authorization', 'Bearer ' + apiToken);
|
|
567
|
+
xhr.setRequestHeader('Accept', 'application/json');
|
|
568
|
+
|
|
569
|
+
return new Promise(function (resolve, reject) {
|
|
570
|
+
xhr.onreadystatechange = function () {
|
|
571
|
+
if (xhr.readyState === 4) {
|
|
572
|
+
if (xhr.status !== 200) {
|
|
573
|
+
reject(xhr.status + ' ' + xhr.statusText);
|
|
574
|
+
return;
|
|
575
|
+
}
|
|
576
|
+
resolve(xhr.response);
|
|
554
577
|
}
|
|
555
|
-
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
}
|
|
562
|
-
</script>
|
|
563
|
-
|
|
578
|
+
};
|
|
579
|
+
console.debug(`API Request: ${url}`);
|
|
580
|
+
xhr.send();
|
|
581
|
+
});
|
|
582
|
+
}
|
|
583
|
+
</script>
|
|
564
584
|
</html>
|