NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript==
// @name Jira append description from template story
// @namespace https://openuserjs.org/users/floodmeadows
// @description Adds button to copy description from template story and append to current story description
// @copyright 2023, floodmeadows (https://openuserjs.org/users/floodmeadows)
// @license MIT
// @version 0.2
// @include https://jira.*.uk/browse/*
// @updateURL https://openuserjs.org/meta/floodmeadows/Jira_append_description_from_template_story.meta.js
// @downloadURL https://openuserjs.org/install/floodmeadows/Jira_append_description_from_template_story.user.js
// @grant none
// ==/UserScript==
/* jshint esversion: 6 */
//--- Customise your template stories here ----//
const radioButtonPageTemplateIssueKey = 'APB-10130';
const textFieldPageTemplateIssueKey = 'APB-10131';
//-------------------------------------//
const currentUrl = new URL(document.URL);
const jiraBaseUrl = currentUrl.protocol + '//' + currentUrl.host;
const debug = false;
const targetElementForButtonsAndLinks = document.getElementById('descriptionmodule-label');
(function () {
'use strict';
if (debug) addButton("Clear description", targetElementForButtonsAndLinks, clearDescription);
addLink("Radio button template", targetElementForButtonsAndLinks, jiraBaseUrl + "/browse/" + radioButtonPageTemplateIssueKey);
addButton("Append radio button template", targetElementForButtonsAndLinks, appendRadioButtonTemplateTextToCurrentDescription);
addLink("Text field template", targetElementForButtonsAndLinks, jiraBaseUrl + "/browse/" + textFieldPageTemplateIssueKey);
addButton("Append text field template", targetElementForButtonsAndLinks, appendTextFieldTemplateTextToCurrentDescription);
})();
function addButton(buttonText, targetElement, functionName) {
const button = document.createElement("button");
button.setAttribute("class", "aui-button");
button.addEventListener("click", functionName);
const text = document.createTextNode(buttonText);
button.appendChild(text);
targetElement.after(button);
}
function addLink(linkText, targetElement, url) {
const link = document.createElement("a");
link.setAttribute("href", url);
link.setAttribute("style", "margin-left: 8px;");
const text = document.createTextNode(linkText);
link.appendChild(text);
targetElement.after(link);
}
function appendRadioButtonTemplateTextToCurrentDescription() {
appendTemplateTextToCurrentDescription(radioButtonPageTemplateIssueKey);
}
function appendTextFieldTemplateTextToCurrentDescription() {
appendTemplateTextToCurrentDescription(textFieldPageTemplateIssueKey);
}
function appendTemplateTextToCurrentDescription(templateIssueKey) {
//--- Get standard info ---//
const currentIssueKey = document.getElementById("key-val").childNodes[0].nodeValue;
const currentIssueApiUrl = `${jiraBaseUrl}/rest/api/latest/issue/${currentIssueKey}`;
const templateIssueApiUrl = `${jiraBaseUrl}/rest/api/latest/issue/${templateIssueKey}`;
if(debug) console.log('URL: ' + currentIssueApiUrl);
var headers = new Headers();
headers.append("Content-Type", "application/json");
var requestOptions = {
method: 'GET',
headers: headers
};
/* --- start block for fetching the template issue details --- */
fetch(templateIssueApiUrl, requestOptions)
.then(response => {
const jsonPromise = response.json()
.then(data => {
const templateIssue = data;
if (debug) console.log(templateIssue);
console.log("Template description = '" + templateIssue.fields.description + ".'");
const templateDescription = templateIssue.fields.description;
/* --- start block for fetching the current issue details --- */
fetch(currentIssueApiUrl, requestOptions)
.then(response => {
const jsonPromise = response.json()
.then(data => {
const currentIssue = data;
if (debug) console.log(currentIssue);
console.log("Current description = '" + currentIssue.fields.description + ".'");
const currentDescription = currentIssue.fields.description;
var newDescription = "";
if (currentDescription != null) {
newDescription = currentDescription + "\r\n\r\n" + templateDescription;
} else {
newDescription = templateDescription;
}
console.log("New description = '" + newDescription + ".'");
updateDescription(newDescription);
});
})
.catch(error => {
console.log('Error fetching current issue: ', error);
return false;
});
/* --- end block for fetching the current issue details --- */
});
})
.catch(error => {
console.log('Error fetching template issue: ', error);
return false;
});
/* --- end block for fetching the template issue details --- */
}
function clearDescription() {
updateDescription("");
}
function updateDescription(newDescription) {
//--- Get standard info ---//
const currentUrl = new URL(document.URL);
const jiraBaseUrl = currentUrl.protocol + '//' + currentUrl.host;
const currentIssueKey = document.getElementById("key-val").childNodes[0].nodeValue;
const updateIssueUrl = `${jiraBaseUrl}/rest/api/latest/issue/${currentIssueKey}`;
var headers = new Headers();
headers.append("Content-Type", "application/json");
var jsonToUpdateIssue = JSON.stringify({
"fields": {
"description": newDescription
}
});
if (debug) console.log(jsonToUpdateIssue);
var requestOptions = {
method: 'PUT',
headers: headers,
body: jsonToUpdateIssue
};
fetch(updateIssueUrl, requestOptions)
.then(response => {
console.log(response.text());
if(!debug) window.location.assign(currentUrl);
})
.catch(error => console.log('error', error));
}