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.
This commit is contained in:
Ramkrishna Chakrabarty
2011-01-14 15:09:43 -05:00
parent a3ed7733a6
commit ba0e5491ae
10 changed files with 114 additions and 22 deletions
@@ -3,8 +3,7 @@
<version>3</version>
<data_transfer_settings>
<data_transfer type='scp' automatic_transfer='False' host='host' user_name='user_name' password='password'
data_location='data_location' rename_dataset='rename_dataset' />
<data_transfer type='scp' automatic_transfer='False' host='host' user_name='user_name' password='password' data_location='data_location' rename_dataset='rename_dataset' />
</data_transfer_settings>
<run_details>
@@ -7,8 +7,7 @@ This is only for backward compatibility
<description></description>
<version></version>
<data_transfer_settings>
<data_transfer type='scp' automatic_transfer='False' host='host' user_name='user_name' password='password'
data_location='data_location' rename_dataset='rename_dataset' />
<data_transfer type='scp' automatic_transfer='False' host='host' user_name='user_name' password='password' data_location='data_location'/>
</data_transfer_settings>
<form type="external_service" name="Simple unknown sequencer form" description="">
<fields>
+16 -7
View File
@@ -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 )
+11 -6
View File
@@ -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 )
@@ -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" )
+2 -1
View File
@@ -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:
+18 -1
View File
@@ -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'
+50 -2
View File
@@ -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.
<a href="${h.url_for( controller='requests_admin', action='manage_datasets', cntrller=cntrller, sample_id=trans.security.encode_id( sample.id ) )}">${len( sample.datasets )}</a>
<a id="sampleDatasets-${sample.id}" href="${h.url_for( controller='requests_admin', action='manage_datasets', cntrller=cntrller, sample_id=trans.security.encode_id( sample.id ) )}">${len( sample.datasets )}</a>
%elif sample.datasets:
## Since this is a regular user, only display a link if there is at least 1
## selected dataset for the sample.
@@ -0,0 +1,5 @@
<%def name="render_sample_datasets( sample )">
${len( sample.datasets )}
</%def>
${render_sample_datasets( sample )}
+9 -1
View File
@@ -144,12 +144,20 @@
${states}
<div style="clear: both"></div>
</div>
%if request.samples and request.is_submitted:
## Sample state updater
%if request.samples and request.is_submitted and request.samples_with_bar_code:
<script type="text/javascript">
// Updater
sample_state_updater( {${ ",".join( [ '"%s" : "%s"' % ( s.id, s.state.name ) for s in request.samples ] ) }});
</script>
%endif
## Number of sample state updater
%if request.samples and request.is_submitted:
<script type="text/javascript">
// Updater
sample_datasets_updater( {${ ",".join( [ '"%s" : "%s"' % ( s.id, len(s.datasets) ) for s in request.samples ] ) }});
</script>
%endif
</div>
</div>
</div>