Changeset 467

Show
Ignore:
Timestamp:
26-05-10 10:50:53 (4 years ago)
Author:
roberth
Message:

Updated study view to show the events on a timeline.

Location:
trunk
Files:
112 added
4 modified

Legend:

Unmodified
Added
Removed
  • trunk/grails-app/conf/BootStrap.groovy

    r464 r467  
    389389                                        researchQuestion:"Leptin etc.", 
    390390                                        ecCode:"2007117.c", 
    391                                         startDate: Date.parse('yyyy-MM-dd','2007-12-11') 
     391                                        startDate: Date.parse('yyyy-MM-dd','2008-01-02') 
    392392                                ) 
    393393                                .with { if (!validate()) { errors.each { println it} } else save()} 
  • trunk/grails-app/controllers/dbnp/studycapturing/StudyController.groovy

    r454 r467  
    11package dbnp.studycapturing 
     2 
     3import grails.converters.* 
     4 
    25/** 
    36 * Controller class for studies 
     
    4548    }*/ 
    4649 
     50    /** 
     51     * Shows one or more studies 
     52     */ 
    4753    def show = { 
    4854        def startTime = System.currentTimeMillis() 
    4955 
    50         def studyInstance = Study.get(params.id) 
     56        def studyInstance = Study.get( params.id ) 
    5157        if (!studyInstance) { 
    5258            flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'study.label', default: 'Study'), params.id])}" 
     
    6167    } 
    6268 
     69    /** 
     70     * Gives the events for one eventgroup in JSON format 
     71     * 
     72     */ 
     73    def events = { 
     74        def eventGroup = EventGroup.get(params.id) 
     75        def startDate  = params.startDate 
     76 
     77        if (!eventGroup) { 
     78            flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'eventgroup.label', default: 'Eventgroup'), params.id])}" 
     79            redirect(action: "list") 
     80        } 
     81        else { 
     82 
     83            // Create JSON object 
     84            def json = [ 'dateTimeFormat': 'iso8601', events: [] ]; 
     85 
     86            // Add the start of the study as event 
     87            /* 
     88            json.events << [ 
     89                'start':    startDate, 
     90                'durationEvent': false, 
     91                'title': "Start date study", 
     92                'color': 'red' 
     93            ] 
     94            */ 
     95            
     96            // Add all other events 
     97            for( event in eventGroup.events ) { 
     98                def parameters = [] 
     99                for( templateField in event.giveTemplateFields() ) { 
     100                    def value = event.getFieldValue( templateField.name ); 
     101                    if( value ) { 
     102                        parameters << templateField.name + " = " + value; 
     103                    } 
     104                } 
     105 
     106                json.events << [ 
     107                    'start':    event.startTime, 
     108                    'end':      event.endTime, 
     109                    'durationEvent': !event.isSamplingEvent(), 
     110                    'title': event.template.name + " (" + parameters.join( ', ' ) + ")", 
     111                    'description': parameters 
     112                ] 
     113            } 
     114            render json as JSON 
     115        } 
     116    } 
    63117 
    64118    /*def edit = { 
  • trunk/grails-app/views/study/show.gsp

    r454 r467  
    55    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 
    66    <meta name="layout" content="main" /> 
    7   <g:set var="entityName" value="${message(code: 'study.label', default: 'Study')}" /> 
    8   <title><g:message code="default.show.label" args="[entityName]" /></title> 
    9   <script type="text/javascript"> 
    10     $(function() { 
    11             $("#tabs").tabs(); 
    12     }); 
    13   </script> 
    14   <link rel="stylesheet" href="${resource(dir: 'css', file: 'studies.css')}"/> 
    15  
     7    <g:set var="entityName" value="${message(code: 'study.label', default: 'Study')}" /> 
     8    <title><g:message code="default.show.label" args="[entityName]" /></title> 
     9    <script type="text/javascript"> 
     10      // Flag whether the timelines have been loaded 
     11      var timelineloaded = false; 
     12       
     13      // Number of timelines that should be loaded 
     14      var numTimelines = ${studyList.size()}; 
     15       
     16      // This method is called on the event body.onLoad 
     17      $(function() { 
     18              $("#tabs").tabs({ 
     19                show: function(event, ui) { 
     20                  // If the events tab is shown, the timeline should be redrawn 
     21                  if( ui.tab.hash == '#events' && !timelineloaded ) { 
     22                    loadTimeline( 'eventstimeline', 'eventtitles', 0 ); 
     23                    timelineloaded = true; 
     24                  } 
     25                } 
     26              }); 
     27      }); 
     28    </script> 
     29    <link rel="stylesheet" type="text/css" href="${resource(dir: 'css', file: 'studies.css')}"/> 
     30 
     31    <!-- Include scripts for the SIMILE timeline. See http://simile-widgets.org/wiki/ --> 
     32    <script type="text/javascript"> 
     33      Timeline_ajax_url="${resource(dir: 'js', file: 'timeline-simile/timeline_ajax/simile-ajax-api.js')}"; 
     34      Timeline_urlPrefix='${resource(dir: 'js', file: 'timeline-simile/')}'; 
     35      Timeline_parameters='bundle=true'; 
     36    </script> 
     37    <script src="${resource(dir: 'js', file: 'timeline-simile/timeline-api.js')}" type="text/javascript"></script> 
     38    <script src="${resource(dir: 'js', file: 'timeline-simile/custom-timeline.js')}" type="text/javascript"></script> 
     39    <script src="${resource(dir: 'js', file: 'jquery-callback-1.2.js')}" type="text/javascript"></script> 
     40 
     41    <!-- Create the JSON objects for the timeline with events --> 
     42    <script type="text/javascript"> 
     43         /* 
     44          * Creates timeline bands for displaying different timelines 
     45          * 
     46          * @returns array with BandInfo objects, as described on http://simile-widgets.org/wiki/Timeline_GettingStarted 
     47          */ 
     48        function createTimelineBands( timelineNr ) { 
     49          var bandInfos = []; 
     50          var eventSources = []; 
     51          var overviewEventSource = new Timeline.DefaultEventSource(); 
     52 
     53          // The way the timeline should look. See http://www.linuxjournal.com/article/9301 
     54          var theme = Timeline.ClassicTheme.create(); 
     55          var emptyEtherPainter = new Timeline.EmptyEtherPainter( { theme: theme } ) 
     56 
     57          // Now create the bands for all studies, and add them to one timeline 
     58          // Multiple timeline on one page do not seem to work 
     59          <g:set var="bandNr" value="${0}" /> 
     60          <g:each in="${studyList}" var="study" status="timelineNr"> 
     61              // The date that the timeline should start on 
     62              var dateStr = "<g:formatDate format="yyyy/MM/dd HH:mm:ss" date="${study.startDate}"/>"; 
     63              firstDate = new Date ( dateStr ); 
     64 
     65              //------------- Eventgroup overview --------------- 
     66 
     67              <g:set var="datesBandNr" value="${bandNr}" /> 
     68              // Add an empty band to show the dates 
     69              bandInfos[${bandNr}] = 
     70                     Timeline.createBandInfo({ 
     71                        width:          40, 
     72                        intervalUnit:   Timeline.DateTime.DAY, 
     73                        intervalPixels: 40, 
     74                        showEventText:  false, 
     75                        date:           firstDate, 
     76                        timeZone:       +1, 
     77                        layout:         'original', 
     78                        theme:          theme 
     79                     }); 
     80              bandTitleInfo[ timelineNr ][ ${bandNr} ] = { 
     81                title: "${study.title}", 
     82                subjects: "", 
     83                className: "studytitle" 
     84              }; 
     85 
     86              <g:set var="bandNr" value="${bandNr+1}" /> 
     87 
     88              <g:each in="${study.eventGroups}" var="eventGroup" status="i"> 
     89 
     90                //------------- Eventgroup ${bandNr} --------------- 
     91 
     92                // Create an eventsource for all events 
     93                eventSources[${bandNr}] = new Timeline.DefaultEventSource(); 
     94 
     95                // Load events for this eventsource (using jquery) 
     96                var event_url = '${createLink(controller:'study', action:'events', id:eventGroup.id, params: [startDate: study.startDate])}'; 
     97                $.getJSON(event_url, $.callback( _loadJSONEvents, [0, ${bandNr}, eventSources[${bandNr}], overviewEventSource, event_url] ) ); 
     98 
     99                // Create a new timeline band 
     100                bandInfos[${bandNr}] = 
     101                       Timeline.createBandInfo({ 
     102                           eventSource:    eventSources[${bandNr}], 
     103                           width:          30, 
     104                           intervalUnit:   Timeline.DateTime.DAY, 
     105                           intervalPixels: 40, 
     106                           date:           firstDate, 
     107                           timeZone:       +1, 
     108                           syncWith:       1, 
     109                           layout:         'original', 
     110                           theme:          theme 
     111                       }); 
     112 
     113                // Make sure the date isn't printed by using the empty ether painter 
     114                bandInfos[${bandNr}].etherPainter = emptyEtherPainter; 
     115 
     116                // Add a title to the bandinfo 
     117                <% sortedGroupSubjects = eventGroup.subjects.sort( { a, b -> a.name <=> b.name } as Comparator )  %> 
     118                bandTitleInfo[ timelineNr ][ ${bandNr} ] = { 
     119                  title: "${eventGroup.name}", 
     120                  subjects: "${sortedGroupSubjects.name.join( ', ' )}" 
     121                }; 
     122 
     123                <g:set var="bandNr" value="${bandNr+1}" /> 
     124              </g:each> 
     125 
     126              // Synchronize all bands 
     127              <g:each in="${study.eventGroups}" var="eventGroup" status="i"> 
     128                bandInfos[${i + datesBandNr +1}].syncWith = ${datesBandNr}; 
     129              </g:each> 
     130 
     131          </g:each> 
     132 
     133          return bandInfos; 
     134        } 
     135     </script> 
    16136</head> 
    17137<body> 
     
    23143    </g:if> 
    24144    <div class="dialog"> 
    25  
    26145      <div id="tabs"> 
    27146        <ul> 
     
    36155 
    37156        <div id="study"> 
    38  
    39157          <table> 
    40158            <!-- only show the head section if there are multiple studies --> 
     
    242360          </g:if> 
    243361          <g:else> 
    244  
     362            <g:each in="${studyList}" var="study" status="i"> 
     363              <div style="margin: 10px; "> 
     364                <div class="eventtitles" id="eventtitles-${i}"></div> 
     365                <div class="eventstimeline" id="eventstimeline-${i}"></div> 
     366              </div> 
     367            </g:each> 
     368            <noscript> 
    245369              <table> 
    246370                <thead> 
     
    304428                </g:each> 
    305429              </table> 
     430 
     431            </noscript> 
    306432 
    307433          </g:else> 
  • trunk/web-app/css/studies.css

    r453 r467  
    2424    vertical-align: center; 
    2525} 
     26 
     27/* 
     28    Hide the timeline by default in order to create a good layout for non-script 
     29    browsers. The div is shown again using javascript 
     30*/ 
     31.eventstimeline { 
     32    display: none; 
     33    height: 350px; 
     34    margin-left: 200px; 
     35    border: 1px solid #cccccc; 
     36} 
     37.eventtitles { 
     38    display: none; 
     39    position: absolute; width: 200px; 
     40} 
     41.eventtitles .timeline-subjects { 
     42    margin-top: 3px; 
     43    font-size: 0.9em; 
     44    color: #555; 
     45} 
     46 
     47.eventtitles .timeline-title { 
     48    position: absolute; 
     49    width: 190px; 
     50    padding: 5px; 
     51} 
     52 
     53/* Hide titles for overview and date bands */ 
     54.eventtitles .timeline-title-0, 
     55.eventtitles .timeline-title-1 { display: none; } 
     56 
     57/* Background color of the overview and date bands */ 
     58.eventstimeline .timeline-band-0 .timeline-ether-bg { background-color:#eee } 
     59.eventstimeline .timeline-band-1 .timeline-ether-bg { background-color:#ddd; } 
     60 
     61/* Background colors of the other bands (and titles)*/ 
     62.eventstimeline .timeline-band-2 .timeline-ether-bg , 
     63.eventstimeline .timeline-band-4 .timeline-ether-bg , 
     64.eventstimeline .timeline-band-6 .timeline-ether-bg , 
     65.eventstimeline .timeline-band-8 .timeline-ether-bg , 
     66.eventstimeline .timeline-band-10 .timeline-ether-bg , 
     67.eventstimeline .timeline-band-12 .timeline-ether-bg , 
     68.eventstimeline .timeline-band-14 .timeline-ether-bg , 
     69.eventstimeline .timeline-band-16 .timeline-ether-bg, 
     70.eventtitles .even 
     71    {background-color:#eee} 
     72 
     73.eventstimeline .timeline-band-3 .timeline-ether-bg , 
     74.eventstimeline .timeline-band-5 .timeline-ether-bg , 
     75.eventstimeline .timeline-band-7 .timeline-ether-bg , 
     76.eventstimeline .timeline-band-9 .timeline-ether-bg , 
     77.eventstimeline .timeline-band-11 .timeline-ether-bg , 
     78.eventstimeline .timeline-band-13 .timeline-ether-bg , 
     79.eventstimeline .timeline-band-15 .timeline-ether-bg , 
     80.eventstimeline .timeline-band-17 .timeline-ether-bg, 
     81.eventtitles .odd 
     82    {background-color:#ddd} 
     83 
     84.eventtitles .studytitle { font-weight: bold; background-color: transparent; } 
     85