Create
cancel
Showing results for 
Search instead for 
Did you mean: 
Sign up Log in
Deleted user
0 / 0 points
Next:
badges earned

Your Points Tracker
Challenges
Leaderboard
  • Global
  • Feed

Badge for your thoughts?

You're enrolled in our new beta rewards program. Join our group to get the inside scoop and share your feedback.

Join group
Recognition
Give the gift of kudos
You have 0 kudos available to give
Who do you want to recognize?
Why do you want to recognize them?
Kudos
Great job appreciating your peers!
Check back soon to give more kudos.

Past Kudos Given
No kudos given
You haven't given any kudos yet. Share the love above and you'll see it here.

It's not the same without you

Join the community to find out what other Atlassian users are discussing, debating and creating.

Atlassian Community Hero Image Collage

Custom dialog does not open with <script> tag Edited

Hello,

i have a  problem with my custom dialog in jira.

I created a custom dialog with the rest endpoint and fragment item and this works very well. The dialog opens and shows alle fields, tables. But now i need some javascript to give this dialog some functions. But i dont know, how to do it. I followed this blog from adaptavist.

If i add the <script>...</script> tag, the dialog wont open. And i cant find an error message, what the reason could be. 

What i`m doing wrong? I hope you could help me.

I found the Dialogs (Advanced) documentation from adaptavist, but i dont understand js part below. What should i do? I hope you guys can guide me to the solution to successfully using javascript.

This is my rest endpoint script:

import com.onresolve.scriptrunner.runner.rest.common.CustomEndpointDelegate
import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.issue.Issue
import groovy.transform.BaseScript
import javax.ws.rs.core.MediaType
import javax.ws.rs.core.MultivaluedMap
import javax.ws.rs.core.Response

@BaseScript CustomEndpointDelegate delegate

static getUsersFromAD(String adGroup) {
def groupManager = ComponentAccessor.getGroupManager()
Collection users = groupManager.getUsersInGroup(adGroup)

return users[0].getDisplayName()
}


static getDialogContent(String issueKey) {
return """
<script type="text/javascript">

</script>

<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">Edit cost units</h2>
<button class="aui-close-button" type="button" aria-label="close"></button>
</header>

<div class="aui-dialog2-content">
<div id="Container" style="width:px">
<form class="aui">

<div id="colmn1" class="field-group">
<label for="ktr-input">KTR</label>
<input id="ktr-input" class="text" type="number" name="ktr-input"/>
</div>

<div id="colmn2" class="field-group">
<label>KTR Identifkation</label>
<div>
<input type="radio" id="flag-3" name="flag" value="3" checked>
<label for="flag-3">first 3</label><br>
</div>
<div>
<input type="radio" id="flag-complete" name="flag" value="complete">
<label for="flag-complete">Complete</label><br>
</div>
</div>

<div id="colmn3" class="field-group">
<label for="select-responsible">responsible</label>
<select class="select" id="select-responsible" name="select-responsible">
<option>Person X</option>
<option>Person Y</option>
<option>Person Z</option>
</select>
</div>

<div id="colmn4" class="field-group">
<label for="select-gf">Manager</label>
<select class="select" id="select-gf" name="select-gf">
<option>Person X</option>
<option>Person Y</option>
<option>Person Z</option>
</select>
</div>

<div style="float: right; margin-top: 10px; margin-bottom: 20px;">
<button id="addToTable" class="aui-button aui-button-primary">add</button>
<button id="removeFromTable" class="aui-button">clear</button>
</div>

<table class="aui">
<thead>
<tr>
<th id="KTR">KTR</th>
<th id="Responsible">Responsible</th>
<th id="GF">GF</th>
<th id="Action">Action</th>
</tr>
</thead>
<tbody>
<tr>
<td headers="KTR">733</td>
<td headers="Responsible">Person X</td>
<td headers="GF">Person Y</td>
<td headers="Action">
<button class="aui-button aui-button-link" id="edit1">Edit</button>
<button class="aui-button aui-button-link" id="delete1">Delete</button>
</td>
</tr>
<tr>
<td headers="KTR">378</td>
<td headers="Responsible">Person Z</td>
<td headers="GF">Person ZZ</td>
<td headers="Action">
<button class="aui-button aui-button-link" id="edit2">Edit</button>
<button class="aui-button aui-button-link" id="delete2">Delete</button>
</td>
</tr>
</tbody>
</table>

</form>
</div>
</div>

<footer class="aui-dialog2-footer">
<div class="aui-dialog2-footer-actions">
<button class="aui-button aui-button-primary" id="submit">Update</button>
<button id="dialog-close-button" class="aui-button aui-button-link"">Close</button>
</div>
<div class="aui-dialog2-footer-hint">This is a footer message</div>
</footer>
</section>
"""
}

// REST
showEditDialogCostUnit(groups: ["jira-administrators"]) { MultivaluedMap queryParams ->
def issueKey = queryParams.getFirst("issueId") as String
//String users = getUsersFromAD("")
String dialog = getDialogContent(users);
Response.ok().type(MediaType.TEXT_HTML).entity(dialog.toString()).build()
}


My goal is to give these buttons some functionalities. 

Our jira test system: v8.13.6, Scriptrunner: 6.23.0

Thx for your help.

1 answer

1 accepted

1 vote
Answer accepted

Try putting the script tag just before the close of the <section>.

You might want to explore using the MarkupBuilder to create your form. In my opinion, it is easier to manage than a huge long string. Especially if you have to repeat information such as for your table.

Here is your script converted up to the first field, with a little extra to get and include the javascript stored in a  different file.

I've also added your dummy data as a map in the getUserFromAD to demonstrate how you can get that data and iterate through it.

import com.onresolve.scriptrunner.runner.rest.common.CustomEndpointDelegate
import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.issue.Issue
import groovy.transform.BaseScript
import groovy.xml.MarkupBuilder
import com.atlassian.jira.config.util.JiraHome

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

@BaseScript CustomEndpointDelegate delegate

static getUsersFromAD(String adGroup) {
//def groupManager = ComponentAccessor.getGroupManager()
//Collection users = groupManager.getUsersInGroup(adGroup)

//return users[0].getDisplayName()
def usersMap = [
[ktr:733, responsible: 'person x', gf: 'person y'],
[ktr:378, responsible: 'person z', gf: 'person zz'],
]
}


static String getDialogContent(String issueKey) {
def jiraHome = ComponentAccessor.getComponent(JiraHome).home
def xmlWriter = new StringWriter()
def xml = new MarkupBuilder(xmlWriter)
xml.secion(role: 'dialog', id: 'sr-dialog', class: 'aui-layer aui-dialog2 aui-dialog2-medium', 'data-aui-remove-on-hide': 'true') {
header(class: 'aui-dialog2-header') {
h2(class: 'aui0dialog-2-header-main') { xml.mkp.yield('Edit cost units') }
button(class: 'aui-clone-button', type: 'button arial-label', ' aria-label':'close')
}
div(class: "aui-dialog2-content") {
div(id: "Container", style: "width:px") {
form(class: "aui") {
div(id: "colmn1", class: "field-group") {
label (for: "ktr-input") { xml.mkp.yield 'KTR' }
input(id: "ktr-input", class: "text", type: "number", name: "ktr-input")
}
}
}
}
table(class:'aui') {
thead {
tr {
th(id: 'KTR') { xml.mkp.yield('KTR') }
th(id: 'Responsible') { xml.mkp.yield('Responsible') }
th(id: 'GF') { xml.mkp.yield('GF') }
th(id:'Action'){ xml.mkp.yield('Action')}
}
}
tbody{
getUsersFromAD().eachWithIndex{user, index->
tr{
td(headers:'KTR'){xml.mkp.yield user['ktr']}
td(headers:'KTR'){xml.mkp.yield user['responsible']}
td(headers:'GF'){xml.mkp.yield user['gf']}
td(headers:'KTR'){
button(class:"aui-button aui-button-link",id:"edit$index"){xml.mkp.yield('Edit')}
button(class:"aui-button aui-button-link",id:"delete$index"){xml.mkp.yield('Delete')}
}
}
}
}
}
script(type:'text/javascript'){
def scriptFile = new File("$jiraHome/path/to/you/javascript/file.js")
xml.mkp.yieldUnescaped( scriptFile.getText('UTF-8'))
}
}
return xmlWriter.toString()
}

// REST
showEditDialogCostUnit(groups: ["jira-administrators"]) { MultivaluedMap queryParams ->
def issueKey = queryParams.getFirst("issueId") as String
//String users = getUsersFromAD("")
String dialog = getDialogContent(issueKey);
Response.ok().type(MediaType.TEXT_HTML).entity(dialog).build()
}

@Peter-Dave Sheehan 

Thx a lot. This helped me a lot. The MarkupBuilder is great. I wasn`t aware of this. But now im capable to debug a little bit better :-)

i struggled a little bit with your script file explaination: "$jiraHome/path.." and tried several times and now this seems to work for me and i understand your "$jiraHome" :-)
def scriptFile = new File("E:/Atlassian/.../myscript.js")
After that i added to my button an "onclick="myTest()" with an console.log()" and this seems to work either. There is a log in the console.

Do you have any hints or tips to do it in a better way? Maybe there are some build in functions i can use?!

And how can i populate my changes back to the issue? Is it possible with js? At this moment, i have no clue how i can do this.

Best regards

Are you familiar with the script root concept of scriptrunner?

In your jira-home directory, there should be a folder called "scripts". There were all the files to create and manage with the Script Editor will go.

My suggestion is to store your .js file in there. And rather than hardcoding the full path, for better portability, you get the jiraHome directory and access the file using a relative path from there.

As for how to populate your changes back to the issue, you will need to use ajax or equivalent methods from javascript to call built-in or customer REST end-point in jira.

Hello @Peter-Dave Sheehan 
i tried again the jira-home-directory and it seems to work. I guess i made some misstakes earlier. My .js file is located under the script folder. Thanks for your advice.
About the probleme to populate the changes back:
I would not want to build another REST endpoint. I think without a second endpoint it is more clearly arranged.
Can you show my an example how to use ajax or an equivalent method like you mentioned before? Something like changing a field "customfield_12034". Thanks a lot for your help and advices.

Here is an example

var customField = AJS.$('#html-id-of-the-field-in-your-dialog');
var issueKey = ''; //you'll need some way to access the issue. Maybe add a hidden field in your dialog
AJS.$.ajax({
type: "PU",
dataType: "json",
"contentType": "application/json",
headers: { "X-Atlassian-Token": "no-check" },
data: {
"fields":{
"customfield_xxxxx": customField.val()
}
},
url: `/rest/api/latest/issues/${issueKey}`,

beforeSend: function (){
//something you want to happen before making the call
},

success: function (data, status){
//something you want to do after the call returns success
},

error: function (data){
//something to do in case you have an error
console.error(data);
},
complete: function(){
//something you want to happen at the end of ajax call regardless of status
},
});

Thx, it helped me a lot.
But i had a problem with the data. When i tried execute put request i received a 400. This was the error message:

errorMessages\":[\"Unrecognized token 'fields': was expecting 'null', 'true', 'false' or NaN...

A JSON.stringify(...) fixed it for me.

 

...
var payload = {
"fields":{
"customfield_10443" : mydata
}
};

payload = JSON.stringify(payload);

AJS.$.ajax({
type: "PUT",
dataType: "json",
contentType: "application/json",
headers: { "X-Atlassian-Token": "no-check" },
data: payload,
url: `/rest/api/latest/issue/${issueKey}`,
...

 

Suggest an answer

Log in or Sign up to answer
TAGS
Community showcase
Published in Jira Service Management

JSM June Challenge #2: Share how your business teams became ITSM rockstars

For JSM June Challenge #2, share how your non-technical teams like HR, legal, marketing, finance, and beyond started using Jira Service Management! Tell us: Did they ask to start using it or...

315 views 9 7
Read article

Community Events

Connect with like-minded Atlassian users at free events near you!

Find an event

Connect with like-minded Atlassian users at free events near you!

Unfortunately there are no Community Events near you at the moment.

Host an event

You're one step closer to meeting fellow Atlassian users at your local event. Learn more about Community Events

Events near you