Introduction
Excerpt |
---|
Use TGE as a storage of simple sub-tasks and get email notification on change of the task assignee |
This article details out how to setup a table grid to track 'sub' tasks, and be notified when something is assigned to yourself. It is using Script Listeners (from ScriptRunner) to send out the notifications.
...
Create the TGE Listener
Install latest ScriptRunner add-on, create a file "TgeListener.groovy" with the following content in the "$JIRA_HOME/scripts/com/idalko/scripts" directory.
Code Block | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
import com.atlassian.crowd.embedded.api.User import com.atlassian.jira.component.ComponentAccessor import com.atlassian.jira.config.properties.APKeys import com.atlassian.jira.config.properties.ApplicationProperties import com.atlassian.jira.event.issue.AbstractIssueEventListener import com.atlassian.jira.event.issue.IssueEvent import com.atlassian.jira.issue.CustomFieldManager import com.atlassian.jira.issue.Issue import com.atlassian.jira.issue.fields.CustomField import com.atlassian.jira.security.JiraAuthenticationContext import com.atlassian.jira.user.ApplicationUser import com.atlassian.jira.user.UserUtils import com.atlassian.mail.Email import com.atlassian.mail.queue.MailQueue import com.atlassian.mail.queue.SingleMailQueueItem import com.atlassian.plugin.PluginAccessor import org.apache.commons.lang3.ObjectUtils import org.apache.log4j.Logger import org.ofbiz.core.entity.GenericValue class TgeListener extends AbstractIssueEventListener { // configuration private static final String TGE_FIELD_NAME = "TGE"; private static final String TRACKED_USERLIST_COLUMNS_NAME = "iassignee"; private static final String PREVIOUS_USERLIST_COLUMNS_NAME = "previousiassignee"; private static final Logger LOG = Logger.getLogger("com.idalko.scripts"); private final CustomFieldManager customFieldManager; private final PluginAccessor pluginAccessor; private final JiraAuthenticationContext jiraAuthenticationContext; private final ApplicationProperties applicationProperties; private final MailQueue mailQueue; private final def tgeGridDataManager; public TgeListener() { customFieldManager = get(CustomFieldManager.class); pluginAccessor = get(PluginAccessor.class); jiraAuthenticationContext = get(JiraAuthenticationContext.class); Class dataManagerClass = pluginAccessor.getClassLoader().findClass("com.idalko.jira.plugins.igrid.api.data.TGEGridTableDataManager"); tgeGridDataManager = get(dataManagerClass) applicationProperties = get(ApplicationProperties.class); mailQueue = get(MailQueue.class); } private <T> T get(Class<T> clazz) { return ObjectUtils.firstNonNull( ComponentAccessor.getComponent(clazz), ComponentAccessor.getComponentOfType(clazz), ComponentAccessor.getOSGiComponentInstanceOfType(clazz) ); } @Override void issueUpdated(IssueEvent event) { Set<Long> updatedCustomFieldIds = getUpdatedCustomFieldsIds(event); LOG.debug("Updated custom fields IDs are: " + updatedCustomFieldIds); CustomField tgeCustomField = customFieldManager.getCustomFieldObjectByName(TGE_FIELD_NAME); Long tgeCustomFieldId = tgeCustomField.getIdAsLong(); LOG.debug("TGE custom fields ID is: " + tgeCustomFieldId); if (updatedCustomFieldIds.contains(tgeCustomFieldId)) { Issue issue = event.getIssue() processTgeFieldChange(issue, tgeCustomFieldId); } } private Set<Long> getUpdatedCustomFieldsIds(IssueEvent event) { List<GenericValue> changeItems = event.getChangeLog().getRelated("ChildChangeItem"); Set<Long> updatedCustomFields = new HashSet<Long>(); for (GenericValue changeItem : changeItems) { String changeType = changeItem.getString("fieldtype"); if (changeType.equalsIgnoreCase("custom")) { String customFieldName = changeItem.getString("field"); CustomField customFieldObject = customFieldManager.getCustomFieldObjectByName(customFieldName); Long customFieldId = customFieldObject.getIdAsLong() updatedCustomFields.add(customFieldId); } } return updatedCustomFields; } private void processTgeFieldChange(Issue issue, long tgeCustomFieldId) { User user = getCurrentUser(); Long issueId = issue.getId(); def result = tgeGridDataManager.readGridData(issueId, tgeCustomFieldId, null, null, 0, 10, user); List<Map<String, Object>> gridData = result.getValues(); for (Map<String, Object> row : gridData) { String selectedUserName = getSelectedUserNameFromRow(row); String previousUserName = getPreviousUserNameFromRow(row); if (selectedUserName != null && !selectedUserName.equals(previousUserName)) { sendEmailNotificationToUser(selectedUserName, issue); setPreviousUserEqualToSelected(row, issueId, tgeCustomFieldId, user); } } } private User getCurrentUser() { Object userObject = jiraAuthenticationContext.getLoggedInUser(); User user = userObject instanceof ApplicationUser ? ((ApplicationUser) userObject).getDirectoryUser() : (User) userObject; return user; } private String getSelectedUserNameFromRow(Map<String, Object> row) { Map<String, String> selectedUser = (Map<String, String>) row.get(TRACKED_USERLIST_COLUMNS_NAME) String selectedUserName = selectedUser.get("value"); return selectedUserName; } private String getPreviousUserNameFromRow(Map<String, Object> row) { return row.get(PREVIOUS_USERLIST_COLUMNS_NAME); } private void sendEmailNotificationToUser(String userName, Issue issue) { // prepare data User user = UserUtils.getUser(userName); String userEmail = user.getEmailAddress(); String baseUrl = applicationProperties.getString(APKeys.JIRA_BASEURL); String issueKey = issue.getKey(); String issueLink = baseUrl + "/browse/" + issueKey; String userDisplayName = user.getDisplayName(); // build email Email email = new Email(userEmail); email.setSubject("TGE notification"); email.setBody("Hi " + userDisplayName + "! A new task has been assigned to you in issue " + issueKey + "! Please visit <a href=\"" + issueLink + "\">" + issueKey + "</a>."); email.setMimeType("text/html"); // send it SingleMailQueueItem mailItem = new SingleMailQueueItem(email); mailQueue.addItem(mailItem); } private void setPreviousUserEqualToSelected(Map<String, Object> row, Long issueId, Long tgeCustomFieldId, User user) { List changes = new ArrayList(); // get row values Long rowId = (Long) row.get("id"); String selectedUserName = getSelectedUserNameFromRow(row); // prepare new values Map<String, Object> newRowValues = new HashMap<String, Object>(); newRowValues.put(PREVIOUS_USERLIST_COLUMNS_NAME, selectedUserName); // create changeset Class changeSetClass = pluginAccessor.getClassLoader().loadClass("com.idalko.jira.plugins.igrid.api.data.dto.TGEChangeSet"); def changeSet = changeSetClass.newInstance(); changeSet.setRowId(rowId); changeSet.setValues(newRowValues); changes.add(changeSet); // update row tgeGridDataManager.applyChanges(issueId, tgeCustomFieldId, changes, user); } } |
Then Configure Scripted Listener
Usage
Create new rows in the grid, edit existing ones. On the change of the value of the "Assignee" column new Assignee will get a TGE email notification like this
Code Block | ||
---|---|---|
| ||
Subject: TGE notification Body: Hi Samuel Stone! A new task has been assigned to you in issue TGE-1! Please visit http://seriouscopr.com/browse/TGE-1. |