Skip to contentSkip to navigationSkip to topbar
On this page

Control Worker Activities using Worker.js: Add an Agent UI to our Project


Let's get started on our agent UI. Assuming you've followed the conventions so far in this tutorial, the UI we create will be accessible using your web browser at:

http://localhost:8080/agent.cshtml?WorkerSid=WK01234012340123401234 (substitute your Alice's WorkerSid)

We pass the WorkerSid in the URL to avoid implementing complex user management in our demo. In reality, you are likely to store a user's WorkerSid in your database alongside other User attributes.

Now create a CSHTML file that will be rendered when the URL is requested:


agent.cshtml

agentcshtml page anchor
1
@using System;
2
@using System.Collections.Generic;
3
@using Twilio;
4
@using Twilio.Http;
5
@using Twilio.Jwt.Taskrouter;
6
7
@{
8
class PolicyUrlUtils
9
{
10
const string taskRouterBaseUrl = "https://taskrouter.twilio.com";
11
const string taskRouterVersion = "v1";
12
13
readonly string _workspaceSid;
14
readonly string _workerSid;
15
16
public PolicyUrlUtils(string workspaceSid, string workerSid)
17
{
18
_workspaceSid = workspaceSid;
19
_workerSid = workerSid;
20
}
21
22
public string AllTasks => $"{Workspace}/Tasks/**";
23
24
public string Worker => $"{Workspace}/Workers/{_workerSid}";
25
26
public string AllReservations => $"{Worker}/Reservations/**";
27
28
public string Workspace =>
29
$"{taskRouterBaseUrl}/{taskRouterVersion}/Workspaces/{_workspaceSid}";
30
31
public string Activities => $"{Workspace}/Activities";
32
33
}
34
35
@{
36
// put your Twilio API credentials here
37
const string accountSid = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
38
const string authToken = "your_auth_token";
39
const string workspaceSid = "WSXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
40
const string workerSid = "WKXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
41
42
var updateActivityFilter = new Dictionary<string, Policy.FilterRequirement>
43
{
44
{ "ActivitySid", Policy.FilterRequirement.Required }
45
};
46
47
var urls = new PolicyUrlUtils(workspaceSid, workerSid);
48
49
var allowActivityUpdates = new Policy(urls.Worker,
50
HttpMethod.Post,
51
postFilter: updateActivityFilter);
52
var allowTasksUpdate = new Policy(urls.AllTasks, HttpMethod.Post);
53
var allowReservationUpdate = new Policy(urls.AllReservations, HttpMethod.Post);
54
var allowWorkerFetches = new Policy(urls.Worker, HttpMethod.Get);
55
var allowTasksFetches = new Policy(urls.AllTasks, HttpMethod.Get );
56
var allowReservationFetches = new Policy(urls.AllReservations, HttpMethod.Get);
57
var allowActivityFetches = new Policy(urls.Activities, HttpMethod.Get);
58
59
var policies = new List<Policy>
60
{
61
allowActivityUpdates,
62
allowTasksUpdate,
63
allowReservationUpdate,
64
allowWorkerFetches,
65
allowTasksFetches,
66
allowReservationFetches
67
68
};
69
70
var capability = new TaskRouterCapability(
71
accountSid,
72
authToken,
73
workspaceSid,
74
workerSid,
75
policies: policies);
76
77
var workerToken = capability.ToJwt();
78
}
79
<!DOCTYPE html>
80
<html>
81
<head>
82
<title>Customer Care - Voice Agent Screen</title>
83
<link rel="stylesheet" href="//media.twiliocdn.com/taskrouter/quickstart/agent.css"/>
84
<script src="https://sdk.twilio.com/js/taskrouter/v1.21/taskrouter.min.js" integrity="sha384-5fq+0qjayReAreRyHy38VpD3Gr9R2OYIzonwIkoGI4M9dhfKW6RWeRnZjfwSrpN8" crossorigin="anonymous"></script>
85
<script type="text/javascript">
86
/* Subscribe to a subset of the available TaskRouter.js events for a worker */
87
function registerTaskRouterCallbacks() {
88
worker.on('ready', function(worker) {
89
agentActivityChanged(worker.activityName);
90
logger("Successfully registered as: " + worker.friendlyName)
91
logger("Current activity is: " + worker.activityName);
92
});
93
94
worker.on('activity.update', function(worker) {
95
agentActivityChanged(worker.activityName);
96
logger("Worker activity changed to: " + worker.activityName);
97
});
98
99
worker.on("reservation.created", function(reservation) {
100
logger("-----");
101
logger("You have been reserved to handle a call!");
102
logger("Call from: " + reservation.task.attributes.from);
103
logger("Selected language: " + reservation.task.attributes.selected_language);
104
logger("-----");
105
});
106
107
worker.on("reservation.accepted", function(reservation) {
108
logger("Reservation " + reservation.sid + " accepted!");
109
});
110
111
worker.on("reservation.rejected", function(reservation) {
112
logger("Reservation " + reservation.sid + " rejected!");
113
});
114
115
worker.on("reservation.timeout", function(reservation) {
116
logger("Reservation " + reservation.sid + " timed out!");
117
});
118
119
worker.on("reservation.canceled", function(reservation) {
120
logger("Reservation " + reservation.sid + " canceled!");
121
});
122
}
123
124
/* Hook up the agent Activity buttons to TaskRouter.js */
125
126
function bindAgentActivityButtons() {
127
// Fetch the full list of available Activities from TaskRouter. Store each
128
// ActivitySid against the matching Friendly Name
129
var activitySids = {};
130
worker.activities.fetch(function(error, activityList) {
131
var activities = activityList.data;
132
var i = activities.length;
133
while (i--) {
134
activitySids[activities[i].friendlyName] = activities[i].sid;
135
}
136
});
137
138
/* For each button of class 'change-activity' in our Agent UI, look up the
139
ActivitySid corresponding to the Friendly Name in the button's next-activity
140
data attribute. Use Worker.js to transition the agent to that ActivitySid
141
when the button is clicked.*/
142
var elements = document.getElementsByClassName('change-activity');
143
var i = elements.length;
144
while (i--) {
145
elements[i].onclick = function() {
146
var nextActivity = this.dataset.nextActivity;
147
var nextActivitySid = activitySids[nextActivity];
148
worker.update({"ActivitySid":nextActivitySid});
149
}
150
}
151
}
152
153
/* Update the UI to reflect a change in Activity */
154
155
function agentActivityChanged(activity) {
156
hideAgentActivities();
157
showAgentActivity(activity);
158
}
159
160
function hideAgentActivities() {
161
var elements = document.getElementsByClassName('agent-activity');
162
var i = elements.length;
163
while (i--) {
164
elements[i].style.display = 'none';
165
}
166
}
167
168
function showAgentActivity(activity) {
169
activity = activity.toLowerCase();
170
var elements = document.getElementsByClassName(('agent-activity ' + activity));
171
elements.item(0).style.display = 'block';
172
}
173
174
/* Other stuff */
175
176
function logger(message) {
177
var log = document.getElementById('log');
178
log.value += "\n> " + message;
179
log.scrollTop = log.scrollHeight;
180
}
181
182
window.onload = function() {
183
// Initialize TaskRouter.js on page load using window.workerToken -
184
// a Twilio Capability token that was set from rendering the template with agents endpoint
185
logger("Initializing...");
186
window.worker = new Twilio.TaskRouter.Worker("@workerToken");
187
188
registerTaskRouterCallbacks();
189
bindAgentActivityButtons();
190
};
191
</script>
192
</head>
193
<body>
194
<div class="content">
195
<section class="agent-activity offline">
196
<p class="activity">Offline</p>
197
<button class="change-activity" data-next-activity="Idle">Go Available</button>
198
</section>
199
<section class="agent-activity idle">
200
<p class="activity"><span>Available</span></p>
201
<button class="change-activity" data-next-activity="Offline">Go Offline</button>
202
</section>
203
<section class="agent-activity reserved">
204
<p class="activity">Reserved</p>
205
</section>
206
<section class="agent-activity busy">
207
<p class="activity">Busy</p>
208
</section>
209
<section class="agent-activity wrapup">
210
<p class="activity">Wrap-Up</p>
211
<button class="change-activity" data-next-activity="Idle">Go Available</button>
212
<button class="change-activity" data-next-activity="Offline">Go Offline</button>
213
</section>
214
<section class="log">
215
<textarea id="log" readonly="true"></textarea>
216
</section>
217
</div>
218
</body>
219
</html>

You'll notice that we included two external files:

  • taskrouter.min.js is the primary TaskRouter.js JavaScript file that communicates with TaskRouter's infrastructure on our behalf. You can use this URL to include Worker.js in your production application, but first check the reference documentation to ensure that you include the latest version number.
  • agent.css is a simple CSS file created for the purpose of this Quickstart. It saves us having to type out some simple pre-defined styles.

And that's it! Compile your Java class and start your server.

Open http://localhost:8080/agent.cshtml?WorkerSid=WK01234012340123401234 in your browser and you should see the screen below. If you make the same phone call as we made in Part 3, you should see Alice's Activity transition on screen as she is reserved and assigned to handle the Task.

If you see "Initializing..." and no progress, make sure that you have included the correct WorkerSid in the "WorkerSid" request parameter of the URL.

For more details, refer to the TaskRouter JavaScript SDK documentation.


  • This simple PoC has been tested in the latest version of popular browsers, including IE 11. *
Completed Agent UI.

Need some help?

Terms of service

Copyright © 2024 Twilio Inc.