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.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.