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:

This tutorial is the fourth part of a series on building a server-side Zendesk app:

Planning the update

The error messages displayed by the app are unsatisfactory — they're just plain text on a blank page.

In this section, you'll use the ZAF client'snotify行动与我显示成功或错误消息n-product notifications.

Retrieving and storing the app parameters

The ZAF SDK needs two parameters to create a client object that can interact with ZAF: the URL of the Zendesk Support instance (itsorigin) and the Zendesk app's unique id (itsapp_guid).

You must retrieve the parameters from the initial page request made by Zendesk Support when the app starts. This is the page specified in themanifest.jsonfile, which ishttp://localhost:8080/sidebarin this case. Zendesk Support appends the parameters to the URL as query string parameters. Example:

             
https://localhost:8080/sidebar?app_guid=f278bc69-6098-aab88a5ec49f&origin=https%3A%2F%example.亚博.com

To retrieve the Zendesk app parameters from the query string and store them:

  1. Inapp.py, modify the sidebar route as follows (highlighted):

                   
    @route('/sidebar')defsend_iframe_html():qs=request.query_stringresponse.set_cookie('my_app_params',qs)returntemplate('start')

    Here's how it works:

    • The first bolded line uses the Bottlerequestobject to retrieve the query string and assigns it to theqsvariable
    • The second line uses the Bottleresponseobject to save the query string in a cookie on the agent's browser for other pages.
  2. Because you introduced therequestandresponseBottle objects, make sure to import them at the top of the file:

             
...frombottleimportroute,run,template,request,response...

To make the app parameters available to the page that will interact with the Apps 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'srefererheader.

For the tutorial, you want the page that lists tasks to access the ZAF API to display an in-product notification that the request was successful. Thestart.tpltemplate includes a link to that page:

             
<aclass="btn btn-default btn-block"href="list"role="button">List tech note ideasa>

To append the app parameters to the link:

  1. Inapp.py, modify the sidebar route as follows (highlighted):

                   
    @route('/sidebar')defsend_iframe_html():qs=request.query_stringresponse.set_cookie('my_app_params',qs)returntemplate('start',qs=qs)

    You pass the query string to thestart.tpltemplate so you can add it to the URL of the list page.

  2. In thestart.tpltemplate, append the query string to the URL of the list page:

                   
    ...href="//www.ying8.net/developer/documentation/apps/build-an-app/building-a-server-side-app/part-4-access-framework-apis/list?{{qs}}"...

    When an agent clicks the link in the iframe, the query string is sent to the server and then back to the iframe in the response'srefererheader.

    Note: You don't have to append the parameters to a link if the linked page won't interact with ZAF.

Accessing the framework

The plan is to use the ZAF client'snotifyaction to display in-product notifications of the request's success or failure to the agent.

You access the framework from the HTML page currently loaded in the iframe, not from the server directly. Thelingua 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 ZAF.

Displaying a success message

If the request to Asana is successful, display a success notification with the list page.

  1. In thelist_tasks.tpltemplate, import the ZAF SDK by adding the following script tag before the closingbodytag:

                   
    <scriptsrc="https://static.zdassets.com/zendesk_app_framework_sdk/2.0/zaf_sdk.min.js">script>
  2. Immediately following it, add another script tag and use it to create the ZAF client and invoke the client'snotify行动:

                   
    <script>constclient=ZAFClient.init()client.invoke("notify","Request successful!")script>

    Note that creating the client would fail here without the Zendesk app parameters in the link that the agent clicked on the start page to get this page.

Displaying 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.

  1. In theshow_tasks()function inapp.py, make the following changes (highlighted) to the error-handlingelseclause:

                   
    ...else:msg='Problem with the request: {} {}'.format(r.status_code,r.原因)qs=request.get_cookie('my_app_params')returntemplate('start',qs=qs,error_msg=msg)

    If there's an error, the web app renders thestart.tpltemplate instead oflist_tasks.tpl, and passes the error message to the template. Because the template expects aqsparameter for the list link (href="//www.ying8.net/developer/documentation/apps/build-an-app/building-a-server-side-app/part-4-access-framework-apis/list?{{qs}}" ...), the app retrieves the query string from the cookie and passes it to the template too.

  2. In thestart.tpltemplate, add the following template conditional block before the closingbodytag:

                   
    % if defined('error_msg'):\\ JS here% end

    This checks to see if a template parameter namederror_msgexists in the template namespace. It exists only if there was a request error.

  3. Replace the\\ JS hereplaceholder in the conditional block with the followingscripttags:

                   
    <scriptsrc="https://static.zdassets.com/zendesk_app_framework_sdk/2.0/zaf_sdk.min.js">script><script>constmsg="{{error_msg}}"constclient=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'snotifyaction to display the message.

To test the changes, introduce a typo in the Asana endpoint URL inapp.pyand restart the Bottle development server. 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.

  1. In thelist_tasks.tpltemplate, replace all the script tags with the following script tags:

                   
    <scriptsrc="https://static.zdassets.com/zendesk_app_framework_sdk/2.0/zaf_sdk.min.js">script><script>constaction="notifySuccess"script><scriptsrc="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.

  2. In thestart.tpltemplate, replace the script tags in the conditional block with the following script tags:

                   
    <scriptsrc="https://static.zdassets.com/zendesk_app_framework_sdk/2.0/zaf_sdk.min.js">script><script>constaction="notifyFailure"constmsg="{{error_msg}}"script><scriptsrc="js/main.js">script>
  3. In theapp_remotefolder, create a folder namedstatic/js.

  4. In thejsfolder, create a file namedmain.js.

    The folder structure should look as follows:

                   
    /app_remote/views.../static/jsmain.js
  5. Inmain.js, add the following JavaScript:

                   
    functioninit(){constclient=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 theinit()函数在页面加载完成后。的函数tion creates a client object and displays different notifications based on the value of theactionvariable.

  6. In theapp.pyfile, add the following route to handle requests for any file in thejsfolder:

                   
    ...@route('/js/')defsend_js(filename):returnstatic_file(filename,root='static/js')...
  7. Because you introduced the Bottlestatic_file()method, add it to the list of imported Bottle methods at the top of the file:

                   
    ...frombottleimportroute,run,template,request,response,static_file...

To test the updated web app in Zendesk Support:

  1. Restart the Bottle development server.

  2. In the Zendesk Support instance running the local ZCLI server, refresh the app and clickList tech note ideas.

    A notification appears:

You've updated the web app to access ZAF APIs to display in-product notifications in Zendesk Support. In the next tutorial, you'll update the web app so that it only responds to verified requests from your Zendesk app. SeePart 5: Securing the app.