floodmeadows / Jira move current issue to sprint

// ==UserScript==
// @name         Jira move current issue to sprint
// @description  Adds buttons to move the current issue into one or more sprints
// @namespace    https://openuserjs.org/users/floodmeadows
// @copyright    2025, floodmeadows (https://openuserjs.org/users/floodmeadows)
// @license      MIT
// @version      0.1
// @include      https://jira.*.uk/browse/*
// @grant        none
// ==/UserScript==

/* jshint esversion: 6 */

var issueKey = "";
const debug = true;
const currentUrl = new URL(document.URL);
const jiraBaseUrl = currentUrl.protocol + '//' + currentUrl.host;
// Sprint IDs
const inAnalysis = 20090;
const readyForRefinement = 18522;
const sprintReady = 18509;

(function() {
  'use strict';

  issueKey = document.getElementById('key-val').childNodes[0].nodeValue;

  addLink("Backlog", moveToBacklog)
  addLink("In Analysis", function() { moveToSprint(inAnalysis) } )
  addLink("Ready for Refinement", function() { moveToSprint(readyForRefinement) } )
  addLink("Sprint Ready", function() { moveToSprint(sprintReady) } )
})();

function addLink(buttonText, clickFunction) {
  const newElement = document.createElement("a");
  newElement.setAttribute("href","#");
  newElement.setAttribute("class","aui-button toolbar-trigger issueaction-workflow-transition");
  newElement.setAttribute("style", "margin-left:10px");
  newElement.addEventListener("click", clickFunction);
  const text = document.createTextNode(buttonText);
  newElement.appendChild(text);
  const target = document.getElementById('opsbar-opsbar-admin');
  target.appendChild(newElement);
}

function moveToSprint(sprintId) {
    const url = `${jiraBaseUrl}/rest/agile/latest/sprint/${sprintId}/issue`

    var headers = new Headers();
    headers.append("Content-Type", "application/json");

    var body = JSON.stringify({ "issues": [ issueKey ] });
    console.log("issueKey is: " + issueKey);
    console.log("About to POST with body: " + body);

    var requestOptions = {
        method: 'POST',
        headers: headers,
        body: body
    };

    fetch(url, requestOptions)
        .then(response => {
            console.log(response.text())
            if(!debug) window.location.assign(currentUrl);
        })
        .catch(error => console.log('error', error));
}

function moveToBacklog() {
    const url = `${jiraBaseUrl}/rest/agile/latest/backlog/issue`

    var headers = new Headers();
    headers.append("Content-Type", "application/json");

    var body = JSON.stringify({ "issues": [ issueKey ] });

    var requestOptions = {
        method: 'POST',
        headers: headers,
        body: body
    };

    fetch(url, requestOptions)
        .then(response => {
            console.log(response.text())
            if(!debug) window.location.assign(currentUrl);
        })
        .catch(error => console.log('error', error));
}