source: extensions/net.sf.basedb.reggie/trunk/resources/samplereportgenerator.jsp @ 1772

Last change on this file since 1772 was 1772, checked in by olle, 10 years ago

Fixes #439. First version of missing sample data report added.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 78.9 KB
Line 
1<%@ page
2  pageEncoding="UTF-8"
3  session="false"
4  import="net.sf.basedb.core.User"
5  import="net.sf.basedb.core.DbControl"
6  import="net.sf.basedb.core.SessionControl"
7  import="net.sf.basedb.core.Application"
8  import="net.sf.basedb.clients.web.Base" 
9  import="net.sf.basedb.clients.web.extensions.ExtensionsControl"
10%>
11<%@ taglib prefix="base" uri="/WEB-INF/base.tld" %>
12<%@ taglib prefix="p" uri="/WEB-INF/path.tld" %>
13<%
14final SessionControl sc = Base.getExistingSessionControl(request, true);
15final String ID = sc.getId();
16final float scale = Base.getScale(sc);
17final String home = ExtensionsControl.getHomeUrl("net.sf.basedb.reggie");
18DbControl dc = null;
19try
20{
21  dc = sc.newDbControl();
22  final User user = User.getById(dc, sc.getLoggedInUserId());
23  %>
24<base:page type="default" >
25<base:head scripts="ajax.js" styles="path.css">
26  <link rel="stylesheet" type="text/css" href="css/reggie.css">
27  <script language="JavaScript" src="reggie.js" type="text/javascript" charset="UTF-8"></script>
28   
29   
30  <script language="JavaScript">
31  var currentStep = 1;
32  var debug = false;
33  var numCols;
34  var unknownSite = 0;
35  var unknownCreation;
36  var numPatientsNoSamples = 0;
37 
38  var month=new Array(12);
39    month[0]="Jan";
40    month[1]="Feb";
41    month[2]="Mar";
42    month[3]="Apr";
43    month[4]="May";
44    month[5]="Jun";
45    month[6]="Jul";
46    month[7]="Aug";
47    month[8]="Sep";
48    month[9]="Oct";
49    month[10]="Nov";
50    month[11]="Dec";
51 
52  var intervalIsValid = true;
53 
54  function goNext()
55  {
56    if (currentStep == 1)
57    {
58      gotoStep2();
59    }
60  }
61 
62  function gotoStep2()
63  {
64    var frm = document.forms['reggie'];
65    frm.reporttype.disabled = true;
66    // Hide report period input fields
67    document.getElementById("reportPeriodSubSection01").style.display = 'none';
68    document.getElementById("reportPeriodSubSection02").style.display = 'none';
69    document.getElementById("reportPeriodSubSection04").style.display = 'none';
70    // Hide view type pop-up menu
71    document.getElementById("viewTypeSubSection01").style.display = 'none';
72    document.getElementById("viewTypeSubSection02").style.display = 'none';
73    document.getElementById("viewTypeSubSection04").style.display = 'none';
74    // Hide sample type pop-up menu
75    document.getElementById("sampleTypeSubSection01").style.display = 'none';
76    document.getElementById("sampleTypeSubSection02").style.display = 'none';
77    document.getElementById("sampleTypeSubSection04").style.display = 'none';
78    if (frm.reporttype[frm.reporttype.selectedIndex].value == 'samplecount')
79    {
80      // Show report period input fields
81      document.getElementById("reportPeriodSubSection01").style.display = 'block';
82      document.getElementById("reportPeriodSubSection02").style.display = 'block';
83      document.getElementById("reportPeriodSubSection04").style.display = 'block';
84      document.getElementById("reportPeriodSubSection01Header").innerHTML="Report period";
85      document.getElementById("reportPeriodSubSection04HelpText").innerHTML="Define which period the report should cover. Empty fields will include all tubes.";
86      // Set item name for report time step text
87      document.getElementById("items02").innerHTML="samples";
88      document.getElementById("items03").innerHTML="samples";
89      document.getElementById("items04").innerHTML="samples";
90      document.getElementById("items05").innerHTML="samples";
91      // Show view type pop-up menu
92      document.getElementById("viewTypeSubSection01").style.display = 'block';
93      document.getElementById("viewTypeSubSection02").style.display = 'block';
94      document.getElementById("viewTypeSubSection04").style.display = 'block';
95      // Show sample type pop-up menu
96      document.getElementById("sampleTypeSubSection01").style.display = 'block';
97      document.getElementById("sampleTypeSubSection02").style.display = 'block';
98      document.getElementById("sampleTypeSubSection04").style.display = 'block';
99    }
100    else if (frm.reporttype[frm.reporttype.selectedIndex].value == 'consentcount')
101    {
102      // Show report period input fields
103      document.getElementById("reportPeriodSubSection01").style.display = 'block';
104      document.getElementById("reportPeriodSubSection02").style.display = 'block';
105      document.getElementById("reportPeriodSubSection04").style.display = 'block';
106      document.getElementById("reportPeriodSubSection01Header").innerHTML="Report period";
107      document.getElementById("reportPeriodSubSection04HelpText").innerHTML="Define which period the report should cover. Empty fields will include all consents.";
108    }
109    else if (frm.reporttype[frm.reporttype.selectedIndex].value == 'patientcount')
110    {
111      // Show report period input fields
112      document.getElementById("reportPeriodSubSection01").style.display = 'block';
113      document.getElementById("reportPeriodSubSection02").style.display = 'block';
114      document.getElementById("reportPeriodSubSection04").style.display = 'block';
115      document.getElementById("reportPeriodSubSection01Header").innerHTML="Report period";
116      document.getElementById("reportPeriodSubSection04HelpText").innerHTML="Define which period the report should cover. Empty fields will include all patients.";
117      // Set item name for report time step text
118      document.getElementById("items02").innerHTML="patients";
119      document.getElementById("items03").innerHTML="patients";
120      document.getElementById("items04").innerHTML="patients";
121      document.getElementById("items05").innerHTML="patients";
122      // Show view type pop-up menu
123      document.getElementById("viewTypeSubSection01").style.display = 'block';
124      document.getElementById("viewTypeSubSection02").style.display = 'block';
125      document.getElementById("viewTypeSubSection04").style.display = 'block';
126    }
127    else if (frm.reporttype[frm.reporttype.selectedIndex].value == 'overviewreport')
128    {
129      // Set parameters (report period) help text
130      document.getElementById("reportPeriodSubSection01").style.display = 'block';
131      document.getElementById("reportPeriodSubSection04").style.display = 'block';
132      document.getElementById("reportPeriodSubSection01Header").innerHTML="No report parameters";
133      document.getElementById("reportPeriodSubSection04HelpText").innerHTML="Overview report will be generated irrespective of date for items.";
134    }
135    else if (frm.reporttype[frm.reporttype.selectedIndex].value == 'missingsampledatareport')
136    {
137      // Show sample type pop-up menu
138      document.getElementById("sampleTypeSubSection01").style.display = 'block';
139      document.getElementById("sampleTypeSubSection02").style.display = 'block';
140      document.getElementById("sampleTypeSubSection04").style.display = 'block';
141    }
142    Main.show('itemCountSection');
143       
144    Main.show('gocreate');   
145    Main.hide('gonext');
146    frm.fromdate.focus();
147    currentStep = 2;
148  }
149 
150  function dateOnChange()
151  {
152    var frm = document.forms['reggie'];   
153    var fdate;
154    var tdate;
155   
156    intervalIsValid = false;
157    setInputStatus('displayInterval','','valid');
158    if (frm.fromdate.value != null && frm.fromdate.value != '')
159    {
160      frm.fromdate.value = autoFillDate(frm.fromdate.value);     
161      if (!Dates.isDate(frm.fromdate.value, 'yyyyMMdd'))
162      {
163        setInputStatus('displayInterval','Not a valid from-date', 'invalid');
164        return;
165      }
166      else
167      {
168        fdate = frm.fromdate.value;
169        fdate = new Date(fdate.substr(0,4), parseInt(fdate.substr(4,2), 10)-1, fdate.substr(6,2));
170      }
171    }
172   
173    if (frm.todate.value != null && frm.todate.value != '')
174    {
175      frm.todate.value = autoFillDate(frm.todate.value);
176      if (!Dates.isDate(frm.todate.value, 'yyyyMMdd'))
177      {
178        setInputStatus('displayInterval', 'Not a valid to-date', 'invalid');
179        return;
180      }
181      else
182      {
183        tdate = frm.todate.value;
184        tdate = new Date(tdate.substr(0,4), parseInt(tdate.substr(4,2), 10)-1, tdate.substr(6,2));
185      }
186    }
187   
188    if (tdate != null && fdate != null)
189    {
190      if (fdate > tdate)
191      {
192        setInputStatus('displayInterval', 'Invalid period', 'invalid')
193        return;
194      }     
195    }
196    intervalIsValid = true;
197  }
198 
199  function goCreate()
200  {
201    if (!intervalIsValid) return;
202    var cellElement = document.getElementById('reportcell');
203    var frm = document.forms['reggie'];   
204    var reportType = frm.reporttype[frm.reporttype.selectedIndex].value;   
205    frm.fromdate.disabled = true;
206    frm.todate.disabled = true;
207    var sampleType = frm.sampletype[frm.sampletype.selectedIndex].value;   
208    if (reportType == 'samplecount')
209    {
210      frm.viewtype.disabled = true;
211      frm.sampletype.disabled = true;
212    }
213    else if (reportType == 'patientcount')
214    {
215      frm.viewtype.disabled = true;
216    }
217    else if (reportType == 'missingsampledatareport')
218    {
219      frm.sampletype.disabled = true;
220    }
221    Main.hide('gocreate');
222    Main.show('reportSection');
223    var url = 'SampleReport.servlet?ID=<%=ID%>&cmd='+reportType;   
224   
225    if (frm.fromdate.value != null) url += '&fdate='+frm.fromdate.value;
226    if (frm.todate.value != null) url += '&tdate='+frm.todate.value;
227    if (reportType == 'samplecount')
228    {     
229      if (frm.viewtype.value != null) url += '&vtype='+frm.viewtype.value;
230      if (frm.sampletype.value != null) url += '&stype='+frm.sampletype.value;
231    }
232    else if (reportType == 'patientcount')
233    {     
234      if (frm.viewtype.value != null) url += '&vtype='+frm.viewtype.value;
235    }
236    else if (reportType == 'missingsampledatareport')
237    {     
238      if (frm.sampletype.value != null) url += '&stype='+frm.sampletype.value;
239    }
240   
241    var request = Ajax.getXmlHttpRequest();
242    request.open("GET", url, false);
243    request.send(null);
244   
245    if (debug) Main.debug(request.responseText);   
246    var response = JSON.parse(request.responseText); 
247    if (response.status != 'ok')
248    {
249      setFatalError(response.message);
250      return false;
251    }
252    var report = response.report;
253    var permissionDeniedForPatientName = report.permissionDeniedForPatientName;
254    var reportTable;
255   
256    if (report != null)
257    {
258      if ('samplecount' == reportType)
259      {     
260        reportTable = createItemCountReport(report, reportType);
261      }
262      else if ('consentcount' == reportType)
263      {     
264        reportTable = createConsentCountReport(report);
265      }
266      else if ('patientcount' == reportType)
267      {     
268        reportTable = createItemCountReport(report, reportType);
269      }
270      else if ('overviewreport' == reportType)
271      {     
272        reportTable = createOverviewReport(report);
273      }
274      else if ('missingsampledatareport' == reportType)
275      {     
276        reportTable = createMissingSampleDataReport(report);
277      }
278    }
279    else
280    {
281      var messageCell = getTableCellElement('No values could be found during given period', 'reportheader');
282      var messageRow = document.createElement('tr');
283      messageRow.appendChild(messageCell);     
284      var messageTable = getReportTable();
285      messageTable.appendChild(messageRow);
286      reportTable = messageTable;     
287    }
288    setInnerHTML('reportcell', '');
289    cellElement.appendChild(reportTable);
290    // Optional extra tables
291    if ('consentcount' == reportType)
292    {
293      var spacer = document.createElement('text');
294      spacer.innerHTML = "<BR>";
295      cellElement.appendChild(spacer);
296      var unknownDateTable = createConsentCountUnknownDateTable(report);
297      cellElement.appendChild(unknownDateTable);
298    }
299    else if ('overviewreport' == reportType)
300    {
301      var spacer = document.createElement('text');
302      spacer.innerHTML = "<BR>";
303      cellElement.appendChild(spacer);
304      var patientDetailedTable = createOverviewPatientDetailedTable(report);
305      cellElement.appendChild(patientDetailedTable);
306    }
307    // Summary list
308    var summaryList = document.createElement('ul');
309    if (unknownSite == null) unknownSite = 0;
310    if (unknownCreation == null) unknownCreation = 0;
311    if ('samplecount' == reportType)
312    {
313      var samples = 'specimens';
314      if ('nospecimen' == sampleType)
315      {
316        samples = '"no specimens"';
317      }
318      else if ('blood' == sampleType)
319      {
320        samples = 'blood samples';
321      }
322      summaryList.appendChild(getListElement(unknownSite + ' ' + samples + ' registered to unknown sites.'));
323      summaryList.appendChild(getListElement(unknownCreation + ' ' + samples + ' without creation date. These are included in the \'Total\' column.'));
324    }
325    else if ('consentcount' == reportType)
326    {
327      var numDuplicates = 0;
328      if (report != null)
329      {
330        var statistics = report.statistics;
331        numDuplicates = statistics.duplicateKey;
332      }
333      if (numDuplicates == null)
334      {
335        numDuplicates = 0;
336      }
337      summaryList.appendChild(getListElement(unknownSite + ' consents registered to unknown sites.'));
338      summaryList.appendChild(getListElement(unknownCreation + ' consents without known date. These are included in the \'Total\' column.'));
339      summaryList.appendChild(getListElement(numDuplicates + ' duplicates ignored.'));
340
341      var patientsWithMultipleDates = statistics.patientsWithMultipleDatesKey;
342      var counter = 0;
343      for (var key in patientsWithMultipleDates)
344      {
345        counter++;
346      }
347      var patientsWithMultipleDatesText = counter + ' patients with multiple dates.';
348      summaryList.appendChild(getListElement(patientsWithMultipleDatesText));
349    }
350    else if ('patientcount' == reportType)
351    {
352      summaryList.appendChild(getListElement(unknownSite + ' patients registered to unknown sites.'));
353      summaryList.appendChild(getListElement(unknownCreation + ' patients without creation date. These are included in the \'Total\' column.'));
354    }
355    else if ('overviewreport' == reportType)
356    {
357      summaryList.appendChild(getListElement(unknownSite + ' patients registered to unknown sites.'));
358      summaryList.appendChild(getListElement(numPatientsNoSamples + ' patients with no samples.'));
359      summaryList.appendChild(getListElement('Note: Consents of type "Yes" include consents without patient id (PAT#) or date.'));
360    }
361    else if ('missingsampledatareport' == reportType)
362    {
363      summaryList.appendChild(getListElement('Note: Patient name is considered missing if either "all first names" or "family name" is missing.'));
364      if ('true' == permissionDeniedForPatientName)
365      {
366        var patientNamePermissionWarningIconWithMessage = document.createElement('img');
367        patientNamePermissionWarningIconWithMessage.innerHTML = '<img src="images/warning.png"> Sorry, logged-in user does not have permission to check patient names.</img>';
368        var patientNamePermissionWarningListElement = document.createElement('li');
369        patientNamePermissionWarningListElement.appendChild(patientNamePermissionWarningIconWithMessage);
370        summaryList.appendChild(patientNamePermissionWarningListElement);
371      }
372    }
373    cellElement.appendChild(summaryList);
374    if ('consentcount' == reportType)
375    {
376      // Add table with patients with consents with multiple dates
377      var multipleDatesTable = createConsentTablePatientsWithMultipleDates(report);
378      cellElement.appendChild(multipleDatesTable);
379    }
380    Main.show('gorestart');   
381  }
382 
383  function createItemCountReport(report, reportType)
384  {
385    var reportTable = getReportTable();
386    var sdString = report.beginDate;
387    var edString = report.endDate;
388    var psdString = report.periodBeginDate;
389    var ldString = report.latestDate;
390    var startDate = dateStrToDate(sdString);
391    var endDate = dateStrToDate(edString);
392    var periodStartDate = dateStrToDate(psdString);
393    var latestDate = dateStrToDate(ldString);
394   
395    var viewType = report.viewType;   
396    var sampleType = report.sampleType;
397 
398    var headerRow = document.createElement('tr');   
399    var subHeaderRowYear = document.createElement('tr');
400    var columnHeaderRow = document.createElement('tr');
401   
402    var headerText = '# Items by ';
403    var startDateStr = addHyphensToDateString(sdString);
404    var endDateStr = addHyphensToDateString(edString);
405    var latestDateStr = addHyphensToDateString(ldString);
406    if ('samplecount' == reportType)
407    {
408      headerText = '# Specimens by ';
409      if ('nospecimen' == sampleType)
410      {
411        headerText = '# "No specimens" by ';
412      }
413      else if ('blood' == sampleType)
414      {
415        headerText = '# Blood samples by ';
416      }
417    }
418    else if ('patientcount' == reportType)
419    {
420      headerText = '# Patients by ';
421    }
422    if (viewType == 'WEEK')
423    {
424      var startWeek = getISOWeekNumber(periodStartDate);
425      var endWeek = getISOWeekNumber(endDate);
426      var tempDate = new Date(periodStartDate.getFullYear(), periodStartDate.getMonth(), periodStartDate.getDate()-periodStartDate.getDay()+1);
427      numCols = 0;
428      while (tempDate < endDate)
429      {
430        numCols++;
431        tempDate.setDate(tempDate.getDate()+7);
432      }
433      headerText += 'week';
434    }
435    else if (viewType == 'MONTH')
436    {
437      numCols = (endDate.getFullYear()-periodStartDate.getFullYear())*12 + endDate.getMonth()-periodStartDate.getMonth()+1;
438      headerText += 'month';
439    }
440    else if (viewType == 'QUARTER')
441    {
442      // First year (from start quarter to end of year)
443      numCols = 4 - Math.floor(periodStartDate.getMonth()/3);
444      // Last year (from start of year to end quarter) 
445      numCols += Math.floor(endDate.getMonth()/3)+1;
446      // If first and last year is the same, subtract 4 quarters
447      if (endDate.getFullYear() - periodStartDate.getFullYear() == 0)
448      {
449        numCols -= 4;
450      }
451      // Full years between start and end dates
452      if((endDate.getFullYear() - periodStartDate.getFullYear()) > 1)
453      {
454        numCols += 4 * (endDate.getFullYear() - periodStartDate.getFullYear()-1);
455      }
456      headerText += 'quarter';
457    }
458    else
459    {
460      numCols = endDate.getFullYear() - periodStartDate.getFullYear() + 1;
461      headerText += 'year';
462    }
463     
464    // Set table header
465    headerText += ' (between ' + startDateStr + ' and ' + endDateStr + ')';
466    if (latestDate != null)
467    {
468      headerText += '\nLast registration ' + latestDateStr;
469    }   
470    headerRow.appendChild(getTableCellElement(headerText, 'reportheader', (numCols+5)));
471   
472    // Sub headers
473    // Only if each datacol is less then a year
474    if (viewType != 'YEAR')
475    {
476      subHeaderRowYear.appendChild(getTableCellElement('', 'reportsubheader', 3));
477      addYearSubHeaders(periodStartDate, endDate, subHeaderRowYear, viewType);     
478      subHeaderRowYear.appendChild(getTableCellElement('', 'reportsubheader', 2));
479    }   
480         
481    // Columnsheader   
482    var siteHeader = getTableCellElement('Site', 'reportsubheader');     
483    var startDateHeader = getTableCellElement('Start date','reportsubheader');
484    var latestDateHeader = getTableCellElement('Latest date','reportsubheader');
485    columnHeaderRow.appendChild(siteHeader);
486    columnHeaderRow.appendChild(startDateHeader);
487    columnHeaderRow.appendChild(latestDateHeader); 
488   
489    if (viewType == 'MONTH') addMonthColumnHeaders(columnHeaderRow, periodStartDate);
490    else if (viewType == 'WEEK') addWeekColumnHeaders(columnHeaderRow, periodStartDate);
491    else if (viewType == 'QUARTER') addQuarterColumnHeaders(columnHeaderRow, periodStartDate);
492    else if (viewType == 'YEAR') addYearSubHeaders(periodStartDate, endDate, columnHeaderRow, viewType);
493   
494   
495    columnHeaderRow.appendChild(getTableCellElement('Sum', 'reportsubheader'));
496    columnHeaderRow.appendChild(getTableCellElement('Total', 'reportsubheader'));
497
498    // Build table     
499    reportTable.appendChild(headerRow);
500    reportTable.appendChild(subHeaderRowYear);
501    reportTable.appendChild(columnHeaderRow);
502         
503    // Data rows     
504    addDataRowsToTable(report, reportTable);
505     
506    // Add a row with the combined numbers for all sites for each period
507    var sitesCombinedRow = document.createElement('tr');
508    sitesCombinedRow.appendChild(getTableCellElement('Sites combined', 'colsummary'));
509    sitesCombinedRow.appendChild(getTableCellElement('', 'colsummary', 2));
510    // Get combined numbers for all sites for each period
511    var statistics = report.statistics;
512    var sitesCombined = statistics.sitesCombinedKey;   
513    var sortedKeyArray = createSortedPeriodArray(report, numCols);
514    var key;
515    for (arrayIndex in sortedKeyArray)
516    {
517      key = sortedKeyArray[arrayIndex];
518      var data = getJSONData(sitesCombined, key, 0);
519      // Add entry with sample sum for site for selected time period
520      sitesCombinedRow.appendChild(getTableCellElement(data,'colsummary'));
521    }
522    // Get total number of samples for site for the selected time period
523    var sum = getJSONData(statistics, 'sumKey', 0);
524    // Add entry with total number of samples for site for the selected time period
525    sitesCombinedRow.appendChild(getTableCellElement(sum, 'colsummary'));
526    // Get total number of samples for all sites, regardless of creation date
527    var total = getJSONData(statistics, 'totalKey', 0);
528    // Add entry with total number of samples for all sites, regardless of creation date
529    sitesCombinedRow.appendChild(getTableCellElement(total, 'colsummary'));
530    reportTable.appendChild(sitesCombinedRow); 
531
532    return reportTable;
533  }
534 
535  function createConsentCountReport(report)
536  {
537    var reportTable = getReportTable();
538    var sdString = report.beginDate;
539    var edString = report.endDate;
540    var ldString = report.latestDate;
541    var startDate = dateStrToDate(sdString);
542    var endDate = dateStrToDate(edString);
543    var latestDate = dateStrToDate(ldString);
544
545    var headerRow = document.createElement('tr');   
546    var subHeaderRow = document.createElement('tr');
547    var columnHeaderRow = document.createElement('tr');
548   
549    var numCols = 5;
550    var numDecimals = 0;
551    var headerText = '# Consent forms of different types for cases and blood samples';
552    var startDateStr = addHyphensToDateString(sdString);
553    var endDateStr = addHyphensToDateString(edString);
554    var latestDateStr = addHyphensToDateString(ldString);
555    headerText += ' (betweeen ' + startDateStr + ' and ' + endDateStr + ')';
556    if (latestDate != null)
557    {
558        headerText += '\nLast registration ' + latestDateStr;
559    }
560    headerRow.appendChild(getTableCellElement(headerText, 'reportheader', (numCols+5)));
561   
562    // Subheader   
563    subHeaderRow.appendChild(getTableCellElement('', 'reportsubheader', 3));
564   
565    subHeaderRow.appendChild(getTableCellElement('Yes', 'reportsubheader'));
566    subHeaderRow.appendChild(getTableCellElement('Yes', 'reportsubheader'));
567    subHeaderRow.appendChild(getTableCellElement('No', 'reportsubheader'));
568    subHeaderRow.appendChild(getTableCellElement('Not asked', 'reportsubheader'));
569    subHeaderRow.appendChild(getTableCellElement('Unknown date', 'reportsubheader'));
570    subHeaderRow.appendChild(getTableCellElement('', 'reportsubheader', 2));
571
572    // Columnsheader   
573    var siteHeader = getTableCellElement('Site', 'reportsubheader');     
574    var startDateHeader = getTableCellElement('Start date','reportsubheader');
575    var latestDateHeader = getTableCellElement('Latest date','reportsubheader');
576    columnHeaderRow.appendChild(siteHeader);
577    columnHeaderRow.appendChild(startDateHeader);
578    columnHeaderRow.appendChild(latestDateHeader); 
579   
580    columnHeaderRow.appendChild(getTableCellElement('(has PAT#)', 'reportsubheader'));
581    columnHeaderRow.appendChild(getTableCellElement('(no PAT#)', 'reportsubheader'));
582    columnHeaderRow.appendChild(getTableCellElement('(has date)', 'reportsubheader'));
583    columnHeaderRow.appendChild(getTableCellElement('(has date)', 'reportsubheader'));
584    columnHeaderRow.appendChild(getTableCellElement('', 'reportsubheader'));
585    columnHeaderRow.appendChild(getTableCellElement('Sum', 'reportsubheader'));
586    columnHeaderRow.appendChild(getTableCellElement('Total', 'reportsubheader'));
587
588    // Build table     
589    reportTable.appendChild(headerRow);
590    reportTable.appendChild(subHeaderRow);
591    reportTable.appendChild(columnHeaderRow);
592         
593    // Data rows     
594    addDataRowsToConsentTable(report, reportTable);
595     
596    // Add a row with the combined numbers for all sites for each period
597    var sitesCombinedRow = document.createElement('tr');
598    sitesCombinedRow.appendChild(getTableCellElement('Sites combined', 'colsummary'));
599    sitesCombinedRow.appendChild(getTableCellElement('', 'colsummary', 2));
600    // Get combined numbers for all sites for each period
601    var noDateKey = 'noDate';
602    var sumKey = 'sumKey';
603    var statistics = report.statistics;
604    var sitesCombined = statistics.sitesCombinedKey;
605    if (sitesCombined != null)
606    {
607      data = getJSONDataWithPercent(sitesCombined, 'yesPatient', sumKey, numDecimals);
608      sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
609      data = getJSONDataWithPercent(sitesCombined, 'yesNoPatient', sumKey, numDecimals);
610      sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
611      data = getJSONDataWithPercent(sitesCombined, 'no', sumKey, numDecimals);
612      sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
613      data = getJSONDataWithPercent(sitesCombined, 'notAsked', sumKey, numDecimals);
614      sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
615      data = getJSONDataWithPercent(sitesCombined, noDateKey, sumKey, numDecimals);
616      sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
617    }
618    // Add entry with total number of consents with chosen restrictions
619    data = getJSONData(sitesCombined, sumKey, 0);
620    sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
621    // Add entry with total number of consents, regardless of restrictions
622    var totalKey = 'totalKey';
623    data = getJSONData(sitesCombined, totalKey, 0);
624    sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
625    reportTable.appendChild(sitesCombinedRow); 
626
627    return reportTable;
628  }
629 
630  function createConsentCountUnknownDateTable(report)
631  {
632    var reportTable = getReportTable();
633    var headerRow = document.createElement('tr');   
634    var subHeaderRow = document.createElement('tr');
635    var columnHeaderRow = document.createElement('tr');
636   
637    var numCols = 4;
638    var numDecimals = 0;
639    var headerText = '# Consent forms of different types for cases and blood samples, unknown consent date';
640    headerRow.appendChild(getTableCellElement(headerText, 'reportheader', (numCols+5)));
641   
642    // Subheader   
643    subHeaderRow.appendChild(getTableCellElement('', 'reportsubheader', 3));
644   
645    subHeaderRow.appendChild(getTableCellElement('Yes', 'reportsubheader'));
646    subHeaderRow.appendChild(getTableCellElement('No', 'reportsubheader'));
647    subHeaderRow.appendChild(getTableCellElement('Not asked', 'reportsubheader'));
648    subHeaderRow.appendChild(getTableCellElement('Missing', 'reportsubheader'));
649    subHeaderRow.appendChild(getTableCellElement('', 'reportsubheader', 2));
650
651    // Columnsheader   
652    var siteHeader = getTableCellElement('Site', 'reportsubheader');     
653    var startDateHeader = getTableCellElement('Start date','reportsubheader');
654    var latestDateHeader = getTableCellElement('Latest date','reportsubheader');
655    columnHeaderRow.appendChild(siteHeader);
656    columnHeaderRow.appendChild(startDateHeader);
657    columnHeaderRow.appendChild(latestDateHeader); 
658   
659    columnHeaderRow.appendChild(getTableCellElement('(no date)', 'reportsubheader'));
660    columnHeaderRow.appendChild(getTableCellElement('(no date)', 'reportsubheader'));
661    columnHeaderRow.appendChild(getTableCellElement('(no date)', 'reportsubheader'));
662    columnHeaderRow.appendChild(getTableCellElement('', 'reportsubheader'));
663    columnHeaderRow.appendChild(getTableCellElement('Sum', 'reportsubheader'));
664    columnHeaderRow.appendChild(getTableCellElement('Total', 'reportsubheader'));
665
666    // Build table     
667    reportTable.appendChild(headerRow);
668    reportTable.appendChild(subHeaderRow);
669    reportTable.appendChild(columnHeaderRow);
670         
671    // Data rows     
672    addDataRowsToConsentTableUnknownDate(report, reportTable);
673     
674    // Add a row with the combined numbers for all sites
675    var sitesCombinedRow = document.createElement('tr');
676    sitesCombinedRow.appendChild(getTableCellElement('Sites combined', 'colsummary'));
677    sitesCombinedRow.appendChild(getTableCellElement('', 'colsummary', 2));
678    // Get combined numbers for all sites
679    var sumKey = 'sumKey';
680    var statistics = report.statistics;
681    var sitesCombined = statistics.sitesCombinedKey;
682    if (sitesCombined != null)
683    {
684      data = getJSONDataWithPercent(sitesCombined, 'yesNoDate', sumKey, numDecimals);
685      sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
686      data = getJSONDataWithPercent(sitesCombined, 'noNoDate', sumKey, numDecimals);
687      sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
688      data = getJSONDataWithPercent(sitesCombined, 'notAskedNoDate', sumKey, numDecimals);
689      sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
690      data = getJSONDataWithPercent(sitesCombined, 'missing', sumKey, numDecimals);
691      sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
692    }
693    // Add entry with total number of consents with chosen restrictions
694    var noDateKey = 'noDate';
695    data = getJSONData(sitesCombined, noDateKey, 0);
696    sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
697    // Add entry with total number of consents, regardless of restrictions
698    var totalKey = 'totalKey';
699    data = getJSONData(sitesCombined, totalKey, 0);
700    sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
701    reportTable.appendChild(sitesCombinedRow); 
702
703    return reportTable;
704  }
705 
706  function createOverviewReport(report)
707  {
708    var reportTable = getReportTable();
709    var sdString = report.beginDate;
710    var edString = report.endDate;
711    var ldString = report.latestDate;
712    var startDate = dateStrToDate(sdString);
713    var endDate = dateStrToDate(edString);
714    var latestDate = dateStrToDate(ldString);
715 
716    var headerRow = document.createElement('tr');   
717    var subHeaderRow = document.createElement('tr');
718    var subHeader2Row = document.createElement('tr');
719    var columnHeaderRow = document.createElement('tr');
720   
721    var numCols = 6;
722    var numDecimals = 0;
723    var headerText = 'Number of items of different kinds';
724    var startDateStr = addHyphensToDateString(sdString);
725    var endDateStr = addHyphensToDateString(edString);
726    var latestDateStr = addHyphensToDateString(ldString);
727    headerText += ' (betweeen ' + startDateStr + ' and ' + endDateStr + ')';
728    if (latestDate != null)
729    {
730        headerText += '\nLast registration ' + latestDateStr;
731    }
732    headerRow.appendChild(getTableCellElement(headerText, 'reportheader', (numCols+3)));
733   
734    // Subheader
735    subHeaderRow.appendChild(getTableCellElement('', 'reportsubheader', 3));
736   
737    subHeaderRow.appendChild(getTableCellElement('Patients', 'reportsubheader'));
738    subHeaderRow.appendChild(getTableCellElement('Blood', 'reportsubheader'));
739    subHeaderRow.appendChild(getTableCellElement('Specimens', 'reportsubheader'));
740    subHeaderRow.appendChild(getTableCellElement('No specimens', 'reportsubheader'));
741    subHeaderRow.appendChild(getTableCellElement('Consents', 'reportsubheader'));
742    subHeaderRow.appendChild(getTableCellElement('Consents', 'reportsubheader'));
743
744    // Columnsheader   
745    var siteHeader = getTableCellElement('Site', 'reportsubheader');     
746    var startDateHeader = getTableCellElement('Start date','reportsubheader');
747    var latestDateHeader = getTableCellElement('Latest date','reportsubheader');
748    columnHeaderRow.appendChild(siteHeader);
749    columnHeaderRow.appendChild(startDateHeader);
750    columnHeaderRow.appendChild(latestDateHeader); 
751   
752    columnHeaderRow.appendChild(getTableCellElement('', 'reportsubheader'));
753    columnHeaderRow.appendChild(getTableCellElement('samples', 'reportsubheader'));
754    columnHeaderRow.appendChild(getTableCellElement('', 'reportsubheader'));
755    columnHeaderRow.appendChild(getTableCellElement('', 'reportsubheader'));
756    columnHeaderRow.appendChild(getTableCellElement('(Yes)', 'reportsubheader'));
757    columnHeaderRow.appendChild(getTableCellElement('missing', 'reportsubheader'));
758
759    // Build table     
760    reportTable.appendChild(headerRow);
761    reportTable.appendChild(subHeaderRow);
762    reportTable.appendChild(subHeader2Row);
763    reportTable.appendChild(columnHeaderRow);
764         
765    // Data rows     
766    addDataRowsToOverviewTable(report, reportTable);
767     
768    // Add a row with the combined numbers for all sites for each period
769    var sitesCombinedRow = document.createElement('tr');
770    sitesCombinedRow.appendChild(getTableCellElement('Sites combined', 'colsummary'));
771    sitesCombinedRow.appendChild(getTableCellElement('', 'colsummary', 2));
772    // Get combined numbers for all sites for each period
773    var noDateKey = 'noDate';
774    var sumKey = 'sumKey';
775    var statistics = report.statistics;
776    // Get values for use in summary section
777    numPatientsNoSamples = statistics.patientNoSamples;
778    var sitesCombined = statistics.sitesCombinedKey;
779    if (sitesCombined != null)
780    {
781      data = getJSONData(sitesCombined, 'patient');
782      sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
783      data = getJSONData(sitesCombined, 'bloodSample');
784      sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
785      data = getJSONData(sitesCombined, 'specimen');
786      sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
787      data = getJSONData(sitesCombined, 'noSpecimen');
788      sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
789      data = getJSONData(sitesCombined, 'consentYes');
790      sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
791      data = getJSONData(sitesCombined, 'consentMissing');
792      sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
793    }
794    reportTable.appendChild(sitesCombinedRow); 
795
796    return reportTable;
797  }
798 
799  function createOverviewPatientDetailedTable(report)
800  {
801    var reportTable = getReportTable();
802    var sdString = report.beginDate;
803    var edString = report.endDate;
804    var ldString = report.latestDate;
805    var startDate = dateStrToDate(sdString);
806    var endDate = dateStrToDate(edString);
807 
808    var headerRow = document.createElement('tr');   
809    var subHeaderRow = document.createElement('tr');
810    var subHeader2Row = document.createElement('tr');
811    var columnHeaderRow = document.createElement('tr');
812   
813    var numCols = 8;
814    var numDecimals = 0;
815    var headerText = 'Patient records of different kinds';
816    var startDateStr = addHyphensToDateString(sdString);
817    var endDateStr = addHyphensToDateString(edString);
818    var latestDateStr = addHyphensToDateString(ldString);
819    headerText += ' (betweeen ' + startDateStr + ' and ' + endDateStr + ')';
820/*
821    if (latestDate != null)
822    {
823        headerText += '\nLast registration ' + latestDateStr;
824    }
825*/
826    headerRow.appendChild(getTableCellElement(headerText, 'reportheader', (numCols+2)));
827   
828    // Subheader
829    subHeaderRow.appendChild(getTableCellElement('', 'reportsubheader', 2));
830   
831    subHeaderRow.appendChild(getTableCellElement('Patients', 'reportsubheader'));
832    subHeaderRow.appendChild(getTableCellElement('Patients', 'reportsubheader'));
833    subHeaderRow.appendChild(getTableCellElement('Patients', 'reportsubheader'));
834    subHeaderRow.appendChild(getTableCellElement('Patients', 'reportsubheader'));
835    subHeaderRow.appendChild(getTableCellElement('Patients', 'reportsubheader'));
836    subHeaderRow.appendChild(getTableCellElement('Patients', 'reportsubheader'));
837    subHeaderRow.appendChild(getTableCellElement('Patients', 'reportsubheader'));
838    //subHeaderRow.appendChild(getTableCellElement('Patients', 'reportsubheader'));
839    subHeaderRow.appendChild(getTableCellElement('', 'reportsubheader'));
840
841    // Subheader 2
842    subHeader2Row.appendChild(getTableCellElement('', 'reportsubheader', 2));
843   
844    subHeader2Row.appendChild(getTableCellElement('(blood', 'reportsubheader'));
845    subHeader2Row.appendChild(getTableCellElement('(spec.', 'reportsubheader'));
846    subHeader2Row.appendChild(getTableCellElement('(no spec.', 'reportsubheader'));
847    subHeader2Row.appendChild(getTableCellElement('(blood and', 'reportsubheader'));
848    subHeader2Row.appendChild(getTableCellElement('(blood and', 'reportsubheader'));
849    subHeader2Row.appendChild(getTableCellElement('(spec. and', 'reportsubheader'));
850    subHeader2Row.appendChild(getTableCellElement('(blood, spec.,', 'reportsubheader'));
851    //subHeader2Row.appendChild(getTableCellElement('(no samples)', 'reportsubheader'));
852    subHeader2Row.appendChild(getTableCellElement('', 'reportsubheader'));
853
854    // Columnsheader   
855    var siteHeader = getTableCellElement('Site', 'reportsubheader');     
856    var startDateHeader = getTableCellElement('Start date','reportsubheader');
857    //var latestDateHeader = getTableCellElement('Latest date','reportsubheader');
858    columnHeaderRow.appendChild(siteHeader);
859    columnHeaderRow.appendChild(startDateHeader);
860    //columnHeaderRow.appendChild(latestDateHeader); 
861   
862    columnHeaderRow.appendChild(getTableCellElement('only)', 'reportsubheader'));
863    columnHeaderRow.appendChild(getTableCellElement('only)', 'reportsubheader'));
864    columnHeaderRow.appendChild(getTableCellElement('only)', 'reportsubheader'));
865    columnHeaderRow.appendChild(getTableCellElement('specimens)', 'reportsubheader'));
866    columnHeaderRow.appendChild(getTableCellElement('no spec.)', 'reportsubheader'));
867    columnHeaderRow.appendChild(getTableCellElement('no spec.)', 'reportsubheader'));
868    columnHeaderRow.appendChild(getTableCellElement('and no spec.)', 'reportsubheader'));
869    //columnHeaderRow.appendChild(getTableCellElement('', 'reportsubheader'));
870
871    columnHeaderRow.appendChild(getTableCellElement('Sum', 'reportsubheader'));
872
873    // Build table     
874    reportTable.appendChild(headerRow);
875    reportTable.appendChild(subHeaderRow);
876    reportTable.appendChild(subHeader2Row);
877    reportTable.appendChild(columnHeaderRow);
878         
879    // Data rows     
880    addDataRowsToOverviewPatientDetailedTable(report, reportTable);
881     
882    // Add a row with the combined numbers for all sites
883    var sitesCombinedRow = document.createElement('tr');
884    sitesCombinedRow.appendChild(getTableCellElement('Sites combined', 'colsummary'));
885    sitesCombinedRow.appendChild(getTableCellElement('', 'colsummary'));
886    // Get combined numbers for all sites
887    var noDateKey = 'noDate';
888    var sumKey = 'sumKey';
889    var statistics = report.statistics;
890    // Get values for use in summary section
891    numPatientsNoSamples = statistics.patientNoSamples;
892    var sitesCombined = statistics.sitesCombinedKey;
893    if (sitesCombined != null)
894    {
895      data = getJSONData(sitesCombined, 'patientBloodSampleOnly');
896      sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
897      data = getJSONData(sitesCombined, 'patientSpecimenOnly');
898      sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
899      data = getJSONData(sitesCombined, 'patientNoSpecimenOnly');
900      sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
901      data = getJSONData(sitesCombined, 'patientBloodSampleAndSpecimen');
902      sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
903      data = getJSONData(sitesCombined, 'patientBloodSampleAndNoSpecimen');
904      sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
905      data = getJSONData(sitesCombined, 'patientSpecimenAndNoSpecimen');
906      sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
907      data = getJSONData(sitesCombined, 'patientBloodSampleAndSpecimenAndNoSpecimen');
908      sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
909      //data = getJSONData(sitesCombined, 'patientNoSamples');
910      //sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
911      data = getJSONData(sitesCombined, 'sumKey');
912      sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
913    }
914    reportTable.appendChild(sitesCombinedRow); 
915
916    return reportTable;
917  }
918 
919  function createMissingSampleDataReport(report)
920  {
921    var reportTable = getReportTable();
922    var sdString = report.beginDate;
923    var edString = report.endDate;
924    var ldString = report.latestDate;
925    var startDate = dateStrToDate(sdString);
926    var endDate = dateStrToDate(edString);
927    var latestDate = dateStrToDate(ldString);
928
929    var sampleType = report.sampleType;
930    var permissionDeniedForPatientName = report.permissionDeniedForPatientName;
931
932    var headerRow = document.createElement('tr');   
933    var subHeaderRow = document.createElement('tr');
934    var subHeader2Row = document.createElement('tr');
935    var columnHeaderRow = document.createElement('tr');
936   
937    var numCols = 5;
938    if (sampleType == 'specimen')
939    {
940      numCols = 5;
941    }
942    else if (sampleType == 'nospecimen')
943    {
944      numCols = 2;
945    }
946    else if (sampleType == 'blood')
947    {
948      numCols = 3;
949    }
950    var numDecimals = 0;
951    var headerText = 'Number of missing specimen items of different kinds';
952    if ('nospecimen' == sampleType)
953    {
954      headerText = 'Number of missing "no specimen" items of different kinds';
955    }
956    else if ('blood' == sampleType)
957    {
958      headerText = 'Number of missing blood sample items of different kinds';
959    }
960    var startDateStr = addHyphensToDateString(sdString);
961    var endDateStr = addHyphensToDateString(edString);
962    var latestDateStr = addHyphensToDateString(ldString);
963    headerText += ' (betweeen ' + startDateStr + ' and ' + endDateStr + ')';
964    if (latestDate != null)
965    {
966        headerText += '\nLast registration ' + latestDateStr;
967    }
968    headerRow.appendChild(getTableCellElement(headerText, 'reportheader', (numCols+3)));
969   
970    // Subheader
971    subHeaderRow.appendChild(getTableCellElement('', 'reportsubheader', 3));
972   
973    subHeaderRow.appendChild(getTableCellElement('Patient', 'reportsubheader'));
974    if (sampleType == 'specimen')
975    {
976      subHeaderRow.appendChild(getTableCellElement('PAD', 'reportsubheader'));
977      subHeaderRow.appendChild(getTableCellElement('Laterality', 'reportsubheader'));
978      subHeaderRow.appendChild(getTableCellElement('Sampling', 'reportsubheader'));
979      subHeaderRow.appendChild(getTableCellElement('RNALater', 'reportsubheader'));
980    }
981    else if (sampleType == 'nospecimen')
982    {
983      subHeaderRow.appendChild(getTableCellElement('Sampling', 'reportsubheader'));
984    }
985    else if (sampleType == 'blood')
986    {
987      subHeaderRow.appendChild(getTableCellElement('Blood sampling', 'reportsubheader'));
988      subHeaderRow.appendChild(getTableCellElement('Blood freezer', 'reportsubheader'));
989    }
990
991    // Columnsheader   
992    var siteHeader = getTableCellElement('Site', 'reportsubheader');     
993    var startDateHeader = getTableCellElement('Start date','reportsubheader');
994    var latestDateHeader = getTableCellElement('Latest date','reportsubheader');
995    columnHeaderRow.appendChild(siteHeader);
996    columnHeaderRow.appendChild(startDateHeader);
997    columnHeaderRow.appendChild(latestDateHeader); 
998   
999    columnHeaderRow.appendChild(getTableCellElement('name', 'reportsubheader'));
1000    if (sampleType == 'specimen')
1001    {
1002      columnHeaderRow.appendChild(getTableCellElement('reference', 'reportsubheader'));
1003      columnHeaderRow.appendChild(getTableCellElement('', 'reportsubheader'));
1004      columnHeaderRow.appendChild(getTableCellElement('date', 'reportsubheader'));
1005      columnHeaderRow.appendChild(getTableCellElement('date', 'reportsubheader'));
1006    }
1007    else if (sampleType == 'nospecimen')
1008    {
1009      columnHeaderRow.appendChild(getTableCellElement('date', 'reportsubheader'));
1010    }
1011    else if (sampleType == 'blood')
1012    {
1013      columnHeaderRow.appendChild(getTableCellElement('date', 'reportsubheader'));
1014      columnHeaderRow.appendChild(getTableCellElement('date', 'reportsubheader'));
1015    }
1016
1017    // Build table     
1018    reportTable.appendChild(headerRow);
1019    reportTable.appendChild(subHeaderRow);
1020    reportTable.appendChild(columnHeaderRow);
1021         
1022    // Data rows     
1023    addDataRowsToMissingSampleDataTable(report, reportTable);
1024     
1025    // Add a row with the combined numbers for all sites for each period
1026    var sitesCombinedRow = document.createElement('tr');
1027    sitesCombinedRow.appendChild(getTableCellElement('Sites combined', 'colsummary'));
1028    sitesCombinedRow.appendChild(getTableCellElement('', 'colsummary', 2));
1029    // Get combined numbers for all sites for each period
1030    var noDateKey = 'noDate';
1031    var sumKey = 'sumKey';
1032    var statistics = report.statistics;
1033    var sitesCombined = statistics.sitesCombinedKey;
1034    if (sitesCombined != null)
1035    {
1036      if ('false' == permissionDeniedForPatientName)
1037      {
1038        data = getJSONData(sitesCombined, 'missingPatientName');
1039        sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
1040      }
1041      else
1042      {
1043        data = '-';
1044        sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
1045      }
1046      if (sampleType == 'specimen')
1047      {
1048        data = getJSONData(sitesCombined, 'missingPadReference');
1049        sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
1050        data = getJSONData(sitesCombined, 'missingLaterality');
1051        sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
1052        data = getJSONData(sitesCombined, 'missingSamplingDateTime');
1053        sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
1054        data = getJSONData(sitesCombined, 'missingRnaLaterDateTime');
1055        sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
1056      }
1057      else if (sampleType == 'nospecimen')
1058      {
1059        data = getJSONData(sitesCombined, 'missingSamplingDateTime');
1060        sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
1061      }
1062      else if (sampleType == 'blood')
1063      {
1064        data = getJSONData(sitesCombined, 'missingBloodSamplingDateTime');
1065        sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
1066        data = getJSONData(sitesCombined, 'missingBloodFreezerDateTime');
1067        sitesCombinedRow.appendChild(getTableCellElement(data, 'colsummary'));
1068      }
1069    }
1070    reportTable.appendChild(sitesCombinedRow); 
1071
1072    return reportTable;
1073  }
1074 
1075  function createConsentTablePatientsWithMultipleDates(report)
1076  {
1077    var multipleDatesTable = getReportTable();
1078    var headerRow = document.createElement('tr');   
1079    var columnHeaderRow = document.createElement('tr');
1080   
1081    // Table header
1082    var numCols = 3;
1083    var headerText = 'Consent forms with multiple dates for same patient';
1084    headerRow.appendChild(getTableCellElement(headerText, 'reportheader', numCols));
1085   
1086    // Columnsheader
1087    columnHeaderRow.appendChild(getTableCellElement('Patient ID', 'reportsubheader'));
1088    columnHeaderRow.appendChild(getTableCellElement('Date 1', 'reportsubheader'));
1089    columnHeaderRow.appendChild(getTableCellElement('Date 2', 'reportsubheader'));
1090
1091    // Build table     
1092    multipleDatesTable.appendChild(headerRow);
1093    multipleDatesTable.appendChild(columnHeaderRow);
1094         
1095    // Data rows
1096    if (report != null)
1097    {
1098      var statistics = report.statistics;
1099      var sessionId = statistics.sessionIdKey;
1100      var patientsWithMultipleDates = statistics.patientsWithMultipleDatesKey;
1101      var patientnamePatientid = statistics.patientnamePatientidKey;
1102      for (var patientName in patientsWithMultipleDates)
1103      {
1104        var tableRow = document.createElement('tr');
1105        // Add patient name to table
1106        var patientIdStr = patientnamePatientid[patientName];
1107        var columnCell = document.createElement('td');
1108        var patientLinkStr = createLinkStr(patientName, patientIdStr, 'BIOSOURCE', 'View this sample', sessionId);
1109        var tableCol = createTableCellElementHtml(patientLinkStr, 'reportdata');
1110        tableRow.appendChild(tableCol);
1111        // Add dates to table in chronological order
1112        var dateSet = patientsWithMultipleDates[patientName];
1113        var dateStr1 = '';
1114        var dateStr2 = '';
1115        for (var key in dateSet)
1116        {
1117          var dateStr = dateSet[key];
1118          if (dateStr1 == '')
1119          {
1120            dateStr1 = dateStr;
1121          }
1122          else if (dateStr > dateStr1)
1123          {
1124            dateStr2 = dateStr;
1125          }
1126          else
1127          {
1128            dateStr2 = dateStr1;
1129            dateStr1 = dateStr;
1130          }
1131        }
1132        var dateCol = '';
1133        dateCol = getTableCellElement(dateStr1, 'reportdata');
1134        tableRow.appendChild(dateCol);
1135        dateCol = getTableCellElement(dateStr2, 'reportdata');
1136        tableRow.appendChild(dateCol);
1137        multipleDatesTable.appendChild(tableRow);
1138      }
1139    }
1140
1141    return multipleDatesTable;
1142  }
1143 
1144  function addDataRowsToConsentTable(report, reportTable, numDecimals)
1145  {
1146    var sites = report.sites;   
1147    var statistics = report.statistics;
1148    unknownCreation = statistics.noDate;
1149    unknownSite = statistics.unknownSite;
1150    var siteOrderList = report.siteOrderListKey;
1151    for (var siteOrderIndex in siteOrderList)
1152    {
1153      var namePrefix = siteOrderList[siteOrderIndex];   
1154      if (!sites.hasOwnProperty(namePrefix)) continue;       
1155      var site = sites[namePrefix];
1156      var siteName = site.name;
1157      var siteStartDate = dateStrToDate(site.startDate);
1158      var siteStartDateStr = addHyphensToDateString(site.startDate);
1159     
1160      var siteData = statistics[namePrefix];     
1161      var siteLatestDate = siteData['latestDateKey'];
1162      var siteLatestDateStr = addHyphensToDateString(siteLatestDate);
1163      var tableRow = document.createElement('tr');
1164      var tableCol = getTableCellElement(siteName, 'rowtitle');
1165      tableRow.appendChild(tableCol);
1166      tableRow.appendChild(getTableCellElement(siteStartDateStr, 'reportdata'));
1167      tableRow.appendChild(getTableCellElement(siteLatestDateStr, 'reportdata'));
1168      var noDateKey = 'noDate';
1169      var sumKey = 'sumKey';
1170      var totalKey = 'totalKey';
1171      if (siteData != null)
1172      {
1173        data = getJSONDataWithPercent(siteData, 'yesPatient', sumKey, numDecimals);
1174        tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1175        data = getJSONDataWithPercent(siteData, 'yesNoPatient', sumKey, numDecimals);
1176        tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1177        data = getJSONDataWithPercent(siteData, 'no', sumKey, numDecimals);
1178        tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1179        data = getJSONDataWithPercent(siteData, 'notAsked', sumKey, numDecimals);
1180        tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1181        data = getJSONDataWithPercent(siteData, noDateKey, sumKey, numDecimals);
1182        tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1183        // Add column with summed values for site
1184        var siteSum = getJSONData(siteData, sumKey, 0);
1185        tableRow.appendChild(getTableCellElement(siteSum, 'rowsummary'));
1186      }
1187      // Add column with total number of samples for site, regardless of creation date
1188      var siteTotal = getJSONData(siteData, totalKey, 0);
1189      tableRow.appendChild(getTableCellElement(siteTotal, 'rowsummary'));
1190      reportTable.appendChild(tableRow);
1191    }
1192  }
1193
1194  function addDataRowsToConsentTableUnknownDate(report, reportTable, numDecimals)
1195  {
1196    var sites = report.sites;   
1197    var statistics = report.statistics;
1198    unknownCreation = statistics.noDate;
1199    unknownSite = statistics.unknownSite;
1200    var siteOrderList = report.siteOrderListKey;
1201    for (var siteOrderIndex in siteOrderList)
1202    {
1203      var namePrefix = siteOrderList[siteOrderIndex];   
1204      if (!sites.hasOwnProperty(namePrefix)) continue;       
1205      var site = sites[namePrefix];
1206      var siteName = site.name;
1207      var siteStartDate = dateStrToDate(site.startDate);
1208      var siteStartDateStr = addHyphensToDateString(site.startDate);
1209     
1210      var siteData = statistics[namePrefix];     
1211      var siteLatestDate = siteData['latestDateKey'];
1212      var siteLatestDateStr = addHyphensToDateString(siteLatestDate);
1213      var tableRow = document.createElement('tr');
1214      var tableCol = getTableCellElement(siteName, 'rowtitle');
1215      tableRow.appendChild(tableCol);
1216      tableRow.appendChild(getTableCellElement(siteStartDateStr, 'reportdata'));
1217      tableRow.appendChild(getTableCellElement(siteLatestDateStr, 'reportdata'));
1218      var noDateKey = 'noDate';
1219      var sumKey = 'sumKey';
1220      var totalKey = 'totalKey';
1221      if (siteData != null)
1222      {
1223        data = getJSONDataWithPercent(siteData, 'yesNoDate', sumKey, numDecimals);
1224        tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1225        data = getJSONDataWithPercent(siteData, 'noNoDate', sumKey, numDecimals);
1226        tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1227        data = getJSONDataWithPercent(siteData, 'notAskedNoDate', sumKey, numDecimals);
1228        tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1229        data = getJSONDataWithPercent(siteData, 'missing', sumKey, numDecimals);
1230        tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1231        // Add column with summed values for site
1232        var siteSum = getJSONData(siteData, noDateKey, 0);
1233        tableRow.appendChild(getTableCellElement(siteSum, 'rowsummary'));
1234      }
1235      // Add column with total number of samples for site, regardless of creation date
1236      var siteTotal = getJSONData(siteData, totalKey, 0);
1237      tableRow.appendChild(getTableCellElement(siteTotal, 'rowsummary'));
1238      reportTable.appendChild(tableRow);
1239    }
1240  }
1241
1242  function addDataRowsToOverviewTable(report, reportTable)
1243  {
1244    var sites = report.sites;   
1245    var statistics = report.statistics;
1246    unknownCreation = statistics.noDate;
1247    unknownSite = statistics.unknownSite;
1248    var siteOrderList = report.siteOrderListKey;
1249    for (var siteOrderIndex in siteOrderList)
1250    {
1251      var namePrefix = siteOrderList[siteOrderIndex];   
1252      if (!sites.hasOwnProperty(namePrefix)) continue;       
1253      var site = sites[namePrefix];
1254      var siteName = site.name;       
1255      var siteStartDate = dateStrToDate(site.startDate);
1256      var siteStartDateStr = addHyphensToDateString(site.startDate);
1257     
1258      var siteData = statistics[namePrefix];     
1259      var siteLatestDate = siteData['latestDateKey'];
1260      var siteLatestDateStr = addHyphensToDateString(siteLatestDate);
1261      var tableRow = document.createElement('tr');
1262      var tableCol = getTableCellElement(siteName, 'rowtitle');
1263      tableRow.appendChild(tableCol);
1264      tableRow.appendChild(getTableCellElement(siteStartDateStr, 'reportdata'));
1265      tableRow.appendChild(getTableCellElement(siteLatestDateStr, 'reportdata'));
1266      var noDateKey = 'noDate';
1267      var sumKey = 'sumKey';
1268      var totalKey = 'totalKey';
1269      if (siteData != null)
1270      {
1271        data = getJSONData(siteData, 'patient');
1272        tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1273        data = getJSONData(siteData, 'bloodSample');
1274        tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1275        data = getJSONData(siteData, 'specimen');
1276        tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1277        data = getJSONData(siteData, 'noSpecimen');
1278        tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1279        data = getJSONData(siteData, 'consentYes');
1280        tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1281        data = getJSONData(siteData, 'consentMissing');
1282        tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1283      }
1284      reportTable.appendChild(tableRow);
1285    }
1286  }
1287
1288  function addDataRowsToOverviewPatientDetailedTable(report, reportTable)
1289  {
1290    var sites = report.sites;   
1291    var statistics = report.statistics;
1292    unknownCreation = statistics.noDate;
1293    unknownSite = statistics.unknownSite;
1294    var siteOrderList = report.siteOrderListKey;
1295    for (var siteOrderIndex in siteOrderList)
1296    {
1297      var namePrefix = siteOrderList[siteOrderIndex];   
1298      if (!sites.hasOwnProperty(namePrefix)) continue;       
1299      var site = sites[namePrefix];
1300      var siteName = site.name;       
1301      var siteStartDate = dateStrToDate(site.startDate);
1302      var siteStartDateStr = addHyphensToDateString(site.startDate);
1303     
1304      var siteData = statistics[namePrefix];
1305/*   
1306      var siteLatestDate = siteData['latestDateKey'];
1307      var siteLatestDateStr = addHyphensToDateString(siteLatestDate);
1308*/
1309      var tableRow = document.createElement('tr');
1310      var tableCol = getTableCellElement(siteName, 'rowtitle');
1311      tableRow.appendChild(tableCol);
1312      tableRow.appendChild(getTableCellElement(siteStartDateStr, 'reportdata'));
1313/*
1314      tableRow.appendChild(getTableCellElement(siteLatestDateStr, 'reportdata'));
1315*/
1316      var noDateKey = 'noDate';
1317      var sumKey = 'sumKey';
1318      var totalKey = 'totalKey';
1319      if (siteData != null)
1320      {
1321        data = getJSONData(siteData, 'patientBloodSampleOnly');
1322        tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1323        data = getJSONData(siteData, 'patientSpecimenOnly');
1324        tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1325        data = getJSONData(siteData, 'patientNoSpecimenOnly');
1326        tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1327        data = getJSONData(siteData, 'patientBloodSampleAndSpecimen');
1328        tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1329        data = getJSONData(siteData, 'patientBloodSampleAndNoSpecimen');
1330        tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1331        data = getJSONData(siteData, 'patientSpecimenAndNoSpecimen');
1332        tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1333        data = getJSONData(siteData, 'patientBloodSampleAndSpecimenAndNoSpecimen');
1334        tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1335        //data = getJSONData(siteData, 'patientNoSamples');
1336        //tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1337        data = getJSONData(siteData, 'sumKey');
1338        tableRow.appendChild(getTableCellElement(data, 'rowsummary'));
1339      }
1340      reportTable.appendChild(tableRow);
1341    }
1342  }
1343
1344  function addDataRowsToMissingSampleDataTable(report, reportTable)
1345  {
1346    var sites = report.sites;   
1347    var statistics = report.statistics;
1348    var sampleType = report.sampleType;
1349    var permissionDeniedForPatientName = report.permissionDeniedForPatientName;
1350    var unknownCreation = statistics.noDate;
1351    var unknownSite = statistics.unknownSite;
1352    var siteOrderList = report.siteOrderListKey;
1353    for (var siteOrderIndex in siteOrderList)
1354    {
1355      var namePrefix = siteOrderList[siteOrderIndex];   
1356      if (!sites.hasOwnProperty(namePrefix)) continue;       
1357      var site = sites[namePrefix];
1358      var siteName = site.name;
1359      var siteStartDate = dateStrToDate(site.startDate);
1360      var siteStartDateStr = addHyphensToDateString(site.startDate);
1361     
1362      var siteData = statistics[namePrefix];     
1363      var siteLatestDate = siteData['latestDateKey'];
1364      var siteLatestDateStr = addHyphensToDateString(siteLatestDate);
1365      var tableRow = document.createElement('tr');
1366      var tableCol = getTableCellElement(siteName, 'rowtitle');
1367      tableRow.appendChild(tableCol);
1368      tableRow.appendChild(getTableCellElement(siteStartDateStr, 'reportdata'));
1369      tableRow.appendChild(getTableCellElement(siteLatestDateStr, 'reportdata'));
1370      //var currentDate = new Date(periodStartDate.getFullYear(), periodStartDate.getMonth(), periodStartDate.getDate());     
1371      var noDateKey = 'noDate';
1372      var sumKey = 'sumKey';
1373      var totalKey = 'totalKey';
1374      if (siteData != null)
1375      {
1376        if ('false' == permissionDeniedForPatientName)
1377        {
1378          data = getJSONData(siteData, 'missingPatientName');
1379          tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1380        }
1381        else
1382        {
1383          data = '-';
1384          tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1385        }
1386        if (sampleType == 'specimen')
1387        {
1388          data = getJSONData(siteData, 'missingPadReference');
1389          tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1390          data = getJSONData(siteData, 'missingLaterality');
1391          tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1392          data = getJSONData(siteData, 'missingSamplingDateTime');
1393          tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1394          data = getJSONData(siteData, 'missingRnaLaterDateTime');
1395          tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1396        }
1397        else if (sampleType == 'nospecimen')
1398        {
1399          data = getJSONData(siteData, 'missingSamplingDateTime');
1400          tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1401        }
1402        else if (sampleType == 'blood')
1403        {
1404          data = getJSONData(siteData, 'missingBloodSamplingDateTime');
1405          tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1406          data = getJSONData(siteData, 'missingBloodFreezerDateTime');
1407          tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1408        }
1409      }
1410      reportTable.appendChild(tableRow);
1411    }
1412  }
1413
1414  function createLinkStr(linkName, idStr, itemTypeStr, titleStr, sessionId)
1415  {
1416    var linkStr = '<span class="link" onclick="Main.itemOnClick(event, \'' + sessionId + '\', \'' + itemTypeStr + '\', ' + idStr + ', false)" title="' + titleStr + '">' + linkName + '</span>';
1417    return linkStr;
1418  }
1419
1420  function createTableCellElementHtml(html, clazz, colspan, rowspan)
1421  {
1422    var htmlStr = new String(html);
1423    var cellElement = document.createElement('td');
1424    cellElement.innerHTML = htmlStr;
1425    cellElement.setAttribute('class', clazz);
1426    if (colspan != null) cellElement.setAttribute('colspan', colspan);
1427    if (rowspan != null) cellElement.setAttribute('rowspan', rowspan);
1428   
1429    return cellElement;
1430  }
1431 
1432  function getJSONDataWithPercent(jsonObject, key, sumKey, numDecimals)
1433  {
1434    var dataNum = getJSONData(jsonObject, key);
1435    var dataSum = getJSONData(jsonObject, sumKey);
1436    var dataPct = '0';
1437    if (dataSum != null || dataSum != 0)
1438    {
1439      dataPct = 100*dataNum/dataSum;
1440      dataPct = dataPct.toFixed(numDecimals);
1441    }
1442    var data = dataNum + ' (' + dataPct + '%)';
1443    return data;
1444  }
1445
1446  function getJSONData(jsonObject, key)
1447  {
1448    var data = getJSONData(jsonObject, key, '');
1449    return data;
1450  }
1451
1452  function getJSONData(jsonObject, key, defaultChoice)
1453  {
1454    var data = defaultChoice;
1455    if (jsonObject != null)
1456    {
1457      if (jsonObject[key] != null)
1458      {
1459        data = jsonObject[key];
1460      }
1461    }
1462    /*
1463    else
1464    {
1465      data = 'jsonObject==null';
1466    }
1467    */
1468    return data;
1469  }
1470
1471  function addQuarterColumnHeaders(columnHeaderRow, startDate)
1472  {
1473    var currentDate = startDate;
1474    for (var i=0;i<numCols;i++)
1475    {
1476      var quarter = Math.floor(currentDate.getMonth()/3)+1;
1477      var columnText = 'Q'+quarter;
1478      var quarterHeader = getTableCellElement(columnText, 'reportsubheader');
1479      columnHeaderRow.appendChild(quarterHeader); 
1480      currentDate.setMonth(currentDate.getMonth()+3);     
1481    }
1482  }
1483 
1484  function addWeekColumnHeaders(columnHeaderRow, startDate)
1485  {
1486    var currentDate = startDate;
1487    var day = currentDate.getDay()-1;
1488    day = day>=0 ? day: day + 7;
1489    currentDate.setDate(currentDate.getDate()-day);
1490    for (var i=0;i<numCols;i++)
1491    {     
1492      var weekNum = getISOWeekNumber(currentDate);
1493      var columnText = weekNum;
1494      if (weekNum < 10) columnText = '0'+columnText;     
1495      columnHeaderRow.appendChild(getTableCellElement(columnText, 'reportsubheader'));
1496      currentDate.setDate(currentDate.getDate()+7);     
1497    }
1498  }
1499 
1500  function addMonthColumnHeaders(columnHeaderRow, startDate)
1501  {   
1502    var currentDate = new Date(startDate.getFullYear(), startDate.getMonth());
1503    for (var i=0;i<numCols;i++)
1504    {             
1505      var monthHeader = getTableCellElement(month[currentDate.getMonth()], 'reportsubheader');
1506      columnHeaderRow.appendChild(monthHeader);       
1507      currentDate.setMonth(currentDate.getMonth() +1);
1508    }   
1509  }
1510 
1511  function addYearSubHeaders(startDate, endDate, subHeaderRowYear, vt)
1512  {   
1513    var currentYear = startDate.getFullYear(); 
1514   
1515    var columnCounter = 0;   
1516    do
1517    {
1518      var colspan;
1519      var headerText = currentYear;
1520      if (vt == "MONTH")
1521      {
1522        if (currentYear == startDate.getFullYear())
1523        {
1524          colspan =  11-startDate.getMonth()+1;
1525          if (endDate.getFullYear() == currentYear)
1526          {
1527            colspan = colspan - (11-endDate.getMonth());
1528          }
1529        }
1530        else if (currentYear == endDate.getFullYear()) 
1531          colspan = endDate.getMonth()+1;
1532        else
1533          colspan = 12;
1534      }
1535      else if (vt == "WEEK")
1536      { 
1537        if (startDate.getFullYear() == endDate.getFullYear())
1538        {
1539          colspan = numCols;
1540        }
1541        else if (currentYear == startDate.getFullYear())
1542        {
1543          var startWeek = getISOWeekNumber(startDate);
1544          var lastDay = new Date(startDate.getFullYear(), 11, 31);
1545          var endWeek = getISOWeekNumber(lastDay);
1546          if (endWeek == 1)
1547          {
1548            lastDay.setDate(lastDay.getDate()-7);
1549            endWeek = getISOWeekNumber(lastDay);
1550          }
1551          colspan = endWeek - startWeek +1;
1552        }
1553        else if (currentYear == endDate.getFullYear())
1554        {
1555          var endWeek = getISOWeekNumber(endDate);
1556          colspan = endWeek;
1557        }
1558        else
1559        {
1560          var dateInLastWeek = new Date(currentYear, 11, 31);
1561          var endWeek = getISOWeekNumber(dateInLastWeek);
1562          if (endWeek == 1)
1563          {
1564            dateInLastWeek.setDate(dateInLastWeek.getDate()-7);
1565            endWeek = getISOWeekNumber(dateInLastWeek);
1566          }
1567          colspan = endWeek;
1568        }               
1569      }
1570      else if (vt == "QUARTER")
1571      {
1572        if (currentYear == startDate.getFullYear())
1573        {
1574          if (startDate.getFullYear() == endDate.getFullYear())
1575          {
1576            colspan = Math.floor((endDate.getMonth()-startDate.getMonth())/3)+1;
1577          }
1578          else
1579          {
1580            colspan = Math.floor((11-startDate.getMonth())/3) +1;
1581          }
1582        }
1583        else if(currentYear == endDate.getFullYear())
1584        {
1585          colspan = Math.floor(endDate.getMonth()/3)+1;
1586        }
1587        else 
1588        {
1589          colspan = 4;
1590        }
1591      }
1592      else if (vt == "YEAR")
1593      {
1594        colspan = 1;       
1595      }
1596      columnCounter += colspan;           
1597      subHeaderRowYear.appendChild(getTableCellElement(headerText, 'reportsubheader', colspan));
1598    }while(!(++currentYear>endDate.getFullYear()));
1599  }
1600 
1601  function addDataRowsToTable(report, reportTable)
1602  {
1603    var fdString = report.beginDate;
1604    var ldString = report.endDate;
1605    var psdString = report.periodBeginDate;
1606    var startDate = new Date();
1607    startDate.setYear(fdString.substr(0,4));
1608    startDate.setMonth(fdString.substr(4,2)-1);
1609    startDate.setDate(fdString.substr(6));
1610    var endDate = new Date();
1611    endDate.setYear(ldString.substr(0,4));
1612    endDate.setMonth(ldString.substr(4,2)-1);
1613    endDate.setDate(ldString.substr(6));
1614    var periodStartDate = new Date();
1615    periodStartDate.setYear(psdString.substr(0,4));
1616    periodStartDate.setMonth(psdString.substr(4,2)-1);
1617    periodStartDate.setDate(psdString.substr(6));
1618    var viewType = report.viewType;   
1619    var sites = report.sites;   
1620    var statistics = report.statistics;
1621    unknownCreation = statistics.noDate;
1622    unknownSite = statistics.unknownSite;
1623    var siteOrderList = report.siteOrderListKey;
1624    for (var siteOrderIndex in siteOrderList)
1625    {
1626      var namePrefix = siteOrderList[siteOrderIndex];   
1627      if (!sites.hasOwnProperty(namePrefix)) continue;
1628      var site = sites[namePrefix];
1629      var siteName = site.name;   
1630      var year = site.startDate.substr(0,4);
1631      var month = site.startDate.substr(5,2);
1632      var date = site.startDate.substr(8,2);     
1633      var siteStartDate = new Date(year, month-1, date);
1634     
1635      var siteData = statistics[namePrefix];
1636      var siteLatestDate = siteData['latestDateKey'];
1637      var siteLatestDateStr = '????-??-??';
1638      if (siteLatestDate != null)
1639      {
1640        var siteLatestDateYear = siteLatestDate.substr(0,4);
1641        var siteLatestDateMonth = siteLatestDate.substr(4,2);
1642        var siteLatestDateDate = siteLatestDate.substr(6,2);
1643        siteLatestDateStr = siteLatestDateYear + '-' + siteLatestDateMonth + '-' + siteLatestDateDate;
1644      }
1645      var tableRow = document.createElement('tr');
1646      var tableCol = getTableCellElement(siteName, 'rowtitle');
1647      tableRow.appendChild(tableCol);
1648      tableRow.appendChild(getTableCellElement(year+'-'+(month)+'-'+date, 'reportdata'));
1649      tableRow.appendChild(getTableCellElement(siteLatestDateStr, 'reportdata'));
1650      var currentDate = new Date(periodStartDate.getFullYear(), periodStartDate.getMonth(), periodStartDate.getDate());     
1651      var columnCounter = 0;
1652      do
1653      {
1654        var data = 0;
1655        var keyIndex;
1656        var yearIndex = currentDate.getFullYear();
1657       
1658        if (viewType == 'YEAR')
1659        {
1660          keyIndex = yearIndex;
1661          if (siteData != null)
1662          {
1663            if (siteData[keyIndex] != null) data = siteData[keyIndex];
1664          }
1665          if ( (currentDate.getFullYear() < siteStartDate.getFullYear()))
1666          {
1667            data = '';
1668          }
1669          currentDate.setFullYear(currentDate.getFullYear()+1);
1670        }
1671        else if (viewType == 'QUARTER')
1672        {
1673          var qIndex = Math.floor(currentDate.getMonth()/3) + 1;
1674          var startQuarter = Math.floor(siteStartDate.getMonth()/3)+1;
1675          keyIndex = yearIndex + '' + qIndex;
1676          if (siteData != null)
1677          {
1678            if (siteData[keyIndex] != null) data = siteData[keyIndex];           
1679          }         
1680          if ( (currentDate.getFullYear() <= siteStartDate.getFullYear()) && qIndex<startQuarter)
1681          {
1682            data = '';
1683          }
1684          currentDate.setMonth(currentDate.getMonth()+3);         
1685        }
1686        else if (viewType == 'MONTH')
1687        {
1688          var monthIndex = currentDate.getMonth()+1;
1689          var rowFill = monthIndex < 10 ? '0' : '';
1690          keyIndex = yearIndex + rowFill + monthIndex;
1691          if (siteData != null)
1692          {
1693            if (siteData[keyIndex] != null) data = siteData[keyIndex];
1694          }
1695          if (currentDate.getFullYear() <= siteStartDate.getFullYear() && (monthIndex-1) < siteStartDate.getMonth())
1696          {
1697            data = '';
1698          }
1699         
1700         
1701          currentDate.setMonth(currentDate.getMonth()+1);
1702        }
1703        else if (viewType == 'WEEK')
1704        {
1705          var weekIndex = getISOWeekNumber(currentDate);
1706          keyIndex = yearIndex + '' + weekIndex;
1707          if (siteData != null)
1708          {
1709            if (siteData[keyIndex] != null) data = siteData[keyIndex];
1710          }
1711          if (currentDate.getFullYear() <= siteStartDate.getFullYear() && getISOWeekNumber(currentDate) < getISOWeekNumber(siteStartDate))
1712          {
1713            data = '';
1714          }
1715          currentDate.setDate(currentDate.getDate()+7);
1716        }
1717       
1718        tableRow.appendChild(getTableCellElement(data, 'reportdata'));
1719        columnCounter++;       
1720      } while (columnCounter < numCols)
1721      // Add column with sample sum for site for the selected time period
1722      var siteSum = 0;
1723      if (siteData != null)
1724      {
1725        var sumSiteKey = 'sumSiteKey';
1726        if (siteData[sumSiteKey] != null)
1727        {
1728          siteSum = siteData[sumSiteKey];
1729        }
1730      }
1731      tableRow.appendChild(getTableCellElement(siteSum, 'rowsummary'));
1732      // Add column with total number of samples for site, regardless of creation date
1733      var siteTotal = 0;
1734      if (siteData != null)
1735      {
1736        var totalSiteKey = 'totalSiteKey';
1737        if (siteData[totalSiteKey] != null)
1738        {
1739          siteTotal = siteData[totalSiteKey];
1740        }
1741      }
1742      tableRow.appendChild(getTableCellElement(siteTotal, 'rowsummary'));
1743      reportTable.appendChild(tableRow);
1744    }
1745  }
1746 
1747  function createSortedPeriodArray(report, numberOfColumns)
1748  {
1749    var psdString = report.periodBeginDate;
1750    var periodStartDate = new Date();
1751    periodStartDate.setYear(psdString.substr(0,4));
1752    periodStartDate.setMonth(psdString.substr(4,2)-1);
1753    periodStartDate.setDate(psdString.substr(6));
1754    var viewType = report.viewType;   
1755    var sortedPeriodArray = Array(numberOfColumns);
1756    var currentDate = new Date(periodStartDate.getFullYear(), periodStartDate.getMonth(), periodStartDate.getDate());     
1757    var columnCounter = 0;
1758    do
1759    { 
1760      var keyIndex;
1761      var yearIndex = currentDate.getFullYear();
1762       
1763      if (viewType == 'YEAR')
1764      {
1765        keyIndex = yearIndex;
1766        currentDate.setFullYear(currentDate.getFullYear()+1);
1767      }
1768      else if (viewType == 'QUARTER')
1769      {
1770        var qIndex = Math.floor(currentDate.getMonth()/3) + 1;
1771        keyIndex = yearIndex + '' + qIndex;
1772        currentDate.setMonth(currentDate.getMonth()+3);         
1773      }
1774      else if (viewType == 'MONTH')
1775      {
1776        var monthIndex = currentDate.getMonth()+1;
1777        var rowFill = monthIndex < 10 ? '0' : '';
1778        keyIndex = yearIndex + rowFill + monthIndex;
1779        currentDate.setMonth(currentDate.getMonth()+1);
1780      }
1781      else if (viewType == 'WEEK')
1782      {
1783        var weekIndex = getISOWeekNumber(currentDate);
1784        keyIndex = yearIndex + '' + weekIndex;
1785        currentDate.setDate(currentDate.getDate()+7);
1786      }
1787      sortedPeriodArray[columnCounter] = keyIndex;
1788      columnCounter++;       
1789    } while (columnCounter < numberOfColumns)
1790    return sortedPeriodArray;
1791  }
1792 
1793  function getReportTable()
1794  {
1795      var reportTable = document.createElement('table');
1796      reportTable.setAttribute('class','reporttable');
1797      reportTable.setAttribute('border','1');     
1798      return reportTable;
1799  }
1800 
1801  function getTableCellElement(text, clazz, colspan, rowspan)
1802  {
1803    var cellElement = document.createElement('td');
1804    text = new String(text);   
1805    var textArray = text.split("\n");   
1806    if (textArray.length > 1)
1807    {
1808      for (var i=0;i<textArray.length;i++)
1809      {       
1810        if (i>0)cellElement.appendChild(document.createElement('br'));
1811        cellElement.appendChild(document.createTextNode(textArray[i]));
1812      }     
1813    }
1814    else
1815    {
1816      cellElement.appendChild(document.createTextNode(text));
1817    }
1818    cellElement.setAttribute('class', clazz);
1819    if (colspan != null) cellElement.setAttribute('colspan', colspan);
1820    if (rowspan != null) cellElement.setAttribute('rowspan', rowspan);
1821   
1822    return cellElement;
1823  }
1824 
1825  function getListElement(itemText)
1826  {
1827    var listElement = document.createElement('li');
1828    var textNode = document.createTextNode(itemText);
1829    listElement.appendChild(textNode);
1830    return listElement;
1831  }
1832
1833  /**
1834   *  addHyphensToDateStr()
1835   *
1836   *  Adds hyphens to date string in yyyymmdd format to
1837   *  get yyyy-mm-dd format. If input string already contains
1838   *  hyphen(s), the input string is returned unchanged.
1839   *  If input string is null or empty, '????-??-??' is returned.
1840   *
1841   *  @param dateStr String Input date string in yyyy-mm-dd or yyyymmdd format.
1842   *  @return String Date string in yyyy-mm-dd format.
1843   */
1844  function addHyphensToDateString(dateStr)
1845  {
1846    var dateWithHyphensStr = '????-??-??';
1847    if (dateStr != null && dateStr != '')
1848    {
1849      // Check if input string already contains hyphen
1850      if (dateStr.indexOf("-") >= 0)
1851      {
1852        // Date already has hyphen(s)
1853        dateWithHyphensStr = dateStr;
1854      }
1855      else
1856      {
1857        // Date in yyyymmdd format
1858        var yearStr = dateStr.substr(0,4);
1859        var monthStr = dateStr.substr(4,2);
1860        var dayStr = dateStr.substr(6,2);     
1861        dateWithHyphensStr = yearStr + '-' + monthStr + '-' + dayStr;
1862      }
1863    }
1864    return dateWithHyphensStr;
1865  }
1866
1867  /**
1868   *  dateStrToDate()
1869   *
1870   *  Takes an input date string in yyyy-mm-dd or yyyymmdd format
1871   *  and returns a date corresponding to the date string.
1872   *  If input string is null or empty, null is returned.
1873   *
1874   *  @param dateStr String Input date string in yyyy-mm-dd or yyyymmdd format.
1875   *  @return Date Date corresponding to input date string.
1876   */
1877  function dateStrToDate(dateStr)
1878  {
1879    var date = null;
1880    if (dateStr != null && dateStr != '')
1881    {
1882      // Check if input string already contains hyphen
1883      if (dateStr.indexOf("-") >= 0)
1884      {
1885        // Date in yyyy-mm-dd format
1886        var yearStr = dateStr.substr(0,4);
1887        var monthStr = dateStr.substr(5,2);
1888        var dayStr = dateStr.substr(8,2);     
1889        var date = new Date(parseInt(yearStr, 10), parseInt(monthStr, 10)-1, parseInt(dayStr, 10));
1890      }
1891      else
1892      {
1893        // Date in yyyymmdd format
1894        var yearStr = dateStr.substr(0,4);
1895        var monthStr = dateStr.substr(4,2);
1896        var dayStr = dateStr.substr(6,2);     
1897        var date = new Date(parseInt(yearStr, 10), parseInt(monthStr, 10)-1, parseInt(dayStr, 10));
1898      }
1899    }
1900    return date;
1901  }
1902
1903  /*
1904   *  Get the ISO week number for a given date
1905   *
1906   *  Based on code at http://stackoverflow.com/questions/6117814/get-week-of-year-in-javascript-like-in-php
1907   *
1908   *  @param date String Input date to get ISO week number for.
1909   *  @return int ISO week number for input date.
1910   */
1911  function getISOWeekNumber(date)
1912  {
1913    tmpDate = new Date(date);
1914    tmpDate.setHours(0,0,0);
1915    // Set to nearest Thursday: current date + 4 - current day number
1916    // Make Sunday day number 7
1917    tmpDate.setDate(tmpDate.getDate() + 4 - (tmpDate.getDay() || 7));
1918    // Get first day of year
1919    var yearStart = new Date(tmpDate.getFullYear(), 0, 1);
1920    // Calculate full weeks to nearast Thursday (86400000 = 24*60*60*1000 number of ms in a day)
1921    var weekNo = Math.ceil(( ( (tmpDate - yearStart) / 86400000) + 1)/7);
1922    return weekNo;
1923  }
1924
1925  </script>
1926 
1927 
1928  </base:head>
1929  <base:body onload="init()">
1930    <p:path><p:pathelement 
1931      title="Reggie" href="<%="index.jsp?ID="+ID%>" 
1932      /><p:pathelement title="Report generator" 
1933      /></p:path>
1934    <div class="content">
1935    <%
1936    if (sc.getActiveProjectId() == 0)
1937    {
1938      %>
1939      <div class="messagecontainer note" style="width: 950px; margin-left: 20px; margin-bottom: 20px; margin-right: 0px; font-weight: bold; color: #cc0000;">
1940        No project has been selected. You may proceed with the report generation but
1941        only your own items will be included in the report.
1942      </div>
1943      <%
1944    }
1945    %>
1946 
1947    <form name="reggie" onsubmit="return false;">
1948      <!-- 1. Report type-->
1949      <table border="0" cellspacing="0" cellpadding="0" class="stepform">
1950      <tr>
1951        <td rowspan="3" class="stepno">1</td>
1952        <td class="steptitle">Report type</td>
1953      </tr>
1954      <tr>
1955        <td class="stepfields">
1956          <table border="0" cellspacing="0" cellpadding="0" width="100%">
1957          <tr valign="top">
1958            <td class="prompt">Report</td>
1959            <td class="input">
1960              <select name="reporttype">
1961                <option value="samplecount" selected="yes">Sample count report</option>
1962                <option value="consentcount">Consent count report</option>
1963                <option value="patientcount">Patient count report</option>
1964                <option value="overviewreport">Overview report</option>
1965                <option value="missingsampledatareport">Missing sample data report</option>
1966              </select>
1967            </td>
1968            <td class="status" id="report.status"></td>
1969            <td class="help">
1970              <span id="report.message" class="message" style="display: none;"></span>
1971              Select which report to generate.
1972            </td>
1973          </tr>
1974          </table>
1975        </td>
1976      </tr>
1977      </table>
1978     
1979      <div id="itemCountSection" style="display:none;">
1980        <p></p>
1981        <!-- 2. Report parameters-->
1982        <table border="0" cellspacing="0" cellpadding="0" class="stepform">
1983        <tr>
1984          <td rowspan="3" class="stepno">2</td>
1985          <td class="steptitle">Report parameters</td>
1986        </tr>
1987        <tr>
1988          <td class="stepfields">
1989            <table border="0" cellspacing="0" cellpadding="0" width="100%">           
1990            <tr>
1991              <td valign="top" class="prompt">
1992                <div id="reportPeriodSubSection01" style="display:none;">
1993                  <text id="reportPeriodSubSection01Header">Report period</text>
1994                </div>
1995              </td>
1996              <td valign="top" class="input">
1997                <div id="reportPeriodSubSection02" style="display:none;">
1998                  From<input type="text" onChange="dateOnChange()" size=7 name="fromdate"/>&nbsp;
1999                  To<input type="text" onChange="dateOnChange()" size=7 name="todate" />
2000                </div>
2001              </td>
2002              <td valign="top" class="status" id="displayInterval.status"></td>
2003              <td class="help">
2004                <div id="reportPeriodSubSection04" style="display:none;">
2005                  <span id="displayInterval.message" class="message" style="display: none;"></span>
2006                  <!--
2007                  Define which period the report should cover. Empty fields will include all <text id="items01">items</text>.<br>
2008                  -->
2009                  <text id="reportPeriodSubSection04HelpText">Parameter help text</text><br>
2010                </div>
2011              </td>
2012            </tr> 
2013            <tr>
2014              <td valign="top" class="prompt">
2015                <div id="viewTypeSubSection01" style="display:none;">
2016                  View type
2017                </div>
2018              </td>
2019              <td valign="top" class="input">
2020                <div id="viewTypeSubSection02" style="display:none;">
2021                  <select name="viewtype">
2022                    <option value="AUTO" selected="yes">Auto</option>
2023                    <option value="WEEK">Week</option>
2024                    <option value="MONTH">Month</option>
2025                    <option value="QUARTER">Quarter</option>
2026                    <option value="YEAR">Year</option>
2027                  </select>
2028                </div>
2029              </td>
2030              <td valign="top" class="status" id="displayViewType.status"></td>
2031              <td class="help">
2032                <div id="viewTypeSubSection04" style="display:none;">
2033                  <span id="displayViewType.message" class="message" style="display: none;"></span>
2034                  Auto will adjust the report depending on the size of the period.
2035                  <ul>
2036                    <li>Period shorter than 3 months - <text id="items02">items</text> per week</li>
2037                    <li>Period shorter than 13 months - <text id="items03">items</text> per month</li>
2038                    <li>Period shorter than 3 years - <text id="items04">items</text> per quarter</li>
2039                    <li>Period is 3 years or greater - <text id="items05">items</text> per year</li>
2040                  </ul>                 
2041                </div>
2042              </td>
2043            </tr>
2044            <tr>
2045              <td valign="top" class="prompt">
2046                <div id="sampleTypeSubSection01" style="display:none;">
2047                  Sample type
2048                </div>
2049              </td>
2050              <td valign="top" class="input">
2051                <div id="sampleTypeSubSection02" style="display:none;">
2052                  <select name="sampletype">
2053                    <option value="specimen" selected="yes">Specimen</option>
2054                    <option value="nospecimen">No specimen</option>
2055                    <option value="blood">Blood</option>
2056                  </select>
2057                </div>
2058              </td>
2059              <td valign="top" class="status" id="displaySampleType.status"></td>
2060              <td class="help">
2061                <div id="sampleTypeSubSection04" style="display:none;">
2062                  <span id="displaySampleType.message" class="message" style="display: none;"></span>
2063                  Select sample type for report.
2064                </div>
2065              </td>
2066            </tr>
2067            </table>
2068          </td>
2069        </tr>
2070        </table>
2071      </div>
2072     
2073      <div id="reportSection" style="display:none;">
2074        <p></p>
2075        <table border="0" cellspacing="0" cellpadding="0" class="stepform">
2076        <tr>
2077          <td rowspan="3" class="stepno">3</td>
2078          <td class="steptitle">Generated report</td>
2079        </tr>
2080        <tr>
2081          <td id="reportcell" class="stepfields">
2082            <i>Generating report...</i>
2083          </td>
2084        </tr>
2085        </table>
2086      </div> 
2087     
2088      <div class="messagecontainer error" id="errorMessage" style="display: none; width: 950px; margin-left: 20px; margin-bottom: 0px;"></div>   
2089       
2090      <table style="margin-left: 20px; margin-top: 10px;" class="navigation">
2091        <tr>
2092          <td><base:button id="gocancel" title="Cancel" onclick="goRestart(false)" style="display: none;"/></td>
2093          <td><base:button id="gonext" title="Next" image="<%=home+"/images/gonext.png"%>" onclick="goNext(true)" /></td>
2094          <td><base:button id="gocreate" title="Generate" image="<%=home+"/images/gonext.png"%>" onclick="goCreate()" style="display: none;"/></td>         
2095          <td><base:button id="gorestart" title="Restart" image="<%=home+"/images/goback.png"%>" onclick="goRestart(true)" style="display: none;"/></td>
2096          <td id="gonext.message" class="message"></td>
2097        </tr>
2098      </table>     
2099    </form>
2100    </div>
2101   
2102  </base:body>
2103  </base:page>
2104  <%
2105}
2106finally
2107{
2108  if (dc != null) dc.close();
2109}
2110%>
Note: See TracBrowser for help on using the repository browser.