Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Table of Contents

Introduction

Directive Sets are a way of providing a simple and secure way to drive issue changes from links in generated email notifications to achieve anything from simple custom field value changes, to more complex workflow.  The links generated only have a security token, no arguments are supported, meaning that the links can only be used for exactly the purpose intended, one link per action.  An Email can have many such links covering a variety of field values or actions.  Here is a high level overview of the flow, showing the following flow:

  1. An Webhook Issue Event occurs, rendering a TemplateSet (selected in Email Notification Mapping).  As part of that, unique links are generated

...

  1. for each required DirectiveSet to run.  The email is then sent to the Recipient.

  2. The Recipient clicks on a link, that contains no data other than a token.  The link points to a public REST API on the JEMHCloud server.

  3. The JEMH REST service validates the token is still valid (not yet used), and executes the process.

  4. JEMH Cloud renders a processing result, that the user can customize (in a DirectiveSet Render Result TemplateSet) and which is selected in each directiveSet it is needed.  The HTML is returned to the user.

...

How it works

Directive Sets work in a very similar way to the manual approach (a Test Case), in a nutshell, the DirectiveSet is the 'body' of a text email, JEMH Cloud will 'supply' a minimal set of headers with specific values in order to drive the JEMH Cloud processing logic (issue selection by subject, sender lookup by address).  They  The key pieces of information are shown below:

  1. The From: contains the email address of the sender JIRA user

  2. The To: matches the JEMH Cloud Profile catchemail (mailbox) address

  3. The Subject: contains the issue-key

  4. The content contains Directives (more on this later)

...

Directive Sets enable the content (4) to be statically defined, the rest are contextually available at the time an email notification is generated though a custom Template Set or Custom Macros  There are new additions to the standard JEMH Velocity Context that allow the issue key (1), the JIRA user email address (2) and the Profile Selection that matches (3):

...

The DirectiveSetManager can be interacted with as shown below, to call createDirectiveSetLink. Directive Set Link can be created in custom Templates but the easiest way to inject them in notifications is via macro extension in  Notification →  Notification > Custom Macros. 

JIRA - GENERIC - Directive Links Macros

For JIRA and Generic themes, add the following method in Custom Macros

title
Code Block
JIRA - GENERIC - Directive Links Macros
#macro (jemhIncludeDirectiveSetLinks)
    #set ($groupId = $jemhDirectiveSetLinkManager.generateGroupIdForEvent($context))
    #set ($profileId=13)
    #set ($directiveSetId=3)
	#set ($issueKey=$context.issue.key.textValue())
    #set ($catchEmailAddress="user.2.hydra@gmail.com")
    #set ($recipient=$jemhUtils.getRecipient())

    #set ($directSetLinkUrl = $jemhDirectiveSetLinkManager.createDirectiveSetLink($groupId, $directiveSetId, $profileId, $issueKey, $catchEmailAddress, $recipient))
    #if($directSetLinkUrl)
    <tr>
        <td class="email-content-main mobile-expand  wrapper-special-margin">
            <a href="$directSetLinkUrl" target="_blank">$jemhDirectiveSetLinkManager.getDirectiveSetName($directiveSetId)</a>
        </td>
    </tr>
    #end
#end

SERVICE DESK - Directive Links Macros

For Service Desk theme, add the following method in Custom Macros

SERVICE DESK - Directive Links Macros
Code Block
title
#macro (renderDirectiveSetLinks)
    #set ($groupId = $jemhDirectiveSetLinkManager.generateGroupIdForEvent($context))
    #set ($profileId=13)
    #set ($directiveSetId=3)   
	#set ($issueKey=$context.issue.key.textValue())
    #set ($catchEmailAddress="user.2.hydra@gmail.com")
    #set ($recipient=$jemhUtils.getRecipient())

    #set ($directSetLinkUrl = $jemhDirectiveSetLinkManager.createDirectiveSetLink($groupId, $directiveSetId, $profileId, $issueKey,
        $catchEmailAddress, $recipient))
	#if($directSetLinkUrl && !$context.webhookEvent.textValue().equals('jira:issue_deleted'))
    <tr>
        <td class="label" style="padding: 5px 0; color: #707070; width: 120px; padding-right: 10px; font-size: 14px">
            Some Label For The Link
        </td>
        <td class="value" style="padding: 5px 0">
            <table style="width: 100%; font-family: sans-serif">
                <tbody>
                <tr class="sd-email-user-tagged">
                    <td>
      					 <a href="$directSetLinkUrl" target="_blank" style="text-decoration: none; color: black; cursor:pointer;">
                                $jemhDirectiveSetLinkManager.getDirectiveSetName($directiveSetId)
						</a>
                    </td>
                </tr>
                </tbody>
            </table>
        </td>
    </tr>
    #end
#end

The $jemhDirectiveSetLinkManager.createDirectiveSetLink parameters to this are as follows:

Example Variable

Example Value

Description

Code Block
$groupId

8f5f485b-7496-4f4b-a0fc-3e37269704bc

This is an id that is used to relate a set of links, such that when one link is used, the others are inherently expired/voided. An email may have several groups of links.

Code Block
$directiveSetId

10

This integer value must refer a known ID value shown in the DirectiveSet section of the JEMH Cloud Notification page. It refers to the set of Directives that will be applied.

Code Block
$profileId

20

This integer value must refer a known profile ID value shown in the JEMH Cloud Profiles page. It will be the profile that will be used for processing the DirectiveSet defined in $directiveSetId, as the $recipient on the $issue.

Code Block
$issueKey

ABC-123

The issue key of the issue where the action will be performed. Value is generally $context.issue.key.textValue().

Code Block
$catchEmailAddress

myprofile@company.com

An email address that matches one of the profile's catch email address. 

Code Block
$recipient

myuser@mail.com

The email address of user that will perform the action, generally the current recipient $jemhUtils.getRecipient().

Terminology

Directive Sets

Allow users to perform defined Issue Directives by just clicking a link (called a Directive Set Link) generated in an email notification.  Directive Set can be enabled or disabled - links will only be generated and consumed if the parent Directive Set is enabled.

These are the hyperlinks that are associated with a Directive Set and are validated using single-use tokens, meaning that only recipients of the notification will be able to use the Directive Set.

Each link in a single outbound notification is put in a Link Group which is unique to that recipient.  Once a link has been processed by JEMH Cloud, it (and others in that link group) will expire.  If 30 days pass without a link from an individual notification being processed, then this will also cause all related links to expire.


Note

Directive Sets use Directives, so make sure you understand how they work before attempting to use this feature. If changes aren't applied:

  • Check the JEMH Cloud Auditing

...

  • > Inbound Messages does not show any problems

  • Validate the Profile referred actually has Directives enabled, and the appropriate Field Processor for the body format used, e.g. At Prefix (the example used on this page)


Example Scenarios

As a Directive Set can be configured with any valid Directive there are many ways that this feature can be used, here are just a few example scenarios:

...

Lets say that you want a nice link in a notification that assigns the issue to the user Juan PerezRyan Clifton

  1. Create the Directive Set in

...

  1. Notifications > Directive

...

  1. Set > Create

...

  1. Image Added
  2. Remember the id of the Directive Set (first column on table)

...

  1. Image Added

    Go to

...

  1. Notifications > Custom Macros and Edit. Add the macro below (replace parameters $directiveSetId, $profileId, $catchEmailAddress) and save.

...

...

  1. Image Added

    Create an Issue and inspect the generated email. The email should have the Assign to

...

  1. Ryan link

...

  1. Image Added

    If you click the link, the directive will be executed and the issue's assignee changed. The response is generated based on the Directive Set's template.

...

  1. Image Added

JIRA - GENERIC - Assign to

...

Ryan Custom Macro
Code Block
#macro (jemhIncludeDirectiveSetLinks)
    #set ($groupId = $jemhDirectiveSetLinkManager.generateGroupIdForEvent($context))
    #set ($profileId=13)
    #set ($directiveSetId=6)
    #set ($catchEmailAddress="user.2.hydra@gmail.com")
    #set ($recipient=$jemhUtils.getRecipient())

    #set ($directSetLinkUrl = $jemhDirectiveSetLinkManager.createDirectiveSetLink($groupId, $directiveSetId, $profileId, $context.issue.key.textValue(), $catchEmailAddress, $recipient))

    #if($directSetLinkUrl)
    <tr>
        <td class="email-content-main mobile-expand  wrapper-special-margin">
            <a href="$directSetLinkUrl" target="_blank">
                $jemhDirectiveSetLinkManager.getDirectiveSetName($directiveSetId)</a>
        </td>
    </tr>
    #end
#end

...

Using a Select custom field, with values UNHAPPY, OK and HAPPY, we can create 3 DirectiveSets, here using the AtPrefix Directive format:

  1. Create Select List (single

...

  1. choice) custom field in

...

  1. Cog > Issue > Custom Fields

...

  1. > Create

...

  1. Image Added
  2. Add field to project's screen

  3. Create 3 Directive Sets in JEMH

...

  1. Cloud >Notifications > Directive Sets

...

  1. Image AddedImage Added


  2. Image Added

    Directive Sets page should looks like

...

  1. this:

...

  1. Image Added
  2. For JIRA and GENERIC themes, insert #jemhIncludeDirectiveSetLinks macro below in

...

  1. Notifications > Custom Macros. For Service Desk theme, insert #renderDirectiveSetLinks macro below in

...

  1. Notification >Custom Macros. Update $profileId, $directiveSetIdHAPPY, $directiveSetIdOK, $directiveSetIdUNHAPPY and $catchEmailAddress  to match your values.  Custom Macros in Notification should looks like this:

...

  1. Image Added

  2. Then, an email sent to your customer will include the 3 icons + links. 

...

  1. Image Added

  2. When the user clicks in one of them, the Directive Set will be executed invalidating the other links.

...

  1. Image AddedImage Added


JIRA - GENERIC - Custom Satisfaction Custom Macros
code
Code Block
#macro (jemhIncludeDirectiveSetLinks)
    #set ($groupId = $jemhDirectiveSetLinkManager.generateGroupIdForEvent($context))
    #set ($profileId=13)
    #set ($directiveSetIdHAPPY=3)
    #set ($directiveSetIdOK=5)
    #set ($directiveSetIdUNHAPPY=4)
    #set ($issueKey=$context.issue.key.textValue())
    #set ($catchEmailAddress="user.2.hydra@gmail.com")
    #set ($recipient=$jemhUtils.getRecipient())

    #set ($directSetLinkUrlHAPPY = $jemhDirectiveSetLinkManager.createDirectiveSetLink($groupId, $directiveSetIdHAPPY, $profileId, $issueKey, $catchEmailAddress, $recipient))

    #set ($directSetLinkUrlOK = $jemhDirectiveSetLinkManager.createDirectiveSetLink($groupId, $directiveSetIdOK, $profileId, $issueKey,$catchEmailAddress, $recipient))

    #set ($directSetLinkUrlUNHAPPY = $jemhDirectiveSetLinkManager.createDirectiveSetLink($groupId, $directiveSetIdUNHAPPY, $profileId, $issueKey, $catchEmailAddress, $recipient))

    #if($directSetLinkUrlHAPPY || $directSetLinkUrlOK || $directSetLinkUrlUNHAPPY)
    <tr>
        <td class="email-content-main mobile-expand  wrapper-special-margin">

            #if($directSetLinkUrlHAPPY)
                <a href="$directSetLinkUrlHAPPY" target="_blank">
                    <img style="vertical-align:middle"
                         src="$jemhUtils.inlineImage($jemhUtils.getImageUrl('font-awesome_smile-o'))"/>
                    $jemhDirectiveSetLinkManager.getDirectiveSetName($directiveSetIdHAPPY)</a>
            #end

            #if($directSetLinkUrlOK)
                <a href="$directSetLinkUrlOK" target="_blank">
                    <img style="vertical-align:middle"
                         src="$jemhUtils.inlineImage($jemhUtils.getImageUrl('font-awesome_meh-o'))"/>
                    $jemhDirectiveSetLinkManager.getDirectiveSetName($directiveSetIdOK)</a>
            #end

            #if($directSetLinkUrlUNHAPPY)
                <a href="$directSetLinkUrlUNHAPPY" target="_blank">
                    <img style="vertical-align:middle"
                         src="$jemhUtils.inlineImage($jemhUtils.getImageUrl('font-awesome_frown-o'))"/>
                    $jemhDirectiveSetLinkManager.getDirectiveSetName($directiveSetIdUNHAPPY)</a>
            #end

        </td>
    </tr>
    #end
#end

title


SERVICE DESK - Customer Satisfaction Macro
Code Block
#macro (renderDirectiveSetLinks)
    #set ($groupId = $jemhDirectiveSetLinkManager.generateGroupIdForEvent($context))
    #set ($profileId=13)
    #set ($directiveSetIdHAPPY=3)
    #set ($directiveSetIdOK=5)
    #set ($directiveSetIdUNHAPPY=4)
    #set ($catchEmailAddress="user.2.hydra@gmail.com")
    #set ($recipient=$jemhUtils.getRecipient())

    #set ($directSetLinkUrlHAPPY = $jemhDirectiveSetLinkManager.createDirectiveSetLink($groupId, $directiveSetIdHAPPY, $profileId, $context.issue.key.textValue(),
        $catchEmailAddress, $recipient))


    #set ($directSetLinkUrlOK = $jemhDirectiveSetLinkManager.createDirectiveSetLink($groupId, $directiveSetIdOK, $profileId, $context.issue.key.textValue(),
        $catchEmailAddress, $recipient))

    #set ($directSetLinkUrlUNHAPPY = $jemhDirectiveSetLinkManager.createDirectiveSetLink($groupId, $directiveSetIdUNHAPPY, $profileId, $context.issue.key.textValue(),
        $catchEmailAddress, $recipient))

    #if(($directSetLinkUrlHAPPY || $directSetLinkUrlOK || $directSetLinkUrlUNHAPPY) && !$context.webhookEvent.textValue().equals(
        'jira:issue_deleted'))

    <tr>
        <td class="label" style="padding: 5px 0; color: #707070; width: 120px; padding-right: 10px; font-size: 14px">
            Customer Satisfaction
        </td>
        <td class="value" style="padding: 5px 0">
            <table style="width: 100%; font-family: sans-serif">
                <tbody>
                <tr class="sd-email-user-tagged">
                    <td>

                        #if($directSetLinkUrlHAPPY)
                            <a href="$directSetLinkUrlHAPPY" target="_blank"
                               style="text-decoration: none; color: black; cursor:pointer;">
                                <img style="vertical-align:middle"
                                     src="$jemhUtils.inlineImage($jemhUtils.getImageUrl('font-awesome_smile-o'))"/>
                                $jemhDirectiveSetLinkManager.getDirectiveSetName($directiveSetIdHAPPY)</a>
                        #end

                        #if($directSetLinkUrlOK)
                            <a href="$directSetLinkUrlOK" target="_blank"
                               style="text-decoration: none; color: black; cursor:pointer;">
                                <img style="vertical-align:middle"
                                     src="$jemhUtils.inlineImage($jemhUtils.getImageUrl('font-awesome_meh-o'))"/>
                                $jemhDirectiveSetLinkManager.getDirectiveSetName($directiveSetIdOK)</a>
                        #end

                        #if($directSetLinkUrlUNHAPPY)
                            <a href="$directSetLinkUrlUNHAPPY" target="_blank"
                               style="text-decoration: none; color: black; cursor:pointer;">
                                <img style="vertical-align:middle"
                                     src="$jemhUtils.inlineImage($jemhUtils.getImageUrl('font-awesome_frown-o'))"/>
                                $jemhDirectiveSetLinkManager.getDirectiveSetName($directiveSetIdUNHAPPY)</a>
                        #end

                    </td>
                </tr>
                </tbody>
            </table>
        </td>
    </tr>
    #end
#end


Filter by label (Content by label)
showLabelsfalse
max5
spacesJEMHC
sortmodified
showSpacefalse

...

reversetrue
typepage
cqllabel = "kb-how-to-article" and type = "page" and space = "JEMHC"
labelskb-how-to-article

...

hiddentrue

...