Hi all,
Based on my previous post, I want to be able to parse JSON data to an html table from data pulled from an external API, which in our case is our ServiceNow instance.
The REST Endpoint Code is as follows:
import com.onresolve.scriptrunner.runner.rest.common.CustomEndpointDelegate
import groovy.json.JsonBuilder
import groovy.json.JsonOutput
import groovy.json.JsonSlurper
import groovy.xml.MarkupBuilder
import groovy.transform.BaseScript
import groovyx.net.http.ContentType
import groovyx.net.http.HTTPBuilder
import groovyx.net.http.Method
import javax.ws.rs.core.MultivaluedMap
import javax.ws.rs.core.Response
import javax.ws.rs.core.MediaType
@BaseScript CustomEndpointDelegate delegate2
CMRDisplay(httpMethod: "GET") { MultivaluedMap queryParams ->
def query = queryParams.getFirst("query") as String
def rt = [:]
if (query) {
String url = "https://test.service-now.com"
String uriPath = "/api/now/table/u_jira_change_data"
HTTPBuilder http = new HTTPBuilder(url)
def output = http.request(Method.GET, ContentType.JSON) {
uri.path = uriPath
uri.query = [sysparm_query:"u_jira_ticket_number=$query", sysparm_fields:"u_change_record.number,u_change_record.short_description,u_change_record.state", sysparm_display_value: "true"]
headers.'Authorization' = "Basic ${"xxxxxxxx".bytes.encodeBase64().toString()}"
response.failure = { resp, reader ->
log.warn("Failed to query ServiceNow API: " + reader.text)
}
}
def cmrState = output["result"]*."u_change_record.state"
def cmrNumber = output["result"]*."u_change_record.number"
def cmrDesc = output["result"]*."u_change_record.short_description"
def table =
"""<table class="aui aui-table-list" aria-hidden="true">
<thead>
<tr>
<th id="record-num">Record Number</th>
<th id="record-desc">Description</th>
<th id="record-state">State</th>
</tr>
</thead>
<tbody>
<tr class="aui-row-subtle">
<td headers="record-num">${cmrNumber}</td>
<td headers="record-desc">${cmrDesc}</td>
<td headers="record-state">${cmrState}</td>
</tr>
</tbody>
</table>
"""
Response.ok().type(MediaType.TEXT_HTML).entity(table.toString()).build()
}
}
Working with a test issue in our sandbox instance, we get the following JSON data:
{
"result": [
{
"u_change_record.number":"CHG0010042",
"u_change_record.state":"Draft",
"u_change_record.short_description":"test app req 5"
},
{
"u_change_record.number":"CHG0010061",
"u_change_record.state":"Draft",
"u_change_record.short_description":"test"
},
{
"u_change_record.number":"CHG0016010",
"u_change_record.state":"Draft",
"u_change_record.short_description":"Test Jira"
},
{
"u_change_record.number":"CHG0010057",
"u_change_record.state":"Draft",
"u_change_record.short_description":"tesst"
}
]
}
And the REST Endpoint code renders the json into the following. html table:
My only problem now is that the rows don't generate as expected. Obviously, there should be 4 rows in total, with [CMR1..., test app req 5, Draft] in one row, then [CMR2..., test, Draft] as the second row, and so on. But instead, the output results are being crammed into one row.
I want the table to look something like this, but styled with css to resemble a Jira table:
Additionally, the css class attributes don't take effect for some reason. Referencing Jira's AUI Documentation, I figured that the CSS would automatically apply when referencing the 'aui' class in for the table.
I know I have to iterate through the JSON Map somehow, but I don't know how to map that out to the html table and have each record number/recrod desc/record state set listed out as rows on the table.
Any tips/suggestions as always are highly appreciated!
I would recommend you become familiar with groovy's markup builder
Here is something I quickly put together to in the Scriptrunner Console
import groovy.json.JsonSlurper
import groovy.xml.MarkupBuilder
def jsonString ="""{"result": [{
"u_change_record.number":"CHG0010042",
"u_change_record.state":"Draft",
"u_change_record.short_description":"test app req 5"
},{
"u_change_record.number":"CHG0010061",
"u_change_record.state":"Draft",
"u_change_record.short_description":"test"
},{
"u_change_record.number":"CHG0016010",
"u_change_record.state":"Draft",
"u_change_record.short_description":"Test Jira"
},{
"u_change_record.number":"CHG0010057",
"u_change_record.state":"Draft",
"u_change_record.short_description":"tesst"
}]}"""
def json = new JsonSlurper().parseText(jsonString)
def writer = new StringWriter()
def xml = new MarkupBuilder(writer)
xml.table(class:'aui'){
thead{
tr{
json.result[0].keySet().each{
th it.split(/\./)[1]
}
}
}
tbody{
json.result.each{ res->
tr{
res.values().each{
td it
}
}
}
}
}
writer.toString()
That generated a table that looks like this:
Hi @Peter-Dave Sheehan ,
Thanks for the reply! I'll be sure to further reference the XML Builder. Hopefully I can use it in this case.
So I tried using the the code you provided and integrating it with the REST Endpoint code. I do believe this is close to the solution I am looking for. The only thing, however, is that I think the REST Endpoint code has to return a javax.ws.rs.core.Response
object.
This is how I modified the code to include yours:
import com.onresolve.scriptrunner.runner.rest.common.CustomEndpointDelegate
import groovy.json.JsonBuilder
import groovy.json.JsonOutput
import groovy.json.JsonSlurper
import groovy.xml.MarkupBuilder
import groovy.transform.BaseScript
import groovyx.net.http.ContentType
import groovyx.net.http.HTTPBuilder
import groovyx.net.http.Method
import javax.ws.rs.core.MultivaluedMap
import javax.ws.rs.core.Response
import javax.ws.rs.core.MediaType
@BaseScript CustomEndpointDelegate delegate2
CMRDisplay(httpMethod: "GET") { MultivaluedMap queryParams ->
def query = queryParams.getFirst("query") as String
def rt = [:]
if (query) {
String url = "https://test.service-now.com"
String uriPath = "/api/now/table/u_jira_change_data"
HTTPBuilder http = new HTTPBuilder(url)
def output = http.request(Method.GET, ContentType.JSON) {
uri.path = uriPath
uri.query = [sysparm_query:"u_jira_ticket_number=$query",
sysparm_fields:"u_change_record.number,u_change_record.short_description,u_change_record.state",
sysparm_display_value: "true"]
headers.'Authorization' = "Basic ${"xxxxxxxx".bytes.encodeBase64().toString()}"
response.failure = { resp, reader ->
log.warn("Failed to query ServiceNow API: " + reader.text)
}
}
def cmrState = output["result"]*."u_change_record.state"
def cmrNumber = output["result"]*."u_change_record.number"
def cmrDesc = output["result"]*."u_change_record.short_description"
rt = output
def json = new groovy.json.JsonBuilder()
json rootKey: rt
def jsonString = rt.toString()
def jsonOutput = new JsonSlurper().parseText(jsonString)
def writer = new StringWriter()
def xml = new MarkupBuilder(writer)
xml.table(class:'aui'){
thead{
tr{
jsonOutput.result[0].keySet().each{
th it.split(/\./)[1]
}
}
}
tbody{
jsonOutput.result.each{ res->
tr{
res.values().each{
td it
}
}
}
}
}
Response.ok().type(MediaType.TEXT_HTML).entity(writer.toString()).build()
}
}
Upon testing this endpoint, unfortunately it didn't produce the table but rather this String message:
{"message":"expecting '}' or ',' but got current char 'r' with an int value of 114\n\nThe current
character read is 'r' with an int value of 114\nexpecting '}' or ',' but got current char 'r' with an
int value of 114\nline number 1\nindex number 1\n{result=[{u_change_record.number=CHG0010042,
u_change_record.state=Draft, u_change_record.short_description=test app req 5},
{u_change_record.number=CHG0010061, u_change_record.state=Draft,
u_change_record.short_description=test}, {u_change_record.number=CHG0016010,
u_change_record.state=Draft, u_change_record.short_description=Test Jira},
{u_change_record.number=CHG0010057, u_change_record.state=Draft,
u_change_record.short_description=tesst}]}\n.^","stack-trace":"groovy.json.JsonException: expecting '}'
or ',' but got current char 'r' with an int value of 114\n\nThe current character read is 'r' with an
int value of 114\nexpecting '}' or ',' but got current char 'r' with an int value of 114\nline number
1\nindex number 1\n{result=[{u_change_record.number=CHG0010042, u_change_record.state=Draft,
u_change_record.short_description=test app req 5}, {u_change_record.number=CHG0010061,
u_change_record.state=Draft, u_change_record.short_description=test},
{u_change_record.number=CHG0016010, u_change_record.state=Draft, u_change_record.short_description=Test
Jira}, {u_change_record.number=CHG0010057, u_change_record.state=Draft,
u_change_record.short_description=tesst}]}\n.^\n\tat
org.apache.groovy.json.internal.JsonParserCharArray.complain(JsonParserCharArray.java:149)\n\tat
org.apache.groovy.json.internal.JsonParserCharArray.decodeJsonObject(JsonParserCharArray.java:140)\n\tat
org.apache.groovy.json.internal.JsonParserCharArray.decodeValueInternal(JsonParserCharArray.java:182)\n\
tat org.apache.groovy.json.internal.JsonParserCharArray.decodeValue(JsonParserCharArray.java:153)\n\tat
org.apache.groovy.json.internal.JsonParserCharArray.decodeFromChars(JsonParserCharArray.java:43)\n\tat
org.apache.groovy.json.internal.JsonParserCharArray.parse(JsonParserCharArray.java:380)\n\tat
org.apache.groovy.json.internal.BaseJsonParser.parse(BaseJsonParser.java:110)\n\tat
Script1839$_run_closure1.doCall(Script1839.groovy:52)\n\tat
com.onresolve.scriptrunner.runner.rest.common.UserCustomScriptEndpoint$_doEndpoint_closure2.doCall(UserCustomScriptEndpoint.groovy:187)\n\tat
com.onresolve.scriptrunner.runner.rest.common.UserCustomScriptEndpoint$_doEndpoint_closure2.doCall(UserCustomScriptEndpoint.groovy)\n\tat
com.onresolve.scriptrunner.runner.diag.DiagnosticsManagerImpl$DiagnosticsExecutionHandlerImpl$_execute_closure1.doCall(DiagnosticsManagerImpl.groovy:350)\n\tat
com.onresolve.scriptrunner.runner.diag.DiagnosticsManagerImpl$DiagnosticsExecutionHandlerImpl$_execute_closure1.doCall(DiagnosticsManagerImpl.groovy)\n\tat
com.onresolve.scriptrunner.runner.ScriptExecutionRecorder.withRecording(ScriptExecutionRecorder.groovy:13)\n\tat
com.onresolve.scriptrunner.runner.ScriptExecutionRecorder$withRecording$0.call(Unknown Source)\n\tat
com.onresolve.scriptrunner.runner.diag.DiagnosticsManagerImpl$DiagnosticsExecutionHandlerImpl.execute(DiagnosticsManagerImpl.groovy:348)\n\tat
com.onresolve.scriptrunner.runner.rest.common.UserCustomScriptEndpoint.doEndpoint(UserCustomScriptEndpoint.groovy:220)\n\tat
com.onresolve.scriptrunner.runner.rest.common.UserCustomScriptEndpoint.getUserEndpoint(UserCustomScriptEndpoint.groovy:71)\n","status-code":"INTERNAL_SERVER_ERROR"}
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
First, it looks like you left some api credentials in your last comment. If they are real, you might want to obfuscate them.
Second, I'm not sure what this section's purpose is:
rt = output
def json = new groovy.json.JsonBuilder()
json rootKey: rt
def jsonString = rt.toString()
def jsonOutput = new JsonSlurper().parseText(jsonString)
But it seems that that might be what is triggering your error.
The HTTPBuilder should already have taken care of parsing the JSON response into a data structure object.
You should be able to just use that instead of my jsonOutput.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Thanks for mentioning the credentials part...big uh oh on my end.
And yes that's exactly what it was. I forgot the builder already took care of the Json.
Now I have a table as expected :D
Many Thanks!
Only one question left though...how come the builder didn't register the "class:aui" attribute? Because now the only thing is that the css didn't carry over.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
The class is there is you inspect the html.
But when calling just a rest api, the styles are not loaded. If you were to display this table in web-panel within an existing Jira environment (where all the styles and scripts are loaded) then the table will have the desired style.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Ah ok, gotcha. So if I wanted to have the table stylized, I'd have to apply some inline css in the endpoint code?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Correct, but maybe instead of in-line style, create a <style> block above your table and then use class names in your table. Especially if you need to apply certain styles for each row or cell.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Ok. Two more things (and then I should be good to go. You've been a really great help to me, I can't thank you enough!):
1.) When you mention creating a style block above my table, how exactly would I initiate that? Would I write something like :
style{
.
css
.
}
right above where the structure of the table starts (above xml.table), define the classes with css elements, and then reference the class names for thead, dr, etc.? (Hope this makes sense.)
2.) Looking through the groovy markup builder doc that you referred to me in the beginning of this post, I don't see anything about css property names that are accepted in groovy/by the markupbuilder. If you review the css I added to the headers and (attempted to add to the) table:
xml.table('style':'column-rule: 4px double #ff00ff'){
thead('style':'color:rgba(183,189,199,255); font-family:arial,sans-serif; border: 1px solid #dddddd'){
tr{
jsonOutput.result[0].keySet().each{
th it.split(/\./)[1]
}
}
}
tbody{
jsonOutput.result.each{ res->
tr{
res.values().each{
td it
}
}
}
}
}
The color and font for the headers change, as expected. But the border doesn't get created, and for the table as a whole, the column-rule property doesn't get rendered. Is this because I'm not setting the properties correctly?
And on a further note regarding the css properties usable by the markupbuilder code/groovy in general, do you know of any documentation/web resources that I could reference to further build upon stylizing the table within the rest endpoint code? My end goal is to make this table look similar to the tables in a jira environment...like the table generated from the markup builder code that you ran in the scriptrunner console.
________________________
I'm very close to the output I'm looking for from the REST Endpoint, and I couldn't have done it without your help. Thank you!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
For the style tag, I would do it like this:
def xml = new MarkupBuilder(writer)
xml.style{
mkp.yieldUnescaped """
.aui td {color:red}
"""
}
xml.table(class:'aui'){
[...]
}
For in-line style or any other attribute, just give the tags a list of attributes in map form to the parens for the tag. The map can be right in the markup builder, or you can extract it and put it in a variable
For example
def tableAttr = [ class:'aui', style:'column-rule: 4px double #ff00ff']
xml.table(tableAttr){
{...]
}
Or
xml.table(class:'aui', style:'column-rule: 4px double #ff00ff'){
{...]
}
Now, I'm not really great at css and formatting. So I can't tell you how to write your css or in-line styles to get your desired results. But just by grabbing all the css from my chrome developer pannel, you can try this (inside the triple-quotes):
table.aui {border-collapse: collapse;width: 100%}
table.aui table.aui {margin: 0}
table.aui>caption {color: #7a869a;background: #f4f5f7;border-bottom: 1px solid #dfe1e6;
caption-side: top;padding: 7px 10px;text-align: left}
table.aui>tbody>tr>td,table.aui>tbody>tr>th,table.aui>tfoot>tr>td,table.aui>tfoot>tr>th,table.aui>thead>tr>td,table.aui>thead>tr>th {
padding: 7px 10px;text-align: left;vertical-align: top}
table.aui>tbody>tr>td>ul.menu,table.aui>tbody>tr>th>ul.menu,table.aui>tfoot>tr>td>ul.menu,table.aui>tfoot>tr>th>ul.menu,table.aui>thead>tr>td>ul.menu,table.aui>thead>tr>th>ul.menu {
list-style-type: none;margin: 0;padding: 0}
table.aui>tbody>tr>td>ul.menu>li,table.aui>tbody>tr>th>ul.menu>li,table.aui>tfoot>tr>td>ul.menu>li,table.aui>tfoot>tr>th>ul.menu>li,table.aui>thead>tr>td>ul.menu>li,table.aui>thead>tr>th>ul.menu>li {
float: left;margin: 0 10px 0 0;width: auto}
table.aui>tbody>tr,table.aui>tfoot>tr {background: #fff;color: #172b4d}
table.aui>tbody>tr:first-child>td,table.aui>tbody>tr:first-child>th,table.aui>tfoot>tr:first-child>td,table.aui>tfoot>tr:first-child>th {
border-top: 1px solid #dfe1e6}
table.aui>thead {border-bottom: 2px solid #dfe1e6}
table.aui>tbody>tr>th,table.aui>thead>tr>th {
color: #7a869a;font-size: 12px;font-weight: 600;line-height: 1.66666667;
letter-spacing: 0;text-transform: none}
table.aui>tbody>tr>th {font-size: inherit;background: #fff}
table.aui .aui-button-link {padding-top: 0;padding-bottom: 0;line-height: inherit;
height: auto;border: 0}
table.aui:not(.aui-table-list)>tbody>tr>td,table.aui:not(.aui-table-list)>tbody>tr>th,table.aui:not(.aui-table-list)>tfoot>tr>td,table.aui:not(.aui-table-list)>tfoot>tr>th {
border-bottom: 1px solid #dfe1e6}
table.aui.aui-table-interactive>tbody>tr:focus-within,table.aui.aui-table-interactive>tbody>tr:hover,table.aui.aui-table-list>tbody>tr:focus-within,table.aui.aui-table-list>tbody>tr:hover {
background: rgba(9,30,66,.08)}
table.aui.aui-table-interactive>tbody>tr.aui-row-subtle *,table.aui.aui-table-list>tbody>tr.aui-row-subtle * {
color: #b3bac5}
table.aui.aui-table-interactive>tbody>tr.aui-row-subtle * .aui-avatar,table.aui.aui-table-interactive>tbody>tr.aui-row-subtle * .aui-button,table.aui.aui-table-interactive>tbody>tr.aui-row-subtle * .aui-icon,table.aui.aui-table-list>tbody>tr.aui-row-subtle * .aui-avatar,table.aui.aui-table-list>tbody>tr.aui-row-subtle * .aui-button,table.aui.aui-table-list>tbody>tr.aui-row-subtle * .aui-icon {
opacity: .8}
And Finally, when testing this, I found that the browser ignores some css if you don't include the DOCTYPE declaration.
I was able to do it like this:
Response.ok().type(MediaType.TEXT_HTML).entity('<!DOCTYPE html>' +writer.toString()).build()
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
And there we have it! Amazing!
@Peter-Dave Sheehan Thanks for putting the time into helping with this!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi @Peter-Dave Sheehan ,
Hope this isn't a big ask...this deviates a little from my original ask for this post, but there's two other things I wanted to do with this table.
Is there a way to update/overwrite the table headers that were pulled from the api request (number, state, short_description) to "Number", "Status", "Short Description"?
And also, for each value in the number column, how would I go about converting each value to a link that references the value itself in the loop? For example, for the number CHG0010042, it would contain the link: "test.com/CHG0010042", and CHG0010061 would contain: test.com/CHG0010061, and so on.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I was actually able to change the table headers myself. It was just simply listing the values for the headers rather than iterating though the key values:
xml.table(class:'aui') {
thead {
tr{
th 'Number'
th 'Status'
th 'Short Description'
}
}
tbody{
output.result.each{ res->
tr{
res.values().each{
td it
}
}
}
}
}
Now I just need to figure out how to embed a link in each of the record number values (test.com/${number}).
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
The potential danger your manually putting in the headers is that with JSON and the resulting map object, there is no guarantee of the order of the fields. Should that change for some reason in the API, you may get mis-allignment.
You can get around that by also defining each td by calling a specific key.
tbody{
output.result.each{ res->
tr{
td res['u_change_record.number']
td res['u_change_record.state']
td res['u_change_record.short_description']
}
}
}
But you would loose the ability of capturing new columns automatically (you may not want that).
Another possible approach would be to create a simple mapping.
def headerMaps = [
'u_change_record.number': 'Number',
'u_change_record.state' : 'State',
'u_change_record.short_description' : 'Short Description'
]
Then
thead {
tr{
json.result[0].keySet().each{
th headerMaps[it] ?: it.split(/\./)[1]
}
}
}
With this, you will get the mapped value if it is found, but there will always be a fallback of using the built-in key value.
As for creating a link, if using the static approach above, you can expand it to add the link like this:
tbody{
output.result.each{ res->
tr{
td {
def number = res['u_change_record.number']
a(href:"https://test.com/$number",target:'_blank') number
}
td res['u_change_record.state']
td res['u_change_record.short_description']
}
}
}
If you are still using the loop
tbody{
output.result.each{ res->
tr{
res.values().each{
if(it=='number'){
td {
def number = res['u_change_record.number']
a(href:"https://test.com/$number",target:'_blank') number
}
} else {
td it
}
}
}
}
}
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Thanks for the suggestion of mapping/calling the headers! I didn't think about the order of the values potentially changing up in response.
The updated headers successfully display with the changes to thead:
.
.
.
def headerMaps = [
'u_change_record.number': 'Number',
'u_change_record.state' : 'State',
'u_change_record.short_description' : 'Short Description'
]
xml.table(class:'aui'){
thead {
tr{
output.result[0].keySet().each{
th headerMaps[it] ?: it.split(/\./)[1]
}
}
}
.
.
.
...as for the url embedding, however, that still doesn't work :(
I went with using the loop and edited the tbody block as follows:
tbody{
output.result.each{ res->
tr{
res.values().each{
if(it=='number'){
td {
def number = res['u_change_record.number']
a(href:"https://test.service-now.com/cm?id=cm_stdnew&table=change_request&view=sp&number=$number",target:'_blank') number
}
} else {
td it
}
}
}
}
}
And here's how the table looks now with the changes in place:
The headers successfully changed. But the "Number" values are still plain and the urls didn't get embedded. It's nothing to do with the url itself because I even tried testing with the link to Google, and that didn't get embedded either.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Sorry my mistake...
Try this
tbody{
output.result.each{ res->
tr{
res.values().eachWithIndex{val, idx->
def colHeader= res.keySet()[idx]
if(colHeader=='u_change_record.number'){
td {
a(href:"https://test.service-now.com/cm?id=cm_stdnew&table=change_request&view=sp&number=$val",target:'_blank') {
mkp.yield val
}
}
} else {
td it
}
}
}
}
}
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Thanks!
That seems to have solved the problem with the url embedding...but there's a new problem now. The values for State and Short Description don't appear now.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Bit of a transcription error ... change "td it" in the else block to "td val"
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Ah, I think I got it! All I had to change was at the end of the condition to td val:
tbody{
output.result.each{ res->
tr{
res.values().eachWithIndex{val, idx->
def colHeader= res.keySet()[idx]
if(colHeader=='u_change_record.number'){
td {
a(href:"https://test.service-now.com/cm?id=cm_stdnew&table=change_request&view=sp&number=$val",target:'_blank') {
mkp.yield val
}
}
} else {
td val
}
}
}
}
}
Let me know if this was the right way to correct the code.
But with that, I think I now have my final expected result:
Once again, thanks for all the help!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Can you share your final scriptrunner rest endpoint and sample output?
I would like to test this scenario.Thanks
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
We are working to make the same kind of script in 2023 and are trying to follow along because we would also like to have hyperlinks, but instead of having a status, we are looking to just have the project number as a hyperlink and the short description. We were first looking through the initial script and trying to replace the status with sys_id since our API call we had includes the sys_id, but we are running into all kinds of errors with Jira 9.6 and scriptrunner 8.9.0
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.