OK! So... yesterday I published a user's guide to my Page Approvals implementation.
But let's get into the fun stuff. What's under the hood?
Smart Buttons are a nifty, but limited feature that allow users to trigger a pre-defined Automation rules that can be chosen from a stock set of simple templates. The rules can only be modified within the Smart Button templates, and only settings for the pre-defined actions can be modified, ex: Page Status to change to, Labels to add, hard-coded address to email.
BUT! Thanks to the handy Allow rule trigger option, we can use Labels to trigger more advanced rules.
So in our case, we created a Request Approval Smart Button that changes the Page Status to [IN REVIEW] and adds a label approval-started.
Per a user suggestion, I’ve put the button in an Expand macro as a “safety” of sorts. In truth, anyone can click a Smart Button, but the page restriction added upon publishing should prevent it from working for anyone but the page author.
When page published:
If Page Condition where page was created from the template we use for approvals
Then: Restrict page to only be edited by the “Rule initiator” (which is the page author in this case).
When Page status changes to In Review (triggered by the Smart Button, because we have enabled the Allow rule trigger option):
Web request to the get page API just to get the current version of the page (minus the version that gets created when the Page Status changes, sigh).
Create variable {{approvalVersion}} - used to hold version for use in Comment.
Web request to the get tasks API to get all the tasks for the page.
Create variable {{approversIdArray}} to filter out only tasks that include “Approve”, and store the IDs of the assignee (Approver) of each task.
Smart Value:
{{#webResponse.body.results}}{{#if(body.storage.value.match(".(Approve).").isNotEmpty())}}"{{assignedTo}}"{{^last}}, {{/}}{{/}}{{/}}
Web request to the Add restrictions API (using POST method) with {{approversIdArray}} to allow the Approvers to edit this page (which the previous automation restricted to the author) so that they can actually check the Tasks off.
Web request to the bulk user lookup API to query {{approversIdArray}} and to get email and displayName for each Approvers.
Add comment to the page logging that the approval has been requested, including the {{webResponse.body.results.displayName}} and {{approvalVersion}}.
Send email to the Approvers giving them instructions to approve the page, using {{webResponse.body.results.emailAddress}}.
Add label approvalversion-{{approvalVersion}}so that we can later reference this version.
Remove label approval-started because we really only need it for the Smart Button trigger.
When Task status changes:
If: Page status is In Review and if the Task body {{task.body}} includes the word “Approve” (to allow for the possibility of non-Approval tasks to be used on these pages.)
Add comment that an Approval Task was APPROVED or (if unchecked) UNAPPROVED, and who carried initiated the change, as well as the assignee of the task. Unfortunately we cannot restrict assignees to only checking their own tasks, but through the comment log we have an audit trail of mistaken clicks OR (in theory) approvals made on behalf of somebody else.
Web request to the get tasks API to get all the incomplete tasks for the page.
Create variable {{incompleteApprovalsList}} to filter out only tasks that include “Approve”, and store the IDs of the assignee (Approver) of each task.
Smart Value:
{{#webResponse.body.results}}{{#if(body.storage.value.match(".(Approve).").isNotEmpty())}}{{id}}{{^last}}~~{{/}}{{/}}{{/}}
If: Compare two values - if the list of approvers {{incompleteApprovalsList}} is Empty …
Change page status to Approved
When: Page edited
If: Page Status is In Review or Approved, we cancel/invalidate the Request/Approval, because the page under review (or approved) is no longer the same.
Change the page status to IN PROGRESS (as there is no automation action to remove a page status).
Add label: approval-cancelled
Add comment indicating Approval request was cancelled. Include version.
Remove approvalversion-VERSIONlabel.
Web request to the get tasks API to get all the tasks for the page.
Create variable {{approversIdArray}} to filter out only tasks that include “Approve”, and store the IDs of the assignee (Approver) of each task.
Smart Value:
{{#webResponse.body.results}}{{#if(body.storage.value.match(".(Approve).").isNotEmpty())}}"{{assignedTo}}"{{^last}}, {{/}}{{/}}{{/}}
Web request to the Delete restrictions API (using DELETE method) to remove page edit permissions for approvers.
Web request to the Add restrictions API (using POST method) add edit permission back for Page Author, in case they were an Approver.
Send email to Approvers indicating Approval Cancelled.
Web request to the get page API just to get the version, title, and body (content) of the page.
Web request to the update page API (using PUT method) replace the body of the page where the replaceAll text function has been used to find all completed tasks that include “Approve” in their description and set their status to incomplete.
{
"id": "{{page.id}}",
"status": "current",
"title": "{{webResponse.body.title}}",
"body": {
"representation": "storage",
"value": "{{webResponse.body.body.storage.value.replaceAll("<ac:task-status>complete</ac:task-status>\\n<ac:task-body>(.*?[Aa]pprove.*?)</ac:task-body>", "<ac:task-status>incomplete</ac:task-status>\n<ac:task-body>$1</ac:task-body>").jsonEncode}}"
},
"version": {
"number": {{webResponse.body.version.number.plus(1)}},
"message": "Approval Cancelled - Clearing Approvals"
}
}
Whew. That's a lot.
Documentation can be a lot of work.
Hopefully this helps somebody in the future. Please let me know if you have questions.
Happy to provide text of various calls/custom data if that helps, as I know the images can be hard to read.
Darryl Lee
Sr. Atlassian Systems Engineer
Roku, Inc.
San Jose, CA
191 accepted answers
4 comments