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.4: - improve position of search box
13 // 0.3: - fix abort search
14 // - filter reuslts by committers name
15 // - no need for an observer
16 // - use GM_addStyle to improve readability
17 // - "Escape" stops search and removes resultstab
19 /* jshint esversion:6 */
23 let searchDelayTimerId;
24 let pollUrl = 'https://ads/HeBa/Entwicklung/_apis/tfvc/changesets?maxCommentLength=500?$top=1000?searchCriteria.itemPath=$/Entwicklung/HEAD';
25 let skipParm = '&$skip=';
26 let changeSetUrl = `/HeBa/Entwicklung/_versionControl/changeset/`;
28 let totalReceived = 0;
32 GM_addStyle(`#ts_cs_search {
38 transform: translateX(-50%);
40 GM_addStyle(`.ts_match {
43 GM_addStyle(`.ts_found {
46 GM_addStyle(`.ts_found a {
47 text-decoration: none;
49 GM_addStyle(`#ts_searchResults{
55 let searchDelayed = function(){
56 if (searchDelayTimerId) {
57 clearTimeout(searchDelayTimerId);
60 searchDelayTimerId = setTimeout(
62 searchDelayTimerId = undefined;
68 let pressEscapeToAbort = function(e) {
69 if (e.key == "Escape"){
70 document.getElementById('ts_searchBox').value = "";
71 startSearching(); // will abort search and clean results
75 let requestNext = function(skipCnt, currentSearch){
76 let xhr = new XMLHttpRequest();
77 xhr.onload = () => searchItems(xhr, currentSearch);
78 xhr.onerror = function (e){
79 console.warning(`poll error: ${e.type}: ${e.loaded} bytes transferred\n` + JSON.stringify(e));
81 xhr.open('GET', pollUrl + skipParm + skipCnt, true);
85 let searchItems = function(xhr, searchStr){
86 if (xhr.status !== 200){
87 console.info("poll failed: " + xhr.statusText);
91 if (searchStr !== searchTerm)
93 console.info("Searchterm changed while searching to " + searchTerm);
97 let sp = searchStr.split(/(von:|from:)/i);
98 let searchName = undefined;
99 let search = searchStr;
101 search = sp[0].trim();
102 searchName = sp[2].trim();
105 let resultDiv = document.getElementById('ts_searchResults');
106 let statsSpan = document.getElementById('ts_searchStats');
108 var d = JSON.parse(xhr.responseText);
109 let regex = undefined;
110 let regexAuthor = undefined;
112 regex = new RegExp("("+search+")", 'gi');
115 regexAuthor = new RegExp("("+searchName+")", 'i');
117 totalReceived += d.value.length;
118 for (let e in d.value){
120 if (regex !== undefined && regexAuthor !== undefined)
122 if (!(cs.comment && regex.test(cs.comment) && regexAuthor.test(cs.author.displayName)))
130 (cs.comment && regex !== undefined && regex.test(cs.comment))
131 || (regexAuthor !== undefined && regexAuthor.test(cs.author.displayName))
140 comment = cs.comment.replace(regex, `<span class="ts_match">$1</span>`);
144 comment = cs.comment;
147 author = cs.author.displayName.replace(regexAuthor, `<span class="ts_match">$1</span>`);
150 author = cs.author.displayName;
154 let item = `<div class='ts_found'>
155 <a href='${changeSetUrl}${cs.changesetId}'>
156 ${cs.changesetId}: ${comment} (${author})
159 resultDiv.innerHTML += item;
161 statsSpan.innerHTML = "matches: " + matchesFound +" searched comments: " + totalReceived;
162 if (d.value.length <= 0)
164 statsSpan.innerHTML += " -- search done.";
168 requestNext(totalReceived, searchStr);
171 let startSearching = function (){
172 searchTerm = document.getElementById('ts_searchBox').value;
173 let results = document.getElementById('ts_searchResults');
176 results.innerHTML = "";
177 document.getElementById('ts_searchStats').innerHTML = "";
179 if (searchTerm.length < 3){ return; }
181 console.debug("new search term: '" + searchTerm+"'");
182 requestNext(0, searchTerm);
185 let addSearch = () => {
186 if (window.location.href.includes("_apis")){ return; }
188 let search = document.getElementById('ts_cs_search');
189 if (search){ return; }
191 console.debug("adding searchbox");
192 let html = `<div id="ts_cs_search">
193 <input id="ts_searchBox" placeholder="searchstring [von:Name]" />
194 <span id="ts_searchStats"></span>
195 <div id="ts_searchResults"></div>
198 document.body.insertAdjacentHTML('afterbegin', html);
199 let s = document.getElementById('ts_searchBox');
200 s.addEventListener("keyup", searchDelayed);
201 document.body.addEventListener("keyup", pressEscapeToAbort);