source: extensions/net.sf.basedb.reggie/trunk/resources/libprep/mrna_registration.jsp @ 2073

Last change on this file since 2073 was 2073, checked in by Nicklas Nordborg, 10 years ago

Fixes #517: Ensure that the "Failure" option is not selected by mistake

Added a checkbox that is displayed next to the "Register" button when the "Failure" option is selected. The "Register" button is disabled until the checkbox is selected.

File size: 19.7 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.util.HTML" 
10  import="net.sf.basedb.clients.web.extensions.ExtensionsControl"
11%>
12<%@ taglib prefix="base" uri="/WEB-INF/base.tld" %>
13<%@ taglib prefix="p" uri="/WEB-INF/path.tld" %>
14<%
15final SessionControl sc = Base.getExistingSessionControl(request, true);
16final String ID = sc.getId();
17final float scale = Base.getScale(sc);
18final String home = ExtensionsControl.getHomeUrl("net.sf.basedb.reggie");
19DbControl dc = null;
20try
21{
22  dc = sc.newDbControl();
23  final User user = User.getById(dc, sc.getLoggedInUserId());
24%>
25<base:page type="default" >
26<base:head scripts="ajax.js" styles="path.css">
27  <link rel="stylesheet" type="text/css" href="../css/reggie.css">
28  <script language="JavaScript" src="../reggie.js" type="text/javascript" charset="UTF-8"></script>
29
30<script language="JavaScript">
31
32var MRNA_QC_FILES_PATH = '/home/SCANB/MRnaPlateQC';
33var firstBrowse = true;
34var subtypeBioAnalyzerPdf;
35
36var debug = false;
37var currentStep = 1;
38
39var dateIsValid = [];
40
41var pdfIsValid = false;
42var commentsIsValid = false;
43
44function init()
45{
46  var frm = document.forms['reggie'];
47  var bioplates = getMRnaBioPlates();
48 
49  // Load existing mRNA plates not yet registered
50  var plates = frm.bioplate;
51  if (bioplates != null && bioplates.length > 0)
52  {
53    for (var i=0; i < bioplates.length; i++)
54    {
55      var bioplate = bioplates[i];
56      var option = new Option(bioplate.name, bioplate.id);
57      option.comments = bioplate.comments;
58      plates.options[plates.length] = option;
59    }
60    bioplateIsValid = true;
61    setInputStatus('bioplate', '', 'valid');
62    bioPlateOnChange();
63    outcomeOnChange();
64  }
65  else
66  {
67    var msg = 'No mRNA bioplates available for processing.';
68    setFatalError(msg);
69    return;
70  }
71
72  // All is ok
73  frm.bioplate.focus();
74}
75
76
77function goNextAuto()
78{
79  goNext(false);
80}
81
82function goNext(manual)
83{
84  setInnerHTML('gonext.message', '');
85  if (currentStep == 1)
86  {   
87    gotoStep2();
88  }
89  setCurrentStep(currentStep);
90}
91
92
93
94function getMRnaBioPlates()
95{
96  var frm = document.forms['reggie']; 
97 
98  var request = Ajax.getXmlHttpRequest();
99  try
100  {
101    showLoadingAnimation('Loading histology work lists...');
102    var url = '../MRna.servlet?ID=<%=ID%>&cmd=GetUnprocessedPlates&plateType=MRNA';   
103    request.open("GET", url, false); 
104    request.send(null);
105  }
106  finally
107  {
108    hideLoadingAnimation();
109  }
110 
111  if (debug) Main.debug(request.responseText);
112  var response = JSON.parse(request.responseText); 
113  if (response.status != 'ok')
114  {
115    setFatalError(response.message);
116    return false;
117  }
118  return response.bioplates;
119}
120
121function gotoStep2()
122{
123  var frm = document.forms['reggie']; 
124  frm.bioplate.disabled = true;
125  frm.outcome[0].disabled = true;
126  frm.outcome[1].disabled = true;
127
128 
129  currentStep = 2;
130  Main.show('step.2.section');
131  Main.addClass(document.getElementById('step.1.section'), 'disabled');
132  Main.hide('gonext');
133  Main.show('gocancel');
134  Main.show('goregister');
135 
136  // Load mRNA protocols
137  var mrnaProtocols = getProtocols('MRNA_PROTOCOL');
138  for (var i = 0; i < mrnaProtocols.length; i++)
139  {
140    var protocol = mrnaProtocols[i];
141    frm.mrnaProtocol[frm.mrnaProtocol.length] = new Option(protocol.name, protocol.id, protocol.isDefault);
142    setInputStatus('mrnaProtocol', '', 'valid');
143  }
144  if (frm.mrnaProtocol.length == 0)
145  {
146    frm.mrnaProtocol[0] = new Option('- none -', '');
147  }
148
149  if (document.getElementById('outcomeFailed').checked)
150  {
151    setInnerHTML('gonext.message', '<input type="checkbox" name="verifyFailure" onclick="verifyFailureOnClick()"> Check to verify registration of failure');
152    Main.addClass(document.getElementById('goregister'), 'disabled');
153  }
154 
155  frm.dilutionDate.focus();
156}
157
158function getProtocols(subtype)
159{
160  var request = Ajax.getXmlHttpRequest();
161  try
162  {
163    showLoadingAnimation('Loading ' + subtype + ' protocols...');
164    var url = '../Protocol.servlet?ID=<%=ID%>&cmd=GetProtocols&subtype='+subtype;   
165    request.open("GET", url, false); 
166    request.send(null);
167  }
168  finally
169  {
170    hideLoadingAnimation();
171  }
172
173  if (debug) Main.debug(request.responseText);
174  var response = JSON.parse(request.responseText); 
175  if (response.status != 'ok')
176  {
177    setFatalError(response.message);
178    return false;
179  }
180  return response.protocols;
181}
182
183function bioPlateOnChange()
184{
185  var frm = document.forms['reggie'];
186  frm.comments.value = frm.bioplate[frm.bioplate.selectedIndex].comments;
187  commentsOnChange();
188}
189
190function outcomeOnChange()
191{
192  var frm = document.forms['reggie'];
193  Main.addOrRemoveClass(frm['pdf.path'], 'required', document.getElementById('outcomeSuccess').checked);
194  Main.addOrRemoveClass(frm['comments'], 'required', document.getElementById('outcomeFailed').checked);
195  pdfFileOnChange();
196  commentsOnChange();
197}
198
199function browseOnClick(extension)
200{
201  var frm = document.forms['reggie'];
202  if (frm[extension+'.path'].disabled) return;
203  if (firstBrowse)
204  {
205    firstBrowse = false;
206    setCurrentDirectory('<%=ID%>', MRNA_QC_FILES_PATH, debug, '../');
207    subtypeBioAnalyzerPdf = getSubtypeInfo('<%=ID%>', 'BIOANALYZER_PDF', debug, '../');
208  }
209  var url = getRoot() + 'filemanager/index.jsp?ID=<%=ID%>&cmd=SelectOne&callback=setFileCallback';
210  url += '&resetTemporary=1&tmpfilter:STRING:name='+escape('%.' + extension.substr(0, 3));
211  if (subtypeBioAnalyzerPdf)
212  {
213    url += '&tmpfilter:INT:itemSubtype='+subtypeBioAnalyzerPdf.id;
214  }
215  lastExtension = extension;
216  Main.openPopup(url, 'SelectFile', 1000, 700);
217}
218
219function setFileCallback(id, path)
220{
221  var frm = document.forms['reggie'];
222  frm[lastExtension+'.id'].value = id;
223  frm[lastExtension+'.path'].value = path;
224  setInputStatus(lastExtension, '', 'valid');
225  if (lastExtension == 'pdf')
226  {
227    pdfIsValid = true;
228  }
229}
230
231function pdfFileOnChange()
232{
233  var frm = document.forms['reggie'];
234  if (!frm['pdf.id'].value)
235  {
236    var outcomeSuccess = document.getElementById('outcomeSuccess');
237    pdfIsValid = false;
238    // A PDF is reuired for successful registration, optional after a failure
239    var status = outcomeSuccess.checked ? 'invalid' : 'warning';
240    if (!frm['pdf.path'].value)
241    {
242      setInputStatus('pdf', 'Missing', status);
243      pdfIsValid = !outcomeSuccess.checked;
244    }
245    else
246    {
247      setInputStatus('pdf', 'Use the Browse button to select a file', 'invalid');
248    }
249  }
250}
251
252function dateOnChange(dateField)
253{
254  var frm = document.forms['reggie'];
255
256  setInputStatus(dateField, '', '');
257  dateIsValid[dateField] = true;
258  var date = frm[dateField].value;
259
260  if (date == '')
261  {
262    setInputStatus(dateField, 'Missing date', 'warning');
263    return;
264  }
265
266  // Auto-fill the date if it's only given with 4(MMdd) or 6(yyMMdd) digits.   
267  date = autoFillDate(date);
268  frm[dateField].value = date;
269  if (!Dates.isDate(date, 'yyyyMMdd'))
270  {
271    setInputStatus(dateField, 'Not a valid date', 'invalid');
272    dateIsValid[dateField] = false;
273    return;
274  }
275 
276  setInputStatus(dateField, '', 'valid');
277}
278
279function setDate(frmName, dateField, date)
280{
281  var frm = document.forms['reggie'];
282  frm[dateField].value = date;
283  dateOnChange(dateField);
284  frm[dateField].focus();
285}
286
287function commentsOnChange()
288{
289  var frm = document.forms['reggie'];
290  commentsIsValid = false;
291  setInputStatus('comments', '', '');
292 
293  var comments = frm.comments.value;
294 
295  if (comments == '' && document.getElementById('outcomeFailed').checked)
296  {
297    setInputStatus('comments', 'Missing', 'invalid');
298    return;
299  }
300
301  setInputStatus('comments', '', 'valid');
302  commentsIsValid = true;
303}
304
305function step2IsValid()
306{
307  var frm = document.forms['reggie'];
308  if (!pdfIsValid || !commentsIsValid) return false;
309 
310  if (dateIsValid['dilutionDate'] == false) return false;
311  if (dateIsValid['purificationDate'] == false) return false;
312  if (dateIsValid['fragmentationDate'] == false) return false;
313  if (dateIsValid['cleanupDate'] == false) return false;
314 
315  if (document.getElementById('outcomeFailed').checked && !frm.verifyFailure.checked) return false;
316 
317  return true;
318}
319
320function verifyFailureOnClick()
321{
322  var frm = document.forms['reggie'];
323  var checked = frm.verifyFailure.checked;
324  Main.addOrRemoveClass(document.getElementById('goregister'), 'disabled', !checked);
325}
326
327function goRegister()
328{
329  if (!step2IsValid()) return;
330
331  var frm = document.forms['reggie'];
332  var pdfId = parseInt(frm['pdf.id'].value, 10);
333 
334  Main.hide('goregister');
335  Main.hide('gocancel');
336  Main.hide('gonext.message');
337  Main.addClass(document.getElementById('step.2.section'), 'disabled');
338
339  frm['pdf.path'].disabled = true;
340  Main.addClass(document.getElementById('btnPdf'), 'disabled');
341  frm.dilutionDate.disabled = true;
342  frm.dilutionOperator.disabled = true;
343  frm.purificationDate.disabled = true;
344  frm.purificationOperator.disabled = true;
345  frm.fragmentationDate.disabled = true;
346  frm.fragmentationOperator.disabled = true;
347  frm.cleanupDate.disabled = true;
348  frm.cleanupOperator.disabled = true;
349  frm.mrnaProtocol.disabled = true;
350  frm.comments.disabled = true;
351 
352  var submitInfo = {};
353  submitInfo.bioplate = parseInt(frm.bioplate.value, 10);
354  submitInfo.mrnaProtocol = parseInt(frm.mrnaProtocol.value, 10);
355  submitInfo.failed = document.getElementById('outcomeSuccess').checked ? false : true;
356  submitInfo.pdf = pdfId;
357  submitInfo.dilutionDate = frm.dilutionDate.value;
358  submitInfo.dilutionOperator = frm.dilutionOperator.value;
359  submitInfo.purificationDate = frm.purificationDate.value;
360  submitInfo.purificationOperator = frm.purificationOperator.value;
361  submitInfo.fragmentationDate = frm.fragmentationDate.value;
362  submitInfo.fragmentationOperator = frm.fragmentationOperator.value;
363  submitInfo.cleanupDate = frm.cleanupDate.value;
364  submitInfo.cleanupOperator = frm.cleanupOperator.value;
365  submitInfo.comments = frm.comments.value;
366 
367  if (debug) Main.debug(JSON.stringify(submitInfo));
368  var url = '../MRna.servlet?ID=<%=ID%>&cmd=ImportMRnaQCResults';
369 
370  var request = Ajax.getXmlHttpRequest();
371  try
372  {
373    showLoadingAnimation('Performing registration...');
374    request.open("POST", url, false);
375    request.send(JSON.stringify(submitInfo));
376  }
377  finally
378  {
379    hideLoadingAnimation();
380  }
381 
382  if (debug) Main.debug(request.responseText);
383  var response = JSON.parse(request.responseText);
384 
385  if (response.messages && response.messages.length > 0)
386  {
387    var msg = '<ul>';
388    for (var i = 0; i < response.messages.length; i++)
389    {
390      var msgLine = response.messages[i];
391      if (msgLine.indexOf('[Warning]') >= 0)
392      {
393        msg += '<li class="warning">' + msgLine.replace('[Warning]', '');
394      }
395      else
396      {
397        msg += '<li>' + msgLine;
398      }
399    }
400    msg += '</ul>';
401    setInnerHTML('messages', msg);
402    Main.show('messages');
403  }
404 
405  if (response.status != 'ok')
406  {
407    Main.addClass(document.getElementById('messages'), 'failure');
408    setFatalError(response.message);
409    return false;
410  }
411
412  Main.show('gorestart');
413}
414
415
416</script>
417
418</base:head>
419<base:body onload="init()">
420
421  <p:path><p:pathelement 
422    title="Reggie" href="<%="../index.jsp?ID="+ID%>" 
423    /><p:pathelement title="mRNA registration and quality control results" 
424    /></p:path>
425
426  <div class="content">
427  <%
428  if (sc.getActiveProjectId() == 0)
429  {
430    %>
431    <div class="messagecontainer note" style="width: 950px; margin-left: 20px; margin-bottom: 20px; margin-right: 0px; font-weight: bold; color: #cc0000;">
432      No project has been selected. You may proceed with the registration but
433      created items will not be shared.
434    </div>
435    <%
436  }
437  %>
438
439  <form name="reggie" onsubmit="return false;">
440    <input type="hidden" name="pdf.id" value="">
441 
442  <div id="step.1.section">
443  <table class="stepform">
444  <tr>
445    <td rowspan="3" class="stepno">1</td>
446    <td class="steptitle">Select mRNA bioplate</td>
447  </tr>
448  <tr>
449    <td class="stepfields">
450      <table>
451      <tr valign="top">
452        <td class="prompt">mRNA bioplate</td>
453        <td class="input"><select class="required" style="width:90%;" 
454            name="bioplate" id="bioplate" onchange="bioPlateOnChange()"></select>
455        </td>
456        <td class="status" id="bioplate.status"></td>
457        <td class="help"><span id="bioplate.message" class="message" style="display: none;"></span>
458          Select an existing mRNA bioplate. The list contain all mRNA bioplates that
459          has not yet been processed (determined by the absence of a 'creation' date).
460        </td>
461      </tr>
462      <tr valign="top">
463        <td class="prompt">Outcome</td>
464        <td class="input">
465          <input type="radio" name="outcome" id="outcomeSuccess" 
466            onchange="outcomeOnChange()" checked><label for="outcomeSuccess">Success</label> - continue processing to cDNA<br>
467          <input type="radio" name="outcome" id="outcomeFailed" 
468            onchange="outcomeOnChange()"><label for="outcomeFailed">Failure</label> - no further processing to cDNA
469        </td>
470        <td class="status"></td>
471        <td class="help">
472          Select the <b>Failure</b> option if further processing to cDNA is not possible.
473          No child cDNA plate will be created and existing RNA will be flagged and added
474          to the <b>Flagged RNA</b> list.
475        </td>
476      </tr>
477      </table>
478    </td>
479  </tr>
480  </table>
481  </div>
482 
483  <div id="step.2.section" style="display: none;">
484  <table class="stepform">
485  <tr>
486    <td rowspan="3" class="stepno">2</td>
487    <td class="steptitle">mRNA preparation information</td>
488  </tr>
489  <tr>
490    <td class="stepfields">
491      <table>
492      <tr valign="top">
493        <td class="prompt">Step</td>
494        <td style="width: 11em;"><b>Date</b></td>
495        <td><b>Operator</b></td>
496        <td class="status"></td>
497        <td class="help" rowspan="5">
498          <span id="mrnaDate.message" class="message" style="display: none;"></span>
499          Enter date and operator for each step in the mRNA preparation.
500          (YYYYMMDD or MMDD)
501        </td>
502      </tr>
503      <tr>
504        <td class="subprompt">Dilution</td>
505        <td>
506          <input type="text" name="dilutionDate" maxlength="10" style="width: 8em;"
507            onblur="dateOnChange('dilutionDate')" onkeypress="focusOnEnter(event, 'dilutionOperator')">
508            <base:icon 
509              onclick="Dates.selectDate('Dilution date', 'reggie', 'dilutionDate', 'setDate', 'yyyyMMdd')"
510              image="calendar.png" 
511              tooltip="Select a date from a calendar" 
512              tabindex="-1"
513            />
514        </td>
515        <td>
516          <input type="text" name="dilutionOperator" value="<%=HTML.encodeTags(user.getName()) %>" 
517            style="width: 95%;" maxlength="255" onkeypress="focusOnEnter(event, 'purificationDate')">
518        </td>
519        <td class="status" id="dilutionDate.status"></td>
520      </tr>
521      <tr>
522        <td class="subprompt">Purification</td>
523        <td>
524          <input type="text" name="purificationDate" maxlength="10" style="width: 8em;"
525            onblur="dateOnChange('purificationDate')" onkeypress="focusOnEnter(event, 'purificationOperator')">
526            <base:icon 
527              onclick="Dates.selectDate('Purification date', 'reggie', 'purificationDate', 'setDate', 'yyyyMMdd')"
528              image="calendar.png" 
529              tooltip="Select a date from a calendar" 
530              tabindex="-1"
531            />
532        </td>
533        <td>
534          <input type="text" name="purificationOperator" value="<%=HTML.encodeTags(user.getName()) %>" 
535            style="width: 95%;" maxlength="255" onkeypress="focusOnEnter(event, 'fragmentationDate')">
536        </td>
537        <td class="status" id="purificationDate.status"></td>
538      </tr>
539      <tr>
540        <td class="subprompt">Fragmentation</td>
541        <td>
542          <input type="text" name="fragmentationDate" maxlength="10" style="width: 8em;"
543            onblur="dateOnChange('fragmentationDate')" onkeypress="focusOnEnter(event, 'fragmentationOperator')">
544            <base:icon 
545              onclick="Dates.selectDate('Fragmentation date', 'reggie', 'fragmentationDate', 'setDate', 'yyyyMMdd')"
546              image="calendar.png" 
547              tooltip="Select a date from a calendar" 
548              tabindex="-1"
549            />
550        </td>
551        <td>
552          <input type="text" name="fragmentationOperator" value="<%=HTML.encodeTags(user.getName()) %>" 
553            style="width: 95%;" maxlength="255" onkeypress="focusOnEnter(event, 'cleanupDate')">
554        </td>
555        <td class="status" id="fragmentationDate.status"></td>
556      </tr>
557      <tr>
558        <td class="subprompt">Cleanup</td>
559        <td>
560          <input type="text" name="cleanupDate" maxlength="10" style="width: 8em;"
561            onblur="dateOnChange('cleanupDate')" onkeypress="focusOnEnter(event, 'cleanupOperator')">
562            <base:icon 
563              onclick="Dates.selectDate('Cleanup date', 'reggie', 'cleanupDate', 'setDate', 'yyyyMMdd')"
564              image="calendar.png" 
565              tooltip="Select a date from a calendar" 
566              tabindex="-1"
567            />
568        </td>
569        <td>
570          <input type="text" name="cleanupOperator" value="<%=HTML.encodeTags(user.getName()) %>" 
571            style="width: 95%;" maxlength="255" onkeypress="focusOnEnter(event, 'pdf.path')">
572        </td>
573        <td class="status" id="cleanupDate.status"></td>
574      </tr>
575      <tr valign="top">
576        <td class="prompt">BA PDF file</td>
577        <td class="input" colspan="2">
578          <table>
579          <tr>
580          <td><input class="text required" type="text" 
581            name="pdf.path" value=""
582            size="50" onkeypress="doOnEnter(event, function(){document.getElementById('btnPdf').click()})"
583            onblur="pdfFileOnChange()"
584            ></td>
585          <td style="padding-left: 4px;"><base:button 
586              title="Browse&hellip;"
587              onclick="browseOnClick('pdf')"
588              id="btnPdf"
589              />
590          </td>
591          </tr>
592          </table>
593        </td>
594        <td class="status" id="pdf.status"></td>
595        <td class="help"><span id="pdf.message" class="message" style="display: none;"></span>
596          Select the <b>BioAnalyzer PDF file</b> that contains a printout with diagrams and other
597          useful documentation.
598        </td>
599      </tr>
600      <tr valign="top">
601        <td class="prompt">Protocol</td>
602        <td class="input" colspan="2"><select style="width:90%" name="mrnaProtocol" id="mrnaProtocol" 
603          onkeypress="focusOnEnter(event, 'mrnaOperator')"></select></td>
604        <td class="status" id="mrnaProtocol.status"></td>
605        <td class="help"><span id="mrnaProtocol.message" class="message" style="display: none;"></span>
606          Select the protocol which was used in the mRNA preparation.
607        </td>
608      </tr>
609      <tr valign="top">
610        <td class="prompt">Comments</td>
611        <td class="input" colspan="2"><textarea rows="4" cols="50" style="width: 90%;" name="comments" value="" onblur="commentsOnChange()"></textarea></td>
612        <td class="status" id="comments.status"></td>
613        <td class="help"><span id="comments.message" class="message" style="display: none;"></span>Comments about the mRNA processing.</td>
614      </tr>
615      </table>
616    </td>
617  </tr>
618  </table>
619  </div>
620 
621  <div class="loading" id="loading" style="display: none;"><table><tr><td><img src="../images/loading.gif"></td><td id="loading.msg">Please wait...</td></tr></table></div>
622 
623  <div class="messagecontainer error" id="errorMessage" style="display: none; width: 950px; margin-left: 20px; margin-bottom: 0px;"></div>
624 
625  <div id="messages" class="success" style="display: none; width: 950px; margin-left: 20px; margin-top: 20px;"></div>
626 
627  <table style="margin-left: 20px; margin-top: 10px;" class="navigation">
628    <tr>
629      <td><base:button id="gocancel" title="Cancel" onclick="goRestart(false)" style="display: none;"/></td>
630      <td><base:button id="gonext" title="Next" image="<%=home+"/images/gonext.png"%>" onclick="goNext(true)"/></td>
631      <td><base:button id="goregister" title="Register" image="<%=home+"/images/import.png"%>" onclick="goRegister()" style="display: none;"/></td>
632      <td><base:button id="gorestart" title="Restart" image="<%=home+"/images/goback.png"%>" onclick="goRestart(true)" style="display: none;"/></td>
633      <td id="gonext.message" class="message"></td>
634    </tr>
635  </table>
636 
637  </form>
638  </div>
639 
640</base:body>
641</base:page>
642<%
643}
644finally
645{
646  if (dc != null) dc.close();
647}
648%>
Note: See TracBrowser for help on using the repository browser.