How to actually use the Dialog2 along with a groovy script in Script Runner?

Zhixun Deng May 17, 2017

My goal is to produce a custom buttom, on clicking which a dialog with some checkboxes and text fields will be shown. After the user enters all the information and clicks the confirm button, another REST endpoint will be called which should take the information and do something I really want. All these things should be done within Script Runner.

 

As far as I know, the process should be:

1. create a "Custom web item" which "Run code and display a dialog"

2. create a corresponding REST endpoint script containing some HTML

3. create the second  REST endpoint script which does things I want

4. finish the interaction details of the script in step2

 

Now I already have the second REST endpoint script (which is responsible for some integration between JIRA and other services), so what I need is to make a dialog, require some information and call the other endpoint when the confirm button is clicked. I understand that this requires some Javascript, but I find myself stuck just at the beginning which is making the javascript cooperate with the HTML part, or more exactly  the groovy script. I've done quite a lot searching but since I'm both new to javascript and HTML there are just too many concepts which make me really confused.

I took the example from here https://scriptrunner.adaptavist.com/latest/jira/fragments/WebItem.html and made my endpoint code so:

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

@BaseScript CustomEndpointDelegate delegate

showDialog() { MultivaluedMap queryParams ->
    
    def sprintId = queryParams.getFirst("sprintId") as String;
    def boardId = queryParams.getFirst("boardId") as String;

    // get a reference to the current page...
    // def page = getPage(queryParams)

    def dialog =
        """
			<section role="dialog" id="sr-dialog" class="aui-layer aui-dialog2 aui-dialog2-medium" aria-hidden="true">
				
				<header class="aui-dialog2-header">
					<h2 class="aui-dialog2-header-main">Create IMS Checkpoint</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">
					<div id="container"  style="width:px">
						<form class="aui">
						<div id="projects" style="height:220px;width:280px;float:left;">
							<p>Please select the project:</p>
							<p>
							<input class="checkbox" type="checkbox" name="project" value="projectA">MB_213_16_PSCM_ECU</input><br>
							<input class="checkbox" type="checkbox" name="project" value="projectB">MB_213_16_PSCM_CCC</input><br>
							<input class="checkbox" type="checkbox" name="project" value="projectC">MB_223_19_PSCM_ECU</input><br>
							<input class="checkbox" type="checkbox" name="project" value="projectD">MB_223_16_PSCM_CCC</input><br>
							</p>
						</div>
						<div id="description" style="height:220px;width:280px;float:left;">
							<p>Please enter the description information:</p>
							<p>Info1: <input id="input1" class="text" type="text" name="descriptionInfo1"></input><br>
							   Info2: <input id="input2" class="text" type="text" name="descriptionInfo2"></input><br></p>
						</div>
						</form>
					</div>
				</div>
				<footer class="aui-dialog2-footer">
					<div class="aui-dialog2-footer-actions">
						<button id="submit-button" class="aui-button aui-button-primary">Confirm</button>
						<button id="dialog-close-button" class="aui-button aui-button-link">Close</button>
					</div>
					<div class="aui-dialog2-footer-hint">Some hint here if you like</div>
				</footer>
			</section>		
        """
    Response.ok().type(MediaType.TEXT_HTML).entity(dialog.toString()).build()
	
}

The script works fine and will create a dialog with checkboxes, textfields and a confirm button. Then comes the problem, I have no idea how to combine it with a javascrpt specifically. For instance, it is written on the page that The button with the ID dialog-close-button will be automatically wired to close when clicked if you use a dialog ID of sr-dialog. If you require more complex interactions you should require some javascript and wire the elements: I really have no idea how to wire the elements.

And the You must explicitly require the web resource key on https://docs.atlassian.com/aui/latest/docs/dialog2.html makes me even more confused because I didn't see it in the example above. If I do a little bit more digging into it I will just find many things about XML which are apparently not what I want. Reading the web resource fragment and Web Resource Plugin Module won't help too.

Actually there is already a question where @Roberto Saltini wanted to do similar things How to call a script runner REST endpoint from a custom Dialog connecte to a script runner Web Item?, gramatically I understand what the code provided there will do, but agian the problem is I don't know how to apply it. Acutally I don't have a clear picture of how things cooperate with each other here. Lik I said, I'm new to javascript and html, so the single way I know for now to combine javacript with html is to put the javascript code into the html code wrapped by a pair of tags, but here the html code itself is just a fragment of a groovy script, besides there is something called AJS which indicates maybe some JIRA configuration also needs to be involved, it's just getting too complicated for me and there seems to be nothing helpful online for a beginner like me.

Could anyone give some clear clues for that? Thanks very much.

3 answers

1 accepted

2 votes
Answer accepted
Jonny Carter
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
June 13, 2017

I think you're really close, actually. It's easy to get lost in the documentation forest.

Basically, you just need some way to send the contents of your dialog box's form to the second REST endpoint, right?

It seems to me that one way you could do that would be to put the submit buttons inside the form and just point the form's action attribute to your REST endpoint. You can get the base URL of JIRA like this:

import com.atlassian.jira.config.properties.APKeys
import com.atlassian.jira.component.ComponentAccessor

def baseUrl = ComponentAccessor.getApplicationProperties().getString(APKeys.JIRA_BASEURL)

 Then reference it in your form like this (note how I put the submit button inside the form):

<section role="dialog" id="sr-dialog" class="aui-layer aui-dialog2 aui-dialog2-medium" aria-hidden="true">

    <header class="aui-dialog2-header">
        <h2 class="aui-dialog2-header-main">Create IMS Checkpoint</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">
        <div id="container" style="width:px">
            <form id="my-custom-sr-dialog-form" class="aui" action="${baseUrl/rest/scriptrunner/latest/custom/yourSecondEndpoint}">
                <div id="projects" style="height:220px;width:280px;float:left;">
                    <p>Please select the project:</p>
                    <p>
                        <input class="checkbox" type="checkbox" name="project" value="projectA">MB_213_16_PSCM_ECU</input>
                        <br>
                        <input class="checkbox" type="checkbox" name="project" value="projectB">MB_213_16_PSCM_CCC</input>
                        <br>
                        <input class="checkbox" type="checkbox" name="project" value="projectC">MB_223_19_PSCM_ECU</input>
                        <br>
                        <input class="checkbox" type="checkbox" name="project" value="projectD">MB_223_16_PSCM_CCC</input>
                        <br>
                    </p>
                </div>
                <div id="description" style="height:220px;width:280px;float:left;">
                    <p>Please enter the description information:</p>
                    <p>Info1: <input id="input1" class="text" type="text" name="descriptionInfo1"/><br>
                        Info2: <input id="input2" class="text" type="text" name="descriptionInfo2"/><br></p>
                </div>
                <button id="submit-button" class="aui-button aui-button-primary">Confirm</button>
            </form>
        </div>
    </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">Some hint here if you like</div>
    </footer>
</section>

That will cause the form's data to get posted to your REST endpoint, though notably, it will also navigate your users to a different page (whatever is returned by your REST endpoint). Maybe that's what you want, but you probably want something a little more AJAXy. In that case, don't move your button around, but add some JavaScript like that below as a custom web resource:

 

 

(function ($) {
    $(function () {
        AJS.dialog2.on("show", function (e) {
                var targetId = e.target.id;
                if (targetId === "sr-dialog") {
                    var someDialog = AJS.dialog2(e.target);
                    $(e.target).find("#submit-button").click(function (button) {
                        $.ajax({
                            type: "POST",
                            url: AJS.contextPath() + "/rest/scriptrunner/latest/custom/yourSecondEndpoint",
                            data: AJS.$(window.opener.document).find("#my-custom-sr-dialog-form").serialize(),
                            beforeSend: function (request) {
                                request.setRequestHeader("X-Atlassian-token", "no-check");
                            }
                        }).done(function(response) {
                            //do whatever needs done in the UI here
                        });
                    });
                }
            }
        );
    });
})(AJS.$);

If you need some help figuring out how the $.ajax function works, consult the relevant jQuery docs.

 

Zhixun Deng June 22, 2017

Hi Jonny,

thanks very much! Actually before you answered I figured out a way by myself which is not to a add a submit button inside the form but add a normal button outside the form and add some javascripts to send a POST when the button is clicked (because I do not want the page to be redirected, instead I only need some information sent), so far it works well, but I guess there's something not so good with this solution as you emphasized "don't move your button around", right? So what's the difference between these two solutions?

Best regards

Zhixun

Jonny Carter
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
June 28, 2017

Your solution sounds fine, and is totally legitimate. I just meant if you moved the button my code would break, but clearly you're comfortable working around that. :)

0 votes
Raul Pelaez _TecnoFor - Marketplace Partner_
Marketplace Partner
Marketplace Partners provide apps and integrations available on the Atlassian Marketplace that extend the power of Atlassian products.
September 21, 2020
תהילה יששכר January 27, 2021

Hey, @Raul Pelaez _TecnoFor - Marketplace Partner_ 
I want to build dialog like yours but when I paste the code it looks like
Capture.PNG
Can you help understanding what I did wrong?

תהילה יששכר January 27, 2021

I have this log in my rest endpoint 

The following log information was produced by this execution. Use statements like:log.info("...") to record logging information.

2021-01-27 09:06:05,900 ERROR [common.UserCustomScriptEndpoint]: *************************************************************************************
2021-01-27 09:06:05,900 ERROR [common.UserCustomScriptEndpoint]: Script endpoint failed on method: GET showDialog
java.lang.NullPointerException: Cannot invoke method replaceAll() on null object
at java_lang_String$replaceAll$4.call(Unknown Source)
at Script278.trimIssueKey(Script278.groovy:34)
at Script278$trimIssueKey.callStatic(Unknown Source)
at Script278$trimIssueKey.callStatic(Unknown Source)
at Script278$_run_closure1.doCall(Script278.groovy:100)
at com.onresolve.scriptrunner.runner.rest.common.UserCustomScriptEndpoint$_doEndpoint_closure2.doCall(UserCustomScriptEndpoint.groovy:221)
at com.onresolve.scriptrunner.runner.rest.common.UserCustomScriptEndpoint$_doEndpoint_closure2.doCall(UserCustomScriptEndpoint.groovy)
at com.onresolve.scriptrunner.runner.diag.DiagnosticsManagerImpl$DiagnosticsExecutionHandlerImpl$_execute_closure1.doCall(DiagnosticsManagerImpl.groovy:345)
at com.onresolve.scriptrunner.runner.diag.DiagnosticsManagerImpl$DiagnosticsExecutionHandlerImpl$_execute_closure1.doCall(DiagnosticsManagerImpl.groovy)
at com.onresolve.scriptrunner.runner.ScriptExecutionRecorder.withRecording(ScriptExecutionRecorder.groovy:13)
at com.onresolve.scriptrunner.runner.ScriptExecutionRecorder$withRecording.call(Unknown Source)
at com.onresolve.scriptrunner.runner.diag.DiagnosticsManagerImpl$DiagnosticsExecutionHandlerImpl.execute(DiagnosticsManagerImpl.groovy:343)
at com.onresolve.scriptrunner.runner.rest.common.UserCustomScriptEndpoint.doEndpoint(UserCustomScriptEndpoint.groovy:215)
at com.onresolve.scriptrunner.runner.rest.common.UserCustomScriptEndpoint.getUserEndpoint(UserCustomScriptEndpoint.groovy:108)

Raul Pelaez _TecnoFor - Marketplace Partner_
Marketplace Partner
Marketplace Partners provide apps and integrations available on the Atlassian Marketplace that extend the power of Atlassian products.
January 27, 2021

Hello, the code must be inserted as custom REST Endpoint using the standard process of Scriptrunner. After this you need to create the action (button) inside the ticket (this is a Web Fragment) The Web Fragment will run the query to the REST custom endpoint and will show the Dialog.

First start with a simple example like this:

https://mraddon.blog/2017/03/29/jira-scriptrunner-rest-endpoint-web-fragment-example/

Regards!

תהילה יששכר January 27, 2021

@Raul Pelaez _TecnoFor - Marketplace Partner_ Now I dont have Java error but I have a problem that the dialog opens over a full screen and looks styleless. 

0 votes
Quinton Lephoto June 6, 2019

@ZhixunDeng, can you please post the code of your first nad second rest point for our better understanding. thanks in advance

Zhixun Deng June 6, 2019

I'm sorry, but I posted this question about two years ago when I was doing those stuff for my internship, and I have already forgotten all of it for too long... I guess the question can just be ignored now.

Suggest an answer

Log in or Sign up to answer
TAGS
AUG Leaders

Atlassian Community Events