NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name Jira Workflow diagram extract to SVG // @namespace https://jrwarwick.github.io/ // @version 0.1 // @description Jira Workflow Diagrams, in edit mode, are embedded SVG, just find and pull it out and then drop it into a download file for other usage. // @copyright 2022, Justin Warwick // @author jrwarwick // @license MIT // @match https://onprem-jira.domain.com/plugins/servlet/project-config/*/workflow/edit/* // @match https://onprem-jira.domain.com/plugins/servlet/project-config/*/workflow/* // @icon https://marketplace.atlassian.com/s/images/favicon.ico // @grant none // ==/UserScript== //Bug/TODO: it only really works if you come into the workflow editor clean, no on-going draft as this modifies button states. //Bug/TODO: janky timer usage in injector function. Better if we have some more clean deterministic events to hook onto, or queues to jump into. var logTag = "[UserScript:DiagramSVGExtract]: " //The work itself is simple: the diagram in Jira is just an embedded SVG (once you have gone into Edit mode). //So just get it and throw down as a WUA "download" file. function saveSvg(svgEl, name) { svgEl.setAttribute("xmlns", "http://www.w3.org/2000/svg"); var svgData = svgEl.outerHTML; var preface = '<?xml version="1.0" standalone="no"?>\r\n'; var svgBlob; try { svgBlob = new Blob([preface, svgData], {type:"image/svg+xml;charset=utf-8"}); } catch (e) { // Old browser, need to use blob builder window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder; if (window.BlobBuilder) { var bb = new BlobBuilder(); bb.append(svgData); svgBlob = bb.getBlob("image/svg+xml;charset=utf-8"); } } var svgUrl = URL.createObjectURL(svgBlob); var downloadLink = document.createElement("a"); downloadLink.href = svgUrl; downloadLink.download = name; document.body.appendChild(downloadLink); downloadLink.click(); document.body.removeChild(downloadLink); } //now everything else is just inject a button to click to do this (which is harder than I expected): //saveSvg($("#workflow-designer1 > svg")[0], $("#project-config-header-descriptor-title").html().replace(/[^0-9A-Z]/gi,"_") + ".svg"); function performSVGextraction() { console.info(logTag+"grasping and groping for the diagram's SVG content..."); saveSvg($("#workflow-designer1 > svg")[0], $("#project-config-header-descriptor-title").html().replace(/[^0-9A-Z]/gi,"_") + ".svg"); } function extractorEventInjector(evt) { console.info(logTag+"does edit_workflow exist yet? " + $("#edit_workflow")[0]); var timeoutID = setTimeout(function(){ console.log(logTag+$("#edit_workflow")[0]); $("#edit_workflow").on('click',function() { if ($("#btnPerfSVGExt").length) { console.info(" already have the svg extract button..."); } else { var timeoutID = setTimeout(function(){ $("#workflow-designer-last-saved-by").append(' <button id="btnPerfSVGExt" class="aui-button"><span class="aui-icon aui-icon-small aui-iconfont-open">Get SVG </span>Get SVG</button>'); $("#btnPerfSVGExt").on('click',performSVGextraction); },1234); console.log(logTag+"SVG event injection initiated... " + timeoutID); } }); },4444); } (function() { 'use strict'; // Your code here... //$( window ).on( 'hashchange', function(evt) { //weered. why doesn't this work. //$(document).ajaxComplete(function(evt) { $(document).ready(extractorEventInjector); $( window ).on( 'hashchange',extractorEventInjector); //weered. why doesn't this work. })();