Skip to content

Lab 2 - Admin Actions

Story

As a contact center administrator, I need to log out agents which have not logged out after their shift, so that the contact center reporting statistics are accurate.

Requirements

  1. Need a list of logged in agents which includes:
    • Agent name
    • Team name
    • Login time
    • Current Status
    • Last Activity time
  2. Need to be able to log out an agent

Data and Actions

Log into the Agent Desktop (so that you have data to query against)

Launch the Agent Desktop

Login:
Password: password
Team: team


Use the Search API GraphQL Workbench to create the query for the Search API

Open the Search API GraphQL Workbench

Use the Authorization Tool (Tools > Authorization)

Login:
Password: password

Copy the authorization header into the environment variables

Set the URL: https://api.wxcc-us1.cisco.com/search

Open the Docs Panel Click Query to see which fields are available

Which Fields are we going to use to find information about agents?

agentSession

Click on the blue text of the name of the field you want to use
You can now see the Arguments and Fields available

Hover over the name of the fields you selected in the previous step at the top of the frame and the ADD QUERY button will appear, click it

You now have a query template in the first pane of Altair

Delete the "has" section and all of its fields

In the Fields section of the query (agentSessions section):

Delete the lines for intervalStartTime(sort: asc) and aggregation as we are not using them in this query.

In the Arguments section of the query (top section):

Delete the lines for aggregation, aggregations, and aggregationInterval as we are not using aggregations in this query.

Based on the requirements listed above in the story, what fields do you need to return in your query?
  • Agent name = agentName
  • Team name = teamName
  • Login time = startTime
  • Current Status = channelInfo => currentState (note that this is not the same as the state field)
  • Last Activity time = channelInfo => lastActivityTime
currentState and lastActivityTime have a special method of being addressed in the query

channelInfo{
    currentState
    lastActivityTime
}
Update the channelInfo fields in the query.

Use the Time Widget in the Graph QL Workbench to update the Arguments section of the query selecting From: 1 day ago and To: Now. Then copy the values into the query.

Press the green Send Request button
Scroll through the results in the middle pane of Altair

Note that there is a lot of extra information you will not need to satisfy the requirements.

Add filters to the Arguments section of the query to only return agent data for agent which are currently active (logged in) and only return the status information for the telephony channel Inside the curly braces after filter add this compound filter

    and:[
    {isActive:{equals:true}}
    {channelInfo:{channelType:{equals:"telephony"}}}
    ]

Press the green Send Request button

Note there are still fields you will not need to satisfy your requirements

Comment out any fields you will not need by using ctrl + / in front of the field name (you can comment more than one line at a time by selecting multiple lines)
Press the green Send Request button to see the results.

Do not close this tab as you will be using it in an upcoming step


Use API to log out agents

Navigate to the Agent Logout API documentation

Log into the developer portal using your admin credentials

Login:
Password: password

In the logoutReason field enter Admin Logout

In the search API results in the the GraphQL Workbench, find your agent's information.

Do you have all of the data we need to to make the logout API call?

You will also need the agentID of the agent you want to log out.

Uncomment out agentId in the fields of the GQL query if they were previously commented out and rerun the request

Enter your agent's agentId in the agentId field
Click on the option to see the Request Body (JSON)
Click on the RUN button

You should receive a 202 response

Do not close this tab as you will be using it in an upcoming step


Creating the Web Component

Now that you have the basic data and API elements understood and tested, it is time to put them together in code to visualize the data and orchestrate our actions all while creating a good experience for the end user.

Create a new Web Component

Create a new file in the src directory named admin-actions.ts

In the new file type (not paste) littemplate

Select the Create LitElement Component With lit-html


Add a string Property to hold your Access Token

@property() token?: string


Add an array State to hold the data you will return in the query

@state() agentList = []


Create an Async method to call the search API

async getAgents(){}

Refactor and Export your Graph QL Query

In your GraphQL Workbench browser tab, click on the "suitcase" icon on the left menu bar then click Refactor Query

Change the name of the query from refactored### to: activeAgents
Compress the query (suitcase menu > Compress)
Copy as cURL (suitcase menu > Copy as cURL)

Show me the steps


Import cURL into Postman

Open Postman Click Import

Paste the cURL from the GraphQL Workbench into the import text box


Update Headers in Postman

Uncheck all headers except: Content-Type and Accept
Add an Authorization Header:

Key: Authorization
Value: Bearer placeHolder


Format the request Body

Click on Body
Click the Text dropdown and select JSON
Click Beautify


Turn the request into code

Click the Code button
Select JavaScript - Fetch for the language
Click the settings cog and ensure the Use async/await is toggled on
Copy the code using the copy button.

Show me


Add the code to the getAgents method and make these changes

Between the curly braces of the getAgents method, press enter then paste the copied code from postman
In the headers section of the method, find the Authorization header and change "Bearer placeHolder" to `Bearer ${this.token}`
In the raw section which holds the stringified JSON:

Change the from variable value to represent a time 24 hours (86400000 ms) before the current time (Date.now()) using a string literal expression: `${Date.now() - 86400000}`

Change the to variable value to represent the time now: `${Date.now()}`

Set the type of requestOptions to be an object by adding this notation, after its name and before the equals sign: : object

In the try section of the method:

Change result to equal: response.json() instead of response.text()


Return to the GraphQL Workbench to understand how to use the returned data

In the center pane of Altair, copy the data returned from the query
Open JSON Path Finder
Paste the copied data into the left pane
In the right pane, navigate until you find the array of agentSessions

What is the JSON path which will return the array of agentSessions?

x.data.agentSession.agentSessions

In the agent-actions.ts file, set the value of agentList to this JSON path

Add this.agentList = result.data.agentSession.agentSessions; in the try section of the getAgents method, below the const result = await response.json(); line

Back in JSON Path Finder, make the data mimic what you set agentList to in the previous step and only keeping the agentSessions array

On line 4 double click next to the opening bracket of agentSessions to select the entire array.
Copy the array (ctrl + c)
Delete all the data (ctrl + a and delete)
Paste the previously copied array (ctrl + v)

Show me


Update the html template in the render method

In the render() method add a few lines between the back ticks in of the return html`` line
Add a title header for the web component: <h1 class="title">Admin Actions</h1>
Add a button to call the getAgents method: <div><button @click=${this.getAgents}>Refresh Agent List</button></div>
Create a table with headers for Agent Name, Team, Login Time, and Status

Add a <table> tag
Inside the table tags add a table head tag <thead>
Inside the table head tag add table headers for the table as listed above. Example: <th>Agent Name</th>

Check your code


Create the table body using the data from the agentList array

In this section you are going to use the map method which will preform an action for each object in an array. Each iteration of the map method will produce an object from that index of the array which you will refer to as t and will represent the root of the JSON path. You will be using JSON Path Finder to understand the JSON path addresses as you progress through the fields. You will also be doing some math and other formatting to the returned values to produce a more user friendly table.

Use the map method to render the html of the table body below the </thead> closing tag

    ${this.agentList?.map((t: any) => html`
    <tbody>

    </tbody>
    `)}

Inside the tbody tags create the table data cells

Using JSON Path Finder, Create the field for agentName

<td>${t.agentName}</td>

Create the field for Team

<td>${t.teamName}</td>

Create the value of startTime in a human readable datetime stamp

<td>${new Date(t.startTime).toLocaleString()}</td>

Create the value of currentState

<td>${t.channelInfo[0].currentState}</td>

Create the duration of time in the current state

<td>${new Date(Date.now() - t.channelInfo[0].lastActivityTime).toISOString().slice(11, -5)}</td>

Check your code

Save the TS file


Add to index.html passing the Bearer token as a property

Add the script tag in the header of index.html

<script type="module" src="/src/admin-actions.ts"></script>

Add the custom element tag to the html body of index.html

<admin-actions token="Replace with the token value from the GraphQL Workbench"></admin-actions>


Start the Development server

In the terminal of VS Code run: yarn dev
Launch the development server index page

You should see your web component in the browser


Log into the Agent Desktop (so that you will have data to populate the web component)

Launch the Agent Desktop

Login:
Password: password
Team: team

Click the Refresh Agent List button

You should see the list of logged in agents populate

Keep this tab open for additional testing.


Make the output look a better by adding this CSS to the static styles:

            :host{
            display: flex;
            flex-direction: column;
            border: solid 3px var(--md-primary-text-color);
            padding: 2em;
            color:var(--md-primary-text-color)
            }
            .title{
            text-align: center
            }
            table{
            display:table;
            border-collapse:collapse;
            border-spacing: 0;
            margin-top: 15px;
            }
            tr, th, td{
            border: solid 1px;
            text-align: center;
            }
            .hidden{
            display:none;
            }

Save the file
Click the Refresh Agent List button
Observe the changes to your web component


Convert the Logout Agents API call into code

In the browser tab with the developer portal open to the agent logout API:

Click on Code Snippets
Select Curl
Click the Copy button in the upper right corner of the code
Open Postman and import the cURL
Click the code button in Postman

Make sure that you have selected Javascript - Fetch with async/await
Copy the code


Create a new async method to log out agents

async logOutAgent(e: any){}
Between the curly braces, press enter then paste the copied code from postman.
Make the following edits to the method code:

Change the Authorization header to use the token property
Set the type of requestOptions to be an object by adding this notation, after its name and before the equals sign: : object
Change the agentId in the raw variable to use e.target.value

Check your code


Add a button to log out the agent in every row of the table

Add a header to the bottom of the <thead> section: <th>Action</th>
Add another column to the table data map at the bottom of the <tbody> section: <td><button value=${t.agentId} @click="${this.logOutAgent}">Log Out</button></td>

Check your code

Save the file
Click the Refresh Agent List button
Observe the changes to your web component


Adding the Web Component to the agent desktop

Download the Desktop Layout

In Control Hub navigate to Contact Center => Desktop Layouts
Locate the Desktop Layout named placeholder for layout name
Click the name of the Desktop Layout to access the details

Note

  • Desktop Layouts are assigned to agents based on the team they have logged in with.
  • You can download the existing Desktop Layout JSON if you would like to see the configuration or make edits.
  • You can download the default Desktop Layout if you want to start fresh or see what new options may be available on the agent desktop.
  • If you do not upload a custom desktop layout, new features will automatically appear on the agent desktop for the assigned teams as they become available.

Click the button to download the default desktop layout.
Open the JSON file in Visual Studio Code

In the Explorer pane (left pane) of VS Code, click on the Outline to expand it.

You may choose to click on HELLO-WORLD at the top of the Explored pane to collapse the file list of your web components while you explore the Desktop Layout outline.
Hover over OUTLINE to expose the Collapse All button and click on it.

Note

  • The JSON layout contains sections for agent, supervisor, and supervisorAgent
  • The layout options will be based on the role the user is logging in with in addition to the team they are logging into.

Expand agent > area > advancedHeader and click on advancedHeader to jump to that section

Look at the first entry in the advancedHeader array

  • Based on what you have been adding to the index.html file, what similarities do you notice?
    • comp - component and is the same as the html tag value you would put in the html body
    • script - same as the script src value in the html header
    • attributes - similar to properties, but limited to only containing strings, are the same (well similar) as passing a property in the opening component tag in the html
  • Notice that the attributes (similar to properties) are being set with a variable

Code

    {
      "comp": "digital-outbound",
      "script": "https://wc.imiengage.io/AIC/engage_aic.js",
      "attributes": {
        "darkmode": "$STORE.app.darkMode",
        "accessToken": "$STORE.auth.accessToken",
        "orgId": "$STORE.agent.orgId",
        "dataCenter": "$STORE.app.datacenter",
        "emailCount": "$STORE.agent.channels.emailCount",
        "socialCount": "$STORE.agent.channels.socialCount"
      }
    }

Adding your widget to a Navigation Page

In the Desktop Layout Outline, Expand agent > area > navigation and click on navigation to jump to that section of the JSON.

After the closing curly brace of the last item in the navigation array and before the closing square bracket of the navigation array:

Add a comma and press enter
Paste this JSON into the layout

{
        "nav": {
            "label": "Admin Actions",
            "icon": "admin-regular",
            "iconType": "momentumDesign",
            "navigateTo": "aActions",
            "align": "top"
        },
        "page": {
            "id": "aActions",

            "widgets": {
            "comp1": {
                "comp": "admin-actions",
                "script":"http://localhost:4173/index.js",
                "attributes": {
                "token": "$STORE.auth.accessToken"
                }
            }
            },
            "layout": {
        "areas": [["comp1"]],
        "size": {
            "cols": [1],
            "rows": [1]
        }
        }
        }
        }

Save and update the new layout JSON

Save the file as yourTeamName.json
Locate your assigned Desktop Layout Upload the new JSON by dragging the file into the import box or clicking Replace file and navigating to the file using the file explorer Click Save in the lower right corner


Testing

Build and server your widget code

In the terminal at the bottom of VS Code:
Use press ctrl + c to shut down the development server
Build the externally usable code by entering the command: yarn build
Start the preview server with the build command in watch mode by entering the command: yarn game


Log into the agent desktop

Log into the Agent Desktop if you are not already logged in.

Login:
Password: password
Team: team


Testing steps

The Navigation pane should include the icon you defined in the agent desktop
Click on the icon to show the Admin Actions screen

Does the tool render?

Click the Refresh Agent List button

Do you see a list of logged in users with all of the fields populated?

Click on the avatar (your initials) in the upper right corner of the screen to open the desktop settings

Toggle to dark mode

Does the tool render correctly in both light and dark mode?

Find a buddy next to you in the room and one of you log the other person out using the logout button.

Did the agent get logged out?

Refresh the list using the button to make sure.


Stop the testing server

In the terminal of VS Code press ctrl + c