Get current issue and pass it to Create Issue window in a REST endpoint script

Mario Schöck February 21, 2019

I am new to Jira, Scriptrunner and Groovy and if there is a better way in general to solve my problem I'd be happy to hear it, but a REST endpoint seemed to be what I needed.

I'd like to create a follow-up issue based on the currently displayed issue (e.g. a test issue after a bug has been fixed) with the click of a button.

Ideally I want to:

  • get the current issue as object,
  • pre-set or change some field values and
  • pass the modified issue object as parameter to the built-in Create Issue dialog window.

I managed to place a button and connect it to a REST endpoint which opens a pop-up window and displays the values of each field of a specified (hard coded) issue.

But I don't know how to get the current issue. I tried a few suggestions but they all seem to be for specific cases, like using Behaviours, Java or other types of Scripts.

Here is my code:

import com.onresolve.scriptrunner.runner.rest.common.CustomEndpointDelegate
import groovy.transform.BaseScript

import javax.ws.rs.core.MediaType
import javax.ws.rs.core.MultivaluedMap
import javax.ws.rs.core.Response

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.IssueManager

@BaseScript CustomEndpointDelegate delegate

showDialog()
{
MultivaluedMap queryParams ->

def issueManager = ComponentAccessor.getIssueManager()
def issueFactory = ComponentAccessor.getIssueFactory()

def issue = issueManager.getIssueObject("ABC-123")

def projectObj = issue.getProjectObject()
def projectName = projectObj.getName()
def issueType = issue.getIssueType().getName()

def clonedIssue = issueFactory.cloneIssueWithAllFields(issue)
clonedIssue.setReporter(issue.getAssignee())
clonedIssue.setAssignee(issue.getReporter())

 def dialog =
"""<section role="dialog" id="sr-dialog" class="aui-layer aui-dialog2 aui-dialog2-medium" aria-hidden="true" data-aui-remove-on-hide="true">
<header class="aui-dialog2-header">
<h2 class="aui-dialog2-header-main">${projectName} / ${issue.key}</h2>
<a class="aui-dialog2-header-close">
<span class="aui-icon aui-icon-small aui-iconfont-close-dialog">Close</span>
</a>
</header>
<div class="aui-dialog2-content">
<p>Issue Type: ${issueType}</p>
<p>some other variables</p>
</div>
<footer class="aui-dialog2-footer">
<div class="aui-dialog2-footer-actions">
<button id="dialog-close-button" class="aui-button aui-button-link">Close</button>
</div>
<div class="aui-dialog2-footer-hint">Optional information</div>
</footer>
</section>
"""

return Response.ok().type(MediaType.TEXT_HTML).entity(dialog.toString()).build()
}

I'd like to replace the line

def issue = issueManager.getIssueObject("ABC-123")

with the current issue. Alternatively I could extract the issue key from the URL but I couldn't find a way to get the entire URL either.

Also I'd like to replace the returning of the dialog variable to create a pop-up window with passing clonedIssue to the built-in Create Issue dialog window if that's possible. (I'd like to avoid replicating its functionality)

I welcome any solutions or suggestions.

1 answer

1 accepted

1 vote
Answer accepted
Jean-Théo [Adaptavist]
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
March 5, 2019

Hi @Mario Schöck

Where do you call your REST Endpoint from? If you are using a web-fragment on your issue view, it is quite easy to send the issue to your rest endpoint.

Here is how to do it :

Script Fragment link to your rest endpoint

/rest/scriptrunner/latest/custom/restCall?issueId=${issue.id}

 

Rest Endpoint code to add to get the issue

def issueId = queryParams.getFirst(Constants.QueryParamIssueId)
if(!issueId) return Response.ok(JsonOutput.toJson([type: 'error', title: "No Issue With id", close: 'auto', body: "The issue has not been found"])).build()
Issue issue = issueManager.getIssueObject(issueId as long)
if(!issue) return Response.ok(JsonOutput.toJson(Constants.NoIssueMessage[type: 'error', title: "No Issue With id", close: 'auto', body: "The issue has not been found"])).build()

 I hope this helps,

JT

Mario Schöck March 21, 2019

Thank you very much. That's exactly what I was looking for. I am indeed using a web-fragment for the button but I didn't know that it was possible to pass parameters. Thank you.

I couldn't figure out how to make Constants.QueryParamIssueId work, so I replaced it with the parameter name ("issueId"), and now that part works.

Do you know if it is possible to open Jira's "Create Issue" form with pre-filled values?

Or should I open a separate question for that problem?

edit:

The "Constrained create issue dialog" Script Fragment is partly what I need but I want to set the values based on what Issue I am currently viewing.

Oleksii Okhmush January 23, 2020

@Mario Schöck may you show please, how did you replace 

I couldn't figure out how to make Constants.QueryParamIssueId work, so I replaced it with the parameter name ("issueId"), and now that part works.

so its worked in your code

Mario Schöck January 24, 2020

This worked for me:

def passedIssueId = queryParams.getFirst("issueId")
def issueManager = ComponentAccessor.getIssueManager()
Issue issue = issueManager.getIssueObject(passedIssueId as long)

The parameter name must be the same as in the link in the Script Fragment button:

/rest/scriptrunner/latest/custom/createFollowUp?issueId=${issue.id}

 

I couldn't figure out how to open the "Create Issue"-dialog like I orignally wanted. Instead after clicking the button the issue is automatically created and the user will be informed about it in a dialog-box:

import com.atlassian.jira.bc.issue.IssueService
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.IssueInputParameters
import com.atlassian.jira.issue.IssueManager
import com.onresolve.scriptrunner.runner.rest.common.CustomEndpointDelegate
import groovy.transform.BaseScript
import groovy.json.JsonOutput
import javax.ws.rs.core.MediaType
import javax.ws.rs.core.MultivaluedMap
import javax.ws.rs.core.Response

@BaseScript CustomEndpointDelegate delegate

createFollowUp()
{
MultivaluedMap queryParams ->

def passedIssueId = queryParams.getFirst("issueId")
if(!passedIssueId)
return Response.ok(JsonOutput.toJson([type: 'error', title: "No Issue With id", close: 'auto', body: "Issue not found"])).build()

def issueManager = ComponentAccessor.getIssueManager()

// Get issue through passed parameter
Issue issue = issueManager.getIssueObject(passedIssueId as long)

def newIssue = createNewIssue(issue)

def dialog = """...""" // dialog from my original post with added info about the new issue

return Response.ok().type(MediaType.TEXT_HTML).entity(dialog.toString()).build()
}



Issue createNewIssue(Issue originalIssue)
{
def currentUser = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

IssueService issueService = ComponentAccessor.getIssueService()
IssueInputParameters issueInputParameters = issueService.newIssueInputParameters()
// Set issue parameters
issueInputParameters
.setProjectId(originalIssue.getProjectObject().getId())
.setSummary("FOLLOW-UP - " + originalIssue.getSummary())
.setDescription("")
.setIssueTypeId(originalIssue.getIssueTypeId())
.setReporterId(currentUser.getUsername())
.setAssigneeId(null)

IssueService.CreateValidationResult createVR = issueService.validateCreate(currentUser, issueInputParameters)

def newIssue = issueService.create(currentUser, createVR).getIssue()

// Link new and original issue
def issueLinkManager = ComponentAccessor.getIssueLinkManager()
issueLinkManager.createIssueLink(originalIssue.getId(), newIssue.getId(), 10003, 1, currentUser) // 10003 = "relates to"

return newIssue
}
Pradeep A July 8, 2021

Hi @Jean-Théo [Adaptavist] 

I'm getting Null pointer exception for the issue object

Suggest an answer

Log in or Sign up to answer
TAGS
AUG Leaders

Atlassian Community Events