// // Create a copy-pastable list of issuetitle + links. Easy for in Slack, Powerpoint // Create a copy-pastable list of HTML-tablerows for testscenarios which can be used in Confluence or any othe HTML page. // // click on Backlog-header to open a new tab with the name + link of each issues // @author Oebe, Stefan, Leroy, Rinki, Vlad, Javad // // =========== configuration : start =============== // Show the amount of Story Point on the Active Sprints board aka scrumboard var bShowStoryPointsOnScrumboard = true; // Adjust the sizes of the columns on the Active Sprints board aka scrumboard var bAdjustColumnSizesOnScrumboard = true; // Hide Done subtasks above threshold amount var doneSubtasksLimit = 5; /* Test Sceanrios feature ======= */ // Show HTML for Test Scenarios when clicking on Show copyable list var bShowTestScenarios = true; // Add rows for browsertest in the Test Scenarios (set to false for backend-teams) var bAddBrowserchecksInTestScenarios = false; // set columnheaders in the Test Scenarios var colHeader1 = 'Test user(s) /
Test data'; var colHeader2 = 'Scenario/ steps to execute'; var colHeader3 = 'Expected result'; var colHeader4 = 'Actual result'; var colHeader5 = 'Remarks'; // Fill in jiraServerId for Confluence macros to JIRA stories // You can get this ID by looking into the source of a confluence page while you added a JIRA marcro in that page, or ask your admin: https://confluence.atlassian.com/adminjiraserver/finding-your-server-id-938847652.html var jiraServerId = ''; var jiraLicense = 'server'; // server or cloud // =========== configuration : end =============== var timer; function AddBacklogFunctionalities() { if (jiraLicense == 'server') { $('.ghx-mode-planning .js-quickfilter-selector').append('| Show copyable list'); } else { $('.ghx-mode-planning #ghx-quick-filters > ul').append('
  • Show copyable list
  • '); } // add Collapse Done Only button (if it isnt in there already) if ($('.ghx-column:nth-last-child(1) .ghx-column-title:contains("Collapse Done only")').length === 0) { $('.ghx-column:nth-last-child(1) .ghx-column-title').append(' Collapse Done only'); // when clicked on "Collapse Done Only" button $('.collapseDoneBtn').on('click', function () { // loop all stories and expand them all first $( ".ghx-swimlane.ghx-closed" ).each(function( index, val ) { // collapse all $( this ).find(".js-expander").click(); // ps we're using the .click() here because JIRA has some internal logic connected to it, like storing the setting in memory and localStorage. }); // then collapse the Done ones $( ".ghx-swimlane" ).each(function( index, val ) { var story = $( this ) // find story status var storyStatus = story.find(".jira-issue-status-lozenge").text(); // Close Done ones if (storyStatus == 'Done') { $( this ).find(".js-expander").click(); } }); }); } // when clicked on "Show copyable list"-button $('.showCopyableListButton').on('click', function () { var jsonDescription = {}; var counter = 0; // if no issue selected: select all from sprint if ($( ".js-issue-list .ghx-selected" ).length === 0) { $( ".ghx-sprint-group .js-issue" ).addClass('ghx-selected'); } // loop all selected stories $( ".js-issue-list .ghx-selected" ).each(function( index) { var listlength = $( ".js-issue-list .ghx-selected" ).length; var storyId = $( this ).attr('data-issue-key'); var urlParams = new URLSearchParams(window.location.search); var rapidViewId = urlParams.get('rapidView'); // get story information $.getJSON( "../rest/greenhopper/1.0/xboard/issue/details.json?rapidViewId=" + rapidViewId + "&issueIdOrKey=" + storyId, function( data ) { // get Description if (data) jsonDescription[storyId] = data.tabs.defaultTabs[2].sections[0].html; counter++; // only render text if all async processes are done if (counter == listlength) { RenderText (jsonDescription); } }); }); }); } function AddSprintBacklogFunctionalities() { if (bAdjustColumnSizesOnScrumboard) { // specific column width for 4 or 5 columns scrumboard var iAmountOfColumns = $( "#ghx-column-header-group .ghx-column").length; if (iAmountOfColumns == 5 ) { // no changes (yet) } else { // wide - small - small - wide (more space in columns that often have a lot of stories) var gridtemplatecolumns = "33% 16% 16% 33%"; $( "#ghx-rabid #ghx-work #ghx-pool-column .ghx-columns, #ghx-rabid #ghx-work #ghx-pool-column #ghx-column-headers, #ghx-rabid #ghx-work #ghx-pool-column .ghx-zone-overlay-table" ).css("grid-template-columns", gridtemplatecolumns); } } // loop all stories and add SPs to titles if (bShowStoryPointsOnScrumboard) { $( ".ghx-swimlane" ).each(function( index, val ) { var storyId = $( this ).find(".ghx-parent-key").text(); if (!storyId) { return true; } // get SPs var storySP; var storyTitle = $( this ).find('.ghx-swimlane-header .ghx-summary'); var urlParams = new URLSearchParams(window.location.search); var rapidViewId = urlParams.get('rapidView'); // get story information $.getJSON( "../rest/greenhopper/1.0/xboard/issue/details.json?rapidViewId=" + rapidViewId + "&issueIdOrKey=" + storyId, function( data ) { // get SPs if (data) storySP = data.tabs.defaultTabs[0].fields[2].value; var storyHtml = storyTitle.html(); // add SPs to title (if it isnt in there already) if (storyHtml.indexOf('storyEstimation') === -1) { if (typeof storySP == "undefined") { storyTitle.html(storyTitle.html() + ' unestimated'); } else { storyTitle.html(storyTitle.html() + ' ' + storySP + ' SP'); } } }); }); } } function appendLink() { /* @todo add toggle based on url */ AddBacklogFunctionalities(); AddSprintBacklogFunctionalities(); } function htmlEntities(str) { return String(str).replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"'); } function RenderText (description) { var copyTextAndLink = ''; var copyTextPresentation = ''; var copyTextTitles = ''; var copyTextTestScenarioTable = ''; var copyTextLarge = ''; var copyTextSlack = ''; $( ".js-issue-list .ghx-selected" ).each(function( index ) { var storyTitle = $( this ).find('.ghx-summary').text(); var escapedStoryTitle = storyTitle.replace(/&/g, "&").replace(//g, ">"); var storyId = $( this ).attr('data-issue-key'); var storyType = $( this ).find('.ghx-type').attr('title'); var storyPoints = $( this ).find('.ghx-statistic-badge').text(); // get url to issue const parsedUrl = new URL(window.location.href); var pUrl = parsedUrl.origin + parsedUrl.pathname; var urlSplit = pUrl.split('/'); urlSplit.pop(); var urlWithoutLastPart = urlSplit.join("/"); var storyLink = urlWithoutLastPart.replace(/secure/g, "browse/") + storyId; // for POs copy-paste into Slack copyTextAndLink += storyTitle; copyTextAndLink += "
    "; copyTextAndLink += storyLink; copyTextAndLink += "
    "; // for POs copy-paste into Slack copyTextSlack += ''; copyTextSlack += storyId + ' - ' + storyTitle + " (" + storyPoints + ")"; copyTextSlack += ""; copyTextSlack += "
    "; // for SMs (for Powerpoint presentation) copyTextPresentation += ''+storyTitle + ''; copyTextPresentation += "
    "; copyTextPresentation += storyId + ' (' + storyPoints + ' SP) - ' ; copyTextPresentation += "
    "; // for SMs (for printed stories - JIRA has an option for this as well) copyTextLarge += '

    '+storyTitle + '

    '; copyTextLarge += '

    ' + storyId + ' ' + storyPoints + ' SP

    ' ; copyTextLarge += "


    "; // for POs copy-paste clean list copyTextTitles += storyTitle; copyTextTitles += "
    "; // for Testers (for Confluence page) copyTextTestScenarioTable += '

    '+storyId+' - '+escapedStoryTitle+'

    \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ '; if (bAddBrowserchecksInTestScenarios) { copyTextTestScenarioTable += '\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ '; } copyTextTestScenarioTable += '
    \
    \

    \ \ JIRA\ '+jiraServerId+'\ '+storyId+'\ \

    \
    \
    '+colHeader1+''+colHeader2+''+colHeader3+''+colHeader4+' \ \ Not completed\ \ '+colHeader5+'

    '+description[storyId]+'








    \ Check all the above scenarios in below browsers for a desktop:
    \ - IE11 (not supported, but tested for awareness)
    \ - Edge
    \ - Firefox
    \ - Mac Safari
    \
    All test scenarios must look good in these browsers, devices.


    \ Check all the above scenarios in below browsers for a Android mobile devices:
    \ - iPad Air 2/ iPad 2017, Safari, landscape
    \ - iPad Air 2/ iPad 2017, Safari, portrait \
    All test scenarios must look good in these browsers, devices.


    \ Check all the above scenarios in below browsers for a iOS mobile devices:
    \ - iPhone 8, Safari, iOS11, portrait
    \ - iPhone 8, Safari, iOS11, landscape\
    All test scenarios must look good in these browsers, devices.


    \ Check the 3 languages:
    \ - English
    \ - Dutch
    \ - French\
    Languages must be correct on the web page.


    Check in PDF\ Changes must be correct and in sync with PDF in all languages \

    ' + 'newtablerow'; }); // each : end copyTextTestScenarioTable = escapeHtml(copyTextTestScenarioTable) // make the source a bit readable copyTextTestScenarioTable = copyTextTestScenarioTable.replace(/newtablerow/g, "
    "); var copyTextAll = 'CHAT/MESSAGING (that dont accept links)

    ' + copyTextAndLink + '

    CHAT/MESSAGING/SLACK

    ' + copyTextSlack + '

    PRESENTATIONS

    ' + copyTextPresentation + '


    ' + copyTextTitles; // show output in separate tab(s) if (bShowTestScenarios) { // separate tab for easier copy-pasting window.open('about:blank').document.body.innerHTML = '<!-- start test scenario HTML -->
    ' + copyTextTestScenarioTable; } window.open('about:blank').document.body.innerHTML = copyTextAll; } function escapeHtml(text) { var map = { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }; return text.replace(/[&<>"']/g, function(m) { return map[m]; }); } function hideSomeSubtasks() { // Hide Done subtasks above threshold amount $('.ghx-columns').find('.ghx-column:last').each(function (index) { var issues = $(this).find('.ghx-issue'); var doneCount = issues.length; if(doneCount > doneSubtasksLimit) { var showButton = issues.eq(doneSubtasksLimit).clone(); showButton.addClass('showMoreSubtasks'); showButton.html('Show more (+' + (doneCount - doneSubtasksLimit) + ')'); $(this).append(showButton); showButton.on('click', function(){ $(this).hide().parent().find('.hiddenSubtask').show(); }) issues.each(function(index){ if(index >= doneSubtasksLimit) $(this).addClass('hiddenSubtask').hide(); }) } }) } (function () { // wait 2 secs for the navbar / header to popup setTimeout(function() { $('.aui-nav-item').on('click', function () { // click on Backlog view button //if ($.contains(this, $('.agile-icon-plan').get(0))) { setTimeout(function () { appendLink(); }, 1200); // } }); // Reinitiate after a click on the 3rd cell of the (Review?)table header of scrum board (workaround for SPs dissappearing after moving a subtask) $(document).on('click', '.ghx-column:nth-child(3) .ghx-column-title', function (e) { clearTimeout(timer); timer = setTimeout(function() { appendLink(); }, 500) }) // change of Quick filter or Release/Epic $(document).on('click', '.js-quickfilter-button, .ghx-classification-item', function (e) { clearTimeout(timer); timer = setTimeout(function() { appendLink(); }, 2000) }) // change of search-filter (at left side of Quick filters) $(document).on('blur', '#ghx-backlog-search-input', function (e) { clearTimeout(timer); timer = setTimeout(function() { appendLink(); }, 2000) }) // Make all ticket links open in a new tab $(document).on('click', 'a.js-detailview, a.js-key-link', function(e) { var href = $(this).attr('href'); if (href) { window.open(href, '_blank'); e.stopPropagation(); } } ); // reinitiate after moving an issue var mouseouttimer; $(document).on('mouseout', '.ghx-issue', function (e) { console.log('move') clearTimeout(mouseouttimer); mouseouttimer = setTimeout(function() { appendLink(); }, 2000) }) hideSomeSubtasks(); appendLink(); }, 2000); // wait for ajax-list to be loaded.. if link fails to show: increase amount here })();