Thank you for the reply. The link you provided I had not seen before and exposes a wealth of information and I’ll be spending some time there. Relevance language is difficult for me and then trying to convert that to a meaningful web report is too much. I can’t get any results from the session debugger on the ‘first became relevant property’ and I’m not sure if that is even possible as I read somewhere else in a forum that this property is only available from web reports.
A colleague pointed me to a report that is close to what I’m looking for, but it hasn’t worked for some time. It turned out that the fix was to update the site name in the source to “Patches for Windows”. At some point in the past it had been “Patches for Windows (English)”
Here is the updated code for anyone that might come across this in the future:
<!--
Fixlet Relevant 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 (dead link)
-->
<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 Computer 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">Relevant 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>Source Severity</th><th class=%22res%22>Relevant 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 (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 relevant 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 = true and ((date (local time zone) of last became relevant 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 relevant 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>
Anyway,