DeskPRO Apps Manual May 20th, 2014 • Revision #2

DeskPRO
Apps Manual
DeskPRO Apps Manual
May 20th, 2014 • Revision #2
DeskPRO
. . . . . . . . . . .Apps
. . . . . . Manual
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1. . . . . . . . . . . . . . . .
About
. . . . . . .Apps
...........................................................................................................2
.................
Regular
. . . . . . . . Apps
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2. . . . . . . . . . . . . . . .
Widgets
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2. . . . . . . . . . . . . . . .
Native
. . . . . . .Apps
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2. . . . . . . . . . . . . . . .
Creating
. . . . . . . . . .Widgets
........................................................................................................3
.................
Editing
. . . . . . . . Widgets
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5. . . . . . . . . . . . . . . .
Javascript
. . . . . . . . . . Controller
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5. . . . . . . . . . . . . . . .
HTML
. . . . . . . Template
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .6. . . . . . . . . . . . . . . .
Example:
. . . . . . . . . . .Link
. . . . . .to
. . CRM
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
..................
Create
. . . . . . .your
. . . . . Widget
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .10
.................
Widget
. . . . . . . .Code
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .10
.................
Example:
. . . . . . . . . . .Consuming
. . . . . . . . . . . . . an
. . . .API
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .12
.................
Create
. . . . . . .your
. . . . . Widget
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .12
.................
Widget
. . . . . . . .Code:
. . . . . . Javascript
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .12
.................
Widget
. . . . . . . .Code:
. . . . . . HTML
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
.................
Loading
. . . . . . . . .Indicator
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .14
................
Iterating
. . . . . . . . .over
. . . . . results
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .14
................
The
. . . . full
. . . . template
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .14
................
More
. . . . . . Examples
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .16
.................
Coding
. . . . . . . . Apps
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .17
.................
Packaging
. . . . . . . . . . . Apps
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .18
.................
Native
. . . . . . . Apps
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .19
.................
DeskPRO Apps Manual
1
DeskPRO
Apps Manual
About Apps
Apps are collections of HTML templates and Javascript controllers that change how DeskPRO looks and
operates.
Throughout the DeskPRO Agent Interface, there are dozens of predefined locations where you can inject
your custom HTML templates (if these predefined locations don't suit you, there are also ways to fine-tune
the insertion point).
Using Javascript, you can add functionality to your HTML to create fully-functional "apps" that live
directly within the DeskPRO interface and have access to the same data that DeskPRO has.
All apps operate in roughly the same way, but there are three broad categories of apps:
Regular Apps
Apps are distributed as ZIP archives. To install an app, you upload it to your helpdesk from the Admin
Interface.
Most Apps are fairly simple and are just a few HTML and Javascript files. But they can get pretty advanced
with multiple source files (e.g., modular Javascript code), external data files, images, and maybe even
settings with an installer.
We'll go over how to create and package apps later in this manual.
Widgets
Widgets are simple apps that you can create and manage completely from within the Admin Interface.
These work in the same was a regular apps, except you edit HTML and Javascript files from the Admin
Interface so you don't have to go through the trouble of packaging and distributing a ZIP file.
Creating widgets is the simplest way to add simple features to your helpdesk right now with little learning
curve.
Native Apps
Finally, for customers who run DeskPRO on their own server, you have the ability to create Native Apps. A
native app is exactly the same as a regular app except you also have the ability to run native PHP code.
There aren't many cases where you would need to use a Native App instead of a regular app. In the
majority of cases, it's easier to consume a web service from an app (via Javscript/AJAX) instead of using
native PHP code executed by DeskPRO. But if you really need it, the option is there.
About Apps
2
DeskPRO
Apps Manual
Creating Widgets
Creating and managing widgets is done entirely from the Admin Interface. Go to the Apps sections and
then click the Create Widget button.
You will see the New Widget form which is where you define the properties of your widget. To start with,
give your widget a meaningful title that describes its purpose. The title is only used in the Admin Interface
so it's mainly just a reminder to yourself.
The next sections, Tickets, Users, and Organizations, let you define where you want to add your HTML and
Javascript to.
In the above screenshot, I've selected a single Ticket location, "A new tab in the properties box". This
renders my HTML template into a new tab at the top of the Ticket view:
Creating Widgets
3
DeskPRO
Apps Manual
You can select as many locations as you want to.
Creating Widgets
4
DeskPRO
Apps Manual
Editing Widgets
After you have created a widget, select it from the "Your Widgets" section of the Apps area in the Admin
Interface.
The first thing you see is this App Definition. It looks a little scary, but you can ignore this section entirely.
It was automatically generated by DeskPRO and you will probably never need to edit it.
The fact is that Widgets are actually fully-feautred Apps under-the-covers, and
the App Definition is how an app configures itself. It tells DeskPRO which
templates you have defined and where to put them.
Ignore the first App Definition tab and switch to any of the other tabs which contain the HTML and
Javascript templates you can edit to actually add content to your widget.
For every location you checked during the widget creation step, you will have two files: A Javascript
controller and an HTML template.
Javascript Controller
The Javascript file is what we call a controller. Here is where you can add custom Javascript code like AJAX
calls or event handlers. All of your JS code should live within that one function controller.
You'll notice that the default JS controller accepts a number of paramaters. The next section goes into
more detail about how JS controllers work, but briefly:
Editing Widgets
5
DeskPRO
Apps Manual
$scope is a special object that lets you connect your JS controller to your HTML template. Any
value you assign to $scope will be available from your template. We'll go over a few examples
in a moment.
$ticket is an object containing all of the current ticket information including things like the
ticket ID, the subject, the user, the user email etc. There is a lot of information here. To view the
available values, the easiest thing to do is use console.log($ticket) and then view your browser
console (e.g., Chrome Developer Console).
If you specified a different tab type, such as a user or organization profile, you won't see
$ticket . Instead you'll have $person or $org which are user info and org info,
respectively.
$person
$http
is also available on tickets, it's an alias for
$ticket.person .
is a service for performing AJAX requests. We'll go over a few examples below.
$el contains a jQuery-wrapped element that is the outer container for your HTML template.
You can use this to fine specific elements in your HTML template. For example,
$el.find('input') to find an input box.
Note that there are much better ways than using jQuery for connecting your JS
controller to your template. The next section goes into more detail.
$app is a reference to the Javascript object that represents your widget app. It includes things
like your app ID. You probably will never need to use this.
HTML Template
Below the JS file is the HTML template file. This HTML template has special features attached to it that
makes it easy to interact with the JS controller. We go into more detail in the next section, but here are a
few examples.
Binding variables
Perhaps the most common thing you will want to do is to render values from your JS controller in your
HTML template. For example, perhaps you have done an AJAX lookup and want to render the results.
To do this, just assign values to the
$scope
variable in your controller:
$scope.name = 'Christopher'
Then within your HTML template, use the variable syntax:
Hello, {{name}}
You can even use variables to generate things like links:
<a href="http://example.com/script?name={{name}}">Hello, {{name}}</a>
Attaching click events
You could use jQuery and the
to do it.
$el
variable to manually attach events. But there is a much cleaner way
First, define a function callback on your
$scope :
$scope.submitForm = function() {
alert("Hello!");
}
Editing Widgets
6
DeskPRO
Apps Manual
Then in your HTML template, use the special
ng-click
attribute on an element:
<button ng-click="submitForm()">Submit</button>
Conditionally showing an element
Use the special
expression:
attribute on an element to conditionally show an element based on a Javascript
ng-if
<div ng-if="name">Hello, {{name}}</div>
<div ng-if="!name">You have no name</div>
Binding form controls
Binding form values can be done with the special
ng-model attribute. When the form input changes,
the target variable will be set on your Javascript $scope variable.
Enter your name: <input type="text" ng-model="name" />
<button ng-click="submitForm()">Submit</button
// Javascript
$scope.submitForm = function() {
alert("Hello, " + $scope.name + "!");
}
Iterating over a collection
If you have an array of data in your Javascript controller:
$scope.family = [
{ name: "John", age: 38 },
{ name: "Jane", age: 36 },
{ name: "Jesse", age: 12 }
];
... then you can iterate over those values in your template with
ng-repeat :
<ul>
<li ng-repeat="p in family">
{{p.name}} is {{p.age}}
</li>
</ul>
Using data from the ticket
Use the
$ticket
object. Here are some commonly used values:
$ticket.id
Editing Widgets
- The ticket ID
7
DeskPRO
Apps Manual
$ticket.id
- The ticket ID
$ticket.subject
- The ticket subject
$ticket.agent - Is an object containing information for the currently assigned agent:
$ticket.agent.id - The agent ID
$ticket.agent.display_name
- The agent name
$ticket.agent.primary_email.email
- The agents primary email address
$ticket.agent.picture_url_80 - The agents profile picture scaled to 80x80. Replace '80'
with any of these standard sizes: 80, 64, 50, 45, 32, 22, 16
$ticket.agent_team.name
- The name of the currently assigned team
$ticket.department.name
- The name of the assigned department
$ticket.status
- The current status
$ticket.urgency
- The current urgency
$ticket.person - An object containing information about the user who opened the ticket:
$ticket.person.id - The agent ID
$ticket.person.display_name
- The agent name
$ticket.person.primary_email.email
- The agents primary email address
$ticket.person.picture_url_80 - The agents profile picture scaled to 80x80. Replace '80'
with any of these standard sizes: 80, 64, 50, 45, 32, 22, 16
To use these values in your HTML template, you need to assign them to the
$scope :
// Javascript
$scope.user_name = $ticket.person.display_name;
// HTML
Hello, {{user_name}}
Or you could assign the entire ticket object to the scope:
// Javascript
$scope.ticket = $ticket;
// HTML
Subject: {{ticket.subject}}<br/>
User Name: {{ticket.person.display_name}}<br/>
User Email: <a href="mailto:{{ticket.person.primary_email.email}}">{{ticket.person.primary_email.email}}</a>
Performing AJAX requests
Use the
$http
service to perform AJAX requests.
The Apps system is powered by a framework called AngularJS, and
$http is a
built-in service. You can refer to the official documentation for detailed API
information: https://docs.angularjs.org/api/ng/service/$http
Editing Widgets
8
DeskPRO
Apps Manual
Here's an example of using $http to perform an AJAX call to a web-service. After the result comes back,
see how we assign the value to $scope which we use in the template:
// Javascript
$scope.is_loading = true;
$http.get('/web-service').success(function(data) {
$scope.is_loading = false;
$scope.customer = data.customer;
});
// HTML
<div ng-if="is_loading">Loading results, please wait...</div>
<div ng-if="!is_loading">
Customer ID: {{customer.id}}
</div>
Note that due to a browser security feature called same-origin policy , you cannot use AJAX to load web
services from external domains. For example, if your helpdesk is on support.example.com you cannot
use $http to perform AJAX requests against other-domain.com because the domain is different and
the browser will reject the request.
If your API supports JSONP, you can use that method instead via
$http.jsonp . Otherwise, you can use
the DeskPRO proxy service which allows you to proxy a AJAX requests through DeskPRO to make remote
API calls:
var params = {
url:
'http://other-domain.com/api/some-service',
email_address: $ticket.person.primary_email.email,
other_params: 'example',
something:
'these other params will be passed as-is to your remote service'
};
$http.get('DP_URL/agent/misc/proxy', {params: params}).siccess(function(data) {
// ...
});
Note that the special DP_URL
to the URL of your helpdesk.
prefix in the URL will be automatically replaced
Much more...
There is much much more you can do with your Javascript and HTML templates that we will go over in
the next section.
Editing Widgets
9
DeskPRO
Apps Manual
Example: Link to CRM
One of the simplest examples would be to create a widget that displays a link to an external system, such
as a CRM.
Most CRMs offer a way to look-up a user based on criteria like an email address. In this example, we use
an app that outputs a link with the users email address in it.
Create your Widget
First, create your app from Admin > Apps > Create Widget like described in the previous section. Select
where you want your link to appear. In this example, we'll create a new section under the properties box:
Widget Code
Switch to the Tickets tab to see the two inputs for our Javascript controller and HTML template. In this
example, we'll be using the users email address to generate a simple HTML link. So in the first box we
need to assign the email address variable to the $scope so it becomes available to the HTML template:
Example: Link to CRM
10
DeskPRO
Apps Manual
define(function() {
return function($scope, $ticket, $person, $http, $el, $app) {
$scope.user_email = $person.primary_email.email;
};
});
Then we are free to use the new
user_email variable in our HTML template. Here's an example
template. It has a bit of styling around the outer div to make it a bit prettier on the view-ticket screen.
<div style="margin-top: 10px; padding: 5px; background: #fff; border: 1px solid #ccc; border-radius: 4px;">
<a href="http://example.com/crm/find-user?email={{user_email}}" target="_blank">Look up {{user_email}} in CRM
</div>
This is what it looks like when we view a ticket in the Agent Interface:
Example: Link to CRM
11
DeskPRO
Apps Manual
Example: Consuming an API
Another common use-case for widgets is to consume an API and display data directly in the Agent
Interface. For example, maybe you run an online store and you want to show the users recent purchases.
Create your Widget
First step is to create your app like we've done before from Admin > Apps > Create Widget.
In this example, we'll create a new tab in the properties box:
Widget Code: Javascript
Switch to the
Tickets
tab so we can edit the Javascript controller code.
We can make AJAX requests with the
$http
service.
Full documentation on the $http service can be found on the official
AngularJS website: https://docs.angularjs.org/api/ng/service/$http
Example: Consuming an API
12
DeskPRO
Apps Manual
Note that due to browser security features, you cannot make AJAX calls to services on a different domain
from the current domain. To get around this limitation, DeskPRO has a special proxy script we can use
that will pass-through a request to a remote service.
Here's an example using
DeskPRO proxy:
$http
to perform an AJAX request to a remote web service through the
define(function() {
return function($scope, $ticket, $person, $http, $el, $app) {
// Setting a loading indicator like this means we
// can show a loading message in our HTML template
$scope.is_loading = true;
var params = {
url: "http://api.example.com/lookup-orders",
// Any other parameters will be sent as-is
// to your remote web service.
// For example, here we are sending an 'email' parameter:
email: $person.primary_email.email
};
$http.get('DP_URL/agent/misc/proxy', {params: params}).success(function(data) {
$scope.is_loading = false;
$scope.orders = data.orders;
});
};
});
For the sake of our example, let's pretend our web service returned the following data:
[
{ id: 1, title: "iPhone", total: 649.00 },
{ id: 2, title: "Headphones", total: 32.99 },
{ id: 4, title: "USB Cable", total: 3.99 },
{ id: 5, title: "Phone Case", total: 24.99 },
]
In our controller we assigned those results to the scope with this line:
$scope.orders = data.orders;
Next we'll see how to show those results in our template.
Example: Consuming an API
13
DeskPRO
Apps Manual
Widget Code: HTML
We have two goals with this HTML template;
1
2
We want to show a loading message while the results are loaded. This means we need
some kind of if/else logic in our template based on the is_loading variable we set
in our Javascript controller.
We want to show a list of orders from our
orders
kind of looping feature to loop through the results.
array. This means we need some
Loading Indicator
To show content based on a value, we can use a special HTML attribute
ng-if :
<div ng-if="is_loading">Loading results, please wait...</div>
<div ng-if="!is_loading">Results are in!</div>
The value of ng-if can be any Javascript expression. In this case, we are just taking the value of our
is_loading varaible. But we could use any valid expression. For example:
<div ng-if="1 + 1 == 2">Yes, 1+1 does equal 2</div>
Iterating over results
The next thing we want to do is iterate over the
orders array so we can list the results we got from our
web service. We can do this with another special HTML attribute called ng-repeat :
<ul>
<li ng-repeat="order in orders">
<a href="http://example.com/admin/order?id={{order.id}}">
{{order.title}} - ${{order.total}}
</a>
</li>
</ul>
ng-repeat syntax is <local variable> in <collection> and repeats the HTML element for each item
in the collection. In our example, we repeated a <li> for each order in our orders array.
The full template
Putting it all together, our template looks something like this:
Example: Consuming an API
14
DeskPRO
Apps Manual
<div ng-if="is_loading">Loading results, please wait...</div>
<div ng-if="!is_loading">
<div ng-if="orders.length == 0">
This user has no orders.
</div>
<div ng-if="orders.length > 0">
<ul style="margin: 10px">
<li ng-repeat="order in orders">
<a href="http://example.com/admin/order?id={{order.id}}">
{{order.title}} - ${{order.total}}
</a>
</li>
</ul>
</div>
</div>
And here's what it looks like in the Agent Interface:
Example: Consuming an API
15
DeskPRO
Apps Manual
More Examples
See the DeskPRO Apps GitHub repository at https://github.com/DeskPRO/DeskPRO-Apps for more apps.
More Examples
16
DeskPRO
Apps Manual
Coding Apps
Coming Soon
Coding Apps
17
DeskPRO
Apps Manual
Packaging Apps
Coming Soon
Packaging Apps
18
DeskPRO
Apps Manual
Native Apps
Coming Soon
Native Apps
19