Changeset 1260

Show
Ignore:
Timestamp:
10-12-10 15:12:28 (3 years ago)
Author:
work@…
Message:

- resolves #198, user friendly error messages in wizard

Location:
trunk/grails-app
Files:
4 modified

Legend:

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

    r1227 r1260  
    88import dbnp.authentication.AuthenticationService 
    99import dbnp.authentication.SecUser 
     10import org.codehaus.groovy.grails.plugins.web.taglib.ValidationTagLib 
    1011 
    1112 
     
    3031class WizardController { 
    3132        def authenticationService 
     33        def validationTagLib = new ValidationTagLib()    
    3234 
    3335        /** 
     
    145147                                        } 
    146148                                } else if (flow.jump && flow.jump.action == 'create') { 
     149                                        if (!flow.study) flow.study = new Study() 
    147150                                        toStudyPage() 
    148151                                } else { 
     
    167170                                // clean the flow scope 
    168171                                flow.remove('study') 
     172 
     173                                // create a new study instance 
     174                                if (!flow.study) flow.study = new Study()                                
    169175 
    170176                                // set 'quicksave' variable to false 
     
    469475                                // remove eventGroup 
    470476                                def eventGroupToRemove = flow.study.eventGroups.find { it.getIdentifier() == (params.get('do') as int) } 
    471                                 if (eventGroupToRemove) { 
    472                                         println flow.study.deleteEventGroup( eventGroupToRemove ) 
    473                                 } 
    474477                        }.to "events" 
    475478                        on("previous") { 
     
    664667                                    flow.assay.setFieldValue( 
    665668                                            'externalAssayID', 
    666                                             this.ucwords(flow.study.code).replaceAll("([ ]{1,})", "") + '_' + this.ucwords(template.name).replaceAll("([ ]{1,})", "") 
     669                                            ucwords(flow.study.code).replaceAll("([ ]{1,})", "") + '_' + ucwords(template.name).replaceAll("([ ]{1,})", "") 
    667670                                    ) 
    668671                            } 
     
    673676                                    flow.assay.setFieldValue( 
    674677                                            'externalAssayID', 
    675                                             this.ucwords(flow.study.code).replaceAll("([ ]{1,})", "") + '_' + this.ucwords(template.name).replaceAll("([ ]{1,})", "") 
     678                                            ucwords(flow.study.code).replaceAll("([ ]{1,})", "") + '_' + ucwords(template.name).replaceAll("([ ]{1,})", "") 
    676679                                    ) 
    677680                            } 
     
    708711                        }.to "assays" 
    709712                        on("deleteAssay") { 
    710                                 println params 
    711  
    712713                                // handle form data 
    713714                                assayPage(flow, flash, params) 
     
    908909         */ 
    909910        def loadStudy(flow, flash, params, user) { 
    910                 flash.wizardErrors = new LinkedHashMap() 
     911                flash.wizardErrors      = [:] 
    911912                 
    912913                // load study 
     
    960961         */ 
    961962        def studyPage(flow, flash, params) { 
    962                 // remember the params in the flash scope 
    963                 flash.values = params 
     963                flash.values            = params 
     964                flash.wizardErrors      = [:] 
    964965 
    965966                // instantiate study of it is not yet present 
     
    968969                // did the study template change? 
    969970                if (params.get('template').size() && flow.study.template?.name != params.get('template')) { 
    970                         println ".change study template!" 
    971  
    972                         // yes, was the template already set? 
    973                         if (flow.study.template instanceof Template) { 
    974                                 // yes, first make sure all values are unset? 
    975                                 println "!!! check the database fields if data of a previous template remains in the database or is deleted by GORM!" 
    976                         } 
    977  
    978971                        // set the template 
    979972                        flow.study.template = Template.findByName(params.remove('template')) 
     
    1004997                } 
    1005998 
    1006                 // validate the study 
    1007                 if (flow.study.validate()) { 
    1008                         // instance is okay 
    1009                         return true 
     999                // have we got a template? 
     1000                if (flow.study.template && flow.study.template instanceof Template) { 
     1001                        // validate the study 
     1002                        if (flow.study.validate()) { 
     1003                                // instance is okay 
     1004                                return true 
     1005                        } else { 
     1006                                // validation failed 
     1007                                this.appendErrors(flow.study, flash.wizardErrors) 
     1008                                return false 
     1009                        } 
    10101010                } else { 
    1011                         // validation failed 
    1012                         flash.wizardErrors = [:] 
    1013                         this.appendErrors(flow.study, flash.wizardErrors) 
     1011                        // no, return an error that the template is not set 
     1012                        this.appendErrorMap(['template': g.message(code: 'select.not.selected.or.add', args: ['template'])], flash.wizardErrors) 
    10141013                        return false 
    10151014                } 
     
    10241023         */ 
    10251024        def handlePublications(flow, flash, params) { 
     1025                flash.wizardErrors      = [:] 
     1026 
    10261027                if (!flow.study.publications) flow.study.publications = [] 
    10271028 
     
    10651066         */ 
    10661067        def handleContacts(flow, flash, params) { 
     1068                flash.wizardErrors      = [:] 
     1069 
    10671070                if (!flow.study.persons) flow.study.persons = [] 
    10681071 
     
    11261129         */ 
    11271130        def handleUsers(flow, flash, params, type) { 
     1131                flash.wizardErrors = [:] 
     1132 
    11281133                def users = [] 
    11291134 
     
    11401145 
    11411146                // Users are saved as user_id 
    1142                 def userIDs = params.get( type + '_ids') 
     1147                def userIDs = params.get(type + '_ids') 
    11431148                if (userIDs) { 
    11441149                        // Find the individual IDs and make integers 
     
    11531158                                        def user = SecUser.get(id) 
    11541159                                        if (user) { 
    1155                                             users.add(user) 
     1160                                                users.add(user) 
    11561161                                        } else { 
    11571162                                                log.info('.user with ID ' + id + ' not found in database.') 
     
    11671172                if (type == "readers") { 
    11681173                        if (flow.study.readers) 
    1169                         flow.study.readers.clear() 
     1174                                flow.study.readers.clear() 
    11701175                        users.each { flow.study.addToReaders(it) } 
    11711176                } else if (type == "writers") { 
    11721177                        if (flow.study.writers) 
    1173                         flow.study.writers.clear() 
     1178                                flow.study.writers.clear() 
    11741179 
    11751180                        users.each { flow.study.addToWriters(it) } 
    11761181                } 
    1177         } 
     1182        } 
    11781183 
    11791184        /** 
     
    12861291                        errors = true 
    12871292                        if (number < 1) this.appendErrorMap(['addNumber': 'Enter a positive number of subjects to add'], flash.wizardErrors) 
    1288                         if (!species)   this.appendErrorMap(['species': 'You need to select a species, or add one if it is not yet present'], flash.wizardErrors) 
    1289                         if (!template)  this.appendErrorMap(['template': 'You need to select a template, or add one if it is not yet present'], flash.wizardErrors) 
     1293                        if (!species)   this.appendErrorMap(['species': g.message(code: 'select.not.selected.or.add', args: ['species'])], flash.wizardErrors) 
     1294                        if (!template)  this.appendErrorMap(['template': g.message(code: 'select.not.selected.or.add', args: ['template'])], flash.wizardErrors) 
    12901295                } 
    12911296 
     
    13531358                                                        eventGroup.subjects.each() { subject -> 
    13541359                                                                // instantiate a sample for this subject / event 
    1355                                                                 def samplingEventName = this.ucwords(event.template.name) 
    1356                                                                 def eventGroupName = this.ucwords(eventGroup.name).replaceAll("([ ]{1,})", "") 
    1357                                                                 def sampleName = (this.ucwords(subject.name) + '_' + samplingEventName + '_' + eventGroupName + '_' + new RelTime(event.startTime).toString()).replaceAll("([ ]{1,})", "") 
     1360                                                                def samplingEventName = ucwords(event.template.name) 
     1361                                                                def eventGroupName = ucwords(eventGroup.name).replaceAll("([ ]{1,})", "") 
     1362                                                                def sampleName = (ucwords(subject.name) + '_' + samplingEventName + '_' + eventGroupName + '_' + new RelTime(event.startTime).toString()).replaceAll("([ ]{1,})", "") 
    13581363                                                                def tempSampleIterator = 0 
    13591364                                                                def tempSampleName = sampleName 
     
    14501455                                                // iterate through samplingEvents 
    14511456                                                eventGroup.samplingEvents.each() { samplingEvent -> 
    1452                                                         def samplingEventName = this.ucwords(samplingEvent.template.name) 
    1453                                                         def eventGroupName = this.ucwords(eventGroup.name) 
    1454                                                         def sampleName = (this.ucwords(subject.name) + '_' + samplingEventName + '_' + eventGroupName + '_' + new RelTime(samplingEvent.startTime).toString()).replaceAll("([ ]{1,})", "") 
     1457                                                        def samplingEventName = ucwords(samplingEvent.template.name) 
     1458                                                        def eventGroupName = ucwords(eventGroup.name) 
     1459                                                        def sampleName = (ucwords(subject.name) + '_' + samplingEventName + '_' + eventGroupName + '_' + new RelTime(samplingEvent.startTime).toString()).replaceAll("([ ]{1,})", "") 
    14551460                                                        def tempSampleIterator = 0 
    14561461                                                        def tempSampleName = sampleName 
     
    16091614                        flow.study.assays.each() { assay -> 
    16101615                                if (params.get( 'sample_' + sample.getIdentifier() + '_assay_' + assay.getIdentifier() )) { 
    1611                                         println "add sample "+sample.getIdentifier()+" to assay "+assay.getIdentifier() 
    16121616                                        // add sample to assay 
    16131617                                        assay.addToSamples( sample ) 
     
    16161620                                        assay.removeFromSamples( sample ) 
    16171621                                } 
    1618                                 println assay.samples 
    16191622                        } 
    16201623                } 
     
    16311634         * @return String 
    16321635         */ 
    1633         def ucwords(String text) { 
     1636        public static ucwords(String text) { 
    16341637                def newText = '' 
    16351638 
     
    16701673        def getHumanReadableErrors(object) { 
    16711674                def errors = [:] 
    1672                 object.errors.getAllErrors().each() { 
    1673                         def message = it.toString() 
    1674  
    1675                         //errors[it.getArguments()[0]] = it.getDefaultMessage() 
    1676                         errors[it.getArguments()[0]] = message.substring(0, message.indexOf(';')) 
     1675                object.errors.getAllErrors().each() { error -> 
     1676                        // error.codes.each() { code -> println code } 
     1677 
     1678                        // generally speaking g.message(...) should work, 
     1679                        // however it fails in some steps of the wizard 
     1680                        // (add event, add assay, etc) so g is not always 
     1681                        // availably. Using our own instance of the 
     1682                        // validationTagLib instead so it is always 
     1683                        // available to us 
     1684                        errors[ error.getArguments()[0] ] = validationTagLib.message(error: error) 
    16771685                } 
    16781686 
     
    16871695         */ 
    16881696        def appendErrors(object, map) { 
    1689                 this.appendErrorMap(this.getHumanReadableErrors(object), map) 
     1697                this.appendErrorMap(getHumanReadableErrors(object), map) 
    16901698        } 
    16911699 
    16921700        def appendErrors(object, map, prepend) { 
    1693                 this.appendErrorMap(this.getHumanReadableErrors(object), map, prepend) 
     1701                this.appendErrorMap(getHumanReadableErrors(object), map, prepend) 
    16941702        } 
    16951703 
  • trunk/grails-app/i18n/messages_nl.properties

    r1181 r1260  
    5454typeMismatch.java.math.BigDecimal=Attribuut {0} is geen geldig nummer 
    5555typeMismatch.java.math.BigInteger=Attribuut {0} is geen geldig nummer 
     56 
     57# Generic error messages 
     58nullable={0} is verplicht en mag niet leeg zijn 
     59select.not.selected=Je moet een {0} kiezen 
     60select.not.selected.or.add=Je moet een {0} kiezen, of er een toevoegen als hij nog niet bestaat 
     61 
     62 
     63# Template entity meesages 
     64templateEntity.typeMismatch.long={0} moet een absoluut getal zijn (zonder komma's) 
     65templateEntity.typeMismatch.double={0} moet een getal zijn 
     66templateEntity.typeMismatch.integer={0} moet een getal zijn 
     67templateEntity.typeMismatch.string={0} moest een tekst zijn (maximum 255 karakters) 
     68templateEntity.tooLong.string={0} maar maar 255 karakters bevatten 
     69templateEntity.typeMismatch.templateFieldListItem={0} moet van het type TemplateFieldListItem zijn en momenteel is het een {1} instantie 
     70templateEntity.typeMismatch.date={0} moet een datum zijn 
     71templateEntity.typeMismatch.term={0} must ontology term zijn 
     72event.endTime.greaterThanStartTime=de eindtijd moet groter of gelijk zijn aan de begin tijd 
  • trunk/grails-app/i18n/messages.properties

    r1167 r1260  
    5555typeMismatch.java.math.BigInteger=Property {0} must be a valid number 
    5656 
    57 // TemplateEntity errors 
    58 templateEntity.typeMismatch.integer=Property {0} must be of type Integer and is currently of type {1} 
    59 templateEntity.typeMismatch.string=Property {0} must be of type String and is currently of type {1} 
    60 templateEntity.tooLong.string=Property {0} may contain at most 255 characters. 
     57# Generic error messages 
     58nullable={0} is required and may not be left blank 
     59select.not.selected=You need to select a {0} 
     60select.not.selected.or.add=You need to select a {0}, or add one if it is not yet present 
     61 
     62# TemplateEntity errors 
     63templateEntity.typeMismatch.long={0} has to be an absolute number (without comma's) 
     64templateEntity.typeMismatch.double={0} must be a number 
     65templateEntity.typeMismatch.integer={0} must be a number 
     66templateEntity.typeMismatch.string={0} must be a text (maximum 255 characters) 
     67templateEntity.tooLong.string={0} may contain at most 255 characters 
    6168templateEntity.typeMismatch.templateFieldListItem=Property {0} must be of type TemplateFieldListItem and is currently of type {1} 
    62 templateEntity.typeMismatch.float=Property {0} must be of type Float and is currently of type {1} 
    63 templateEntity.typeMismatch.double=Property {0} must be of type Double and is currently of type {1} 
    64 templateEntity.typeMismatch.date=Property {0} must be of type Date and is currently of type {1} 
    65 templateEntity.typeMismatch.term=Property {0} must be of type Term and is currently of type {1} 
    66  
     69templateEntity.typeMismatch.date={0} must be a date 
     70templateEntity.typeMismatch.term={0} must be an ontology term 
    6771event.endTime.greaterThanStartTime=End time should be greater than or equal to the Start Time 
  • trunk/grails-app/views/wizard/common/_error.gsp

    r1149 r1260  
    2727                // mark error fields 
    2828                <g:each in="${wizardErrors}" var="error"> 
    29                 var element = $("input:[name='${error.key}'], input:[name='${error.key.toLowerCase().replaceAll("([^a-z0-9])","_")}'], select:[name='${error.key}'], select:[name='${error.key.toLowerCase().replaceAll("([^a-z0-9])","_")}']"); 
     29                var element = $("input:[name='${error.key}'], input:[name='${error.key.toLowerCase().replaceAll("([^a-z0-9])","_")}'], select:[name='${error.key}'], select:[name='${error.key.toLowerCase().replaceAll("([^a-z0-9])","_")}'], textarea:[name='${error.key}'], textarea:[name='${error.key.toLowerCase().replaceAll("([^a-z0-9])","_")}']"); 
    3030                 <g:if test="${error.value['dynamic']}"> 
    3131                element.addClass('error');