Changeset 1501 for trunk/grails-app


Ignore:
Timestamp:
Feb 7, 2011, 4:07:54 PM (10 years ago)
Author:
robert@…
Message:
  • Number of seconds for the rest controller to keep data in cache is now a configuration option
  • After searching, it is possible to choose which action to perform on the search results.
Location:
trunk/grails-app
Files:
1 added
18 edited

Legend:

Unmodified
Added
Removed
  • trunk/grails-app/conf/config-ci.properties

    r1459 r1501  
    3636modules.metagenomics.url=http://ci.metagenomics.nmcdsp.org
    3737
     38# Number of seconds to keep rest results from modules in cache
     39modules.cacheDuration = 600
     40
    3841# default application users
    3942authentication.users.admin.username=admin
  • trunk/grails-app/conf/config-dbnpdemo.properties

    r1459 r1501  
    3636modules.metagenomics.url=http://demo.metagenomics.dbnp.org
    3737
     38# Number of seconds to keep rest results from modules in cache
     39modules.cacheDuration = 600
     40
    3841# default application users
    3942authentication.users.admin.username=admin
  • trunk/grails-app/conf/config-dbnptest.properties

    r1459 r1501  
    3636modules.metagenomics.url=http://test.metagenomics.dbnp.org
    3737
     38# Number of seconds to keep rest results from modules in cache
     39modules.cacheDuration = 600
     40
    3841# default application users
    3942authentication.users.admin.username=admin
  • trunk/grails-app/conf/config-development.properties

    r1459 r1501  
    3535modules.metagenomics.url=http://localhost:8184/metagenomics
    3636
     37# Number of seconds to keep rest results from modules in cache
     38modules.cacheDuration = 0
     39
    3740# default application users
    3841authentication.users.admin.username=admin
  • trunk/grails-app/conf/config-nmcdsptest.properties

    r1459 r1501  
    3636modules.metagenomics.url=http://test.metagenomics.nmcdsp.org
    3737
     38# Number of seconds to keep rest results from modules in cache
     39modules.cacheDuration = 600
     40
    3841# default application users
    3942authentication.users.admin.username=admin
  • trunk/grails-app/conf/config-production.properties

    r1459 r1501  
    3636modules.metagenomics.url=http://metagenomics.nmcdsp.org
    3737
     38# Number of seconds to keep rest results from modules in cache
     39modules.cacheDuration = 600
     40
    3841# default application users
    3942authentication.users.admin.username=admin
  • trunk/grails-app/conf/config-test.properties

    r1459 r1501  
    3535modules.metagenomics.url=http://localhost:8184/metagenomics
    3636
     37# Number of seconds to keep rest results from modules in cache
     38modules.cacheDuration = 600
     39
    3740# default application users
    3841authentication.users.admin.username=admin
  • trunk/grails-app/conf/config-www.properties

    r1459 r1501  
    3636modules.metagenomics.url=http://metagenomics.nmcdsp.org
    3737
     38# Number of seconds to keep rest results from modules in cache
     39modules.cacheDuration = 600
     40
    3841# default application users
    3942authentication.users.admin.username=admin
  • trunk/grails-app/controllers/dbnp/query/AdvancedQueryController.groovy

    r1482 r1501  
    11package dbnp.query
     2
    23import dbnp.modules.*
    34import org.dbnp.gdt.*
     
    1516
    1617        def entitiesToSearchFor = [ 'Study': 'Studies', 'Sample': 'Samples']
    17        
     18
    1819        /**
    1920         * Shows search screen
     
    2526                        criteria = parseCriteria( params.criteria, false )
    2627                }
    27                 [entitiesToSearchFor: entitiesToSearchFor, searchableFields: getSearchableFields(), criteria: criteria]
     28                [searchModes: SearchMode.values(), entitiesToSearchFor: entitiesToSearchFor, searchableFields: getSearchableFields(), criteria: criteria]
    2829        }
    2930
     
    4748
    4849                // Create a search object and let it do the searching
    49                 Search search;
     50                Search search = determineSearch( params.entity );
    5051                String view = determineView( params.entity );
    51                 switch( params.entity ) {
    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
    56                         // mentioned in this switch structure.
    57                         default:                throw new Exception( "Can't search for entities of type " + params.entity );
    58                 }
     52
     53                // Choose between AND and OR search. Default is given by the Search class itself.
     54                switch( params.operator?.toString()?.toLowerCase() ) {
     55                        case "or":
     56                                search.searchMode = SearchMode.or;
     57                                break;
     58                        case "and":
     59                                search.searchMode = SearchMode.and;
     60                                break;
     61                }
     62
    5963                search.execute( parseCriteria( params.criteria ) );
    6064
    6165                // Save search in session
    6266                def queryId = saveSearch( search );
    63                 render( view: view, model: [search: search, queryId: queryId] );
     67                render( view: view, model: [search: search, queryId: queryId, actions: determineActions(search)] );
    6468        }
    6569
     
    6973         */
    7074        def discard = {
    71                 Integer queryId
    72                 try {
    73                         queryId = params.id as Integer
    74                 } catch( Exception e ) {
     75                def queryIds = params.list( 'id' );
     76                queryIds = queryIds.findAll { it.isInteger() }.collect { Integer.valueOf( it ) }
     77
     78                if( queryIds.size() == 0 ) {
    7579                        flash.error = "Incorrect search ID given to discard"
    7680                        redirect( action: "index" );
     
    7882                }
    7983
    80                 discardSearch( queryId );
    81                 flash.message = "Search has been discarded"
     84                queryIds.each { queryId ->
     85                        discardSearch( queryId );
     86                }
     87
     88                if( queryIds.size() > 1 ) {
     89                        flash.message = "Searches have been discarded"
     90                } else {
     91                        flash.message = "Search has been discarded"
     92                }
    8293                redirect( action: "list" );
    8394        }
     
    8899         */
    89100        def show = {
    90                 Integer queryId
    91                 try {
    92                         queryId = params.id as Integer
    93                 } catch( Exception e ) {
     101                def queryId = params.int( 'id' );
     102
     103                if( !queryId ) {
    94104                        flash.error = "Incorrect search ID given to show"
    95105                        redirect( action: "index" );
     
    107117                // Determine which view to show
    108118                def view = determineView( s.entity );
    109                 render( view: view, model: [search: s, queryId: queryId] );
    110         }
    111 
     119                render( view: view, model: [search: s, queryId: queryId, actions: determineActions(s)] );
     120        }
     121
     122        /**
     123         * Performs an action on specific searchResults
     124         * @param       queryId         queryId of the search to show
     125         * @param       id                      list with the ids of the results to perform the action on
     126         * @param       actionName      Name of the action to perform
     127         */
     128        def performAction = {
     129                def queryId = params.int( 'queryId' );
     130                def selectedIds = params.list( 'id' ).findAll { it.isLong() }.collect { Long.parseLong(it) }
     131                def actionName = params.actionName;
     132                def moduleName = params.moduleName;
     133
     134                if( !queryId ) {
     135                        flash.error = "Incorrect search ID given to show"
     136                        redirect( action: "index" );
     137                        return
     138                }
     139               
     140                // Retrieve the search from session
     141                Search s = retrieveSearch( queryId );
     142                if( !s ) {
     143                        flash.message = "Specified search could not be found"
     144                        redirect( action: "list" );
     145                        return;
     146                }
     147
     148                // Determine the possible actions
     149                def actions = determineActions(s, selectedIds );
     150
     151                // Find the right action to perform
     152                def redirectUrl;
     153                for( action in actions ) {
     154                        if( action.module == moduleName && action.name == actionName ) {
     155                                redirectUrl = action.url;
     156                                break;
     157                        }
     158                }
     159               
     160                if( !redirectUrl ) {
     161                        flash.error = "No valid action is given to perform";
     162                        redirect( action: "show", id: queryId );
     163                        return;
     164                }
     165               
     166                redirect( url: redirectUrl );
     167        }
     168       
    112169        /**
    113170         * Shows a list of searches that have been saved in session
     
    124181                [searches: searches]
    125182        }
    126        
     183
    127184        /**
    128185         * Shows a search screen where the user can search within the results of another search
     
    130187         */
    131188        def searchIn = {
    132                 Integer queryId
    133                 try {
    134                         queryId = params.id as Integer
    135                 } catch( Exception e ) {
     189                def queryIds = params.list( 'id' );
     190                queryIds = queryIds.findAll { it.isInteger() }.collect { Integer.valueOf( it ) }
     191
     192                if( queryIds.size() == 0 ) {
    136193                        flash.error = "Incorrect search ID given to show"
    137194                        redirect( action: "index" );
     
    139196                }
    140197
    141                 // Retrieve the search from session
    142                 Search s = retrieveSearch( queryId );
    143                 if( !s ) {
    144                         flash.message = "Specified search could not be found"
     198                // Retrieve the searches from session
     199                def params = [:]
     200                queryIds.eachWithIndex { queryId, idx ->
     201                        Search s = retrieveSearch( queryId );
     202                        if( !s ) {
     203                                flash.message = "Specified search " + queryId + " could not be found"
     204                                return;
     205                        } else {
     206                                params[ "criteria." + idx + ".entityfield" ] = s.entity;
     207                                params[ "criteria." + idx + ".operator" ] = "in";
     208                                params[ "criteria." + idx + ".value" ] = queryId;
     209                        }
     210                }
     211
     212                redirect( action: "index", params: params)
     213        }
     214
     215        /**
     216         * Combines the results of multiple searches
     217         * @param       id      queryIds of the searches to combine
     218         */
     219        def combine = {
     220                def queryIds = params.list( 'id' );
     221                queryIds = queryIds.findAll { it.isInteger() }.collect { Integer.valueOf( it ) }
     222
     223                if( queryIds.size() == 0 ) {
     224                        flash.error = "Incorrect search ID given to combine"
    145225                        redirect( action: "index" );
     226                        return
     227                }
     228
     229                // First determine whether the types match
     230                def searches = [];
     231                def type = "";
     232                flash.error = "";
     233                queryIds.eachWithIndex { queryId, idx ->
     234                        Search s = retrieveSearch( queryId );
     235                        if( !s ) {
     236                                return;
     237                        }
     238
     239                        if( type ) {
     240                                if( type != s.entity ) {
     241                                        flash.error = type + " and " + s.entity.toLowerCase() + " queries can't be combined. Selected queries of one type.";
     242                                        return
     243                                }
     244                        } else {
     245                                type = s.entity
     246                        }
     247                }
     248
     249                if( flash.error ) {
     250                        redirect( action: "list" );
    146251                        return;
    147252                }
    148253
    149                 redirect( action: "index", params: [ "criteria.0.entityfield": s.entity, "criteria.0.operator": "in", "criteria.0.value": queryId ])
     254                if( !type ) {
     255                        flash.error = "No correct query ids were given."
     256                        redirect( action: "list" );
     257                        return;
     258                }
     259
     260                // Retrieve the searches from session
     261                Search combined = determineSearch( type );
     262                combined.searchMode = SearchMode.or;
     263
     264                queryIds.eachWithIndex { queryId, idx ->
     265                        Search s = retrieveSearch( queryId );
     266                        if( s ) {
     267                                combined.addCriterion( new Criterion( entity: type, field: null, operator: Operator.insearch, value: s ) );
     268                        }
     269                }
     270
     271                // Execute search to combine the results
     272                combined.execute();
     273
     274                def queryId = saveSearch( combined );
     275                redirect( action: "show", id: queryId );
    150276        }
    151277
     
    155281                        case "Sample":  return "sampleresults"; break;
    156282                        default:                return "results"; break;
     283                }
     284        }
     285
     286        /**
     287         * Returns the search object used for searching
     288         */
     289        protected Search determineSearch( String entity ) {
     290                switch( entity ) {
     291                        case "Study":   return new StudySearch();
     292                        case "Sample":  return new SampleSearch();
     293
     294                        // This exception will only be thrown if the entitiesToSearchFor contains more entities than
     295                        // mentioned in this switch structure.
     296                        default:                throw new Exception( "Can't search for entities of type " + entity );
    157297                }
    158298        }
     
    230370                        if( c.key ==~ /[0-9]+/ ) {
    231371                                def formCriterion = c.value;
    232                                
     372
    233373                                Criterion criterion = new Criterion();
    234374
     
    251391                                        continue;
    252392                                }
    253                                
     393
    254394                                // Special case of the 'in' operator
    255395                                if( criterion.operator == Operator.insearch ) {
     
    258398                                                s = retrieveSearch( Integer.parseInt( formCriterion.value ) );
    259399                                        } catch( Exception e ) {}
    260                                        
     400
    261401                                        if( !s ) {
    262402                                                flash.error += "Can't search within previous query: query not found";
    263403                                                continue;
    264404                                        }
    265                                        
     405
    266406                                        if( parseSearchIds ) {
    267407                                                criterion.value = s
     
    273413                                        criterion.value = formCriterion.value;
    274414                                }
    275                                
     415
    276416                                list << criterion;
    277417                        }
     
    332472                // First check whether a search with the same criteria is already present
    333473                def previousSearch = retrieveSearchByCriteria( s.getCriteria() );
    334                
     474
    335475                def id
    336476                if( previousSearch ) {
     
    340480                        id = ( session.queries*.key.max() ?: 0 ) + 1;
    341481                }
    342                
     482
    343483                s.id = id;
    344484                session.queries[ id ] = s;
    345485
    346                 println "On saveSearch: " + session.queries;
    347486                return id;
    348487        }
     
    356495                if( !session.queries )
    357496                        return null
    358                
     497
    359498                if( !criteria )
    360499                        return null
    361                        
     500
    362501                for( query in session.queries ) {
    363502                        def key = query.key;
     
    385524                        return null;
    386525
    387                 println "On retrieveSearch: " + session.queries;
    388526                return (Search) session.queries[ id ]
    389527        }
     
    402540                session.queries.remove( id );
    403541
    404                 println "On discardSearch: " + session.queries;
    405542                if( !( sessionSearch instanceof Search ) )
    406543                        return null;
     
    419556                return session.queries*.value.toList()
    420557        }
     558
     559        /**
     560         * Determine a list of actions that can be performed on specific entities
     561         * @param entity                Name of the entity that the actions could be performed on
     562         * @param selectedIds   List with ids of the selected items to perform an action on
     563         * @return
     564         */
     565        protected List determineActions( Search s, def selectedIds = null ) {
     566                return gscfActions( s, selectedIds ) + moduleActions( s, selectedIds );
     567        }
     568
     569        /**
     570         * Determine a list of actions that can be performed on specific entities by GSCF
     571         * @param entity        Name of the entity that the actions could be performed on
     572         * @param selectedIds   List with ids of the selected items to perform an action on
     573         */
     574        protected List gscfActions(Search s, def selectedIds = null) {
     575                switch(s.entity) {
     576                        case "Study":
     577                                def exportParams = [:]
     578                                s.filterResults(selectedIds).each {
     579                                        exportParams[ it.code ] = it.id;
     580                                }
     581                                return [[
     582                                                module: "gscf",
     583                                                name:"simpletox",
     584                                                description: "Export as SimpleTox",
     585                                                url: createLink( controller: "exporter", action: "export", params: exportParams )
     586                                        ]]
     587                        case "Sample":
     588                                return []
     589                        default:
     590                                return [];
     591                }
     592        }
     593
     594        /**
     595         * Determine a list of actions that can be performed on specific entities by other modules
     596         * @param entity        Name of the entity that the actions could be performed on
     597         */
     598        protected List moduleActions(Search s, def selectedIds = null) {
     599                def actions = []
     600
     601                if( !s.getResults() || s.getResults().size() == 0 )
     602                        return []
     603
     604                // Loop through all modules and check which actions can be performed on the
     605                AssayModule.list().each { module ->
     606                        // Remove 'module' from module name
     607                        def moduleName = module.name.replace( 'module', '' ).trim()
     608                        try {
     609                                def callUrl = module.url + "/rest/getPossibleActions?entity=" + s.entity
     610                                def json = moduleCommunicationService.callModuleRestMethodJSON( module.url, callUrl );
     611
     612                                // Check whether the entity is present in the return value
     613                                if( json[ s.entity ] ) {
     614                                        json[ s.entity ].each { action ->
     615                                                def url = module.url + "/action/" + action.name
     616                                                url += "?entity=" + s.entity
     617                                                url += "&" + s.filterResults(selectedIds).collect { "tokens=" + it.giveUUID() }.join( "&" )
     618                                                actions << [
     619                                                                        module: moduleName,
     620                                                                        name: action.name,
     621                                                                        description: action.description + " (" + moduleName + ")",
     622                                                                        url: url
     623                                                                ];
     624                                        }
     625                                }
     626                        } catch( Exception e ) {
     627                                // Exception is thrown when the call to the module fails. No problems though.
     628                                log.error "Error while fetching possible actions from " + module.name + ": " + e.getMessage()
     629                        }
     630                }
     631
     632                return actions;
     633        }
     634
    421635}
  • trunk/grails-app/services/dbnp/modules/ModuleCommunicationService.groovy

    r1482 r1501  
    1818import grails.converters.*
    1919import javax.servlet.http.HttpServletResponse
     20import org.codehaus.groovy.grails.commons.ConfigurationHolder
    2021
    2122class ModuleCommunicationService implements Serializable {
     
    3334         * Number of seconds to save the data in cache
    3435         */
    35         def numberOfSecondsInCache = 10 * 60;
     36        def numberOfSecondsInCache = Integer.valueOf( ConfigurationHolder.config.modules.cacheDuration )
    3637
    3738        /**
     
    147148                def user = authenticationService.getLoggedInUser();
    148149                def userId = user ? user.id : -1;
    149 
     150               
     151                println "Retrieve from cache: " + url
     152                println "Seconds in cache: " + numberOfSecondsInCache
     153               
    150154                if( cache[ userId ] && cache[ userId ][ url ] && ( System.currentTimeMillis() - cache[ userId ][ url ][ "timestamp" ] ) < numberOfSecondsInCache * 1000 ) {
    151155                        return cache[ userId ][ url ];
  • trunk/grails-app/views/advancedQuery/_criteria.gsp

    r1482 r1501  
     1<%@ page import="dbnp.query.*" %>
    12<ul id="criteria">
    2         <g:each in="${criteria}" var="criterion">
     3        <g:each in="${criteria}" var="criterion" status="j">
    34                <li>
    45                        <span class="entityfield">${criterion.entityField()}</span>
    56                        <span class="operator">${criterion.operator}</span>
    6                         <span class="value">${criterion.value}</span>
     7                        <span class="value">
     8                                <g:if test="${criterion.value != null && criterion.value instanceof Search}">
     9                                        <g:link action="show" id="${criterion.value.id}">${criterion.value}</g:link>
     10                                </g:if>
     11                                <g:else>
     12                                        ${criterion.value}
     13                                </g:else>
     14                        </span>
     15                        <g:if test="${j < criteria.size() -1}">
     16                                <g:if test="${search.searchMode == SearchMode.and}">and</g:if>
     17                                <g:if test="${search.searchMode == SearchMode.or}">or</g:if>
     18                        </g:if>
    719                </li>
    820        </g:each>
  • trunk/grails-app/views/advancedQuery/_resultbuttons.gsp

    r1482 r1501  
    1 <p>
    2         <g:link action="searchIn" id="${queryId}">Search within results</g:link><br />
    3         <g:link action="index">Search again</g:link><br />
    4         <g:link action="discard" id="${queryId}">Discard results</g:link><br />
    5         <g:link action="list">Previous searches</g:link>
     1<p class="options">
     2        <g:link class="searchIn" action="searchIn" id="${queryId}">Search within results</g:link><br />
     3        <g:link class="search" action="index">Search again</g:link><br />
     4        <g:link class="discard" action="discard" id="${queryId}">Discard results</g:link><br />
     5        <g:link class="listPrevious" action="list">Previous searches</g:link>
    66</p>
     7<p class="options">
     8        <g:each in="${actions}" var="action">
     9                <a class="performAction ${action.name}" href="${action.url}" onClick="performAction( $('form#results'), '${action.name}', '${action.module}' ); return false;">${action.description}</a><br />
     10        </g:each>
     11</p>
     12<br clear="all">
  • trunk/grails-app/views/advancedQuery/index.gsp

    r1487 r1501  
    1414                                        <g:if test="${j > 0}">,</g:if>
    1515                                        {
     16                                                label: "${entity.key.toString().encodeAsJavaScript()}.${field.toString().encodeAsJavaScript()} ${entity.key.toString().encodeAsJavaScript()} ${field.toString().encodeAsJavaScript()}",
     17                                                show: "${(field[0].toUpperCase() + field[1..-1]).encodeAsJavaScript()}",
    1618                                                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()}",
    1919                                                entity: "${entity.key.toString().encodeAsJavaScript()}"
    2020                                        }
     
    4949        </div>
    5050</g:if>
    51 
    52 <a href="<g:createLink action="list" />">View previous queries</a>
    5351
    5452<form id="input_criteria">
     
    9189        <g:form action="search" method="get">
    9290                <label for="entity">Search for</label><g:select from="${entitiesToSearchFor}" optionKey="key" optionValue="value" name="entity" /><br />
     91                <label for="entity">Searchtype</label><g:select from="${searchModes}" name="operator" /><br />
    9392                <label for="criteria">Criteria</label>
    9493                <ul id="criteria">
     
    9998        </g:form>
    10099</div>
    101 
     100<p class="options">
     101        <g:link class="listPrevious" action="list">Previous searches</g:link>
     102</p>
    102103<br  clear="all" />
    103104</body>
  • trunk/grails-app/views/advancedQuery/list.gsp

    r1482 r1501  
    66        <title>Previous queries</title>
    77        <link rel="stylesheet" href="<g:resource dir="css" file="advancedQuery.css" />" type="text/css"/>
     8        <g:javascript src="advancedQueryResults.js" />
     9        <script type="text/javascript">
     10                function searchWithinResults( form ) {
     11                        submitForm( form, '/advancedQuery/searchIn' );
     12                }
     13                function discardResults( form ) {
     14                        submitForm( form, '/advancedQuery/discard' );
     15                }       
     16                function combineResults( form ) {
     17                        submitForm( form, '/advancedQuery/combine' );
     18                }                               
     19        </script>
     20       
    821</head>
    922<body>
     
    1124<h1>Previous queries</h1>
    1225
     26<g:if test="${flash.error}">
     27        <div class="errormessage">
     28                ${flash.error.toString().encodeAsHTML()}
     29        </div>
     30</g:if>
     31<g:if test="${flash.message}">
     32        <div class="message">
     33                ${flash.message.toString().encodeAsHTML()}
     34        </div>
     35</g:if>
     36
    1337<g:if test="${searches.size() > 0}">
    14         <table id="searchresults">
     38        <form id="searchform" method="post">
     39        <table id="searchresults" class="paginate">
    1540                <thead>
    1641                        <tr>
    17                                 <th></th>
     42                                <th class="nonsortable"></th>
    1843                                <th>#</th>
    1944                                <th>Type</th>
     
    2146                                <th># results</th>
    2247                                <th>time</th>
    23                                 <th></th>
    24                                 <th></th>
     48                                <th class="nonsortable"></th>
     49                                <th class="nonsortable"></th>
    2550                        </tr>
    2651                </thead>
    2752                <g:each in="${searches}" var="search">
    2853                        <tr>
    29                                 <td><g:checkBox name="queryId" value="${search.id}" checked="${false}" /></td>
     54                                <td><g:checkBox name="id" value="${search.id}" checked="${false}" /></td>
    3055                                <td>${search.id}</td>
    3156                                <td>${search.entity}</td>
     
    5277                </g:each>
    5378        </table>
     79        </form>
    5480</g:if>
    55 <p>
    56         <g:link action="index">Search again</g:link>
     81
     82<p class="options">
     83        <a href="#" class="combine" onClick="combineResults( $( '#searchform' ) ); return false;">Combine results</a><br />
     84        <a href="#" class="searchIn" onClick="searchWithinResults( $( '#searchform' ) ); return false;">Search within results</a><br />
     85        <g:link class="search" action="index">Search again</g:link><br />
     86        <a href="#" class="discard" onClick="discardResults( $( '#searchform' ) ); return false;">Discard results</a><br />
    5787</p>
     88
    5889</body>
    5990</html>
  • trunk/grails-app/views/advancedQuery/results.gsp

    r1482 r1501  
    55        <title>Query results</title>
    66        <link rel="stylesheet" href="<g:resource dir="css" file="advancedQuery.css" />" type="text/css"/>
     7        <g:javascript src="advancedQueryResults.js" />
    78</head>
    89<body>
     
    1314        Your search for:
    1415</p>
    15 <ul id="criteria">
    16         <g:each in="${search.getCriteria()}" var="criterion">
    17                 <li>
    18                         <span class="entityfield">${criterion.entityField()}</span>
    19                         <span class="operator">${criterion.operator}</span>
    20                         <span class="value">${criterion.value}</span>
    21                 </li>
    22         </g:each>
    23 </ul>
     16<g:render template="criteria" model="[criteria: search.getCriteria()]" />
    2417<p>
    2518        resulted in ${search.getNumResults()} results.
     
    3124                def extraFields = resultFields[ search.getResults()[ 0 ].id ]?.keySet();
    3225        %>
    33         <table id="searchresults">
     26        <table id="searchresults" class="paginate">
    3427                <thead>
    3528                        <tr>
     29                                <th class="nonsortable"></th>
    3630                                <th>Type</th>
    3731                                <th>Id</th>
     
    4337                <g:each in="${search.getResults()}" var="result">
    4438                        <tr>
     39                                <td width="3%">
     40                                        <% /*
     41                                                The value of this checkbox will be moved to the form (under this table) with javascript. This
     42                                                way the user can select items from multiple pages of the paginated result list correctly. See
     43                                                also http://datatables.net/examples/api/form.html and advancedQueryResults.js
     44                                        */ %>
     45                                        <g:checkBox name="id" value="${result.id}" checked="${false}" />
     46                                </td>                   
    4547                                <td>${search.entity}</td>
    4648                                <td>${result.id}</td>
     
    5052                                                        def fieldValue = resultFields[ result.id ]?.get( fieldName );
    5153                                                        if( fieldValue ) {
    52                                                                 if( fieldValue instanceof Collection )
     54                                                                if( fieldValue instanceof Collection ) {
    5355                                                                        fieldValue = fieldValue.collect { it.toString() }.findAll { it }.join( ', ' );
    54                                                                 else
     56                                                                } else {
    5557                                                                        fieldValue = fieldValue.toString();
     58                                                                }
     59                                                        } else {
     60                                                                fieldValue = "";
    5661                                                        }
    5762                                                %>
  • trunk/grails-app/views/advancedQuery/sampleresults.gsp

    r1482 r1501  
    55        <title>Query results</title>
    66        <link rel="stylesheet" href="<g:resource dir="css" file="advancedQuery.css" />" type="text/css"/>
     7        <g:javascript src="advancedQueryResults.js" />
    78</head>
    89<body>
     
    2627                <thead>
    2728                <tr>
     29                        <th class="nonsortable"></th>                   
     30                        <th>Name</th>
    2831                        <th>Study</th>
    29                         <th>Name</th>
    3032                        <g:each in="${extraFields}" var="fieldName">
    3133                                <th>${fieldName}</th>
     
    3638                <g:each in="${search.getResults()}" var="sampleInstance" status="i">
    3739                        <tr class="${(i % 2) == 0 ? 'odd' : 'even'}">
     40                                <td width="3%">
     41                                        <% /*
     42                                                The value of this checkbox will be moved to the form (under this table) with javascript. This
     43                                                way the user can select items from multiple pages of the paginated result list correctly. See
     44                                                also http://datatables.net/examples/api/form.html and advancedQueryResults.js
     45                                        */ %>
     46                                        <g:checkBox name="id" value="${sampleInstance.id}" checked="${false}" />
     47                                </td>
     48                                <td>${fieldValue(bean: sampleInstance, field: "name")}</td>
    3849                                <td><g:link controller="study" action="show" id="${sampleInstance?.parent?.id}">${sampleInstance?.parent?.title}</g:link></td>
    39                                 <td>${fieldValue(bean: sampleInstance, field: "name")}</td>
    4050                                <g:each in="${extraFields}" var="fieldName">
    4151                                        <td>
     
    4353                                                        def fieldValue = resultFields[ sampleInstance.id ]?.get( fieldName );
    4454                                                        if( fieldValue ) {
    45                                                                 if( fieldValue instanceof Collection )
     55                                                                if( fieldValue instanceof Collection ) {
    4656                                                                        fieldValue = fieldValue.collect { it.toString() }.findAll { it }.join( ', ' );
    47                                                                 else
     57                                                                } else {
    4858                                                                        fieldValue = fieldValue.toString();
     59                                                                }
     60                                                        } else {
     61                                                                fieldValue = "";
    4962                                                        }
    5063                                                %>
     
    5669                </tbody>
    5770        </table>
     71        <g:render template="resultsform" />
    5872
    5973</g:if>
  • trunk/grails-app/views/advancedQuery/studyresults.gsp

    r1482 r1501  
    55        <title>Query results</title>
    66        <link rel="stylesheet" href="<g:resource dir="css" file="advancedQuery.css" />" type="text/css"/>
     7        <g:javascript src="advancedQueryResults.js" />
    78</head>
    89<body>
     
    2223                def extraFields = resultFields[ search.getResults()[ 0 ].id ]?.keySet();
    2324        %>
    24 
    2525        <table id="searchresults" class="paginate">
    2626                <thead>
    2727                <tr>
    28                         <th colspan="2"></th>
     28                        <th class="nonsortable"></th>
     29                        <th>Title</th>
    2930                        <th>Code</th>
    30                         <th>Title</th>
    3131                        <th>Subjects</th>
    3232                        <th>Events</th>
     
    4040                <g:each in="${search.getResults()}" var="studyInstance" status="i">
    4141                        <tr class="${(i % 2) == 0 ? 'odd' : 'even'}">
    42 
    43                                 <td><g:link controller="study" action="show" id="${studyInstance?.id}"><img src='${fam.icon(name: 'application_form_magnify')}' border="0" alt="view study" /></g:link></td>
    44                                 <td><g:if test="${studyInstance.canWrite(loggedInUser)}"><g:link class="edit" controller="studyWizard" params="[jump:'edit']" id="${studyInstance?.id}"><img src='${fam.icon(name: 'application_form_edit')}' border="0" alt="edit study" /></g:link></g:if><g:else><img src='${fam.icon(name: 'lock')}' border="0" alt="you have no write access to shis study" /></g:else> </td>
     42                                <td width="3%">
     43                                        <% /*
     44                                                The value of this checkbox will be moved to the form (under this table) with javascript. This
     45                                                way the user can select items from multiple pages of the paginated result list correctly. See
     46                                                also http://datatables.net/examples/api/form.html and advancedQueryResults.js
     47                                        */ %>
     48                                        <g:checkBox name="id" value="${studyInstance.id}" checked="${false}" />
     49                                </td>
     50                                <td>
     51                                        <g:link controller="study" action="show" id="${studyInstance?.id}">${fieldValue(bean: studyInstance, field: "title")}</g:link>
     52                                       
     53                                </td>
    4554                                <td>${fieldValue(bean: studyInstance, field: "code")}</td>
    46                                 <td>
    47                                         ${fieldValue(bean: studyInstance, field: "title")}
    48                                 </td>
    4955                                <td>
    5056                                        <g:if test="${studyInstance.subjects.species.size()==0}">
     
    8288                                                        def fieldValue = resultFields[ studyInstance.id ]?.get( fieldName );
    8389                                                        if( fieldValue ) {
    84                                                                 if( fieldValue instanceof Collection )
     90                                                                if( fieldValue instanceof Collection ) {
    8591                                                                        fieldValue = fieldValue.collect { it.toString() }.findAll { it }.join( ', ' );
    86                                                                 else
     92                                                                } else {
    8793                                                                        fieldValue = fieldValue.toString();
     94                                                                }
     95                                                        } else {
     96                                                                fieldValue = "";
    8897                                                        }
    8998                                                %>
     
    95104                </tbody>
    96105        </table>
     106        <g:render template="resultsform" />
    97107
    98108</g:if>
  • trunk/grails-app/views/layouts/main.gsp

    r1434 r1501  
    2121        <script type="text/javascript" src="${resource(dir: 'js', file: 'topnav.js')}"></script>
    2222        <g:if env="development"><script type="text/javascript" src="${resource(dir: 'js', file: 'development.js')}"></script></g:if>
     23
     24        <!--  Scripts for pagination using dataTables -->
     25        <link rel="stylesheet" href="${resource(dir: 'css/datatables', file: 'demo_table_jui.css')}"/>
     26        <script type="text/javascript" src="${resource(dir: 'js', file: 'jquery.dataTables.min.js')}"></script>
     27        <script type="text/javascript" src="${resource(dir: 'js', file: 'paginate.js')}"></script>
     28
    2329</head>
    2430<body>
Note: See TracChangeset for help on using the changeset viewer.