In this post, I will explain how you can use report state API endpoints and SAS® Viya Jobs to create a button that will restore the default report state in a SAS® Visual Analytics report. We will call this button reset filters as in the default report state, the report is unfiltered.
SAS® Visual Analytics provides report viewers a lot of interactivity, helping them gain insights from the data. This includes their selections in report and page prompts, selections in report objects that may filter other objects, and sorting on individual objects. There are also many object-specific options that can be saved with the report state. For example, report viewers can change data labels, grouping style, show or hide legends, show or hide totals, etc. Depending on the viewer capabilities, report viewers can also change the object types, and change data roles, filters and ranks. All of this is recorded in the report state.
When a report is edited and saved, this creates the default report state. This is the report state that all report viewers see when they open the report for the first time. Subsequently, if a report viewer changes the report state, closes the report and reopens the report later, they will see the report in the same state that they left it in. This is called primary report state, and it is only visible to that user. Hence, any change to the report state made while viewing a report using the Visual Analytics UI overwrites the previous primary report state, if it exists. While there can only be one report state per user, they can have multiple non-primary report states. We can create, update and delete (primary or non-primary) report states using API.
In this post, I will demonstrate deleting the primary report state so the report state resets to the default report state, which is the state the report creator left the report in. Report viewers can easily return to this default report state using the report menu, and clicking on Restore default report state.
Select any image to see a larger version.
Mobile users: To view the images, select the "Full" version at the bottom of the page.
Note this button only appears once a report viewer has made a change to the report state.
If this functionality exists using the Visual Analytics UI, why implement this using an API and a job? There are two reasons:
Don’t worry – we will put all of this code into a SAS® Viya Job – the report viewer will not need to know how to code.
For an introduction to using REST API, see Accessing VA Reports with Parameterized URLs - SAS Users. While that post focuses on the Visual Analytics API, I will work with the Reports API in this post. The Reports API’s documentation can be viewed from the developer.sas.com site. You can access the reports API by clicking on APIs > REST APIs, then filtering for your version of Viya, and clicking on the Visualization and Reports category on the left. Finally, click on the Reports API. You can also directly click on the link below.
The following page lists all of the report endpoints in this API. We will focus on those in the ReportState sections.
We will need the following API endpoints:
Click on Get a collection of report states. You will see the following request sample code (screenshot edited):
The sample code is almost ready for use. Note this sample code is available in multiple languages – we will be using Python and the requests library. We only need to adapt the URL to point to our Viya instance, which we will retrieve from the SERVICESBASEURL systems option. We need to insert the reportID of our report into the URL and our access token into the value of the Authorization key in the header. We will retrieve this token from the SAS_CLIENT_TOKEN macro variable. Scroll down, look at the structure of the response. We need to understand this structure in order write code to extract the ID of the primary state.
Click on Schema for the 200 response code, which is for a valid request. We are interested in items, which is an array. Click on items to see its contents:
Each item is a dictionary, and we are interested in the value of id, but only for the element where the value for primary is True.
Clicking on Delete report state, you will see the below request sample code.
Again, the sample code is almost ready to use. We only to adapt the URL to point to our Viya instance. We need to replace the first STRING_VALUE in the URL with the reportId, and the second one with the stateID retrieved from the previous API call. The access token is the same as in the previous API call.
I need the internal name of the report: the report ID. I can retrieve it by clicking on the Report Menu and then on Copy Link. The structure of the report link is <hostname>/links/resources/report?uri=reports/reports/reportID. The report ID is at the end. Note that the Copy Link window displays the encoded URL, where each / has been replaced with %2F. Therefore, I copy the part of the report link after the last %2F.
Write down this report ID and the full report link. We will need them.
You can find the full code below, or here. It is ready to use – you just need to insert your report ID after the equals (=) but before the semi-colon (;) in line 1. For testing purposes, you can execute this code in SAS® Studio (ensuring the right compute context is selected at the top right – in my case SAS Job Execution compute context), or with the SAS extension in Visual Studio Code, or any other code editor that can connect to SAS® Viya. I personally like to use Visual Studio Code with the SAS extension.
%let reportID = ; /* insert your reportID between equals and semicolon */
/* retrieve the authorization token */
%let token=%sysget(SAS_CLIENT_TOKEN);
/* retrieve the Viya base URL */
%let host=%sysfunc(getoption(SERVICESBASEURL));
proc python;
submit;
import requests
# convert SAS macro variables to Python variables
token = SAS.symget('token')
host = SAS.symget('host')
reportId = SAS.symget('reportID')
def retrieve_primary_state(reportId):
headers = {
"Content-Type": "application/json",
"Authorization": "Bearer " + token,
"Accept": "application/json, application/vnd.sas.collection+json, application/vnd.sas.error+json"
}
url = str(host) + "/reports/reports/" + reportId + "/states"
response = requests.get(url, headers=headers)
# parse the items array:
for item in response.json()['items']:
# if an item has True for the primary key, return its id
if item['primary']:
stateId = item['id']
return stateId
def delete_primary_state(reportId):
stateId = retrieve_primary_state(reportId)
headers = {
"Authorization": "Bearer " + token,
"Accept": "application/vnd.sas.error+json"
}
url = str(host) + "/reports/reports/" + reportId + "/states/" + stateId
response = requests.delete(url, headers=headers)
print(response)
if __name__ == '__main__':
primary_state_content = delete_primary_state(reportId)
endsubmit;
run;
We don’t want our users to have to deal with the code. Therefore, we will put the code in a SAS® Viya Job. The report viewer will:
For this, copy the above code and go to SAS Studio. You can reach it by clicking on Develop Code and Flows in the SAS® Viya application menu:
Then click on New > Job definition
You can build a user interface for the job by dragging and dropping from the Control Library. However, our job form will just display a link back to the Visual Analytics report. We will implement this in HTML. Click on the Associate a form menu on the right, and then on HTML form:
Enter the following HTML code:
<html>
<a href=" "> Return to report </a>
</html>
Enter the link to your Visual Analytics report in between the quotation marks (“ ”). Remember we copied this from the Copy link in the Report menu.
We need the link to our job to include as a button in the Visual Analytics report. You can get this by clicking on the Properties menu on the right.
Note the Job URL down. Next, click on the Program tab and paste the code calling the APIs from the previous section.
I am ready to try it out! You can try it out with your own report, or follow along in this section. I will create a new report using the ORSALES table in the SASHELP library, available to everyone. We need to load this data into CAS. You can do that using the following code:
cas;
proc casutil;
load data=sashelp.orsales casout="orsales" outcaslib="casuser" promote;
run;
I create a new report with report prompts of Product Line and Quarter, a bar chart of Profit in USD by Product Category and a list table of Product Group and Profit in USD. I also added a US dollar format for Profit in USD and created an object link filter action from the bar chart to the list table. Then, I added a text object with the text Reset all Filters linking to the URL of the SAS Viya Job we just created. Recall that we will call this Reset all Filters, but actually it restores the default report state. We will ensure that in the default report state, the report is unfiltered.
In the options menu on the right, I select the report from the drop-down list and change the viewer capabilities to Object data edits. This will allow the viewer to change data roles, add filters and ranks to objects.
I save the report.
The state you see above is the default report state. Note there are no filters and the bar chart is sorted by Profit in USD in descending order. I shall now switch to view mode and create a different primary report state. Let’s say we are in charge of the shoes business. I select Clothes & Shoes from the report and Shoes from the bar chart. I will also sort the list table by Profit in USD in ascending order, and add a rank to only show the top Product Group (note we do this from within viewing mode).
Now, I wish to return to the default report state without any filters. For this, I click on the Restore Filters button and reload the page. Voilà, all the filters are gone! Note: if you try this multiple times, ensure you don’t have the report open in multiple tabs.
We built a Reset all filters (which actually just restores the default report state, which happens to be unfiltered) to our report. This can be very useful and it does more than just resetting all filters! For example, try changing the bar chart to a pie chart in view mode. The Reset all filters button also resets the pie chart to its original state. By understanding these report state API endpoints, you can even build more customized functionality to meet your needs. You could save multiple states for a report and allow report viewers to apply them with just a few clicks.
Find more articles from SAS Global Enablement and Learning here.
It's finally time to hack! Remember to visit the SAS Hacker's Hub regularly for news and updates.
The rapid growth of AI technologies is driving an AI skills gap and demand for AI talent. Ready to grow your AI literacy? SAS offers free ways to get started for beginners, business leaders, and analytics professionals of all skill levels. Your future self will thank you.