Fixlet Remediation History By Computer Name

@jvandenheuvel, is it not the link that is right above your post?

I must have downloaded an older version of the report or something as it wasn’t working. When I downloaded that version from your most recent post it is working. Thank you very much.

Is there any way to add the operator that performed the action and the fixlet source release date to this report?

I’m new to BigFix and using it for patching now in our environment. I’m also looking for similar detailed patching information to show which fixlets were installed on Server-X and when they were installed. Was this report ever identified that I could take advantage of? I see other links posted in this forum but I can’t seem to access them. The page shows it either doesn’t exist or is marked private.

Hi Leewei,

I downloaded the Fixlet Remediation History by computer name but its not working.
Please lok to the snapshot.After clicking on generate report nothing comes out.

Please help me out.

Thanks,
Vineet Kumar

A post was split to a new topic: Remediated Fixlets by Computer report?

You need to edit some of the code in the report. I think it says “Patches for Windows (English)”, but you need to change that to reference the new site name of just “Patches for Windows”.

Good luck.

@leewei We unfortunately are running into the same issue where no results are being returned. We attempted to update the code in the report from “Patches for Windows (English)” to “Patches for Windows” but it did not alleviate the issue. Perhaps someone can see something we are missing that needs to be amended? We are running on Bigfix 10.0.1.41

Fixlet Fix Date by Computer Group with Date and Fixlet Name Search
Please see the BigFix Forum for information on this report
http://forum.bigfix.com/viewtopic.php?pid=16225#p16225
-->
<style type="text/css">
	a {
	text-decoration: none;
	}
    
	a:hover {
	color: #FF8000;
	font-weight: bold;
	text-decoration: none;
	}
    
	table.sortable {
	margin: 0;
	border-collapse: collapse;
	color: #222;
	font: 10pt verdana, geneva, lucida, 'lucida grande', arial, helvetica, sans-serif;
	}
	
	th.res {
	font: 10pt verdana, geneva, lucida, 'lucida grande', arial, helvetica, sans-serif;
	color: navy;
	font-weight: bold;
	background-color: #F2F2F2;
	border: 1px solid #cccccc;
	margin: 0;
	padding: 4px 10px 4px 5px;          
	text-align: left;
	} 
    
	td.res {
	color: #222;
	font: 8pt verdana, geneva, lucida, 'lucida grande', arial, helvetica, sans-serif;
	border-bottom: 1px solid #cccccc;
	margin: 0;
	/* padding: 6px 20px 1px 0;  */
	padding: 8px 20px 5px 5px;
	}
    
	td.userinput {
	color: #222;
	font: 10pt verdana, geneva, lucida, 'lucida grande', arial, helvetica, sans-serif;
	font-weight: bold;
	border-bottom: 0px;
	margin: 0;
	padding: 6px 20px 1px 0;
	} 
    
	td.errormsg {
	color: red;
	font: 10pt verdana, geneva, lucida, 'lucida grande', arial, helvetica, sans-serif;
	font-weight: bold;
	border-bottom: 0px;
	margin: 0;
	padding: 6px 20px 1px 0;
	}
	td.msg {
	color: #747170;
	font: 10pt verdana, geneva, lucida, 'lucida grande', arial, helvetica, sans-serif;
	font-weight: bold;
	border-bottom: 0px;
	margin: 0;
	padding: 6px 20px 1px 0;
	}
    
	h3 {
	font: 10pt verdana, geneva, lucida, 'lucida grande', arial, helvetica, sans-serif;
	background-color: #747170;
	padding: 4px 4px 4px 4px;
	color: white;
	width: 100%;
	}
	
	#CalendarControlIFrame {
	display: none;
	left: 0px;
	position: absolute;
	top: 0px;
	height: 250px;
	width: 250px;
	z-index: 99;
	}
	table.date
	{text-align: center;
	font-family: Verdana, Geneva, Arial, Helvetica, sans-serif ;
	font-weight: normal;
	font-size: 14px;
	color: #fff;
	width: 400px;
	background-color: #777;
	border: 0px;
	border-collapse: collapse;
	border-spacing: 0px;}
	
	table.date td.dateleft
	{background-color: #CCC;
	color: #000;
	padding: 4px;
	text-align: right;
	border: 0px;}
	table.date td.dateright
	{background-color: #CCC;
	color: #000;
	padding: 4px;
	text-align: left;
	border: 0px;}
	table.stats
	{text-align: center;
	font-family: Verdana, Geneva, Arial, Helvetica, sans-serif ;
	font-weight: normal;
	font-size: 14px;
	color: #fff;
	width: 400px;
	background-color: #666;
	border: 0px;
	border-collapse: collapse;
	border-spacing: 0px;}
	table.stats td
	{background-color: #CCC;
	color: #000;
	padding: 4px;
	text-align: left;
	border: 1px #fff solid;}
	table.stats td.result
	{background-color: #CCC;
	color: #000;
	padding: 4px;
	text-align: right;
	border: 1px #fff solid;}
	table.stats td.hed
	{background-color: #666;
	color: #fff;
	padding: 4px;
	text-align: left;
	border-bottom: 2px #fff solid;
	font-size: 14px;
	font-weight: bold;} 
</style>
<h3>Select Printable Version on left for printing</h3>
<table class="stats">
	<tr>
		<td class="userinput" >
			Select&nbsp;Computer&nbsp;Group:
		</td>
		<td class="userinput">
			<select id = "groupName" name = "groupName" size = "1">
				<option value = "default" selected = "true" style = "background-color: #532900; color: white;" > --Select Computer Group-- </option>
				<?relevance (html "<option value=%22" & it & html "%22>" & it & html "</options>") of names of bes computer groups ?>
			</select>
		</td>
		<td class="userinput">
			<input type='button' onclick='search()' value='Generate Report'/>
		</td>
	</tr>
	<tr>
		<td class="userinput" >
				Fixlet Name:
		</td>
		<td colspan=2 class="userinput">
			<input type="text" id="fixletname" name="fixletname" style="width:100%">
		</td>
	</tr>
				
				<tr>
				<td colspan="3">
				<table class="date">
				<tr>
				<td class="dateleft">Fix Date between:</td><td class="dateright"><input id="start_date" name="start_date" onfocus="showCalendarControl(this);" type="text"> (MM-DD-YYYY)</td>
				</tr>
				<tr>
				<td class="dateleft">and:</td><td class="dateright"><input id="end_date" name="end_date" onfocus="showCalendarControl(this);" type="text"> (MM-DD-YYYY)</td>
				</tr>
				</table>
				</td>
				</tr>
				</table>
				<hr />
	
				<div id="resultsDiv">
				</div>
				<script type="text/javascript">
    
				addEvent(window, "load", init_load);
				var divRes = document.getElementById('resultsDiv');
				var computerFilter;
				var res_count
				function search(){
	
				if (document.getElementById('groupName').value == 'default')
				{
				divRes.style.display = 'block';
				divRes.innerHTML = 'Please select a computer group.';
				return;
				}
				else if (document.getElementById('start_date').value == '')
				{
				divRes.style.display = 'block';
				divRes.innerHTML = 'Please enter a start date.';
				return;
				}
				else if (document.getElementById('end_date').value == '')
				{
				divRes.style.display = 'block';
				divRes.innerHTML = 'Please enter an end date.';
				return;
				}
		
				divRes.style.display = 'block';
				divRes.innerHTML = 'Processing...';
	
	var relevance = '(html "<table id=%22resultsTable%22 class=%22sortable%22><tr class=%22res%22><th class=%22res%22>Computer</th><th class=%22res%22>Fixlet</th><th class=%22res%22 nowrap>Source Release Date</th><th class=%22res%22 nowrap>Source Severity</th><th class=%22res%22>Fix Date</th></tr>" & it & html "</table>") of concatenations of trs "class=%22res%22" of (td "class=%22res%22 nowrap" of name of computer of it & td "class=%22res%22" of name of fixlet of it & td "class=%22res%22" of (if (exists source release date of fixlet of it) then ((year of it as string & "/" & month of it as two digits & "/" & day_of_month of it as two digits) of source release date of fixlet of it) else ("Unspecified")) & td "class=%22res%22" of (if (source severity of fixlet of it as lowercase = "<unspecified>") then ("Unspecified") else (source severity of fixlet of it)) & td "class=%22res%22 nowrap" of ((year of it as string & "/" & month of it as two digits & "/" & day_of_month of it as two digits) of date (local time zone) of it & " " & (two digit hour of it as string & ":" & two digit minute of it as string & ":" & two digit second of it as string) of time (local time zone) of it) of last became nonrelevant of it) of results from (bes fixlets whose (name of it as lowercase contains "' + document.getElementById('fixletname').value.toLowerCase() + '" and display name of site of it contains "Patches for Windows" and fixlet flag of it = true)) whose (exists last became relevant of it and relevant flag of it = false and ((date (local time zone) of last became nonrelevant of it) >=(((last 2 of first 5 of it & " " & first 2 of it as integer as month as three letters & " " & last 4 of it) of "' + document.getElementById('start_date').value + '") as date)) and (date (local time zone) of last became nonrelevant of it) <=(((last 2 of first 5 of it & " " & first 2 of it as integer as month as three letters & " " & last 4 of it) of "' + document.getElementById('end_date').value + '") as date)) of members of bes computer groups whose (name of it = "' + document.getElementById('groupName').value + '")';
	strResponse = EvaluateRelevance(relevance);             
	divRes.innerHTML = strResponse;
	sortables_init();
	stripe('resultsTable', '#fff', '#E6E3E8');
}
				
	function init_load()
	{
		// stripe('resultsTable', '#fff', '#E6E3E8');
		// sortables_init();
		var currentTime = new Date()
		var year = currentTime.getFullYear();
		var month = currentTime.getMonth() + 1;	
		var day = currentTime.getDate();
		if (month < 10){
			month = "0" + month
		}
		if (day < 10){
			day = "0" + day
		}
		document.getElementById('end_date').value = month + '-' + day + '-' + year;
		document.getElementById('start_date').value = '01-01-2000';
	}
    
	var SORT_COLUMN_INDEX;
	function sortables_init(){
    
	// Find all tables with class sortable and make them sortable
	if (!document.getElementsByTagName) 
	return;
	tbls = document.getElementsByTagName("table");
	for (ti = 0; ti < tbls.length; ti++) {
		thisTbl = tbls[ti];
		if (((' ' + thisTbl.className + ' ').indexOf("sortable") != -1) && (thisTbl.id)) {
		//initTable(thisTbl.id);
		ts_makeSortable(thisTbl);
		}
		}
		}
    
		function ts_makeSortable(table){
		if (table.rows && table.rows.length > 0) {
		var firstRow = table.rows[0];
		}
		if (!firstRow) 
		return;
        
		// We have a first row: assume it's the header, and make its contents clickable links
		for (var i = 0; i < firstRow.cells.length; i++) {
		var cell = firstRow.cells[i];
		var txt = ts_getInnerText(cell);
		cell.innerHTML = '<a href="#" class="sortheader" ' +
		'onclick="ts_resortTable(this, ' +
		i +
		');return false;">' +
		txt +
	'<span class="sortarrow">   </span></a>';
        }
    }
    
    function ts_getInnerText(el){
        if (typeof el == "string") 
            return el;
        if (typeof el == "undefined") {
            return el
        };
        if (el.innerText) 
            return el.innerText; //Not needed but it is faster
        var str = "";
        
        var cs = el.childNodes;
        var l = cs.length;
        for (var i = 0; i < l; i++) {
            switch (cs[i].nodeType) {
                case 1: //ELEMENT_NODE
                    str += ts_getInnerText(cs[i]);
                    break;
                case 3: //TEXT_NODE
                    str += cs[i].nodeValue;
                    break;
            }
        }
        return str;
    }
    
    function ts_resortTable(lnk, clid){
        // get the span
        var span;
        for (var ci = 0; ci < lnk.childNodes.length; ci++) {
            if (lnk.childNodes[ci].tagName && lnk.childNodes[ci].tagName.toLowerCase() == 'span') 
                span = lnk.childNodes[ci];
        }
        var spantext = ts_getInnerText(span);
        var td = lnk.parentNode;
        var column = clid || td.cellIndex;
        var table = getParent(td, 'TABLE');
        
        // Work out a type for the column
        if (table.rows.length <= 1) 
            return;
        var itm = ts_getInnerText(table.rows[1].cells[column]);
        sortfn = ts_sort_caseinsensitive;
        if (itm.match(/^\d\d[\/-]\d\d[\/-]\d\d\d\d$/)) 
            sortfn = ts_sort_date;
        if (itm.match(/^\d\d[\/-]\d\d[\/-]\d\d$/)) 
            sortfn = ts_sort_date;
        if (itm.match(/^[ $]/)) 
            sortfn = ts_sort_currency;
        if (itm.match(/^[\d\.]+$/)) 
            sortfn = ts_sort_numeric;
        SORT_COLUMN_INDEX = column;
        var firstRow = new Array();
        var newRows = new Array();
        for (i = 0; i < table.rows[0].length; i++) {
            firstRow[i] = table.rows[0][i];
        }
        for (j = 1; j < table.rows.length; j++) {
            newRows[j - 1] = table.rows[j];
        }
        newRows.sort(sortfn);
        if (span.getAttribute("sortdir") == 'down') {
            ARROW = ' <img src="/images/besreports/ENU/maximizebutton1.gif" border="0" height="12" width="15" alt="">';
            newRows.reverse();
            span.setAttribute('sortdir', 'up');
        }
        else {
            ARROW = ' <img src="/images/besreports/ENU/minimizebutton1.gif" border="0" height="12" width="15" alt="">';
            span.setAttribute('sortdir', 'down');
        }
        
        // We appendChild rows that already exist to the tbody, so it moves them rather than creating new ones
        // don't do sortbottom rows
        for (i = 0; i < newRows.length; i++) {
            if (!newRows[i].className || (newRows[i].className && (newRows[i].className.indexOf('sortbottom') == -1))) {
                table.tBodies[0].appendChild(newRows[i]);
                if (i % 2 > 0) 
                    newRows[i].className = 'wr_oddRow';
                else 
                    newRows[i].className = 'wr_evenRow';
            }
        }
        // do sortbottom rows only
        for (i = 0; i < newRows.length; i++) {
            if (newRows[i].className && (newRows[i].className.indexOf('sortbottom') != -1)) 
                table.tBodies[0].appendChild(newRows[i]);
        }
        
        // Delete any other arrows there may be showing
        var allspans = document.getElementsByTagName("span");
        for (var ci = 0; ci < allspans.length; ci++) {
            if (allspans[ci].className == 'sortarrow') {
                if (getParent(allspans[ci], "table") == getParent(lnk, "table")) { // in the same table as us?
                    allspans[ci].innerHTML = '   ';
                }
            }
        }
        // adds up/down arrow to the column header 
        span.innerHTML = ARROW;
// Make zebra stripes in table
stripe('resultsTable', '#fff', '#E6E3E8');
    }
    
    function getParent(el, pTagName){
        if (el == null) 
            return null;
        else 
            if (el.nodeType == 1 && el.tagName.toLowerCase() == pTagName.toLowerCase()) // Gecko bug, supposed to be uppercase
                return el;
            else 
                return getParent(el.parentNode, pTagName);
    }
    
    function ts_sort_date(a, b){
        // y2k notes: two digit years less than 50 are treated as 20XX, greater than 50 are treated as 19XX
        aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]);
        bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]);
        if (aa.length == 10) {
            dt1 = aa.substr(6, 4) + aa.substr(3, 2) + aa.substr(0, 2);
        }
        else {
            yr = aa.substr(6, 2);
            if (parseInt(yr) < 50) {
                yr = '20' + yr;
            }
            else {
                yr = '19' + yr;
            }
            dt1 = yr + aa.substr(3, 2) + aa.substr(0, 2);
        }
        if (bb.length == 10) {
            dt2 = bb.substr(6, 4) + bb.substr(3, 2) + bb.substr(0, 2);
        }
        else {
            yr = bb.substr(6, 2);
            if (parseInt(yr) < 50) {
                yr = '20' + yr;
            }
            else {
                yr = '19' + yr;
            }
            dt2 = yr + bb.substr(3, 2) + bb.substr(0, 2);
        }
        
        if (dt1 == dt2) 
            return 0;
        if (dt1 < dt2) 
            return -1;
        return 1;
    }
    
    function ts_sort_currency(a, b){
        aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]).replace(/[^0-9.]/g, '');
        bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]).replace(/[^0-9.]/g, '');
        return parseFloat(aa) - parseFloat(bb);
    }
    
    function ts_sort_numeric(a, b){
        aa = parseFloat(ts_getInnerText(a.cells[SORT_COLUMN_INDEX]));
        if (isNaN(aa)) 
            aa = 0;
        bb = parseFloat(ts_getInnerText(b.cells[SORT_COLUMN_INDEX]));
        if (isNaN(bb)) 
            bb = 0;
        return aa - bb;
    }
    
    function ts_sort_caseinsensitive(a, b){
        aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]).toLowerCase();
        bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]).toLowerCase();
        if (aa == bb) 
            return 0;
        if (aa < bb) 
            return -1;
        return 1;
    }
    
    function ts_sort_default(a, b){
        aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]);
        bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]);
        if (aa == bb) 
            return 0;
        if (aa < bb) 
            return -1;
        return 1;
    }
    
    function addEvent(elm, evType, fn, useCapture)// addEvent and removeEvent
    // cross-browser event handling for IE5+,  NS6 and Mozilla
    // By Scott Andrew
    {
        if (elm.addEventListener) {
            elm.addEventListener(evType, fn, useCapture);
            return true;
        }
        else 
            if (elm.attachEvent) {
                var r = elm.attachEvent("on" + evType, fn);
                return r;
            }
            else {
                alert("Handler could not be removed");
            }
    }
// this function is needed to work around 
// a bug in IE related to element attributes
function hasClass(obj) {
var result = false;
if (obj.getAttributeNode("class") != null) {
    result = obj.getAttributeNode("class").value;
}
return result;
}   
function stripe(id) {
// the flag we'll use to keep track of 
// whether the current row is odd or even
var even = false;
// if arguments are provided to specify the colours
// of the even & odd rows, then use the them;
// otherwise use the following defaults:
var evenColor = arguments[1] ? arguments[1] : "#fff";
var oddColor = arguments[2] ? arguments[2] : "#eee";
// obtain a reference to the desired table
// if no such table exists, abort
var table = document.getElementById(id);
if (! table) { return; }
// by definition, tables can have more than one tbody
// element, so we'll have to get the list of child
// <tbody>s 
var tbodies = table.getElementsByTagName("tbody");
// and iterate through them...
for (var h = 0; h < tbodies.length; h++) {
// find all the <tr> elements... 
 var trs = tbodies[h].getElementsByTagName("tr");
 
 // ... and iterate through them
 for (var i = 0; i < trs.length; i++) {
     // get all the cells in this row...
     var tds = trs[i].getElementsByTagName("td");
   
     // and iterate through them...
     for (var j = 0; j < tds.length; j++) {
   
       var mytd = tds[j];
         mytd.style.backgroundColor =
           even ? evenColor : oddColor;
     }
   // flip from odd to even, or vice-versa
   even =  ! even;
 }
}
}
</script>

Here is our code. It takes a long time to return results, but it works on 10.0.1.41:

<!-- 
Fixlet Fix Date by Computer Group with Date and Fixlet Name Search
Please see the BigFix Forum for information on this report
http://forum.bigfix.com/viewtopic.php?pid=16225#p16225
-->
<style type="text/css">
a {
text-decoration: none;
}

a:hover {
color: #FF8000;
font-weight: bold;
text-decoration: none;
}

table.sortable {
margin: 0;
border-collapse: collapse;
color: #222;
font: 10pt verdana, geneva, lucida, 'lucida grande', arial, helvetica, sans-serif;
}

th.res {
font: 10pt verdana, geneva, lucida, 'lucida grande', arial, helvetica, sans-serif;
color: navy;
font-weight: bold;
background-color: #F2F2F2;
border: 1px solid #cccccc;
margin: 0;
padding: 4px 10px 4px 5px;          
text-align: left;
} 

td.res {
color: #222;
font: 8pt verdana, geneva, lucida, 'lucida grande', arial, helvetica, sans-serif;
border-bottom: 1px solid #cccccc;
margin: 0;
/* padding: 6px 20px 1px 0;  */
padding: 8px 20px 5px 5px;
}

td.userinput {
color: #222;
font: 10pt verdana, geneva, lucida, 'lucida grande', arial, helvetica, sans-serif;
font-weight: bold;
border-bottom: 0px;
margin: 0;
padding: 6px 20px 1px 0;
} 

td.errormsg {
color: red;
font: 10pt verdana, geneva, lucida, 'lucida grande', arial, helvetica, sans-serif;
font-weight: bold;
border-bottom: 0px;
margin: 0;
padding: 6px 20px 1px 0;
}
td.msg {
color: #747170;
font: 10pt verdana, geneva, lucida, 'lucida grande', arial, helvetica, sans-serif;
font-weight: bold;
border-bottom: 0px;
margin: 0;
padding: 6px 20px 1px 0;
}

h3 {
font: 10pt verdana, geneva, lucida, 'lucida grande', arial, helvetica, sans-serif;
background-color: #747170;
padding: 4px 4px 4px 4px;
color: white;
width: 100%;
}

#CalendarControlIFrame {
display: none;
left: 0px;
position: absolute;
top: 0px;
height: 250px;
width: 250px;
z-index: 99;
}
table.date
{text-align: center;
font-family: Verdana, Geneva, Arial, Helvetica, sans-serif ;
font-weight: normal;
font-size: 14px;
color: #fff;
width: 400px;
background-color: #777;
border: 0px;
border-collapse: collapse;
border-spacing: 0px;}

table.date td.dateleft
{background-color: #CCC;
color: #000;
padding: 4px;
text-align: right;
border: 0px;}
table.date td.dateright
{background-color: #CCC;
color: #000;
padding: 4px;
text-align: left;
border: 0px;}
table.stats
{text-align: center;
font-family: Verdana, Geneva, Arial, Helvetica, sans-serif ;
font-weight: normal;
font-size: 14px;
color: #fff;
width: 400px;
background-color: #666;
border: 0px;
border-collapse: collapse;
border-spacing: 0px;}
table.stats td
{background-color: #CCC;
color: #000;
padding: 4px;
text-align: left;
border: 1px #fff solid;}
table.stats td.result
{background-color: #CCC;
color: #000;
padding: 4px;
text-align: right;
border: 1px #fff solid;}
table.stats td.hed
{background-color: #666;
color: #fff;
padding: 4px;
text-align: left;
border-bottom: 2px #fff solid;
font-size: 14px;
font-weight: bold;} 
</style>
<h3>Select Printable Version on left for printing</h3>
<table class="stats">
<tr>
	<td class="userinput" >
		Select&nbsp;Computer&nbsp;Group:
	</td>
	<td class="userinput">
		<select id = "groupName" name = "groupName" size = "1">
			<option value = "default" selected = "true" style = "background-color: #532900; color: white;" > --Select Computer Group-- </option>
			<?relevance (html "<option value=%22" & it & html "%22>" & it & html "</options>") of names of bes computer groups ?>
		</select>
	</td>
	<td class="userinput">
		<input type='button' onclick='search()' value='Generate Report'/>
	</td>
</tr>
<tr>
	<td class="userinput" >
			Fixlet Name:
	</td>
	<td colspan=2 class="userinput">
		<input type="text" id="fixletname" name="fixletname" style="width:100%">
	</td>
</tr>
			
			<tr>
			<td colspan="3">
			<table class="date">
			<tr>
			<td class="dateleft">Fix Date between:</td><td class="dateright"><input id="start_date" name="start_date" onfocus="showCalendarControl(this);" type="text"> (MM-DD-YYYY)</td>
			</tr>
			<tr>
			<td class="dateleft">and:</td><td class="dateright"><input id="end_date" name="end_date" onfocus="showCalendarControl(this);" type="text"> (MM-DD-YYYY)</td>
			</tr>
			</table>
			</td>
			</tr>
			</table>
			<hr />

			<div id="resultsDiv">
			</div>
			<script type="text/javascript">

			addEvent(window, "load", init_load);
			var divRes = document.getElementById('resultsDiv');
			var computerFilter;
			var res_count
			function search(){

			if (document.getElementById('groupName').value == 'default')
			{
			divRes.style.display = 'block';
			divRes.innerHTML = 'Please select a computer group.';
			return;
			}
			else if (document.getElementById('start_date').value == '')
			{
			divRes.style.display = 'block';
			divRes.innerHTML = 'Please enter a start date.';
			return;
			}
			else if (document.getElementById('end_date').value == '')
			{
			divRes.style.display = 'block';
			divRes.innerHTML = 'Please enter an end date.';
			return;
			}
	
			divRes.style.display = 'block';
			divRes.innerHTML = 'Processing...';
 
 // var relevance = '(html "<table id=%22resultsTable%22 class=%22sortable%22><tr class=%22res%22><th class=%22res%22>Fixlet</th><th class=%22res%22>Source Severity</th><th class=%22res%22>Fix Date</th></tr>" & it & html "</table>") of concatenations of trs "class=%22res%22" of (td "class=%22res%22" of name of fixlet of it & td "class=%22res%22" of (if (source severity of fixlet of it as lowercase = "<unspecified>") then ("Unspecified") else (source severity of fixlet of it))  & td "class=%22res%22" of ((year of it as string & "/" & month of it as two digits & "/" & day_of_month of it as two digits) of  date(local time zone) of it & " "& (two digit hour of it as string & ":" & two digit minute of it as string & ":" & two digit second of it as string) of time (local time zone) of it) of last became nonrelevant of it) of results from (bes fixlets whose (display name of site of it contains "Patches for Windows (English)" and fixlet flag of it = true)) whose (exists last became relevant of it and relevant flag of it = false and ((date (local time zone) of last became nonrelevant of it) >= (((last 2 of first 5 of it & " " & first 2 of it as integer as month as three letters & " " & last 4 of it) of "' + start_date.value + '") as date)) and (date (local time zone) of last became nonrelevant of it) <= (((last 2 of first 5 of it & " " & first 2 of it as integer as month as three letters & " " & last 4 of it) of "' + end_date.value + '") as date)) of bes computers whose (id of it = ' + computerName.value + ')';	
	
var relevance = '(html "<table id=%22resultsTable%22 class=%22sortable%22><tr class=%22res%22><th class=%22res%22>Computer</th><th class=%22res%22>Fixlet</th><th class=%22res%22 nowrap>Source Release Date</th><th class=%22res%22>Source Severity</th><th class=%22res%22>Fix Date</th></tr>" & it & html "</table>") of concatenations of trs "class=%22res%22" of (td "class=%22res%22" of name of computer of it & td "class=%22res%22" of name of fixlet of it & td "class=%22res%22" of  (if (exists source release date of fixlet of it) then ((year of it as string & "/" & month of it as two digits & "/" & day_of_month of it as two digits) of source release date of fixlet of it) else ("Unspecified")) & td "class=%22res%22" of (if (source severity of fixlet of it as lowercase = "<unspecified>") then ("Unspecified") else (source severity of fixlet of it))  & td "class=%22res%22" of ((year of it as string & "/" & month of it as two digits & "/" & day_of_month of it as two digits) of  date(local time zone) of it & " "& (two digit hour of it as string & ":" & two digit minute of it as string & ":" & two digit second of it as string) of time (local time zone) of it) of last became nonrelevant of it) of results from (bes fixlets whose (name of it as lowercase contains "' + document.getElementById('fixletname').value.toLowerCase() + '" and display name of site of it contains "Patches for Windows" and fixlet flag of it = true)) whose (exists last became relevant of it and relevant flag of it = false and ((date (local time zone) of last became nonrelevant of it) >= (((last 2 of first 5 of it & " " & first 2 of it as integer as month as three letters & " " & last 4 of it) of "' + document.getElementById('start_date').value + '") as date)) and (date (local time zone) of last became nonrelevant of it) <= (((last 2 of first 5 of it & " " & first 2 of it as integer as month as three letters & " " & last 4 of it) of "' + document.getElementById('end_date').value + '") as date)) of members of bes computer groups whose (name of it = "' + document.getElementById('groupName').value + '")';
		
strResponse = EvaluateRelevance(relevance);             
divRes.innerHTML = strResponse;
sortables_init();
stripe('resultsTable', '#fff', '#E6E3E8');
}
			
function init_load()
{
	// stripe('resultsTable', '#fff', '#E6E3E8');
	// sortables_init();
	var currentTime = new Date()
	var year = currentTime.getFullYear();
	var month = currentTime.getMonth() + 1;	
	var day = currentTime.getDate();
	if (month < 10){
		month = "0" + month
	}
	if (day < 10){
		day = "0" + day
	}
	document.getElementById('end_date').value = month + '-' + day + '-' + year;
	document.getElementById('start_date').value = '01-01-2000';
}

var SORT_COLUMN_INDEX;
function sortables_init(){

// Find all tables with class sortable and make them sortable
if (!document.getElementsByTagName) 
return;
tbls = document.getElementsByTagName("table");
for (ti = 0; ti < tbls.length; ti++) {
	thisTbl = tbls[ti];
	if (((' ' + thisTbl.className + ' ').indexOf("sortable") != -1) && (thisTbl.id)) {
	//initTable(thisTbl.id);
	ts_makeSortable(thisTbl);
	}
	}
	}

	function ts_makeSortable(table){
	if (table.rows && table.rows.length > 0) {
	var firstRow = table.rows[0];
	}
	if (!firstRow) 
	return;
    
	// We have a first row: assume it's the header, and make its contents clickable links
	for (var i = 0; i < firstRow.cells.length; i++) {
	var cell = firstRow.cells[i];
	var txt = ts_getInnerText(cell);
	cell.innerHTML = '<a href="#" class="sortheader" ' +
	'onclick="ts_resortTable(this, ' +
	i +
	');return false;">' +
	txt +
'<span class="sortarrow">   </span></a>';
    }
}

function ts_getInnerText(el){
    if (typeof el == "string") 
        return el;
    if (typeof el == "undefined") {
        return el
    };
    if (el.innerText) 
        return el.innerText; //Not needed but it is faster
    var str = "";
    
    var cs = el.childNodes;
    var l = cs.length;
    for (var i = 0; i < l; i++) {
        switch (cs[i].nodeType) {
            case 1: //ELEMENT_NODE
                str += ts_getInnerText(cs[i]);
                break;
            case 3: //TEXT_NODE
                str += cs[i].nodeValue;
                break;
        }
    }
    return str;
}

function ts_resortTable(lnk, clid){
    // get the span
    var span;
    for (var ci = 0; ci < lnk.childNodes.length; ci++) {
        if (lnk.childNodes[ci].tagName && lnk.childNodes[ci].tagName.toLowerCase() == 'span') 
            span = lnk.childNodes[ci];
    }
    var spantext = ts_getInnerText(span);
    var td = lnk.parentNode;
    var column = clid || td.cellIndex;
    var table = getParent(td, 'TABLE');
    
    // Work out a type for the column
    if (table.rows.length <= 1) 
        return;
    var itm = ts_getInnerText(table.rows[1].cells[column]);
    sortfn = ts_sort_caseinsensitive;
    if (itm.match(/^\d\d[\/-]\d\d[\/-]\d\d\d\d$/)) 
        sortfn = ts_sort_date;
    if (itm.match(/^\d\d[\/-]\d\d[\/-]\d\d$/)) 
        sortfn = ts_sort_date;
    if (itm.match(/^[ $]/)) 
        sortfn = ts_sort_currency;
    if (itm.match(/^[\d\.]+$/)) 
        sortfn = ts_sort_numeric;
    SORT_COLUMN_INDEX = column;
    var firstRow = new Array();
    var newRows = new Array();
    for (i = 0; i < table.rows[0].length; i++) {
        firstRow[i] = table.rows[0][i];
    }
    for (j = 1; j < table.rows.length; j++) {
        newRows[j - 1] = table.rows[j];
    }
    newRows.sort(sortfn);
    if (span.getAttribute("sortdir") == 'down') {
        ARROW = ' <img src="/images/besreports/ENU/maximizebutton1.gif" border="0" height="12" width="15" alt="">';
        newRows.reverse();
        span.setAttribute('sortdir', 'up');
    }
    else {
        ARROW = ' <img src="/images/besreports/ENU/minimizebutton1.gif" border="0" height="12" width="15" alt="">';
        span.setAttribute('sortdir', 'down');
    }
    
    // We appendChild rows that already exist to the tbody, so it moves them rather than creating new ones
    // don't do sortbottom rows
    for (i = 0; i < newRows.length; i++) {
        if (!newRows[i].className || (newRows[i].className && (newRows[i].className.indexOf('sortbottom') == -1))) {
            table.tBodies[0].appendChild(newRows[i]);
            if (i % 2 > 0) 
                newRows[i].className = 'wr_oddRow';
            else 
                newRows[i].className = 'wr_evenRow';
        }
    }
    // do sortbottom rows only
    for (i = 0; i < newRows.length; i++) {
        if (newRows[i].className && (newRows[i].className.indexOf('sortbottom') != -1)) 
            table.tBodies[0].appendChild(newRows[i]);
    }
    
    // Delete any other arrows there may be showing
    var allspans = document.getElementsByTagName("span");
    for (var ci = 0; ci < allspans.length; ci++) {
        if (allspans[ci].className == 'sortarrow') {
            if (getParent(allspans[ci], "table") == getParent(lnk, "table")) { // in the same table as us?
                allspans[ci].innerHTML = '   ';
            }
        }
    }
    // adds up/down arrow to the column header 
    span.innerHTML = ARROW;
// Make zebra stripes in table
stripe('resultsTable', '#fff', '#E6E3E8');
}

function getParent(el, pTagName){
    if (el == null) 
        return null;
    else 
        if (el.nodeType == 1 && el.tagName.toLowerCase() == pTagName.toLowerCase()) // Gecko bug, supposed to be uppercase
            return el;
        else 
            return getParent(el.parentNode, pTagName);
}

function ts_sort_date(a, b){
    // y2k notes: two digit years less than 50 are treated as 20XX, greater than 50 are treated as 19XX
    aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]);
    bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]);
    if (aa.length == 10) {
        dt1 = aa.substr(6, 4) + aa.substr(3, 2) + aa.substr(0, 2);
    }
    else {
        yr = aa.substr(6, 2);
        if (parseInt(yr) < 50) {
            yr = '20' + yr;
        }
        else {
            yr = '19' + yr;
        }
        dt1 = yr + aa.substr(3, 2) + aa.substr(0, 2);
    }
    if (bb.length == 10) {
        dt2 = bb.substr(6, 4) + bb.substr(3, 2) + bb.substr(0, 2);
    }
    else {
        yr = bb.substr(6, 2);
        if (parseInt(yr) < 50) {
            yr = '20' + yr;
        }
        else {
            yr = '19' + yr;
        }
        dt2 = yr + bb.substr(3, 2) + bb.substr(0, 2);
    }
    
    if (dt1 == dt2) 
        return 0;
    if (dt1 < dt2) 
        return -1;
    return 1;
}

function ts_sort_currency(a, b){
    aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]).replace(/[^0-9.]/g, '');
    bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]).replace(/[^0-9.]/g, '');
    return parseFloat(aa) - parseFloat(bb);
}

function ts_sort_numeric(a, b){
    aa = parseFloat(ts_getInnerText(a.cells[SORT_COLUMN_INDEX]));
    if (isNaN(aa)) 
        aa = 0;
    bb = parseFloat(ts_getInnerText(b.cells[SORT_COLUMN_INDEX]));
    if (isNaN(bb)) 
        bb = 0;
    return aa - bb;
}

function ts_sort_caseinsensitive(a, b){
    aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]).toLowerCase();
    bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]).toLowerCase();
    if (aa == bb) 
        return 0;
    if (aa < bb) 
        return -1;
    return 1;
}

function ts_sort_default(a, b){
    aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]);
    bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]);
    if (aa == bb) 
        return 0;
    if (aa < bb) 
        return -1;
    return 1;
}

function addEvent(elm, evType, fn, useCapture)// addEvent and removeEvent
// cross-browser event handling for IE5+,  NS6 and Mozilla
// By Scott Andrew
{
    if (elm.addEventListener) {
        elm.addEventListener(evType, fn, useCapture);
        return true;
    }
    else 
        if (elm.attachEvent) {
            var r = elm.attachEvent("on" + evType, fn);
            return r;
        }
        else {
            alert("Handler could not be removed");
        }
}
// this function is needed to work around 
// a bug in IE related to element attributes
function hasClass(obj) {
var result = false;
if (obj.getAttributeNode("class") != null) {
result = obj.getAttributeNode("class").value;
}
return result;
}   
function stripe(id) {
// the flag we'll use to keep track of 
// whether the current row is odd or even
var even = false;
// if arguments are provided to specify the colours
// of the even & odd rows, then use the them;
// otherwise use the following defaults:
var evenColor = arguments[1] ? arguments[1] : "#fff";
var oddColor = arguments[2] ? arguments[2] : "#eee";
 // obtain a reference to the desired table
// if no such table exists, abort
var table = document.getElementById(id);
if (! table) { return; }
// by definition, tables can have more than one tbody
// element, so we'll have to get the list of child
// <tbody>s 
var tbodies = table.getElementsByTagName("tbody");
// and iterate through them...
for (var h = 0; h < tbodies.length; h++) {
// find all the <tr> elements... 
var trs = tbodies[h].getElementsByTagName("tr");

// ... and iterate through them
 for (var i = 0; i < trs.length; i++) {
 // get all the cells in this row...
 var tds = trs[i].getElementsByTagName("td");

 // and iterate through them...
 for (var j = 0; j < tds.length; j++) {

   var mytd = tds[j];
     mytd.style.backgroundColor =
       even ? evenColor : oddColor;
 }
// flip from odd to even, or vice-versa
even =  ! even;
 }
}
}
</script>
1 Like

@thomasdietrich Thank you for sharing this. Something strange is definetely up with our environment in essence to WebReports and this report. We copied the code you provided and imported. We can see the groups list populated, but generating the report simply comes back with no results.

We can go to Explore Data and can successfully filter via a group and see it’s endpoints. We can also go under Explore Data → Content → and see results of remediated patches from a group. It seems to be an issue with this one report…

Just validated further that taking @thomasdietrich’s provided report code and putting that into our DEV Bigfix site running the same version (10.0.1.41) that it works without issue. The only thing different about our Dev env from Prod is the new implementation of cloud plugins. Other than that the two environments are one of the same configuration wise. We attempted to modify the filters for the report to only return “Native” Agent Types, but same issue is present with no results returning.

One thing that tends to happen at larger scales, is that the edge cases that don’t matter on smaller deployments become more apparent.

Take the use of singular expressions. With a singular value, any computer that has not reported a value will cause the statement as a whole to throw an error.

On the relevance posted above, the only singular I see that doesn’t look like it has some kind of error trapping is ‘name of computer of it’. I find that one simple statement pretty commonly blows up a whole relevance expression, and usually only in larger deployments, where there might be one computer somewhere showing its name as <Not Reported>.

Try this modification to the javascript that traps for a missing computer name and see whether it helps:

var relevance = '(html "<table id=%22resultsTable%22 class=%22sortable%22><tr class=%22res%22><th class=%22res%22>Computer</th><th class=%22res%22>Fixlet</th><th class=%22res%22 nowrap>Source Release Date</th><th class=%22res%22>Source Severity</th><th class=%22res%22>Fix Date</th></tr>" & it & html "</table>") of concatenations of trs "class=%22res%22" of (td "class=%22res%22" of (name of computer of it | "Name Not Reported") & td "class=%22res%22" of name of fixlet of it & td "class=%22res%22" of  (if (exists source release date of fixlet of it) then ((year of it as string & "/" & month of it as two digits & "/" & day_of_month of it as two digits) of source release date of fixlet of it) else ("Unspecified")) & td "class=%22res%22" of (if (source severity of fixlet of it as lowercase = "<unspecified>") then ("Unspecified") else (source severity of fixlet of it))  & td "class=%22res%22" of ((year of it as string & "/" & month of it as two digits & "/" & day_of_month of it as two digits) of  date(local time zone) of it & " "& (two digit hour of it as string & ":" & two digit minute of it as string & ":" & two digit second of it as string) of time (local time zone) of it) of last became nonrelevant of it) of results from (bes fixlets whose (name of it as lowercase contains "' + document.getElementById('fixletname').value.toLowerCase() + '" and display name of site of it contains "Patches for Windows" and fixlet flag of it = true)) whose (exists last became relevant of it and relevant flag of it = false and ((date (local time zone) of last became nonrelevant of it) >= (((last 2 of first 5 of it & " " & first 2 of it as integer as month as three letters & " " & last 4 of it) of "' + document.getElementById('start_date').value + '") as date)) and (date (local time zone) of last became nonrelevant of it) <= (((last 2 of first 5 of it & " " & first 2 of it as integer as month as three letters & " " & last 4 of it) of "' + document.getElementById('end_date').value + '") as date)) of members of bes computer groups whose (name of it = "' + document.getElementById('groupName').value + '")';
2 Likes

@JasonWalker thank you very much for the feedback and explanation. This unfortunately did not solve the issue for us as even after modifying we are still seeing the same issue with no results being displayed. To ensure we are to expect results from this report for the specific targeted group we went back and validated from past BES Actions that Windows patches were deployed to a member of this group and were fixed, however they are not showing in this report.

(
submitted without comment on possibility of making the query faster / more readable but will consider that when I need another puzzle
)

WebReports logs show the relevance being evaluated, but simply no results are returned.

Wed, 03 Feb 2021 16:53:59 -0600 -- /webreports (5516) --       Exiting WebReportsRelevanceEvaluator::Evaluate( (html "<table id=%22resultsTable%22 class=%22sortable%22><tr class=%22res%22><th class=%22res%22>Computer</th><th class=%22res%22>Fixlet</th><th class=%22res%22 nowrap>Source Release Date</th><th class=%22res%22>Source Severity</th><th class=%22res%22>Fix Date</th></tr>" & it & html "</table>") of concatenations of trs "class=%22res%22" of (td "class=%22res%22" of (name of computer of it | "Name Not Reported") & td "class=%22res%22" of name of fixlet of it & td "class=%22res%22" of  (if (exists source release date of fixlet of it) then ((year of it as string & "/" & month of it as two digits & "/" & day_of_month of it as two digits) of source release date of fixlet of it) else ("Unspecified")) & td "class=%22res%22" of (if (source severity of fixlet of it as lowercase = "<unspecified>") then ("Unspecified") else (source severity of fixlet of it))  & td "class=%22res%22" of ((year of it as string & "/" & month of it as two digits & "/" & day_of_month of it as two digits) of  date(local time zone) of it & " "& (two digit hour of it as string & ":" & two digit minute of it as string & ":" & two digit second of it as string) of time (local time zone) of it) of last became nonrelevant of it) of results from (bes fixlets whose (name of it as lowercase contains "" and display name of site of it contains "Patches for Windows" and fixlet flag of it = true)) whose (exists last became relevant of it and relevant flag of it = false and ((date (local time zone) of last became nonrelevant of it) >= (((last 2 of first 5 of it & " " & first 2 of it as integer as month as three letters & " " & last 4 of it) of "01-01-2021") as date)) and (date (local time zone) of last became nonrelevant of it) <= (((last 2 of first 5 of it & " " & first 2 of it as integer as month as three letters & " " & last 4 of it) of "02-03-2021") as date)) of members of bes computer groups whose (name of it = "WinCust - Group 1") ) (20371 ms)Wed, 03 Feb 2021 16:53:59 -0600 -- /webreports (5516) --     Exiting WebReportsPageMap::PrintPage (20371 ms)

Also, in case you weren’t aware, when debugging something like this I like to use the hidden Web Reports QNA page. You can access that by replacing the end of your Web Reports URL with ?page=QNA

1 Like

Trying that out now. Thanks for the tip!

What I like to do is to get the query working and optimized in the QNA page first, before putting any HTML formatting on it at all. I’ve shortened the query to

q: ((name of computer of it | "Name Not Reported") ,name of fixlet of it , (if (exists source release date of fixlet of it) then ((year of it as string & "/" & month of it as two digits & "/" & day_of_month of it as two digits) of source release date of fixlet of it) else ("Unspecified")) , (if (source severity of fixlet of it as lowercase = "<unspecified>") then ("Unspecified") else (source severity of fixlet of it))  ,((year of it as string & "/" & month of it as two digits & "/" & day_of_month of it as two digits) of  date(local time zone) of it & " "& (two digit hour of it as string & ":" & two digit minute of it as string & ":" & two digit second of it as string) of time (local time zone) of it) of last became nonrelevant of it) of results from (bes fixlets whose (name of it as lowercase contains "" and display name of site of it contains "Patches for Windows" and fixlet flag of it = true)) whose (exists last became relevant of it and relevant flag of it = false and ((date (local time zone) of last became nonrelevant of it) >= (((last 2 of first 5 of it & " " & first 2 of it as integer as month as three letters & " " & last 4 of it) of "01-01-2021") as date)) and (date (local time zone) of last became nonrelevant of it) <= (((last 2 of first 5 of it & " " & first 2 of it as integer as month as three letters & " " & last 4 of it) of "02-03-2021") as date)) of members of bes computer groups whose (name of it = "Windows Servers")

and I’ll look at error trapping and optimizing now.

Then, when done, I’d put the table header in the HTML itself, and at the front of the query just add concatenation of trs of (concatenation of tds of (item 0 of it as string; item 1 of it as string; item 2 of it as string)) of ...

1 Like

Try this in your QNA page, and then we’ll narrow down to see which property might be giving you a problem – replace the computer group name with your real group

q: number of results from (bes fixlets whose (name of it as lowercase contains "" and display name of site of it contains "Patches for Windows" and fixlet flag of it = true)) whose (exists last became relevant of it and relevant flag of it = false and ((date (local time zone) of last became nonrelevant of it) >= (((last 2 of first 5 of it & " " & first 2 of it as integer as month as three letters & " " & last 4 of it) of "01-01-2021") as date)) and (date (local time zone) of last became nonrelevant of it) <= (((last 2 of first 5 of it & " " & first 2 of it as integer as month as three letters & " " & last 4 of it) of "02-03-2021") as date)) of members of bes computer groups whose (name of it = "Windows Servers")
1 Like

This returned 0