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:
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.
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
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.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
@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
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
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
}
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I'm getting Null pointer exception for the issue object
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Online forums and learning are now in one easy-to-use experience.
By continuing, you accept the updated Community Terms of Use and acknowledge the Privacy Policy. Your public name, photo, and achievements may be publicly visible and available in search engines.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.