2 // @name ADS changeset comment search
4 // @description Places a searchbox somewhere to search commit messages
5 // @author Tobias Sachs
6 // @match https://ads/*
8 // @updateURL https://src.twobees.de/?p=tampermonkeyscripts.git;a=blob_plain;f=AzureDevOpsChangesetCommentSearch.js;hb=HEAD
9 // @downloadURL https://src.twobees.de/?p=tampermonkeyscripts.git;a=blob_plain;f=AzureDevOpsChangesetCommentSearch.js;hb=HEAD
12 // 0.5: - fix size of search box
13 // 0.4: - improve position of search box
14 // 0.3: - fix abort search
15 // - filter reuslts by committers name
16 // - no need for an observer
17 // - use GM_addStyle to improve readability
18 // - "Escape" stops search and removes resultstab
20 /* jshint esversion:6 */
24 let searchDelayTimerId;
25 let pollUrl = 'https://ads/HeBa/Entwicklung/_apis/tfvc/changesets?maxCommentLength=500?$top=1000?searchCriteria.itemPath=$/Entwicklung/HEAD';
26 let skipParm = '&$skip=';
27 let changeSetUrl = `/HeBa/Entwicklung/_versionControl/changeset/`;
29 let totalReceived = 0;
33 GM_addStyle(`#ts_cs_search {
39 transform: translateX(-50%);
41 GM_addStyle(`.ts_match {
44 GM_addStyle(`.ts_found {
47 GM_addStyle(`.ts_found a {
48 text-decoration: none;
50 GM_addStyle(`#ts_searchResults{
56 let searchDelayed = function(){
57 if (searchDelayTimerId) {
58 clearTimeout(searchDelayTimerId);
61 searchDelayTimerId = setTimeout(
63 searchDelayTimerId = undefined;
69 let pressEscapeToAbort = function(e) {
70 if (e.key == "Escape"){
71 document.getElementById('ts_searchBox').value = "";
72 startSearching(); // will abort search and clean results
76 let requestNext = function(skipCnt, currentSearch){
77 let xhr = new XMLHttpRequest();
78 xhr.onload = () => searchItems(xhr, currentSearch);
79 xhr.onerror = function (e){
80 console.warning(`poll error: ${e.type}: ${e.loaded} bytes transferred\n` + JSON.stringify(e));
82 xhr.open('GET', pollUrl + skipParm + skipCnt, true);
86 let searchItems = function(xhr, searchStr){
87 if (xhr.status !== 200){
88 console.info("poll failed: " + xhr.statusText);
92 if (searchStr !== searchTerm)
94 console.info("Searchterm changed while searching to " + searchTerm);
98 let sp = searchStr.split(/(von:|from:)/i);
99 let searchName = undefined;
100 let search = searchStr;
102 search = sp[0].trim();
103 searchName = sp[2].trim();
106 let resultDiv = document.getElementById('ts_searchResults');
107 let statsSpan = document.getElementById('ts_searchStats');
109 var d = JSON.parse(xhr.responseText);
110 let regex = undefined;
111 let regexAuthor = undefined;
113 regex = new RegExp("("+search+")", 'gi');
116 regexAuthor = new RegExp("("+searchName+")", 'i');
118 totalReceived += d.value.length;
119 for (let e in d.value){
121 if (regex !== undefined && regexAuthor !== undefined)
123 if (!(cs.comment && regex.test(cs.comment) && regexAuthor.test(cs.author.displayName)))
131 (cs.comment && regex !== undefined && regex.test(cs.comment))
132 || (regexAuthor !== undefined && regexAuthor.test(cs.author.displayName))
141 comment = cs.comment.replace(regex, `<span class="ts_match">$1</span>`);
145 comment = cs.comment;
148 author = cs.author.displayName.replace(regexAuthor, `<span class="ts_match">$1</span>`);
151 author = cs.author.displayName;
155 let item = `<div class='ts_found'>
156 <a href='${changeSetUrl}${cs.changesetId}'>
157 ${cs.changesetId}: ${comment} (${author})
160 resultDiv.innerHTML += item;
162 statsSpan.innerHTML = "matches: " + matchesFound +" searched comments: " + totalReceived;
163 if (d.value.length <= 0)
165 statsSpan.innerHTML += " -- search done.";
169 requestNext(totalReceived, searchStr);
172 let startSearching = function (){
173 searchTerm = document.getElementById('ts_searchBox').value;
174 let results = document.getElementById('ts_searchResults');
177 results.innerHTML = "";
178 document.getElementById('ts_searchStats').innerHTML = "";
180 if (searchTerm.length < 3){ return; }
182 console.debug("new search term: '" + searchTerm+"'");
183 requestNext(0, searchTerm);
186 let addSearch = () => {
187 if (window.location.href.includes("_apis")){ return; }
189 let search = document.getElementById('ts_cs_search');
190 if (search){ return; }
192 console.debug("adding searchbox");
193 let html = `<div id="ts_cs_search">
194 <input id="ts_searchBox" style="width: 200px;" placeholder="searchstring [von:Name]" />
195 <span id="ts_searchStats"></span>
196 <div id="ts_searchResults"></div>
199 document.body.insertAdjacentHTML('afterbegin', html);
200 let s = document.getElementById('ts_searchBox');
201 s.addEventListener("keyup", searchDelayed);
202 document.body.addEventListener("keyup", pressEscapeToAbort);