Changeset 316


Ignore:
Timestamp:
Mar 26, 2010, 1:02:39 PM (7 years ago)
Author:
ademcan
Message:

queryController changes

Location:
trunk/grails-app
Files:
1 added
13 edited

Legend:

Unmodified
Added
Removed
  • trunk/grails-app/controllers/SearchableController.groovy

    r247 r316  
    1 
    21/*
    32 * Copyright 2007 the original author or authors.
     
    2120 * Basic web interface for Grails Searchable Plugin
    2221 *
    23  * @author Adem and Jahn
     22 * @author Maurice Nicholson
    2423 */
    2524class SearchableController {
    2625    def searchableService
    27 
    28     def selectsample = {
    29 
    30 
    31             // produce error message here if studies don't contain samples!
    32             // redirect back or use error
    33 
    34 
    35             println "in selectsample: "
    36             params.each{println it}
    37 
    38             // prepare showing all studies selected in the previous view
    39             def selectedStudies = []
    40             def selectedStudyIds = params['selectedStudyIds']
    41 
    42             if(selectedStudyIds!=null)
    43             {
    44                  def list = selectedStudyIds.findAll(/(\d)+/)
    45                  selectedStudies = list.collect{ dbnp.studycapturing.Study.get(it) }
    46             }
    47             else
    48             {
    49                  def tmpList = []
    50                  def studyList = dbnp.studycapturing.Study.list()
    51                  selectedStudyIds = []
    52                  params.each{ key,values->
    53                      if (values=="on")  tmpList.add(key)
    54                  }
    55 
    56                  for (i in studyList)
    57                      if (tmpList.contains(i.getId().toString()))
    58                      {
    59                          selectedStudyIds.add(i.id)
    60                          selectedStudies.add(i)
    61                      }
    62            }
    63 
    64 
    65         // subgroups
    66         // provide list of subgroups depending on the type of subgrouping
    67         // selected by the user
    68         def subgroups = []
    69         def submitButton = params["submit"]  // this button's value determines the kind of subgrouping
    70 
    71         switch(submitButton)
    72         {
    73              case "Subject Groups":
    74                   render(params)
    75                   render("Subject Groups")
    76                   def studyGroups = []
    77                   if(selectedStudies!=null)
    78                   {
    79                      selectedStudies.each{ study ->
    80                          study.groups.each{ group -> studyGroups.add[group] }
    81                      }
    82                      println "study groups: "
    83                      studyGroups.each{x-> println x}
    84                   }
    85 
    86                   // testing:
    87                   // there is a lack of data in the mockup (subject groups are still missing)
    88                   // as long as there are no groups in the boot script,
    89                   // we use this
    90                   subgroups = studyGroups.size()<=0 ?
    91                        ["subject group 1","subject group 2"] : studyGroups
    92 
    93                   render(view:"selectsample",model:[selectedStudies:selectedStudies,selectedStudyIds:selectedStudyIds,subgroups:subgroups])
    94                   break
    95 
    96              case "Event Groups":
    97                   def eventGroups = []
    98                   if(selectedStudies!=null)
    99                   {
    100                     selectedStudies.each{ study ->
    101                          println study.id
    102                          println study.samplingEvents.each{ eventGroups.add(it) }
    103                     }
    104                   }
    105                   subgroups=eventGroups
    106                   render(view:"selectsample",model:[selectedStudies:selectedStudies,selectedStudyIds:selectedStudyIds,subgroups:subgroups])
    107                   break
    108 
    109              case "Starting Time Groups":
    110 
    111                   def timeGroups = []
    112                   if(selectedStudies!=null)
    113                   {
    114                     selectedStudies.each{ study ->
    115                          println study.samplingEvents.each{
    116                              def timeDiff = it.getPrettyDuration( study.startDate, it.startTime )
    117                              if( !timeGroups.contains(timeDiff) ) timeGroups.add(timeDiff)
    118                          }
    119                     }
    120                   }
    121                   subgroups=timeGroups
    122                   render("Starting Time Groups")
    123                   render(view:"selectsample",model:[selectedStudies:selectedStudies,selectedStudyIds:selectedStudyIds,subgroups:subgroups])
    124                   break
    125 
    126              case ">> Execute and continue with biomarker selection":
    127                   render("Starting Time Groups")
    128                   break
    129              case "<< Back to study selection":
    130                   break
    131         }
    132         render(view:"selectsample",model:[selectedStudies:selectedStudies,selectedStudyIds:selectedStudyIds,subgroups:subgroups])
    133     }
    134 
    135 
    13626
    13727    /**
     
    16656        render("unindexAll done")
    16757    }
    168 
    169 
    170     def subjectGroups = { render ("hello") }
    171 
    172 
    17358}
  • trunk/grails-app/controllers/dbnp/query/QueryController.groovy

    r315 r316  
    3333    }
    3434
     35        def results= {
     36          println('query controller')
     37        if (!params.q?.trim()) {
     38            return [:]
     39        }
     40        try {
     41            return [searchResult: searchableService.search(params.q, params)]
     42        } catch (SearchEngineQueryParseException ex) {
     43            return [parseException: true]
     44        }
     45    }
     46
    3547    def pagesFlow = {
    3648       
     
    3850                flow.page = 0
    3951                        flow.pages = [
     52                                [title: 'Query'],
    4053                                [title: 'Study'],
    4154                                [title: 'Samples'],
     
    5265             onRender {
    5366                println "done randering index"
     67                flow.page=1
    5468             }
    55 
    56 
    5769             on("next") {
    5870                println "clicked next in sample"
    59              } .to 'study'
    60 
     71             } .to 'inputQuery'
    6172        }       
    6273
     74        inputQuery {
     75            render(view:'_inputQuery')
     76            onRender {
     77                flow.page=1
     78            }
     79        }
    6380
    6481        study {
    6582             render( view:'_study')
    66 
     83            onRender {
     84                flow.page=2
     85             }
    6786             on("next") {
    6887                println "clicked next in sample"
    6988             } .to 'sample'
    70 
     89             on("previous"){}.to 'inputQuery'
    7190        }
    72 
    73 
    7491
    7592        sample {
    7693             render( view:'_sample')
    77 
     94            onRender {
     95                flow.page=3
     96             }
    7897             on("next") {
    7998                println "clicked next in sample"
    8099             } .to 'biomarker'
    81 
     100             on("previous"){}.to 'study'
    82101        }
    83102
     
    85104        biomarker {
    86105             render( view:'_biomarker')
    87 
     106            onRender {
     107                flow.page=4
     108             }
    88109             on("next") {
    89110                println "clicked next in sample"
    90111             } .to 'group'
    91 
     112             on("previous"){}.to 'sample'
    92113        }
    93 
    94114
    95115        group {
    96116             render( view:'_group')
    97 
     117            onRender {
     118                flow.page=5
     119             }
    98120             on("next") {
    99121                println "clicked next in sample"
    100122             } .to 'result'
    101 
     123             on("previous"){}.to 'biomarkers'
    102124        }
    103 
    104 
    105125
    106126        result {
    107127             render( view:'_result')
    108128
     129            onRender {
     130                flow.page=6
     131             }
     132             on("previous"){}.to 'group'
    109133        }
    110 
    111 
    112 
    113 
    114 
    115 
    116 
    117 
    118 
    119 
    120 
    121 
    122134
    123135    }
  • trunk/grails-app/taglib/dbnp/query/QueryTagLib.groovy

    r315 r316  
    1313 *
    1414 * Revision information:
    15  * $Rev$
    16  * $Author$
    17  * $Date$
     15 * $Rev: 299 $
     16 * $Author: duh $
     17 * $Date: 2010-03-22 14:40:35 +0100 (Mon, 22 Mar 2010) $
    1818 */
    19 
    20 class QueryTagLib extends JavascriptTagLib {
     19class WizardTagLib extends JavascriptTagLib {
     20        // define the tag namespace (e.g.: <wizard:action ... />
     21        static namespace = "wizard"
     22
     23        // define the AJAX provider to use
     24        static ajaxProvider = "jquery"
     25
     26        // define default text field width
     27        static defaultTextFieldSize = 25;
     28
     29        /**
     30         * ajaxButton tag, this is a modified version of the default
     31         * grails submitToRemote tag to work with grails webflows.
     32         * Usage is identical to submitToRemote with the only exception
     33         * that a 'name' form element attribute is required. E.g.
     34         * <wizard:ajaxButton name="myAction" value="myButton ... />
     35         *
     36         * you can also provide a javascript function to execute after
     37         * success. This behaviour differs from the default 'after'
     38         * action which always fires after a button press...
     39         *
     40         * @see http://blog.osx.eu/2010/01/18/ajaxifying-a-grails-webflow/
     41         * @see http://www.grails.org/WebFlow
     42         * @see http://www.grails.org/Tag+-+submitToRemote
     43         * @todo perhaps some methods should be moved to a more generic
     44         *        'webflow' taglib or plugin
     45         * @param Map attributes
     46         * @param Closure body
     47         */
     48        def ajaxButton = {attrs, body ->
     49                // get the jQuery version
     50                def jQueryVersion = grailsApplication.getMetadata()['plugins.jquery']
     51
     52                // fetch the element name from the attributes
     53                def elementName = attrs['name'].replaceAll(/ /, "_")
     54
     55                // javascript function to call after success
     56                def afterSuccess = attrs['afterSuccess']
     57
     58                // src parameter?
     59                def src = attrs['src']
     60                def alt = attrs['alt']
     61
     62                // generate a normal submitToRemote button
     63                def button = submitToRemote(attrs, body)
     64
     65                /**
     66                 * as of now (grails 1.2.0 and jQuery 1.3.2.4) the grails webflow does
     67                 * not properly work with AJAX as the submitToRemote button does not
     68                 * handle and submit the form properly. In order to support webflows
     69                 * this method modifies two parts of a 'normal' submitToRemote button:
     70                 *
     71                 * 1) replace 'this' with 'this.form' as the 'this' selector in a button
     72                 *    action refers to the button and / or the action upon that button.
     73                 *    However, it should point to the form the button is part of as the
     74                 *    the button should submit the form data.
     75                 * 2) prepend the button name to the serialized data. The default behaviour
     76                 *    of submitToRemote is to remove the element name altogether, while
     77                 *    the grails webflow expects a parameter _eventId_BUTTONNAME to execute
     78                 *    the appropriate webflow action. Hence, we are going to prepend the
     79                 *    serialized formdata with an _eventId_BUTTONNAME parameter.
     80                 */
     81                if (jQueryVersion =~ /^1.([1|2|3]).(.*)/) {
     82                        // fix for older jQuery plugin versions
     83                        button = button.replaceFirst(/data\:jQuery\(this\)\.serialize\(\)/, "data:\'_eventId_${elementName}=1&\'+jQuery(this.form).serialize()")
     84                } else {
     85                        // as of jQuery plugin version 1.4.0.1 submitToRemote has been modified and the
     86                        // this.form part has been fixed. Consequently, our wrapper has changed as well...
     87                        button = button.replaceFirst(/data\:jQuery/, "data:\'_eventId_${elementName}=1&\'+jQuery")
     88                }
     89
     90                // add an after success function call?
     91                // usefull for performing actions on success data (hence on refreshed
     92                // wizard pages, such as attaching tooltips)
     93                if (afterSuccess) {
     94                        button = button.replaceFirst(/\.html\(data\)\;/, '.html(data);' + afterSuccess + ';')
     95                }
     96
     97                // got an src parameter?
     98                if (src) {
     99                        def replace = 'type="image" src="' + src + '"'
     100
     101                        if (alt) replace = replace + ' alt="' + alt + '"'
     102
     103                        button = button.replaceFirst(/type="button"/, replace)
     104                }
     105
     106                // replace double semi colons
     107                button = button.replaceAll(/;{2,}/, ';')
     108
     109                // render button
     110                out << button
     111        }
     112
     113        /**
     114         * generate a ajax submit JavaScript
     115         * @see WizardTagLib::ajaxFlowRedirect
     116         * @see WizardTagLib::baseElement (ajaxSubmitOnChange)
     117         */
     118        def ajaxSubmitJs = {attrs, body ->
     119                // define AJAX provider
     120                setProvider([library: ajaxProvider])
     121
     122                // got a function name?
     123                def functionName = attrs.remove('functionName')
     124                if (functionName && !attrs.get('name')) {
     125                        attrs.name = functionName
     126                }
     127
     128                // generate an ajax button
     129                def button = this.ajaxButton(attrs, body)
     130
     131                // strip the button part to only leave the Ajax call
     132                button = button.replaceFirst(/<[^\"]*\"jQuery.ajax/, 'jQuery.ajax')
     133                button = button.replaceFirst(/return false.*/, '')
     134
     135                // change form if a form attribute is present
     136                if (attrs.get('form')) {
     137                        button = button.replaceFirst(/this\.form/,
     138                                "\\\$('" + attrs.get('form') + "')"
     139                        )
     140                }
     141
     142                out << button
     143        }
     144
     145        /**
     146         * generate ajax webflow redirect javascript
     147         *
     148         * As we have an Ajaxified webflow, the initial wizard page
     149         * cannot contain a wizard form, as upon a failing submit
     150         * (e.g. the form data does not validate) the form should be
     151         * shown again. However, the Grails webflow then renders the
     152         * complete initial wizard page into the success div. As this
     153         * ruins the page layout (a page within a page) we want the
     154         * initial page to redirect to the first wizard form to enter
     155         * the webflow correctly. We do this by emulating an ajax post
     156         * call which updates the wizard content with the first wizard
     157         * form.
     158         *
     159         * Usage: <wizard:ajaxFlowRedirect form="form#wizardForm" name="next" url="[controller:'wizard',action:'pages']" update="[success:'wizardPage',failure:'wizardError']" />
     160         * form = the form identifier
     161         * name = the action to execute in the webflow
     162         * update = the divs to update upon success or error
     163         *
     164         * OR: to generate a JavaScript function you can call yourself, use 'functionName' instead of 'name'
     165         *
     166         * Example initial webflow action to work with this javascript:
     167         * ...
     168         * mainPage {*  render(view: "/wizard/index")
     169         *      onRender {*             flow.page = 1
     170         *}*    on("next").to "pageOne"
     171         *}* ...
     172         *
     173         * @param Map attributes
     174         * @param Closure body
     175         */
     176        def ajaxFlowRedirect = {attrs, body ->
     177                // generate javascript
     178                out << '<script type="text/javascript">'
     179                out << '$(document).ready(function() {'
     180                out << ajaxSubmitJs(attrs, body)
     181                out << '});'
     182                out << '</script>'
     183        }
    21184
    22185        /**
     
    25188         * @param Closure body  (help text)
    26189         */
    27 
    28190        def pageContent = {attrs, body ->
    29191                // define AJAX provider
     
    31193
    32194                // render new body content
    33                
    34195                out << render(template: "/query/common/tabs")
    35196                out << '<div class="content">'
     
    38199                out << render(template: "/query/common/navigation")
    39200                out << render(template: "/query/common/error")
    40                
    41         }
    42 
     201        }
     202
     203        /**
     204         * generate a base form element
     205         * @param String inputElement name
     206         * @param Map attributes
     207         * @param Closure help content
     208         */
     209        def baseElement = {inputElement, attrs, help ->
     210                // work variables
     211                def description = attrs.remove('description')
     212                def addExampleElement = attrs.remove('addExampleElement')
     213                def addExample2Element = attrs.remove('addExample2Element')
     214
     215                // got an ajax onchange action?
     216                def ajaxOnChange = attrs.remove('ajaxOnChange')
     217                if (ajaxOnChange) {
     218                        if (!attrs.onChange) attrs.onChange = ''
     219
     220                        // add onChange AjaxSubmit javascript
     221                        attrs.onChange += ajaxSubmitJs(
     222                                [
     223                                        functionName: ajaxOnChange,
     224                                        url: attrs.get('url'),
     225                                        update: attrs.get('update'),
     226                                        afterSuccess: attrs.get('afterSuccess')
     227                                ],
     228                                ''
     229                        )
     230                }
     231
     232                // execute inputElement call
     233                def renderedElement = "$inputElement"(attrs)
     234
     235                // if false, then we skip this element
     236                if (!renderedElement) return false
     237
     238                // render a form element
     239                out << '<div class="element">'
     240                out << ' <div class="description">'
     241                out << description
     242                out << ' </div>'
     243                out << ' <div class="input">'
     244                out << renderedElement
     245                if (help()) {
     246                        out << '        <div class="helpIcon"></div>'
     247                }
     248
     249                // add an disabled input box for feedback purposes
     250                // @see dateElement(...)
     251                if (addExampleElement) {
     252                        def exampleAttrs = new LinkedHashMap()
     253                        exampleAttrs.name = attrs.get('name') + 'Example'
     254                        exampleAttrs.class = 'isExample'
     255                        exampleAttrs.disabled = 'disabled'
     256                        exampleAttrs.size = 30
     257                        out << textField(exampleAttrs)
     258                }
     259
     260                // add an disabled input box for feedback purposes
     261                // @see dateElement(...)
     262                if (addExample2Element) {
     263                        def exampleAttrs = new LinkedHashMap()
     264                        exampleAttrs.name = attrs.get('name') + 'Example2'
     265                        exampleAttrs.class = 'isExample'
     266                        exampleAttrs.disabled = 'disabled'
     267                        exampleAttrs.size = 30
     268                        out << textField(exampleAttrs)
     269                }
     270
     271                out << ' </div>'
     272
     273                // add help content if it is available
     274                if (help()) {
     275                        out << '  <div class="helpContent">'
     276                        out << '    ' + help()
     277                        out << '  </div>'
     278                }
     279
     280                out << '</div>'
     281        }
     282
     283        /**
     284         * render a textFieldElement
     285         * @param Map attrs
     286         * @param Closure body  (help text)
     287         */
     288        def textFieldElement = {attrs, body ->
     289                // set default size, or scale to max length if it is less than the default size
     290                if (!attrs.get("size")) {
     291                        if (attrs.get("maxlength")) {
     292                                attrs.size = ((attrs.get("maxlength") as int) > defaultTextFieldSize) ? defaultTextFieldSize : attrs.get("maxlength")
     293                        } else {
     294                                attrs.size = defaultTextFieldSize
     295                        }
     296                }
     297
     298                // render template element
     299                baseElement.call(
     300                        'textField',
     301                        attrs,
     302                        body
     303                )
     304        }
     305
     306        /**
     307         * render a select form element
     308         * @param Map attrs
     309         * @param Closure body  (help text)
     310         */
     311        def selectElement = {attrs, body ->
     312                baseElement.call(
     313                        'select',
     314                        attrs,
     315                        body
     316                )
     317        }
     318
     319        /**
     320         * render a checkBox form element
     321         * @param Map attrs
     322         * @param Closure body  (help text)
     323         */
     324        def checkBoxElement = {attrs, body ->
     325                baseElement.call(
     326                        'checkBox',
     327                        attrs,
     328                        body
     329                )
     330        }
     331
     332        /**
     333         * render a dateElement
     334         * NOTE: datepicker is attached through wizard.js!
     335         * @param Map attrs
     336         * @param Closure body  (help text)
     337         */
     338        def dateElement = {attrs, body ->
     339                // transform value?
     340                if (attrs.value instanceof Date) {
     341                        // transform date instance to formatted string (dd/mm/yyyy)
     342                        attrs.value = String.format('%td/%<tm/%<tY', attrs.value)
     343                }
     344
     345                // add 'rel' field to identity the datefield using javascript
     346                attrs.rel = 'date'
     347
     348                // set some textfield values
     349                attrs.maxlength = (attrs.maxlength) ? attrs.maxlength : 10
     350                attrs.addExampleElement = true
     351
     352                // render a normal text field
     353                //out << textFieldElement(attrs,body)
     354                textFieldElement.call(
     355                        attrs,
     356                        body
     357                )
     358        }
     359
     360        /**
     361         * render a dateElement
     362         * NOTE: datepicker is attached through wizard.js!
     363         * @param Map attrs
     364         * @param Closure body  (help text)
     365         */
     366        def timeElement = {attrs, body ->
     367                // transform value?
     368                if (attrs.value instanceof Date) {
     369                        // transform date instance to formatted string (dd/mm/yyyy)
     370                        attrs.value = String.format('%td/%<tm/%<tY %<tH:%<tM', attrs.value)
     371                }
     372
     373                // add 'rel' field to identity the field using javascript
     374                attrs.rel = 'datetime'
     375
     376                attrs.addExampleElement = true
     377                attrs.addExample2Element = true
     378                attrs.maxlength = 16
     379
     380                // render a normal text field
     381                //out << textFieldElement(attrs,body)
     382                textFieldElement.call(
     383                        attrs,
     384                        body
     385                )
     386        }
     387
     388        /**
     389         * Template form element
     390         * @param Map attributes
     391         * @param Closure help content
     392         */
     393        def speciesElement = {attrs, body ->
     394                // render template element
     395                baseElement.call(
     396                        'speciesSelect',
     397                        attrs,
     398                        body
     399                )
     400        }
     401
     402        /**
     403         * Button form element
     404         * @param Map attributes
     405         * @param Closure help content
     406         */
     407        def buttonElement = {attrs, body ->
     408                // render template element
     409                baseElement.call(
     410                        'ajaxButton',
     411                        attrs,
     412                        body
     413                )
     414        }
     415
     416        /**
     417         * render a species select element
     418         * @param Map attrs
     419         */
     420        def speciesSelect = {attrs ->
     421                // fetch the speciesOntology
     422                // note that this is a bit nasty, probably the ontologyName should
     423                // be configured in a configuration file... --> TODO: centralize species configuration
     424                def speciesOntology = Ontology.findByName('NCBI Taxonomy')
     425
     426                // fetch all species
     427                attrs.from = Term.findAllByOntology(speciesOntology)
     428
     429                // got a name?
     430                if (!attrs.name) {
     431                        // nope, use a default name
     432                        attrs.name = 'species'
     433                }
     434
     435                out << select(attrs)
     436        }
     437
     438        /**
     439         * Template form element
     440         * @param Map attributes
     441         * @param Closure help content
     442         */
     443        def templateElement = {attrs, body ->
     444                // render template element
     445                baseElement.call(
     446                        'templateSelect',
     447                        attrs,
     448                        body
     449                )
     450        }
     451
     452        /**
     453         * render a template select element
     454         * @param Map attrs
     455         */
     456        def templateSelect = {attrs ->
     457                def entity = attrs.remove('entity')
     458
     459                // fetch templates
     460                if (attrs.remove('addDummy')) {
     461                        attrs.from = ['']
     462                        if (entity && entity instanceof Class) {
     463                                Template.findAllByEntity(entity).each() {
     464                                        attrs.from[attrs.from.size()] = it
     465                                }
     466                        }
     467                } else {
     468                        attrs.from = (entity) ? Template.findAllByEntity(entity) : Template.findAll()
     469                }
     470
     471                // got a name?
     472                if (!attrs.name) {
     473                        attrs.name = 'template'
     474                }
     475
     476                // got result?
     477                if (attrs.from.size() > 0) {
     478                        out << select(attrs)
     479                } else {
     480                        // no, return false to make sure this element
     481                        // is not rendered in the template
     482                        return false
     483                }
     484        }
     485
     486        /**
     487         * Term form element
     488         * @param Map attributes
     489         * @param Closure help content
     490         */
     491        def termElement = {attrs, body ->
     492                // render term element
     493                baseElement.call(
     494                        'termSelect',
     495                        attrs,
     496                        body
     497                )
     498        }
     499
     500        /**
     501         * render a term select element
     502         * @param Map attrs
     503         */
     504        def termSelect = {attrs ->
     505                // fetch all terms
     506                attrs.from = Term.findAll()     // for now, all terms as we cannot identify terms as being treatment terms...
     507
     508                // got a name?
     509                if (!attrs.name) {
     510                        attrs.name = 'term'
     511                }
     512
     513                out << select(attrs)
     514        }
     515
     516        /**
     517         * Protocol form element
     518         * @param Map attributes
     519         * @param Closure help content
     520         */
     521        def protocolElement = {attrs, body ->
     522                // render protocol element
     523                baseElement.call(
     524                        'protocolSelect',
     525                        attrs,
     526                        body
     527                )
     528        }
     529
     530        /**
     531         * render a protocol select element
     532         * @param Map attrs
     533         */
     534        def protocolSelect = {attrs ->
     535                // fetch all protocold
     536                attrs.from = Protocol.findAll() // for now, all protocols
     537
     538                // got a name?
     539                if (!attrs.name) {
     540                        attrs.name = 'protocol'
     541                }
     542
     543                out << select(attrs)
     544        }
     545
     546        def show = {attrs ->
     547                // is object parameter set?
     548                def o = attrs.object
     549
     550                println o.getProperties();
     551                o.getProperties().each {
     552                        println it
     553                }
     554
     555                out << "!! test version of 'show' tag !!"
     556        }
     557
     558        /**
     559         * render table headers for all subjectFields in a template
     560         * @param Map attributes
     561         */
     562        def templateColumnHeaders = {attrs ->
     563                def template = attrs.remove('template')
     564
     565                // output table headers for template fields
     566                template.fields.each() {
     567                        out << '<div class="' + attrs.get('class') + '">' + it + '</div>'
     568                }
     569        }
     570
     571        /**
     572         * render table input elements for all subjectFields in a template
     573         * @param Map attributes
     574         */
     575        def templateColumns = {attrs, body ->
     576                def subject = attrs.remove('subject')
     577                def subjectId = attrs.remove('id')
     578                def template = attrs.remove('template')
     579                def intFields = subject.templateIntegerFields
     580                def stringFields = subject.templateStringFields
     581                def floatFields = subject.templateFloatFields
     582                def termFields = subject.templateTermFields
     583
     584                // output columns for these subjectFields
     585                template.fields.each() {
     586                        def fieldValue = subject.getFieldValue(it.name)
     587
     588                        // output div
     589                        out << '<div class="' + attrs.get('class') + '">'
     590
     591                        // handle field types
     592                        switch (it.type.toString()) {
     593                                case ['STRING', 'TEXT', 'INTEGER', 'FLOAT', 'DOUBLE']:
     594                                        out << textField(
     595                                                name: attrs.name + '_' + it.escapedName(),
     596                                                value: fieldValue
     597                                        )
     598                                        break
     599                                case 'STRINGLIST':
     600                                        // render stringlist subjectfield
     601                                        if (!it.listEntries.isEmpty()) {
     602                                                out << select(
     603                                                        name: attrs.name + '_' + it.escapedName(),
     604                                                        from: it.listEntries,
     605                                                        value: fieldValue
     606                                                )
     607                                        } else {
     608                                                out << '<span class="warning">no values!!</span>'
     609                                        }
     610                                        break
     611                                case 'DATE':
     612                                        // transform value?
     613                                        if (fieldValue instanceof Date) {
     614                                                if (fieldValue.getHours() == 0 && fieldValue.getMinutes() == 0) {
     615                                                        // transform date instance to formatted string (dd/mm/yyyy)
     616                                                        fieldValue = String.format('%td/%<tm/%<tY', fieldValue)
     617                                                } else {
     618                                                        // transform to date + time
     619                                                        fieldValue = String.format('%td/%<tm/%<tY %<tH:%<tM', fieldValue)
     620                                                }
     621                                        }
     622
     623                                        // output a date field (not the 'rel' which makes the
     624                                        // javascript front-end bind the jquery-ui datepicker)
     625                                        out << textField(
     626                                                name: attrs.name + '_' + it.escapedName(),
     627                                                value: fieldValue,
     628                                                rel: 'date'
     629                                        )
     630                                        break
     631                                case 'ONTOLOGYTERM':
     632                                        // @see http://www.bioontology.org/wiki/index.php/NCBO_Widgets#Term-selection_field_on_a_form
     633                                        // @see ontology-chooser.js, table-editor.js
     634                                        //out << it.getClass()
     635                                        out << textField(
     636                                                name: attrs.name + '_' + it.escapedName(),
     637                                                value: fieldValue,
     638                                                rel: 'ontology-all-name',
     639                                                size: 100
     640                                        )
     641                                        out << hiddenField(
     642                                                name: attrs.name + '_' + it.escapedName() + '-concept_id'
     643                                        )
     644                                        out << hiddenField(
     645                                                name: attrs.name + '_' + it.escapedName() + '-ontology_id'
     646                                        )
     647                                        out << hiddenField(
     648                                                name: attrs.name + '_' + it.escapedName() + '-full_id'
     649                                        )
     650                                        break
     651                                default:
     652                                        // unsupported field type
     653                                        out << '<span class="warning">!' + it.type + '</span>'
     654                                        break
     655                        }
     656
     657                        out << '</div>'
     658                }
     659        }
     660
     661        /**
     662         * render form elements based on an entity's template
     663         * @param Map attributes
     664         * @param String body
     665         */
     666        def templateElements = {attrs ->
     667                def entity = (attrs.get('entity'))
     668                def template = (entity && entity instanceof TemplateEntity) ? entity.template : null
     669
     670                // got a template?
     671                if (template) {
     672                        // render template fields
     673                        template.fields.each() {
     674                                def fieldValue = entity.getFieldValue(it.name)
     675
     676                                switch (it.type.toString()) {
     677                                        case ['STRING', 'TEXT', 'INTEGER', 'FLOAT', 'DOUBLE']:
     678                                                out << textFieldElement(
     679                                                        description: it.name,
     680                                                        name: it.escapedName(),
     681                                                        value: fieldValue
     682                                                )
     683                                                break
     684                                        case 'STRINGLIST':
     685                                                if (!it.listEntries.isEmpty()) {
     686                                                        out << selectElement(
     687                                                                description: it.name,
     688                                                                name: it.escapedName(),
     689                                                                from: it.listEntries,
     690                                                                value: fieldValue
     691                                                        )
     692                                                } else {
     693                                                        out << '<span class="warning">no values!!</span>'
     694                                                }
     695                                                break
     696                                        case 'ONTOLOGYTERM':
     697                                                // @see http://www.bioontology.org/wiki/index.php/NCBO_Widgets#Term-selection_field_on_a_form
     698                                                // @see ontology-chooser.js
     699                                                out << textFieldElement(
     700                                                        name: it.escapedName(),
     701                                                        value: fieldValue,
     702                                                        rel: 'ontology-all-name',
     703                                                        size: 100
     704                                                )
     705                                                out << hiddenField(
     706                                                        name: it.name + '-concept_id',
     707                                                        value: fieldValue
     708                                                )
     709                                                out << hiddenField(
     710                                                        name: it.escapedName() + '-ontology_id',
     711                                                        value: fieldValue
     712                                                )
     713                                                out << hiddenField(
     714                                                        name: it.escapedName() + '-full_id',
     715                                                        value: fieldValue
     716                                                )
     717                                                break
     718                                        case 'DATE':
     719                                                out << dateElement(
     720                                                        description: it.name,
     721                                                        name: it.escapedName(),
     722                                                        value: fieldValue
     723                                                )
     724                                                break
     725                                        default:
     726                                                out << "unkown field type '" + it.type + "'<br/>"
     727                                                break
     728                                }
     729                        }
     730                }
     731        }
    43732}
  • trunk/grails-app/views/query/common/_error.gsp

    r315 r316  
    1515         */
    1616%>
     17<g:if test="${errors}">
     18        <div id="wizardError" class="error" title="errors">
     19                <g:each in="${errors}" var="error" status="e">
     20                        <p>
     21                                <g:if test="${!e}"><span class="ui-icon ui-icon-alert" style="float:left; margin:0 7px 50px 0;"></span></g:if>
     22                                ${error.value['key']} &rarr; ${error.value['value']}
     23${error.value['dynamic']}
     24                        </p>
     25                </g:each>
     26        </div>
     27        <script type="text/javascript">
     28                // mark error fields
     29                <g:each in="${errors}" var="error">
     30                <g:if test="${error.value['dynamic']}">
     31                $("input:[name='${error.key}'], select:[name='${error.key}']").addClass('error');
     32                </g:if><g:else>
     33                $("input:[name='${error.key}'], select:[name='${error.key}']").parent().parent().addClass('error');
     34                </g:else>
     35                </g:each>
    1736
    18 error...
     37                // show error dialog
     38                var we = $("div#wizardError");
     39                we.dialog({
     40                        modal: true,
     41                        width: 600,
     42                        buttons: {
     43                                Ok: function() {
     44                                        $(this).dialog('close');
     45                                        we.remove();
     46                                }
     47                        }
     48                });
     49        </script>
     50</g:if>
     51
  • trunk/grails-app/views/query/common/_query.gsp

    r315 r316  
    1616%>
    1717<div id="wizard" class="wizard">
    18         <h1>Create a new study</h1>
     18        <h1>Query</h1>
    1919        <g:form action="pages" name="wizardForm" id="wizardForm">
    2020        <g:hiddenField name="do" value="" />
  • trunk/grails-app/views/query/mainPage.gsp

    r314 r316  
     1
    12<html>
    2     <head>
    3       <title>Generic Study Capture Framework - Query studies</title>
    4       <meta name="layout" content="main" />
    5       <script type="text/javascript">
    6         $(function() {
    7                 $("#tabs").tabs();
    8         });
    9       </script>
    10     </head>
    11     <body>
    12 
    13 aaaaaaa
    14 
    15 
    16 
    17 <div id="wizard" class="wizard">
    18         <h1>Create a new study</h1>
    19         <g:form action="pages" name="wizardForm" id="wizardForm">
    20         <g:hiddenField name="do" value="" />
    21                 <div id="wizardPage">
    22                         <wizard:ajaxFlowRedirect form="form#wizardForm" name="next" url="[controller:'query',action:'pages']" update="[success:'wizardPage',failure:'wizardError']" />
    23                 </div>
    24         </g:form>
    25 </div>
    26 
    27 
    28 
    29 
    30   </body>
     3<head>
     4        <meta name="layout" content="main"/><g:if env="production">
     5        <link rel="stylesheet" href="${resource(dir: 'css', file: 'wizard.min.css')}"/>
     6        <script type="text/javascript" src="${resource(dir: 'js', file: 'jquery.qtip-1.0.0-rc3.min.js')}"></script>
     7        <script type="text/javascript" src="${resource(dir: 'js', file: 'swfobject.min.js')}"></script>
     8        <script type="text/javascript" src="${resource(dir: 'js', file: 'table-editor.min.js')}"></script>
     9        <script type="text/javascript" src="${resource(dir: 'js', file: 'ontology-chooser.min.js')}"></script>
     10        <script type="text/javascript" src="${resource(dir: 'js', file: 'timepicker-0.2.1.min.js')}"></script>
     11        <script type="text/javascript" src="${resource(dir: 'js', file: 'wizard.min.js')}"></script>
     12</g:if><g:else>
     13        <link rel="stylesheet" href="${resource(dir: 'css', file: 'wizard.css')}"/>
     14        <script type="text/javascript" src="${resource(dir: 'js', file: 'jquery.qtip-1.0.0-rc3.min.js')}"></script>
     15        <script type="text/javascript" src="${resource(dir: 'js', file: 'swfobject.js')}"></script>
     16        <script type="text/javascript" src="${resource(dir: 'js', file: 'table-editor.js')}"></script>
     17        <script type="text/javascript" src="${resource(dir: 'js', file: 'ontology-chooser.js')}"></script>
     18        <script type="text/javascript" src="${resource(dir: 'js', file: 'timepicker-0.2.1.js')}"></script>
     19        <script type="text/javascript" src="${resource(dir: 'js', file: 'wizard.js')}"></script>
     20</g:else>
     21</head>
     22<body>
     23<g:render template="common/query"/>
     24</body>
    3125</html>
  • trunk/grails-app/views/query/pages/_biomarker.gsp

    r314 r316  
    1 biomarker
     1<wizard:pageContent>
     2        Biomarkers
     3</wizard:pageContent>
     4
  • trunk/grails-app/views/query/pages/_group.gsp

    r314 r316  
    1 group
     1<wizard:pageContent>
     2    Group
     3</wizard:pageContent>
     4
  • trunk/grails-app/views/query/pages/_result.gsp

    r314 r316  
    1 result
     1<wizard:pageContent>
     2        Results
     3</wizard:pageContent>
     4
  • trunk/grails-app/views/query/pages/_sample.gsp

    r314 r316  
    1 sample
     1<wizard:pageContent>
     2
     3  Select samples
     4</wizard:pageContent>
  • trunk/grails-app/views/query/pages/_study.gsp

    r314 r316  
    11<wizard:pageContent>
    2         hello world
     2        Study
    33</wizard:pageContent>
  • trunk/grails-app/views/study/list_extended.gsp

    r299 r316  
    4444
    4545    <% if (selectedStudies.size()>0) {%>
    46 
    4746
    4847        <div id="tabs">
     
    225224
    226225          <% def protocol_list = [] %>
    227           <% def tmp_protocol = stud.events.eventDescription.protocol.get(0) %>
    228           <% def tmpBis_protocol = stud.samplingEvents.eventDescription.protocol.get(0) %>
    229           <% protocol_list.add(tmp_protocol) %>
    230           <% protocol_list.add(tmpBis_protocol) %>
    231 
    232           <g:each in="${stud.events.eventDescription.protocol}" var="s">
    233           <% if (tmp_protocol!=s) { %>
    234             <% protocol_list.add(s) %>
    235             <%}%>
    236           </g:each>
    237 
    238  <g:each in="${stud.samplingEvents.eventDescription.protocol}" var="s">
    239           <% if (tmpBis_protocol!=s) { %>
    240             <% protocol_list.add(s) %>
    241             <%}%>
    242           </g:each>
     226          <% protocol_list.add(stud.events.eventDescription.protocol.unique()) %>
     227          <% protocol_list.addAll(stud.samplingEvents.eventDescription.protocol.unique()) %>
    243228
    244229          <g:each in="${protocol_list}" var="protocol">
     
    292277          <td>${e.getPrettyDuration()}</td>
    293278           <td><g:checkBox name="event" disabled="${true}" value="${false}"/></td>
    294           <g:each in="${e.eventDescription.protocol.parameters}" var="param">
    295           <td>
    296             ${param.name} : ${param.listEntries}
    297           </td>
    298             </g:each>
    299             </tr>
     279
     280           </tr>
    300281          </g:each>
    301282
  • trunk/grails-app/views/study/show.gsp

    r299 r316  
    371371    </div>
    372372  </div>
    373 </div>
    374373</body>
    375374</html>
Note: See TracChangeset for help on using the changeset viewer.