source: trunk/grails-app/views/study/show.gsp @ 497

Last change on this file since 497 was 497, checked in by roberth, 9 years ago

Implemented RELTIME parsing and showing in the wizard.
Also made TEXT templatefields to show a textarea

  • Property svn:keywords set to Date Author Rev
File size: 27.0 KB
Line 
1
2<%@ page import="dbnp.studycapturing.Study" %>
3<%@ page import="dbnp.studycapturing.RelTime" %>
4<html>
5  <head>
6    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
7    <meta name="layout" content="main" />
8    <g:set var="entityName" value="${message(code: 'study.label', default: 'Study')}" />
9    <title><g:message code="default.show.label" args="[entityName]" /></title>
10    <script type="text/javascript">
11      // Flag whether the timelines have been loaded
12      var timelineloaded = false;
13     
14      // Number of timelines that should be loaded
15      var numTimelines = ${studyList.size()};
16     
17      // This method is called on the event body.onLoad
18      $(function() {
19              $("#tabs").tabs({
20                show: function(event, ui) {
21                  // If the events tab is shown, the timeline should be redrawn
22                  if( ui.tab.hash == '#events' && !timelineloaded ) {
23                    loadTimeline( 'eventstimeline', 'eventtitles', 0 );
24                    timelineloaded = true;
25                  }
26                }
27              });
28      });
29    </script>
30    <link rel="stylesheet" type="text/css" href="${resource(dir: 'css', file: 'studies.css')}"/>
31
32    <!-- Include scripts for the SIMILE timeline. See http://simile-widgets.org/wiki/ -->
33    <script type="text/javascript">
34      Timeline_ajax_url="${resource(dir: 'js', file: 'timeline-simile/timeline_ajax/simile-ajax-api.js')}";
35      Timeline_urlPrefix='${resource(dir: 'js', file: 'timeline-simile/')}';
36      Timeline_parameters='bundle=true';
37    </script>
38    <script src="${resource(dir: 'js', file: 'timeline-simile/timeline-api.js')}" type="text/javascript"></script>
39    <script src="${resource(dir: 'js', file: 'timeline-simile/custom-timeline.js')}" type="text/javascript"></script>
40    <script src="${resource(dir: 'js', file: 'jquery-callback-1.2.js')}" type="text/javascript"></script>
41
42    <!-- Create the JSON objects for the timeline with events -->
43    <script type="text/javascript">
44         /*
45          * Creates timeline bands for displaying different timelines
46          *
47          * @returns array with BandInfo objects, as described on http://simile-widgets.org/wiki/Timeline_GettingStarted
48          */
49        function createTimelineBands( timelineNr ) {
50          var bandInfos = [];
51          var eventSources = [];
52          var overviewEventSource = new Timeline.DefaultEventSource();
53
54          // The way the timeline should look. See http://www.linuxjournal.com/article/9301
55          var theme = Timeline.ClassicTheme.create();
56          var emptyEtherPainter = new Timeline.EmptyEtherPainter( { theme: theme } )
57
58          // Now create the bands for all studies, and add them to one timeline
59          // Multiple timeline on one page do not seem to work
60          <g:set var="bandNr" value="${0}" />
61          <g:each in="${studyList}" var="study" status="timelineNr">
62              // The date that the timeline should start on
63              var dateStr = "<g:formatDate format="yyyy/MM/dd HH:mm:ss" date="${study.startDate}"/>";
64              firstDate = new Date ( dateStr );
65
66              //------------- Eventgroup overview ---------------
67
68              <g:set var="datesBandNr" value="${bandNr}" />
69              // Add an empty band to show the dates
70              bandInfos[${bandNr}] =
71                     Timeline.createBandInfo({
72                        width:          40,
73                        intervalUnit:   Timeline.DateTime.DAY,
74                        intervalPixels: 40,
75                        showEventText:  false,
76                        date:           firstDate,
77                        timeZone:       +1,
78                        layout:         'original',
79                        theme:          theme
80                     });
81              bandTitleInfo[ timelineNr ][ ${bandNr} ] = {
82                title: "${study.title}",
83                subjects: "",
84                className: "studytitle"
85              };
86
87              <g:set var="bandNr" value="${bandNr+1}" />
88
89              <g:each in="${study.eventGroups}" var="eventGroup" status="i">
90
91                //------------- Eventgroup ${bandNr} ---------------
92
93                // Create an eventsource for all events
94                eventSources[${bandNr}] = new Timeline.DefaultEventSource();
95
96                // Load events for this eventsource (using jquery)
97                var event_url = '${createLink(controller:'study', action:'events', id:eventGroup.id, params: [startDate: study.startDate.getTime() ])}';
98                $.getJSON(event_url, $.callback( _loadJSONEvents, [0, ${bandNr}, eventSources[${bandNr}], overviewEventSource, event_url] ) );
99
100                // Create a new timeline band
101                bandInfos[${bandNr}] =
102                       Timeline.createBandInfo({
103                           eventSource:    eventSources[${bandNr}],
104                           width:          30,
105                           intervalUnit:   Timeline.DateTime.DAY,
106                           intervalPixels: 40,
107                           date:           firstDate,
108                           timeZone:       +1,
109                           syncWith:       1,
110                           layout:         'original',
111                           theme:          theme
112                       });
113
114                // Make sure the date isn't printed by using the empty ether painter
115                bandInfos[${bandNr}].etherPainter = emptyEtherPainter;
116
117                // Add a title to the bandinfo
118                <% sortedGroupSubjects = eventGroup.subjects.sort( { a, b -> a.name <=> b.name } as Comparator )  %>
119                bandTitleInfo[ timelineNr ][ ${bandNr} ] = {
120                  title: "${eventGroup.name}",
121                  subjects: "${sortedGroupSubjects.name.join( ', ' )}"
122                };
123
124                <g:set var="bandNr" value="${bandNr+1}" />
125              </g:each>
126
127              // Synchronize all bands
128              <g:each in="${study.eventGroups}" var="eventGroup" status="i">
129                bandInfos[${i + datesBandNr +1}].syncWith = ${datesBandNr};
130              </g:each>
131
132          </g:each>
133
134          return bandInfos;
135        }
136     </script>
137</head>
138<body>
139
140  <div class="body" id="studies">
141    <h1><g:message code="default.show.label" args="[entityName]" /></h1>
142    <g:if test="${flash.message}">
143      <div class="message">${flash.message}</div>
144    </g:if>
145    <div class="dialog">
146      <div id="tabs">
147        <ul>
148          <li><a href="#study">Study Information</a></li>
149          <li><a href="#subjects">Subjects</a></li>
150          <li><a href="#events">Events</a></li>
151          <li><a href="#event-group">Event Groups</a></li>
152          <li><a href="#assays">Assays</a></li>
153          <li><a href="#persons">Persons</a></li>
154          <li><a href="#publications">Publications</a></li>
155        </ul>
156
157        <div id="study">
158          <table>
159            <!-- only show the head section if there are multiple studies -->
160            <g:if test="${multipleStudies}">
161              <thead>
162                <tr>
163                  <th></th>
164                  <g:each in="${studyList}" var="studyInstance">
165                    <th>${studyInstance.title}</th>
166                  </g:each>
167                </tr>
168              </thead>
169            </g:if>
170            <%
171              // Determine a union of the fields from all studies, in order
172              // to show a proper list. We want every field to appear just once,
173              // so the list is filtered for unique values
174              studyFields = studyList[0].giveDomainFields() + studyList*.giveTemplateFields().flatten().unique()
175            %>
176            <!-- Show all template and domain fields, if filled -->
177            <g:each in="${studyFields}" var="field">
178              <%
179                // If a value is not set for any of the selected studies, the
180                // field should not appear in the list
181                showField = true in studyList.collect { it.fieldExists( field.name ) && it.getFieldValue( field.name ) != null }.flatten()
182              %>
183              <g:if test="${showField}">
184                <tr>
185                  <td>${field}</td>
186                  <g:each in="${studyList}" var="studyInstance">
187                    <td>${studyInstance.getFieldValue(field.name)}</td>
188                  </g:each>
189                </tr>
190              </g:if>
191            </g:each>
192
193            <!-- Add some extra fields -->
194            <tr>
195              <td>Events</td>
196              <g:each in="${studyList}" var="studyInstance">
197                <td>
198                  <g:if test="${studyInstance.giveEventTemplates().size()==0}">
199                    -
200                  </g:if>
201                  <g:else>
202                   ${studyInstance.giveEventTemplates().name.join(", ")}
203                  </g:else>
204                </td>
205              </g:each>
206            </tr>
207            <tr>
208              <td>Sampling events</td>
209              <g:each in="${studyList}" var="studyInstance">
210                <td>
211                  <g:if test="${studyInstance.giveSamplingEventTemplates().size()==0}">
212                    -
213                  </g:if>
214                  <g:else>
215                   ${studyInstance.giveSamplingEventTemplates().name.join(", ")}
216                  </g:else>
217                </td>
218              </g:each>
219            </tr>
220            <tr>
221              <td>Readers</td>
222              <g:each in="${studyList}" var="studyInstance">
223                <td>
224                  <g:if test="${studyInstance.readers.size()==0}">
225                    -
226                  </g:if>
227                  <g:else>
228                    <g:each in="${studyInstance.readers}" var="r" status="i">
229                      <g:if test="${i > 0}">, </g:if>
230                      <g:link controller="user" action="show" id="${r.id}">${r?.encodeAsHTML()}</g:link>
231                    </g:each>
232                  </g:else>
233                </td>
234              </g:each>
235            </tr>
236            <tr>
237              <td>Editors</td>
238              <g:each in="${studyList}" var="studyInstance">
239                <td>
240                  <g:if test="${studyInstance.editors.size()==0}">
241                    -
242                  </g:if>
243                  <g:else>
244                    <g:each in="${studyInstance.editors}" var="r" status="i">
245                      <g:if test="${i > 0}">, </g:if>
246                      <g:link controller="user" action="show" id="${r.id}">${r?.encodeAsHTML()}</g:link>
247                    </g:each>
248                  </g:else>
249                </td>
250              </g:each>
251            </tr>
252
253          </table>
254        </div>
255
256        <div id="subjects">
257
258          <g:if test="${studyList*.subjects.flatten().size()==0}">
259            No subjects in the selected studies
260          </g:if>
261          <g:else>
262            <table>
263              <thead>
264                <tr>
265                  <g:if test="${multipleStudies}">
266                    <th></th>
267                  </g:if>
268                  <g:each in="${new dbnp.studycapturing.Subject().giveDomainFields()}" var="field">
269                    <th>${field}</th>
270                  </g:each>
271
272                  <%
273                    // Determine a union of the fields for all different
274                    // subjects in all studies. In order to show a proper list.
275                    // We want every field to appear just once,
276                    // so the list is filtered for unique values
277                    subjectTemplates = studyList*.giveSubjectTemplates().flatten().unique()
278                    subjectFields = subjectTemplates*.fields.flatten().unique()
279
280                    showSubjectFields = subjectFields
281
282                    /*
283                     * These lines are rewritten because
284                     * performance sucked
285                     *
286                     *   // These took about 9 seconds (for 31 subjects and
287                     *   allSubjects = studyList*.subjects.flatten()
288                     *
289                     *   subjectFields = subjectFields.findAll { subjectField ->
290                     *     ( true in allSubjects.collect { subject -> subject.fieldExists( subjectField.name ) && subject.getFieldValue( subjectField.name ) != null }.flatten() )
291                     *   }
292                     */
293
294                    // Filter out all fields that are left blank for all subjects
295                    allSubjects = studyList*.subjects.flatten()
296
297                    showSubjectFields = []
298                    subjectFields.each { subjectField ->
299                      for( subject in allSubjects )
300                      {
301                        // If the field is filled for this subject, we have to
302                        // show the field and should not check any other
303                        // subjects (hence the break)
304                        if( subject.fieldExists( subjectField.name ) && subject.getFieldValue( subjectField.name ) ) {
305                          showSubjectFields << subjectField;
306                          break;
307                        }
308                      }
309                    }
310                  %>
311
312                  <g:each in="${showSubjectFields}" var="field">
313                    <th>${field}</th>
314                  </g:each>
315
316                </tr>
317              </thead>
318
319              <g:set var="i" value="${1}" />
320
321              <g:each in="${studyList}" var="studyInstance">
322                <%
323                  // Sort subjects by name
324                  subjects = studyInstance.subjects;
325                  sortedSubjects = subjects.sort( { a, b -> a.name <=> b.name } as Comparator )
326                %>
327
328                <g:each in="${sortedSubjects}" var="subject" status="j">
329                  <tr class="${(i % 2) == 0 ? 'odd' : 'even'}">
330                    <g:if test="${multipleStudies && j==0}">
331                      <td class="studytitle" rowspan="${sortedSubjects.size()}">
332                        ${studyInstance.title}
333                      </td>
334                    </g:if>
335                    <g:each in="${subject.giveDomainFields()}" var="field">
336                      <td>${subject.getFieldValue(field.name)}</td>
337                    </g:each>
338                 
339                    <g:each in="${showSubjectFields}" var="field">
340                      <td>
341                        <g:if test="${subject.fieldExists(field.name)}">
342                          ${subject.getFieldValue(field.name)}
343                        </g:if>
344                        <g:else>
345                          N/A
346                        </g:else>
347                      </td>
348                    </g:each>
349
350                  </tr>
351                  <g:set var="i" value="${i + 1}" />
352                </g:each>
353              </g:each>
354            </table>
355          </g:else>
356        </div>
357
358        <div id="events">
359          <g:if test="${studyList*.events.flatten().size()==0 && studyInstance*.samplingEvents.flatten().size()==0 }">
360            No events in these studies
361          </g:if>
362          <g:else>
363            <g:each in="${studyList}" var="study" status="i">
364              <div style="margin: 10px; ">
365                <div class="eventtitles" id="eventtitles-${i}"></div>
366                <div class="eventstimeline" id="eventstimeline-${i}"></div>
367              </div>
368            </g:each>
369            <noscript>
370              <table>
371                <thead>
372                  <tr>
373                    <g:if test="${multipleStudies}">
374                      <th></th>
375                    </g:if>
376                    <th>Start time</th>
377                    <th>Duration</th>
378                    <th>Type</th>
379                    <th>Sampling event</th>
380                    <th>Parameters</th>
381                  </tr>
382                </thead>
383
384                <g:set var="i" value="${1}" />
385
386                <g:each in="${studyList}" var="studyInstance">
387                  <%
388                    // Sort events by starttime and duration
389                    events = studyInstance.events + studyInstance.samplingEvents;
390                    sortedEvents = events.sort( { a, b ->
391                          a.startTime == b.startTime ?
392                            a.getDuration().getValue() <=> b.getDuration().getValue() :
393                            a.startTime <=> b.startTime
394                      } as Comparator )
395                  %>
396
397                  <g:each in="${sortedEvents}" var="event" status="j">
398                    <tr class="${(i % 2) == 0 ? 'odd' : 'even'}">
399                      <g:if test="${multipleStudies && j==0}">
400                        <td class="studytitle" rowspan="${sortedEvents.size()}">
401                          ${studyInstance.title}
402                        </td>
403                      </g:if>
404                      <td>${new RelTime(event.startTime).toPrettyString()}</td>
405                      <td>${event.getPrettyDuration()}</td>
406                      <td>${event.template.name}</td>
407                      <td>
408                        <g:if test="${event instanceof dbnp.studycapturing.SamplingEvent}">
409                          <g:checkBox name="samplingEvent" disabled="${true}" value="${true}"/>
410                        </g:if>
411                        <g:else>
412                          <g:checkBox name="event" disabled="${true}" value="${false}" />
413                        </g:else>
414                      </td>
415                      <td>
416                        <g:set var="fieldCounter" value="${1}" />
417                        <g:each in="${event.giveTemplateFields()}" var="field">
418                          <g:if test="${event.getFieldValue(field.name)}">
419                            <g:if test="${fieldCounter > 1}">, </g:if>
420                              ${field.name} = ${event.getFieldValue( field.name )}
421                            <g:set var="fieldCounter" value="${fieldCounter + 1}" />
422                          </g:if>
423                        </g:each>
424                      </td>
425                    </tr>
426
427                    <g:set var="i" value="${i + 1}" />
428                  </g:each>
429                </g:each>
430              </table>
431
432            </noscript>
433
434          </g:else>
435        </div>
436
437        <div id="event-group">
438          <g:if test="${studyList*.eventGroups.flatten().size()==0}">
439            No event groups in this study
440          </g:if>
441          <g:else>
442            <%
443              // Determine a union of the event templates for all different
444              // eventgroups in all studies, in order to show a proper list.
445              // We want every field to appear just once,
446              // so the list is filtered for unique values
447              groupTemplates = studyList*.giveAllEventTemplates().flatten().unique()
448              subjectFields = subjectTemplates*.fields.flatten().unique()
449            %>
450            <table>
451              <thead>
452                <tr>
453                  <g:if test="${multipleStudies}">
454                    <th></th>
455                  </g:if>
456                  <th>Name</th>
457                  <th colspan="${groupTemplates.size()}">Events</th>
458                  <th>Subjects</th>
459                </tr>
460                <tr>
461                  <g:if test="${multipleStudies}">
462                    <th></th>
463                  </g:if>
464                  <th></th>
465                  <g:each in="${groupTemplates}" var="eventTemplate">
466                    <th>${eventTemplate.name}</th>
467                  </g:each>
468                  <th></th>
469                </tr>
470              </thead>
471
472              <g:set var="i" value="${1}" />
473
474              <g:each in="${studyList}" var="studyInstance">
475
476                <g:each in="${studyInstance.eventGroups}" var="eventGroup" status="j">
477                  <tr class="${(i % 2) == 0 ? 'odd' : 'even'}">
478                    <g:if test="${multipleStudies && j==0}">
479                      <td class="studytitle" rowspan="${studyInstance.eventGroups.size()}">
480                        ${studyInstance.title}
481                      </td>
482                    </g:if>
483                    <td>${eventGroup.name}</td>
484
485                    <g:each in="${groupTemplates}" var="currentEventTemplate">
486                      <td>
487                        <g:each in="${eventGroup.events}" var="event">
488                          <g:if test="${event.template.name==currentEventTemplate.name}">
489
490                            <g:set var="fieldCounter" value="${1}" />
491                            <g:each in="${event.giveTemplateFields()}" var="field">
492                              <g:if test="${event.getFieldValue(field.name)}">
493                                <g:if test="${fieldCounter > 1}">, </g:if>
494                                  ${field.name} = ${event.getFieldValue( field.name )}
495                                <g:set var="fieldCounter" value="${fieldCounter + 1}" />
496                              </g:if>
497                            </g:each>
498                          </g:if>
499                        </g:each>
500                      </td>
501                    </g:each>
502                    <td>
503                      <% sortedGroupSubjects = eventGroup.subjects.sort( { a, b -> a.name <=> b.name } as Comparator )  %>
504                      ${sortedGroupSubjects.name.join( ', ' )}
505                    </td>
506                  </tr>
507
508                  <g:set var="i" value="${i + 1}" />
509                </g:each>
510
511              </g:each>
512
513            </table>
514          </g:else>
515        </div>
516
517        <div id="assays">
518          <g:if test="${studyList*.assays.flatten().size()==0}">
519            No assays in these studies
520          </g:if>
521          <g:else>
522            <table>
523              <thead>
524                <tr>
525                  <g:if test="${multipleStudies}">
526                    <th></th>
527                  </g:if>
528                  <th width="100">Assay Name</th>
529                  <th width="100">Module</th>
530                  <th>Type</th>
531                  <th width="150">Platform</th>
532                  <th>Url</th>
533                  <th>Samples</th>
534                </tr>
535              </thead>
536              <g:set var="i" value="${1}" />
537
538              <g:each in="${studyList}" var="studyInstance">
539                <g:each in="${studyInstance.assays}" var="assay" status="j">
540                  <tr class="${(i % 2) == 0 ? 'odd' : 'even'}">
541                    <g:if test="${multipleStudies && j==0}">
542                      <td class="studytitle" rowspan="${studyInstance.assays.size()}">
543                        ${studyInstance.title}
544                      </td>
545                    </g:if>
546                    <td>${assay.name}</td>
547                    <td>${assay.module.name}</td>
548                    <td>${assay.module.type}</td>
549                    <td>${assay.module.platform}</td>
550                    <td>${assay.module.url}</td>
551                    <td>
552                      <% sortedAssaySamples = assay.samples.sort( { a, b -> a.name <=> b.name } as Comparator )  %>
553                      ${sortedAssaySamples.name.join( ', ' )}
554                    </td>
555                  </tr>
556                  <g:set var="i" value="${i + 1}" />
557
558                </g:each>
559              </g:each>
560            </table>
561          </g:else>
562        </div>
563
564        <div id="persons">
565          <%
566            // Determine a list of all persons
567            allPersons = studyList*.persons*.person.flatten().unique()
568          %>
569          <g:if test="${allPersons.size()==0}">
570            No persons involved in these studies
571          </g:if>
572          <g:else>
573            <table>
574              <tr>
575                <thead>
576                  <th>Name</th>
577                  <th>Affiliations</th>
578                  <th>Phone</th>
579                  <th>Email</th>
580                  <g:if test="${multipleStudies}">
581                    <g:each in="${studyList}" var="studyInstance">
582                      <th>${studyInstance.title}</th>
583                    </g:each>
584                  </g:if>
585                  <g:else>
586                    <th>Role</th>
587                  </g:else>
588                </thead>
589              </tr>
590              <g:each in="${allPersons}" var="person" status="i">
591                <tr class="${(i % 2) == 0 ? 'odd' : 'even'}">
592                  <td>${person.firstName} ${person.prefix} ${person.lastName}</td>
593                  <td>
594                    ${person.affiliations.join(', ')}
595                  </td>
596                  <td>${person.phone}</td>
597                  <td>${person.email}</td>
598                  <g:each in="${studyList}" var="studyInstance">
599                    <%
600                      studyperson = studyInstance.persons.find { it.person == person }
601                    %>
602                    <td>
603                      <g:if test="${studyperson}">
604                        ${studyperson.role.name}
605                      </g:if>
606                     </td>
607                  </g:each>
608
609                </tr>
610              </g:each>
611            </table>
612          </g:else>
613        </div>
614
615        <div id="publications">
616          <%
617            // Determine a list of all persons
618            allPublications = studyList*.publications.flatten().unique()
619          %>
620          <g:if test="${allPublications.size()==0}">
621            No publications attached to these studies
622          </g:if>
623          <g:else>
624            <table>
625              <tr>
626                <thead>
627                  <th>Title</th>
628                  <th>Authors</th>
629                  <th>Comments</th>
630
631                  <g:if test="${multipleStudies}">
632                    <g:each in="${studyList}" var="studyInstance">
633                      <th>${studyInstance.title}</th>
634                    </g:each>
635                  </g:if>
636                </thead>
637              </tr>
638              <g:each in="${allPublications}" var="publication" status="i">
639                <tr class="${(i % 2) == 0 ? 'odd' : 'even'}">
640                  <td>${publication.title}</td>
641                  <td>
642                    ${publication.authorsList}
643                  </td>
644                  <td>${publication.comments}</td>
645                  <g:if test="${multipleStudies}">
646                    <g:each in="${studyList}" var="studyInstance">
647                      <td>
648                        <g:if test="${publication in studyInstance.publications}">
649                          x
650                        </g:if>
651                      </td>
652                    </g:each>
653                  </g:if>
654                </tr>
655              </g:each>
656            </table>
657          </g:else>
658        </div>
659
660      </div>
661    </div>
662    <br>
663    <div class="buttons">
664      <g:form>
665        <g:if test="${studyList.size() == 1}">
666          <g:set var="studyInstance" value="${studyList[0]}" />
667          <g:hiddenField name="id" value="${studyInstance?.id}" />
668          <span class="button"><g:actionSubmit class="edit" action="edit" value="${message(code: 'default.button.edit.label', default: 'Edit')}" /></span>
669          <span class="button"><g:actionSubmit class="delete" action="delete" value="${message(code: 'default.button.delete.label', default: 'Delete')}" onclick="return confirm('${message(code: 'default.button.delete.confirm.message', default: 'Are you sure?')}');" /></span>
670        </g:if>
671        <span class="button"><g:link class="backToList" action="list">Back to list</g:link></span>
672      </g:form>
673    </div>
674
675  </div>
676</body>
677</html>
Note: See TracBrowser for help on using the repository browser.