Snippets: scripted fields
Oktul Code Studio script snippets for scripted fields: the value, the choices and the default, copied from the console and run by its tests.
These are the snippets the console’s Snippets dialog offers under Scripted fields. Each is TypeScript; in a .js script the console shows the same code with its types removed. Every one runs unchanged in Code Studio’s own tests. How the API they call behaves is in writing scripts and the script API reference.
Percent of subtasks done
For a Code Studio number field: the share of a work item’s subtasks that are done. With no subtasks the field stays empty.
interface WorkItem { fields?: { subtasks?: { fields?: { status?: { statusCategory?: { key?: string } } } }[] };}
export default async function (workItem: WorkItem) { const subtasks = workItem.fields?.subtasks ?? []; if (subtasks.length === 0) return null; const done = subtasks.filter((subtask) => subtask.fields?.status?.statusCategory?.key === 'done').length; return Math.round((done / subtasks.length) * 100);}Minutes since the last update
For a Code Studio number field that changes with time. In Scripted fields, tick Work item viewed under Compute again when. The value is then computed each time someone opens the work item, at most once a minute.
export default async function (workItem: { fields?: { updated?: string } }) { const updated = workItem.fields?.updated ? Date.parse(workItem.fields.updated) : NaN; if (Number.isNaN(updated)) return null; return Math.max(0, Math.floor((Date.now() - updated) / 60_000));}Count what a query finds for each work item
For a Code Studio number field: how many open work items block this one, counted with JQL. Each work item costs one count request, so keep the query narrow.
export default async function (workItem: { key: string }) { const found = await jira.post<{ count: number }>('/rest/api/3/search/approximate-count', { jql: `issue in linkedWorkItems("${workItem.key}", "is blocked by") AND statusCategory != Done`, }); return found.count;}Pick a choice from other fields
For a Code Studio select: the risk from the priority and the due date. options() lists the choices. A value outside them is not stored.
interface WorkItem { fields?: { priority?: { name?: string }; duedate?: string | null };}
export default async function (workItem: WorkItem) { const priority = workItem.fields?.priority?.name ?? 'Medium'; const due = workItem.fields?.duedate ? Date.parse(workItem.fields.duedate) : null; const soon = due !== null && due - Date.now() < 3 * 24 * 60 * 60 * 1000; if (priority === 'Highest' || (priority === 'High' && soon)) return 'High'; return soon ? 'Medium' : 'Low';}
export function options() { return ['Low', 'Medium', 'High'];}Select: choices from Jira, a default
For a Code Studio select, multi select, radio buttons or checkboxes. options() reads the choices, here the space’s components, and the default export sets a new work item’s default. options() runs when you publish and when you choose Read the choices again in the field’s Edit form. A value someone already chose stays.
interface Component { name: string;}
export function options() { return jira.get<Component[]>('/rest/api/3/project/DEMO/components').then((components) => components.map((component) => component.name));}
export default async function () { return 'Platform';}User picker: offer the members of a group
For a Code Studio user picker. options() lists the account IDs people can pick, here a group’s members. The default export makes the reporter the default. With no options() export, anyone can be picked.
interface Members { values: { accountId: string; displayName: string }[]; isLast: boolean;}
/** The group's id, from Atlassian Administration, Directory, Groups. A group can be renamed; its id stays. */const GROUP_ID = 'your-group-id';
export async function options() { const people: { value: string; label: string }[] = []; for (let startAt = 0; ; startAt += 50) { const page = await jira.get<Members>('/rest/api/3/group/member', { query: { groupId: GROUP_ID, startAt, maxResults: 50 } }); people.push(...(page.values ?? []).map((member) => ({ value: member.accountId, label: member.displayName }))); if (page.isLast !== false || people.length >= 200) break; } return people;}
export default async function (workItem: { fields?: { reporter?: { accountId?: string } } }) { return workItem.fields?.reporter?.accountId ?? null;}Group picker: offer the support teams
For a Code Studio group picker. options() lists the group IDs people can pick, here every group whose name starts with team-. With no options(), the field offers nothing.
interface Found { groups: { name: string; groupId: string }[];}
export async function options() { const found = await jira.get<Found>('/rest/api/3/groups/picker', { query: { query: 'team-', maxResults: 50 } }); return (found.groups ?? []).map((group) => ({ value: group.groupId, label: group.name }));}
export default async function () { return null;}Labels from the components
For a Code Studio labels field: one label per component, lower case with no spaces, so JQL can search it.
export default async function (workItem: { fields?: { components?: { name: string }[] } }) { return (workItem.fields?.components ?? []).map((component) => component.name.toLowerCase().replace(/\s+/g, '-'));}Related
A problem or a question? Write to support@oktul.com or open a request in the Help Center (opens in a new tab).