您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Filter pull Requests in Azure DevOps by tags
// ==UserScript== // @name Azure DevOps Pull Request Filter // @namespace https://github.com/calne-ca // @version 0.2.1 // @description Filter pull Requests in Azure DevOps by tags // @author Joscha Düringer // @license MIT // @supportURL https://github.com/calne-ca/tampermonkey-azure-devops-pull-request-tag-filter // @match https://dev.azure.com/*/pullrequests* // @icon https://www.google.com/s2/favicons?domain=dev.azure.com // @grant none // ==/UserScript== function removePullRequest(pullRequest){ console.log("Removing pull request: " + pullRequest); pullRequest.remove(); } function adjustRowSpacers() { const rowSpacers = document.getElementsByClassName('bolt-list-cell-spacer'); for(const rowSpacer of rowSpacers){ rowSpacer.style.height = 0; } } function stringMatchesFilter(str, filter) { return filter.some(filterStr=> new RegExp("^" + filterStr + "$").test(str)); } function pullRequestHasMatchingTag(pullRequest, filteredTags, showUntagged) { if(filteredTags.length === 0) { return true; } const labels = pullRequest.querySelectorAll('.bolt-pill-overflow .text-ellipsis'); const pullRequestLabels = [] if(labels.length === 0 && showUntagged) { return true; } for (const label of labels) { pullRequestLabels.push(label.textContent); } return pullRequestLabels.some(tag=> stringMatchesFilter(tag, filteredTags)); } function pullRequestHasMatchingTitle(pullRequest, filteredTitles) { if(filteredTitles.length === 0){ return true; } const title = pullRequest.querySelector('.body-l').textContent; return stringMatchesFilter(title, filteredTitles); } function pullRequestHasAssignee(pullRequest){ const assignees = pullRequest.querySelectorAll('.bolt-table-cell-content .flex-center img'); return assignees.length > 0; } function pullRequestShouldBeRemoved(pullRequest, filteredTags, showUntagged, filteredTitles, unassignedOnly) { return !pullRequestHasMatchingTag(pullRequest, filteredTags, showUntagged) || !pullRequestHasMatchingTitle(pullRequest, filteredTitles) || (unassignedOnly && pullRequestHasAssignee(pullRequest)); } function filterPullRequests(pullRequests, filteredTags, showUntagged, filteredTitles, unassignedOnly){ for (const pullRequest of pullRequests) { if (pullRequestShouldBeRemoved(pullRequest, filteredTags, showUntagged, filteredTitles, unassignedOnly)) { removePullRequest(pullRequest) } } adjustRowSpacers(); } (function() { 'use strict'; const urlParams = new URLSearchParams(window.location.search); const tagFilterParam = urlParams.get('tagFilter'); const titleFilterParam = urlParams.get('titleFilter'); const showUntaggedParam = urlParams.get('showUntagged'); const unassignedOnlyParam = urlParams.get('unassignedOnly'); const refreshInterval = 200; const filteredTags = tagFilterParam ? tagFilterParam.split(',') : []; const filteredTitles = titleFilterParam ? titleFilterParam.split(',') : []; const showUntagged = showUntaggedParam === 'true' const unassignedOnly = unassignedOnlyParam === 'true' if(filteredTags.length === 0 && filteredTitles.length === 0 && !unassignedOnly) { return; } console.log("Filtering pull requests with filteredTags='" + filteredTags + "', showUntagged='" + showUntagged + "', filteredTitles='" + filteredTitles + "', unassignedOnly='" + unassignedOnly + "'"); setInterval(function() { const path = window.location.pathname.replace(/\/$/, ""); if(!path.endsWith('pullrequests')) { return; } const pullRequests = document.getElementsByClassName('bolt-list-row'); if (pullRequests) { filterPullRequests(pullRequests, filteredTags, showUntagged, filteredTitles, unassignedOnly); } }, refreshInterval); })();