From ba0e5491ae55da8513370dbf5dec184a5c98802b Mon Sep 17 00:00:00 2001 From: Ramkrishna Chakrabarty Date: Fri, 14 Jan 2011 15:09:43 -0500 Subject: [PATCH] Added a new updater for number of sample datasets. The number of sample datasets now updates automatically. The sample states now gets updated only when barcodes are associated with them. Fixed rename dataset bug for AB Solid external service. --- .../applied_biosystems_solid.xml | 3 +- .../simple_unknown_sequencer.xml | 3 +- lib/galaxy/model/__init__.py | 23 +++++--- lib/galaxy/sample_tracking/data_transfer.py | 17 +++--- .../sample_tracking/external_service_types.py | 1 + lib/galaxy/web/controllers/requests_admin.py | 3 +- lib/galaxy/web/controllers/requests_common.py | 19 ++++++- templates/requests/common/common.mako | 52 ++++++++++++++++++- .../requests/common/sample_datasets.mako | 5 ++ templates/requests/common/view_request.mako | 10 +++- 10 files changed, 114 insertions(+), 22 deletions(-) create mode 100644 templates/requests/common/sample_datasets.mako diff --git a/external_service_types/applied_biosystems_solid.xml b/external_service_types/applied_biosystems_solid.xml index b5ec6cac4da..ca24a84c44b 100644 --- a/external_service_types/applied_biosystems_solid.xml +++ b/external_service_types/applied_biosystems_solid.xml @@ -3,8 +3,7 @@ 3 - + diff --git a/external_service_types/simple_unknown_sequencer.xml b/external_service_types/simple_unknown_sequencer.xml index 816e08b78a0..b7a01c44332 100644 --- a/external_service_types/simple_unknown_sequencer.xml +++ b/external_service_types/simple_unknown_sequencer.xml @@ -7,8 +7,7 @@ This is only for backward compatibility - +
diff --git a/lib/galaxy/model/__init__.py b/lib/galaxy/model/__init__.py index 666686cd72b..b33c2a68748 100644 --- a/lib/galaxy/model/__init__.py +++ b/lib/galaxy/model/__init__.py @@ -1717,6 +1717,14 @@ class Request( object, APIItem ): if not sample.library: samples.append( sample ) return samples + @property + def samples_with_bar_code( self ): + # Return all samples that have associated bar code + samples = [] + for sample in self.samples: + if sample.bar_code: + samples.append( sample ) + return samples def send_email_notification( self, trans, common_state, final_state=False ): # Check if an email notification is configured to be sent when the samples # are in this state @@ -1804,18 +1812,19 @@ class ExternalService( object ): def get_external_service_type( self, trans ): return trans.app.external_service_types.all_external_service_types[ self.external_service_type_id ] def load_data_transfer_settings( self, trans ): + trans.app.external_service_types.reload( self.external_service_type_id ) self.data_transfer = {} external_service_type = self.get_external_service_type( trans ) - for data_transfer_type, data_transfer in external_service_type.data_transfer.items(): + for data_transfer_type, data_transfer_obj in external_service_type.data_transfer.items(): if data_transfer_type == self.data_transfer_types.SCP: scp_configs = {} - automatic_transfer = self.form_values.content.get( data_transfer.config.get( 'automatic_transfer', 'false' ), 'false' ) + automatic_transfer = self.form_values.content.get( data_transfer_obj.config.get( 'automatic_transfer', 'false' ), 'false' ) scp_configs[ 'automatic_transfer' ] = util.string_as_bool( automatic_transfer ) - scp_configs[ 'host' ] = self.form_values.content.get( data_transfer.config.get( 'host', '' ), '' ) - scp_configs[ 'user_name' ] = self.form_values.content.get( data_transfer.config.get( 'user_name', '' ), '' ) - scp_configs[ 'password' ] = self.form_values.content.get( data_transfer.config.get( 'password', '' ), '' ) - scp_configs[ 'data_location' ] = self.form_values.content.get( data_transfer.config.get( 'data_location', '' ), '' ) - scp_configs[ 'rename_dataset' ] = self.form_values.content.get( data_transfer.config.get( 'rename_dataset', '' ), '' ) + scp_configs[ 'host' ] = self.form_values.content.get( data_transfer_obj.config.get( 'host', '' ), '' ) + scp_configs[ 'user_name' ] = self.form_values.content.get( data_transfer_obj.config.get( 'user_name', '' ), '' ) + scp_configs[ 'password' ] = self.form_values.content.get( data_transfer_obj.config.get( 'password', '' ), '' ) + scp_configs[ 'data_location' ] = self.form_values.content.get( data_transfer_obj.config.get( 'data_location', '' ), '' ) + scp_configs[ 'rename_dataset' ] = self.form_values.content.get( data_transfer_obj.config.get( 'rename_dataset', '' ), '' ) self.data_transfer[ self.data_transfer_types.SCP ] = scp_configs def populate_actions( self, trans, item, param_dict=None ): return self.get_external_service_type( trans ).actions.populate( self, item, param_dict=param_dict ) diff --git a/lib/galaxy/sample_tracking/data_transfer.py b/lib/galaxy/sample_tracking/data_transfer.py index 7691b2d411a..9112fcd36fc 100644 --- a/lib/galaxy/sample_tracking/data_transfer.py +++ b/lib/galaxy/sample_tracking/data_transfer.py @@ -2,7 +2,6 @@ import logging, sys class DataTransferFactory( object ): type = None - config = {} def parse( self ): pass @@ -11,14 +10,20 @@ class ScpDataTransferFactory( DataTransferFactory ): def __init__( self ): pass def parse( self, config_file, elem ): + self.config = {} # TODO: The 'automatic_transfer' setting is for future use. If set to True, we will need to # ensure the sample has an associated destination data library before it moves to a certain state # ( e.g., Run started ). - self.config[ 'automatic_transfer' ] = elem.get( 'automatic_transfer' ) - self.config[ 'host' ] = elem.get( 'host' ) - self.config[ 'user_name' ] = elem.get( 'user_name' ) - self.config[ 'password' ] = elem.get( 'password' ) - self.config[ 'data_location' ] = elem.get( 'data_location' ) + self.config['automatic_transfer'] = elem.get( 'automatic_transfer' ) + self.config['host'] = elem.get( 'host' ) + self.config['user_name'] = elem.get( 'user_name' ) + self.config['password'] = elem.get( 'password' ) + self.config['data_location'] = elem.get( 'data_location' ) + # 'rename_dataset' is optional and it may not be defined in all external types + # It is only used is AB SOLiD external service type for now + rename_dataset = elem.get( 'rename_dataset', None ) + if rename_dataset: + self.config['rename_dataset'] = rename_dataset # Validate for name, value in self.config.items(): assert value, "'%s' attribute missing in 'data_transfer' element of type 'scp' in external_service_type xml config file: '%s'." % ( name, config_file ) diff --git a/lib/galaxy/sample_tracking/external_service_types.py b/lib/galaxy/sample_tracking/external_service_types.py index 66508d1baed..baee06057cf 100644 --- a/lib/galaxy/sample_tracking/external_service_types.py +++ b/lib/galaxy/sample_tracking/external_service_types.py @@ -60,6 +60,7 @@ class ExternalServiceType( object ): self.config_file = external_service_type_xml_config self.parse( root ) self.visible = visible + root.clear() def parse( self, root ): # Get the name self.name = root.get( "name" ) diff --git a/lib/galaxy/web/controllers/requests_admin.py b/lib/galaxy/web/controllers/requests_admin.py index 2f65d5b60b3..5d34460fe93 100644 --- a/lib/galaxy/web/controllers/requests_admin.py +++ b/lib/galaxy/web/controllers/requests_admin.py @@ -387,7 +387,7 @@ class RequestsAdmin( BaseController, UsesFormDefinitions ): kwd[ 'message' ] = message del kwd[ 'select_datasets_to_transfer_button' ] handle_error( **kwd ) - if sample in sample.request.samples_without_library_destinations: + if not sample.library: # Display an error if a sample has been selected that # has not yet been associated with a destination library. message = 'Select a target data library and folder for the sample before selecting the datasets.' @@ -487,6 +487,7 @@ class RequestsAdmin( BaseController, UsesFormDefinitions ): status=status, message=message ) ) def __save_sample_datasets( self, trans, sample, selected_datasets_to_transfer, external_service ): + external_service.load_data_transfer_settings( trans ) scp_configs = external_service.data_transfer[ trans.model.ExternalService.data_transfer_types.SCP ] sample_dataset_file_names = [] if selected_datasets_to_transfer: diff --git a/lib/galaxy/web/controllers/requests_common.py b/lib/galaxy/web/controllers/requests_common.py index e250cfd38f2..a0476c2e539 100644 --- a/lib/galaxy/web/controllers/requests_common.py +++ b/lib/galaxy/web/controllers/requests_common.py @@ -107,12 +107,29 @@ class RequestsCommon( BaseController, UsesFormDefinitions ): sample = trans.sa_session.query( self.app.model.Sample ).get( id ) if sample.state.name != state: rval[ id ] = { "state": sample.state.name, - "datasets": len( sample.datasets ), "html_state": unicode( trans.fill_template( "requests/common/sample_state.mako", sample=sample), 'utf-8' ) } return rval @web.json + def sample_datasets_updates( self, trans, ids=None, datasets=None ): + # Avoid caching + trans.response.headers['Pragma'] = 'no-cache' + trans.response.headers['Expires'] = '0' + # Create new HTML for any that have changed + rval = {} + if ids is not None and datasets is not None: + ids = map( int, ids.split( "," ) ) + number_of_datasets_list = map(int, datasets.split( "," ) ) + for id, number_of_datasets in zip( ids, number_of_datasets_list ): + sample = trans.sa_session.query( self.app.model.Sample ).get( id ) + if len(sample.datasets) != number_of_datasets: + rval[ id ] = { "datasets": len( sample.datasets ), + "html_datasets": unicode( trans.fill_template( "requests/common/sample_datasets.mako", + sample=sample), + 'utf-8' ) } + return rval + @web.json def dataset_transfer_status_updates( self, trans, ids=None, transfer_status_list=None ): # Avoid caching trans.response.headers['Pragma'] = 'no-cache' diff --git a/templates/requests/common/common.mako b/templates/requests/common/common.mako index 0260c23b538..1425f23b3a5 100644 --- a/templates/requests/common/common.mako +++ b/templates/requests/common/common.mako @@ -98,7 +98,7 @@ data: { ids: ids.join( "," ), states: states.join( "," ) }, success : function ( data ) { $.each( data, function( id, val ) { - // Replace HTML + // Replace sample state HTML var cell1 = $("#sampleState-" + id); cell1.html( val.html_state ); sample_states[ parseInt( id ) ] = val.state; @@ -113,6 +113,54 @@ }; + // Sample Datasets Updater + // + // Looks for changes in the number sample datasets using an async request. Keeps + // calling itself (via setTimeout) until all samples are in a terminal + // state. + var sample_datasets_updater = function ( sample_datasets ) { + // Check if there are any items left to track + var empty = true; + for ( i in sample_datasets ) { + empty = false; + break; + } + if ( ! empty ) { + setTimeout( function() { sample_datasets_updater_callback( sample_datasets ) }, 1000 ); + } + }; + var sample_datasets_updater_callback = function ( sample_datasets ) { + // Build request data + var ids = [] + var datasets = [] + $.each( sample_datasets, function ( id, num_of_datasets ) { + ids.push( id ); + datasets.push( num_of_datasets ); + }); + // Make ajax call + $.ajax( { + type: "POST", + url: "${h.url_for( controller='requests_common', action='sample_datasets_updates' )}", + dataType: "json", + data: { ids: ids.join( "," ), datasets: datasets.join( "," ) }, + success : function ( data ) { + $.each( data, function( id, val ) { + // Replace sample datasets HTML + var cell2 = $("#sampleDatasets-" + id); + cell2.html( val.html_datasets ); + sample_datasets[ parseInt( id ) ] = val.datasets; + + }); + sample_datasets_updater( sample_datasets ); + }, + error: function() { + // Just retry, like the old method, should try to be smarter + sample_datasets_updater( sample_datasets ); + } + }); + }; + + // Sample Dataset Transfer Status Updater // // It is used to update the transfer status on Manage Datasets page for a sample @@ -392,7 +440,7 @@ ## An admin can select the datasets to transfer, while a non-admin can only view what has been selected %if is_admin: ## This link will direct the admin to a page allowing them to manage datasets. - ${len( sample.datasets )} + ${len( sample.datasets )} %elif sample.datasets: ## Since this is a regular user, only display a link if there is at least 1 ## selected dataset for the sample. diff --git a/templates/requests/common/sample_datasets.mako b/templates/requests/common/sample_datasets.mako new file mode 100644 index 00000000000..b98dec42eb5 --- /dev/null +++ b/templates/requests/common/sample_datasets.mako @@ -0,0 +1,5 @@ +<%def name="render_sample_datasets( sample )"> + ${len( sample.datasets )} + + +${render_sample_datasets( sample )} diff --git a/templates/requests/common/view_request.mako b/templates/requests/common/view_request.mako index 0d368420f39..75899c067b7 100644 --- a/templates/requests/common/view_request.mako +++ b/templates/requests/common/view_request.mako @@ -144,12 +144,20 @@ ${states}
- %if request.samples and request.is_submitted: + ## Sample state updater + %if request.samples and request.is_submitted and request.samples_with_bar_code: %endif + ## Number of sample state updater + %if request.samples and request.is_submitted: + + %endif