Changeset 536
- Timestamp:
- Jun 7, 2010, 9:20:00 AM (14 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/grails-app/conf/BootStrap.groovy
r531 r536 960 960 name: currentSubject.name + '_B', 961 961 material: bloodTerm, 962 template: humanBloodSampleTemplate, 962 963 parentSubject: currentSubject, 963 964 parentEvent: bloodSamplingEvent 964 965 ); 966 currentSample.setFieldValue( "Text on vial", "T" + (Math.random() * 100L) ) 965 967 966 968 humanStudy.addToSubjects(currentSubject).addToSamples(currentSample).with { if (!validate()) { errors.each { println it} } else save()} -
trunk/grails-app/controllers/dbnp/studycapturing/StudyController.groovy
r497 r536 31 31 } 32 32 33 /*def create = {34 def studyInstance = new Study()35 studyInstance.properties = params36 return [studyInstance: studyInstance]37 }38 39 def save = {40 def studyInstance = new Study(params)41 if (studyInstance.save(flush: true)) {42 flash.message = "${message(code: 'default.created.message', args: [message(code: 'study.label', default: 'Study'), studyInstance.id])}"43 redirect(action: "show", id: studyInstance.id)44 }45 else {46 render(view: "create", model: [studyInstance: studyInstance])47 }48 }*/49 50 33 /** 51 34 * Shows one or more studies … … 72 55 */ 73 56 def events = { 74 def eventGroup = EventGroup.get(params.id) 57 def eventGroupId = Integer.parseInt( params.id ); 58 def studyId = Integer.parseInt( params.study ); 59 def eventGroup; 60 61 // eventGroupId == -1 means that the orphaned events should be given 62 if( eventGroupId == -1 ) { 63 def studyInstance = Study.get( studyId ) 64 65 if (studyInstance == null) { 66 flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'study.label', default: 'Study'), studyId])}" 67 redirect(action: "list"); 68 return; 69 } 70 71 events = studyInstance.getOrphanEvents(); 72 } else { 73 eventGroup = EventGroup.get(params.id) 74 75 if (eventGroup == null) { 76 flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'eventgroup.label', default: 'Eventgroup'), params.id])}" 77 redirect(action: "list"); 78 return; 79 } 80 events = eventGroup?.events; 81 } 75 82 76 83 // This parameter should give the startdate of the study in milliseconds 77 84 // since 1-1-1970 78 85 long startDate = Long.parseLong( params.startDate ) 79 80 if (!eventGroup) { 81 flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'eventgroup.label', default: 'Eventgroup'), params.id])}" 82 redirect(action: "list") 86 87 // Create JSON object 88 def json = [ 'dateTimeFormat': 'iso8601', events: [] ]; 89 90 // Add all other events 91 for( event in events ) { 92 def parameters = [] 93 for( templateField in event.giveTemplateFields() ) { 94 def value = event.getFieldValue( templateField.name ); 95 if( value ) { 96 parameters << templateField.name + " = " + value; 97 } 98 } 99 100 json.events << [ 101 'start': new Date( startDate + event.startTime * 1000 ), 102 'end': new Date( startDate + event.endTime * 1000 ), 103 'durationEvent': !event.isSamplingEvent(), 104 'title': event.template.name + " (" + parameters.join( ', ' ) + ")", 105 'description': parameters 106 ] 83 107 } 84 else { 85 86 // Create JSON object 87 def json = [ 'dateTimeFormat': 'iso8601', events: [] ]; 88 89 // Add the start of the study as event 90 /* 91 json.events << [ 92 'start': startDate, 93 'durationEvent': false, 94 'title': "Start date study", 95 'color': 'red' 96 ] 97 */ 98 99 // Add all other events 100 for( event in eventGroup.events ) { 101 def parameters = [] 102 for( templateField in event.giveTemplateFields() ) { 103 def value = event.getFieldValue( templateField.name ); 104 if( value ) { 105 parameters << templateField.name + " = " + value; 106 } 107 } 108 109 json.events << [ 110 'start': new Date( startDate + event.startTime * 1000 ), 111 'end': new Date( startDate + event.endTime * 1000 ), 112 'durationEvent': !event.isSamplingEvent(), 113 'title': event.template.name + " (" + parameters.join( ', ' ) + ")", 114 'description': parameters 115 ] 116 } 117 render json as JSON 118 } 108 render json as JSON 119 109 } 120 110 -
trunk/grails-app/domain/dbnp/studycapturing/Event.groovy
r506 r536 84 84 } 85 85 86 def belongsToGroup( Set<EventGroup> groups ){ 87 def eventFound = false; 88 def that = this; 89 groups.each{ eventgroup -> 90 if( !eventFound ) { 91 eventFound = ( that.id in eventgroup.events.id ); 92 } 93 } 94 95 return eventFound; 96 } 97 86 98 def String toString() { 87 99 return fieldExists('Description') ? getFieldValue('Description') : "" -
trunk/grails-app/domain/dbnp/studycapturing/Study.groovy
r511 r536 66 66 } 67 67 68 /** 69 * returns all events and sampling events that do not belong to a group 70 */ 71 def Set<Event> getOrphanEvents() { 72 def orphans = 73 events.findAll{ event -> !event.belongsToGroup( eventGroups ) } + 74 samplingEvents.findAll { event -> !event.belongsToGroup( eventGroups ) }; 75 76 return orphans; 77 } 78 68 79 /** 69 80 * Return the unique Subject templates that are used in this study -
trunk/grails-app/domain/dbnp/studycapturing/TemplateEntity.groovy
r507 r536 585 585 /** 586 586 * Convenience method. Returns all unique templates used within a collection of TemplateEntities. 587 * 588 * If the collection is empty, an empty set is returned. If none of the entities contains 589 * a template, also an empty set is returned. 587 590 */ 588 591 static Set<Template> giveTemplates(Set<TemplateEntity> entityCollection) { 589 return entityCollection*.template.unique(); 592 def set = entityCollection*.template.unique(); 593 594 // If one or more entities does not have a template, the resulting 595 // set contains null. That is not what is meant. 596 return set.findAll { it != null }; 590 597 } 591 598 -
trunk/grails-app/views/study/show.gsp
r522 r536 1 1 2 2 <%@ page import="dbnp.studycapturing.Study" %> 3 <%@ page import="dbnp.studycapturing.EventGroup" %> 3 4 <%@ page import="dbnp.studycapturing.RelTime" %> 4 5 <html> … … 20 21 show: function(event, ui) { 21 22 // If the events tab is shown, the timeline should be redrawn 22 if( ui.tab.hash == '#events ' && !timelineloaded ) {23 if( ui.tab.hash == '#events-timeline' && !timelineloaded ) { 23 24 loadTimeline( 'eventstimeline', 'eventtitles', 0 ); 24 25 timelineloaded = true; … … 86 87 87 88 <g:set var="bandNr" value="${bandNr+1}" /> 88 89 <g:each in="${study.eventGroups}" var="eventGroup" status="i"> 89 <% 90 def sortedEventGroups = study.eventGroups.sort( { a, b -> 91 return a.name <=> b.name; 92 } as Comparator ); 93 94 def orphans = study.getOrphanEvents(); 95 if( orphans.size() > 0 ) { 96 sortedEventGroups.add( new EventGroup( 97 id: -1, 98 name: 'No group', 99 events: orphans, 100 subjects: [] 101 )); 102 } 103 104 %> 105 <g:each in="${sortedEventGroups}" var="eventGroup" status="i"> 90 106 91 107 //------------- Eventgroup ${bandNr} --------------- … … 95 111 96 112 // Load events for this eventsource (using jquery) 97 var event_url = '${createLink(controller:'study', action:'events', id: eventGroup.id, params: [startDate: study.startDate.getTime()])}';113 var event_url = '${createLink(controller:'study', action:'events', id:( eventGroup.id ? eventGroup.id : -1 ), params: [ startDate: study.startDate.getTime(), study: study.id ])}'; 98 114 $.getJSON(event_url, $.callback( _loadJSONEvents, [0, ${bandNr}, eventSources[${bandNr}], overviewEventSource, event_url] ) ); 99 115 … … 156 172 bandTitleInfo[ timelineNr ][ ${bandNr} ] = { 157 173 title: "${eventGroup.name}", 174 className: "<g:if test="${ eventGroup.id == -1 || !eventGroup.id }">no_group</g:if>", 158 175 subjects: "${showSubjects}" 159 176 }; … … 163 180 164 181 // Synchronize all bands 165 <g:each in="${s tudy.eventGroups}" var="eventGroup" status="i">182 <g:each in="${sortedEventGroups}" var="eventGroup" status="i"> 166 183 bandInfos[${i + datesBandNr +1}].syncWith = ${datesBandNr}; 167 184 </g:each> … … 185 202 <li><a href="#study">Study Information</a></li> 186 203 <li><a href="#subjects">Subjects</a></li> 187 <li><a href="#events ">Events</a></li>188 <li><a href="#event -group">Event Groups</a></li>204 <li><a href="#events-timeline">Events timeline</a></li> 205 <li><a href="#events-table">Events table</a></li> 189 206 <li><a href="#assays">Assays</a></li> 207 <li><a href="#samples">Samples</a></li> 190 208 <li><a href="#persons">Persons</a></li> 191 209 <li><a href="#publications">Publications</a></li> … … 313 331 // so the list is filtered for unique values 314 332 subjectTemplates = studyList*.giveSubjectTemplates().flatten().unique() 315 subjectFields = subjectTemplates*.fields.flatten().unique() 316 317 showSubjectFields = subjectFields 318 319 /* 333 if( !subjectTemplates ) { 334 subjectTemplates = []; 335 subjectFields = []; 336 } else { 337 subjectFields = subjectTemplates*.fields.flatten().unique() 338 if( !subjectFields ) { 339 subjectFields = []; 340 } 341 } 342 343 /* 320 344 * These lines are rewritten because 321 345 * performance sucked … … 393 417 </div> 394 418 395 <div id="events ">419 <div id="events-timeline"> 396 420 <g:if test="${studyList*.events.flatten().size()==0 && studyInstance*.samplingEvents.flatten().size()==0 }"> 397 421 No events in these studies … … 472 496 </div> 473 497 474 <div id="event -group">498 <div id="events-table"> 475 499 <g:if test="${studyList*.eventGroups.flatten().size()==0}"> 476 500 No event groups in this study … … 510 534 511 535 <g:each in="${studyList}" var="studyInstance"> 512 513 <g:each in="${studyInstance.eventGroups}" var="eventGroup" status="j"> 536 <% 537 def sortedEventGroups = studyInstance.eventGroups.sort( { a, b -> 538 return a.name <=> b.name; 539 } as Comparator ); 540 541 def orphans = studyInstance.getOrphanEvents(); 542 if( orphans.size() > 0 ) { 543 sortedEventGroups.add( new EventGroup( 544 id: -1, 545 name: 'No group', 546 events: orphans, 547 subjects: [] 548 )); 549 } 550 551 %> 552 <g:each in="${sortedEventGroups}" var="eventGroup" status="j"> 514 553 <tr class="${(i % 2) == 0 ? 'odd' : 'even'}"> 515 554 <g:if test="${multipleStudies && j==0}"> 516 <td class="studytitle" rowspan="${s tudyInstance.eventGroups.size()}">555 <td class="studytitle" rowspan="${sortedEventGroups.size()}"> 517 556 ${studyInstance.title} 518 557 </td> … … 595 634 </g:each> 596 635 </g:each> 636 </table> 637 </g:else> 638 </div> 639 640 <div id="samples"> 641 642 <g:if test="${studyList*.samples.flatten().size()==0}"> 643 No samples in the selected studies 644 </g:if> 645 <g:else> 646 <table> 647 <thead> 648 <tr> 649 <g:if test="${multipleStudies}"> 650 <th></th> 651 </g:if> 652 <g:each in="${new dbnp.studycapturing.Sample().giveDomainFields()}" var="field"> 653 <th>${field}</th> 654 </g:each> 655 656 <% 657 // Determine a union of the fields for all different 658 // samples in all studies. In order to show a proper list. 659 // We want every field to appear just once, 660 // so the list is filtered for unique values 661 sampleTemplates = studyList*.giveSampleTemplates().flatten().unique() 662 663 if( !sampleTemplates ) { 664 sampleTemplates = []; 665 sampleFields = []; 666 showSampleFields = []; 667 } else { 668 sampleFields = sampleTemplates*.fields.flatten().unique() 669 if( !sampleFields ) { 670 sampleFields = []; 671 showSampleFields = []; 672 } else { 673 // Filter out all fields that are left blank for all samples 674 allSamples = studyList*.samples.flatten() 675 676 showSampleFields = []; 677 sampleFields.each { sampleField -> 678 for( sample in allSamples ) 679 { 680 // If the field is filled for this subject, we have to 681 // show the field and should not check any other 682 // samples (hence the break) 683 if( sample.fieldExists( sampleField.name ) && sample.getFieldValue( sampleField.name ) ) { 684 showSampleFields << sampleField; 685 break; 686 } 687 } 688 } 689 } 690 } 691 %> 692 693 <g:each in="${showSampleFields}" var="field"> 694 <th>${field}</th> 695 </g:each> 696 697 </tr> 698 </thead> 699 700 <g:set var="i" value="${1}" /> 701 702 <g:each in="${studyList}" var="studyInstance"> 703 <% 704 // Sort samples by name 705 samples = studyInstance.samples; 706 sortedSamples = samples.sort( { a, b -> a.name <=> b.name } as Comparator ) 707 %> 708 709 <g:each in="${sortedSamples}" var="sample" status="j"> 710 <tr class="${(i % 2) == 0 ? 'odd' : 'even'}"> 711 <g:if test="${multipleStudies && j==0}"> 712 <td class="studytitle" rowspan="${sortedSamples.size()}"> 713 ${studyInstance.title} 714 </td> 715 </g:if> 716 <g:each in="${sample.giveDomainFields()}" var="field"> 717 <td>${sample.getFieldValue(field.name)}</td> 718 </g:each> 719 720 <g:each in="${showSampleFields}" var="field"> 721 <td> 722 <g:if test="${sample.fieldExists(field.name)}"> 723 ${sample.getFieldValue(field.name)} 724 </g:if> 725 <g:else> 726 N/A 727 </g:else> 728 </td> 729 </g:each> 730 731 </tr> 732 <g:set var="i" value="${i + 1}" /> 733 </g:each> 734 </g:each> 735 597 736 </table> 598 737 </g:else> -
trunk/test/unit/dbnp/studycapturing/EventTests.groovy
r496 r536 12 12 } 13 13 14 void testSomething() { 14 void testBelongsToGroup() { 15 def events = []; 16 10.times { 17 events[ it ] = new Event( 18 id: it, 19 startTime: 3600, 20 endTime: 3800 21 ) 22 println( 'Created event ' + it ); 23 } 24 def evGroup1 = new EventGroup( 25 name: 'group1', 26 events: events[0..4] 27 ) 28 def evGroup2 = new EventGroup( 29 name: 'group2', 30 events: events[3..6] 31 ) 32 33 Set<EventGroup> set1 = new HashSet<EventGroup>(); 34 Set<EventGroup> set2 = new HashSet<EventGroup>(); 35 Set<EventGroup> setBoth = new HashSet<EventGroup>(); 36 Set<EventGroup> setEmpty = new HashSet<EventGroup>(); 37 set1.add( evGroup1 ); 38 set2.add( evGroup2 ); 39 setBoth.add( evGroup1 ); 40 setBoth.add( evGroup2 ); 41 42 assert events[0].belongsToGroup( set1 ); 43 assert events[3].belongsToGroup( set1 ); 44 assert !events[6].belongsToGroup( set1 ); 45 46 assert events[3].belongsToGroup( set2 ); 47 assert events[6].belongsToGroup( set2 ); 48 49 assert !events[0].belongsToGroup( setEmpty ); 50 assert !events[8].belongsToGroup( setEmpty ); 51 52 assert events[0].belongsToGroup( setBoth ); 53 assert events[3].belongsToGroup( setBoth ); 54 assert events[6].belongsToGroup( setBoth ); 55 56 assert !events[7].belongsToGroup( setBoth ); 15 57 16 58 } -
trunk/test/unit/dbnp/studycapturing/StudyTests.groovy
r496 r536 2 2 3 3 import grails.test.* 4 4 import groovy.util.GroovyTestCase 5 5 class StudyTests extends GrailsUnitTestCase { 6 6 protected void setUp() { … … 12 12 } 13 13 14 void testSomething() { 14 protected void assertCollectionEquals( Collection set1, Collection set2 ) { 15 set1.each { 16 assert it in set2; 17 } 18 set2.each { 19 assert it in set1; 20 } 15 21 16 22 } 23 24 void testGetOrphanEvents() { 25 def events = []; 26 10.times { 27 events[ it ] = new Event( 28 id: it, 29 startTime: 3600, 30 endTime: 3800 31 ) 32 println( 'Created event ' + it ); 33 } 34 def evGroup1 = new EventGroup( 35 name: 'group1', 36 events: events[0..4] 37 ) 38 def evGroup2 = new EventGroup( 39 name: 'group2', 40 events: events[3..6] 41 ) 42 43 // No events should give no orphan events 44 def study1 = new Study( title: 'Studytitle 1', events: [], eventGroups: [] ); 45 assert study1.getOrphanEvents().size() == 0; 46 47 // Not even with a group 48 study1.eventGroups = [ evGroup1 ]; 49 assert study1.getOrphanEvents().size() == 0; 50 51 // Events 0..4 are part of evGroup1 52 study1.events = events[0..8]; 53 println( study1.getOrphanEvents().id ) 54 println( events[ 5..8].id ) 55 56 assertCollectionEquals( study1.getOrphanEvents(), events[ 5..8 ] ); 57 58 // Remove the evGroup 59 study1.eventGroups = []; 60 assertCollectionEquals( study1.getOrphanEvents(), events[ 0..8 ] ); 61 62 // Add multiple groups 63 study1.eventGroups = [ evGroup1, evGroup2 ]; 64 assertCollectionEquals( study1.getOrphanEvents(), events[ 7..8 ] ); 65 66 // Remove events again 67 study1.events = []; 68 assert study1.getOrphanEvents().size() == 0; 69 } 17 70 } -
trunk/web-app/css/studies.css
r522 r536 84 84 85 85 .eventtitles .studytitle { font-weight: bold; background-color: transparent; } 86 .eventtitles .no_group { color: #990000; } 86 87
Note: See TracChangeset
for help on using the changeset viewer.