Changeset 238 for trunk/grails-app


Ignore:
Timestamp:
Mar 5, 2010, 3:21:52 PM (14 years ago)
Author:
duh
Message:

Refectored version of the wizard

  • initial template page has been removed, now is a generic 'start' page where one (in the future) may create a new study, or load and modify an already stored study
  • study page incorporates study template select element, but does not yet incorporate the study template fields
  • subjects page now allows creation of subjects based on a template. This change also implied the study page altogether had to change into a seperate table entity. Now the the page lists as many tables as unique templates have been selected. These tables contain all subjects that were added using that particular template. NOTE: data is not stored yet, due to the fact that templateEntity does not work properly yey (key/value pairs need to be set correctly when calling the setTemplate method)
  • the JavaScript? now handles multiple tables in a page as well, and automatically initializes any underlying slider div if that is required
Location:
trunk/grails-app
Files:
1 added
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/grails-app/controllers/dbnp/studycapturing/WizardController.groovy

    r217 r238  
    4747                        flow.page = 0
    4848                        flow.pages = [
    49                                 [title: 'Templates'],                   // templates
     49                                //[title: 'Templates'],                 // templates
     50                                [title: 'Start'],                               // load or create a study
    5051                                [title: 'Study'],                               // study
    5152                                [title: 'Subjects'],                    // subjects
     
    6768                                flow.page = 1
    6869                        }
    69                         on("next").to "templates"
     70                        on("next").to "start"
    7071                }
    7172
     
    104105                }
    105106
     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
    106118                // render and handle the study page
     119                // TODO: make sure both template as well as logic will
     120                //       handle Study templates as well!!!
    107121                study {
    108122                        render(view: "_study")
     
    118132                                        error()
    119133                                }
    120                         }.to "templates"
     134                        }.to "start"
    121135                        on("next") {
    122136                                flash.errors = new LinkedHashMap()
     
    138152                                if (!flow.subjects) {
    139153                                        flow.subjects = []
     154                                        flow.subjectTemplates = new LinkedHashMap()
    140155                                }
    141156                        }
     
    143158                                // fetch species by name (as posted by the form)
    144159                                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                                }
    145171
    146172                                // add x subject of species y
    147173                                (params.addNumber as int).times {
    148174                                        def increment = flow.subjects.size()
    149                                         flow.subjects[increment] = new Subject(
     175                                        def subject = new Subject(
    150176                                                name: 'Subject ' + (increment + 1),
    151177                                                species: speciesTerm,
    152                                                 template: flow.study.template
     178                                                template: subjectTemplate
    153179                                        )
     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
    154187                                }
    155188                        }.to "subjects"
    156189                        on("next") {
     190                                println flow.subjectTemplates
     191                                println flow.subjects
    157192                                flash.errors = new LinkedHashMap()
    158193
     
    193228                        on("add") {
    194229                                // fetch classification by name (as posted by the form)
    195                                 params.classification = Term.findByName(params.classification)
     230                                //params.classification = Term.findByName(params.classification)
    196231
    197232                                // transform checkbox form value to boolean
     
    427462
    428463        /**
    429          * re-usable code for handling event grouping in a web flow
    430          * @param Map LocalAttributeMap (the flow scope)
    431          * @param Map localAttributeMap (the flash scope)
    432          * @param Map GrailsParameterMap (the flow parameters = form data)
    433          * @returns boolean
    434          */
    435         def handleEventGrouping(flow, flash, params) {
    436                 // walk through eventGroups
    437                 def g = 0
    438                 flow.eventGroups.each() {
    439                         def e = 0
    440                         def eventGroup = it
    441 
    442                         // reset events
    443                         eventGroup.events = new HashSet()
    444 
    445                         // walk through events
    446                         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         /**
    457464         * re-usable code for handling study form data in a web flow
    458465         * @param Map LocalAttributeMap (the flow scope)
     
    511518                        it.name = params.get('eventDescription_' + id + '_name')
    512519                        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'))
    514521                        it.isSamplingEvent = (params.containsKey('eventDescription_' + id + '_isSamplingEvent'))
    515522
     
    523530                }
    524531
    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                }
    526561        }
    527562
     
    538573                def id = 0;
    539574
    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'] + '_')
    595597                                        }
    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                        }
    612617                }
    613618
  • trunk/grails-app/domain/dbnp/studycapturing/Template.groovy

    r236 r238  
    1212 */
    1313class Template implements Serializable {
    14 
    1514        String name
    1615        Class entity
     
    2120        static constraints = {
    2221                name(unique:['entity'])
    23 
    2422        }
    2523
     
    6462                def results = []
    6563
    66                 // this should not work in static context, however it does so I'll keep
     64                // 'this' should not work in static context, however it does so I'll keep
    6765                // this in for now :)
    6866                this.findAll().each() {
  • trunk/grails-app/domain/dbnp/studycapturing/TemplateEntity.groovy

    r236 r238  
    44import org.codehaus.groovy.runtime.NullObject
    55
    6 class TemplateEntity {
     6/**
     7 * TemplateEntity Domain Class
     8 *
     9 * Revision information:
     10 * $Rev$
     11 * $Author$
     12 * $Date$
     13 */
     14class TemplateEntity implements Serializable {
    715
    816        Template template
     
    2937
    3038        static constraints = {
    31                 template(nullable: true)
     39                template(nullable: true, blank: true)
    3240
    3341        }
     
    8391                }
    8492                else {
    85                         if (templateStringFields.containsKey(fieldName) && value.class == String) {
     93                        if (templateStringFields && templateStringFields.containsKey(fieldName) && value.class == String) {
    8694                                this.templateStringFields[fieldName] = value
    8795                        }
    88                         if (templateStringListFields.containsKey(fieldName) && value.class == TemplateFieldListItem) {
     96                        if (templateStringFields && templateStringListFields.containsKey(fieldName) && value.class == TemplateFieldListItem) {
    8997                                // TODO: check if item really belongs to the list under fieldName
    9098                                this.templateStringListFields[fieldName] = value
     
    93101                                this.templateTextFields[fieldName] = value
    94102                        }
    95                         else if (templateIntegerFields.containsKey(fieldName) && value.class == Integer) {
     103                        else if (templateIntegerFields && templateIntegerFields.containsKey(fieldName) && value.class == Integer) {
    96104                                this.templateIntegerFields[fieldName] = value
    97105                        }
    98                         else if (templateFloatFields.containsKey(fieldName) && value.class == Float) {
     106                        else if (templateFloatFields && templateFloatFields.containsKey(fieldName) && value.class == Float) {
    99107                                this.templateFloatFields[fieldName] = value
    100108                        }
    101                         else if (templateDoubleFields.containsKey(fieldName) && value.class == Double) {
     109                        else if (templateDoubleFields && templateDoubleFields.containsKey(fieldName) && value.class == Double) {
    102110                                this.templateDoubleFields[fieldName] = value
    103111                        }
    104                         else if (templateDateFields.containsKey(fieldName) && value.class == Date) {
     112                        else if (templateDateFields && templateDateFields.containsKey(fieldName) && value.class == Date) {
    105113                                this.templateDateFields[fieldName] = value
    106114                        }
    107                         else if (templateTermFields.containsKey(fieldName) && value.class == Term) {
     115                        else if (templateTermFields && templateTermFields.containsKey(fieldName) && value.class == Term) {
    108116                                this.templateTermFields[fieldName] = value
    109117                        }
     
    129137                // TODO: initialize all template fields with the necessary keys and null values
    130138
    131                 println "Setting template " + newTemplate
     139                //println "Setting template " + newTemplate
    132140                if (template != null) {
    133141
  • trunk/grails-app/domain/dbnp/studycapturing/TemplateFieldListItem.groovy

    r228 r238  
    11package dbnp.studycapturing
    22
    3 class TemplateFieldListItem {
    4 
     3/**
     4 * TemplateFieldListItem Domain Class
     5 *
     6 * Revision information:
     7 * $Rev$
     8 * $Author$
     9 * $Date$
     10 */
     11class TemplateFieldListItem implements Serializable {
    512        String name
    613
    7         static constraints = {
    8         }
     14        static constraints = {
     15        }
    916
    1017        String toString() {
  • trunk/grails-app/domain/dbnp/studycapturing/TemplateFieldType.groovy

    r236 r238  
    88 * $Date$
    99 */
    10 public enum TemplateFieldType {
     10public enum TemplateFieldType implements Serializable  {
    1111        STRING('String'),
    1212        TEXT('Long string'),
  • trunk/grails-app/taglib/dbnp/studycapturing/WizardTagLib.groovy

    r216 r238  
    200200                def addExample2Element  = attrs.remove('addExample2Element')
    201201
     202                // execute inputElement call
     203                def renderedElement = "$inputElement"(attrs)
     204
     205                // if false, then we skip this element
     206                if (!renderedElement) return false
     207
    202208                // render a form element
    203209                out << '<div class="element">'
     
    206212                out << ' </div>'
    207213                out << ' <div class="input">'
    208                 out << "$inputElement"(attrs)
     214                out << renderedElement
    209215                if(help()) {
    210216                        out << '        <div class="helpIcon"></div>'
     
    414420         */
    415421        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()
    418426
    419427                // got a name?
     
    421429                        attrs.name = 'template'
    422430                }
    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                }
    425440        }
    426441
     
    475490
    476491                // output table headers for template fields
    477                 template.subjectFields.each() {
     492                template.fields.each() {
    478493                        out << '<div class="' + attrs.get('class') + '">' + it + '</div>'
    479494                }
     
    494509
    495510                // output columns for these subjectFields
    496                 template.subjectFields.each() {
     511                template.fields.each() {
    497512                        // output div
    498513                        out << '<div class="' + attrs.get('class') + '">'
     
    506521                                                        from: it.listEntries,
    507522                                                        value: (stringFields) ? stringFields.get(it.name) : ''
    508                                                 )
     523                                                )                                               
    509524                                        } else {
    510525                                                out << '<span class="warning">no values!!</span>'
     
    528543                                        // unsupported field type
    529544                                        out << '<span class="warning">!'+it.type+'</span>'
     545                                        //out << subject.getFieldValue(it.name)
    530546                                        break;
    531547                        }
     548
    532549                        out << '</div>'
    533550                }
  • trunk/grails-app/views/wizard/pages/_eventDescriptions.gsp

    r217 r238  
    3030        </span>
    3131
    32         <wizard:termElement name="classification" description="Classification" error="classification" value="${values?.classification}">
    33                 The ontology reference for this particular type of event
    34         </wizard:termElement>
    3532        <wizard:textFieldElement name="name" description="Name" error="name" value="${values?.name}">
    3633                The name of the event description you are creating
     
    5047                        <div class="column">name</div>
    5148                        <div class="column">description</div>
    52                         <div class="column">classification</div>
    5349                        <div class="column">sampling event</div>
    5450                        <div class="column">protocol</div>
     
    6258                        <div class="column"><g:textField name="eventDescription_${i}_name" value="${eventDescription.name}" size="12" maxlength="12" /></div>
    6359                        <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>
    6560                        <div class="column"><g:checkBox name="eventDescription_${i}_isSamplingEvent" value="${eventDescription.isSamplingEvent}" /></div>
    6661                        <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  
    2121        </span>
    2222       
     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>
    2326        <wizard:textFieldElement name="title" description="Title" error="title" value="${study?.title}">
    2427                The title of the study you are creating
     
    3942                The start date of the study     
    4043        </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       
    4151</wizard:pageContent>
  • trunk/grails-app/views/wizard/pages/_subjects.gsp

    r213 r238  
    2525        subjects of species
    2626        <wizard:speciesSelect name="addSpecies" />
     27        using the
     28        <wizard:templateSelect name="template" description="Template" value="${study?.template}" entity="${dbnp.studycapturing.Subject}" />
     29        template
     30
    2731<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>
    3451                </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>
    4354                </div>
    4455        </g:each>
    45         </div>
    46         <div class="sliderContainer">
    47                 <div class="slider"/>
    48         </div>
    4956</g:if>
     57
    5058</wizard:pageContent>
  • trunk/grails-app/views/wizard/pages/_templates.gsp

    r213 r238  
    2121        </span>
    2222
    23         <wizard:templateElement name="template" description="Template" value="${study?.template}">
    24                 The meta data template to use for this study
     23        <wizard:templateElement name="template" description="Template" value="${study?.template}" entity="${dbnp.studycapturing.Subject}">
     24                The subject template to use for this study
    2525        </wizard:templateElement>
    2626</wizard:pageContent>
Note: See TracChangeset for help on using the changeset viewer.