Smart Fields library
The Smart Fields library provides you with an overview of all available templates and additional use cases (example expressions) that should give you an easy start on how to use Smart Fields for Jira.
Make sure to come by once in a while since the number of use cases will grow over time.
Templates
Smart fields provides a varied set of preconfigured Templates you can use with minimal configuration. These are shown if you Create and configure smart fields or when you Manage existing smart fields / Field overview.
They are group into logical categories depending on the use case or the data that you likely want to display. These categories are:
π Use cases
In addition to the built-in templates we have collected a large collection of uses cases to be used in Custom smart number fields and Custom smart text fields
Custom smart number fields
Use case | Parsing mode | Expression |
---|---|---|
Average time since creation of sub-tasks | General | %{floor(avg(toNumberList(jiraExpression("issue.subtasks.map( i=>(Number(new Date())-Number(i.created))/1000/60/60/24)"))))} |
Completion percentage by status | General | %{%{issue.status} = "Open" ? 0 : ( %{issue.status} = "Planning" ? 0.15 : ( %{issue.status} = "In Progress" ? 0.6 : ( %{issue.status} = "In Review" ? 0.7 : ( %{issue.status} = "Implementing" ? 0.85 : 1 ))))} |
Count frequency of a keyword in social media content | General | %{count(findPattern(%{issue.cfnnnn}, %{issue.cfmmmm}))} |
Days until due date | General | %{{issue.dueDate} != null ? floor(max({issue.dueDate} - datePart({system.currentDateTime}, RUN_AS_LOCAL), 0) / DAY) : null |
Difference between the current day and the earliest sub-task due date | General | %{max(fieldValue({issue.dueDate},subtasks())) != null ? ceil(( min(filterByValue(fieldValue({issue.dueDate},subtasks()),!=, null )) - {system.currentDateTime}) / DAY) : null} |
Elapsed time between creation and resolution | General | %{{issue.resolutionDate} != null ? (({issue.resolutionDate} - {issue.created}) / DAY ) : null} |
Highest value out of several fields | General | %{max([{issue.cfAAAAA}, {issue.cfBBBBB}, {issue.cfCCCCC}, {issue.cfDDDDD}, {issue.cfEEEEE}])} |
Number of characters in a field | General | %{count(findPattern(%{issue.cfnnnn}, "."))} |
Number of sub-tasks based on status | General | %{count(filterByStatus(subtasks(), "Done, Completed"))} |
Number of sub-tasks based on status and work item type | General | %{count(filterByIssueType(filterByStatus(subtasks(), "Done, Completed"), "Sub-task, Sub-story"))} |
Number of times that a custom field has been changed | Jira expression | issue.changelogs .filter(changelog => changelog.items .some(item => item.fieldId == 'customfield_nnnnn')) .length |
Number of work items with the same fix versions | General | %{%{issue.fixVersions} != null ? count(issuesFromJQL( "fixVersion in ('" + jiraExpression( "issue?.fixVersions?.map( v => v?.name).join(\"','\") ") + "') ")) : null} |
Operations with field values from sub-tasks | Jira expression | issue.subtasks.length && issue.subtasks.map( s => (s.customfield_nnnnn || 0) * (s.customfield_ppppp || 0)) .reduce((a, b) => a + b) |
Priority assessment based on field values | General | %{sum([%{issue.cfnnnnn} = "Option 1" ? 1 : 0, %{issue.cfppppp} = "Option 2" ? 1 : 0 ])} |
Remaining budget | General | %{{issue.cfnnnnn} = null ? null : {issue.cfnnnnn} - sum( append(fieldValue({issue.cfppppp}, subtasks()), [0]))} |
Sum of field values from work items in JQL query | General | %{sum(fieldValue({issue.cfnnnnn},issuesFromJQL("project = DEMO and 'fieldName' is not empty")))} |
Sum of time spent of blocking work items | General | %{sum(append(fieldValue({issue.timeSpent},linkedIssues("is blocked by")), [0]))/60} |
Sum of time spent of epic and work items under it | General | %{%{issue.issueType} = "Epic" ? (sum(append(fieldValue( {issue.timeSpent}, issuesUnderEpic()), [{issue.timeSpent}] )) / 60) : null} |
Time left until due date | General | %{{issue.dueDate} != null ? max({issue.dueDate} - {system.currentDateTime}, 0) / DAY : null} |
Time since creation | General | %{floor(({system.currentDateTime} - {issue.created})/DAY)} |
Total original estimate of blocking work items | General | %{sum(append(fieldValue({issue.originalEstimate},linkedIssues( "is blocked by")),[0]))/60} |
Total remaining estimate of blocking work items | General | %{sum(append(fieldValue({issue.remainingEstimate},linkedIssues( "is blocked by")),[0]))/60} |
Custom smart text fields
Use case | Parsing mode | Expression |
---|---|---|
Earliest date and time from linked work items | Jira expression | let minDate = issue?.links.map(link => link.linkedIssue.customfield_nnnnn).filter( d => d != null); minDate.length > 0 ? new Date(minDate.reduce((a, b) => a < b ? a : b )).toString() : "" |
Earliest date from linked work items | Jira expression | let minDate = issue?.links.map(link => link.linkedIssue.customfield_nnnnn).filter( d => d != null); minDate.length > 0 ? new CalendarDate(minDate.reduce((a, b) => a < b ? a : b )).toString() : "" |
Field value validation | General | %{matches(%{issue.cfnnnnn},"6|7|8|9") ? "Valid":"Invalid"} |
Historical due dates | Jira expression | issue.changelogs.filter(changelog => changelog.items.some(item => item.fieldId == 'duedate' && item.from != null)).map( changelog => {duedateentry: changelog.items.filter(item => item.fieldId == 'duedate' )}).map(e => new CalendarDate( e.duedateentry[0].from).toString()).join(", ") |
Keys of linked work items in current project | General | %{filterByProject(linkedIssues(), %{issue.project.key})} |
Keys of non-estimated sub-tasks | Jira expression | issue.subtasks.filter(s => s?.originalEstimate == null && s?.customfield_nnnnn == null).map(i => i.key).join(", ") |
Last status change date | Jira expression | issue.changelogs.filter(changelog => changelog.items.some(item => item.fieldId == 'status')).map(changelog => changelog.created).concat(issue.created)[0].toString() |
RAG - due date traffic light | General | %{addDays({system.currentDateTime}, 14, RUN_AS_LOCAL) < {issue.dueDate} ? "π’" : (addDays({system.currentDateTime}, 7, RUN_AS_LOCAL) < {issue.dueDate} ? "π‘" : "π΄") } |
RAG - status traffic light | General | %{%{issue.status.category} = "To Do" ? "π΄βͺοΈβͺοΈ" : ( %{issue.status.category} = "In Progress" ? "βͺοΈπ‘βͺοΈ" : ( %{issue.status.category} = "Done" ? "βͺοΈβͺοΈπ’" : "βͺοΈβͺοΈβͺοΈ" ))} |
Validate URLs for Google Analytics | General | %{count(findPattern(%{issue.cfnnnnn}, "\b(?:https?://|www\.)\S*(?=.*utm_source=)(?=.*utm_medium=)(?=.utm_campaign=)\S\b")) = count(findPattern(%{issue.cfnnnnn}, "\b(?:https?://|www\.)\S+\b")) ? "π’" : "π΄"} |
Visual progress of sub-tasks | General | let subtasks = issue.subtasks|| []; if (subtasks.length == 0){ 'No sub-tasks' } else{ let doneSubtasks = subtasks.filter(s => s.status.name == "Done"); let value = (doneSubtasks.length / subtasks.length) * 100; let percent = value - value % 1 + (value % 1 >= 0.5 ? 1 : 0); let totalBlocks = 10; let filled = (percent / 100) * totalBlocks; let full = filled - filled % 1 + (filled % 1 >= 0.5 ? 1 : 0); let bar = 'π©'.repeat(full) + 'β¬οΈ'.repeat(totalBlocks - full); `${bar} ${percent}%` } |
Visual progress of work item | General | %{%{issue.status} = "Open" ? "π©π©π©π©π©" : ( %{issue.status} = "Planning" ? "π©π©β¬οΈβ¬οΈβ¬οΈ" : ( %{issue.status} = "In Progress" ? "π©π©π©β¬οΈβ¬οΈ" : ( %{issue.status} = "In Review" ? "π©π©π©π©β¬οΈ" : ( %{issue.status} = "Done" ? "π©π©π©π©π©" : "β¬οΈβ¬οΈβ¬οΈβ¬οΈβ¬οΈ" ))))} |