Changeset 778
- Timestamp:
- Aug 5, 2010, 10:58:09 PM (13 years ago)
- Location:
- trunk/grails-app
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/grails-app/controllers/dbnp/studycapturing/WizardController.groovy
r769 r778 138 138 // clean the flow scope 139 139 flow.remove('study') 140 flow.remove('subjects')141 flow.remove('subjectTemplates')142 flow.remove('event')143 flow.remove('events')144 flow.remove('eventGroups')145 flow.remove('eventTemplates')146 flow.remove('samples')147 flow.remove('sampleTemplates')148 140 149 141 // set 'quicksave' variable to false … … 172 164 } 173 165 on("cancel") { 174 flow. study = null166 flow.remove('study') 175 167 176 168 success() … … 194 186 } 195 187 on("refresh") { 196 println ".refreshing...." 197 flash.values = params 198 199 // handle study data 200 this.handleStudy(flow, flash, params) 188 // handle form data 189 studyPage(flow, flash, params) 201 190 202 191 // force refresh of the template 203 if (flow.study.template ) {192 if (flow.study.template && flow.study.template instanceof Template) { 204 193 flow.study.template.refresh() 205 194 } 206 195 207 // remove errors as we don't want any warnings now 208 flash.errors = [:] 209 196 // reset errors 197 flash.errors = [:] 210 198 success() 211 199 }.to "study" 212 200 on("switchTemplate") { 213 flash.values = params 214 215 // handle study data 216 this.handleStudy(flow, flash, params) 217 218 // force refresh of the template 219 if (flow.study.template) { 220 flow.study.template.refresh() 221 } 222 223 // remove errors as we don't want any warnings now 224 flash.errors = [:] 225 201 // handle form data 202 studyPage(flow, flash, params) 203 204 // reset errors 205 flash.errors = [:] 226 206 success() 227 207 }.to "study" 228 208 on("previous") { 229 flash.errors = [:] 230 231 // handle the study 232 this.handleStudy(flow, flash, params) 209 // handle form data 210 studyPage(flow, flash, params) 233 211 234 212 // reset errors 235 213 flash.errors = [:] 236 237 214 success() 238 215 }.to "start" 239 216 on("next") { 240 flash.errors = [:] 241 242 if (this.handleStudy(flow, flash, params)) { 243 success() 244 } else { 245 error() 246 } 217 studyPage(flow, flash, params) ? success() : error() 247 218 }.to "subjects" 248 219 on("quickSave") { 249 flash.errors = [:] 250 251 if (this.handleStudy(flow, flash, params)) { 252 success() 253 } else { 254 error() 255 } 220 studyPage(flow, flash, params) ? success() : error() 256 221 }.to "waitForSave" 257 222 } … … 263 228 flow.page = 3 264 229 265 if (!flow.subjects) { 266 flow.subjects = [:] 267 flow.subjectTemplates = [:] 268 } 269 270 if (!flash.values) flash.values = [addNumber:1] 230 if (!flash.values || !flash.values.addNumber) flash.values = [addNumber:1] 271 231 272 232 success() 273 233 } 274 234 on("refresh") { 235 // remember the params in the flash scope 275 236 flash.values = params 276 237 277 238 // refresh templates 278 flow.s ubjectTemplates.each() {279 it. value.template.refresh()239 flow.study.giveSubjectTemplates().each() { 240 it.refresh() 280 241 } 281 242 … … 283 244 }.to "subjects" 284 245 on("add") { 285 flash.errors = [:] 286 287 // handle subjects 288 this.handleSubjects(flow, flash, params) 289 290 flash.errors = [:] 291 flash.values = params 292 293 def speciesTerm = Term.findByName(params.species) 294 def subjectTemplateName = params.get('template') 295 def subjectTemplate = Template.findByName(subjectTemplateName) 296 297 // got a species and a subjectTemplate? 298 if (speciesTerm && subjectTemplate) { 299 // add this subject template to the subject template array 300 if (!flow.subjectTemplates[subjectTemplateName]) { 301 flow.subjectTemplates[subjectTemplateName] = [ 302 name: subjectTemplateName, 303 template: subjectTemplate, 304 subjects: [:] 305 ] 306 } 307 308 // add x subjects of species y 309 (params.addNumber as int).times { 310 def increment = (flow.subjects.size()) ? (flow.subjects.keySet().max() + 1) : 0 311 def subject = new Subject( 312 name: 'Subject ' + (increment + 1), 313 species: speciesTerm, 314 template: subjectTemplate 315 ) 316 317 // instantiate a new Subject 318 flow.subjects[increment] = subject 319 320 // add the subject to the study 321 flow.study.addToSubjects( subject ) 322 323 // and remember the subject id with the template 324 def subjectsSize = (flow.subjectTemplates[subjectTemplateName].subjects.size()) ? (flow.subjectTemplates[subjectTemplateName].subjects.keySet().max() + 1) : 0 325 flow.subjectTemplates[subjectTemplateName].subjects[subjectsSize] = increment 326 } 327 328 success() 329 } else { 330 // add feedback 331 if (!speciesTerm) this.appendErrorMap(['species': 'You need to select a species, or add one if it is not yet present'], flash.errors) 332 if (!subjectTemplate) this.appendErrorMap(['template': 'You need to select a template, or add one if it is not yet present'], flash.errors) 333 334 error() 335 } 246 // handle form data 247 addSubjects(flow, flash, params) ? success() : error() 336 248 }.to "subjects" 337 249 on("delete") { 338 // handle subjects339 this.handleSubjects(flow, flash, params)340 341 flash.errors = [:]342 def delete = params.get('do') as int250 // handle form data 251 subjectPage(flow, flash, params) 252 253 // reset errors 254 flash.errors = [:] 343 255 344 256 // remove subject 345 if (flow.subjects[ delete ] && flow.subjects[ delete ] instanceof Subject) { 346 // from study as well 347 flow.study.removeFromSubjects( flow.subjects[ delete ] ) 348 349 // remove subject from templates 350 flow.subjectTemplates.each() { templateName, templateData -> 351 templateData.subjects.values().remove( delete ) 352 } 353 354 // remove templates that contain no subject 355 flow.subjectTemplates.find{!it.value.subjects.size()}.each{ flow.subjectTemplates.remove( it.key ) } 356 357 // remove subject altogether 358 flow.subjects.remove( delete ) 257 def subjectToRemove = flow.study.subjects.find { it.identifier == (params.get('do') as int) } 258 if (subjectToRemove) { 259 flow.study.deleteSubject( subjectToRemove ) 359 260 } 360 261 }.to "subjects" 361 262 on("previous") { 362 flash.errors = [:] 363 364 // handle form data 365 if (!this.handleSubjects(flow, flash, params)) { 366 error() 367 } else { 368 success() 369 } 263 // handle form data 264 subjectPage(flow, flash, params) 265 266 // reset errors 267 flash.errors = [:] 268 success() 370 269 }.to "study" 371 270 on("next") { 372 flash.errors = [:] 373 374 // check form data 375 if (!this.handleSubjects(flow, flash, params)) { 376 error() 377 } else { 378 success() 379 } 271 // handle form data 272 subjectPage(flow, flash, params) ? success() : error() 380 273 }.to "events" 381 274 on("quickSave") { 382 flash.errors = [:] 383 384 // check form data 385 if (!this.handleSubjects(flow, flash, params)) { 386 error() 387 } else { 388 success() 389 } 275 // handle form data 276 subjectPage(flow, flash, params) ? success() : error() 390 277 }.to "waitForSave" 391 278 } … … 397 284 flow.page = 4 398 285 399 if (!flow.event) { 400 flow.event = new Event() 401 flow.events = [:] 402 flow.eventGroups = [ new EventGroup(name: 'Group 1') ] 403 flow.eventTemplates = [:] 404 405 // add initial eventGroup to study 406 flow.study.addToEventGroups( flow.eventGroups[ 0 ] ) 407 } else if (!flash.values) { 408 // set flash.values.templateType based on the event instance 409 flash.values = [:] 410 flash.values.templateType = (flow.event instanceof Event) ? 'event' : 'sample' 411 } 286 // add initial eventGroup to study 287 if (!flow.study.eventGroups?.size()) { 288 flow.study.addToEventGroups( 289 new EventGroup(name: 'Group 1') 290 ) 291 } 292 412 293 success() 413 294 } 414 295 on("clear") { 415 flow.remove('event') 296 // remove all events 297 (flow.study.events + flow.study.samplingEvents).each() { event -> 298 if (event instanceof SamplingEvent) { 299 flow.study.deleteSamplingEvent( event ) 300 } else { 301 flow.study.deleteEvent( event ) 302 } 303 } 304 416 305 success() 417 306 }.to "events" 418 307 on("switchTemplate") { 419 flash.values = params 420 421 // handle study data 422 this.handleEvents(flow, flash, params) 423 424 // refresh event templates 425 flow.eventTemplates.each() { 426 it.value.template.refresh() 427 } 428 429 // refresh flow template 430 if (flow.event.template) flow.event.template.refresh() 431 432 // remove errors as we don't want any warnings now 433 flash.errors = [:] 308 // handle form data 309 eventPage(flow, flash, params) 310 311 // get template 312 def type = params.get('eventType') 313 def template= Template.findByName( params.get( type + 'Template' ) ) 314 315 // change template and/or instance? 316 if (!flow.event || (flow.event instanceof Event && type == "sample") || (flow.event instanceof SamplingEvent && type == "event")) { 317 // create new instance 318 flow.event = (type == "event") ? new Event(template: template, parent: flow.study) : new SamplingEvent(template: template, parent: flow.study) 319 } else { 320 flow.event.template = template 321 } 322 323 // reset errors 324 flash.errors = [:] 325 success() 326 434 327 }.to "events" 435 328 on("refresh") { 436 flash.values = params 437 438 // handle study data 439 this.handleEvents(flow, flash, params) 329 // handle form data 330 eventPage(flow, flash, params) 440 331 441 332 // refresh templates 442 flow.eventTemplates.each() { 443 it.value.template.refresh() 444 } 445 446 // refresh flow template 447 if (flow.event.template) flow.event.template.refresh() 448 449 // remove errors as we don't want any warnings now 450 flash.errors = [:] 333 flow.study.giveEventTemplates().each() { 334 it.refresh() 335 } 336 337 // refresh event template 338 if (flow.event?.template) flow.event.template.refresh() 339 340 // reset errors 341 flash.errors = [:] 342 success() 451 343 }.to "events" 452 344 on("add") { 453 flash.values = params 454 def eventTemplateName = (params.get('eventType') == 'event') ? params.get('eventTemplate') : params.get('sampleTemplate') 455 def eventTemplate = Template.findByName(eventTemplateName) 456 457 // handle study data 458 this.handleEvents(flow, flash, params) 459 460 // add event to study 461 if (flow.event instanceof SamplingEvent) { 462 flow.study.addToSamplingEvents( flow.event ) 463 } else { 464 flow.study.addToEvents( flow.event ) 465 } 466 467 // validate event object 345 // handle form data 346 eventPage(flow, flash, params) 347 348 // reset errors 349 flash.errors = [:] 350 351 // validate event 468 352 if (flow.event.validate()) { 469 // add this event template to the event template array 470 if (!flow.eventTemplates[ eventTemplateName ]) { 471 flow.eventTemplates[ eventTemplateName ] = [ 472 name: eventTemplateName, 473 template: eventTemplate, 474 events: [] 475 ] 353 // validates properly 354 if (flow.event instanceof SamplingEvent) { 355 flow.study.addToSamplingEvents( flow.event ) 356 } else { 357 flow.study.addToEvents( flow.event ) 476 358 } 477 359 478 // ...store it in the events map in the flow scope... 479 def increment = flow.events.size() 480 flow.events[ increment ] = flow.event 481 482 // ...add it to the study... 483 /* 484 if (newEvent instanceof SamplingEvent) { 485 flow.study.addToSamplingEvents( newEvent ) 486 } else { 487 flow.study.addToEvents( newEvent ) 488 } 489 */ 490 491 // ...and 'reset' the event object in the flow scope 492 flow.event = new Event(template: flow.event.template) 360 // remove event from the flowscope 361 flow.remove('event') 493 362 494 // remember the event id with the template495 def eventSize = flow.eventTemplates[ eventTemplateName ]['events'].size()496 flow.eventTemplates[ eventTemplateName ]['events'][ eventSize ] = increment497 498 363 success() 499 364 } else { 500 // it does not validate, remove event from study 501 if (flow.event instanceof SamplingEvent) { 502 flow.study.removeFromSamplingEvents(flow.event) 503 } else { 504 flow.study.removeFromEvents(flow.event) 505 } 506 507 // show error feedback 508 flash.errors = [:] 365 // event does not validate 509 366 this.appendErrors(flow.event, flash.errors) 510 367 error() … … 512 369 }.to "events" 513 370 on("deleteEvent") { 514 flash.values = params 515 def delete = params.get('do') as int 516 517 // handle event groupings 518 this.handleEventGrouping(flow, flash, params) 519 520 // remove event 521 if (flow.events[ delete ] && flow.events[ delete ] instanceof Event) { 522 // remove it from the study 523 if ( flow.events[ delete ] instanceof SamplingEvent ) { 524 flow.study.removeFromSamplingEvents( flow.events[ delete ] ) 525 } else { 526 flow.study.removeFromEvents( flow.events[ delete ] ) 527 } 528 529 // remove it from the map 530 flow.events.remove(delete) 531 flow.eventTemplates.each() { eventTemplate -> 532 eventTemplate.value.events = eventTemplate.value.events.minus(delete) 533 } 534 535 // find eventTemplates without events 536 flow.eventTemplates.find { eventTemplate -> 537 eventTemplate.value.events.size() < 1 538 }.each() { 539 // remove eventTemplate 540 flow.eventTemplates.remove( it.value.name ) 541 } 542 } 543 544 success() 371 // handle form data 372 eventPage(flow, flash, params) 373 374 // reset errors 375 flash.errors = [:] 376 377 // find matching (sampling) event 378 def event = flow.study.events.find { it.getIdentifier() == (params.get('do') as int) } 379 def samplingEvent = flow.study.samplingEvents.find { it.getIdentifier() == (params.get('do') as int) } 380 381 // perform delete 382 if (event) flow.study.deleteEvent( event ) 383 if (samplingEvent) flow.study.deleteSamplingEvent( samplingEvent ) 545 384 }.to "events" 546 385 on("addEventGroup") { 547 flash.values = params 548 549 // handle study data 550 this.handleEvents(flow, flash, params) 551 552 // handle event groupings 553 this.handleEventGrouping(flow, flash, params) 554 555 def increment = flow.eventGroups.size() 556 def groupName = "Group " + (increment + 1) 557 558 // check if group name exists 559 def nameExists = true 560 def u = 0 561 562 // make sure a unique name is generated 563 while (nameExists) { 564 u++ 565 def count = 0 566 567 flow.eventGroups.each() { 568 if (it.name == groupName) { 569 groupName = "Group " + (increment + 1) + "," + u 570 } else { 571 count++ 386 // handle form data 387 eventPage(flow, flash, params) 388 389 // first find the current maximum default name "Subject xxxx" 390 def eventGroupNo = 0 391 def eventGroupMax = 0 392 flow.study.eventGroups.each() { 393 it.name.trim().eachMatch(/(\d+)$/){ 394 eventGroupNo = it[1] as int 395 if (eventGroupNo > eventGroupMax) { 396 eventGroupMax = eventGroupNo 572 397 } 573 398 } 574 575 nameExists = !(count == flow.eventGroups.size()) 576 } 577 578 // remember eventGroup 579 flow.eventGroups[ increment ] = new EventGroup( name: groupName ) 580 581 // and add the group to the study 582 flow.study.addToEventGroups( flow.eventGroups[ increment ] ) 583 399 } 400 401 // add a new eventGroup 402 flow.study.addToEventGroups( 403 new EventGroup( 404 name : 'Group ' + (eventGroupMax+1), 405 parent : flow.study 406 ) 407 ) 408 409 // reset errors 410 flash.errors = [:] 584 411 success() 585 412 }.to "events" 586 413 on("deleteEventGroup") { 587 flash.values = params 588 def delete = params.get('do') as int 589 590 // handle event groupings 591 this.handleEventGrouping(flow, flash, params) 592 593 // remove the group with this specific id 594 if (flow.eventGroups[delete] && flow.eventGroups[delete] instanceof EventGroup) { 595 // remove the eventGroup from the study 596 flow.study.removeFromEventGroups( flow.eventGroups[ delete ] ) 597 598 // remove this eventGroup 599 flow.eventGroups.remove(delete) 600 } 601 602 success() 414 // handle form data 415 eventPage(flow, flash, params) 416 417 // reset errors 418 flash.errors = [:] 419 420 // remove eventGroup 421 def eventGroupToRemove = flow.study.eventGroups.find { it.getIdentifier() == (params.get('do') as int) } 422 if (eventGroupToRemove) { 423 flow.study.deleteEventGroup( eventGroupToRemove ) 424 } 603 425 }.to "events" 604 426 on("previous") { 605 // handle event groupings 606 this.handleEventGrouping(flow, flash, params) 427 // handle form data 428 eventPage(flow, flash, params) 429 430 // reset errors 431 flash.errors = [:] 432 success() 607 433 }.to "subjects" 608 434 on("next") { 609 flash.values = params 610 flash.errors = [:] 611 612 // handle study data 613 /* turned off by request of Kees / Leny / Jildau 614 if (!flow.eventTemplates.find { eventTemplate -> eventTemplate.value.template.entity == SamplingEvent }) { 615 // append error map 616 this.appendErrorMap(['events': 'You need to create at least one sampling event for your study'], flash.errors) 617 error() 618 } else 619 */ 620 if (this.handleEvents(flow, flash, params)) { 621 success() 622 } else { 623 error() 624 } 435 // handle form data 436 eventPage(flow, flash, params) ? success() : error() 625 437 }.to "groups" 626 438 on("quickSave") { 627 flash.values = params 628 flash.errors = [:] 629 630 // handle study data 631 /* turned off by request of Kees / Leny / Jildau 632 if (!flow.eventTemplates.find { eventTemplate -> eventTemplate.value.template.entity == SamplingEvent }) { 633 // append error map 634 this.appendErrorMap(['events': 'You need to create at least one sampling event for your study'], flash.errors) 635 error() 636 } else 637 */ 638 if (this.handleEvents(flow, flash, params)) { 639 success() 640 } else { 641 error() 642 } 439 // handle form data 440 eventPage(flow, flash, params) ? success() : error() 643 441 }.to "waitForSave" 644 442 } … … 652 450 } 653 451 on("previous") { 654 this.handleSubjectGrouping(flow, flash, params)655 success()452 // handle form data 453 groupPage(flow, flash, params) ? success() : error() 656 454 }.to "events" 657 455 on("next") { 658 this.handleSubjectGrouping(flow, flash, params) 659 flash.check = true 660 success() 661 }.to "samples" 456 // handle form data 457 groupPage(flow, flash, params) ? success() : error() 458 }.to "waitForSave" 662 459 on("quickSave") { 663 this.handleSubjectGrouping(flow, flash, params)664 success()460 // handle form data 461 groupPage(flow, flash, params) ? success() : error() 665 462 }.to "waitForSave" 666 463 } … … 694 491 onRender { 695 492 flow.page = 6 696 493 /* 697 494 // iterate through eventGroups 698 495 if (!flow.samples) { … … 739 536 740 537 success() 538 */ 741 539 } 742 540 on("switchTemplate") { … … 854 652 // persist data to the database 855 653 try { 856 // user modifying?857 if (flow.quickSave && grails.util.GrailsUtil.environment == 'production') {858 // yes, not allowed on production as this results in data inconsistency859 println ".saving is not allowed in study edit wizard"860 throw new Exception("Saving is not allowed in the edit study wizard because this leads to data inconsistency in the database!")861 }862 863 654 // save study 864 655 println ".saving study" … … 921 712 flow.study = (params.studyid) ? Study.findById( params.studyid ) : Study.findByTitle( params.study ) 922 713 923 // recreate subjects924 flow.subjects = [:]925 flow.subjectTemplates = [:]926 flow.study.subjects.each() { subject ->927 def subjectIncrement = flow.subjects.size()928 flow.subjects[subjectIncrement] = subject929 930 // add subject template?931 if (!flow.subjectTemplates[subject.template.name]) {932 flow.subjectTemplates[subject.template.name] = [933 name: subject.template.name,934 template: subject.template,935 subjects: [:]936 ]937 }938 939 // reference subject in template940 flow.subjectTemplates[subject.template.name].subjects[flow.subjectTemplates[subject.template.name].subjects.size()] = subjectIncrement941 }942 943 // recreate events944 flow.events = [:]945 flow.eventGroups = []946 flow.eventTemplates = [:]947 flow.study.events.each() { event ->948 def eventIncrement = flow.events.size()949 flow.events[eventIncrement] = event950 951 // add event template?952 if (!flow.eventTemplates[event.template.name]) {953 flow.eventTemplates[event.template.name] = [954 name: event.template.name,955 template: event.template,956 events: new ArrayList()957 ]958 }959 960 // reference event in template961 flow.eventTemplates[event.template.name].events[flow.eventTemplates[event.template.name].events.size()] = eventIncrement962 963 // set dummy event964 flow.event = event965 }966 967 // recreate sample events968 flow.study.samplingEvents.each() { event ->969 def eventIncrement = flow.events.size()970 flow.events[eventIncrement] = event971 972 // add event template?973 if (!flow.eventTemplates[event.template.name]) {974 flow.eventTemplates[event.template.name] = [975 name: event.template.name,976 template: event.template,977 events: new ArrayList()978 ]979 }980 981 // reference event in template982 flow.eventTemplates[event.template.name].events[flow.eventTemplates[event.template.name].events.size()] = eventIncrement983 984 // set dummy event985 flow.event = event986 }987 988 // recreate eventGroups989 flow.study.eventGroups.each() { eventGroup ->990 flow.eventGroups[flow.eventGroups.size()] = eventGroup991 }992 993 714 // set 'quicksave' variable 994 715 flow.quickSave = true … … 1002 723 } 1003 724 } 1004 1005 /**1006 * re-usable code for handling study form data in a web flow1007 * @param Map LocalAttributeMap (the flow scope)1008 * @param Map localAttributeMap (the flash scope)1009 * @param Map GrailsParameterMap (the flow parameters = form data)1010 * @returns boolean1011 */1012 def handleStudy(flow, flash, params) {1013 // create study instance if we have none1014 if (!flow.study) flow.study = new Study()1015 1016 // create date instance from date string?1017 // @see WizardTagLibrary::dateElement{...}1018 if (params.get('startDate')) {1019 params.startDate = new Date().parse("d/M/yyyy", params.get('startDate').toString())1020 } else {1021 params.remove('startDate')1022 }1023 1024 // if a template is selected, get template instance1025 def template = params.remove('template')1026 if (template instanceof String && template.size() > 0) {1027 flow.study.template = Template.findByName(template)1028 } else if (template instanceof Template) {1029 flow.study.template = template1030 }1031 1032 // iterate through fields1033 if (flow.study.template) {1034 flow.study.giveFields().each() {1035 flow.study.setFieldValue(it.name, params.get(it.escapedName()))1036 }1037 }1038 1039 // handle Publications and Contacts1040 handlePublications(flow, flash, params)1041 handleContacts(flow, flash, params)1042 1043 // validate study1044 if (flow.study.validate()) {1045 return true1046 } else {1047 // validation failed, feedback errors1048 flash.errors = [:]1049 this.appendErrors(flow.study, flash.errors)1050 return false1051 }1052 }1053 1054 /**1055 * re-usable code for handling publications form data in a web flow1056 * @param Map LocalAttributeMap (the flow scope)1057 * @param Map localAttributeMap (the flash scope)1058 * @param Map GrailsParameterMap (the flow parameters = form data)1059 * @returns boolean1060 */1061 def handlePublications(flow, flash, params) {1062 // create study instance if we have none1063 if (!flow.study) flow.study = new Study()1064 if (!flow.study.publications) flow.study.publications = []1065 1066 // Check the ids of the pubblications that should be attached1067 // to this study. If they are already attached, keep 'm. If1068 // studies are attached that are not in the selected (i.e. the1069 // user deleted them), remove them1070 def publicationIDs = params.get('publication_ids')1071 if (publicationIDs) {1072 // Find the individual IDs and make integers1073 publicationIDs = publicationIDs.split(',').collect { Integer.parseInt(it, 10) }1074 1075 // First remove the publication that are not present in the array1076 flow.study.publications.removeAll { publication -> !publicationIDs.find { id -> id == publication.id } }1077 1078 // Add those publications not yet present in the database1079 publicationIDs.each { id ->1080 if (!flow.study.publications.find { publication -> id == publication.id }) {1081 def publication = Publication.get(id)1082 if (publication) {1083 flow.study.addToPublications(publication)1084 } else {1085 println('.publication with ID ' + id + ' not found in database.')1086 }1087 }1088 }1089 1090 } else {1091 println('.no publications selected.')1092 flow.study.publications.clear()1093 }1094 1095 }1096 1097 /**1098 * re-usable code for handling contacts form data in a web flow1099 * @param Map LocalAttributeMap (the flow scope)1100 * @param Map localAttributeMap (the flash scope)1101 * @param Map GrailsParameterMap (the flow parameters = form data)1102 * @return boolean1103 */1104 def handleContacts(flow, flash, params) {1105 // create study instance if we have none1106 if (!flow.study) flow.study = new Study()1107 if (!flow.study.persons) flow.study.persons = []1108 1109 // Check the ids of the contacts that should be attached1110 // to this study. If they are already attached, keep 'm. If1111 // studies are attached that are not in the selected (i.e. the1112 // user deleted them), remove them1113 1114 // Contacts are saved as [person_id]-[role_id]1115 def contactIDs = params.get('contacts_ids')1116 if (contactIDs) {1117 // Find the individual IDs and make integers1118 contactIDs = contactIDs.split(',').collect {1119 def parts = it.split('-')1120 return [person: Integer.parseInt(parts[0]), role: Integer.parseInt(parts[1])]1121 }1122 1123 // First remove the contacts that are not present in the array1124 flow.study.persons.removeAll {1125 studyperson -> !contactIDs.find { ids -> (ids.person == studyperson.person.id) && (ids.role == studyperson.role.id) }1126 }1127 1128 // Add those contacts not yet present in the database1129 contactIDs.each { ids ->1130 if (!flow.study.persons.find { studyperson -> (ids.person == studyperson.person.id) && (ids.role == studyperson.role.id) }) {1131 def person = Person.get(ids.person)1132 def role = PersonRole.get(ids.role)1133 if (person && role) {1134 // Find a studyperson object with these parameters1135 def studyPerson = StudyPerson.findAll().find { studyperson -> studyperson.person.id == person.id && studyperson.role.id == role.id }1136 1137 // If if does not yet exist, save the example1138 if (!studyPerson) {1139 studyPerson = new StudyPerson(1140 person: person,1141 role: role1142 )1143 studyPerson.save(flush: true)1144 }1145 1146 flow.study.addToPersons(studyPerson)1147 } else {1148 println('.person ' + ids.person + ' or Role ' + ids.role + ' not found in database.')1149 }1150 }1151 }1152 } else {1153 println('.no persons selected.')1154 flow.study.persons.clear()1155 }1156 1157 }1158 1159 /**1160 * re-usable code for handling subject form data in a web flow1161 * @param Map LocalAttributeMap (the flow scope)1162 * @param Map localAttributeMap (the flash scope)1163 * @param Map GrailsParameterMap (the flow parameters = form data)1164 * @return boolean1165 */1166 def handleSubjects(flow, flash, params) {1167 def names = [:]1168 def errors = false1169 def id = 01170 1171 // iterate through subject templates1172 flow.subjectTemplates.each() { subjectTemplate ->1173 // iterate through subjects1174 subjectTemplate.value.subjects.each() { subjectIncrement, subjectId ->1175 // iterate through fields (= template fields and domain properties)1176 flow.subjects[ subjectId ].giveFields().each() { subjectField ->1177 // set the field1178 flow.subjects[ subjectId ].setFieldValue(1179 subjectField.name,1180 params.get( 'subject_' + subjectId + '_' + subjectField.escapedName() )1181 )1182 }1183 1184 // validate subject1185 if (!flow.subjects[ subjectId ].validate()) {1186 errors = true1187 this.appendErrors(flow.subjects[ subjectId ], flash.errors, 'subject_' + subjectId + '_')1188 }1189 }1190 }1191 1192 return !errors1193 }1194 1195 /**1196 * re-usable code for handling event form data in a web flow1197 * @param Map LocalAttributeMap (the flow scope)1198 * @param Map localAttributeMap (the flash scope)1199 * @param Map GrailsParameterMap (the flow parameters = form data)1200 * @return boolean1201 */1202 def handleEvents(flow, flash, params) {1203 def errors = false1204 def template = null1205 1206 // handle the type of event1207 if (params.eventType == 'event') {1208 flow.event = new Event()1209 template = params.remove('eventTemplate')1210 } else if (params.eventType == 'sample') {1211 flow.event = new SamplingEvent()1212 template = params.remove('sampleTemplate')1213 }1214 1215 // if a template is selected, get template instance1216 if (template instanceof String && template.size() > 0) {1217 params.template = Template.findByName(template)1218 } else if (template instanceof Template) {1219 params.template = template1220 } else {1221 params.template = null1222 }1223 1224 // set template1225 if (params.template) flow.event.template = params.template1226 1227 // update event instance with parameters1228 flow.event.giveFields().each() { eventField ->1229 flow.event.setFieldValue(eventField.name, params[ eventField.escapedName() ])1230 }1231 1232 // handle event objects1233 flow.eventTemplates.each() { eventTemplate ->1234 // iterate through events1235 eventTemplate.getValue().events.each() { eventId ->1236 // iterate through template fields1237 flow.events[ eventId ].giveFields().each() { eventField ->1238 if ( params.containsKey( 'event_' + eventId + '_' + eventField.escapedName() ) ) {1239 flow.events[ eventId ].setFieldValue(eventField.name, params.get( 'event_' + eventId + '_' + eventField.escapedName() ) )1240 }1241 }1242 1243 // validate event1244 if (!flow.events[ eventId ].validate()) {1245 errors = true1246 this.appendErrors(flow.events[ eventId ], flash.errors, 'event_' + eventId + '_')1247 }1248 }1249 }1250 1251 // handle event grouping1252 handleEventGrouping(flow, flash, params)1253 1254 return !errors1255 }1256 1257 /**1258 * re-usable code for handling event grouping in a web flow1259 * @param Map LocalAttributeMap (the flow scope)1260 * @param Map localAttributeMap (the flash scope)1261 * @param Map GrailsParameterMap (the flow parameters = form data)1262 * @return boolean1263 */1264 def handleEventGrouping(flow, flash, params) {1265 // walk through eventGroups1266 def g = 01267 flow.eventGroups.each() { eventGroup ->1268 def e = 01269 1270 // reset events1271 eventGroup.events = new HashSet()1272 1273 // iterate through events1274 flow.events.each() {1275 if (params.get('event_' + e + '_group_' + g) == 'on') {1276 // add event to eventgroup1277 if (it.value instanceof SamplingEvent) {1278 eventGroup.addToSamplingEvents(it.value)1279 } else {1280 eventGroup.addToEvents(it.value)1281 }1282 }1283 e++1284 }1285 g++1286 }1287 }1288 1289 /**1290 * re-usable code for handling subject grouping in a web flow1291 * @param Map LocalAttributeMap (the flow scope)1292 * @param Map localAttributeMap (the flash scope)1293 * @param Map GrailsParameterMap (the flow parameters = form data)1294 * @return boolean1295 */1296 def handleSubjectGrouping(flow, flash, params) {1297 // iterate through event groups1298 def g = 01299 flow.eventGroups.each() { eventGroup ->1300 // reset subjects1301 eventGroup.subjects = new HashSet()1302 1303 // iterate through subjects1304 flow.subjects.each() { subjectId, subject ->1305 // is this combination set?1306 if (params.get('subject_' + subjectId + '_group_' + g) != null) {1307 eventGroup.addToSubjects(subject)1308 }1309 }1310 1311 g++1312 }1313 }1314 1315 725 1316 726 /** … … 1525 935 ); 1526 936 } 937 938 939 /****** REFACTORED METHODS OVER HERE! ******/ 940 941 /** 942 * Handle the wizard study page 943 * 944 * @param Map LocalAttributeMap (the flow scope) 945 * @param Map localAttributeMap (the flash scope) 946 * @param Map GrailsParameterMap (the flow parameters = form data) 947 * @returns boolean 948 */ 949 def studyPage(flow, flash, params) { 950 // remember the params in the flash scope 951 flash.values = params 952 953 // instantiate study of it is not yet present 954 if (!flow.study) flow.study = new Study() 955 956 // did the study template change? 957 if (params.get('template').size() && flow.study.template?.name != params.get('template')) { 958 println ".change study template!" 959 960 // yes, was the template already set? 961 if (flow.study.template instanceof Template) { 962 // yes, first make sure all values are unset? 963 println "!!! check the database fields if data of a previous template remains in the database or is deleted by GORM!" 964 } 965 966 // set the template 967 flow.study.template = Template.findByName(params.remove('template')) 968 } 969 970 // does the study have a template set? 971 if (flow.study.template && flow.study.template instanceof Template) { 972 // yes, iterate through template fields 973 flow.study.giveFields().each() { 974 // and set their values 975 flow.study.setFieldValue(it.name, params.get(it.escapedName())) 976 } 977 } 978 979 // handle publications 980 handlePublications(flow, flash, params) 981 982 // handle contacts 983 handleContacts(flow, flash, params) 984 985 // validate the study 986 if (flow.study.validate()) { 987 // instance is okay 988 return true 989 } else { 990 // validation failed 991 flash.errors = [:] 992 this.appendErrors(flow.study, flash.errors) 993 return false 994 } 995 } 996 997 /** 998 * re-usable code for handling publications form data in a web flow 999 * @param Map LocalAttributeMap (the flow scope) 1000 * @param Map localAttributeMap (the flash scope) 1001 * @param Map GrailsParameterMap (the flow parameters = form data) 1002 * @returns boolean 1003 */ 1004 def handlePublications(flow, flash, params) { 1005 if (!flow.study.publications) flow.study.publications = [] 1006 1007 // Check the ids of the pubblications that should be attached 1008 // to this study. If they are already attached, keep 'm. If 1009 // studies are attached that are not in the selected (i.e. the 1010 // user deleted them), remove them 1011 def publicationIDs = params.get('publication_ids') 1012 if (publicationIDs) { 1013 // Find the individual IDs and make integers 1014 publicationIDs = publicationIDs.split(',').collect { Integer.parseInt(it, 10) } 1015 1016 // First remove the publication that are not present in the array 1017 flow.study.publications.removeAll { publication -> !publicationIDs.find { id -> id == publication.id } } 1018 1019 // Add those publications not yet present in the database 1020 publicationIDs.each { id -> 1021 if (!flow.study.publications.find { publication -> id == publication.id }) { 1022 def publication = Publication.get(id) 1023 if (publication) { 1024 flow.study.addToPublications(publication) 1025 } else { 1026 println('.publication with ID ' + id + ' not found in database.') 1027 } 1028 } 1029 } 1030 1031 } else { 1032 println('.no publications selected.') 1033 flow.study.publications.clear() 1034 } 1035 1036 } 1037 1038 /** 1039 * re-usable code for handling contacts form data in a web flow 1040 * @param Map LocalAttributeMap (the flow scope) 1041 * @param Map localAttributeMap (the flash scope) 1042 * @param Map GrailsParameterMap (the flow parameters = form data) 1043 * @return boolean 1044 */ 1045 def handleContacts(flow, flash, params) { 1046 if (!flow.study.persons) flow.study.persons = [] 1047 1048 // Check the ids of the contacts that should be attached 1049 // to this study. If they are already attached, keep 'm. If 1050 // studies are attached that are not in the selected (i.e. the 1051 // user deleted them), remove them 1052 1053 // Contacts are saved as [person_id]-[role_id] 1054 def contactIDs = params.get('contacts_ids') 1055 if (contactIDs) { 1056 // Find the individual IDs and make integers 1057 contactIDs = contactIDs.split(',').collect { 1058 def parts = it.split('-') 1059 return [person: Integer.parseInt(parts[0]), role: Integer.parseInt(parts[1])] 1060 } 1061 1062 // First remove the contacts that are not present in the array 1063 flow.study.persons.removeAll { 1064 studyperson -> !contactIDs.find { ids -> (ids.person == studyperson.person.id) && (ids.role == studyperson.role.id) } 1065 } 1066 1067 // Add those contacts not yet present in the database 1068 contactIDs.each { ids -> 1069 if (!flow.study.persons.find { studyperson -> (ids.person == studyperson.person.id) && (ids.role == studyperson.role.id) }) { 1070 def person = Person.get(ids.person) 1071 def role = PersonRole.get(ids.role) 1072 if (person && role) { 1073 // Find a studyperson object with these parameters 1074 def studyPerson = StudyPerson.findAll().find { studyperson -> studyperson.person.id == person.id && studyperson.role.id == role.id } 1075 1076 // If if does not yet exist, save the example 1077 if (!studyPerson) { 1078 studyPerson = new StudyPerson( 1079 person: person, 1080 role: role 1081 ) 1082 studyPerson.save(flush: true) 1083 } 1084 1085 flow.study.addToPersons(studyPerson) 1086 } else { 1087 println('.person ' + ids.person + ' or Role ' + ids.role + ' not found in database.') 1088 } 1089 } 1090 } 1091 } else { 1092 println('.no persons selected.') 1093 flow.study.persons.clear() 1094 } 1095 1096 } 1097 1098 /** 1099 * Handle the wizard subject page 1100 * 1101 * @param Map LocalAttributeMap (the flow scope) 1102 * @param Map localAttributeMap (the flash scope) 1103 * @param Map GrailsParameterMap (the flow parameters = form data) 1104 * @returns boolean 1105 */ 1106 def subjectPage(flow, flash, params) { 1107 def errors = false 1108 flash.errors = [:] 1109 1110 // remember the params in the flash scope 1111 flash.values = params 1112 1113 // iterate through subjects 1114 flow.study.subjects.each() { subject -> 1115 // iterate through (template and domain) fields 1116 subject.giveFields().each() { field -> 1117 // set field 1118 subject.setFieldValue( 1119 field.name, 1120 params.get('subject_' + subject.getIdentifier() + '_' + field.escapedName()) 1121 ) 1122 } 1123 1124 // validate subject 1125 if (!subject.validate()) { 1126 errors = true 1127 this.appendErrors(subject, flash.errors, 'subject_' + subject.getIdentifier() + '_') 1128 } 1129 } 1130 1131 return !errors 1132 } 1133 1134 /** 1135 * Add a number of subjects to a study 1136 * 1137 * required params entities: 1138 * -addNumber (int) 1139 * -species (string) 1140 * -template (string) 1141 * 1142 * @param Map LocalAttributeMap (the flow scope) 1143 * @param Map localAttributeMap (the flash scope) 1144 * @param Map GrailsParameterMap (the flow parameters = form data) 1145 * @returns boolean 1146 */ 1147 def addSubjects(flow, flash, params) { 1148 // remember the params in the flash scope 1149 flash.values = params 1150 1151 // handle the subject page 1152 subjectPage(flow, flash, params) 1153 1154 // (re)set error message 1155 flash.errors = [:] 1156 1157 // set work variables 1158 def errors = false 1159 def number = params.get('addNumber') as int 1160 def species = Term.findByName(params.get('species')) 1161 def template = Template.findByName(params.get('template')) 1162 def subjectNo = 0 1163 def subjectMax = 0 1164 1165 // can we add subjects? 1166 if (number > 0 && species && template) { 1167 // first find the current maximum default name "Subject xxxx" 1168 flow.study.subjects.each() { 1169 it.name.trim().eachMatch(/(\d+)$/){ 1170 subjectNo = it[1] as int 1171 if (subjectNo > subjectMax) { 1172 subjectMax = subjectNo 1173 } 1174 } 1175 } 1176 1177 // add subjects to study 1178 number.times { 1179 subjectMax++ 1180 1181 // create a subject instance 1182 def subject = new Subject( 1183 name : 'Subject ' + subjectMax, 1184 species : species, 1185 template : template, 1186 parent : flow.study 1187 ) 1188 1189 // validate subject 1190 if (subject.validate()) { 1191 // add it to the study 1192 flow.study.addToSubjects( subject ) 1193 println ".added subject "+subject 1194 } else { 1195 // whoops? 1196 this.appendErrors(subject, flash.errors) 1197 errors = true 1198 } 1199 } 1200 } else { 1201 // add feedback 1202 errors = true 1203 if (number < 1) this.appendErrorMap(['addNumber': 'Enter a positive number of subjects to add'], flash.errors) 1204 if (!species) this.appendErrorMap(['species': 'You need to select a species, or add one if it is not yet present'], flash.errors) 1205 if (!template) this.appendErrorMap(['template': 'You need to select a template, or add one if it is not yet present'], flash.errors) 1206 } 1207 1208 return !errors 1209 } 1210 1211 /** 1212 * Handle the wizard event page 1213 * 1214 * @param Map LocalAttributeMap (the flow scope) 1215 * @param Map localAttributeMap (the flash scope) 1216 * @param Map GrailsParameterMap (the flow parameters = form data) 1217 * @returns boolean 1218 */ 1219 def eventPage(flow, flash, params) { 1220 def errors = false 1221 flash.errors = [:] 1222 1223 // remember the params in the flash scope 1224 flash.values = params 1225 1226 // handle the 'add event' form 1227 if (flow.event) { 1228 flow.event.giveFields().each() { field -> 1229 // set field 1230 flow.event.setFieldValue( 1231 field.name, 1232 params.get(field.escapedName()) 1233 ) 1234 } 1235 } 1236 1237 // handle the eventGroup names and grouping 1238 def name = "" 1239 def tempName= "" 1240 flow.study.eventGroups.each() { eventGroup -> 1241 // iterate through templates 1242 flow.study.giveAllEventTemplates().each() { template -> 1243 tempName = params.get( 'eventGroup_' + eventGroup.getIdentifier() + '_' + template.getIdentifier() ) 1244 1245 // is the name different? 1246 if (tempName != eventGroup.name) { 1247 name = tempName 1248 } 1249 } 1250 1251 // should the name change? 1252 if (name) { 1253 // yes, change it 1254 eventGroup.name = name 1255 name = "" 1256 } 1257 1258 // handle eventGrouping 1259 ( ((flow.study.events) ? flow.study.events : []) + ((flow.study.samplingEvents) ? flow.study.samplingEvents : []) ) .each() { event -> 1260 if (params.get( 'event_' + event.getIdentifier() + '_group_' + eventGroup.getIdentifier() )) { 1261 // add to eventGroup 1262 if (event instanceof SamplingEvent) { 1263 eventGroup.addToSamplingEvents(event) 1264 } else { 1265 eventGroup.addToEvents(event) 1266 } 1267 } else { 1268 // remove from eventGroup 1269 if (event instanceof SamplingEvent) { 1270 eventGroup.removeFromSamplingEvents(event) 1271 } else { 1272 eventGroup.removeFromEvents(event) 1273 } 1274 } 1275 } 1276 } 1277 1278 // handle the (sampling) events 1279 ( ((flow.study.events) ? flow.study.events : []) + ((flow.study.samplingEvents) ? flow.study.samplingEvents : []) ) .each() { event -> 1280 event.giveFields().each() { field -> 1281 event.setFieldValue( 1282 field.name, 1283 params.get( 'event_' + event.getIdentifier() + '_' + field.escapedName()) 1284 ) 1285 } 1286 1287 // validate event 1288 if (!event.validate()) { 1289 errors = true 1290 this.appendErrors(event, flash.errors) 1291 } 1292 } 1293 1294 // handle eventGroup names 1295 flow.study.eventGroups.each() { eventGroup -> 1296 1297 } 1298 1299 return !errors 1300 } 1301 1302 /** 1303 * Handle the wizard group page 1304 * 1305 * @param Map LocalAttributeMap (the flow scope) 1306 * @param Map localAttributeMap (the flash scope) 1307 * @param Map GrailsParameterMap (the flow parameters = form data) 1308 * @returns boolean 1309 */ 1310 def groupPage(flow, flash, params) { 1311 def errors = false 1312 flash.errors = [:] 1313 1314 // remember the params in the flash scope 1315 flash.values = params 1316 1317 // iterate through groups 1318 flow.study.eventGroups.each() { eventGroup -> 1319 // iterate through subjects 1320 flow.study.subjects.each() { subject -> 1321 if (params.get('subject_' + subject.getIdentifier() + '_group_' + eventGroup.getIdentifier() )) { 1322 // add to eventGroup 1323 eventGroup.addToSubjects(subject) 1324 } else { 1325 // remove from eventGroup 1326 eventGroup.removeFromSubjects(subject) 1327 } 1328 } 1329 } 1330 } 1331 1332 /** 1333 * Handle the wizard samples page 1334 * 1335 * @param Map LocalAttributeMap (the flow scope) 1336 * @param Map localAttributeMap (the flash scope) 1337 * @param Map GrailsParameterMap (the flow parameters = form data) 1338 * @returns boolean 1339 */ 1340 def samplePage(flow, flash, params) { 1341 def errors = false 1342 flash.errors = [:] 1343 1344 // remember the params in the flash scope 1345 flash.values = params 1346 1347 return !errors 1348 } 1527 1349 } -
trunk/grails-app/domain/dbnp/studycapturing/EventGroup.groovy
r754 r778 10 10 */ 11 11 class EventGroup implements Serializable { 12 13 static belongsTo = [parent : Study]14 15 12 String name 16 13 14 // keep an internal identifier for use in dynamic forms 15 private int identifier = 0 16 static int iterator = 0 17 18 static transients = [ "identifier", "iterator" ] 19 static belongsTo = [parent : Study] 17 20 static hasMany = [ 18 21 subjects: Subject, … … 23 26 static constraints = { 24 27 } 28 29 /** 30 * Class constructor increments that static iterator 31 * and sets the object's identifier (used in dynamic webforms) 32 * @void 33 */ 34 public EventGroup() { 35 if (!identifier) identifier = iterator++ 36 } 37 38 /** 39 * Return the identifier 40 * @return int 41 */ 42 final public int getIdentifier() { 43 return identifier 44 } 25 45 } -
trunk/grails-app/domain/dbnp/studycapturing/Study.groovy
r774 r778 100 100 } 101 101 102 103 /** 104 * Return all subjects for a specific template 105 * @param Template 106 * @return ArrayList 107 */ 108 def ArrayList<Subject> giveSubjectsForTemplate(Template template) { 109 subjects.findAll { it.template.equals(template) } 110 } 111 102 112 /** 103 113 * Return the unique Event and SamplingEvent templates that are used in this study … … 107 117 // gives trouble when asking .size() to the result 108 118 // So we also use giveTemplates here 109 TemplateEntity.giveTemplates(events + samplingEvents) 119 TemplateEntity.giveTemplates( ((events) ? events : []) + ((samplingEvents) ? samplingEvents : []) ) 120 } 121 122 123 /** 124 * Return all events and samplingEvenets for a specific template 125 * @param Template 126 * @return ArrayList 127 */ 128 def ArrayList giveEventsForTemplate(Template template) { 129 def events = events.findAll { it.template.equals(template) } 130 def samplingEvents = samplingEvents.findAll { it.template.equals(template) } 131 132 return (events) ? events : samplingEvents 110 133 } 111 134 … … 138 161 139 162 140 141 * Delete a specific subject from this study, including all its relations142 * @param subject The subject to be deleted143 * @return A String which contains a (user-readable) message describing the changes to the database144 */163 /** 164 * Delete a specific subject from this study, including all its relations 165 * @param subject The subject to be deleted 166 * @return A String which contains a (user-readable) message describing the changes to the database 167 */ 145 168 String deleteSubject(Subject subject) { 146 147 169 String msg = "Subject ${subject.name} was deleted" 148 170 … … 171 193 return msg 172 194 } 195 196 /** 197 * Delete an event from the study, including all its relations 198 * @param Event 199 * @return String 200 */ 201 String deleteEvent(Event event) { 202 String msg = "Event ${event} was deleted" 203 204 // remove event from the study 205 this.removeFromEvents(event) 206 207 // remove event from eventGroups 208 this.eventGroups.each() { eventGroup -> 209 eventGroup.removeFromEvents(event) 210 } 211 212 return msg 213 } 214 215 /** 216 * Delete a samplingEvent from the study, including all its relations 217 * @param SamplingEvent 218 * @return String 219 */ 220 String deleteSamplingEvent(SamplingEvent samplingEvent) { 221 String msg = "SamplingEvent ${samplingEvent} was deleted" 222 223 // remove event from eventGroups 224 this.eventGroups.each() { eventGroup -> 225 eventGroup.removeFromSamplingEvents(samplingEvent) 226 } 227 228 // remove event from the study 229 this.removeFromSamplingEvents(samplingEvent) 230 231 return msg 232 } 233 /** 234 * Delete an eventGroup from the study, including all its relations 235 * @param EventGroup 236 * @return String 237 */ 238 String deleteEventGroup(EventGroup eventGroup) { 239 String msg = "EventGroup ${eventGroup} was deleted" 240 241 // remove the eventGroup from the study 242 this.removeFromEventGroups(eventGroup) 243 244 return msg 245 } 173 246 } -
trunk/grails-app/domain/dbnp/studycapturing/Template.groovy
r754 r778 33 33 /** The template fields which are the members of this template. This is a List to preserve the field order */ 34 34 List fields 35 36 // keep an internal identifier for use in dynamic forms 37 private int identifier = 0 38 static int iterator = 0 39 40 // set transients 41 static transients = [ "identifier", "iterator" ] 42 35 43 static hasMany = [fields: TemplateField] 36 44 … … 70 78 // which can co-exist with the same name. See also TemplateField 71 79 // name(unique:['entity']) 80 } 81 82 /** 83 * Class constructor increments that static iterator 84 * and sets the object's identifier (used in dynamic webforms) 85 * @void 86 */ 87 public Template() { 88 if (!identifier) identifier = iterator++ 89 println ".instantiating [" + this.getClass() + "] ("+ identifier + ")" 90 } 91 92 /** 93 * Return the identifier 94 * @return int 95 */ 96 final public int getIdentifier() { 97 return identifier 72 98 } 73 99 -
trunk/grails-app/domain/dbnp/studycapturing/TemplateEntity.groovy
r754 r778 18 18 */ 19 19 abstract class TemplateEntity implements Serializable { 20 21 20 /** The actual template of this TemplateEntity instance */ 22 21 Template template … … 38 37 Map templateTermFields = [:] 39 38 39 // keep an internal identifier for use in dynamic forms 40 private int identifier = 0 41 static int iterator = 0 42 43 // set transients 44 static transients = [ "identifier", "iterator" ] 45 46 // define relationships 40 47 static hasMany = [ 41 48 templateStringFields: String, … … 54 61 55 62 static mapping = { 56 57 63 // Specify that each TemplateEntity-subclassing entity should have its own tables to store TemplateField values. 58 64 // This results in a lot of tables, but performance is presumably better because in most queries, only values of … … 324 330 return (!error) 325 331 }) 332 } 333 334 /** 335 * Class constructor increments that static iterator 336 * and sets the object's identifier (used in dynamic webforms) 337 * @void 338 */ 339 public TemplateEntity() { 340 if (!identifier) identifier = iterator++ 341 } 342 343 /** 344 * Return the identifier 345 * @return int 346 */ 347 final public int getIdentifier() { 348 return identifier 326 349 } 327 350 … … 593 616 // it is unset if it is. 594 617 if (value || value == 0 || ( field.type == TemplateFieldType.BOOLEAN && value == false)) { 595 println ".setting [" + ((super) ? super.class : '??') + "] template field: [" + fieldName + "] ([" + value.toString() + "] of type [" + value.class + "])"618 println ".setting [" + ((super) ? super.class : '??') + "] ("+getIdentifier()+") template field: [" + fieldName + "] ([" + value.toString() + "] of type [" + value.class + "])" 596 619 597 620 // set value 598 621 store[fieldName] = value 599 622 } else if (store[fieldName]) { 600 println ".unsetting [" + ((super) ? super.class : '??') + "] template field: [" + fieldName + "]"623 println ".unsetting [" + ((super) ? super.class : '??') + "] ("+getIdentifier()+") template field: [" + fieldName + "]" 601 624 602 625 // remove the item from the Map (if present) -
trunk/grails-app/views/wizard/pages/_events.gsp
r637 r778 70 70 </script> 71 71 72 <g:if test="${events}"> 73 <g:each var="eventTemplate" in="${eventTemplates}"> 74 <g:set var="showHeader" value="${true}" /> 75 <h1>${eventTemplate.value.name}</h1> 76 <div class="table"> 77 <g:each var="eventId" in="${eventTemplate.value.events}"> 78 <g:if test="${showHeader}"> 79 <g:set var="showHeader" value="${false}" /> 80 <div class="header"> 81 <div class="firstColumn">#</div> 82 <div class="firstColumn"></div> 83 <g:if test="${eventGroups}"><g:each var="eventGroup" status="g" in="${eventGroups}"> 84 <div class="column"> 85 <g:textField name="eventGroup_${g}_name" value="${eventGroup.name}" /> 86 <wizard:ajaxButton name="deleteEventGroup" src="../images/icons/famfamfam/delete.png" alt="delete this eventgroup" class="famfamfam" value="-" url="[controller:'wizard',action:'pages']" update="[success:'wizardPage',failure:'wizardError']" before="\$(\'input[name=do]\').val(${g});" afterSuccess="onWizardPage()" /> 72 <g:if test="${study.events || study.samplingEvents}"> 73 <g:each var="template" in="${study.giveAllEventTemplates()}"> 74 <g:set var="showHeader" value="${true}" /> 75 <h1>${template}</h1> 76 <div class="table"> 77 <g:each var="event" in="${study.giveEventsForTemplate(template)}"> 78 <g:if test="${showHeader}"> 79 <g:set var="showHeader" value="${false}" /> 80 <div class="header"> 81 <div class="firstColumn">#</div> 82 <div class="firstColumn"></div> 83 <g:if test="${study.eventGroups}"><g:each var="eventGroup" in="${study.eventGroups}"> 84 <div class="column"> 85 <g:textField name="eventGroup_${eventGroup.getIdentifier()}_${template.getIdentifier()}" value="${eventGroup.name}" /> 86 <wizard:ajaxButton name="deleteEventGroup" src="../images/icons/famfamfam/delete.png" alt="delete this eventgroup" class="famfamfam" value="-" url="[controller:'wizard',action:'pages']" update="[success:'wizardPage',failure:'wizardError']" before="\$(\'input[name=do]\').val(${eventGroup.getIdentifier()});" afterSuccess="onWizardPage()" /> 87 </div> 88 </g:each></g:if> 89 <div class="firstColumn"> 90 <wizard:ajaxButton name="addEventGroup" src="../images/icons/famfamfam/add.png" alt="add a new eventgroup" class="famfamfam" value="+" url="[controller:'wizard',action:'pages']" update="[success:'wizardPage',failure:'wizardError']" afterSuccess="onWizardPage()" /> 91 </div> 92 <wizard:templateColumnHeaders class="column" entity="${event}" /> 87 93 </div> 88 </g:each></g:if> 89 <div class="firstColumn"> 90 <wizard:ajaxButton name="addEventGroup" src="../images/icons/famfamfam/add.png" alt="add a new eventgroup" class="famfamfam" value="+" url="[controller:'wizard',action:'pages']" update="[success:'wizardPage',failure:'wizardError']" afterSuccess="onWizardPage()" /> 94 </g:if> 95 96 <div class="row"> 97 <div class="firstColumn">${event.getIdentifier()}</div> 98 <div class="firstColumn"> 99 <wizard:ajaxButton name="deleteEvent" src="../images/icons/famfamfam/delete.png" alt="delete this subject" class="famfamfam" value="-" url="[controller:'wizard',action:'pages']" update="[success:'wizardPage',failure:'wizardError']" before="\$(\'input[name=do]\').val(${event.getIdentifier()});" afterSuccess="onWizardPage()"/> 100 </div> 101 <g:if test="${study.eventGroups}"><g:each var="eventGroup" in="${study.eventGroups}"> 102 <div class="column"> 103 <g:if test="${eventGroup.events.find{ it == event } || eventGroup.samplingEvents.find{ it == event }}"> 104 <input type="checkbox" name="event_${event.getIdentifier()}_group_${eventGroup.getIdentifier()}" checked="checked" /> 105 </g:if><g:else> 106 <input type="checkbox" name="event_${event.getIdentifier()}_group_${eventGroup.getIdentifier()}"/> 107 </g:else> 108 </div> 109 </g:each></g:if> 110 <div class="firstColumn"></div> 111 <wizard:templateColumns class="column" entity="${event}" name="event_${event.getIdentifier()}" /> 91 112 </div> 92 <wizard:templateColumnHeaders entity="${events[ eventId ]}" class="column"/> 113 114 </g:each> 93 115 </div> 94 </g:if> 95 <div class="row"> 96 <div class="firstColumn">${eventId + 1}</div> 97 <div class="firstColumn"> 98 <wizard:ajaxButton name="deleteEvent" src="../images/icons/famfamfam/delete.png" alt="delete this subject" class="famfamfam" value="-" url="[controller:'wizard',action:'pages']" update="[success:'wizardPage',failure:'wizardError']" before="\$(\'input[name=do]\').val(${eventId});" afterSuccess="onWizardPage()"/> 99 </div> 100 <g:if test="${eventGroups}"><g:each var="eventGroup" status="j" in="${eventGroups}"> 101 <div class="column"> 102 <g:if test="${eventGroup.events.find{ it == events[ eventId ] } }"> 103 <input type="checkbox" name="event_${eventId}_group_${j}" checked="checked" /> 104 </g:if><g:else> 105 <input type="checkbox" name="event_${eventId}_group_${j}"/> 106 </g:else> 107 </div> 108 </g:each></g:if> 109 <div class="firstColumn"></div> 110 <wizard:templateColumns id="${eventId}" entity="${events[ eventId ]}" template="${events[ eventId ].template}" name="event_${eventId}" class="column" /> 116 <div class="sliderContainer"> 117 <div class="slider"></div> 111 118 </div> 112 119 </g:each> 113 </div> 114 <div class="sliderContainer"> 115 <div class="slider"></div> 116 </div> 117 </g:each> 118 </g:if> 120 </g:if> 119 121 120 122 </wizard:pageContent> -
trunk/grails-app/views/wizard/pages/_groups.gsp
r529 r778 27 27 <div class="column">Template</div> 28 28 <div class="column">Subjects</div> 29 <g:if test="${ eventGroups}"><g:each var="eventGroup" status="g" in="${eventGroups}">29 <g:if test="${study.eventGroups}"><g:each var="eventGroup" in="${study.eventGroups}"> 30 30 <div class="column"> 31 31 ${eventGroup.name} … … 43 43 </g:each></g:if> 44 44 </div> 45 <g:each var="sTemplate" in="${subjectTemplates}"> 46 <g:set var="subjectTemplate" value="${sTemplate.getValue()}"/> 45 <g:each var="template" in="${study.giveSubjectTemplates()}"> 47 46 <g:set var="showHeader" value="${true}"/> 48 <g:each var="sId" in="${subjectTemplate.subjects}"> 49 <g:set var="subjectId" value="${sId.getValue()}"/> 50 <div class="row"> 51 <div class="column"> 52 <g:if test="${showHeader}"> 53 <g:set var="showHeader" value="${false}"/> 54 ${subjectTemplate.name} 55 <div class="helpIcon"></div> 56 <div class="helpContent"> 57 <h1>${subjectTemplate.name}</h1> 58 <h2>Template Fields:</h2> 59 <g:each var="field" status="f" in="${subjects[ subjectId ].giveFields()}"> 60 ${field.name[0].toUpperCase() + field.name.substring(1)}<br/> 61 </g:each> 62 </div> 63 </g:if> 64 </div> 65 <div class="column">${subjects[subjectId].name}</div> 66 <g:if test="${eventGroups}"><g:each var="eventGroup" status="g" in="${eventGroups}"> 67 <div class="column"> 68 <g:if test="${eventGroup.subjects.find{ it == subjects[ subjectId ] } }"> 69 <input type="checkbox" name="subject_${subjectId}_group_${g}" checked="checked"/> 70 </g:if><g:else> 71 <input type="checkbox" name="subject_${subjectId}_group_${g}"/> 72 </g:else> 47 <g:each var="subject" in="${study.giveSubjectsForTemplate(template)}"> 48 <div class="row"> 49 <div class="column"> 50 <g:if test="${showHeader}"> 51 <g:set var="showHeader" value="${false}"/> 52 ${template.name} 53 <div class="helpIcon"></div> 54 <div class="helpContent"> 55 <h1>${template.name}</h1> 56 <h2>Template Fields:</h2> 57 <g:each var="field" in="${subject.giveFields()}"> 58 ${field.name[0].toUpperCase() + field.name.substring(1)}<br/> 59 </g:each> 73 60 </div> 74 </g: each></g:if>61 </g:if> 75 62 </div> 63 <div class="column">${subject.name}</div> 64 <g:if test="${study.eventGroups}"><g:each var="eventGroup" in="${study.eventGroups}"> 65 <div class="column"> 66 <g:if test="${eventGroup.subjects.find{ it == subject } }"> 67 <input type="checkbox" name="subject_${subject.getIdentifier()}_group_${eventGroup.getIdentifier()}" checked="checked"/> 68 </g:if><g:else> 69 <input type="checkbox" name="subject_${subject.getIdentifier()}_group_${eventGroup.getIdentifier()}" /> 70 </g:else> 71 </div> 72 </g:each></g:if> 73 </div> 76 74 </g:each> 77 75 </g:each> -
trunk/grails-app/views/wizard/pages/_subjects.gsp
r567 r778 37 37 </wizard:ajaxButtonElement> 38 38 39 <g:if test="${subjects}"> 40 <g:each var="sTemplate" in="${subjectTemplates}"> 41 <g:set var="showHeader" value="${true}" /> 42 <g:set var="subjectTemplate" value="${sTemplate.getValue()}" /> 43 <h1>${subjectTemplate.name} template</h1> 44 <div class="table"> 45 <g:each status="i" var="sId" in="${subjectTemplate.subjects}"> 46 <g:set var="subjectId" value="${sId.getValue()}" /> 47 <g:if test="${subjects[ subjectId ]}"> 48 <g:if test="${showHeader}"> 49 <g:set var="showHeader" value="${false}" /> 50 <div class="header"> 51 <div class="firstColumn">#</div> 52 <div class="firstColumn"></div> 53 <wizard:templateColumnHeaders entity="${subjects[ subjectId ]}" class="column" /> 39 <g:if test="${study.subjects}"> 40 <g:each var="template" in="${study.giveSubjectTemplates()}"> 41 <g:set var="showHeader" value="${true}" /> 42 <h1>${template} template</h1> 43 <div class="table"> 44 <g:each var="subject" status="s" in="${study.giveSubjectsForTemplate(template)}"> 45 <g:if test="${showHeader}"> 46 <g:set var="showHeader" value="${false}" /> 47 <div class="header"> 48 <div class="firstColumn">#</div> 49 <div class="firstColumn"></div> 50 <wizard:templateColumnHeaders class="column" entity="${subject}" /> 51 </div> 52 </g:if> 53 <div class="row"> 54 <div class="firstColumn">${subject.getIdentifier()}</div> 55 <div class="firstColumn"> 56 <wizard:ajaxButton name="delete" src="../images/icons/famfamfam/delete.png" alt="delete this subject" class="famfamfam" value="-" url="[controller:'wizard',action:'pages']" update="[success:'wizardPage',failure:'wizardError']" before="\$(\'input[name=do]\').val(${subject.getIdentifier()});" afterSuccess="onWizardPage()" /> 57 </div> 58 <wizard:templateColumns class="column" entity="${subject}" name="subject_${subject.getIdentifier()}" /> 59 </div> 60 </g:each> 54 61 </div> 55 </g:if> 56 <div class="row"> 57 <div class="firstColumn">${subjectId + 1}</div> 58 <div class="firstColumn"> 59 <wizard:ajaxButton name="delete" src="../images/icons/famfamfam/delete.png" alt="delete this subject" class="famfamfam" value="-" url="[controller:'wizard',action:'pages']" update="[success:'wizardPage',failure:'wizardError']" before="\$(\'input[name=do]\').val(${subjectId});" afterSuccess="onWizardPage()" /> 60 </div> 61 <wizard:templateColumns id="${subjectId}" entity="${subjects[ subjectId ]}" template="${subjects[ subjectId ].template}" name="subject_${subjectId}" class="column" subject="${subjects[ subjectId ]}" addDummy="true" /> 62 <div class="sliderContainer"> 63 <div class="slider" ></div> 62 64 </div> 63 </g:if>64 65 </g:each> 65 </div> 66 <div class="sliderContainer"> 67 <div class="slider" ></div> 68 </div> 69 </g:each> 70 </g:if> 66 </g:if> 71 67 72 68 </wizard:pageContent>
Note: See TracChangeset
for help on using the changeset viewer.