Changeset 1482 for trunk/grails-app


Ignore:
Timestamp:
Feb 2, 2011, 4:40:22 PM (10 years ago)
Author:
robert@…
Message:

Implemented saving of queries

Location:
trunk/grails-app
Files:
3 added
10 edited

Legend:

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

    r1440 r1482  
    525525
    526526                        def user = AuthenticationService.getRemotelyLoggedInUser( params.consumer, params.token );
    527                         render( ['isOwner': study.isOwner(user), 'canRead': study.canRead(user), 'canWrite': study.canWrite(user)] as JSON )
     527                        def auth = ['isOwner': study.isOwner(user), 'canRead': study.canRead(user), 'canWrite': study.canWrite(user)];
     528                        log.trace "Authorization for study " + study.title + " and user " + user.username + ": " + auth
     529                        render auth as JSON;
    528530                } else {
    529531                        response.sendError(400)
  • trunk/grails-app/controllers/dbnp/authentication/LogoutController.groovy

    r1430 r1482  
    1616                }
    1717                // TODO  put any pre-logout code here
     18               
     19                // Remove all queries from session
     20                session.queries = [];
    1821        }
    1922
     
    3033                        redirect uri: SpringSecurityUtils.securityConfig.logout.filterProcessesUrl // '/j_spring_security_logout'
    3134                }
     35
     36                // Remove all queries from session
     37                session.queries = [];
    3238        }
    3339}
  • trunk/grails-app/controllers/dbnp/query/AdvancedQueryController.groovy

    r1458 r1482  
    1212class AdvancedQueryController {
    1313        def moduleCommunicationService;
     14        def authenticationService
     15
     16        def entitiesToSearchFor = [ 'Study': 'Studies', 'Sample': 'Samples']
    1417       
    15         def entitiesToSearchFor = [ 'Study': 'Studies', 'Sample': 'Samples']
    16     def index = {
    17                 [entitiesToSearchFor: entitiesToSearchFor, searchableFields: getSearchableFields()]
    18     }
     18        /**
     19         * Shows search screen
     20         */
     21        def index = {
     22                // Check whether criteria have been given before
     23                def criteria = [];
     24                if( params.criteria ) {
     25                        criteria = parseCriteria( params.criteria, false )
     26                }
     27                [entitiesToSearchFor: entitiesToSearchFor, searchableFields: getSearchableFields(), criteria: criteria]
     28        }
    1929
    2030        /**
     
    3848                // Create a search object and let it do the searching
    3949                Search search;
    40                 String view;
     50                String view = determineView( params.entity );
    4151                switch( params.entity ) {
    42                         case "Study":   search = new StudySearch();             view = "studyresults";  break;
    43                         case "Sample":  search = new SampleSearch();    view = "sampleresults"; break;
    44                        
    45                         // This exception will only be thrown if the entitiesToSearchFor contains more entities than 
     52                        case "Study":   search = new StudySearch();     break;
     53                        case "Sample":  search = new SampleSearch(); break;
     54
     55                        // This exception will only be thrown if the entitiesToSearchFor contains more entities than
    4656                        // mentioned in this switch structure.
    47                         default:                throw new Exception( "Can't search for entities of type " + params.entity );   
    48                 }
    49                
     57                        default:                throw new Exception( "Can't search for entities of type " + params.entity );
     58                }
    5059                search.execute( parseCriteria( params.criteria ) );
    51                
    52                 render( view: view, model: [search: search] );
     60
     61                // Save search in session
     62                def queryId = saveSearch( search );
     63                render( view: view, model: [search: search, queryId: queryId] );
     64        }
     65
     66        /**
     67         * Removes a specified search from session
     68         * @param       id      queryId of the search to discard
     69         */
     70        def discard = {
     71                Integer queryId
     72                try {
     73                        queryId = params.id as Integer
     74                } catch( Exception e ) {
     75                        flash.error = "Incorrect search ID given to discard"
     76                        redirect( action: "index" );
     77                        return
     78                }
     79
     80                discardSearch( queryId );
     81                flash.message = "Search has been discarded"
     82                redirect( action: "list" );
     83        }
     84
     85        /**
     86         * Shows a specified search from session
     87         * @param       id      queryId of the search to show
     88         */
     89        def show = {
     90                Integer queryId
     91                try {
     92                        queryId = params.id as Integer
     93                } catch( Exception e ) {
     94                        flash.error = "Incorrect search ID given to show"
     95                        redirect( action: "index" );
     96                        return
     97                }
     98
     99                // Retrieve the search from session
     100                Search s = retrieveSearch( queryId );
     101                if( !s ) {
     102                        flash.message = "Specified search could not be found"
     103                        redirect( action: "index" );
     104                        return;
     105                }
     106
     107                // Determine which view to show
     108                def view = determineView( s.entity );
     109                render( view: view, model: [search: s, queryId: queryId] );
     110        }
     111
     112        /**
     113         * Shows a list of searches that have been saved in session
     114         * @param       id      queryId of the search to show
     115         */
     116        def list = {
     117                def searches = listSearches();
     118
     119                if( !searches || searches.size() == 0 ) {
     120                        flash.message = "No previous searches found";
     121                        redirect( action: "index" );
     122                        return;
     123                }
     124                [searches: searches]
    53125        }
    54126       
     127        /**
     128         * Shows a search screen where the user can search within the results of another search
     129         * @param       id      queryId of the search to search in
     130         */
     131        def searchIn = {
     132                Integer queryId
     133                try {
     134                        queryId = params.id as Integer
     135                } catch( Exception e ) {
     136                        flash.error = "Incorrect search ID given to show"
     137                        redirect( action: "index" );
     138                        return
     139                }
     140
     141                // Retrieve the search from session
     142                Search s = retrieveSearch( queryId );
     143                if( !s ) {
     144                        flash.message = "Specified search could not be found"
     145                        redirect( action: "index" );
     146                        return;
     147                }
     148
     149                redirect( action: "index", params: [ "criteria.0.entityfield": s.entity, "criteria.0.operator": "in", "criteria.0.value": queryId ])
     150        }
     151
     152        protected String determineView( String entity ) {
     153                switch( entity ) {
     154                        case "Study":   return "studyresults";  break;
     155                        case "Sample":  return "sampleresults"; break;
     156                        default:                return "results"; break;
     157                }
     158        }
     159
    55160        /**
    56161         * Returns a map of entities with the names of the fields the user can search on
     
    59164        protected def getSearchableFields() {
    60165                def fields = [:];
    61                
     166
    62167                // Retrieve all local search fields
    63168                getEntities().each {
    64169                        def entity = getEntity( 'dbnp.studycapturing.' + it );
    65                        
     170
    66171                        if( entity ) {
    67172                                def domainFields = entity.giveDomainFields();
    68173                                def templateFields = TemplateField.findAllByEntity( entity )
    69                                
     174
    70175                                def fieldNames = ( domainFields + templateFields ).collect { it.name }.unique() + 'Template'
    71                                
     176
    72177                                fields[ it ] = fieldNames.sort { a, b -> a[0].toUpperCase() + a[1..-1] <=> b[0].toUpperCase() + b[1..-1] };
    73178                        }
    74179                }
    75                
     180
    76181                // Loop through all modules and check which fields are searchable
    77182                // Right now, we just combine the results for different entities
     
    81186                                def json = moduleCommunicationService.callModuleRestMethodJSON( module.url, callUrl );
    82187                                def moduleFields = [];
    83                                 entitiesToSearchFor.each { entity ->                                   
     188                                entitiesToSearchFor.each { entity ->
    84189                                        if( json[ entity.key ] ) {
    85190                                                json[ entity.key ].each { field ->
     
    88193                                        }
    89194                                }
    90                                
     195
    91196                                // Remove 'module' from module name
    92197                                def moduleName = module.name.replace( 'module', '' ).trim()
    93                                
     198
    94199                                fields[ moduleName ] = moduleFields.unique();
    95200                        } catch( Exception e ) {
     
    97202                        }
    98203                }
    99                
     204
    100205                return fields;
    101206        }
    102        
     207
    103208        /**
    104209         * Parses the criteria from the query form given by the user
     
    115220         *              1.field: d
    116221         *      ]
    117          *
    118          * @return      List with Criterion objects
    119          */
    120         protected List parseCriteria( def c ) {
     222         * @param parseSearchIds        Determines whether searches are returned instead of their ids
     223         * @return                                      List with Criterion objects
     224         */
     225        protected List parseCriteria( def formCriteria, def parseSearchIds = true ) {
    121226                ArrayList list = [];
    122                
     227                flash.error = "";
    123228                // Loop through all keys of c and remove the non-numeric ones
    124                 c.each {
    125                         if( it.key ==~ /[0-9]+/ ) {
    126                                 def formCriterion = it.value;
     229                for( c in formCriteria ) {
     230                        if( c.key ==~ /[0-9]+/ ) {
     231                                def formCriterion = c.value;
     232                               
    127233                                Criterion criterion = new Criterion();
    128                                
     234
    129235                                // Split entity and field
    130236                                def field = formCriterion.entityfield?.split( /\./ );
    131                                
    132237                                if( field.size() > 1 ) {
    133238                                        criterion.entity = field[0].toString();
    134239                                        criterion.field = field[1].toString();
    135240                                } else {
    136                                         criterion.entity = null;
    137                                         criterion.field = field;
     241                                        criterion.entity = field[0];
     242                                        criterion.field = null;
     243                                }
     244
     245                                // Convert operator string to Operator-enum field
     246                                try {
     247                                        criterion.operator = Criterion.parseOperator( formCriterion.operator );
     248                                } catch( Exception e) {
     249                                        println "Operator " + formCriterion.operator + " could not be parsed: " + e.getMessage();
     250                                        flash.error += "Criterion could not be used: operator " + formCriterion.operator + " is not valid.<br />\n";
     251                                        continue;
    138252                                }
    139253                               
    140                                 // Convert operator string to Operator-enum field
    141                                 switch( formCriterion.operator ) {
    142                                         case ">=":                      criterion.operator = Operator.gte; break;
    143                                         case ">":                       criterion.operator = Operator.gt;  break;
    144                                         case "<":                       criterion.operator = Operator.lte; break;
    145                                         case "<=":                      criterion.operator = Operator.lt;  break;
    146                                         case "contains":        criterion.operator = Operator.contains; break;
    147                                         case "equals":          criterion.operator = Operator.equals; break;
     254                                // Special case of the 'in' operator
     255                                if( criterion.operator == Operator.insearch ) {
     256                                        Search s
     257                                        try {
     258                                                s = retrieveSearch( Integer.parseInt( formCriterion.value ) );
     259                                        } catch( Exception e ) {}
     260                                       
     261                                        if( !s ) {
     262                                                flash.error += "Can't search within previous query: query not found";
     263                                                continue;
     264                                        }
     265                                       
     266                                        if( parseSearchIds ) {
     267                                                criterion.value = s
     268                                        } else {
     269                                                criterion.value = s.id
     270                                        }
     271                                } else {
     272                                        // Copy value
     273                                        criterion.value = formCriterion.value;
    148274                                }
    149275                               
    150                                 // Copy value
    151                                 criterion.value = formCriterion.value;
    152                                  
    153276                                list << criterion;
    154277                        }
    155278                }
    156                
     279
    157280                return list;
    158281        }
    159        
     282
    160283        /**
    161284         * Returns all entities for which criteria can be entered
     
    165288                return [ 'Study', 'Subject', 'Sample', 'Event', 'SamplingEvent', 'Assay' ]
    166289        }
    167        
    168         /**
    169         * Creates an object of the given entity.
    170         *
    171         * @return False if the entity is not a subclass of TemplateEntity
    172         */
    173    protected def getEntity( entityName ) {
    174            // Find the templates
    175            def entity
    176            try {
    177                    entity = Class.forName(entityName, true, this.getClass().getClassLoader())
    178 
    179                    // succes, is entity an instance of TemplateEntity?
    180                    if (entity.superclass =~ /TemplateEntity$/ || entity.superclass.superclass =~ /TemplateEntity$/) {
    181                            return entity;
    182                    } else {
    183                            return false;
    184                    }
    185            } catch( ClassNotFoundException e ) {
    186                         log.error "Class " + entityName + " not found: " + e.getMessage()
    187                         return null;
    188            }
    189 
    190    }
    191 
     290
     291        /**
     292         * Creates an object of the given entity.
     293         *
     294         * @return False if the entity is not a subclass of TemplateEntity
     295         */
     296        protected def getEntity( entityName ) {
     297                // Find the templates
     298                def entity
     299                try {
     300                        entity = Class.forName(entityName, true, this.getClass().getClassLoader())
     301
     302                        // succes, is entity an instance of TemplateEntity?
     303                        if (entity.superclass =~ /TemplateEntity$/ || entity.superclass.superclass =~ /TemplateEntity$/) {
     304                                return entity;
     305                        } else {
     306                                return false;
     307                        }
     308                } catch( ClassNotFoundException e ) {
     309                        log.error "Class " + entityName + " not found: " + e.getMessage()
     310                        return null;
     311                }
     312
     313        }
     314
     315
     316        /***************************************************************************
     317         *
     318         * Methods for saving results in session
     319         *
     320         ***************************************************************************/
     321
     322        /**
     323         * Saves the given search in session. Any search with the same criteria will be overwritten
     324         * 
     325         * @param s             Search to save
     326         * @return              Id of the search for later reference
     327         */
     328        protected int saveSearch( Search s ) {
     329                if( !session.queries )
     330                        session.queries = [:]
     331
     332                // First check whether a search with the same criteria is already present
     333                def previousSearch = retrieveSearchByCriteria( s.getCriteria() );
     334               
     335                def id
     336                if( previousSearch ) {
     337                        id = previousSearch.id;
     338                } else {
     339                        // Determine unique id
     340                        id = ( session.queries*.key.max() ?: 0 ) + 1;
     341                }
     342               
     343                s.id = id;
     344                session.queries[ id ] = s;
     345
     346                println "On saveSearch: " + session.queries;
     347                return id;
     348        }
     349
     350        /**
     351         * Retrieves a search from session with the same criteria as given
     352         * @param criteria      List of criteria to search for
     353         * @return                      Search that has this criteria, or null if no such search is found.
     354         */
     355        protected Search retrieveSearchByCriteria( List criteria ) {
     356                if( !session.queries )
     357                        return null
     358               
     359                if( !criteria )
     360                        return null
     361                       
     362                for( query in session.queries ) {
     363                        def key = query.key;
     364                        def value = query.value;
     365
     366                        if( value.criteria && value.criteria.containsAll( criteria ) && criteria.containsAll( value.criteria ) ) {
     367                                return value;
     368                        }
     369                }
     370
     371                return null;
     372        }
     373
     374
     375        /**
     376         * Retrieves a search from session
     377         * @param id    Id of the search
     378         * @return              Search that belongs to this ID or null if no search is found
     379         */
     380        protected Search retrieveSearch( int id ) {
     381                if( !session.queries || !session.queries[ id ] )
     382                        return null
     383
     384                if( !( session.queries[ id ] instanceof Search ) )
     385                        return null;
     386
     387                println "On retrieveSearch: " + session.queries;
     388                return (Search) session.queries[ id ]
     389        }
     390
     391        /**
     392         * Removes a search from session
     393         * @param id    Id of the search
     394         * @return      Search that belonged to this ID or null if no search is found
     395         */
     396        protected Search discardSearch( int id ) {
     397                if( !session.queries || !session.queries[ id ] )
     398                        return null
     399
     400                def sessionSearch = session.queries[ id ];
     401
     402                session.queries.remove( id );
     403
     404                println "On discardSearch: " + session.queries;
     405                if( !( sessionSearch instanceof Search ) )
     406                        return null;
     407
     408                return (Search) sessionSearch
     409        }
     410
     411        /**
     412         * Retrieves a list of searches from session
     413         * @return      List of searches from session
     414         */
     415        protected List listSearches() {
     416                if( !session.queries )
     417                        return []
     418
     419                return session.queries*.value.toList()
     420        }
    192421}
  • trunk/grails-app/domain/dbnp/studycapturing/Sample.groovy

    r1457 r1482  
    129129                return name
    130130        }
     131
     132        /**
     133        * Basic equals method to check whether objects are equals, by comparing the ids
     134        * @param o              Object to compare with
     135        * @return               True iff the id of the given Sample is equal to the id of this Sample
     136        */
     137   public boolean equals( Object o ) {
     138           if( o == null )
     139                   return false;
     140                   
     141           if( !( o instanceof Sample ) )
     142                   return false
     143           
     144           Sample s = (Sample) o;
     145           
     146           return this.id == s.id
     147   }
    131148       
    132149        /**
  • trunk/grails-app/domain/dbnp/studycapturing/Study.groovy

    r1457 r1482  
    522522                return this.studyUUID;
    523523        }
     524       
     525        /**
     526         * Basic equals method to check whether objects are equals, by comparing the ids
     527         * @param o             Object to compare with
     528         * @return              True iff the id of the given Study is equal to the id of this Study
     529         */
     530        public boolean equals( Object o ) {
     531                if( o == null )
     532                        return false;
     533                       
     534                if( !( o instanceof Study ) )
     535                        return false
     536               
     537                Study s = (Study) o;
     538               
     539                return this.id == s.id
     540        }
    524541
    525542        // Send messages to modules about changes in this study
  • trunk/grails-app/services/dbnp/modules/ModuleCommunicationService.groovy

    r1458 r1482  
    4848         * @return
    4949         */
    50         def invalidateStudy( Study study ) {
     50        def invalidateStudy( def study ) {
    5151                moduleNotificationService.invalidateStudy( study );
    5252        }
     
    113113                try {
    114114                        def textResponse = url.toURL().getText()
    115                         println "GSCF call to " + consumer + " URL: " + url
    116                         println "GSCF response: " + textResponse
     115                        log.trace "GSCF call to " + consumer + " URL: " + url
     116                        log.trace "GSCF response: " + textResponse
    117117                        restResponse = JSON.parse( textResponse )
    118118                } catch (Exception e) {
  • trunk/grails-app/views/advancedQuery/index.gsp

    r1430 r1482  
    66        <link rel="stylesheet" href="<g:resource dir="css" file="advancedQuery.css" />" type="text/css"/>
    77        <g:javascript src="advancedQuery.js" />
     8        <script type="text/javascript">
     9                // Make a list of fields to search in
     10                var queryableFields = [
     11                        <g:set var="j" value="${0}" />
     12                        <g:each in="${searchableFields}" var="entity">
     13                                <g:each in="${entity.value}" var="field">
     14                                        <g:if test="${j > 0}">,</g:if>
     15                                        {
     16                                                value: "${entity.key.toString().encodeAsJavaScript()}.${field.toString().encodeAsJavaScript()}",
     17                                                show: "${(field[0].toUpperCase() + field[1..-1]).encodeAsJavaScript()}",
     18                                                label: "${entity.key.toString().encodeAsJavaScript()}.${field.toString().encodeAsJavaScript()}",
     19                                                entity: "${entity.key.toString().encodeAsJavaScript()}"
     20                                        }
     21                                        <g:set var="j" value="1" />
     22                                </g:each>
     23                        </g:each>
     24                ];
     25       
     26                <g:if test="${criteria && criteria.size() > 0}">
     27                        // Show given criteria
     28                        $(function() {
     29                                <g:each in="${criteria}" var="criterion">
     30                                        showCriterium("${criterion.entityField().encodeAsJavaScript()}", "${criterion.value.toString().encodeAsJavaScript()}", "${criterion.operator.toString().encodeAsJavaScript()}");
     31                                </g:each>
     32                                showHideNoCriteriaItem();
     33                        });
     34                </g:if>
     35        </script>
    836</head>
    937<body>
     
    1139<h1>Query database</h1>
    1240
     41<g:if test="${flash.error}">
     42        <div class="error">
     43                ${flash.error.toString().encodeAsHTML()}
     44        </div>
     45</g:if>
     46<g:if test="${flash.message}">
     47        <div class="message">
     48                ${flash.message.toString().encodeAsHTML()}
     49        </div>
     50</g:if>
     51
     52<a href="<g:createLink action="list" />">View previous queries</a>
     53
    1354<form id="input_criteria">
    1455        <h2>Add criterium</h2>
    15         <p>
     56        <p class="explanation">
    1657                N.B. Comparing numerical values is done without taking into
    1758                account the units. E.g. a weight of 1 kg equals 1 grams.
    1859        </p>
    1960        <label for="field">Field</label>
    20                 <select name="field">
     61                <select name="field" id="queryFieldSelect">
    2162                        <option value=""></option>
    2263                        <g:each in="${searchableFields}" var="entity">
     
    2970                                </optgroup>
    3071                        </g:each>
    31                 </select> 
     72                </select>
    3273               
    3374        <label for="value">Comparison</label>
  • trunk/grails-app/views/advancedQuery/results.gsp

    r1430 r1482  
    55        <title>Query results</title>
    66        <link rel="stylesheet" href="<g:resource dir="css" file="advancedQuery.css" />" type="text/css"/>
    7         <g:javascript src="advancedQuery.js" />
    87</head>
    98<body>
     
    1716        <g:each in="${search.getCriteria()}" var="criterion">
    1817                <li>
    19                         <span class="entityfield">${criterion.entity}.${criterion.field}</span>
     18                        <span class="entityfield">${criterion.entityField()}</span>
    2019                        <span class="operator">${criterion.operator}</span>
    2120                        <span class="value">${criterion.value}</span>
     
    2827
    2928<g:if test="${search.getNumResults() > 0}">
    30 
     29        <%
     30                def resultFields = search.getShowableResultFields();
     31                def extraFields = resultFields[ search.getResults()[ 0 ].id ]?.keySet();
     32        %>
    3133        <table id="searchresults">
    3234                <thead>
     
    3436                                <th>Type</th>
    3537                                <th>Id</th>
     38                                <g:each in="${extraFields}" var="fieldName">
     39                                        <th>${fieldName}</th>
     40                                </g:each>
    3641                        </tr>
    3742                </thead>
     
    4045                                <td>${search.entity}</td>
    4146                                <td>${result.id}</td>
     47                                <g:each in="${extraFields}" var="fieldName">
     48                                        <td>
     49                                                <%
     50                                                        def fieldValue = resultFields[ result.id ]?.get( fieldName );
     51                                                        if( fieldValue ) {
     52                                                                if( fieldValue instanceof Collection )
     53                                                                        fieldValue = fieldValue.collect { it.toString() }.findAll { it }.join( ', ' );
     54                                                                else
     55                                                                        fieldValue = fieldValue.toString();
     56                                                        }
     57                                                %>
     58                                                ${fieldValue}
     59                                        </td>
     60                                </g:each>
     61
    4262                        </tr>
    4363                </g:each>
    4464        </table>
    4565</g:if>
    46 <p>
    47         <g:link action="index">Search again</g:link>
    48 </p>
     66<g:render template="resultbuttons" model="[queryId: queryId]" />
     67
    4968</body>
    5069</html>
  • trunk/grails-app/views/advancedQuery/sampleresults.gsp

    r1458 r1482  
    55        <title>Query results</title>
    66        <link rel="stylesheet" href="<g:resource dir="css" file="advancedQuery.css" />" type="text/css"/>
    7         <g:javascript src="advancedQuery.js" />
    87</head>
    98<body>
     
    1211
    1312<p>
    14         Your search for studies with:
     13        Your search for samples with:
    1514</p>
    16 <ul id="criteria">
    17         <g:each in="${search.getCriteria()}" var="criterion">
    18                 <li>
    19                         <span class="entityfield">${criterion.entity}.${criterion.field}</span>
    20                         <span class="operator">${criterion.operator}</span>
    21                         <span class="value">${criterion.value}</span>
    22                 </li>
    23         </g:each>
    24 </ul>
     15<g:render template="criteria" model="[criteria: search.getCriteria()]" />
    2516<p>
    2617        resulted in ${search.getNumResults()} <g:if test="${search.getNumResults() == 1}">sample</g:if><g:else>samples</g:else>.
    2718</p>
    2819
    29 
    3020<g:if test="${search.getNumResults() > 0}">
    31 
     21        <%
     22                def resultFields = search.getShowableResultFields();
     23                def extraFields = resultFields[ search.getResults()[ 0 ].id ]?.keySet();
     24        %>
    3225        <table id="searchresults" class="paginate">
    3326                <thead>
     
    3528                        <th>Study</th>
    3629                        <th>Name</th>
     30                        <g:each in="${extraFields}" var="fieldName">
     31                                <th>${fieldName}</th>
     32                        </g:each>
    3733                </tr>
    3834                </thead>
     
    4036                <g:each in="${search.getResults()}" var="sampleInstance" status="i">
    4137                        <tr class="${(i % 2) == 0 ? 'odd' : 'even'}">
    42 
    4338                                <td><g:link controller="study" action="show" id="${sampleInstance?.parent?.id}">${sampleInstance?.parent?.title}</g:link></td>
    4439                                <td>${fieldValue(bean: sampleInstance, field: "name")}</td>
     40                                <g:each in="${extraFields}" var="fieldName">
     41                                        <td>
     42                                                <%
     43                                                        def fieldValue = resultFields[ sampleInstance.id ]?.get( fieldName );
     44                                                        if( fieldValue ) {
     45                                                                if( fieldValue instanceof Collection )
     46                                                                        fieldValue = fieldValue.collect { it.toString() }.findAll { it }.join( ', ' );
     47                                                                else
     48                                                                        fieldValue = fieldValue.toString();
     49                                                        }
     50                                                %>
     51                                                ${fieldValue}
     52                                        </td>
     53                                </g:each>
    4554                        </tr>
    4655                </g:each>
     
    4958
    5059</g:if>
    51 <p>
    52         <g:link action="index">Search again</g:link>
    53 </p>
     60<g:render template="resultbuttons" model="[queryId: queryId]" />
    5461</body>
    5562</html>
  • trunk/grails-app/views/advancedQuery/studyresults.gsp

    r1458 r1482  
    55        <title>Query results</title>
    66        <link rel="stylesheet" href="<g:resource dir="css" file="advancedQuery.css" />" type="text/css"/>
    7         <g:javascript src="advancedQuery.js" />
    87</head>
    98<body>
     
    1413        Your search for studies with:
    1514</p>
    16 <ul id="criteria">
    17         <g:each in="${search.getCriteria()}" var="criterion">
    18                 <li>
    19                         <span class="entityfield">${criterion.entity}.${criterion.field}</span>
    20                         <span class="operator">${criterion.operator}</span>
    21                         <span class="value">${criterion.value}</span>
    22                 </li>
    23         </g:each>
    24 </ul>
     15<g:render template="criteria" model="[criteria: search.getCriteria()]" />
    2516<p>
    2617        resulted in ${search.getNumResults()} <g:if test="${search.getNumResults() == 1}">study</g:if><g:else>studies</g:else>.
    2718</p>
    2819<g:if test="${search.getNumResults() > 0}">
     20        <%
     21                def resultFields = search.getShowableResultFields();
     22                def extraFields = resultFields[ search.getResults()[ 0 ].id ]?.keySet();
     23        %>
    2924
    3025        <table id="searchresults" class="paginate">
     
    3732                        <th>Events</th>
    3833                        <th>Assays</th>
     34                        <g:each in="${extraFields}" var="fieldName">
     35                                <th>${fieldName}</th>
     36                        </g:each>                       
    3937                </tr>
    4038                </thead>
     
    7977                                        </g:else>
    8078                                </td>
    81 
     79                                <g:each in="${extraFields}" var="fieldName">
     80                                        <td>
     81                                                <%
     82                                                        def fieldValue = resultFields[ studyInstance.id ]?.get( fieldName );
     83                                                        if( fieldValue ) {
     84                                                                if( fieldValue instanceof Collection )
     85                                                                        fieldValue = fieldValue.collect { it.toString() }.findAll { it }.join( ', ' );
     86                                                                else
     87                                                                        fieldValue = fieldValue.toString();
     88                                                        }
     89                                                %>
     90                                                ${fieldValue}
     91                                        </td>
     92                                </g:each>
    8293                        </tr>
    8394                </g:each>
     
    8697
    8798</g:if>
    88 <p>
    89         <g:link action="index">Search again</g:link>
    90 </p>
     99<g:render template="resultbuttons" model="[queryId: queryId]" />
    91100</body>
    92101</html>
Note: See TracChangeset for help on using the changeset viewer.