Dynamic Forms
Use the Dynamic Forms feature to simplify the process of adding variables to your ScriptRunner Groovy scripts. Dynamic Forms allows you to create complex scripts with flexible variables that can be shared with multiple users, allowing one script to be used for various use cases.
Inline scripts are often copied and pasted, with minor changes made for different use cases. This approach requires maintenance for each usage of the script. Using Dynamic Forms, create flexible scripts with annotated variables that can be stored as files, reducing maintenance requirements while allowing for script customization.
Annotate your variables to have them appear as form fields when a user edits a script. These annotations allow variable values within a script to be changed easily by those with limited code familiarity.
Dynamic forms annotations are available anywhere you can enter code in ScriptRunner, including the Script Console, Conditions, Validators, Post Functions, Behaviours, and many more.
For example, as a power user, you have created a script to delete issues within a project with a specific assignee. This script is used across multiple locations, varying by one variable (User) for each use case. Instead of hardcoding the User variable, you can now use a dynamic form annotation, meaning the user can be changed without needing to re-write the script. As well as being able to edit the script quickly, you can maintain the code in one centralized location. The dynamic form annotation shows the User variable as a form field:
The above example uses the following code:
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.search.SearchProvider
import com.atlassian.jira.jql.parser.JqlQueryParser
import com.atlassian.jira.user.ApplicationUser
import com.atlassian.jira.web.bean.PagerFilter
import com.onresolve.scriptrunner.parameters.annotation.UserPicker
@UserPicker(label = "Assignee", description = "Issues with this assignee will be permanently deleted")
ApplicationUser user
// issues returned from that JQL will get deleted
final String searchQuery = "assignee = $user.name"
def jqlQueryParser = ComponentAccessor.getComponent(JqlQueryParser)
def searchProvider = ComponentAccessor.getComponent(SearchProvider)
def loggedInUser = ComponentAccessor.jiraAuthenticationContext.loggedInUser
def issueService = ComponentAccessor.issueService
def query = jqlQueryParser.parseQuery(searchQuery)
def searchResults = searchProvider.search(query, loggedInUser, PagerFilter.unlimitedFilter)
searchResults.getIssues().each { issue ->
def deleteValidationResult = issueService.validateDelete(loggedInUser, issue.id)
assert deleteValidationResult.isValid(): deleteValidationResult.errorCollection
def deleteResult = issueService.delete(loggedInUser, deleteValidationResult)
assert deleteResult
}
The following dynamic form field types are available:
Name | Description | Target Type |
---|---|---|
User Picker | Field allowing user selection. | |
Field Picker | Field to select any system or custom field. | |
Short Text | Field allowing a short text input. | String |
Number | Field allowing an integer | Integer |
Select List | Single-select list field. | String |
Checkbox | A checkbox field. | Boolean |
Project Picker | Field allowing project selection. | |
Priority Picker | Field allowing priority selection. | com.atlassian.jira.issue.priority.Priority |
Issue Type Picker | Field allowing issue type selection. | com.atlassian.jira.issue.issuetype.IssueType |
Issue Link Type Picker | Field allowing issue link type selection. | com.atlassian.jira.issue.link.IssueLinkType |
Project Role Picker | Field allowing project role selection. | com.atlassian.jira.security.roles.ProjectRole |
Group Picker | Field allowing group selection. | com.atlassian.crowd.embedded.api.Group |
Saved Filter Picker | Field allowing saved filter selection. | com.atlassian.jira.issue.search.SearchRequest |
Issue Status Picker | Field allowing status selection. | com.atlassian.jira.issue.status.Status |
We are in the process of adding more dynamic form field types.
Create a Dynamic Form
Navigate to ScriptRunner.
Select Console.
Write your new script in the Script field, annotating the variables you want users to provide (see the Examples section below). Annotating variables allows them to be edited depending on requirements when running the script. These variables show as editable fields above the Script Console.
Transforming an Existing Inline Script
To enable sharing of annotated scripts, all inline scripts must be saved as files.
Navigate to your existing inline script, and add in required annotations.
Copy the script.
Use the Script Editor to open your Scripts Root folder.
Select the folder in which you want to save the script, and click the Create New File icon.
Enter a file name in the Add New Groovy File/Add New Groovy Folder window.
Click Add.
Paste your inline script into the file, and click Save. This script is now available as a file and can be shared with multiple Jira users on the same instance.
Annotations
User Picker
Add a user picker field into your script.
import com.atlassian.jira.user.ApplicationUser
import com.onresolve.scriptrunner.parameters.annotation.*
@UserPicker(label = "User", description = "Select a user")
ApplicationUser user
User multi-pickers are also supported.
import com.atlassian.jira.user.ApplicationUser
import com.onresolve.scriptrunner.parameters.annotation.*
@UserPicker(label = "Users", description = "Select users", multiple = true)
List<ApplicationUser> users
Field Picker
Add a field picker into your script. The field picker lets you pick from any fields (system or custom).
import com.atlassian.jira.issue.fields.Field
import com.onresolve.scriptrunner.parameters.annotation.*
@FieldPicker(label = "Field", description = "Select a field")
Field field
Field multi-pickers are also supported.
import com.atlassian.jira.issue.fields.Field
import com.onresolve.scriptrunner.parameters.annotation.*
@FieldPicker(label = "Fields", description = "Select fields", multiple = true)
List<Field> fields
Short Text
Add a short text field to a script.
import com.onresolve.scriptrunner.parameters.annotation.*
@ShortTextInput(label = "Summary", description = "Enter a short issue summary")
String issueSummaryTextInput
Number
Add a number field to a script.
import com.onresolve.scriptrunner.parameters.annotation.NumberInput
@NumberInput(label = 'Number of Approvals', description = 'How many approvals should be required')
Integer requiredApprovals
Select List
Add a single-select list with configurable options.
import com.onresolve.scriptrunner.parameters.annotation.*
import com.onresolve.scriptrunner.parameters.annotation.meta.*
@Select(
label = "Color",
description = "Select color",
options = [
@Option(label = "Green", value = "green"),
@Option(label = "Blue", value = "blue"),
]
)
String value
Multi-select lists are also supported.
import com.onresolve.scriptrunner.parameters.annotation.*
import com.onresolve.scriptrunner.parameters.annotation.meta.*
@Select(
label = "Colors",
description = "Select colors",
options = [
@Option(label = "Green", value = "green"),
@Option(label = "Blue", value = "blue"),
@Option(label = "Red", value = "red"),
],
multiple = true
)
List<String> values
Checkbox
Add a checkbox to a script.
import com.onresolve.scriptrunner.parameters.annotation.*
@Checkbox(label = "Clone project", description = "Select the checkbox to clone project")
Boolean projectShouldBeCloned
Project Picker
Add a project picker to a script.
import com.atlassian.jira.project.Project
import com.onresolve.scriptrunner.parameters.annotation.ProjectPicker
@ProjectPicker(
label = 'Project', description = 'Pick a project', placeholder = 'Pick a project', includeArchived = false
)
Project project
Project multi-pickers are also supported.
import com.atlassian.jira.project.Project
import com.onresolve.scriptrunner.parameters.annotation.ProjectPicker
@ProjectPicker(
label = 'Projects', description = 'Pick projects', placeholder = 'Pick projects', includeArchived = false,
multiple = true
)
List<Project> projects
Priority Picker
Add a priority picker to a script.
import com.atlassian.jira.issue.priority.Priority
import com.onresolve.scriptrunner.parameters.annotation.PriorityPicker
@PriorityPicker(label = 'Priority', description = 'Pick a priority', placeholder = 'Pick a priority')
Priority priority
Priority multi-pickers are also supported.
import com.atlassian.jira.issue.priority.Priority
import com.onresolve.scriptrunner.parameters.annotation.PriorityPicker
@PriorityPicker(
label = 'Priorities', description = 'Pick priorities', placeholder = 'Pick priorities', multiple = true
)
List<Priority> priorities
Issue Type Picker
Add an issue type picker to a script.
import com.atlassian.jira.issue.issuetype.IssueType
import com.onresolve.scriptrunner.parameters.annotation.IssueTypePicker
@IssueTypePicker(label = 'Issue type', description = 'Pick an issue type', placeholder = 'Select issue type')
IssueType issueType
Issue type multi-pickers are also supported.
import com.atlassian.jira.issue.issuetype.IssueType
import com.onresolve.scriptrunner.parameters.annotation.IssueTypePicker
@IssueTypePicker(
label = 'Issue type', description = 'Pick issue types', placeholder = 'Select issue types',
multiple = true
)
List<IssueType> issueTypes
Issue Link Type Picker
Add an issue link type picker to a script.
import com.atlassian.jira.issue.link.IssueLinkType
import com.onresolve.scriptrunner.parameters.annotation.IssueLinkTypePicker
@IssueLinkTypePicker(label = 'Issue link type', description = 'Pick an issue link type', placeholder = 'Pick an issue link type')
IssueLinkType issueLinkType
Issue link type multi-pickers are also supported.
import com.atlassian.jira.issue.link.IssueLinkType
import com.onresolve.scriptrunner.parameters.annotation.IssueLinkTypePicker
@IssueLinkTypePicker(
label = 'Issue link types', description = 'Pick issue link types', placeholder = 'Pick issue link types',
multiple = true
)
List<IssueLinkType> issueLinkTypes
Project Role Picker
Add a project role picker to a script.
import com.atlassian.jira.security.roles.ProjectRole
import com.onresolve.scriptrunner.parameters.annotation.ProjectRolePicker
@ProjectRolePicker(label = 'Project role', description = 'Project role picker')
ProjectRole projectRole
Project role multi pickers are also supported.
import com.atlassian.jira.security.roles.ProjectRole
import com.onresolve.scriptrunner.parameters.annotation.ProjectRolePicker
@ProjectRolePicker(label = 'Project roles', description = 'Project role picker', multiple = true)
List<ProjectRole> projectRoles
Group Picker
Add a group Picker to a script.
import com.atlassian.crowd.embedded.api.Group
import com.onresolve.scriptrunner.parameters.annotation.GroupPicker
@GroupPicker(label = 'Group', description = 'Pick a group', placeholder = 'Pick a group')
Group group
Group multi-pickers are also supported.
import com.atlassian.crowd.embedded.api.Group
import com.onresolve.scriptrunner.parameters.annotation.GroupPicker
@GroupPicker(label = 'Groups', description = 'Pick groups', placeholder = 'Pick groups', multiple = true)
List<Group> groups
Saved Filter Picker
Add a saved filter to a script.
import com.atlassian.jira.issue.search.SearchRequest
import com.onresolve.scriptrunner.parameters.annotation.SavedFilterPicker
@SavedFilterPicker(label = "Saved Filter", description = "Pick a saved filter", placeholder = "Pick a saved filter")
SearchRequest searchRequest
Saved filter multi-pickers are also supported.
import com.atlassian.jira.issue.search.SearchRequest
import com.onresolve.scriptrunner.parameters.annotation.SavedFilterPicker
@SavedFilterPicker(
label = "Saved Filters", description = "Pick saved filters", placeholder = "Pick saved filters",
multiple = true
)
List<SearchRequest> searchRequests
Issue Status Picker
Add a status to a script.
import com.atlassian.jira.issue.status.Status
import com.onresolve.scriptrunner.parameters.annotation.IssueStatusPicker
@IssueStatusPicker(label = 'Status', description = 'Pick a status', placeholder = 'Pick a status')
Status status
Issue status multi pickers are also supported.
import com.atlassian.jira.issue.status.Status
import com.onresolve.scriptrunner.parameters.annotation.IssueStatusPicker
@IssueStatusPicker(
label = 'Statuses', description = 'Pick statuses', placeholder = 'Pick statuses', multiple = true
)
List<Status> statuses
Custom Field Picker
Add a custom field picker to a script.
import com.atlassian.jira.issue.fields.CustomField
import com.onresolve.scriptrunner.parameters.annotation.CustomFieldPicker
@CustomFieldPicker(label = 'Custom Field', description = 'Pick a custom field', placeholder='Select custom field')
CustomField customField
Custom field multi-pickers are also supported.
import com.atlassian.jira.issue.fields.CustomField
import com.onresolve.scriptrunner.parameters.annotation.CustomFieldPicker
@CustomFieldPicker(
label = 'Custom Fields', description = 'Pick custom fields', placeholder='Select custom fields',
multiple = true
)
List<CustomField> customFields
Resolution Picker
Add a resolution to a script.
import com.atlassian.jira.issue.resolution.Resolution
import com.onresolve.scriptrunner.parameters.annotation.ResolutionPicker
@ResolutionPicker(label = 'Resolution', description = 'Pick a resolution', placeholder = 'Pick a resolution')
Resolution resolution
Resolution multi-pickers are also supported.
import com.atlassian.jira.issue.resolution.Resolution
import com.onresolve.scriptrunner.parameters.annotation.ResolutionPicker
@ResolutionPicker(
label = 'Resolutions', description = 'Pick resolutions', placeholder = 'Pick resolutions',
multiple = true
)
List<Resolution> resolutions
Version Picker
Add a version to a script.
import com.atlassian.jira.project.version.Version
import com.onresolve.scriptrunner.parameters.annotation.VersionPicker
@VersionPicker(
label = 'Version', description = 'Pick a version',
projectPlaceholder = 'Pick a project', placeholder = 'Pick a version'
)
Version version
Version multi-pickers are also supported.
import com.atlassian.jira.project.version.Version
import com.onresolve.scriptrunner.parameters.annotation.VersionPicker
@VersionPicker(
label = 'Versions', description = 'Pick versions',
projectPlaceholder = 'Pick a project', placeholder = 'Pick versions', multiple = true
)
List<Version> versions
Component Picker
Add a component to a script.
import com.atlassian.jira.bc.project.component.ProjectComponent
import com.onresolve.scriptrunner.parameters.annotation.ComponentPicker
@ComponentPicker(
label = 'Component', description = 'Pick a component',
projectPlaceholder = 'Pick a project', placeholder = 'Pick a component'
)
ProjectComponent component
Component multi-pickers are also supported.
import com.atlassian.jira.bc.project.component.ProjectComponent
import com.onresolve.scriptrunner.parameters.annotation.ComponentPicker
@ComponentPicker(
label = 'Components', description = 'Pick components',
projectPlaceholder = 'Pick a project', placeholder = 'Pick components', multiple = true
)
List<ProjectComponent> components