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

Last change on this file since 497 was 497, checked in by roberth, 12 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.