Changeset 50 for trunk


Ignore:
Timestamp:
Apr 13, 2011, 3:02:19 PM (8 years ago)
Author:
robert@…
Message:
  • Added links to remove samples from a run
  • Added synchronization of authorization for all studies, if a user logs in
  • Improved excel import to handle Error-values in a cell
Location:
trunk
Files:
14 edited

Legend:

Unmodified
Added
Removed
  • trunk/grails-app/conf/BaseFilters.groovy

    r49 r50  
    142142                                } else {
    143143                                        session.sessionToken = "${UUID.randomUUID()}"
    144                                         log.info("SessionToken created, redirecting to GSCF to let the user login! (SessionToken: ${session.sessionToken}")
     144                                        log.info("SessionToken created, redirecting to GSCF to let the user login! (SessionToken: ${session.sessionToken})")
    145145
    146146                                        redirect( url: gscfService.urlAuthRemote(params, session.sessionToken) )
  • trunk/grails-app/controllers/nl/tno/massSequencing/AssayController.groovy

    r49 r50  
    358358        /**
    359359         * Deletes all sequences for a given assay
     360         * @param assayId       Id of the assay we are in
     361         * @param ids           List of ids of the assaysamples to delete the sequences from
    360362         */
    361363        def deleteSequenceData = {
    362                 Assay assay = getAssay( params.id );
     364                // Determine the assay we are in
     365                Assay assay = getAssay( params.assayId );
    363366               
    364367                if( !assay ) {
     
    366369                        return
    367370                }
    368                
    369                 def assaySamples = assay.assaySamples?.toList();
     371
     372                // Find the selected assaysamples
     373                def ids = params.list( 'ids' );
     374                ids = ids.findAll { it.isLong() }.collect { Long.parseLong( it ) }
     375                def assaySamples = ids.collect { AssaySample.get( it ) }.findAll { it }
     376
    370377                if( !assaySamples ) {
    371                         flash.message = "No samples found for given assay";
     378                        flash.message = "No samples selected"
    372379                        redirect( controller: 'assay', action: 'show', id: assay.id );
    373                         return
     380                        return;
    374381                }
    375382               
    376383                def numFiles = fastaService.deleteSequenceData( assaySamples );
    377384               
    378                 flash.message = "All " + numFiles + " files have been removed from the assay.";
     385                flash.message = numFiles + " files have been removed from the assay.";
    379386                redirect( controller: 'assay', action: 'show', id: assay.id );
    380387        }
  • trunk/grails-app/controllers/nl/tno/massSequencing/RunController.groovy

    r49 r50  
    265265                if( !filename || filename.contains( '..' ) ) {
    266266                        response.status = 500;
     267                        response.setContentType( "text/plain" );
    267268                        render "Invalid filename given";
    268269                        return;
     
    274275                if( !file.exists() || !file.canRead() ) {
    275276                        response.status = 404;
     277                        response.setContentType( "text/plain" );
    276278                        render "The uploaded file doesn't exist or doesn't work as expected.";
    277279                        return;
     
    284286                        excelData = sampleExcelService.parseTagsExcel( file, false );
    285287                } catch( Throwable e ) { // Catch a throwable here instead of an exception, since the apache poi stuff gives an Error on failure
     288                        e.printStackTrace()
    286289                        // Couldn't create a workbook from this file.
    287290                        response.status = 400 // Bad request
     291                        response.setContentType( "text/plain" );
    288292                        render "Uploaded file is not a valid excel file: " + e.getMessage()
    289293                        return
     
    412416                        try {
    413417                                def assaySample = AssaySample.findById( assaySampleId as Long )
    414                                 if( assaySample.assay.study.canWrite( session.user ) ) {
     418                                if( !assaySample.run && assaySample.assay.study.canWrite( session.user ) ) {
    415419                                        if( run.assaySamples == null || !run.assaySamples.contains( assaySample ) ) {
    416420                                                run.addToAssaySamples( assaySample );
     
    467471
    468472                redirect( action: 'show', id: params.id)
     473        }
     474       
     475        /**
     476         * Removes samples from this run
     477         */
     478        def removeSamples = {
     479                // Determine the run we are in
     480                Run run = getRun( params.runId );
     481
     482                if( !run ) {
     483                        redirect(controller: 'run', action: 'list')
     484                        return
     485                }
     486
     487                // Find the selected assaysamples
     488                def ids = params.list( 'ids' );
     489                ids = ids.findAll { it.isLong() }.collect { Long.parseLong( it ) }
     490                def assaySamples = ids.collect { AssaySample.get( it ) }.findAll { it }
     491
     492                if( !assaySamples ) {
     493                        flash.message = "No samples selected for removal"
     494                        redirect( action: 'show', id: run.id );
     495                        return;
     496                }
     497
     498                def numRemoved = 0;
     499                assaySamples.each { assaySample ->             
     500                        if( assaySample.assay.study.canWrite( session.user ) ) {
     501                                if( assaySample.run ) {
     502                                        assaySample.run.removeFromAssaySamples( assaySample );
     503                                        numRemoved++;
     504                                }
     505                        }
     506                }
     507               
     508                if( numRemoved > 0 )
     509                        flash.message = numRemoved + " sample(s) have been removed from this run."
     510                else
     511                        flash.message = "No samples have been removed from this run, because you don't have the right privileges to do so."
     512
     513                redirect( action: 'show', id: run.id)
    469514        }
    470515
     
    552597         */
    553598        def deleteSequenceData = {
    554                 Run run = getRun( params.id );
    555                
     599                // Determine the run we are in
     600                Run run = getRun( params.runId );
     601
    556602                if( !run ) {
    557603                        redirect(controller: 'run', action: 'index')
    558604                        return
    559605                }
    560                
    561                 def assaySamples = run.assaySamples?.toList();
     606
     607                // Find the selected assaysamples
     608                def ids = params.list( 'ids' );
     609                ids = ids.findAll { it.isLong() }.collect { Long.parseLong( it ) }
     610                def assaySamples = ids.collect { AssaySample.get( it ) }.findAll { it }
     611
    562612                if( !assaySamples ) {
    563                         flash.message = "No samples found for given run";
    564                         redirect( controller: 'run', action: 'show', id: run.id );
    565                         return
     613                        flash.message = "No samples selected"
     614                        redirect( action: 'show', id: run.id );
     615                        return;
    566616                }
    567617               
    568618                def numFiles = fastaService.deleteSequenceData( assaySamples );
    569619               
    570                 flash.message = "All " + numFiles + " files have been removed from the run.";
     620                flash.message = numFiles + " files have been removed from the run.";
    571621                redirect( controller: 'run', action: 'show', id: run.id );
    572622        }
     
    585635                if( assaySamples.size() == 0 ) {
    586636                        flash.error = "No samples found for selected runs";
    587                         redirect( action: "list" );
     637                        redirect( action: "index" );
    588638                        return;
    589639                } else if( assaySamples*.run.unique().size() == 1 )
     
    614664                if( assaySamples.size() == 0 ) {
    615665                        flash.error = "No samples found for selected runs";
    616                         redirect( action: "list" );
     666                        redirect( action: "index" );
    617667                        return;
    618668                } else if( assaySamples*.run.unique().size() == 1 ) {
  • trunk/grails-app/controllers/nl/tno/massSequencing/integration/SynchronizeController.groovy

    r27 r50  
    11package nl.tno.massSequencing.integration
    22
     3import nl.tno.massSequencing.Study;
    34
    45class SynchronizeController {
     
    4748                }
    4849        }
     50       
     51        /**
     52         * This method should be called after a user logs in. It
     53         * updates the authorization for all studies present in the database,
     54         * so the user can see all his studies
     55         */
     56        def authorization = {
     57                try {
     58                        if( !session.user ) {
     59                                throw new Exception( "No user is logged in" );
     60                        }
     61                       
     62                        println "Synchronize authorization!";
     63                       
     64                        synchronizationService.sessionToken = session.sessionToken
     65                        synchronizationService.user = session.user
     66       
     67                        Study.findAllByTrashcan( false ).each { study ->
     68                                synchronizationService.synchronizeAuthorization( study );
     69                        }
     70                       
     71                        if( params.redirectUrl )
     72                                redirect( url: params.redirectUrl );
     73                        else
     74                                redirect( controller: "run" );
     75                       
     76                        return;
     77                } catch( Exception e ) {
     78                        // Catch all exceptions, show them to the user (by rendering a text message) and print a stacktrace
     79                        def message = e.getMessage();
     80                        if( !message || message == 'null' )
     81                                message = 'unknown error';
     82               
     83                        // Show errors in log file
     84                        log.error "Exception during synchronization of authorization: " + message
     85                        e.printStackTrace()
     86                       
     87                        // Give the user a nice error message
     88                        response.status = 500;
     89                        render "An error occurred during synchronization (" + e.class?.name + "): " + message;
     90                }
     91        }
    4992}
  • trunk/grails-app/services/nl/tno/massSequencing/files/ExcelService.groovy

    r29 r50  
    8787                                        Cell c = excelRow.getCell( colNum );
    8888                                        if( c ) {
    89                                                 if( c.getCellType() == Cell.CELL_TYPE_NUMERIC ) {
    90                                                         row << numberformat.format( c.getNumericCellValue() );
    91                                                 } else {
    92                                                         row << df.formatCellValue( c );
     89                                                switch( c.getCellType() ) {
     90                                                        case Cell.CELL_TYPE_NUMERIC:
     91                                                                row << numberformat.format( c.getNumericCellValue() );
     92                                                                break;
     93                                                        case Cell.CELL_TYPE_BLANK:
     94                                                        case Cell.CELL_TYPE_BOOLEAN:
     95                                                        case Cell.CELL_TYPE_STRING:
     96                                                        case Cell.CELL_TYPE_FORMULA:
     97                                                                row << df.formatCellValue( c );
     98                                                                break
     99                                                        case Cell.CELL_TYPE_ERROR:
     100                                                                row << "Err";
     101                                                                break;
    93102                                                }
    94103                                        } else {
  • trunk/grails-app/services/nl/tno/massSequencing/integration/GscfService.groovy

    r29 r50  
    4545                                return ""
    4646                }.findAll { it }.join( "&" );
     47
     48                // After logging in, send the user to /synchronize/authorization first to synchronize
     49                // authorization for this user
     50                returnUrl = config.grails.serverURL + '/synchronize/authorization?redirectUrl=' + returnUrl.encodeAsURL()
    4751               
    4852                return redirectURL + "returnUrl=" + returnUrl.encodeAsURL();
  • trunk/grails-app/services/nl/tno/massSequencing/integration/SynchronizationService.groovy

    r29 r50  
    212212                // when removing elements from the list
    213213               
    214                 println "Handle deleted studies: " + studies.size() + " -> " + newStudies.size();
    215214                def numStudies = studies.size();
    216215                for( int i = numStudies - 1; i >= 0; i-- ) {
  • trunk/grails-app/views/assay/show.gsp

    r49 r50  
    6262        </g:if>
    6363        <g:else>
    64                 <form id="sampleForm"></form>
     64                <form id="sampleForm"><input type="hidden" name="assayId" value="${assay.id}" /></form>
    6565                <table class="paginate" id="samples">
    6666                        <thead>
     
    120120                        </tbody>
    121121                </table>
    122                 <p class="options">
     122                <p class="options multiple">
    123123                        <g:if test="${editable}">
    124124                                <a class="editAssociation" onClick="showEnterTagsDialog(); return false;" href="#">Edit sample data</a>
     
    127127                                <a class="editAssociation disabled" onClick="return false;" href="#">Edit sample data</a>
    128128                        </g:else>
    129                        
    130                         <a class="fasta" href="#" onClick="submitPaginatedForm( $( '#sampleForm' ), '<g:createLink controller="assaySample" action="exportAsFasta" />', '#samples', 'Please select one or more samples to export' ); return false;">Export as fasta</a>
     129                </p>                   
     130                <p class="options multiple">
    131131                       
    132132                        <g:if test="${!editable || assay.runs == null || assay.runs.size() == 0}">
     
    136136                                <a class="addSequences" onClick="showAddFilesDialog(); return false;" href="#">Add sequence files</a>
    137137                        </g:else>
     138                       
     139                        <br />
     140                       
    138141                        <g:if test="${editable && assay.numFiles() > 0 }">
    139                                 <g:link class="delete" onClick="return confirm( 'Are you sure you want to remove all sequence data from this assay?' );" controller="assay" action="deleteSequenceData" id="${assay.id}">Delete all sequences</g:link>
     142                                <a class="removeSequences" href="#" onClick="if( confirm( 'Are you sure you want to remove all sequence data from this assay?' ) ) { submitPaginatedForm( $( '#sampleForm' ), '<g:createLink controller="assay" action="deleteSequenceData" />', '#samples', 'Please select one or more samples to remove sequences from.' ); } return false;">Delete selected sequences</a>
    140143                        </g:if>
     144
    141145                </p>
    142 
     146                                       
     147                <p class="options multiple">
     148                        <a class="fasta" href="#" onClick="submitPaginatedForm( $( '#sampleForm' ), '<g:createLink controller="assaySample" action="exportAsFasta" />', '#samples', 'Please select one or more samples to export' ); return false;">Export as fasta</a>
     149                </p>
     150                <br clear="all" />
    143151                <g:if test="${editable}">
    144152                        <g:render template="enterTagsDialog" model="[assay: assay, sortedAssaySamples: assaySamples]" />
  • trunk/grails-app/views/run/_addSamplesDialog.gsp

    r23 r50  
    33        <p>
    44                Choose samples to attach to this run. You can only choose samples from assays that have been associated with this run.<br />
    5                 N.B. If the samples are attached to another run, that connection will be removed!
     5                N.B. Only samples that are not associated with a run can be added. To add other samples, first remove the association with the current run.
    66        </p>
    77       
     
    1414                                <th>Sample</th>
    1515                                <th>Assay</th>
    16                                 <th>Run</th>
    1716                        </tr>
    1817                </thead>
     
    2019                        <g:if test="${assay.study.canWrite(session.user)}">
    2120                                <g:each in="${assay.assaySamples}" var="assaySample">
    22                                         <g:if test="${!assaySample.run?.equals(run)}">
     21                                        <g:if test="${!assaySample.run}">
    2322                                                <tr>
    2423                                                        <td><g:checkBox name="assaySamples" value="${assaySample.id}" checked="${false}" onClick="updateCheckAll(this);" /></td>
    2524                                                        <td>${assaySample.sample.name}</td>
    2625                                                        <td>${assaySample.assay.name}</td>
    27                                                         <td>${assaySample.run?.name}</td>
    2826                                                </tr>
    2927                                        </g:if>
  • trunk/grails-app/views/run/show.gsp

    r49 r50  
    9292        </g:if>
    9393        <g:else>
    94                 <form id="sampleForm"></form>
     94                <form id="sampleForm"><input type="hidden" name="runId" value="${run.id}" /></form>
    9595                <table class="paginate" id="samples">
    9696                        <thead>
     
    163163        </g:else>       
    164164        <g:if test="${editable}">
    165                 <p class="options">
     165                <p class="options multiple">
    166166                        <% def writableAssaySamples = assaySamples.findAll { it.assay.study.canWrite( session.user ) } %>
    167                         <a class="addAssociation" onClick="showAddSamplesDialog(); return false;" href="#">Add samples</a>
     167                        <a class="addAssociation" onClick="showAddSamplesDialog(); return false;" href="#">Add samples</a><br />
    168168
    169169                        <g:if test="${writableAssaySamples.size() > 0}">
     
    173173                                <a class="editAssociation disabled" onClick="return false;" href="#">Edit sample data</a>
    174174                        </g:else>
    175 
    176                         <a class="fasta" href="#" onClick="submitPaginatedForm( $( '#sampleForm' ), '<g:createLink controller="assaySample" action="exportAsFasta" />', '#samples', 'Please select one or more samples to export' ); return false;">Export as fasta</a>
    177 
     175                       
     176                        <br />
     177
     178                        <g:if test="${writableAssaySamples.size() > 0}">
     179                                <a class="removeAssociation" href="#" onClick="if( confirm( 'Are you sure you want to remove selected samples from this run?' ) ) { submitPaginatedForm( $( '#sampleForm' ), '<g:createLink controller="run" action="removeSamples" />', '#samples', 'Please select one or more samples to remove from this run' ); } return false;">Remove selected samples</a>
     180                        </g:if>
     181                        <g:else>
     182                                <a class="removeAssociation disabled" onClick="return false;" href="#">Remove selected samples</a>
     183                        </g:else>
     184                </p>
     185                <p class="options multiple">
    178186                        <g:if test="${writableAssaySamples.size() == 0 || !run.assays?.size()}">
    179187                                <a class="addSequences disabled" onClick="return false;" href="#">Add sequence files</a>
     
    182190                                <a class="addSequences" onClick="showAddFilesDialog(); return false;" href="#">Add sequence files</a>
    183191                        </g:else>
     192                       
     193                        <br />
    184194
    185195                        <g:if test="${writableAssaySamples.size() > 0 && run.numFiles() > 0 }">
    186                                 <g:link class="delete" onClick="return confirm( 'Are you sure you want to remove all sequence data from this run? Only sequences are removed from samples you have write access to.' );" controller="run" action="deleteSequenceData" id="${run.id}">Delete all sequences</g:link>
    187                         </g:if>
    188                         <g:else>
    189                                 <a class="delete disabled" onClick="return false;" href="#">Delete all sequences</a>
    190                         </g:else>
    191                 </p>
     196                                <a class="removeSequences" href="#" onClick="if( confirm( 'Are you sure you want to remove all sequence data from this run? Only sequences are removed from samples you have write access to.' ) ) { submitPaginatedForm( $( '#sampleForm' ), '<g:createLink controller="run" action="deleteSequenceData" />', '#samples', 'Please select one or more samples to remove sequences from.' ); } return false;">Delete selected sequences</a>
     197                        </g:if>
     198                        <g:else>
     199                                <a class="removeSequences disabled" onClick="return false;" href="#">Delete selected sequences</a>
     200                        </g:else>
     201                </p>
     202               
     203                <p class="options multiple">
     204                        <a class="fasta" href="#" onClick="submitPaginatedForm( $( '#sampleForm' ), '<g:createLink controller="assaySample" action="exportAsFasta" />', '#samples', 'Please select one or more samples to export' ); return false;">Export as fasta</a><br />
     205                </p>
     206               
     207                <br clear="all" />             
    192208                <g:if test="${writableAssaySamples.size() > 0}">
    193209                        <g:render template="enterTagsDialog" model="[run: run, writableAssaySamples: writableAssaySamples]" />
  • trunk/web-app/css/buttons.css

    r49 r50  
    1212        background-position: 3px 50%;
    1313}
     14
     15.options.multiple { float: left; width: 300px; }
    1416
    1517.options .separator { margin-left: 20px; }
     
    3234        background-image:  url(../plugins/famfamfam-1.0.1/images/icons/page_attach.png);
    3335}
     36.options a.removeSequences {
     37        background-image:  url(../plugins/famfamfam-1.0.1/images/icons/page_delete.png);
     38}
    3439
    3540.options a.addAssociation {
     
    3944        background-image:  url(../plugins/famfamfam-1.0.1/images/icons/application_edit.png);
    4045}
     46.options a.removeAssociation,
     47.options a.deleteAssociation {
     48        background-image:  url(../plugins/famfamfam-1.0.1/images/icons/application_delete.png);
     49}
    4150
    4251.options a.delete {
  • trunk/web-app/js/assay.show.runDialogs.js

    r23 r50  
    77                tabs_disabled: numOtherRuns == 0 ? [1] : [],    // Disable 'existing' tab in addRuns when there are no additional runs available
    88                buttons: {
    9                         "Save": function() {
     9                        "Add": function() {
    1010                                var $tabs = $('#addRunDialog').tabs();
    1111                                var selectedTab = $tabs.tabs('option', 'selected' );
  • trunk/web-app/js/run.show.addSamplesDialog.js

    r23 r50  
    66                autoOpen: false,
    77                buttons: {
    8                         "Save": function() {
     8                        "Add": function() {
    99                                submitPaginatedForm(
    1010                                        $( 'form[name=addSamples]'  ),
  • trunk/web-app/js/run.show.assayDialog.js

    r23 r50  
    66                autoOpen: false,
    77                buttons: {
    8                         "Save": function() {
     8                        "Add": function() {
    99                                submitPaginatedForm(
    1010                                        $( 'form[name=addAssays]'  ),
Note: See TracChangeset for help on using the changeset viewer.