Azure DevOps Zendesk Link latest version (currently v1.2.1)

← Back to User Scripts

Script Content

// ==UserScript==
// @name         Azure DevOps Zendesk Link
// @namespace    https://github.com/tjhleeds/user-scripts/
// @version      1.2.1
// @description  Adds a button to Azure DevOps work items to open the corresponding Zendesk ticket.
// @author       tjhleeds using Jules
// @match        https://dev.azure.com/*
// @match        https://*.visualstudio.com/*
// @grant        GM_openInTab
// @grant        GM_addStyle
// ==/UserScript==

(function() {
    'use strict';

    console.log('Zendesk Link script started');

    const zendeskRegex = /\[Zendesk (\d+)\]/;
    const zendeskIconSvg = `
            
               
               
            
        `;

    function addButtonToTitle(titleElement) {
        console.log('addButtonToTitle called');
        const match = titleElement.value.match(zendeskRegex);
        if (!match) {
            console.log('No Zendesk link found in title');
            return;
        }

        const zendeskId = match[1];
        const zendeskUrl = `https://audacia.zendesk.com/agent/tickets/${zendeskId}`;

        // Check if button already exists
        if (document.getElementById('zendesk-link-button')) {
            console.log('Zendesk link button already exists');
            return;
        }

        console.log(`Zendesk ticket ${zendeskId} found, adding button`);

        const button = document.createElement('button');
        button.id = 'zendesk-link-button';
        button.innerHTML = zendeskIconSvg;
        button.onclick = () => {
            GM_openInTab(zendeskUrl, { active: true });
        };

        const titleElementParent = titleElement.parentElement;
        titleElementParent.style.position = 'relative';

        // Add padding to the title element to make space for the button
        titleElement.style.paddingLeft = '40px';

        GM_addStyle(`
            #zendesk-link-button {
                position: absolute;
                left: 0px;
                top: 50%;
                transform: translateY(-50%);
                width: 34px;
                height: 34px;
                z-index: 1000;
                border: none;
                background: transparent;
                cursor: pointer;
                padding: 3px;
            }
            #zendesk-link-button svg {
                width: 100%;
                height: 100%;
            }
        `);

        titleElementParent.appendChild(button);
        console.log('Zendesk link button added');
    }

    function addZendeskLinkToInlineItem(inlineLinkElement) {
        console.log('addZendeskLinkToInlineItem called');
        const wiData = JSON.parse(inlineLinkElement.dataset.wi);
        const title = wiData[0].title;
        const match = title.match(zendeskRegex);

        if (!match) {
            console.log('No Zendesk link found in inline item title');
            return;
        }

        inlineLinkElement.dataset.zendeskLinkAdded = 'true';

        const zendeskId = match[1];
        const zendeskUrl = `https://audacia.zendesk.com/agent/tickets/${zendeskId}`;

        console.log(`Zendesk ticket ${zendeskId} found, adding link`);

        const zendeskLink = document.createElement('a');
        zendeskLink.href = zendeskUrl;
        zendeskLink.target = '_blank';
        zendeskLink.innerHTML = zendeskIconSvg;
        zendeskLink.classList.add('zendesk-inline-link');

        inlineLinkElement.before(zendeskLink);
    }


    const observer = new MutationObserver(() => {
        console.log('Mutation observer triggered');
        const titleElement = document.querySelector('[aria-label="Title field"]');
        if (titleElement) {
            addButtonToTitle(titleElement);
        } else {
            console.log('Title element not found');
        }

        const inlineLinks = document.querySelectorAll('a[data-wi]:not([data-zendesk-link-added])');
        inlineLinks.forEach(addZendeskLinkToInlineItem);
    });

    GM_addStyle(`
        .zendesk-inline-link {
            display: inline-block;
            width: 16px;
            height: 16px;
            margin-right: 4px;
            vertical-align: middle;
        }
        .zendesk-inline-link svg {
            width: 100%;
            height: 100%;
        }
    `);

    console.log('Observing document for mutations');
    observer.observe(document, {
        childList: true,
        subtree: true
    });
})();