Just a heads up: On March 24, 2025, starting at 4:30pm CDT / 19:30 UTC, the site will be undergoing scheduled maintenance for a few hours. During this time, the site might be unavailable for a short while. Thanks for your patience.

×
Create
cancel
Showing results for 
Search instead for 
Did you mean: 
Sign up Log in

ScriptRunner listener: Load checklist template

Reno February 28, 2022

Hello,

I use this Checklists Plugin and I am setting up a listener as they describe here to update the checklist based on the value of another attribute.

The updateValue(CustomField, Issue, Collection<ChecklistItem>) method needs a collection of items to load, and in the proposed solution that collection is built within the script.

I have created templates in the custom field and I am wondering if it would be possible to load them directly instead of building the item collection.

Do any of you know how? Any other proposal?

Thank you in advance!

1 answer

1 accepted

2 votes
Answer accepted
Maxime Lefebvre _Okapya_
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.
February 28, 2022

Hi Reno,

We have not yet made the templates API public, so at the moment there is no documentation on how to use a template within scripts.

The current ways we have made templates useable in your processes are by:

- Using the template as "Default Local Items"

- Using the template in a workflow post function



This said, if your use-case is more specific and requires scripting, I can definitely help you with that! Just keep in mind that our APIs are not public so they can change in any update.

Importing a template essentially requires you to load the template, convert the template items into checklist items, and update the checklist with those items.

Here's a modified version of our documentation that does exactly that. The main difference with the default documentation is the `createItemsFromTemplate` function.

import com.onresolve.scriptrunner.runner.customisers.WithPlugin;
import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.issue.MutableIssue;
@WithPlugin("com.okapya.jira.checklist")
import com.okapya.jira.customfields.*;

import java.util.stream.Collectors;
import com.okapya.jira.customfields.configuration.*;
import org.codehaus.jackson.type.TypeReference;

def Collection<ChecklistItem> createItemsFromTemplate(ChecklistCFType cfType, int templateId) {
TemplatesManager templatesManager = cfType.templatesManager;
Template template = templatesManager.getTemplate(templateId);
return ChecklistItem.mapper.readValue(template.getItems().toJson(), new TypeReference<ArrayList<ChecklistItem>>() {});
}

// Retrieve the Custom Field Type for the Checklist Custom Field
def customFieldManager = ComponentAccessor.getCustomFieldManager();
def checklistCustomField = customFieldManager.getCustomFieldObject("customfield_10203");
def checklistCustomFieldType = (ChecklistCFType) checklistCustomField.getCustomFieldType();

// Create a new checklist
def Collection<ChecklistItem> newChecklistValue = createItemsFromTemplate(checklistCustomFieldType, 29);

// Update the issue with the new checklist
def issue = (MutableIssue) event.issue;
checklistCustomFieldType.updateValue(checklistCustomField, issue, newChecklistValue);

The sample script has hard-coded the ID of the template (29). In order to know the ID of the desired template in you system, I suggest you to edit the template in your browser with the developer console open (F12), and retrieve the ID from the network tab.



We will be looking in the future to add an friendlier API to use templates in scripts, and also to find the template's ID.

I hope this helps! Don't hesitate to ask if you have any additional questions.

Kind regards
Max

Reno February 28, 2022

Hello Max,

Thank you for the answer, it is what I was looking for!

I tried your code for my listener (modifying the IDs) but the execution is failing. I am using Checklists v5.2.4. Should it work in that version?

Maxime Lefebvre _Okapya_
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.
March 1, 2022

Hi Reno,

I believe it should work in that version.

Can you provide information about the failing execution? I will try to help debug your issue.

Regards

Reno March 1, 2022

Hi Max,

I am quite new with ScriptRunner and I am not yet able to get logs and debug what's happening. If you can suggest something specific I can try :)

And thank you again!

Maxime Lefebvre _Okapya_
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.
March 1, 2022

Hey Reno,

You can see logs by clicking on the history column of your listener:

script-log.png

Regards

Reno March 1, 2022

Hello again,

In that window, all I see after executing the script is: 

logs.png

Nothing of help :(

Maxime Lefebvre _Okapya_
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.
March 1, 2022

Hey Reno,

Interesting, here's what we'll do:

- Provide the initial code you had that added items to the checklist based on another field. I will modify it to work.

- Which events are you linked to? I would expect "Issue Updated" and "Issue Created".

Regards

Reno March 1, 2022

Hey Max,

This is the listener, linked to the "Issue Updated" and "Issue Created" events:

import com.onresolve.scriptrunner.runner.customisers.WithPlugin;
import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.issue.MutableIssue;
@WithPlugin("com.okapya.jira.checklist")
import com.okapya.jira.customfields.*;
import java.util.stream.Collectors;
import com.okapya.jira.customfields.configuration.*;
import org.codehaus.jackson.type.TypeReference;

def Collection<ChecklistItem> createItemsFromTemplate(ChecklistCFType cfType, int templateId) {
    TemplatesManager templatesManager = cfType.templatesManager;
    Template template = templatesManager.getTemplate(templateId);
    return ChecklistItem.mapper.readValue(template.getItems().toJson(), new TypeReference<ArrayList<ChecklistItem>>() {});
}

// Retrieve the Custom Field Type for the Checklist Custom Field
def customFieldManager = ComponentAccessor.getCustomFieldManager();
def checklistCustomField = customFieldManager.getCustomFieldObject("customfield_11309");
def checklistCustomFieldType = (ChecklistCFType) checklistCustomField.getCustomFieldType();

// Create a new checklist
def Collection<ChecklistItem> newChecklistValue = createItemsFromTemplate(checklistCustomFieldType, 29);

// Update the issue with the new checklist
def issue = (MutableIssue) event.issue;
checklistCustomFieldType.updateValue(checklistCustomField, issue, newChecklistValue);

And this is how I got the ID for the template, as you described:

template_edit.png

Just to mention, in my final code I will have a switch like in the original article.

Thank you so much for your help.

Maxime Lefebvre _Okapya_
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.
March 1, 2022

Hi Reno,

It appears that the code only works on our latest version (6.0.0) after all. There's some bizzare typing conflicts with Jackson's "TypeReference" and ScriptRunner.

I've created a different version of the code that works on any version:

import com.onresolve.scriptrunner.runner.customisers.WithPlugin;
import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.issue.MutableIssue;
@WithPlugin("com.okapya.jira.checklist")
import com.okapya.jira.customfields.*;
import java.util.stream.Collectors;
import com.okapya.jira.customfields.configuration.*;

def Collection<ChecklistItem> createItemsFromTemplate(ChecklistCFType cfType, int templateId) {
TemplatesManager templatesManager = cfType.templatesManager;
Template template = templatesManager.getTemplate(templateId);

ArrayList<ChecklistItem> items = new ArrayList<ChecklistItem>();
for (def templateItem in template.getItems()) {
String templateItemJson = ChecklistItem.mapper.writeValueAsString(templateItem);
items.add(ChecklistItem.mapper.readValue(templateItemJson, ChecklistItem.class));
}
return items;
}

// Retrieve the Custom Field Type for the Checklist Custom Field
def customFieldManager = ComponentAccessor.getCustomFieldManager();
def checklistCustomField = customFieldManager.getCustomFieldObject("customfield_10203");
def checklistCustomFieldType = (ChecklistCFType) checklistCustomField.getCustomFieldType();

// Create a new checklist
def Collection<ChecklistItem> newChecklistValue = createItemsFromTemplate(checklistCustomFieldType, 29);

// Update the issue with the new checklist
def issue = (MutableIssue) event.issue;
checklistCustomFieldType.updateValue(checklistCustomField, issue, newChecklistValue);

Also, as a side note: Since you want to change the Checklist value when another field changes, you should take a look at this example to verify if the other field has actually changed before updating the checklist. Otherwise, with our documentation alone, you will always end up overwriting the checklist value on every issue update.

(I will create an internal issue to update our documentation so it better represents this use-case)

Regards

Reno March 1, 2022

Hi Max,

Thank you for the solution! I tried it and it works, I'll keep in mind what you said about this not being part of the public API and the versions (we may update the plugin soon).

About your side note, yes I noticed, what I added is this:

import com.atlassian.jira.event.type.EventType

if(event.eventTypeId == EventType.ISSUE_UPDATED_ID){
    def changeItems = ComponentAccessor.changeHistoryManager.getChangeHistoryById(event.changeLog.id as Long).changeItemBeans
    if (!changeItems.any { it.field == 'Area' } && !changeItems.any { it.field == 'Work Product Type' }) {
        // Skip this listener if the Area and Work Product Type fields were not changed
        return
    }
}
The "Area" and "Work Product Type" fields are the ones I use to switch between cases for each template. 
Thank you for internally taking care of the documentation.
Have a nice day!
Reno
Maxime Lefebvre _Okapya_
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.
March 1, 2022 edited

Hi Reno,

This is good to hear!

I've created tasks in our backlog to improve documentation and also add public APIs for manipulating templates.

EDIT: Here's a method you can use that would replace the bottom part of the "createItemsFromTemplate" method.

com.okapya.jira.customfields.ChecklistSerializer.deserializeChecklist(template.getItemsJson())

Have a nice day too!
Max

Like 2 people like this
Julien ARMINJON
I'm New Here
I'm New Here
Those new to the Atlassian Community have posted less than three times. Give them a warm welcome!
July 22, 2022

Hello,

 

If you have an update about the groovy templates management API implementation, we're waiting about it :)

 

If found the following method signature, but i do not know the parameters names that must be called:

com.okapya.jira.customfields.configuration.TemplatesManager.getTemplates(java.lang.Integer, java.lang.String, java.lang.Long, java.lang.Long, java.lang.Long)

Maxime Lefebvre _Okapya_
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.
July 22, 2022

Hi Julien,

We have since created a sample in our documentation for how to import a template in a checklist:

https://okapya.atlassian.net/wiki/spaces/CHKDOC5/pages/3198321584/Importing+a+template+in+a+checklist

You should use getTemplate(integer) to get a single template by ID. The other method is for retrieving a list of template from multiple filters.

Kind regards

Suggest an answer

Log in or Sign up to answer
TAGS
atlassian, ace, atlassian community event, donation, girls who code, women in tech, malala fund, plan international, kudos, community badge, badge, atlassian badge, International Women’s month, International Women’s Day, women's month, women's day

10 for Change at Atlassian Community Events

Show up and give back by attending an Atlassian Community Event: we’ll donate $10 for every event attendee in March!

Join an Atlassian Community Event!
AUG Leaders

Upcoming Jira Events