Changeset 238
- Timestamp:
- Mar 5, 2010, 3:21:52 PM (14 years ago)
- Location:
- trunk
- Files:
-
- 1 added
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/grails-app/controllers/dbnp/studycapturing/WizardController.groovy
r217 r238 47 47 flow.page = 0 48 48 flow.pages = [ 49 [title: 'Templates'], // templates 49 //[title: 'Templates'], // templates 50 [title: 'Start'], // load or create a study 50 51 [title: 'Study'], // study 51 52 [title: 'Subjects'], // subjects … … 67 68 flow.page = 1 68 69 } 69 on("next").to " templates"70 on("next").to "start" 70 71 } 71 72 … … 104 105 } 105 106 107 // create or modify a study 108 start { 109 render(view: "_start") 110 onRender { 111 flow.page = 1 112 } 113 on("next") { 114 115 }.to "study" 116 } 117 106 118 // render and handle the study page 119 // TODO: make sure both template as well as logic will 120 // handle Study templates as well!!! 107 121 study { 108 122 render(view: "_study") … … 118 132 error() 119 133 } 120 }.to " templates"134 }.to "start" 121 135 on("next") { 122 136 flash.errors = new LinkedHashMap() … … 138 152 if (!flow.subjects) { 139 153 flow.subjects = [] 154 flow.subjectTemplates = new LinkedHashMap() 140 155 } 141 156 } … … 143 158 // fetch species by name (as posted by the form) 144 159 def speciesTerm = Term.findByName(params.addSpecies) 160 def subjectTemplateName = params.get('template') 161 def subjectTemplate = Template.findByName(subjectTemplateName) 162 163 // add this subject template to the subject template array 164 if (!flow.subjectTemplates[ subjectTemplateName ]) { 165 flow.subjectTemplates[ subjectTemplateName ] = [ 166 name: subjectTemplateName, 167 template: subjectTemplate, 168 subjects: [] 169 ] 170 } 145 171 146 172 // add x subject of species y 147 173 (params.addNumber as int).times { 148 174 def increment = flow.subjects.size() 149 flow.subjects[increment]= new Subject(175 def subject = new Subject( 150 176 name: 'Subject ' + (increment + 1), 151 177 species: speciesTerm, 152 template: flow.study.template178 template: subjectTemplate 153 179 ) 180 181 // instantiate a new Subject 182 flow.subjects[ increment ] = subject 183 184 // and remember the subject id with the template 185 def subjectsSize = flow.subjectTemplates[ subjectTemplateName ]['subjects'].size() 186 flow.subjectTemplates[ subjectTemplateName ]['subjects'][ subjectsSize ] = increment 154 187 } 155 188 }.to "subjects" 156 189 on("next") { 190 println flow.subjectTemplates 191 println flow.subjects 157 192 flash.errors = new LinkedHashMap() 158 193 … … 193 228 on("add") { 194 229 // fetch classification by name (as posted by the form) 195 params.classification = Term.findByName(params.classification)230 //params.classification = Term.findByName(params.classification) 196 231 197 232 // transform checkbox form value to boolean … … 427 462 428 463 /** 429 * re-usable code for handling event grouping in a web flow430 * @param Map LocalAttributeMap (the flow scope)431 * @param Map localAttributeMap (the flash scope)432 * @param Map GrailsParameterMap (the flow parameters = form data)433 * @returns boolean434 */435 def handleEventGrouping(flow, flash, params) {436 // walk through eventGroups437 def g = 0438 flow.eventGroups.each() {439 def e = 0440 def eventGroup = it441 442 // reset events443 eventGroup.events = new HashSet()444 445 // walk through events446 flow.events.each() {447 if (params.get('event_' + e + '_group_' + g) == 'on') {448 eventGroup.addToEvents(it)449 }450 e++451 }452 g++453 }454 }455 456 /**457 464 * re-usable code for handling study form data in a web flow 458 465 * @param Map LocalAttributeMap (the flow scope) … … 511 518 it.name = params.get('eventDescription_' + id + '_name') 512 519 it.description = params.get('eventDescription_' + id + '_description') 513 it.classification = Term.findByName(params.get('eventDescription_' + id + '_classification'))520 //it.classification = Term.findByName(params.get('eventDescription_' + id + '_classification')) 514 521 it.isSamplingEvent = (params.containsKey('eventDescription_' + id + '_isSamplingEvent')) 515 522 … … 523 530 } 524 531 525 return !(errors) 532 return !errors 533 } 534 535 /** 536 * re-usable code for handling event grouping in a web flow 537 * @param Map LocalAttributeMap (the flow scope) 538 * @param Map localAttributeMap (the flash scope) 539 * @param Map GrailsParameterMap (the flow parameters = form data) 540 * @returns boolean 541 */ 542 def handleEventGrouping(flow, flash, params) { 543 // walk through eventGroups 544 def g = 0 545 flow.eventGroups.each() { 546 def e = 0 547 def eventGroup = it 548 549 // reset events 550 eventGroup.events = new HashSet() 551 552 // walk through events 553 flow.events.each() { 554 if (params.get('event_' + e + '_group_' + g) == 'on') { 555 eventGroup.addToEvents(it) 556 } 557 e++ 558 } 559 g++ 560 } 526 561 } 527 562 … … 538 573 def id = 0; 539 574 540 // iterate through subjects 541 flow.subjects.each() { 542 // store subject properties 543 def name = params.get('subject_' + id + '_name') 544 it.name = params.get('subject_' + id + '_name') 545 it.species = Term.findByName(params.get('subject_' + id + '_species')) 546 547 // remember name and check for duplicates 548 if (!names[it.name]) { 549 names[it.name] = [count: 1, first: 'subject_' + id + '_name', firstId: id] 550 } else { 551 // duplicate name found, set error flag 552 names[it.name]['count']++ 553 554 // second occurence? 555 if (names[it.name]['count'] == 2) { 556 // yeah, also mention the first 557 // occurrence in the error message 558 this.appendErrorMap(name: 'The subject name needs to be unique!', flash.errors, 'subject_' + names[it.name]['firstId'] + '_') 559 } 560 561 // add to error map 562 this.appendErrorMap([name: 'The subject name needs to be unique!'], flash.errors, 'subject_' + id + '_') 563 errors = true 564 } 565 566 // clear lists 567 def stringList = new LinkedHashMap(); 568 def intList = new LinkedHashMap(); 569 def floatList = new LinkedHashMap(); 570 def termList = new LinkedHashMap(); 571 572 // get all template fields 573 flow.study.template.subjectFields.each() { 574 // valid type? 575 if (!it.type) throw new NoSuchFieldException("Field name ${fieldName} not recognized") 576 577 // get value 578 def value = params.get('subject_' + id + '_' + it.name); 579 if (value) { 580 // add to template parameters 581 switch (it.type) { 582 case 'STRINGLIST': 583 stringList[it.name] = value 584 break; 585 case 'INTEGER': 586 intList[it.name] = value 587 break; 588 case 'FLOAT': 589 floatList[it.name] = value 590 break; 591 default: 592 // unsupported type? 593 throw new NoSuchFieldException("Field type ${it.type} not recognized") 594 break; 575 // iterate through subject templates 576 flow.subjectTemplates.each() { 577 def subjectTemplate = it.getValue().template 578 def templateFields = subjectTemplate.fields 579 580 // iterate through subjects 581 it.getValue().subjects.each() { subjectId -> 582 flow.subjects[ subjectId ].name = params.get('subject_' + subjectId + '_name') 583 flow.subjects[ subjectId ].species = Term.findByName(params.get('subject_' + subjectId + '_species')) 584 585 // remember name and check for duplicates 586 if (!names[ flow.subjects[ subjectId ].name ]) { 587 names[ flow.subjects[ subjectId ].name ] = [count: 1, first: 'subject_' + subjectId + '_name', firstId: subjectId] 588 } else { 589 // duplicate name found, set error flag 590 names[ flow.subjects[ subjectId ].name ]['count']++ 591 592 // second occurence? 593 if (names[ flow.subjects[ subjectId ].name ]['count'] == 2) { 594 // yeah, also mention the first 595 // occurrence in the error message 596 this.appendErrorMap(name: 'The subject name needs to be unique!', flash.errors, 'subject_' + names[ flow.subjects[ subjectId ].name ]['firstId'] + '_') 595 597 } 596 } 597 } 598 599 // set field data 600 it.templateStringFields = stringList 601 it.templateIntegerFields = intList 602 it.templateFloatFields = floatList 603 it.templateTermFields = termList 604 605 // validate subject 606 if (!it.validate()) { 607 errors = true 608 this.appendErrors(it, flash.errors) 609 } 610 611 id++; 598 599 // add to error map 600 this.appendErrorMap([name: 'The subject name needs to be unique!'], flash.errors, 'subject_' + subjectId + '_') 601 errors = true 602 } 603 604 // iterate through template fields 605 templateFields.each() { subjectField -> 606 def value = params.get('subject_' + subjectId + '_' + subjectField.name) 607 608 // TODO: UNCOMMENT THIS if (value) flow.subjects[ subjectId ].setFieldValue(subjectField.name, value) 609 } 610 611 // validate subject 612 if (!flow.subjects[ subjectId ].validate()) { 613 errors = true 614 this.appendErrors(flow.subjects[ subjectId ], flash.errors) 615 } 616 } 612 617 } 613 618 -
trunk/grails-app/domain/dbnp/studycapturing/Template.groovy
r236 r238 12 12 */ 13 13 class Template implements Serializable { 14 15 14 String name 16 15 Class entity … … 21 20 static constraints = { 22 21 name(unique:['entity']) 23 24 22 } 25 23 … … 64 62 def results = [] 65 63 66 // thisshould not work in static context, however it does so I'll keep64 // 'this' should not work in static context, however it does so I'll keep 67 65 // this in for now :) 68 66 this.findAll().each() { -
trunk/grails-app/domain/dbnp/studycapturing/TemplateEntity.groovy
r236 r238 4 4 import org.codehaus.groovy.runtime.NullObject 5 5 6 class TemplateEntity { 6 /** 7 * TemplateEntity Domain Class 8 * 9 * Revision information: 10 * $Rev$ 11 * $Author$ 12 * $Date$ 13 */ 14 class TemplateEntity implements Serializable { 7 15 8 16 Template template … … 29 37 30 38 static constraints = { 31 template(nullable: true )39 template(nullable: true, blank: true) 32 40 33 41 } … … 83 91 } 84 92 else { 85 if (templateStringFields .containsKey(fieldName) && value.class == String) {93 if (templateStringFields && templateStringFields.containsKey(fieldName) && value.class == String) { 86 94 this.templateStringFields[fieldName] = value 87 95 } 88 if (templateString ListFields.containsKey(fieldName) && value.class == TemplateFieldListItem) {96 if (templateStringFields && templateStringListFields.containsKey(fieldName) && value.class == TemplateFieldListItem) { 89 97 // TODO: check if item really belongs to the list under fieldName 90 98 this.templateStringListFields[fieldName] = value … … 93 101 this.templateTextFields[fieldName] = value 94 102 } 95 else if (templateIntegerFields .containsKey(fieldName) && value.class == Integer) {103 else if (templateIntegerFields && templateIntegerFields.containsKey(fieldName) && value.class == Integer) { 96 104 this.templateIntegerFields[fieldName] = value 97 105 } 98 else if (templateFloatFields .containsKey(fieldName) && value.class == Float) {106 else if (templateFloatFields && templateFloatFields.containsKey(fieldName) && value.class == Float) { 99 107 this.templateFloatFields[fieldName] = value 100 108 } 101 else if (templateDoubleFields .containsKey(fieldName) && value.class == Double) {109 else if (templateDoubleFields && templateDoubleFields.containsKey(fieldName) && value.class == Double) { 102 110 this.templateDoubleFields[fieldName] = value 103 111 } 104 else if (templateDateFields .containsKey(fieldName) && value.class == Date) {112 else if (templateDateFields && templateDateFields.containsKey(fieldName) && value.class == Date) { 105 113 this.templateDateFields[fieldName] = value 106 114 } 107 else if (templateTermFields .containsKey(fieldName) && value.class == Term) {115 else if (templateTermFields && templateTermFields.containsKey(fieldName) && value.class == Term) { 108 116 this.templateTermFields[fieldName] = value 109 117 } … … 129 137 // TODO: initialize all template fields with the necessary keys and null values 130 138 131 println "Setting template " + newTemplate139 //println "Setting template " + newTemplate 132 140 if (template != null) { 133 141 -
trunk/grails-app/domain/dbnp/studycapturing/TemplateFieldListItem.groovy
r228 r238 1 1 package dbnp.studycapturing 2 2 3 class TemplateFieldListItem { 4 3 /** 4 * TemplateFieldListItem Domain Class 5 * 6 * Revision information: 7 * $Rev$ 8 * $Author$ 9 * $Date$ 10 */ 11 class TemplateFieldListItem implements Serializable { 5 12 String name 6 13 7 8 14 static constraints = { 15 } 9 16 10 17 String toString() { -
trunk/grails-app/domain/dbnp/studycapturing/TemplateFieldType.groovy
r236 r238 8 8 * $Date$ 9 9 */ 10 public enum TemplateFieldType {10 public enum TemplateFieldType implements Serializable { 11 11 STRING('String'), 12 12 TEXT('Long string'), -
trunk/grails-app/taglib/dbnp/studycapturing/WizardTagLib.groovy
r216 r238 200 200 def addExample2Element = attrs.remove('addExample2Element') 201 201 202 // execute inputElement call 203 def renderedElement = "$inputElement"(attrs) 204 205 // if false, then we skip this element 206 if (!renderedElement) return false 207 202 208 // render a form element 203 209 out << '<div class="element">' … … 206 212 out << ' </div>' 207 213 out << ' <div class="input">' 208 out << "$inputElement"(attrs)214 out << renderedElement 209 215 if(help()) { 210 216 out << ' <div class="helpIcon"></div>' … … 414 420 */ 415 421 def templateSelect = { attrs -> 416 // fetch all templates 417 attrs.from = Template.findAll() // for now, all templates 422 def entity = attrs.remove('entity') 423 424 // fetch templates 425 attrs.from = (entity) ? Template.findAllByEntity(entity) : Template.findAll() 418 426 419 427 // got a name? … … 421 429 attrs.name = 'template' 422 430 } 423 424 out << select(attrs) 431 432 // got result? 433 if (attrs.from.size() >0) { 434 out << select(attrs) 435 } else { 436 // no, return false to make sure this element 437 // is not rendered in the template 438 return false 439 } 425 440 } 426 441 … … 475 490 476 491 // output table headers for template fields 477 template. subjectFields.each() {492 template.fields.each() { 478 493 out << '<div class="' + attrs.get('class') + '">' + it + '</div>' 479 494 } … … 494 509 495 510 // output columns for these subjectFields 496 template. subjectFields.each() {511 template.fields.each() { 497 512 // output div 498 513 out << '<div class="' + attrs.get('class') + '">' … … 506 521 from: it.listEntries, 507 522 value: (stringFields) ? stringFields.get(it.name) : '' 508 ) 523 ) 509 524 } else { 510 525 out << '<span class="warning">no values!!</span>' … … 528 543 // unsupported field type 529 544 out << '<span class="warning">!'+it.type+'</span>' 545 //out << subject.getFieldValue(it.name) 530 546 break; 531 547 } 548 532 549 out << '</div>' 533 550 } -
trunk/grails-app/views/wizard/pages/_eventDescriptions.gsp
r217 r238 30 30 </span> 31 31 32 <wizard:termElement name="classification" description="Classification" error="classification" value="${values?.classification}">33 The ontology reference for this particular type of event34 </wizard:termElement>35 32 <wizard:textFieldElement name="name" description="Name" error="name" value="${values?.name}"> 36 33 The name of the event description you are creating … … 50 47 <div class="column">name</div> 51 48 <div class="column">description</div> 52 <div class="column">classification</div>53 49 <div class="column">sampling event</div> 54 50 <div class="column">protocol</div> … … 62 58 <div class="column"><g:textField name="eventDescription_${i}_name" value="${eventDescription.name}" size="12" maxlength="12" /></div> 63 59 <div class="column"><g:textField name="eventDescription_${i}_description" value="${eventDescription.description}" size="12" maxlength="12" /></div> 64 <div class="column"><wizard:termSelect name="eventDescription_${i}_classification" value="${eventDescription.classification}" /></div>65 60 <div class="column"><g:checkBox name="eventDescription_${i}_isSamplingEvent" value="${eventDescription.isSamplingEvent}" /></div> 66 61 <div class="column"><g:if test="${eventDescription.protocol}">${eventDescription.protocol}</g:if><g:else>-</g:else></div> -
trunk/grails-app/views/wizard/pages/_study.gsp
r213 r238 21 21 </span> 22 22 23 <wizard:templateElement name="template" description="Template" value="${study?.template}" entity="${dbnp.studycapturing.Study}"> 24 The template to use for this study 25 </wizard:templateElement> 23 26 <wizard:textFieldElement name="title" description="Title" error="title" value="${study?.title}"> 24 27 The title of the study you are creating … … 39 42 The start date of the study 40 43 </wizard:dateElement> 44 45 <span class="info"> 46 <span class="title">TODO</span> 47 This page should also contain the template fields of the study template selected above (if available). This is 48 scheduled for implementation in a later version 49 </span> 50 41 51 </wizard:pageContent> -
trunk/grails-app/views/wizard/pages/_subjects.gsp
r213 r238 25 25 subjects of species 26 26 <wizard:speciesSelect name="addSpecies" /> 27 using the 28 <wizard:templateSelect name="template" description="Template" value="${study?.template}" entity="${dbnp.studycapturing.Subject}" /> 29 template 30 27 31 <g:if test="${subjects}"> 28 <div class="table"> 29 <div class="header"> 30 <div class="firstColumn">#</div> 31 <div class="column">name</div> 32 <div class="column">species</div> 33 <wizard:templateColumnHeaders template="${study.template}" class="column" /> 32 <g:each var="subjectTemplate" in="${subjectTemplates}"> 33 <h1>${subjectTemplate.getValue().name} template</h1> 34 <div class="table"> 35 <div class="header"> 36 <div class="firstColumn">#</div> 37 <div class="column">name</div> 38 <div class="column">species</div> 39 <wizard:templateColumnHeaders template="${subjectTemplate.getValue().template}" class="column" /> 40 </div> 41 <g:each var="subjectId" in="${subjectTemplate.getValue().subjects}"> 42 <div class="row"> 43 <div class="firstColumn">${subjectId}</div> 44 <div class="column"><g:textField name="subject_${subjectId}_name" value="${subjects[ subjectId ].name}" size="12" maxlength="12" /></div> 45 <div class="column"> 46 <wizard:speciesSelect value="${subjects[ subjectId ].species}" name="subject_${subjectId}_species" /> 47 </div> 48 <wizard:templateColumns id="${subjectId}" template="${subjects[ subjectId ].template}" name="subject_${subjectId}" class="column" subject="${subjects[ subjectId ]}" /> 49 </div> 50 </g:each> 34 51 </div> 35 <g:each var="subject" status="i" in="${subjects}"> 36 <div class="row"> 37 <div class="firstColumn">${i}</div> 38 <div class="column"><g:textField name="subject_${i}_name" value="${subject.name}" size="12" maxlength="12" /></div> 39 <div class="column"> 40 <wizard:speciesSelect value="${subject.species}" name="subject_${i}_species" /> 41 </div> 42 <wizard:templateColumns id="${i}" template="${study.template}" name="subject_${i}" class="column" subject="${subject}" /> 52 <div class="sliderContainer"> 53 <div class="slider" ></div> 43 54 </div> 44 55 </g:each> 45 </div>46 <div class="sliderContainer">47 <div class="slider"/>48 </div>49 56 </g:if> 57 50 58 </wizard:pageContent> -
trunk/grails-app/views/wizard/pages/_templates.gsp
r213 r238 21 21 </span> 22 22 23 <wizard:templateElement name="template" description="Template" value="${study?.template}" >24 The meta datatemplate to use for this study23 <wizard:templateElement name="template" description="Template" value="${study?.template}" entity="${dbnp.studycapturing.Subject}"> 24 The subject template to use for this study 25 25 </wizard:templateElement> 26 26 </wizard:pageContent> -
trunk/web-app/css/wizard.css
r217 r238 37 37 .wizard .sliderContainer { 38 38 display: block; 39 padding-top: 10px;39 margin-top: 10px; 40 40 width: 150px; 41 41 } -
trunk/web-app/js/wizard.js
r213 r238 39 39 // table handlers 40 40 attachTableEvents(); 41 resizeWizardTable(); 42 attachTableSlider(); 43 new TableEditor().init('div.table','div.row','div.column'); 41 handleWizardTable(); 42 new TableEditor().init('div.table', 'div.row', 'div.column'); 44 43 45 44 // accordeon(s) … … 158 157 // the header and the rows is automatically scaled to 159 158 // the cummalative width of the columns in the header 160 function resizeWizardTable() { 161 var wizardTable = $("div#wizard").find('div.table'); 162 163 if (wizardTable) { 159 function handleWizardTable() { 160 var that = this; 161 var wizardTables = $("div#wizard").find('div.table'); 162 163 wizardTables.each(function() { 164 var wizardTable = $(this); 165 var sliderContainer = (wizardTable.next().attr('class') == 'sliderContainer') ? wizardTable.next() : null; 164 166 var header = wizardTable.find('div.header') 167 var width = 20; 168 165 169 // calculate total width of elements in header 166 var width = 20;167 170 header.children().each(function() { 168 171 // calculate width per column … … 183 186 $(this).css({ width: width + 'px' }); 184 187 }); 185 } 186 } 187 188 // if we have a table and a slider, make the slider 189 // slide the contents of the table if the content of 190 // the table is wider than the table itself 191 function attachTableSlider() { 192 var slider = $("div#wizard").find('div.slider'); 193 var header = $("div#wizard").find('div.header'); 194 var table = $("div#wizard").find('div.table'); 195 196 if (slider && table && header) { 197 // do we really need a slider? 198 if (header.width() < table.width()) { 199 // no, so hide it 200 slider.css({ 'display': 'none '}); 201 } else { 202 slider.slider({ 203 value : 1, 204 min : 1, 205 max : header.width() - table.width(), 206 step : 1, 207 slide: function(event, ui) { 208 $("div#wizard").find('div.header, div.row').css({ 'margin-left': ( 1 - ui.value ) + 'px' }); 209 } 210 }); 188 189 // got a slider for this table? 190 if (sliderContainer) { 191 // handle slider 192 if (header.width() < wizardTable.width()) { 193 // no, so hide it 194 sliderContainer.css({ 'display': 'none '}); 195 } else { 196 sliderContainer.slider({ 197 value : 1, 198 min : 1, 199 max : header.width() - wizardTable.width(), 200 step : 1, 201 slide: function(event, ui) { 202 wizardTable.find('div.header, div.row').css({ 'margin-left': ( 1 - ui.value ) + 'px' }); 203 } 204 }); 205 } 211 206 } 212 } 213 } 207 }); 208 }
Note: See TracChangeset
for help on using the changeset viewer.