### Custom Post Function Example (Groovy) Source: https://docs.adaptavist.com/sr4js/8.x/features/workflows/post-functions/custom-post-functions Demonstrates updating an issue's description using a custom post function script. This example highlights the importance of placing updates before saving and reindexing the issue. ```Groovy issue.setDescription("A new description") ``` -------------------------------- ### Get count of projects using DatabaseUtil in Groovy Source: https://docs.adaptavist.com/sr4js/8.x/features/resources/database-connection This example shows how to retrieve the number of projects by executing a count query. The withSql method returns the value returned by the closure. It uses a database connection named 'local' and assumes the existence of a 'project' table. ```Groovy import com.onresolve.scriptrunner.db.DatabaseUtil def nProjects = DatabaseUtil.withSql('local') { sql -> sql.firstRow('select count(*) from project')[0] } ``` -------------------------------- ### startDate Source: https://docs.adaptavist.com/sr4js/8.x/features/jql-functions/included-jql-functions/versions Finds issues by the start date of the associated version. Allows querying based on date ranges. ```APIDOC ## startDate ### Description Finds issues by the start date of the associated version (_fix versions_, _affects versions_, version custom fields). ### Method Query ### Endpoint N/A ### Parameters #### Path Parameters - N/A #### Query Parameters - N/A #### Request Body - N/A ### Request Example { "example": "fixVersion in startDate(\"after 14d\")" } ### Response #### Success Response (200) - N/A #### Response Example { "example": "" } ``` -------------------------------- ### JQL aggregateExpression Examples for Summary Data Source: https://docs.adaptavist.com/sr4js/8.x/features/jql-functions/included-jql-functions/calculations A collection of JQL examples using the aggregateExpression function to derive various summary data points from issues. These include total time spent, average estimates, work ratios, issue counts by reporter, and custom calculations. ```JQL project = "Test" AND issueFunction in aggregateExpression("Total Time Spent", "timespent.sum()") ``` ```JQL project = "Test" AND issueFunction in aggregateExpression("Average Original Estimate", "originalestimate.average()") ``` ```JQL project = "Test" AND issueFunction in aggregateExpression("Average Work Ratio", "workratio.average()") // Note: Will display as a decimal (e.g. 0.12 rather than 12%) ``` ```JQL project = "Test" AND issueFunction in aggregateExpression("Total Remaining Estimate", "remainingEstimate.sum()") ``` ```JQL project = "Test" AND issueFunction in aggregateExpression("Tracking Error", "(originalEstimate.sum() - timeSpent.sum()) / remainingEstimate.sum()") ``` ```JQL project = "Test" AND issueFunction in aggregateExpression("Issues by jbloggs", "reporter.count('jbloggs')") ``` ```JQL project = "Test" AND issueFunction in aggregateExpression("Reporter Breakdown", "reporter.countBy{it}") // Note: Better to use a pie chart for this data. ``` -------------------------------- ### Jira Condition Script Example Source: https://docs.adaptavist.com/sr4js/8.x/features/fragments/web-item This showcases a Jira condition script example to determine if a menu item should be displayed based on whether the issue has an 'approved' label. It demonstrates accessing issue properties using the `issue` context variable and checking for the existence of labels. Requires JiraHelper object. ```groovy (! ("approved" in issue.labels*.label)) ``` -------------------------------- ### Add Label and Redirect (Groovy) Source: https://docs.adaptavist.com/sr4js/8.x/features/fragments/web-item This example adds a label to an issue and redirects the user to the issue's browse page. It uses the LabelManager component to add a label and ApplicationProperties to construct the redirect URL. The script uses a GET request with an issueId parameter. ```Groovy import com.atlassian.jira.component.ComponentAccessor import com.atlassian.jira.issue.label.LabelManager import com.atlassian.sal.api.ApplicationProperties import com.atlassian.sal.api.UrlMode import com.onresolve.scriptrunner.runner.ScriptRunnerImpl import com.onresolve.scriptrunner.runner.rest.common.CustomEndpointDelegate import com.onresolve.scriptrunner.runner.util.UserMessageUtil import groovy.transform.BaseScript import javax.ws.rs.core.MultivaluedMap import javax.ws.rs.core.Response @BaseScript CustomEndpointDelegate delegate def labelManager = ComponentAccessor.getComponent(LabelManager) def applicationProperties = ScriptRunnerImpl.getOsgiService(ApplicationProperties) def issueManager = ComponentAccessor.getIssueManager() def user = ComponentAccessor.jiraAuthenticationContext?.loggedInUser labelIssue(httpMethod: "GET") { MultivaluedMap queryParams -> def issueId = queryParams.getFirst("issueId") as Long def issue = issueManager.getIssueObject(issueId) labelManager.addLabel(user, issueId, "approved", false) UserMessageUtil.success("Issue approved") def baseUrl = applicationProperties.getBaseUrl(UrlMode.ABSOLUTE) Response.temporaryRedirect(URI.create("${baseUrl}/browse/${issue.key}")).build() } ``` -------------------------------- ### Find Blocker Issues with ScriptRunner JQL Source: https://docs.adaptavist.com/sr4js/8.x/features/jql-functions/jql-functions-tutorial This example demonstrates how to use the hasLinkType function to find all high priority blocker issues in a specified project. The query combines standard JQL fields with ScriptRunner functions. ```JQL project = GAT AND priority in (Highest, High) AND issueFunction in hasLinkType('Blocks') ``` -------------------------------- ### Optimized config population with early return Source: https://docs.adaptavist.com/sr4js/8.x/features/listeners/built-in-listeners/send-a-custom-email Demonstrates an early‑return pattern to avoid unnecessary processing when a condition is not met, and shows how to bulk‑add expensive configuration variables to the config map using putAll. This improves script performance in the Condition and Configuration editor. ```Groovy def condition = issue.status.name == "Open" && ... if (! condition) return false def expensiveConfigVars = [foo: "bar"] config.putAll(expensiveConfigVars) ``` -------------------------------- ### Configure JVM Arguments for Web Resource Directories Source: https://docs.adaptavist.com/sr4js/8.x/features/fragments/web-resource This snippet shows how to set the JVM system property `plugin.resource.directories` to specify locations for web resources. It allows for multiple comma-separated directories, and the resource loader searches them in order. This is typically done in the `setenv.sh` or `.bat` script. ```shell JVM_REQUIRED_ARGS='-Dplugin.resource.directories=/app/home/scripts -Dother.properties...' ``` -------------------------------- ### Set Field Help Text - User Guidance Source: https://docs.adaptavist.com/sr4js/8.x/features/behaviours/api-quick-reference Adds contextual help text under form fields to guide users during form completion. Particularly useful for explaining mandatory field requirements based on other field selections. Use clearHelpText() or setHelpText("") to remove. Deprecated setHelpText method should be avoided. ```groovy formField.setHelpText("You must enter a value for this field if you select priority Blocker") ``` -------------------------------- ### componentMatch JQL Function Source: https://docs.adaptavist.com/sr4js/8.x/features/jql-functions/included-jql-functions/match-functions Matches component names with regular expressions for issue filtering by component patterns. Applies to any component in the issue. Inputs: regex pattern string. Outputs: components matching the regex, usable in component clauses. Example targets components starting with a prefix like 'Web'. Limitation: performance depends on issue volume. ```JQL component in componentMatch("^Web.*") ``` -------------------------------- ### Table View for Multiple Issues with Permissions (Groovy) Source: https://docs.adaptavist.com/sr4js/8.x/features/script-fields/built-in-script-fields/issue-picker/issue-picker-customizations Renders a table displaying Key, Summary, and Description for multiple issues. It uses the `hasPermission` closure to conditionally display issue details or a 'Permission Denied' message, ensuring user permissions are respected. ```groovy import com.atlassian.jira.issue.Issue import com.onresolve.scriptrunner.canned.util.OutputFormatter renderViewHtml = { List issues, Closure hasPermission, String baseUrl -> OutputFormatter.markupBuilder { table(class: 'aui') { thead { tr { td('Key') td('Summary') td('Description') } } issues.each { issue -> tbody { tr { if (hasPermission(issue)) { td { a(href: "${baseUrl}/browse/${issue.key}", issue.key) } td(issue.summary) td(issue.description) } else { td(colspan: 3, issue.key + ' (Permission Denied)') } } } } } } } ``` -------------------------------- ### Get Changed Field ID - Groovy Source: https://docs.adaptavist.com/sr4js/8.x/features/behaviours/api-quick-reference Gets the ID of the form field to which the current script is attached. This is useful for dynamically referencing the field the script is running on, often used in conjunction with other field operations. ```groovy getFieldById(getFieldChanged()) ``` -------------------------------- ### Expression Function - Work Logged and Time Tracking Examples Source: https://docs.adaptavist.com/sr4js/8.x/features/jql-functions/included-jql-functions/calculations Examples demonstrating how to use the 'expression' function to filter issues based on 'Time Spent', 'Original Estimate', and 'Remaining Estimate', including comparisons with subqueries and time units. ```APIDOC ## expression(Subquery, expression) - Time Tracking Examples ### Description These examples showcase advanced usage of the 'expression' function for analyzing work logs and time tracking data. They cover scenarios like identifying issues where more work was logged than estimated, predicting potential overruns, and filtering by specific time durations. ### Method N/A (This is a function used within JQL or other query languages) ### Endpoint N/A ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Examples #### Example 1: Issues where work logged exceeds original estimate ``` issueFunction in expression("", "timespent > originalestimate") ``` #### Example 2: Issues likely to exceed original estimate ``` issueFunction in expression("", "timespent + remainingestimate > originalestimate") ``` #### Example 3: Issues in progress likely to exceed original estimate ``` issueFunction in expression("resolution = empty", "timespent + remainingestimate > originalestimate") ``` #### Example 4: Issues where work logged exceeded original estimate by more than 5 working days ``` issueFunction in expression("", "timespent > originalestimate + 5*wd") ``` ### Notes on Time Tracking Units - **wd**: Number of milliseconds in a working day (based on Jira Admin settings). - **ww**: Number of days in a working week multiplied by the 'wd' value. - Use `wd` or `ww` for time tracking comparisons, not `d` as in `dateCompare`. ### Response #### Success Response (200) N/A (This is a function, not an endpoint) #### Response Example N/A ``` ```APIDOC ## expression(Subquery, expression) - Comparing Time Tracking with Dates ### Description This section explains how to use the `fromTimeTracking` function within the `expression` function to compare time tracking fields (like remaining estimate) with date fields (like due date). ### Method N/A (This is a function used within JQL or other query languages) ### Endpoint N/A ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example #### Example: Issues that will miss their due date based on remaining estimate ``` issueFunction in expression("resolution is empty", "now() + fromTimeTracking(remainingestimate) > duedate") ``` ### Explanation of `fromTimeTracking` Jira stores estimates in hours internally. For example, 3 days with an 8-hour workday is stored as 24 hours. The `fromTimeTracking` function converts these time tracking values (e.g., remaining estimate) into a format comparable with date fields, ensuring accurate calculations when comparing with 'now()' or 'duedate'. ### Response #### Success Response (200) N/A (This is a function, not an endpoint) #### Response Example N/A ``` -------------------------------- ### Query Issues by Version Start Date Source: https://docs.adaptavist.com/sr4js/8.x/features/jql-functions/included-jql-functions/versions Filters issues based on the start date of their associated versions (fix versions, affects versions, version custom fields). It utilizes date predicates to specify timeframes relative to the current date. ```jql fixVersion in startDate("after 14d") ``` -------------------------------- ### Create REST Endpoint for GitHub Repository Query Source: https://docs.adaptavist.com/sr4js/8.x/features/behaviours/behaviours-examples/select-list-conversions This Groovy script defines a custom REST endpoint using ScriptRunner's CustomEndpointDelegate to proxy GitHub API requests. It queries public repositories by name, sorts by stars, and returns formatted JSON for use in multi-select fields. Dependencies include Groovy libraries like HTTPBuilder and JsonBuilder; inputs are query parameters from the URL, outputs are JSON responses with repository data. Limitations include rate limiting (60 requests per hour without authentication) and only accessing public repos. ```groovy import com.onresolve.scriptrunner.runner.rest.common.CustomEndpointDelegate import groovy.json.JsonBuilder import groovy.json.JsonOutput 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 @BaseScript CustomEndpointDelegate delegate githubRepoQuery(httpMethod: "GET") { MultivaluedMap queryParams -> // <1> def query = queryParams.getFirst("query") as String def rt = [:] if (query) { def httpBuilder = new HTTPBuilder("https://api.github.com") def repos = httpBuilder.request(Method.GET, ContentType.JSON) { uri.path = "/search/repositories" uri.query = [q: "$query in:name", sort: "stars", order: "desc"] headers."User-Agent" = "My JIRA" // <2> response.failure = { resp, reader -> log.warn("Failed to query GitHub API: " + reader.text) return Response.serverError().build() } } rt = [ items : repos["items"].collect { Map repo -> def repoName = repo."full_name" [ value: repoName, html : repoName.replaceAll(/(?i)$query/) { "${it}" } // <3> + "${repo['stargazers_count']} ⭐", label: repoName, icon : repo.owner?."avatar_url", ] }, total : repos["total_count"], footer: "Choose repo... (${repos["items"].size()} of ${repos["total_count"]} shown...)" ] } return Response.ok(new JsonBuilder(rt).toString()).build() } ``` -------------------------------- ### Configure custom fields and helper functions via config map Source: https://docs.adaptavist.com/sr4js/8.x/features/listeners/built-in-listeners/send-a-custom-email Sets up a config map to expose the story points custom field and a capitalization closure for use in email templates. Imports necessary Jira components and returns a boolean to satisfy the condition requirement. This snippet runs in the Condition and Configuration editor. ```Groovy import com.atlassian.gzipfilter.org.apache.commons.lang.StringUtils import com.atlassian.jira.component.ComponentAccessor import com.atlassian.jira.issue.CustomFieldManager def customFieldManager = ComponentAccessor.getComponent(CustomFieldManager) def storyPointsCf = customFieldManager.getCustomFieldObjectByName("TextFieldB") // add value of story points to config map config.storyPoints = issue.getCustomFieldValue(storyPointsCf) // add a closure config.capitalize = { String str -> StringUtils.capitalize(str) } return true ``` -------------------------------- ### Define a GET REST Endpoint in Groovy Source: https://docs.adaptavist.com/sr4js/8.x/features/rest-endpoints This Groovy script defines a custom REST endpoint using ScriptRunner. It specifies the HTTP method (GET), user groups allowed to access it, and returns a JSON response. This allows integration with external systems or use in dashboard gadgets. ```groovy import com.onresolve.scriptrunner.runner.rest.common.CustomEndpointDelegate import groovy.json.JsonBuilder import groovy.transform.BaseScript import javax.ws.rs.core.MultivaluedMap import javax.ws.rs.core.Response @BaseScript CustomEndpointDelegate delegate doSomething( httpMethod: "GET", groups: ["jira-administrators"] ) { MultivaluedMap queryParams, String body -> return Response.ok(new JsonBuilder([abc: 42]).toString()).build() } ``` -------------------------------- ### JQL Query to Find Old Support Issues Source: https://docs.adaptavist.com/sr4js/8.x/features/jobs/built-in-jobs/escalation-services This JQL query identifies support issues that have a status of 'Waiting for Customer' and have not been updated in the last 7 days. It is used to select issues for automated closure. ```groovy status = "Waiting for Customer" AND updated < -7d ``` -------------------------------- ### Get Form Field by ID - Groovy Source: https://docs.adaptavist.com/sr4js/8.x/features/behaviours/api-quick-reference Retrieves a FormField object using its unique ID. This object can then be used to get or set field values, validity, and other properties. It accepts string IDs for custom fields or standard fields like 'summary'. ```groovy getFieldById("customfield_11111") getFieldById("summary") ``` -------------------------------- ### Groovy: Email Template Example using Config Variables Source: https://docs.adaptavist.com/sr4js/8.x/features/listeners/built-in-listeners/send-a-custom-email-non-issue-events This is an example of an email body template written using Groovy's GStringTemplateEngine. It demonstrates how to access variables ('versionName' and 'projectName') that were previously stored in the 'config' map by the listener's condition script. This enables personalized email content. ```groovy Version $config.versionName for project $projectName just released. Congratulations! ``` -------------------------------- ### getResponse() Source: https://docs.adaptavist.com/sr4js/8.x/features/behaviours/api-quick-reference Retrieves the servlet response object for the current request. This method is rarely needed in typical scripting scenarios. ```APIDOC ## getResponse() ### Description Gets the servlet response. There is probably no cause to use this. ### Method getResponse() ### Parameters No parameters. ### Usage Example ```javascript const response = getResponse(); ``` ### Response Returns the servlet response object. ``` -------------------------------- ### REST Endpoint for AUI Dialog2 Source: https://docs.adaptavist.com/sr4js/8.x/features/fragments/web-item This example provides a REST endpoint that returns HTML for an AUI dialog, enabling the display of custom dialogs when a web item is clicked. It illustrates the structure of a basic AUI dialog and demonstrates how to return HTML content using a REST endpoint. ```groovy 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 -> // get a reference to the current page... // def page = getPage(queryParams) def dialog = \ """ " Response.ok().type(MediaType.TEXT_HTML).entity(dialog.toString()).build() } ``` -------------------------------- ### GET /rest/scriptrunner/latest/custom/approve Source: https://docs.adaptavist.com/sr4js/8.x/features/fragments/web-item This endpoint approves an issue. It responds with a success flag indicating the issue has been approved. ```APIDOC ## GET /rest/scriptrunner/latest/custom/approve ### Description This endpoint approves an issue and returns a success flag. ### Method GET ### Endpoint /rest/scriptrunner/latest/custom/approve ### Parameters #### Query Parameters - **issueId** (Long) - Required - The ID of the issue to approve. ### Request Example ``` http:///rest/scriptrunner/latest/custom/approve?issueId=12345 ``` ### Response #### Success Response (200) - **type** (string) - The type of the flag (e.g., 'success'). - **title** (string) - The title of the flag. - **close** (string) - How the flag should close (e.g., 'auto'). - **body** (string) - The main content of the flag message. #### Response Example ```json { "type": "success", "title": "Issue approved", "close": "auto", "body": "This issue has been approved for release" } ``` ``` -------------------------------- ### Using Subqueries with ScriptRunner JQL Functions Source: https://docs.adaptavist.com/sr4js/8.x/features/jql-functions/jql-functions-tutorial Illustrates how to use subqueries within ScriptRunner JQL functions to limit results. The example shows filtering epics by status and priority within the issuesInEpics function. ```JQL issueFunction in issuesInEpics ("status = 'to do' AND priority = 'high'") ``` -------------------------------- ### Configure REST Endpoint to Query Jira Database (Groovy) Source: https://docs.adaptavist.com/sr4js/8.x/features/behaviours/behaviours-examples/select-list-conversions This Groovy script defines a custom REST endpoint that queries the JiraEventType table from the current Jira instance. It establishes a database connection, executes a parameterized SQL query (case-insensitive like), and formats the results for a select input. Dependencies include ScriptRunner's CustomEndpointDelegate and standard Java SQL libraries. It returns a JSON response containing items, total count, and a footer. ```groovy import com.atlassian.jira.component.ComponentAccessor import com.atlassian.jira.config.database.DatabaseConfigurationManager import com.atlassian.jira.config.database.JdbcDatasource import com.onresolve.scriptrunner.runner.rest.common.CustomEndpointDelegate import groovy.json.JsonBuilder import groovy.sql.GroovyRowResult import groovy.sql.Sql import groovy.transform.BaseScript import javax.ws.rs.core.MultivaluedMap import javax.ws.rs.core.Response import java.sql.Driver @BaseScript CustomEndpointDelegate delegate eventTypes(httpMethod: "GET") { MultivaluedMap queryParams -> def query = queryParams.getFirst("query") as String def rt = [] def datasource = ComponentAccessor.getComponent(DatabaseConfigurationManager).getDatabaseConfiguration().getDatasource() as JdbcDatasource def driver = Class.forName(datasource.getDriverClassName()).newInstance() as Driver def props = new Properties() props.setProperty("user", datasource.getUsername()) props.setProperty("password", datasource.getPassword()) def conn = driver.connect(datasource.getJdbcUrl(), props) def sql = new Sql(conn) // <1> try { def rows = sql.rows("select name from jiraeventtype where name ilike ?", ["%${query}%".toString()]) // <2> rt = [ items : rows.collect { GroovyRowResult row -> [ value: row.get("name"), html : row.get("name").replaceAll(/(?i)$query/) { "${it}" }, label: row.get("name"), ] }, total : rows.size(), footer: "Choose event type... " ] } finally { sql.close() conn.close() } return Response.ok(new JsonBuilder(rt).toString()).build() } ``` -------------------------------- ### Adding Tooltip and Icon to Jira Web Item using XML Source: https://docs.adaptavist.com/sr4js/8.x/features/fragments/raw-xml-module-built-in-script This XML snippet demonstrates how to add a tooltip and an icon to a web item in Jira's Browse Projects menu. It defines the web item's key, name, section, label, link, tooltip, and icon with its source link. This allows for richer user interface elements within the Jira navigation. ```xml Show only my spaces /images/sr.png ``` -------------------------------- ### Get Earliest Unreleased Version by Release Date Source: https://docs.adaptavist.com/sr4js/8.x/features/jql-functions/included-jql-functions/versions Retrieves the earliest unreleased version within a project, sorted by its release date. It can optionally include archived versions. ```jql earliestUnreleasedVersionByReleaseDate('JRA', 'true') ``` -------------------------------- ### Require Fix Version if Resolution is Fixed Source: https://docs.adaptavist.com/sr4js/8.x/features/workflows/validators/custom-validators This Groovy script example enforces that a Fix Version must be specified when the Resolution is set to 'Fixed'. It throws an InvalidInputException if the condition is not met. ```Groovy import com.opensymphony.workflow.InvalidInputException if (issue.resolution.name == "Fixed" && !issue.fixVersions) { throw new InvalidInputException("fixVersions", "Fix Version/s is required when specifying Resolution of 'Fixed'") } ``` -------------------------------- ### Implement JQL function returning QueryLiteral for version fields Source: https://docs.adaptavist.com/sr4js/8.x/features/jql-functions/custom-jql-functions Implements VersionIsStarted as a scripted JQL function. Accepts no arguments, returns QueryLiteral instances for versions that are not released, have a startDate, and the startDate is before now. Applies project-level browse permission filtering and is intended for version fields like fixVersion and affectsVersion. ```Groovy package com.onresolve.jira.groovy.jql import com.atlassian.jira.JiraDataType import com.atlassian.jira.JiraDataTypes import com.atlassian.jira.component.ComponentAccessor import com.atlassian.jira.jql.operand.QueryLiteral import com.atlassian.jira.jql.query.QueryCreationContext import com.atlassian.jira.permission.ProjectPermissions import com.atlassian.jira.project.version.VersionManager import com.atlassian.jira.security.PermissionManager import com.atlassian.query.clause.TerminalClause import com.atlassian.query.operand.FunctionOperand class VersionIsStarted extends AbstractScriptedJqlFunction implements JqlFunction { VersionManager versionManager = ComponentAccessor.getComponent(VersionManager) PermissionManager permissionManager = ComponentAccessor.getPermissionManager() @Override String getDescription() { "Issues with fixVersion started but not released" } @Override List getArguments() { Collections.EMPTY_LIST // <1> } @Override String getFunctionName() { "versionsStarted" } @Override JiraDataType getDataType() { JiraDataTypes.VERSION // <2> } @Override List getValues( QueryCreationContext queryCreationContext, FunctionOperand operand, TerminalClause terminalClause ) { def now = new Date() versionManager.allVersions.findAll { def startDate = it.startDate !it.released && startDate && startDate < now // <3> }.findAll { queryCreationContext.securityOverriden || permissionManager.hasPermission(ProjectPermissions.BROWSE_PROJECTS, it.project, queryCreationContext.applicationUser) // <4> }.collect { new QueryLiteral(operand, it.id) // <5> } } } ``` -------------------------------- ### Render Wiki Markup to HTML - Jira Templates Source: https://docs.adaptavist.com/sr4js/8.x/features/listeners/built-in-listeners/send-a-custom-email This code snippet shows how to convert Jira wiki markup fields to HTML format for use in HTML emails. It uses the built-in helper.render() method with the standard Atlassian Wiki Renderer. Note that custom plugins providing alternative renderers are not supported, limiting this to the default Jira wiki syntax. ```Groovy ${helper.render(issue.description)} ``` -------------------------------- ### Filter Projects by Type (SR4js) Source: https://docs.adaptavist.com/sr4js/8.x/features/jql-functions/included-jql-functions/projects The `projectsOfType(String type)` function allows filtering issues based on a specified project type. For example, you can filter for issues within projects of type 'service_desk'. ```groovy project in projectsOfType("service_desk") ``` -------------------------------- ### Generate Web Items with Groovy Script Source: https://docs.adaptavist.com/sr4js/8.x/features/fragments/web-item-provider-built-in-script This Groovy script demonstrates how to dynamically generate a collection of web items using `WebFragmentBuilder`. Each item is configured with an ID, label, title, style class, and custom parameters. The script leverages Groovy's `collect` method to iterate and build the web items. ```groovy import com.atlassian.plugin.web.model.WebFragmentBuilder ["Foo", "Bar", "Quz"].collect { new WebFragmentBuilder(50). // <1> id("sample-web-item-${it.toLowerCase()}"). // <2> label("$it Sample Web Item"). title("$it Sample Web Item Title"). styleClass(""). addParam("data-my-key", "data-value"). // <3> addParam("iconUrl", "/jira/images/icons/priorities/highest.svg"). // not all places will show icons webItem(""). // <4> url("/"). build() } ``` -------------------------------- ### JavaScript for Dialog Interaction Source: https://docs.adaptavist.com/sr4js/8.x/features/fragments/web-item This JavaScript snippet demonstrates how to handle dialog interactions using AJS.dialog2. It includes an example of wiring a button to close the dialog and provides notes on controlling dialog removal from the DOM. ```javascript (function ($) { $(function () { AJS.dialog2.on("show", function (e) { var targetId = e.target.id; if (targetId == "my-own-dialog") { var someDialog = AJS.dialog2(e.target); $(e.target).find("#dialog-close-button").click(function (e) { e.preventDefault(); someDialog.hide(); someDialog.remove(); }); // etc } }); }); })(AJS.$); ```