# Snippets: work items

> Oktul Code Studio script snippets for reading and changing work items, copied from the console and run by its tests.
>
> Documentation for Oktul Code Studio, for Jira Cloud and Confluence Cloud, by Oktul: https://oktul.com/docs/plugins/code-studio/snippets/work-items/

These are the snippets the console's **Snippets** dialog offers under Work items. 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](../../writing-scripts/) and the [script API reference](../../script-api/).

## Create a work item

Creates a task with a summary and a description. The description is Atlassian Document Format; the space and work type come from script variables so the script moves between sites unchanged.

```ts
interface Created {
    id: string;
    key: string;
}

export default async function (event: unknown, context: ScriptContext) {
    const vars = context.environment.vars;
    const created = await jira.post<Created>('/rest/api/3/issue', {
        fields: {
            project: { key: vars.SPACE_KEY ?? 'DEMO' },
            issuetype: { name: vars.WORK_TYPE ?? 'Task' },
            summary: 'Review the access list',
            description: {
                type: 'doc',
                version: 1,
                content: [{ type: 'paragraph', content: [{ type: 'text', text: 'Created by Code Studio.' }] }],
            },
        },
    });
    log.info(`Created ${created.key}`);
    return { key: created.key };
}
```

## Update a work item

Changes fields on the work item that started the run, or on WORK_ITEM_KEY. Fields not named are left as they are; notifyUsers false keeps a bulk change out of people's inboxes.

```ts
export default async function (event: { issue?: { key: string } } | null, context: ScriptContext) {
    const key = event?.issue?.key ?? context.environment.vars.WORK_ITEM_KEY;
    if (!key) throw new Error('No work item: run it from a listener or set WORK_ITEM_KEY.');

    await jira.put(`/rest/api/3/issue/${key}`, {
        fields: {
            summary: 'Updated by Code Studio',
            labels: ['reviewed'],
        },
    }, { query: { notifyUsers: false } });
    return { key };
}
```

## Delete a work item

Deletes a work item and its subtasks. Run it in the sandbox first: the run lists the delete and sends nothing.

```ts
export default async function (event: unknown, context: ScriptContext) {
    const key = context.environment.vars.WORK_ITEM_KEY;
    if (!key) throw new Error('Set WORK_ITEM_KEY to the work item to delete.');

    await jira.delete(`/rest/api/3/issue/${key}`, { query: { deleteSubtasks: true } });
    log.warn(`Deleted ${key}`);
    return { deleted: key };
}
```

## Add a comment

Comments on the work item that started the run. A comment body is Atlassian Document Format, the same as a description.

```ts
export default async function (event: { issue?: { key: string } } | null) {
    const key = event?.issue?.key ?? 'DEMO-1';
    await jira.post(`/rest/api/3/issue/${key}/comment`, {
        body: {
            type: 'doc',
            version: 1,
            content: [{ type: 'paragraph', content: [{ type: 'text', text: 'Checked by Code Studio.' }] }],
        },
    });
    return { key };
}
```

## Move a work item to a status

Finds the transition that leads to a status by its name, since transition ids differ per workflow, and takes it.

```ts
interface Transitions {
    transitions: { id: string; to: { name: string } }[];
}

export default async function (event: { issue?: { key: string } } | null) {
    const key = event?.issue?.key ?? 'DEMO-1';
    const target = 'Done';
    const { transitions } = await jira.get<Transitions>(`/rest/api/3/issue/${key}/transitions`);
    const transition = transitions.find((each) => each.to.name === target);
    if (!transition) {
        log.warn(`${key} has no transition to ${target}`);
        return { key, moved: false };
    }
    await jira.post(`/rest/api/3/issue/${key}/transitions`, { transition: { id: transition.id } });
    return { key, moved: true };
}
```

## Assign a work item

Assigns the work item to the person who reported it. Jira identifies people by account id; null unassigns.

```ts
interface Reported {
    fields: { reporter: { accountId: string } | null };
}

export default async function (event: { issue?: { key: string } } | null) {
    const key = event?.issue?.key ?? 'DEMO-1';
    const issue = await jira.get<Reported>(`/rest/api/3/issue/${key}`, { query: { fields: 'reporter' } });
    const accountId = issue.fields.reporter?.accountId ?? null;
    await jira.put(`/rest/api/3/issue/${key}/assignee`, { accountId });
    return { key, assignee: accountId };
}
```

## Link two work items

Links two work items with a link type by its name. inwardIssue is the one that blocks, outwardIssue the one blocked.

```ts
export default async function () {
    await jira.post('/rest/api/3/issueLink', {
        type: { name: 'Blocks' },
        inwardIssue: { key: 'DEMO-1' },
        outwardIssue: { key: 'DEMO-2' },
    });
    return { linked: true };
}
```

## Related

- [Writing scripts](../../writing-scripts/)
- [Requests to other systems](../../requests-to-other-systems/)
- [Script examples](../../script-examples/)

---

A problem or a question? Write to [support@oktul.com](mailto:support@oktul.com) or open a request in the [Help Center](https://oktul.atlassian.net/servicedesk/customer/portals). Both reach the same service desk, so either way the request gets a reference and an SLA measuring the response.
