(function() { // Public Instances // Jira: https://connect.atlassian.net/browse/NERDS-33286 // PivotTracker: https://www.pivotaltracker.com/n/projects/510733 // Trello: https://trello.com/b/8zlPSh70/spike // YouTrack: http://qoomon.myjetbrains.com/youtrack/dashboard var global = {}; global.version = "4.3.6"; global.issueTrackingUrl = "https://github.com/qoomon/Jira-Issue-Card-Printer"; global.isDev = document.currentScript == null; global.isProd = !global.isDev; window.addEventListener("error", function(event) { var error = event.error; console.log("ERROR: " + error.stack); if (global.isProd) { ga('send', 'exception', { 'exDescription': error.message, 'exFatal': true }); } }); init().then(function(){ return main(); }).catch(function(cause){ console.log("ERROR " + cause.stack); alert("Sorry something went wrong.\n\nPlease create an issue at " + global.issueTrackingUrl + "\n\n" + cause.stack); }); function main() { var promises = []; console.log("Run...") // determine application if (jQuery("meta[name='application-name'][ content='JIRA']").length > 0) { console.log("App: " + "Jira"); global.appFunctions = jiraFunctions; } else if (/.*pivotaltracker.com\/.*/g.test(document.URL)) { console.log("App: " + "PivotalTracker"); global.appFunctions = pivotalTrackerFunctions; } else if (/.*trello.com\/.*/g.test(document.URL)) { console.log("App: " + "Trello"); global.appFunctions = trelloFunctions; } else if (/.*myjetbrains.com\/youtrack\/.*/g.test(document.URL) || /.*youtrack.jetbrains.com\/.*/g.test(document.URL) ) { console.log("App: " + "YouTrack"); global.appFunctions = youTrackFunctions; } else { alert("Unsupported app. Please create an issue at " + global.issueTrackingUrl); return; } // collect selcted issues var issueKeyList = global.appFunctions.getSelectedIssueKeyList(); if (issueKeyList.length <= 0) { alert("Please select at least one issue."); return; } else if (issueKeyList.length > 30) { confirm("Are you sure you want select " + issueKeyList.length + " issues?"); return; } //preconditions if (jQuery("#card-printer-iframe").length > 0) { alert("Card Printer already opened!"); return; } // create iFrame var appFrame = document.createElement('iframe'); appFrame.id = "card-printer-iframe"; jQuery(appFrame).css({ 'position': 'fixed', 'height': '100%', 'width': '100%', 'top': '0', 'left': '0', 'background': 'rgba(0, 0, 0, 0.5)', 'boxSizing': 'border-box', 'wordWrap': 'break-word', 'zIndex': '99999' }); jQuery("body").append(appFrame); appFrame.window = appFrame.contentWindow; appFrame.document = appFrame.window.document; global.appFrame = appFrame; // open print preview jQuery("head", appFrame.document).prepend(printPreviewElementStyle()); jQuery("body", appFrame.document).append(printPreviewElement()); var printFrame = jQuery("#card-print-dialog-content-iframe", appFrame.document)[0]; printFrame.window = printFrame.contentWindow; printFrame.document = printFrame.window.document; global.printFrame = printFrame; printFrame.contentWindow.addEventListener("resize", redrawCards); printFrame.contentWindow.matchMedia("print").addListener(redrawCards); var settings = global.settings; // restore UI state jQuery("#scaleRange", appFrame.document).val(settings.scale); jQuery("#scaleRange", appFrame.document).parent().find("output").val(settings.scale); jQuery("#rowCount", appFrame.document).val(settings.rowCount); jQuery("#columnCount", appFrame.document).val(settings.colCount); jQuery("#single-card-page-checkbox", appFrame.document).attr('checked', settings.singleCardPage ); jQuery("#description-checkbox", appFrame.document).attr('checked', !settings.hideDescription ); jQuery("#assignee-checkbox", appFrame.document).attr('checked', !settings.hideAssignee ); jQuery("#due-date-checkbox", appFrame.document).attr('checked', !settings.hideDueDate ); jQuery("#qr-code-checkbox", appFrame.document).attr('checked', !settings.hideQrCode ); jQuery("#card-print-dialog-title", appFrame.document).text("Card Printer " + global.version + " - Loading issues..."); promises.push(renderCards(issueKeyList).then(function() { jQuery("#card-print-dialog-title", appFrame.document).text("Card Printer " + global.version); })); if (global.isProd) { ga('send', 'pageview'); } return Promise.all(promises); } function init() { var promises = []; console.log("Init...") addStringFunctions(); loadSettings(); global.hostOrigin = "https://qoomon.github.io/Jira-Issue-Card-Printer/"; if (global.isDev) { console.log("DEVELOPMENT"); global.hostOrigin = "https://rawgit.com/qoomon/Jira-Issue-Card-Printer/develop/"; } global.resourceOrigin = global.hostOrigin + "resources/"; if (global.isProd) { initGoogleAnalytics(); } promises.push(httpGetCORS(global.hostOrigin + "card.html").then(function(data){ global.cardHtml = data; })); promises.push(httpGetCORS(global.hostOrigin + "card.css").then(function(data){ global.cardCss = data.replace(/https:\/\/qoomon.github.io\/Jira-Issue-Card-Printer\/resources/g, global.resourceOrigin); })); promises.push(httpGetCORS(global.hostOrigin + "printPreview.html").then(function(data){ global.printPreviewHtml = data })); promises.push(httpGetCORS(global.hostOrigin + "printPreview.css").then(function(data){ global.printPreviewCss = data.replace(/https:\/\/qoomon.github.io\/Jira-Issue-Card-Printer\/resources/g, global.resourceOrigin); })); return Promise.all(promises); } function saveSettings(){ var settings = global.settings; writeCookie("card_printer_scale", settings.scale); writeCookie("card_printer_row_count", settings.rowCount); writeCookie("card_printer_column_count", settings.colCount); writeCookie("card_printer_single_card_page", settings.singleCardPage); writeCookie("card_printer_hide_description", settings.hideDescription); writeCookie("card_printer_hide_assignee", settings.hideAssignee); writeCookie("card_printer_hide_due_date", settings.hideDueDate); writeCookie("card_printer_hide_qr_code", settings.hideQrCode); } function loadSettings(){ var settings = global.settings = global.settings || {}; settings.scale = parseFloat(readCookie("card_printer_scale")) || 0.0; settings.rowCount = parseInt(readCookie("card_printer_row_count2")) || 2; settings.colCount = parseInt(readCookie("card_printer_column_count")) || 1; settings.singleCardPage = parseBool(readCookie("card_printer_single_card_page"), true ); settings.hideDescription = parseBool(readCookie("card_printer_hide_description"), false); settings.hideAssignee = parseBool(readCookie("card_printer_hide_assignee"), false); settings.hideDueDate = parseBool(readCookie("card_printer_hide_due_date"), false); settings.hideQrCode = parseBool(readCookie("card_printer_hide_qr_code"), false); } function print() { if (global.isProd) { ga('send', 'event', 'button', 'click', 'print', jQuery(".card", global.printFrame.contentWindow.document).length); } global.printFrame.contentWindow.print(); } function renderCards(issueKeyList) { var promises = []; var printFrame = global.printFrame; printFrame.document.open(); printFrame.document.write(""); jQuery("head", printFrame.document).append(cardElementStyle()); jQuery("body", printFrame.document).append("
"); jQuery("#preload", printFrame.document).append("
"); console.log("load " + issueKeyList.length + " issues..."); jQuery.each(issueKeyList, function(index, issueKey) { var card = cardElement(issueKey); card.attr("index", index); card.hide(); card.find('.issue-id').text(issueKey); jQuery("body", printFrame.document).append(card); promises.push(global.appFunctions.getCardData(issueKey).then(function(cardData) { console.log("cardData: " + JSON.stringify(cardData,2,2)); if (global.isProd) { ga('send', 'event', 'card', 'generate', cardData.type); } fillCard(card, cardData); redrawCards(); card.show(); })); }); console.log("wait for issues loaded..."); return Promise.all(promises).then(function() { console.log("...all issues loaded."); jQuery(printFrame.window).load(function() { console.log("...all resources loaded."); }); console.log("wait for resources loaded..."); printFrame.document.close(); redrawCards(); }); } function redrawCards() { styleCards(); scaleCards(); cropCards(); resizeIframe(global.printFrame); } function fillCard(card, data) { //Key card.find('.issue-id').text(data.key); //Type card.find(".issue-icon").attr("type", data.type); //Summary card.find('.issue-summary').text(data.summary); //Description if (data.description) { card.find('.issue-description').html(data.description); } else { card.find(".issue-description").addClass("hidden"); } //Assignee if (data.assignee) { if (data.avatarUrl) { card.find(".issue-assignee").css("background-image", "url('" + data.avatarUrl + "')"); } else { card.find(".issue-assignee").text(data.assignee[0].toUpperCase()); } } else { card.find(".issue-assignee").remove(); } //Due-Date if (data.dueDate) { card.find(".issue-due-date").text(data.dueDate); } else { card.find(".issue-due-box").remove(); } //Attachment if (data.hasAttachment) {} else { card.find('.issue-attachment').remove(); } //Story Points if (data.storyPoints) { card.find(".issue-estimate").text(data.storyPoints); } else { card.find(".issue-estimate").remove(); } //Epic if (data.superIssue) { card.find(".issue-epic-id").text(data.superIssue.key); card.find(".issue-epic-name").text(data.superIssue.summary); } else { card.find(".issue-epic-box").remove(); } //QR-Code var qrCodeUrl = 'https://chart.googleapis.com/chart?cht=qr&chs=256x256&chld=L|1&chl=' + encodeURIComponent(data.url); card.find(".issue-qr-code").css("background-image", "url('" + qrCodeUrl + "')"); } function styleCards() { var settings = global.settings; var printFrame = global.printFrame // hide/show description jQuery(".issue-description", printFrame.document).toggle(!settings.hideDescription); // hide/show assignee jQuery(".issue-assignee", printFrame.document).toggle(!settings.hideAssignee); // hide/show assignee jQuery(".issue-due-box", printFrame.document).toggle(!settings.hideDueDate); // hide/show cr code jQuery(".issue-qr-code", printFrame.document).toggle(!settings.hideQrCode); // enable/disable single card page jQuery(".card", printFrame.document).css({ 'page-break-after' : '', 'float' : '', 'margin-bottom': '' }); if (settings.singleCardPage) { jQuery(".card", printFrame.document).css({ 'page-break-after': 'always', 'float': 'none', 'margin-bottom': '20px' }); } else { jQuery(".card", printFrame.document).each(function(index, element){ if(index % (settings.colCount * settings.rowCount ) >= (settings.colCount * (settings.rowCount - 1))){ jQuery(element).css({ 'margin-bottom': '20px' }); console.log("buz") } }); } } function scaleCards() { var settings = global.settings; var printFrame = global.printFrame; var scaleValue = settings.scale * 2.0; var scaleRoot; if(scaleValue < 0) { scaleRoot = 1.0 / (1.0 - scaleValue); } else { scaleRoot = 1.0 * (1.0 + scaleValue); } var rowCount = settings.rowCount; var columnCount = settings.colCount; // scale // reset scale jQuery("html", printFrame.document).css("font-size", scaleRoot + "cm"); jQuery("#gridStyle", printFrame.document).remove(); // calculate scale var bodyElement = jQuery("body", printFrame.document); var cardMaxWidth = Math.floor(bodyElement.outerWidth() / columnCount); var cardMaxHeight = Math.floor(bodyElement.outerHeight() / rowCount); var cardElement = jQuery(".card", printFrame.document); var cardMinWidth = cardElement.css("min-width").replace("px", ""); var cardMinHeight = cardElement.css("min-height").replace("px", ""); var scaleWidth = cardMaxWidth / cardMinWidth ; var scaleHeight = cardMaxHeight / cardMinHeight ; var scale = Math.min(scaleWidth, scaleHeight, 1); // scale jQuery("html", printFrame.document).css("font-size", ( scaleRoot * scale ) + "cm"); // grid size var style = document.createElement('style'); style.id = 'gridStyle'; style.type = 'text/css'; style.innerHTML = ".card { "+ "width: calc( 100% / " + columnCount + " );" + "height: calc( 100% / " + rowCount + " );"+ "}"; jQuery("head", printFrame.document).append(style); } function cropCards() { var cardElements = global.printFrame.document.querySelectorAll(".card"); forEach(cardElements, function(cardElement) { var cardContent = cardElement.querySelectorAll(".card-body")[0]; if (cardContent.scrollHeight > cardContent.offsetHeight) { cardContent.classList.add("zigzag"); } else { cardContent.classList.remove("zigzag"); } }); } function forEach(array, callback) { for (i = 0; i < array.length; i++) { callback(array[i]); } } function closePrintPreview() { jQuery("#card-printer-iframe").remove(); } //############################################################################################################################ //############################################################################################################################ //############################################################################################################################ // http://www.cssdesk.com/T9hXg function printPreviewElement() { var result = jQuery('
').html(global.printPreviewHtml).contents(); // info result.find("#report-issue").click(function(event) { window.open('https://github.com/qoomon/Jira-Issue-Card-Printer/issues'); return false; }); result.find("#about").click(function(event) { window.open('http://qoomon.blogspot.de/2014/01/jira-issue-card-printer-bookmarklet.html'); return false; }); // enable single card page result.find("#single-card-page-checkbox").click(function() { global.settings.singleCardPage = this.checked; saveSettings(); redrawCards(); return true; }); // hide description result.find("#description-checkbox").click(function() { global.settings.hideDescription = !this.checked; saveSettings(); redrawCards(); return true; }); // show assignee result.find("#assignee-checkbox").click(function() { global.settings.hideAssignee = !this.checked; saveSettings(); redrawCards(); return true; }); // show due date result.find("#due-date-checkbox").click(function() { global.settings.hideDueDate = !this.checked; saveSettings(); redrawCards(); return true; }); // show QR Code result.find("#qr-code-checkbox").click(function() { global.settings.hideQrCode = !this.checked; saveSettings(); redrawCards(); return true; }); // scale font result.find("#scaleRange").on("input", function() { global.settings.scale = jQuery(this).val(); saveSettings(); redrawCards(); }); // grid result.find("#rowCount").on("input", function() { global.settings.rowCount = jQuery(this).val(); saveSettings(); redrawCards(); }); result.find("#rowCount").click(function() { this.select(); }); result.find("#columnCount").on("input", function() { global.settings.colCount = jQuery(this).val(); saveSettings(); redrawCards(); }); result.find("#columnCount").click(function() { this.select(); }); // print result.find("#card-print-dialog-print") .click(function(event) { print(); return false; }); // closePrintPreview result.find("#card-print-dialog-cancel") .click(function(event) { closePrintPreview(); return false; }); result.click(function(event) { if (event.target == this) { closePrintPreview(); } return true; }); jQuery(document).keyup(function(e) { if (e.keyCode == 27) { // ESC closePrintPreview(); } }); // prevent background scrolling result.scroll(function(event) { return false; }); return result; } function printPreviewElementStyle() { var result = jQuery(document.createElement('style')) .attr("type", "text/css") .html(global.printPreviewCss); return result; } // card layout: http://jsfiddle.net/qoomon/ykbLb2pw/76 function cardElement(issueKey) { var result = jQuery('
').html(global.cardHtml).contents() .attr("id", issueKey) return result; } function cardElementStyle() { var result = jQuery(document.createElement('style')) .attr("type", "text/css") .html(global.cardCss); return result; } //############################################################################################################################ //############################################################################################################################ //############################################################################################################################ function initGoogleAnalytics() { // (function(i, s, o, g, r, a, m) { i['GoogleAnalyticsObject'] = r; i[r] = i[r] || function() { (i[r].q = i[r].q || []).push(arguments) }, i[r].l = 1 * new Date(); a = s.createElement(o), m = s.getElementsByTagName(o)[0]; a.async = 1; a.src = g; m.parentNode.insertBefore(a, m) })(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga'); ga('create', 'UA-50840116-3', { 'alwaysSendReferrer': true }); ga('set', 'page', '/cardprinter'); } //############################################################################################################################ //############################################################################################################################ //############################################################################################################################ function parseBool(text, def){ if(text == 'true') return true; else if ( text == 'false') return false; else return def; } function appendScript(url, callback) { var head = document.getElementsByTagName('head')[0]; var script = document.createElement('script'); script.src = url; // Then bind the event to the callback function. // There are several events for cross browser compatibility. script.onreadystatechange = callback; script.onload = callback; head.appendChild(script); } function readCookie(name) { var cookies = document.cookie.split('; '); for (var i = 0; i < cookies.length; i++) { var cookie = cookies[i].split('='); if (cookie[0] == name) return cookie[1]; } return null; } function writeCookie(name, value) { document.cookie = name + "=" + value; } function httpGetCORS(){ //arguments[0] = 'https://jsonp.afeld.me/?url=' + arguments[0]; //arguments[0] = 'http://cors.io/?u=' + arguments[0]; arguments[0] = 'https://crossorigin.me/' + arguments[0]; return httpGet.apply(this, arguments); } function httpGet(){ return Promise.resolve(jQuery.get.apply(this, arguments)); } function httpGetJSON(){ return Promise.resolve(jQuery.getJSON.apply(this, arguments)); } function multilineString(commentFunction) { return commentFunction.toString() .replace(/^[^\/]+\/\*!?/, '') .replace(/\*\/[^\/]+$/, ''); } function resizeIframe(iframe) { iframe = jQuery(iframe); iframe.height(iframe[0].contentWindow.document.body.height); } //############################################################################################################################ //############################################################################################################################ //############################################################################################################################ function addStringFunctions() { //trim string - remove leading and trailing whitespaces if (!String.prototype.trim) { String.prototype.trim = function() { return this.replace(/^\s+|\s+$/g, ''); }; } if (!String.prototype.startsWith) { String.prototype.startsWith = function(str) { return this.slice(0, str.length) == str; }; } if (!String.prototype.endsWith) { String.prototype.endsWith = function(str) { return this.slice(-str.length) == str; }; } if (!String.prototype.toCamelCase) { String.prototype.toCamelCase = function() { // remove all characters that should not be in a variable name // as well underscores an numbers from the beginning of the string var s = this.replace(/([^a-zA-Z0-9_\- ])|^[_0-9]+/g, "").trim().toLowerCase(); // uppercase letters preceeded by a hyphen or a space s = s.replace(/([ -]+)([a-zA-Z0-9])/g, function(a, b, c) { return c.toUpperCase(); }); // uppercase letters following numbers s = s.replace(/([0-9]+)([a-zA-Z])/g, function(a, b, c) { return b + c.toUpperCase(); }); return s; } } } function formatDate(date) { var shortMonths = {'Jan': 1, 'Feb':2, 'Mar':3, 'Apr':4, 'May':5, 'Jun':6, 'Jul':7, 'Aug':8, 'Sep':9, 'Oct':10, 'Nov':11, 'Dec':12 }; var dateSplit = date.toString().split(" "); // Mo 28.11. return dateSplit[0] + " " + dateSplit[2] + "." + shortMonths[dateSplit[1]] + "."; } // APP Specific Functions //############################################################################################################################ //############################################################################################################################ //############################################################################################################################ var jiraFunctions = (function(module) { module.getSelectedIssueKeyList = function() { //Issues if (/.*\/issues\/\?jql=.*/g.test(document.URL)) { var jql = document.URL.replace(/.*\?jql=(.*)/, '$1'); var jqlIssues = []; var url = '/rest/api/2/search?jql=' + jql + "&maxResults=500&fields=key"; console.log("IssueUrl: " + url); //console.log("Issue: " + issueKey + " Loading..."); jQuery.ajax({ type: 'GET', url: url, data: {}, dataType: 'json', async: false, success: function(responseData) { console.log("responseData: " + responseData.issues); jQuery.each(responseData.issues, function(key, value) { jqlIssues.push(value.key); }); }, }); console.log("jqlIssues: " + jqlIssues); return jqlIssues; } //Browse if (/.*\/browse\/.*/g.test(document.URL)) { return [document.URL.replace(/.*\/browse\/([^?]*).*/, '$1')]; } //Project if (/.*\/projects\/.*/g.test(document.URL)) { return [document.URL.replace(/.*\/projects\/[^\/]*\/[^\/]*\/([^?]*).*/, '$1')]; } // RapidBoard if (/.*\/secure\/RapidBoard.jspa.*/g.test(document.URL)) { return jQuery('div[data-issue-key].ghx-selected').map(function() { return jQuery(this).attr('data-issue-key'); }); } return []; }; module.getCardData = function(issueKey) { var promises = []; var issueData = {}; promises.push(module.getIssueData(issueKey).then(function(data) { var promises = []; issueData.key = data.key; issueData.type = data.fields.issuetype.name.toLowerCase(); issueData.summary = data.fields.summary; issueData.description = data.renderedFields.description; if (data.fields.assignee) { issueData.assignee = data.fields.assignee.displayName; var avatarUrl = data.fields.assignee.avatarUrls['48x48']; if (avatarUrl.indexOf("ownerId=") >= 0) { issueData.avatarUrl = avatarUrl; } } if (data.fields.duedate) { issueData.dueDate = formatDate(new Date(data.fields.duedate)); } issueData.hasAttachment = data.fields.attachment.length > 0; issueData.storyPoints = data.fields.storyPoints; if (data.fields.parent) { promises.push(module.getIssueData(data.fields.parent.key).then(function(data) { issueData.superIssue = {}; issueData.superIssue.key = data.key; issueData.superIssue.summary = data.fields.summary; })); } else if (data.fields.epicLink) { promises.push(module.getIssueData(data.fields.epicLink).then(function(data) { issueData.superIssue = {}; issueData.superIssue.key = data.key; issueData.superIssue.summary = data.fields.epicName; })); } issueData.url = window.location.origin + "/browse/" + issueData.key; //LRS Specific field mapping if (true) { //Desired-Date if (data.fields.desiredDate) { issueData.dueDate = formatDate(new Date(data.fields.desiredDate)); } } return Promise.all(promises); })); return Promise.all(promises).then(function(results){return issueData;}); }; module.getIssueData = function(issueKey) { //https://docs.atlassian.com/jira/REST/latest/ var url = '/rest/api/2/issue/' + issueKey + '?expand=renderedFields,names'; console.log("IssueUrl: " + url); //console.log("Issue: " + issueKey + " Loading..."); return httpGetJSON(url).then(function(responseData) { //console.log("Issue: " + issueKey + " Loaded!"); // add custom fields with field names jQuery.each(responseData.names, function(key, value) { if (key.startsWith("customfield_")) { var fieldName = value.toCamelCase(); //console.log("add new field: " + fieldName + " with value from " + key); responseData.fields[fieldName] = responseData.fields[key]; } }); return responseData; }); }; return module; }({})); var youTrackFunctions = (function(module) { module.getSelectedIssueKeyList = function() { //Detail View if (/.*\/issue\/.*/g.test(document.URL)) { return [document.URL.replace(/.*\/issue\/([^?]*).*/, '$1')]; } // Agile Board if (/.*\/rest\/agile.*/g.test(document.URL)) { return jQuery('div.sb-task-focused').map(function() { return jQuery(this).attr('id'); }); } return []; }; module.getCardData = function(issueKey) { var promises = []; var issueData = {}; promises.push(module.getIssueData(issueKey).then(function(data) { issueData.key = data.id; issueData.type = data.field.type[0]; issueData.summary = data.field.summary; issueData.description = data.field.description; if (data.field.assignee) { issueData.assignee = data.field.assignee[0].fullName; } if (data.field.attachments) { issueData.hasAttachment = data.field.attachments.length > 0; } issueData.url = window.location.origin + "/youtrack/issue/" + issueData.key; })); return Promise.all(promises).then(function(results){return issueData;}); }; module.getIssueData = function(issueKey) { var url = '/youtrack/rest/issue/' + issueKey + '?'; console.log("IssueUrl: " + url); //console.log("Issue: " + issueKey + " Loading..."); return httpGetJSON(url).then(function(responseData) { //console.log("Issue: " + issueKey + " Loaded!"); jQuery.each(responseData.field, function(key, value) { // add fields with field names var fieldName = value.name.toCamelCase(); //console.log("add new field: " + newFieldId + " with value from " + fieldName); responseData.field[fieldName] = value.value; }); return responseData; }); }; return module; }({})); var pivotalTrackerFunctions = (function(module) { module.getSelectedIssueKeyList = function() { //Single Story if (/.*\/stories\/.*/g.test(document.URL)) { return [document.URL.replace(/.*\/stories\/([^?]*).*/, '$1')]; } // Board if (/.*\/projects\/.*/g.test(document.URL)) { return jQuery('.story[data-id]:has(.selected)').map(function() { return jQuery(this).attr('data-id'); }); } return []; }; module.getCardData = function(issueKey) { var promises = []; var issueData = {}; promises.push(module.getIssueData(issueKey).then(function(data) { issueData.key = data.id; issueData.type = data.kind.toLowerCase(); issueData.summary = data.name; issueData.description = data.description; if (data.owned_by && data.owned_by.length > 0) { issueData.assignee = data.owner_ids[0].name; } if (data.deadline) { issueData.dueDate = formatDate(new Date(data.deadline)); } // TODO issueData.hasAttachment = false; issueData.storyPoints = data.estimate; issueData.url = data.url; })); return Promise.all(promises).then(function(results){return issueData;}); }; module.getIssueData = function(issueKey) { //http://www.pivotaltracker.com/help/api var url = 'https://www.pivotaltracker.com/services/v5/stories/' + issueKey + "?fields=name,kind,description,story_type,owned_by(name),comments(file_attachments(kind)),estimate,deadline"; console.log("IssueUrl: " + url); //console.log("Issue: " + issueKey + " Loading..."); return httpGetJSON(url); }; return module; }({})); var trelloFunctions = (function(module) { module.getSelectedIssueKeyList = function() { //Card View if (/.*\/c\/.*/g.test(document.URL)) { return [document.URL.replace(/.*\/c\/([^/]*).*/g, '$1')]; } return []; }; module.getCardData = function(issueKey, callback) { var promises = []; var issueData = {}; promises.push(module.getIssueData(issueKey).then(function(data) { issueData.key = data.idShort; // TODO get kind from label name // issueData.type = data.kind.toLowerCase(); issueData.summary = data.name; issueData.description = data.desc; if (data.members && data.members.length > 0) { issueData.assignee = data.members[0].fullName; issueData.avatarUrl = "https://trello-avatars.s3.amazonaws.com/" + data.members[0].avatarHash + "/170.png"; } if (data.due) { issueData.dueDate = formatDate(new Date(data.due)); } issueData.hasAttachment = data.attachments > 0; issueData.url = data.shortUrl; })); return Promise.all(promises).then(function(results){return issueData;}); }; module.getIssueData = function(issueKey) { var url = "https://trello.com/1/cards/" + issueKey + "?members=true"; console.log("IssueUrl: " + url); //console.log("Issue: " + issueKey + " Loading..."); return httpGetJSON(url); }; return module; }({})); })();