source: extensions/net.sf.basedb.reggie/trunk/resources/index.jsp @ 1983

Last change on this file since 1983 was 1983, checked in by Nicklas Nordborg, 9 years ago

Fixes #494: Show number of items waiting for processing on the index page

After the index page has loaded, multiple AJAX calls are made to the server to count various number of items. The calls are made in a separate thread and should not block other interactions on the page.

On the server side each count is cached using Hibernate's query cache functionality, so it should not be too heavy on the database server even if the index page is loaded multiple times.

File size: 20.2 KB
Line 
1<%@ page
2  pageEncoding="UTF-8"
3  session="false"
4  import="net.sf.basedb.core.Application"
5  import="net.sf.basedb.core.User"
6  import="net.sf.basedb.core.Role"
7  import="net.sf.basedb.core.Group"
8  import="net.sf.basedb.core.DbControl"
9  import="net.sf.basedb.core.Item"
10  import="net.sf.basedb.core.Permission"
11  import="net.sf.basedb.core.SessionControl"
12  import="net.sf.basedb.core.SystemItems"
13  import="net.sf.basedb.core.ItemQuery"
14  import="net.sf.basedb.core.query.Expressions"
15  import="net.sf.basedb.core.query.Hql"
16  import="net.sf.basedb.core.query.Restrictions"
17  import="net.sf.basedb.clients.web.Base"
18  import="net.sf.basedb.clients.web.util.HTML"
19  import="net.sf.basedb.clients.web.extensions.ExtensionsControl"
20  import="net.sf.basedb.util.Values"
21  import="java.util.List"
22%>
23<%@ taglib prefix="base" uri="/WEB-INF/base.tld" %>
24<%@ taglib prefix="p" uri="/WEB-INF/path.tld" %>
25<%
26final SessionControl sc = Base.getExistingSessionControl(request, true);
27final String ID = sc.getId();
28final float scale = Base.getScale(sc);
29final String home = ExtensionsControl.getHomeUrl("net.sf.basedb.reggie");
30DbControl dc = null;
31try
32{
33  dc = sc.newDbControl();
34  final User user = User.getById(dc, sc.getLoggedInUserId());
35 
36  boolean isAdmin = user.getId() == SystemItems.getId(User.ROOT);
37  boolean isPatientCurator = false;
38  boolean hasCreateSamplePermission = sc.hasPermission(Permission.CREATE, Item.SAMPLE);
39  boolean hasCreateExtractPermission = sc.hasPermission(Permission.CREATE, Item.EXTRACT);
40  boolean hasCreateBioPlatePermission = sc.hasPermission(Permission.CREATE, Item.BIOPLATE);
41  if (!isAdmin)
42  {
43    try
44    {
45      Role admin = Role.getById(dc, SystemItems.getId(Role.ADMINISTRATOR));
46      isAdmin = sc.isMemberOf(admin);
47    }
48    catch (RuntimeException ex)
49    {}
50  }
51  try
52  {
53    ItemQuery<Group> query = Group.getQuery();
54    query.restrict(Restrictions.eq(Hql.property("name"), Expressions.string("PatientCurator")));
55    List<Group> result = query.list(dc);
56    if (result.size() == 1)
57    {
58      isPatientCurator = sc.isMemberOf(result.get(0));
59    }
60  }
61  catch (RuntimeException ex)
62  {}
63%>
64<base:page type="default" >
65<base:head styles="path.css" scripts="ajax.js">
66  <script language="JavaScript" src="reggie.js" type="text/javascript" charset="UTF-8"></script>
67  <link rel="stylesheet" type="text/css" href="css/reggie.css">
68  <script language="JavaScript">
69 
70  var debug = false;
71 
72  function caseSummary()
73  {
74    var frm = document.forms['reggie'];
75   
76    var caseName = frm.caseName.value;
77    if (!caseName)
78    {
79      alert('Please enter a 7-digit case id');
80      return;
81    }
82    location.href = 'reports/case_summary.jsp?ID=<%=ID%>&caseName='+encodeURIComponent(caseName);
83  }
84 
85  var currentCount;
86  function startCounting(what)
87  {
88    var url;
89    currentCount = what;
90    if (what == 'specimen')
91    {
92      url = 'PartitionRegistration.servlet?ID=<%=ID%>&cmd=CountSpecimenTubes';
93    }
94    else if (what == 'histology-lists')
95    {
96      url = 'Histology.servlet?ID=<%=ID%>&cmd=CountHistologyWorkLists';
97    }
98    else if (what == 'paraffin-blocks')
99    {
100      url = 'Histology.servlet?ID=<%=ID%>&cmd=CountParaffinBlocks';
101    }
102    else if (what == 'paraffin-blocks-without-heglass')
103    {
104      url = 'Histology.servlet?ID=<%=ID%>&cmd=CountParaffinBlocksWithoutHeGlass';
105    }
106    else if (what == 'lysate')
107    {
108      url = 'Extraction.servlet?ID=<%=ID%>&cmd=CountUnprocessedLysates';
109    }
110    else if (what == 'rnaqc')
111    {
112      url = 'RnaQc.servlet?ID=<%=ID%>&cmd=CountRnaExtractsWithoutQc';
113    }
114    else if (what == 'caliper-plates')
115    {
116      url = 'RnaQc.servlet?ID=<%=ID%>&cmd=CountActiveRnaQcBioPlates';
117    }
118    else if (what == 'rna-without-mrna')
119    {
120      url = 'MRna.servlet?ID=<%=ID%>&cmd=CountRnaWithoutMRna';
121    }
122    else if (what == 'mrna-plates')
123    {
124      url = 'MRna.servlet?ID=<%=ID%>&cmd=CountUnprocessedPlates&plateType=MRNA';
125    }
126    else if (what == 'cdna-plates')
127    {
128      url = 'MRna.servlet?ID=<%=ID%>&cmd=CountUnprocessedPlates&plateType=CDNA';
129    }
130    else if (what == 'cdna-plates-for-barcoding')
131    {
132      url = 'LibPrep.servlet?ID=<%=ID%>&cmd=CountCDNAPlatesForBarcoding';
133    }
134    else if (what == 'lib-plates')
135    {
136      url = 'LibPrep.servlet?ID=<%=ID%>&cmd=CountLibPlatesForLibPrep';
137    }
138    else if (what == 'lib-plates-for-pooling')
139    {
140      url = 'Pool.servlet?ID=<%=ID%>&cmd=CountLibraryPlatesForPooling';
141    }
142    else if (what == 'pools')
143    {
144      url = 'Pool.servlet?ID=<%=ID%>&cmd=CountUnprocessedPools';
145    }
146   
147    if (url)
148    {
149      var request = Main.getAjaxRequest();
150      request.open("GET", url, false);
151      Ajax.setReadyStateHandler(request, onCounted, onCounted);
152      request.send(null);
153    }
154  }
155 
156  function onCounted(request)
157  {
158    if (debug) Main.debug(currentCount +': ' + Main.encodeTags(request.responseText));
159    var response;
160    var error = false;
161    try
162    {
163      response = JSON.parse(request.responseText);
164      if (response.status != 'ok')
165      {
166        error = response.message || response.stacktrace || 'Unexpected error';
167      }
168    }
169    catch (ex)
170    {
171      error = ex;
172    }
173   
174    if (currentCount == 'specimen')
175    {
176      var msg = error || 'Number of unpartitioned specimen';
177      var count = error ? -1 : response.count;
178      setCount('count.specimen', count, 'specimens', msg);
179      startCounting('histology-lists');
180    }
181    else if (currentCount == 'histology-lists')
182    {
183      var msg = error || 'Number of active histology work lists';
184      var count = error ? -1 : response.count;
185      setCount('count.histology-lists', count, 'work lists', msg);
186      startCounting('paraffin-blocks');
187    }
188    else if (currentCount == 'paraffin-blocks')
189    {
190      var msg = error || 'Number of paraffin blocks waiting for registration';
191      var count = error ? -1 : response.count;
192      setCount('count.paraffin-blocks', count, 'paraffin blocks', msg);
193      startCounting('paraffin-blocks-without-heglass');
194    }
195    else if (currentCount == 'paraffin-blocks-without-heglass')
196    {
197      var msg = error || 'Number of paraffin blocks without HE glass';
198      var count = error ? -1 : response.count;
199      setCount('count.paraffin-blocks-without-heglass', count, 'paraffin blocks', msg);
200      startCounting('lysate');
201    }
202    else if (currentCount == 'lysate')
203    {
204      var msg = error || 'Number of unprocessed lysates';
205      var count = error ? -1 : response.count;
206      setCount('count.lysate.1', count, 'lysates', msg);
207      setCount('count.lysate.2', count, 'lysates', msg);
208      startCounting('rnaqc');
209    }
210    else if (currentCount == 'rnaqc')
211    {
212      var msg = error || 'Number of RNA waiting for QC';
213      var count = error ? -1 : response.count;
214      setCount('count.rnaqc', count, 'RNA', msg);
215      startCounting('caliper-plates');
216    }
217    else if (currentCount == 'caliper-plates')
218    {
219      var msg = error || 'Number of active Caliper plates';
220      var count = error ? -1 : response.count;
221      setCount('count.caliper-plates.1', count, 'Caliper plates', msg);
222      setCount('count.caliper-plates.2', count, 'Caliper plates', msg);
223      startCounting('rna-without-mrna');
224    }
225    else if (currentCount == 'rna-without-mrna')
226    {
227      var msg = error || 'Number of RNA with no mRNA';
228      var count = error ? -1 : response.count;
229      setCount('count.rna-without-mrna', count, 'RNA', msg);
230      startCounting('mrna-plates');
231    }
232    else if (currentCount == 'mrna-plates')
233    {
234      var msg = error || 'Number of mRNA plates waiting for registration';
235      var count = error ? -1 : response.count;
236      setCount('count.mrna-plates.1', count, 'mRNA plates', msg);
237      setCount('count.mrna-plates.2', count, 'mRNA plates', msg);
238      startCounting('cdna-plates');
239    }
240    else if (currentCount == 'cdna-plates')
241    {
242      var msg = error || 'Number of cDNA plates waiting for registration';
243      var count = error ? -1 : response.count;
244      setCount('count.cdna-plates.1', count, 'cDNA plates', msg);
245      startCounting('cdna-plates-for-barcoding');
246    }
247    else if (currentCount == 'cdna-plates-for-barcoding')
248    {
249      var msg = error || 'Number of cDNA plates waiting for barcode layout';
250      var count = error ? -1 : response.count;
251      setCount('count.cdna-plates-for-barcoding', count, 'cDNA plates', msg);
252      startCounting('lib-plates')
253    }
254    else if (currentCount == 'lib-plates')
255    {
256      var msg = error || 'Number of Lib plates waiting for registration';
257      var count = error ? -1 : response.count;
258      setCount('count.lib-plates.1', count, 'Lib plates', msg);
259      setCount('count.lib-plates.2', count, 'Lib plates', msg);
260      setCount('count.lib-plates.3', count, 'Lib plates', msg);
261      startCounting('lib-plates-for-pooling');
262    }
263    else if (currentCount == 'lib-plates-for-pooling')
264    {
265      var msg = error || 'Number of Lib plates waiting for pooling';
266      var count = error ? -1 : response.count;
267      setCount('count.lib-plates-for-pooling', count, 'Lib plates', msg);
268      startCounting('pools');
269    }
270    else if (currentCount == 'pools')
271    {
272      var msg = error || 'Number of pools waiting for registration';
273      var count = error ? -1 : response.count;
274      setCount('count.pools.1', count, 'pools', msg);
275      setCount('count.pools.2', count, 'pools', msg);
276    }
277   
278  }
279 
280  function setCount(id, count, unit, msg)
281  {
282    var div = document.getElementById(id);
283    div.title = msg;
284    if (count == -1)
285    {
286      div.innerHTML = '(-)';
287    }
288    else
289    {
290      div.innerHTML = '(' + count + ')';
291    }
292  }
293 
294  </script>
295<style>
296dl
297{
298  margin-top: 0px;
299  padding: 3px;
300}
301dt
302{
303  margin-top: 0.5em;
304  margin-left: 0.5em;
305}
306dd
307{
308  margin-left: 0.5em;
309  margin-bottom: 0.5em;
310  padding-left: 3em;
311}
312ul
313{
314  margin-top: 0px;
315  margin-bottom: 0px;
316  margin-left: 0em;
317  padding-left: 0em;
318}
319li
320{
321  margin-left: 0em;
322}
323img
324{
325  vertical-align: text-bottom;
326}
327h3
328{
329  color: #333377;
330  background: #E8E8E8;
331  font-weight: bold;
332  margin-bottom: 0em;
333  padding: 1px 4px 1px 4px;
334  border: 1px solid #A0A0A0;
335  font-size: 1em;
336}
337a.not-implemented
338{
339  filter: url(css/filters.svg#grayscale); /* Firfox, etc */
340  filter: gray; /* IE */
341  opacity: 0.75;
342  pointer-events: none;
343}
344
345a.not-implemented:after
346{
347  content: ' -- coming soon';
348}
349.counter
350{
351  color: #999999;
352  font-style: italic;
353}
354</style>
355</base:head>
356<base:body onload="startCounting('specimen')">
357
358  <p:path><p:pathelement title="Reggie" /></p:path>
359
360  <div class="content">
361    <form name="reggie" onsubmit="return false;">
362    <div class="absolutefull" style="width: 50%;">
363      <div class="absolutefull" style="left: 1em; right: 0.5em; ">
364     
365        <h3>Sample processing wizards</h3>
366        <dl class="leftborder rightborder bottomborder">
367        <%
368        if (hasCreateSamplePermission)
369        {
370          %>
371          <dt>
372            <base:icon image="<%=home+"/images/specimen.png" %>" />
373            <a href="sampleproc/specimentube.jsp?ID=<%=ID%>">Specimen tube registration</a>
374          </dt>
375          <dd>
376            <ul>
377            <li>Register new specimen tubes.
378            <li>Update existing specimen tubes.
379            </ul>
380          </dd>
381          <%
382        }
383        if (hasCreateSamplePermission && hasCreateExtractPermission)
384        {
385          %>
386          <dt>
387            <base:icon image="<%=home+"/images/partition.png" %>" />
388            <a href="sampleproc/partitionform.jsp?ID=<%=ID%>">Partition wizard</a>
389          </dt>
390          <dd>
391            <ul>
392            <li>Register new partitions of existing specimens <span class="counter" id="count.specimen" title="Counting..."><img src="images/loading-small.gif"></span>
393            </ul>
394          </dd>
395          <%
396        }
397        if (hasCreateSamplePermission && hasCreateBioPlatePermission)
398        {
399          %>
400          <dt>
401            <base:icon image="<%=home+"/images/microscope.png" %>" />
402            Histology wizards
403          </dt>
404          <dd>
405            <ul>
406            <li><a href="sampleproc/histology_protocol.jsp?ID=<%=ID%>">Lab tracking protocol for FFPE/HE</a> <span class="counter" id="count.histology-lists" title="Counting..."><img src="images/loading-small.gif"></span>
407            <li><a href="sampleproc/histology_block.jsp?ID=<%=ID%>">Register paraffin blocks</a> <span class="counter" id="count.paraffin-blocks" title="Counting..."><img src="images/loading-small.gif"></span>
408            <li><a href="sampleproc/histology_glass.jsp?ID=<%=ID%>">Register histology HE glass information</a> <span class="counter" id="count.paraffin-blocks-without-heglass" title="Counting..."><img src="images/loading-small.gif"></span>
409            </ul>
410          </dd>
411          <%
412        }
413        if (hasCreateExtractPermission)
414        {
415          %>
416          <dt>
417            <base:icon image="<%=home+"/images/extraction.png" %>" />
418            DNA/RNA extraction wizards
419          </dt>
420          <dd>
421            <ul>
422            <li><a href="sampleproc/allprep_protocol.jsp?ID=<%=ID%>">Lab tracking protocol for Allprep isolation</a> <span class="counter" id="count.lysate.1" title="Counting..."><img src="images/loading-small.gif"></span>
423            <li><a href="sampleproc/extraction_registration.jsp?ID=<%=ID%>">DNA/RNA/FlowThrough registration</a> <span class="counter" id="count.lysate.2" title="Counting..."><img src="images/loading-small.gif"></span>
424            </ul>
425          </dd>
426          <dt>
427            <base:icon image="<%=home+"/images/rnaqc.png" %>" />
428            RNA quality control wizards
429          </dt>
430          <dd>
431            <ul>
432            <li><a href="sampleproc/rnaqc_aliquot.jsp?ID=<%=ID%>">Create aliquots on Bioanalyzer/Caliper plates</a> <span class="counter" id="count.rnaqc" title="Counting..."><img src="images/loading-small.gif"></span>
433            <li><a href="sampleproc/rnaqc_plate_export.jsp?ID=<%=ID%>">Export Caliper sample names and run parameters</a> <span class="counter" id="count.caliper-plates.1" title="Counting..."><img src="images/loading-small.gif"></span>
434            <li><a href="sampleproc/rnaqc_plate_import.jsp?ID=<%=ID%>">Import RQS scores from Caliper well table file</a> <span class="counter" id="count.caliper-plates.2" title="Counting..."><img src="images/loading-small.gif"></span>
435            </ul>
436          </dd>
437          <%
438        }
439        %>       
440        </dl>
441     
442     
443        <h3>Library preparation wizards</h3>
444        <dl class="leftborder rightborder bottomborder">
445        <%
446        if (hasCreateExtractPermission && hasCreateBioPlatePermission)
447        {
448          %>
449          <dt>
450            <base:icon image="<%=home+"/images/pipette.png" %>" />
451            RNA to cDNA wizards
452          </dt>
453          <dd>
454            <ul>
455            <li><a href="libprep/select_rna.jsp?ID=<%=ID%>">Create new mRNA plate</a> <span class="counter" id="count.rna-without-mrna" title="Counting..."><img src="images/loading-small.gif"></span>
456            <li><a href="libprep/mrna_protocol.jsp?ID=<%=ID%>">Lab protocols for mRNA and cDNA preparation</a> <span class="counter" id="count.mrna-plates.1" title="Counting..."><img src="images/loading-small.gif"></span>
457            <li><a href="libprep/mrna_registration.jsp?ID=<%=ID%>">mRNA registration and quality control results</a> <span class="counter" id="count.mrna-plates.2" title="Counting..."><img src="images/loading-small.gif"></span>
458            <li><a href="libprep/cdna_registration.jsp?ID=<%=ID%>">cDNA registration</a> <span class="counter" id="count.cdna-plates.1" title="Counting..."><img src="images/loading-small.gif"></span>
459            </ul>
460          </dd>
461         
462          <dt>
463            <base:icon image="<%=home+"/images/libprep.png" %>" />
464            Library preparation wizards
465          </dt>
466          <dd>
467            <ul>
468            <li><a href="libprep/assign_barcode.jsp?ID=<%=ID%>">Assign barcodes to cDNA plate</a> <span class="counter" id="count.cdna-plates-for-barcoding" title="Counting..."><img src="images/loading-small.gif"></span>
469            <li><a href="libprep/libprep_protocol.jsp?ID=<%=ID%>">Lab protocols and files for library preparation</a> <span class="counter" id="count.lib-plates.1" title="Counting..."><img src="images/loading-small.gif"></span>
470            <li><a href="libprep/libqc_registration.jsp?ID=<%=ID%>">Register quality control results</a> <span class="counter" id="count.lib-plates.2" title="Counting..."><img src="images/loading-small.gif"></span>
471            <li><a href="libprep/lib_registration.jsp?ID=<%=ID%>">Library registration</a> <span class="counter" id="count.lib-plates.3" title="Counting..."><img src="images/loading-small.gif"></span>
472            </ul>
473          </dd>
474          <dt>
475            <base:icon image="<%=home+"/images/flowcell.png" %>" />
476            Pooling and clustering wizards
477          </dt>
478          <dd>
479            <ul>
480            <li><a href="libprep/create_pools.jsp?ID=<%=ID%>">Create pooled libraries</a> <span class="counter" id="count.lib-plates-for-pooling" title="Counting..."><img src="images/loading-small.gif"></span>
481            <li><a href="libprep/pool_protocol.jsp?ID=<%=ID%>">Lab protocols for pooling</a> <span class="counter" id="count.pools.1" title="Counting..."><img src="images/loading-small.gif"></span>
482            <li><a href="libprep/pool_registration.jsp?ID=<%=ID%>">Register pooled libraries</a> <span class="counter" id="count.pools.2" title="Counting..."><img src="images/loading-small.gif"></span>
483            <li><a href="libprep/flowcell_registration.jsp?ID=<%=ID%>" class="not-implemented">Register flow cells</a>
484            </ul>
485          </dd>
486          <%
487        }
488        %>
489        </dl>
490      </div>
491    </div>
492   
493    <div class="absolutefull" style="width: 50%; left: auto;">
494      <div class="absolutefull" style="left: 0.5em; right: 1em;">
495        <%
496        if (isAdmin)
497        {
498          %>
499          <h3>Server administrator wizards</h3>
500          <dl class="leftborder rightborder bottomborder">
501          <dt>
502            <base:icon image="<%=home + "/images/install.png" %>" />
503            <a href="admin/install.jsp?ID=<%=ID%>">Installation wizard</a>
504          </dt>
505          <dd>
506            <ul>
507            <li>Check that annotation types and other items used by Reggie exists in BASE.
508            <li>Create missing items.
509            </ul>
510          </dd>
511          </dl>
512          <%
513        }
514        if (isPatientCurator || isAdmin)
515        {
516          %>
517          <h3>Personal information wizards</h3>
518          <dl class="leftborder rightborder bottomborder">
519          <dt>
520            <base:icon image="<%=home + "/images/personal.png" %>"/>
521            <a href="personal/persinfo.jsp?ID=<%=ID%>">Pathology referral form registration</a>
522          </dt>
523          <dd>
524            <ul>
525            <li>Register new cases and patients.
526            <li>Update existing cases and specimen tubes.
527            </ul>
528          </dd>
529         
530          <dt>
531            <base:icon image="<%=home + "/images/blood.png" %>"/>
532            <a href="personal/bloodform.jsp?ID=<%=ID%>">Blood referral form registration</a>
533          </dt>
534          <dd>
535            <ul>
536            <li>Register new blood referral forms and patients.
537            <li>Update information for existing blood referral forms.
538            </ul>
539          </dd>
540         
541          <dt>
542            <base:icon image="<%=home+"/images/consent.png" %>"/>
543            <a href="personal/consentform.jsp?ID=<%=ID%>">Consent form registration</a>
544          </dt>
545          <dd>
546            <ul>
547            <li>Register consent forms.
548            </ul>
549          </dd>
550         
551          <dt>
552            <base:icon image="<%=home+"/images/export_import.png" %>" />
553            Export/import information to/from external registers.
554          </dt>
555          <dd>
556            <ul>
557            <li><a href="personal/export_monthly_oplist.jsp?ID=<%=ID%>">Export monthly operation list</a>
558            <li><a href="personal/export_inca.jsp?ID=<%=ID%>">INCA export</a>
559            </ul>
560          </dd>
561          </dl>
562          <%
563        }
564        %>
565       
566        <h3>Statistics and reporting wizards</h3>
567        <dl class="leftborder rightborder bottomborder">
568          <dt>
569            <base:icon image="<%=home+"/images/case_summary.png" %>" />
570            Case summary
571          </dt>
572          <dd>
573            <table>
574            <tr>
575              <td><input type="text" class="text" 
576                name="caseName" title="Please enter a 7-digit case id" 
577                style="width: 25em;"
578                onkeypress="if (event.keyCode==13 && this.value) caseSummary()"></td>
579              <td><base:button title="Go" image="<%=home+"/images/gonext.png"%>" onclick="caseSummary()"/></td>
580            </tr>
581            </table>
582          </dd>
583       
584          <dt>
585            <base:icon image="<%=home+"/images/report.png" %>" />
586            <a href="reports/samplereportgenerator.jsp?ID=<%=ID%>">Sample source report</a>
587          </dt>       
588          <dd>       
589            <ul>
590            <li>Sample count report</li> 
591            <li>Consent count report</li> 
592            <li>Patient count report</li> 
593            <li>Overview report</li> 
594            <li>Missing sample data report</li> 
595            </ul>
596          </dd>
597          <dt>
598            <base:icon image="<%=home+"/images/chart_bar.png" %>" />
599            <a href="reports/scanbquartermonthreportgenerator.jsp?ID=<%=ID%>">Sample processing statistics</a>
600          </dt>       
601          <dd>       
602            <ul>
603            <li>SCAN-B quarter/month report</li> 
604            </ul>
605          </dd>
606        </dl>
607      </div>
608    </div>
609    </form>
610  </div>
611 
612</base:body>
613</base:page>
614<%
615}
616finally
617{
618  if (dc != null) dc.close();
619}
620%>
Note: See TracBrowser for help on using the repository browser.