In the previous tutorial, you updated the web app to get tasks from the Asana API and then display them in the Zendesk app. In this tutorial, you'll update the web app to access framework APIs.
The tutorial covers the following tasks:
- Planning the update
- Retrieve and store the app parameters
- Append the parameters to link URLs
- Access the framework
- Code complete
This tutorial is the fourth part of a series on building a server-side Zendesk app:
- Part 1: Core concepts
- Part 2: Display server-side content in a Zendesk app
- Part 3: Access external APIs
- Part 4: Access framework APIs - YOU ARE HERE
- Part 5: Deploy the app
- Bonus part: Secure the app
Planning the update
The error messages displayed by the app are unsatisfactory -- they're just plain text in a blank page.
In this section, you'll use the Apps framework's
notify method to display success or error messages with in-product notifications.
The tutorial only scratches the surface of the framework APIs. For a comprehensive list of resources at your disposal, see the Support API docs.
Retrieve and store the app parameters
The ZAF SDK needs two parameters to create a client object that can interact with the framework: the url of the Zendesk Support instance (its
origin) and the app's unique id (its
app_guid). For details, see Core Concepts.
You must retrieve the parameters from the initial page request made by Zendesk Support when the app starts. This is the page specified in the manifest.json file, which is in this case. Zendesk Support appends the parameters to the URL as query string parameters. Example:
To retrieve the app parameters from the query string and store them:
In app.py, modify the sidebar route as follows (in bold):
@route('/sidebar') def send_iframe_html(): qs = request.query_string response.set_cookie('my_app_params', qs) return template('start')
Here's how it works:
- The first bolded line uses the Bottle
requestobject to retrieve the query string and assigns it to the qs variable
- The second line uses the Bottle
responseobject to save the query string in a cookie on the user's browser for other pages.
Because you introduced the
requestand
responseBottle objects, make sure to import them at the top of the file:
from bottle import route, run, template, request, response
Append the parameters to link URLs
To make the app parameters available to the page that will interact with the framework, you must append them as a query string to any link to the page. When your server sends the page to the iframe, Zendesk Support reads the URL parameters from the response's
referer header.
For the tutorial, you want the page that lists tasks to access the framework API to display an in-product notification that the request was successful. A link to that page appears in the start.tpl template:
<a class="btn btn-default btn-block" href="list" role="button">List tech note ideas</a>
To append the app parameters to the link:
In app.py, modify the sidebar route as follows (in bold):
@route('/sidebar') def send_iframe_html(): qs = request.query_string response.set_cookie('my_app_params', qs) return template('start', qs=qs)
You pass the query string to the start.tpl template so you can add it to the URL of the list page.
In the start.tpl template, append the query string to the URL of the list page:
... href="list?{{qs}}" ...
When a user clicks the link in the iframe, the query string is sent to the server and then back to the iframe in the response's
refererheader.
Note: You don't have to append the parameters to a link if the linked page won't interact with the framework.
Access the framework
The plan is to use the framework's
notify method to display in-product notifications of the request's success or failure to the user.
You access the framework from the HTML page currently loaded in the iframe, not from the server directly. The lingua franca (the common language) is JavaScript. You use JS with the ZAF SDK, a JavaScript library, to create a client object that lets you communicate with the framework.
Display a success message
If the request to Asana is successful, display a success notification with the list page.
In the list_tasks.tpl template, import the ZAF SDK by adding the following script tag before the closing
bodytag:
<script type="text/javascript" src=""></script>
Immediately following it, add another script tag and use it to create the ZAF client and invoke the framework's
notifyfunction:
<script> var client = ZAFClient.init(); client.invoke('notify', 'Request sucessful!'); </script>
Note that creating the client would fail here without the app parameters in the link that the user clicked on the start page to get this page.
Display an error message
If the request fails (if it returns anything but a 200 status code), then switch back to the start page and display an error message.
In the
show_tasks()function in app.py, make the following changes (in bold) to the error-handling
elseclause:
... else: msg = 'Problem with the request: {} {}'.format(r.status_code, r.reason) qs = request.get_cookie('my_app_params') return template('start', qs=qs, error_msg=msg)
If there's an error, the app renders the start.tpl template instead of list_tasks.tpl, and passes the error message to the template. Because the template expects a
qsparameter for the list link (
href="list?{{qs}}" ...), the app retrieves the query string from the cookie and passes it to the template too.
In the start.tpl template, add the following template conditional block before the closing
bodytag:
% if defined('error_msg'): \\ JS here % end
This checks to see if a template parameter named error_msg exists in the template namespace. It exists only if there was a request error.
Replace the
\\ JS hereplaceholder in the conditional block with the following
scripttags:
<script type="text/javascript" src=""></script> <script> var msg = '{{error_msg}}'; var client = ZAFClient.init(); client.invoke('notify', msg, 'error'); </script>
The first tag imports the ZAF SDK. The second tag assigns the error message to a variable, creates a client object, and invokes the framework's
notifyfunction to display the message.
To test the changes, introduce a typo in the Asana endpoint URL. Remember to fix the URL when you're finished testing.
Separating the JavaScript
It's good practice to separate your JavaScript from your HTML in a server-side app too.
In the list_tasks.tpl template, replace all the script tags with the following script tags:
<script type="text/javascript" src=""></script> <script> var action = 'notifySuccess'; </script> <script type="text/javascript" src="js/main.js"></script>
The first tag still imports the ZAF SDK. The second sets an action for your JS script. The third imports your custom script, which you'll create soon.
In the start.tpl template, replace the script tags in the conditional block with the following script tags:
<script type="text/javascript" src=""></script> <script> var action = 'notifyFailure'; var msg = '{{error_msg}}'; </script> <script type="text/javascript" src="js/main.js"></script>
In the app_remote folder, create a folder named static/js.
In the js folder, create a file named main.js.
The folder structure should look as follows:
/app_remote /views ... /static /js main.js
In main.js, add the following JavaScript:
function init() { var client = ZAFClient.init(); switch (action) { case 'notifySuccess': client.invoke('notify', 'Request successful!'); break; case 'notifyFailure': client.invoke('notify', msg, 'error'); break; } } window.addEventListener('load', init, false);
The event listener on the last line runs the
init()function after the page finishes loading. The function creates a client object, then displays different notifications depending on value of the action variable.
In the app.py file, add the following route to handle requests for any file in the js folder:
@route('/js/<filename>') def send_js(filename): return static_file(filename, root='static/js')
Because you introduced the Bottle
static_file()method, add it to the list of imported Bottle methods at the top of the file:
from bottle import route, run, template, request, static_file
Code complete
The server-side code of your web app should look like this:
The client-side code should look like this:
In this tutorial, you updated the web app to access framework APIs to display in-product notifications in Zendesk Support. In the next and final part, you'll deploy the web app on a server and install the basic framework app in Zendesk Support. Click to go to the next tutorial now: Part 5: Deploy the app.
Please sign in to leave a comment.