Sub-task Default Field
You can use Behaviors to automatically populate sub-task fields with data from the parent issue when creating new sub-tasks.
You can get the parent issue ID via the parentIssueId
form field. Once you have that you can load that issue, get the fields, and set them in the Create Issue dialog.
Setting sub-task fields from the parent issue
You can use the following example to do the following:
- Copy the parent issue summary to the sub-task summary field.
- Copy common system field values to the sub-task and copy custom field values to the sub-task.
- From ScriptRunner, navigate to Behaviours.
- Select Create Behaviour.
- Enter a name for the behaviour.
- Optional: Enter a description for the behaviour.
- Select Create Mapping.
- Select the project and issue type(s) to map this behaviour to.
- Select Add Mapping to confirm the mapping.
- Select Create to create the behaviour.
You're taken to the Edit Behaviour screen where you can configure the behaviour further. Scroll to the Initialiser field and select Create Script.
Use one of the following example scripts, depending on what field defaults you want to set:
You can select Example scripts in the code editor for further examples.
- Copy the parent issue's summary to the sub-task summary field.
import com.atlassian.jira.component.ComponentAccessor import com.onresolve.jira.groovy.user.FieldBehaviours import groovy.transform.BaseScript import static com.atlassian.jira.issue.IssueFieldConstants.SUMMARY @BaseScript FieldBehaviours fieldBehaviours def parent = getFieldById("parentIssueId") def parentIssueId = parent.getFormValue() as Long def summary = getFieldById(SUMMARY) if (!parentIssueId || underlyingIssue) { // this is not a subtask, or issue already exists, so don't set default values return } def issueManager = ComponentAccessor.getIssueManager() def parentIssue = issueManager.getIssueObject(parentIssueId) summary.setFormValue(parentIssue.summary)
- Copy common system field values to the sub-task and copy custom field values to the sub-task.
This sample code demonstrates copying all fields from the parent to the new sub-task. In practice, you will edit this example and select the system and custom fields you need.
import com.atlassian.jira.component.ComponentAccessor import com.atlassian.jira.datetime.DateTimeFormatterFactory import com.atlassian.jira.datetime.DateTimeStyle import com.atlassian.jira.issue.customfields.option.Option import com.atlassian.jira.issue.fields.CustomField import com.onresolve.jira.groovy.user.FieldBehaviours import groovy.transform.BaseScript import java.sql.Timestamp import static com.atlassian.jira.issue.IssueFieldConstants.AFFECTED_VERSIONS import static com.atlassian.jira.issue.IssueFieldConstants.ASSIGNEE import static com.atlassian.jira.issue.IssueFieldConstants.COMPONENTS import static com.atlassian.jira.issue.IssueFieldConstants.DESCRIPTION import static com.atlassian.jira.issue.IssueFieldConstants.DUE_DATE import static com.atlassian.jira.issue.IssueFieldConstants.ENVIRONMENT import static com.atlassian.jira.issue.IssueFieldConstants.FIX_FOR_VERSIONS import static com.atlassian.jira.issue.IssueFieldConstants.LABELS import static com.atlassian.jira.issue.IssueFieldConstants.PRIORITY import static com.atlassian.jira.issue.IssueFieldConstants.SUMMARY @BaseScript FieldBehaviours fieldBehaviours def parent = getFieldById("parentIssueId") def parentIssueId = parent.getFormValue() as Long if (!parentIssueId || underlyingIssue) { // this is not a subtask, or issue already exists, so don't set default values return } def issueManager = ComponentAccessor.getIssueManager() def parentIssue = issueManager.getIssueObject(parentIssueId) def customFieldManager = ComponentAccessor.getCustomFieldManager() // REMOVE OR MODIFY THE SETTING OF THESE FIELDS AS NECESSARY getFieldById(SUMMARY).setFormValue(parentIssue.summary) getFieldById(PRIORITY).setFormValue(parentIssue.priority.id) def dateTimeFormatterFactory = ComponentAccessor.getComponent(DateTimeFormatterFactory) def defaultLocaleFormatter = dateTimeFormatterFactory.formatter().withStyle(DateTimeStyle.DATE).withDefaultLocale() getFieldById(DUE_DATE).setFormValue(defaultLocaleFormatter.format(parentIssue.getDueDate())) getFieldById(COMPONENTS).setFormValue(parentIssue.components*.id) getFieldById(AFFECTED_VERSIONS).setFormValue(parentIssue.affectedVersions*.id) getFieldById(FIX_FOR_VERSIONS).setFormValue(parentIssue.fixVersions*.id) getFieldById(ASSIGNEE).setFormValue(parentIssue.assignee?.name) getFieldById(ENVIRONMENT).setFormValue(parentIssue.environment) getFieldById(DESCRIPTION).setFormValue(parentIssue.description) getFieldById(LABELS).setFormValue(parentIssue.labels*.label) // IF YOU DON'T WANT CUSTOM FIELDS COPIED REMOVE EVERYTHING BELOW HERE // IF YOU ONLY WANT SOME FIELDS INHERITED ADD THEM TO THE LIST BELOW, OR LEAVE EMPTY FOR ALL // eg ['Name of first custom field', 'Name of second custom field'] List copyCustomFields = [] List<CustomField> parentFields = customFieldManager.getCustomFieldObjects(parentIssue) parentFields.each { cf -> if (copyCustomFields && !copyCustomFields.contains(cf.name)) { return } def parentValue = cf.getValue(parentIssue) if (!parentValue) { return } if (parentValue instanceof Timestamp) { getFieldById(cf.id).setFormValue(defaultLocaleFormatter.format(parentValue)) } else if (parentValue instanceof Option) { getFieldById(cf.id).setFormValue(parentValue.optionId) } else if (parentValue instanceof List<Option>) { parentValue = parentValue as List<Option> //This cast is just to placate the static type checker getFieldById(cf.id).setFormValue(parentValue.collect { it.optionId }) } else { getFieldById(cf.id).setFormValue(parentValue) } }
- Copy the parent issue's summary to the sub-task summary field.
Select Save Changes.
You can now test your behaviour works by creating a sub-task and checking the chosen fields are set.