source: trunk/grails-app/controllers/dbnp/studycapturing/WizardController.groovy @ 192

Last change on this file since 192 was 192, checked in by duh, 10 years ago
  • temporary commit
  • rewriting grouping javascript
  • uncommented the bootstrap part I commented previously, it appeared to be a grails cache issue that was resolved after issuing a 'grails clean' command...
  • Property svn:keywords set to
    Date
    Author
    Rev
File size: 7.2 KB
Line 
1package dbnp.studycapturing
2
3import dbnp.studycapturing.*
4import dbnp.data.*
5import grails.converters.*
6
7/**
8 * Wizard Controler
9 *
10 * The wizard controller handles the handeling of pages and data flow
11 * through the study capturing wizard.
12 *
13 * @author Jeroen Wesbeek
14 * @since 20100107
15 * @package studycapturing
16 *
17 * Revision information:
18 * $Rev: 192 $
19 * $Author: duh $
20 * $Date: 2010-02-11 16:47:49 +0000 (do, 11 feb 2010) $
21 */
22class WizardController {
23        /**
24         * index method, redirect to the webflow
25         * @void
26         */
27        def index = {
28                /**
29                 * Do you believe it in your head?
30                 * I can go with the flow
31                 * Don't say it doesn't matter (with the flow) matter anymore
32                 * I can go with the flow (I can go)
33                 * Do you believe it in your head?
34                 */
35                redirect(action: 'pages')
36        }
37
38        /**
39         * WebFlow definition
40         * @see http://grails.org/WebFlow
41         * @void
42         */
43        def pagesFlow = {
44                // start the flow
45                onStart {
46                        // define flow variables
47                        flow.page = 0
48                        flow.pages = [
49                                [title: 'Study'],               // study
50                                [title: 'Subjects'],    // subjects
51                                [title: 'Groups'],              // groups
52                                [title: 'Form elements demo page']
53                        ]
54
55                }
56
57                // render the main wizard page which immediately
58                // triggers the 'next' action (hence, the main
59                // page dynamically renders the study template
60                // and makes the flow jump to the study logic)
61                mainPage {
62                        render(view: "/wizard/index")
63                        onRender {
64                                flow.page = 1
65                        }
66                        on("next").to "study"
67                }
68
69                // render and handle the study page
70                study {
71                        render(view: "_study")
72                        onRender {
73                                flow.page = 1
74                        }
75                        on("next") {
76                                // create date instance from date string?
77                                // @see WizardTagLibrary::dateElement{...}
78                                if (params.get('startDate')) {
79                                        params.startDate = new Date().parse("d/M/yyyy", params.get('startDate').toString())
80                                }
81
82                                // if a template is selected, get template instance
83                                if (params.get('template')) {
84                                        params.template = Template.findByName(params.get('template'))
85                                }
86
87                                // create a study instance
88                                flow.study = new Study(params)
89
90                                // validate study
91                                if (flow.study.validate()) {
92                                        success()
93                                } else {
94                                        // validation failed, feedback errors
95                                        flash.errors = new LinkedHashMap()
96                                        this.appendErrors(flow.study, flash.errors)
97                                        error()
98                                }
99                        }.to "subjects"
100                }
101
102                // render and handle subjects page
103                subjects {
104                        render(view: "_subjects")
105                        onRender {
106                                flow.page = 2
107
108                                if (!flow.subjects) {
109                                        flow.subjects = []
110                                }
111                        }
112                        on("add") {
113                                // fetch species by name (as posted by the form)
114                                def speciesTerm = Term.findByName(params.addSpecies)
115
116                                // add x subject of species y
117                                (params.addNumber as int).times {
118                                        def increment = flow.subjects.size()
119                                        flow.subjects[increment] = new Subject(
120                                                name: 'Subject ' + (increment + 1),
121                                                species: speciesTerm,
122                                                template: flow.study.template
123                                        )
124                                }
125                        }.to "subjects"
126                        on("next") {
127                                flash.errors = new LinkedHashMap()
128
129                                // check if we have at least one subject
130                                // and check form data
131                                if (flow.subjects.size() < 1) {
132                                        // append error map
133                                        this.appendErrorMap(['subjects': 'You need at least to create one subject for your study'], flash.errors)
134                                        error()
135                                } else if (!this.handleSubjects(flow, flash, params)) {
136                                        error()
137                                } else {
138                                        success()
139                                }
140                        }.to "groups"
141                        on("previous") {
142                                flash.errors = new LinkedHashMap()
143
144                                // handle form data
145                                if (!this.handleSubjects(flow, flash, params)) {
146                                        error()
147                                } else {
148                                        success()
149                                }
150                        }.to "study"
151                }
152
153                // render and handle group page
154                groups {
155                        render(view: "_groups")
156                        onRender {
157                                flow.page = 3
158
159                                if (!flow.groups) {
160                                        flow.groups = []
161                                }
162                        }
163                        on("add") {
164                                def increment = flow.groups.size()
165                                flow.groups[increment] = new SubjectGroup(params)
166                        }.to "groups"
167                        on("next") {
168                                // TODO
169                        }.to "groups"
170                        on("previous") {
171                                // TODO
172                        }.to "subjects"
173                }
174
175                // render page three
176                demo {
177                        render(view: "_three")
178                        onRender {
179                                flow.page = 4
180                        }
181                        on("previous") {
182                                // TODO
183                        }.to "groups"
184                }
185        }
186
187        /**
188         * re-usable code for handling subject form data in a web flow
189         * @param Map LocalAttributeMap (the flow scope)
190         * @param Map localAttributeMap (the flash scope)
191         * @param Map GrailsParameterMap (the flow parameters = form data)
192         * @returns boolean
193         */
194        def handleSubjects(flow, flash, params) {
195                def names = new LinkedHashMap();
196                def errors = false;
197                def id = 0;
198
199                // iterate through subjects
200                flow.subjects.each() {
201                        // store subject properties
202                        def name = params.get('subject_' + id + '_name')
203                        it.name = params.get('subject_' + id + '_name')
204                        it.species = Term.findByName(params.get('subject_' + id + '_species'))
205
206                        // remember name and check for duplicates
207                        if (!names[it.name]) {
208                                names[it.name] = [count: 1, first: 'subject_' + id + '_name']
209                        } else {
210                                // duplicate name found, set error flag
211                                names[it.name]['count']++
212
213                                // second occurence?
214                                if (names[it.name]['count'] == 2) {
215                                        // yeah, also mention the first
216                                        // occurrence in the error message
217                                        this.appendErrorMap([[names[it.name]['first']]: 'The subject name needs to be unique!'], flash.errors)
218                                }
219
220                                // add to error map
221                                this.appendErrorMap([['subject_' + id + '_name']: 'The subject name needs to be unique!'], flash.errors)
222                                errors = true
223                        }
224
225                        // clear lists
226                        def stringList = new LinkedHashMap();
227                        def intList = new LinkedHashMap();
228                        def floatList = new LinkedHashMap();
229                        def termList = new LinkedHashMap();
230
231                        // get all template fields
232                        flow.study.template.subjectFields.each() {
233                                // valid type?
234                                if (!it.type) throw new NoSuchFieldException("Field name ${fieldName} not recognized")
235
236                                // get value
237                                def value = params.get('subject_' + id + '_' + it.name);
238                                if (value) {
239                                        // add to template parameters
240                                        switch (it.type) {
241                                                case 'STRINGLIST':
242                                                        stringList[it.name] = value
243                                                        break;
244                                                case 'INTEGER':
245                                                        intList[it.name] = value
246                                                        break;
247                                                case 'FLOAT':
248                                                        floatList[it.name] = value
249                                                        break;
250                                                default:
251                                                        // unsupported type?
252                                                        throw new NoSuchFieldException("Field type ${it.type} not recognized")
253                                                        break;
254                                        }
255                                }
256                        }
257
258                        // set field data
259                        it.templateStringFields = stringList
260                        it.templateIntegerFields = intList
261                        it.templateFloatFields = floatList
262                        it.templateTermFields = termList
263
264                        // validate subject
265                        if (!it.validate()) {
266                                errors = true
267                                println id + ' :: ' + it.errors.getAllErrors()
268                                this.appendErrors(it, flash.errors)
269                        }
270
271                        id++;
272                }
273
274                return !errors
275        }
276
277        /**
278         * transform domain class validation errors into a human readable
279         * linked hash map
280         * @param object validated domain class
281         * @returns object  linkedHashMap
282         */
283        def getHumanReadableErrors(object) {
284                def errors = new LinkedHashMap()
285
286                object.errors.getAllErrors().each() {
287                        errors[it.getArguments()[0]] = it.getDefaultMessage()
288                }
289
290                return errors
291        }
292
293        /**
294         * append errors of a particular object to a map
295         * @param object
296         * @param map linkedHashMap
297         * @void
298         */
299        def appendErrors(object, map) {
300                this.appendErrorMap(this.getHumanReadableErrors(object), map)
301        }
302
303        /**
304         * append errors of one map to another map
305         * @param map linkedHashMap
306         * @param map linkedHashMap
307         * @void
308         */
309        def appendErrorMap(map, mapToExtend) {
310                map.each() {key, value ->
311                        mapToExtend[key] = value
312                }
313        }
314}
Note: See TracBrowser for help on using the repository browser.