galaxy-dist commit d24fca10862b: Add support for all Galaxy form widget types to data library templates ( library templates now support SelectField, AddressField, CheckboxField, WorkflowField in addition to previously supported TextArea and TextField ).
# HG changeset patch -- Bitbucket.org # Project galaxy-dist # URL http://bitbucket.org/galaxy/galaxy-dist/overview # User Greg Von Kuster <greg@bx.psu.edu> # Date 1282834547 14400 # Node ID d24fca10862b5b36ba3dbe8a9f318e2e77ef60f2 # Parent af3ee1e9f9e3c0e51b7b18a323b3fa80460aa864 Add support for all Galaxy form widget types to data library templates ( library templates now support SelectField, AddressField, CheckboxField, WorkflowField in addition to previously supported TextArea and TextField ). Create a new UsesFormDefinitionWidgets base controller class for use with all inheriting controllers that use Galaxy forms. Clean up some of the existing code by re-using mehtods in this new controller. Fix bugs related to new user address creation and editing existing user addresses: (1) form contents are now actually checked and if required, error messages are displayed (2) since there is only 1 "address" row in the UserAddress table, eliminate the address1 / address2 form field combination that was appened together for storage in the table ( ther eis now only 1 address line on all forms ). Fix functional tests to reflect above changes. --- a/templates/mobile/manage_library.mako +++ b/templates/mobile/manage_library.mako @@ -1,7 +1,7 @@ <%inherit file="/base.mako"/><%namespace file="/message.mako" import="render_msg" /><%namespace file="/dataset/security_common.mako" import="render_permission_form" /> -<%namespace file="/library/common/common.mako" import="render_template_info" /> +<%namespace file="/library/common/common.mako" import="render_template_fields" /><% current_user_roles = trans.get_current_user_roles() %> @@ -59,7 +59,7 @@ </div><div style="clear: both"></div><div class="toolForm"> - ${render_template_info( 'mobile', library, library.id, 'library' )} + ${render_template_fields( 'mobile', 'library', trans.security.encode_id( library.id ), widgets, widget_fields_have_contents, info_association, inherited )} </div></div> %endif @@ -69,5 +69,5 @@ %endif %if widgets: - ${render_template_info( 'mobile', library, trans.security.encode_id( library.id ), 'edit_library_information', widgets )} + ${render_template_fields( 'mobile', 'library', trans.security.encode_id( library.id ), widgets, widget_fields_have_contents, info_association inherited )} %endif --- a/templates/library/common/library_dataset_info.mako +++ b/templates/library/common/library_dataset_info.mako @@ -1,6 +1,34 @@ <%inherit file="/base.mako"/><%namespace file="/message.mako" import="render_msg" /> -<%namespace file="/library/common/common.mako" import="render_template_info" /> +<%namespace file="/library/common/common.mako" import="render_template_fields" /> + +<%def name="javascripts()"> + ${parent.javascripts()} + <script type="text/javascript"> + $( function() { + $( "select[refresh_on_change='true']").change( function() { + var refresh = false; + var refresh_on_change_values = $( this )[0].attributes.getNamedItem( 'refresh_on_change_values' ) + if ( refresh_on_change_values ) { + refresh_on_change_values = refresh_on_change_values.value.split( ',' ); + var last_selected_value = $( this )[0].attributes.getNamedItem( 'last_selected_value' ); + for( i= 0; i < refresh_on_change_values.length; i++ ) { + if ( $( this )[0].value == refresh_on_change_values[i] || ( last_selected_value && last_selected_value.value == refresh_on_change_values[i] ) ){ + refresh = true; + break; + } + } + } + else { + refresh = true; + } + if ( refresh ){ + $( "#edit_info" ).submit(); + } + }); + }); + </script> +</%def> %if library_dataset == library_dataset.library_dataset_dataset_association.library_dataset: <b><i>This is the latest version of this library dataset</i></b> @@ -63,5 +91,5 @@ %if widgets: ## Templates are not currently supported for library_datasets, only the associated ldda. - ${render_template_info( cntrller, 'library_dataset', library_id, widgets, info_association=None, inherited=False, editable=False )} + ${render_template_fields( cntrller, 'library_dataset', library_id, widgets, widget_fields_have_contents, info_association=None, inherited=False, editable=False )} %endif --- a/templates/library/common/folder_info.mako +++ b/templates/library/common/folder_info.mako @@ -1,6 +1,34 @@ <%inherit file="/base.mako"/><%namespace file="/message.mako" import="render_msg" /> -<%namespace file="/library/common/common.mako" import="render_template_info" /> +<%namespace file="/library/common/common.mako" import="render_template_fields" /> + +<%def name="javascripts()"> + ${parent.javascripts()} + <script type="text/javascript"> + $( function() { + $( "select[refresh_on_change='true']").change( function() { + var refresh = false; + var refresh_on_change_values = $( this )[0].attributes.getNamedItem( 'refresh_on_change_values' ) + if ( refresh_on_change_values ) { + refresh_on_change_values = refresh_on_change_values.value.split( ',' ); + var last_selected_value = $( this )[0].attributes.getNamedItem( 'last_selected_value' ); + for( i= 0; i < refresh_on_change_values.length; i++ ) { + if ( $( this )[0].value == refresh_on_change_values[i] || ( last_selected_value && last_selected_value.value == refresh_on_change_values[i] ) ){ + refresh = true; + break; + } + } + } + else { + refresh = true; + } + if ( refresh ){ + $( "#edit_info" ).submit(); + } + }); + }); + </script> +</%def><% from cgi import escape @@ -53,5 +81,5 @@ </div></div> %if widgets: - ${render_template_info( cntrller=cntrller, item_type='folder', library_id=library_id, widgets=widgets, info_association=info_association, inherited=inherited, folder_id=trans.security.encode_id( folder.id ) )} + ${render_template_fields( cntrller=cntrller, item_type='folder', library_id=library_id, widgets=widgets, widget_fields_have_contents=widget_fields_have_contents, info_association=info_association, inherited=inherited, folder_id=trans.security.encode_id( folder.id ) )} %endif --- a/lib/galaxy/web/form_builder.py +++ b/lib/galaxy/web/form_builder.py @@ -384,8 +384,7 @@ class AddressField(BaseField): return [ ( "short_desc", "Short address description"), ( "name", "Name" ), ( "institution", "Institution" ), - ( "address1", "Address Line 1" ), - ( "address2", "Address Line 2" ), + ( "address", "Address" ), ( "city", "City" ), ( "state", "State/Province/Region" ), ( "postal_code", "Postal Code" ), @@ -437,8 +436,7 @@ class AddressField(BaseField): else: self.select_address.add_option('Add a new address', 'new') return self.select_address.get_html()+address_html - - + class WorkflowField(BaseField): def __init__(self, name, user=None, value=None, params=None): self.name = name --- a/lib/galaxy/web/base/controller.py +++ b/lib/galaxy/web/base/controller.py @@ -8,6 +8,7 @@ from galaxy.web import error, form, url_ from galaxy.model.orm import * from galaxy.workflow.modules import * from galaxy.web.framework import simplejson +from galaxy.web.form_builder import AddressField, CheckboxField, SelectField, TextArea, TextField, WorkflowField from Cheetah.Template import Template @@ -290,7 +291,57 @@ class UsesHistory( SharableItemSecurity if not show_deleted: query = query.filter( trans.model.HistoryDatasetAssociation.deleted == False ) return query.all() - + +class UsesFormDefinitionWidgets: + """Mixin for controllers that use Galaxy form objects.""" + def widget_fields_have_contents( self, widgets ): + # Return True if any of the fields in widgets contain contents, widgets is a list of dictionaries that looks something like: + # [{'widget': <galaxy.web.form_builder.TextField object at 0x10867aa10>, 'helptext': 'Field 0 help (Optional)', 'label': 'Field 0'}] + for i, field in enumerate( widgets ): + if ( isinstance( field[ 'widget' ], TextArea ) or isinstance( field[ 'widget' ], TextField ) ) and field[ 'widget' ].value: + return True + if isinstance( field[ 'widget' ], SelectField ) and field[ 'widget' ].options: + for option_label, option_value, selected in field['widget'].options: + if selected: + return True + if isinstance( field[ 'widget' ], CheckboxField ) and field[ 'widget' ].checked: + return True + if isinstance( field[ 'widget' ], WorkflowField ) and field[ 'widget' ].value not in [ 'none', 'None', None ]: + return True + if isinstance( field[ 'widget' ], AddressField ) and field[ 'widget' ].value not in [ 'none', 'None', None ]: + return True + return False + def clean_field_contents( self, widgets, **kwd ): + params = util.Params( kwd ) + field_contents = [] + for index in range( len( widgets ) ): + widget = widgets[ index ][ 'widget' ] + field_value = params.get( 'field_%i' % ( index ), '' ) + if isinstance( widget, CheckboxField ): + # CheckboxField values are lists if the checkbox is checked + field_value = str( widget.is_checked( field_value ) ).lower() + elif isinstance( widget, AddressField ): + # If the address was new, is has already been saved and widget.value is the new address.id + field_value = widget.value + field_contents.append( util.restore_text( field_value ) ) + return field_contents + def save_widget_field( self, trans, field_obj, index, **kwd ): + # Save a form_builder field object + # TODO: Add support for other field types ( e.g., WorkflowField ) + params = util.Params( kwd ) + if isinstance( field_obj, trans.model.UserAddress ): + field_obj.desc = util.restore_text( params.get( 'field_%i_short_desc' % index, '' ) ) + field_obj.name = util.restore_text( params.get( 'field_%i_name' % index, '' ) ) + field_obj.institution = util.restore_text( params.get( 'field_%i_institution' % index, '' ) ) + field_obj.address = util.restore_text( params.get( 'field_%i_address' % index, '' ) ) + field_obj.city = util.restore_text( params.get( 'field_%i_city' % index, '' ) ) + field_obj.state = util.restore_text( params.get( 'field_%i_state' % index, '' ) ) + field_obj.postal_code = util.restore_text( params.get( 'field_%i_postal_code' % index, '' ) ) + field_obj.country = util.restore_text( params.get( 'field_%i_country' % index, '' ) ) + field_obj.phone = util.restore_text( params.get( 'field_%i_phone' % index, '' ) ) + trans.sa_session.add( field_obj ) + trans.sa_session.flush() + class Sharable: """ Mixin for a controller that manages an item that can be shared. """ # Implemented methods. --- a/test/functional/test_forms_and_requests.py +++ b/test/functional/test_forms_and_requests.py @@ -13,17 +13,15 @@ request_type_name = 'Test Requestype' sample_states = [ ( 'New', 'Sample entered into the system' ), ( 'Received', 'Sample tube received' ), ( 'Done', 'Sequence run complete' ) ] -address1 = dict( short_desc="Office", - name="James+Bond", - institution="MI6" , - address1="MI6+Headquarters", - address2="", - city="London", - state="London", - postal_code="007", - country="United+Kingdom", - phone="007-007-0007" ) - +address_dict = dict( short_desc="Office", + name="James+Bond", + institution="MI6" , + address="MI6+Headquarters", + city="London", + state="London", + postal_code="007", + country="United+Kingdom", + phone="007-007-0007" ) def get_latest_form(form_name): fdc_list = sa_session.query( galaxy.model.FormDefinitionCurrent ) \ @@ -36,7 +34,6 @@ def get_latest_form(form_name): return fdc.latest_form return None - class TestFormsAndRequests( TwillTestCase ): def test_000_initiate_users( self ): """Ensuring all required user accounts exist""" @@ -114,7 +111,7 @@ class TestFormsAndRequests( TwillTestCas def test_010_create_form( self ): """Testing creating a new form and editing it""" self.logout() - self.login( email='test@bx.psu.edu' ) + self.login( email=admin_user.email ) # create a form global form_one_name desc = "This is Form One's description" @@ -197,7 +194,6 @@ class TestFormsAndRequests( TwillTestCas pass self.logout() self.login( email=admin_user.email ) - def test_030_create_address_and_library( self ): """Testing address & library creation""" # first create a library for the request so that it can be submitted later @@ -249,22 +245,15 @@ class TestFormsAndRequests( TwillTestCas assert folder_one is not None, 'Problem retrieving library folder named "%s" from the database' % name # create address self.logout() - self.login( email='test1@bx.psu.edu', username='regular-user1' ) - self.add_user_address( regular_user1.id, address1 ) - global regular_user - regular_user = sa_session.query( galaxy.model.User ) \ - .filter( galaxy.model.User.table.c.email=='test1@bx.psu.edu' ) \ - .first() + self.login( email=regular_user1.email ) + self.add_user_address( regular_user1.id, address_dict ) global user_address - user_address = sa_session.query( galaxy.model.UserAddress ) \ - .filter( and_( galaxy.model.UserAddress.table.c.desc==address1[ 'short_desc' ], - galaxy.model.UserAddress.table.c.deleted==False ) ) \ - .first() + user_address = get_user_address( regular_user1, address_dict[ 'short_desc' ] ) def test_035_create_request( self ): """Testing creating, editing and submitting a request as a regular user""" # login as a regular user self.logout() - self.login( email='test1@bx.psu.edu', username='regular-user1' ) + self.login( email=regular_user1.email ) # set field values fields = ['option1', str(user_address.id), 'field three value'] # create the request @@ -302,7 +291,7 @@ class TestFormsAndRequests( TwillTestCas """Testing request lifecycle as it goes through all the states""" # goto admin manage requests page self.logout() - self.login( email='test@bx.psu.edu' ) + self.login( email=admin_user.email ) self.check_request_admin_grid(state=request_one.states.SUBMITTED, request_name=request_one.name) self.visit_url( "%s/requests_admin/list?operation=show&id=%s" \ % ( self.url, self.security.encode_id( request_one.id ) )) @@ -317,7 +306,7 @@ class TestFormsAndRequests( TwillTestCas self.home() sa_session.refresh( request_one ) self.logout() - self.login( email='test1@bx.psu.edu', username='regular-user1' ) + self.login( email=regular_user1.email ) # check if the request's state is now set to 'complete' self.check_request_grid(state='Complete', request_name=request_one.name) assert request_one.state is not request_one.states.COMPLETE, "The state of the request '%s' should be set to '%s'" \ @@ -325,11 +314,11 @@ class TestFormsAndRequests( TwillTestCas def test_045_admin_create_request_on_behalf_of_regular_user( self ): """Testing creating and submitting a request as an admin on behalf of a regular user""" self.logout() - self.login( email='test@bx.psu.edu' ) + self.login( email=admin_user.email ) request_name = "RequestTwo" # simulate request creation url_str = '%s/requests_common/new?cntrller=requests_admin&create_request_button=Save&select_request_type=%i&select_user=%i&name=%s&refresh=True&field_2=%s&field_0=%s&field_1=%i' \ - % ( self.url, request_type.id, regular_user.id, request_name, "field_2_value", 'option1', user_address.id ) + % ( self.url, request_type.id, regular_user1.id, request_name, "field_2_value", 'option1', user_address.id ) print url_str self.home() self.visit_url( url_str ) @@ -363,7 +352,7 @@ class TestFormsAndRequests( TwillTestCas def test_050_reject_request( self ): '''Testing rejecting a request''' self.logout() - self.login( email='test@bx.psu.edu' ) + self.login( email=admin_user.email ) self.reject_request( request_two.id, request_two.name, "Rejection test comment" ) sa_session.refresh( request_two ) # check if the request is showing in the 'rejected' filter --- a/templates/library/common/library_info.mako +++ b/templates/library/common/library_info.mako @@ -1,6 +1,34 @@ <%inherit file="/base.mako"/><%namespace file="/message.mako" import="render_msg" /> -<%namespace file="/library/common/common.mako" import="render_template_info" /> +<%namespace file="/library/common/common.mako" import="render_template_fields" /> + +<%def name="javascripts()"> + ${parent.javascripts()} + <script type="text/javascript"> + $( function() { + $( "select[refresh_on_change='true']").change( function() { + var refresh = false; + var refresh_on_change_values = $( this )[0].attributes.getNamedItem( 'refresh_on_change_values' ) + if ( refresh_on_change_values ) { + refresh_on_change_values = refresh_on_change_values.value.split( ',' ); + var last_selected_value = $( this )[0].attributes.getNamedItem( 'last_selected_value' ); + for( i= 0; i < refresh_on_change_values.length; i++ ) { + if ( $( this )[0].value == refresh_on_change_values[i] || ( last_selected_value && last_selected_value.value == refresh_on_change_values[i] ) ){ + refresh = true; + break; + } + } + } + else { + refresh = true; + } + if ( refresh ){ + $( "#edit_info" ).submit(); + } + }); + }); + </script> +</%def><% from cgi import escape @@ -107,5 +135,5 @@ </div> %if widgets: - ${render_template_info( cntrller=cntrller, item_type='library', library_id=trans.security.encode_id( library.id ), widgets=widgets, info_association=info_association, inherited=inherited, editable=not( library.deleted ) )} + ${render_template_fields( cntrller=cntrller, item_type='library', library_id=trans.security.encode_id( library.id ), widgets=widgets, widget_fields_have_contents=widget_fields_have_contents, info_association=info_association, inherited=inherited, editable=not( library.deleted ) )} %endif --- a/lib/galaxy/web/controllers/user.py +++ b/lib/galaxy/web/controllers/user.py @@ -26,7 +26,7 @@ require_login_creation_template = requir VALID_USERNAME_RE = re.compile( "^[a-z0-9\-]+$" ) -class User( BaseController ): +class User( BaseController, UsesFormDefinitionWidgets ): @web.expose def index( self, trans, webapp='galaxy', **kwd ): return trans.fill_template( '/user/index.mako', webapp=webapp ) @@ -263,17 +263,7 @@ class User( BaseController ): if value == 'new': # save this new address in the list of this user's addresses user_address = trans.app.model.UserAddress( user=user ) - user_address.desc = util.restore_text(params.get('field_%i_short_desc' % index, '')) - user_address.name = util.restore_text(params.get('field_%i_name' % index, '')) - user_address.institution = util.restore_text(params.get('field_%i_institution' % index, '')) - user_address.address = util.restore_text(params.get('field_%i_address1' % index, ''))+' '+util.restore_text(params.get('field_%i_address2' % index, '')) - user_address.city = util.restore_text(params.get('field_%i_city' % index, '')) - user_address.state = util.restore_text(params.get('field_%i_state' % index, '')) - user_address.postal_code = util.restore_text(params.get('field_%i_postal_code' % index, '')) - user_address.country = util.restore_text(params.get('field_%i_country' % index, '')) - user_address.phone = util.restore_text(params.get('field_%i_phone' % index, '')) - trans.sa_session.add( user_address ) - trans.sa_session.flush() + self.save_widget_field( trans, user_address, index, **kwd ) trans.sa_session.refresh( user ) values.append(int(user_address.id)) elif value == unicode('none'): @@ -673,8 +663,7 @@ class User( BaseController ): return trans.fill_template( 'user/permissions.mako' ) else: # User not logged in, history group must be only public - return trans.show_error_message( "You must be logged in to change your default permitted actions." ) - + return trans.show_error_message( "You must be logged in to change your default permitted actions." ) @web.expose @web.require_login( "to get most recently used tool" ) @web.json_pretty @@ -697,8 +686,7 @@ class User( BaseController ): "minsizehint" : tool.uihints.get( 'minwidth', -1 ), "description" : tool.description } - return tool_info - + return tool_info @web.expose def manage_addresses(self, trans, **kwd): if trans.user: @@ -726,123 +714,151 @@ class User( BaseController ): message = util.restore_text( params.get( 'message', '' ) ) status = params.get( 'status', 'done' ) admin_view = util.string_as_bool( params.get( 'admin_view', False ) ) - error = '' - user = trans.sa_session.query( trans.app.model.User ).get( int( params.get( 'user_id', None ) ) ) + user_id = params.get( 'user_id', False ) + if not user_id: + # User must be logged in to create a new address + return trans.show_error_message( "You must be logged in to create a new address." ) + user = trans.sa_session.query( trans.app.model.User ).get( int( user_id ) ) + short_desc = util.restore_text( params.get( 'short_desc', '' ) ) + name = util.restore_text( params.get( 'name', '' ) ) + institution = util.restore_text( params.get( 'institution', '' ) ) + address = util.restore_text( params.get( 'address', '' ) ) + city = util.restore_text( params.get( 'city', '' ) ) + state = util.restore_text( params.get( 'state', '' ) ) + postal_code = util.restore_text( params.get( 'postal_code', '' ) ) + country = util.restore_text( params.get( 'country', '' ) ) + phone = util.restore_text( params.get( 'phone', '' ) ) + ok = True if not trans.app.config.allow_user_creation and not trans.user_is_admin(): return trans.show_error_message( 'User registration is disabled. Please contact your Galaxy administrator for an account.' ) - if params.get( 'save_new_address_button', None ) == 'Save': - if not len( util.restore_text( params.get( 'short_desc', '' ) ) ): - error = 'Enter a short description for this address' - elif not len( util.restore_text( params.get( 'name', '' ) ) ): - error = 'Enter the full name' - elif not len( util.restore_text( params.get( 'institution', '' ) ) ): - error = 'Enter the institution associated with the user' - elif not len ( util.restore_text( params.get( 'address1', '' ) ) ): - error = 'Enter the address' - elif not len( util.restore_text( params.get( 'city', '' ) ) ): - error = 'Enter the city' - elif not len( util.restore_text( params.get( 'state', '' ) ) ): - error = 'Enter the state/province/region' - elif not len( util.restore_text( params.get( 'postal_code', '' ) ) ): - error = 'Enter the postal code' - elif not len( util.restore_text( params.get( 'country', '' ) ) ): - error = 'Enter the country' - else: - user_address = trans.app.model.UserAddress( user=user ) - user_address.desc = util.restore_text( params.get( 'short_desc', '' ) ) - user_address.name = util.restore_text( params.get( 'name', '' ) ) - user_address.institution = util.restore_text( params.get( 'institution', '' ) ) - user_address.address = util.restore_text( params.get( 'address1', '' ) )+' '+util.restore_text( params.get( 'address2', '' ) ) - user_address.city = util.restore_text( params.get( 'city', '' ) ) - user_address.state = util.restore_text( params.get( 'state', '' ) ) - user_address.postal_code = util.restore_text( params.get( 'postal_code', '' ) ) - user_address.country = util.restore_text( params.get( 'country', '' ) ) - user_address.phone = util.restore_text( params.get( 'phone', '' ) ) + if params.get( 'new_address_button', False ): + if not short_desc: + ok = False + message = 'Enter a short description for this address' + elif not name: + ok = False + message = 'Enter the name' + elif not institution: + ok = False + message = 'Enter the institution associated with the user' + elif not address: + ok = False + message = 'Enter the address' + elif not city: + ok = False + message = 'Enter the city' + elif not state: + ok = False + message = 'Enter the state/province/region' + elif not postal_code: + ok = False + message = 'Enter the postal code' + elif not country: + ok = False + message = 'Enter the country' + if ok: + user_address = trans.model.UserAddress( user=user, + desc=short_desc, + name=name, + institution=institution, + address=address, + city=city, + state=state, + postal_code=postal_code, + country=country, + phone=phone ) trans.sa_session.add( user_address ) trans.sa_session.flush() - message = 'Address <b>%s</b> has been added' % user_address.desc + message = 'Address (%s) has been added' % user_address.desc if admin_view: return trans.response.send_redirect( web.url_for( controller='user', action='show_info', admin_view=admin_view, user_id=user.id, message=message, - status='done') ) + status='done' ) ) return trans.response.send_redirect( web.url_for( controller='user', action='show_info', message=message, - status='done') ) - else: - # show the address form with the current values filled in - # create the widgets for each address field - widgets = [] - widgets.append(dict(label='Short description', - widget=TextField( 'short_desc', 40, '' ) ) ) - widgets.append(dict(label='Name', - widget=TextField( 'name', 40, '' ) ) ) - widgets.append(dict(label='Institution', - widget=TextField( 'institution', 40, '' ) ) ) - widgets.append(dict(label='Address Line 1', - widget=TextField( 'address1', 40, '' ) ) ) - widgets.append(dict(label='Address Line 2', - widget=TextField( 'address2', 40, '' ) ) ) - widgets.append(dict(label='City', - widget=TextField( 'city', 40, '' ) ) ) - widgets.append(dict(label='State', - widget=TextField( 'state', 40, '' ) ) ) - widgets.append(dict(label='Postal Code', - widget=TextField( 'postal_code', 40, '' ) ) ) - widgets.append(dict(label='Country', - widget=TextField( 'country', 40, '' ) ) ) - widgets.append(dict(label='Phone', - widget=TextField( 'phone', 40, '' ) ) ) - return trans.fill_template( 'user/new_address.mako', - user=user, - admin_view=admin_view, - widgets=widgets, - message=message, - status=status) + status='done' ) ) + # Display the address form with the current values filled in + return trans.fill_template( 'user/new_address.mako', + user=user, + admin_view=admin_view, + short_desc=short_desc, + name=name, + institution=institution, + address=address, + city=city, + state=state, + postal_code=postal_code, + country=country, + phone=phone, + message=message, + status=status ) @web.expose def edit_address( self, trans, **kwd ): params = util.Params( kwd ) - user_id = params.get( 'user_id', None ) - address_id = params.get( 'address_id', None ) message = util.restore_text( params.get( 'message', '' ) ) status = params.get( 'status', 'done' ) admin_view = util.string_as_bool( params.get( 'admin_view', False ) ) - error = '' + user_id = params.get( 'user_id', False ) + if not user_id: + # User must be logged in to create a new address + return trans.show_error_message( "You must be logged in to create a new address." ) user = trans.sa_session.query( trans.app.model.User ).get( int( user_id ) ) - user_address = trans.sa_session.query( trans.app.model.UserAddress ).get( int( address_id ) ) - if params.get( 'edit_address_button', None ) == 'Save changes': - if not len( util.restore_text( params.get( 'short_desc', '' ) ) ): - error = 'Enter a short description for this address' - elif not len( util.restore_text( params.get( 'name', '' ) ) ): - error = 'Enter the full name' - elif not len( util.restore_text( params.get( 'institution', '' ) ) ): - error = 'Enter the institution associated with the user' - elif not len ( util.restore_text( params.get( 'address1', '' ) ) ): - error = 'Enter the address' - elif not len( util.restore_text( params.get( 'city', '' ) ) ): - error = 'Enter the city' - elif not len( util.restore_text( params.get( 'state', '' ) ) ): - error = 'Enter the state/province/region' - elif not len( util.restore_text( params.get( 'postal_code', '' ) ) ): - error = 'Enter the postal code' - elif not len( util.restore_text( params.get( 'country', '' ) ) ): - error = 'Enter the country' - else: - user_address.desc = util.restore_text( params.get( 'short_desc', '' ) ) - user_address.name = util.restore_text( params.get( 'name', '' ) ) - user_address.institution = util.restore_text( params.get( 'institution', '' ) ) - user_address.address = util.restore_text( params.get( 'address1', '' ) )+' '+util.restore_text( params.get( 'address2', '' ) ) - user_address.city = util.restore_text( params.get( 'city', '' ) ) - user_address.state = util.restore_text( params.get( 'state', '' ) ) - user_address.postal_code = util.restore_text( params.get( 'postal_code', '' ) ) - user_address.country = util.restore_text( params.get( 'country', '' ) ) - user_address.phone = util.restore_text( params.get( 'phone', '' ) ) - trans.sa_session.add( user_address ) + address_id = params.get( 'address_id', None ) + if not address_id: + return trans.show_error_message( "No address_id received for editing." ) + address_obj = trans.sa_session.query( trans.app.model.UserAddress ).get( int( address_id ) ) + if params.get( 'edit_address_button', False ): + short_desc = util.restore_text( params.get( 'short_desc', '' ) ) + name = util.restore_text( params.get( 'name', '' ) ) + institution = util.restore_text( params.get( 'institution', '' ) ) + address = util.restore_text( params.get( 'address', '' ) ) + city = util.restore_text( params.get( 'city', '' ) ) + state = util.restore_text( params.get( 'state', '' ) ) + postal_code = util.restore_text( params.get( 'postal_code', '' ) ) + country = util.restore_text( params.get( 'country', '' ) ) + phone = util.restore_text( params.get( 'phone', '' ) ) + ok = True + if not short_desc: + ok = False + message = 'Enter a short description for this address' + elif not name: + ok = False + message = 'Enter the name' + elif not institution: + ok = False + message = 'Enter the institution associated with the user' + elif not address: + ok = False + message = 'Enter the address' + elif not city: + ok = False + message = 'Enter the city' + elif not state: + ok = False + message = 'Enter the state/province/region' + elif not postal_code: + ok = False + message = 'Enter the postal code' + elif not country: + ok = False + message = 'Enter the country' + if ok: + address_obj.desc = short_desc + address_obj.name = name + address_obj.institution = institution + address_obj.address = address + address_obj.city = city + address_obj.state = state + address_obj.postal_code = postal_code + address_obj.country = country + address_obj.phone = phone + trans.sa_session.add( address_obj ) trans.sa_session.flush() - message = 'Changes made to address <b>%s</b> are saved.' % user_address.desc + message = 'Address (%s) has been updated.' % address_obj.desc if admin_view: return trans.response.send_redirect( web.url_for( controller='user', action='show_info', @@ -853,38 +869,14 @@ class User( BaseController ): return trans.response.send_redirect( web.url_for( controller='user', action='show_info', message=message, - status='done') ) - else: - # show the address form with the current values filled in - # create the widgets for each address field - widgets = [] - widgets.append(dict(label='Short description', - widget=TextField( 'short_desc', 40, user_address.desc ) ) ) - widgets.append(dict(label='Name', - widget=TextField( 'name', 40, user_address.name ) ) ) - widgets.append(dict(label='Institution', - widget=TextField( 'institution', 40, user_address.institution ) ) ) - widgets.append(dict(label='Address Line 1', - widget=TextField( 'address1', 40, user_address.address ) ) ) - widgets.append(dict(label='Address Line 2', - widget=TextField( 'address2', 40, '' ) ) ) - widgets.append(dict(label='City', - widget=TextField( 'city', 40, user_address.city ) ) ) - widgets.append(dict(label='State', - widget=TextField( 'state', 40, user_address.state ) ) ) - widgets.append(dict(label='Postal Code', - widget=TextField( 'postal_code', 40, user_address.postal_code ) ) ) - widgets.append(dict(label='Country', - widget=TextField( 'country', 40, user_address.country ) ) ) - widgets.append(dict(label='Phone', - widget=TextField( 'phone', 40, user_address.phone ) ) ) - return trans.fill_template( 'user/edit_address.mako', - user=user, - address=user_address, - admin_view=admin_view, - widgets=widgets, - message=message, - status=status) + status='done' ) ) + # Display the address form with the current values filled in + return trans.fill_template( 'user/edit_address.mako', + user=user, + address_obj=address_obj, + admin_view=admin_view, + message=message, + status=status ) @web.expose def delete_address( self, trans, address_id=None, user_id=None, admin_view=False ): try: @@ -897,12 +889,13 @@ class User( BaseController ): message='Invalid address ID', status='error' ) ) user_address.deleted = True + trans.sa_session.add( user_address ) trans.sa_session.flush() return trans.response.send_redirect( web.url_for( controller='user', action='show_info', admin_view=admin_view, user_id=user_id, - message='Address <b>%s</b> deleted' % user_address.desc, + message='Address (%s) deleted' % user_address.desc, status='done') ) @web.expose def undelete_address( self, trans, address_id=None, user_id=None, admin_view=False ): @@ -921,9 +914,8 @@ class User( BaseController ): action='show_info', admin_view=admin_view, user_id=user_id, - message='Address <b>%s</b> undeleted' % user_address.desc, + message='Address (%s) undeleted' % user_address.desc, status='done') ) - @web.expose def set_user_pref_async( self, trans, pref_name, pref_value ): """ Set a user preference asynchronously. If user is not logged in, do nothing. """ @@ -931,13 +923,11 @@ class User( BaseController ): trans.log_action( trans.get_user(), "set_user_pref", "", { pref_name : pref_value } ) trans.user.preferences[pref_name] = pref_value trans.sa_session.flush() - @web.expose def log_user_action_async( self, trans, action, context, params ): """ Log a user action asynchronously. If user is not logged in, do nothing. """ if trans.user: trans.log_action( trans.get_user(), action, context, params ) - @web.expose @web.require_login() def dbkeys( self, trans, **kwds ): @@ -999,9 +989,7 @@ class User( BaseController ): user=user, dbkeys=dbkeys, message=message, - lines_skipped=lines_skipped ) - - + lines_skipped=lines_skipped ) @web.expose def api_keys( self, trans, **kwd ): params = util.Params( kwd ) --- a/lib/galaxy/web/controllers/requests_common.py +++ b/lib/galaxy/web/controllers/requests_common.py @@ -17,7 +17,7 @@ import csv log = logging.getLogger( __name__ ) -class RequestsCommon( BaseController ): +class RequestsCommon( BaseController, UsesFormDefinitionWidgets ): @web.json def sample_state_updates( self, trans, ids=None, states=None, cntrller=None ): @@ -207,17 +207,7 @@ class RequestsCommon( BaseController ): if value == 'new': # save this new address in the list of this user's addresses user_address = trans.app.model.UserAddress( user=user ) - user_address.desc = util.restore_text(params.get('field_%i_short_desc' % index, '')) - user_address.name = util.restore_text(params.get('field_%i_name' % index, '')) - user_address.institution = util.restore_text(params.get('field_%i_institution' % index, '')) - user_address.address = util.restore_text(params.get('field_%i_address1' % index, ''))+' '+util.restore_text(params.get('field_%i_address2' % index, '')) - user_address.city = util.restore_text(params.get('field_%i_city' % index, '')) - user_address.state = util.restore_text(params.get('field_%i_state' % index, '')) - user_address.postal_code = util.restore_text(params.get('field_%i_postal_code' % index, '')) - user_address.country = util.restore_text(params.get('field_%i_country' % index, '')) - user_address.phone = util.restore_text(params.get('field_%i_phone' % index, '')) - trans.sa_session.add( user_address ) - trans.sa_session.flush() + self.save_widget_field( trans, user_address, index, **kwd ) trans.sa_session.refresh( user ) values.append(int(user_address.id)) elif value == unicode('none'): --- a/templates/library/common/new_folder.mako +++ b/templates/library/common/new_folder.mako @@ -1,6 +1,5 @@ <%inherit file="/base.mako"/><%namespace file="/message.mako" import="render_msg" /> -<%namespace file="/library/common/common.mako" import="render_template_info" /><br/<br/><ul class="manage-table-actions"> --- a/templates/user/edit_address.mako +++ b/templates/user/edit_address.mako @@ -1,7 +1,6 @@ <%inherit file="/base.mako"/><%namespace file="/message.mako" import="render_msg" /> - %if message: ${render_msg( message, status )} %endif @@ -11,23 +10,87 @@ <ul class="manage-table-actions"><li> - <a class="action-button" href="${h.url_for( controller='user', action='show_info', admin_view=admin_view, user_id=user.id)}"> - <span>Manage User Information</span></a> + <a class="action-button" href="${h.url_for( controller='user', action='show_info', admin_view=admin_view, user_id=user.id)}">Manage user information</a></li></ul><div class="toolForm"> -<form name="login_info" id="login_info" action="${h.url_for( controller='user', action='edit_address', admin_view=admin_view, address_id=address.id, user_id=user.id )}" method="post" ><div class="toolFormTitle">Edit address</div><div class="toolFormBody"> - %for field in widgets: + <form name="login_info" id="login_info" action="${h.url_for( controller='user', action='edit_address', admin_view=admin_view, address_id=address_obj.id, user_id=user.id )}" method="post" ><div class="form-row"> - <label>${field[ 'label' ]}</label> - ${field[ 'widget' ].get_html()} + <label>Short Description:</label> + <div style="float: left; width: 250px; margin-right: 10px;"> + <input type="text" name="short_desc" value="${address_obj.desc}" size="40"> + </div> + <div class="toolParamHelp" style="clear: both;">Required</div> + <div style="clear: both"></div></div> - %endfor - <div class="form-row"> - <input type="submit" name="edit_address_button" value="Save changes"> - </div> + <div class="form-row"> + <label>Name:</label> + <div style="float: left; width: 250px; margin-right: 10px;"> + <input type="text" name="name" value="${address_obj.name}" size="40"> + </div> + <div class="toolParamHelp" style="clear: both;">Required</div> + <div style="clear: both"></div> + </div> + <div class="form-row"> + <label>Institution:</label> + <div style="float: left; width: 250px; margin-right: 10px;"> + <input type="text" name="institution" value="${address_obj.institution}" size="40"> + </div> + <div class="toolParamHelp" style="clear: both;">Required</div> + <div style="clear: both"></div> + </div> + <div class="form-row"> + <label>Address Line 1:</label> + <div style="float: left; width: 250px; margin-right: 10px;"> + <input type="text" name="address" value="${address_obj.address}" size="40"> + </div> + <div class="toolParamHelp" style="clear: both;">Required</div> + <div style="clear: both"></div> + </div> + <div class="form-row"> + <label>City:</label> + <div style="float: left; width: 250px; margin-right: 10px;"> + <input type="text" name="city" value="${address_obj.city}" size="40"> + </div> + <div class="toolParamHelp" style="clear: both;">Required</div> + <div style="clear: both"></div> + </div> + <div class="form-row"> + <label>State/Province/Region:</label> + <div style="float: left; width: 250px; margin-right: 10px;"> + <input type="text" name="state" value="${address_obj.state}" size="40"> + </div> + <div class="toolParamHelp" style="clear: both;">Required</div> + <div style="clear: both"></div> + </div> + <div class="form-row"> + <label>Postal Code:</label> + <div style="float: left; width: 250px; margin-right: 10px;"> + <input type="text" name="postal_code" value="${address_obj.postal_code}" size="40"> + </div> + <div class="toolParamHelp" style="clear: both;">Required</div> + <div style="clear: both"></div> + </div> + <div class="form-row"> + <label>Country:</label> + <div style="float: left; width: 250px; margin-right: 10px;"> + <input type="text" name="country" value="${address_obj.country}" size="40"> + </div> + <div class="toolParamHelp" style="clear: both;">Required</div> + <div style="clear: both"></div> + </div> + <div class="form-row"> + <label>Phone:</label> + <div style="float: left; width: 250px; margin-right: 10px;"> + <input type="text" name="phone" value="${address_obj.phone}" size="40"> + </div> + <div style="clear: both"></div> + </div> + <div class="form-row"> + <input type="submit" name="edit_address_button" value="Save changes"> + </div> + </form></div> -</form></div> --- a/templates/user/new_address.mako +++ b/templates/user/new_address.mako @@ -1,13 +1,12 @@ <%inherit file="/base.mako"/><%namespace file="/message.mako" import="render_msg" /> - %if message: ${render_msg( message, status )} %endif </br></br> -<h3>New address</h3> +<h3>Add new address</h3><ul class="manage-table-actions"><li> @@ -16,18 +15,83 @@ </li></ul><div class="toolForm"> -<form name="login_info" id="login_info" action="${h.url_for( controller='user', action='new_address', admin_view=admin_view, user_id=user.id )}" method="post" > - <div class="toolFormTitle">New address</div> + <div class="toolFormTitle">Add new address</div><div class="toolFormBody"> - %for field in widgets: + <form name="login_info" id="login_info" action="${h.url_for( controller='user', action='new_address', admin_view=admin_view, user_id=user.id )}" method="post" ><div class="form-row"> - <label>${field[ 'label' ]}</label> - ${field[ 'widget' ].get_html()} + <label>Short Description:</label> + <div style="float: left; width: 250px; margin-right: 10px;"> + <input type="text" name="short_desc" value="${short_desc}" size="40"> + </div> + <div class="toolParamHelp" style="clear: both;">Required</div> + <div style="clear: both"></div></div> - %endfor - <div class="form-row"> - <input type="submit" name="save_new_address_button" value="Save"> - </div> + <div class="form-row"> + <label>Name:</label> + <div style="float: left; width: 250px; margin-right: 10px;"> + <input type="text" name="name" value="${name}" size="40"> + </div> + <div class="toolParamHelp" style="clear: both;">Required</div> + <div style="clear: both"></div> + </div> + <div class="form-row"> + <label>Institution:</label> + <div style="float: left; width: 250px; margin-right: 10px;"> + <input type="text" name="institution" value="${institution}" size="40"> + </div> + <div class="toolParamHelp" style="clear: both;">Required</div> + <div style="clear: both"></div> + </div> + <div class="form-row"> + <label>Address Line 1:</label> + <div style="float: left; width: 250px; margin-right: 10px;"> + <input type="text" name="address" value="${address}" size="40"> + </div> + <div class="toolParamHelp" style="clear: both;">Required</div> + <div style="clear: both"></div> + </div> + <div class="form-row"> + <label>City:</label> + <div style="float: left; width: 250px; margin-right: 10px;"> + <input type="text" name="city" value="${city}" size="40"> + </div> + <div class="toolParamHelp" style="clear: both;">Required</div> + <div style="clear: both"></div> + </div> + <div class="form-row"> + <label>State/Province/Region:</label> + <div style="float: left; width: 250px; margin-right: 10px;"> + <input type="text" name="state" value="${state}" size="40"> + </div> + <div class="toolParamHelp" style="clear: both;">Required</div> + <div style="clear: both"></div> + </div> + <div class="form-row"> + <label>Postal Code:</label> + <div style="float: left; width: 250px; margin-right: 10px;"> + <input type="text" name="postal_code" value="${postal_code}" size="40"> + </div> + <div class="toolParamHelp" style="clear: both;">Required</div> + <div style="clear: both"></div> + </div> + <div class="form-row"> + <label>Country:</label> + <div style="float: left; width: 250px; margin-right: 10px;"> + <input type="text" name="country" value="${country}" size="40"> + </div> + <div class="toolParamHelp" style="clear: both;">Required</div> + <div style="clear: both"></div> + </div> + <div class="form-row"> + <label>Phone:</label> + <div style="float: left; width: 250px; margin-right: 10px;"> + <input type="text" name="phone" value="${phone}" size="40"> + </div> + <div style="clear: both"></div> + </div> + <div class="form-row"> + <input type="submit" name="new_address_button" value="Save"> + </div> + </form></div> -</form></div> --- a/test/base/twilltestcase.py +++ b/test/base/twilltestcase.py @@ -1573,19 +1573,19 @@ class TwillTestCase( unittest.TestCase ) def add_user_address( self, user_id, address_dict ): self.home() self.visit_url( "%s/user/new_address?admin_view=False&user_id=%i" % ( self.url, user_id ) ) - self.check_page_for_string( 'New address' ) + self.check_page_for_string( 'Add new address' ) for field_name, value in address_dict.items(): tc.fv( "1", field_name, value ) - tc.submit( "save_new_address_button" ) - self.check_page_for_string( 'Address <b>%s</b> has been added' % address_dict[ 'short_desc' ] ) + tc.submit( "new_address_button" ) + self.check_page_for_string( 'Address (%s) has been added' % address_dict[ 'short_desc' ] ) def add_user_address_as_admin( self, user_id, address_dict ): self.home() self.visit_url( "%s/user/new_address?admin_view=True&user_id=%i" % ( self.url, user_id ) ) - self.check_page_for_string( 'New address' ) + self.check_page_for_string( 'Add new address' ) for field_name, value in address_dict.items(): tc.fv( "1", field_name, value ) - tc.submit( "save_new_address_button" ) - self.check_page_for_string( 'Address <b>%s</b> has been added' % address_dict[ 'short_desc' ] ) + tc.submit( "new_address_button" ) + self.check_page_for_string( 'Address (%s) has been added' % address_dict[ 'short_desc' ] ) # Library stuff def add_library_template( self, cntrller, item_type, library_id, form_id, form_name, folder_id=None, ldda_id=None ): --- a/templates/library/common/common.mako +++ b/templates/library/common/common.mako @@ -1,5 +1,61 @@ -<%def name="render_template_info( cntrller, item_type, library_id, widgets, info_association, inherited, folder_id=None, ldda_id=None, editable=True )"> +<%def name="render_template_field( field )"><% + from galaxy.web.form_builder import AddressField, CheckboxField, SelectField, TextArea, TextField, WorkflowField + + has_contents = False + value = '' + if isinstance( field[ 'widget' ], TextArea ) and field[ 'widget' ].value: + has_contents = True + label = field[ 'label' ] + value = '<pre>%s</pre>' % field[ 'widget' ].value + elif isinstance( field[ 'widget' ], TextField ) and field[ 'widget' ].value: + has_contents = True + label = field[ 'label' ] + value = field[ 'widget' ].value + elif isinstance( field[ 'widget' ], SelectField ) and field[ 'widget' ].options: + for option_label, option_value, selected in field['widget'].options: + if selected: + has_contents = True + label = field[ 'label' ] + value = option_value + elif isinstance( field[ 'widget' ], CheckboxField ) and field[ 'widget' ].checked: + has_contents = True + label = field[ 'label' ] + value = 'checked' + elif isinstance( field[ 'widget' ], WorkflowField ) and field[ 'widget' ].value not in [ 'none', 'None', None ]: + has_contents = True + label = field[ 'label' ] + widget = field[ 'widget' ] + workflow_user = widget.user + if workflow_user: + for workflow in workflow_user.stored_workflows: + if not workflow.deleted and str( widget.value ) == str( workflow.id ): + value = workflow.name + break + else: + # If we didn't find the selected workflow option above, we'll just print the value + value = field[ 'widget' ].value + elif isinstance( field[ 'widget' ], AddressField ) and field[ 'widget' ].value not in [ 'none', 'None', None ]: + has_contents = True + widget = field[ 'widget' ] + address = trans.sa_session.query( trans.model.UserAddress ).get( int( widget.value ) ) + label = address.desc + value = address.get_html() + %> + %if has_contents: + <div class="form-row"> + <label>${label}</label> + ${value} + <div class="toolParamHelp" style="clear: both;"> + ${field[ 'helptext' ]} + </div> + <div style="clear: both"></div> + </div> + %endif +</%def> + +<%def name="render_template_fields( cntrller, item_type, library_id, widgets, widget_fields_have_contents, info_association, inherited, folder_id=None, ldda_id=None, editable=True )"> + <% if item_type == 'library': item = trans.sa_session.query( trans.app.model.Library ).get( trans.security.decode_id( library_id ) ) elif item_type == 'folder': @@ -41,7 +97,7 @@ %endif </div><div class="toolFormBody"> - <form name="edit_info" action="${h.url_for( controller='library_common', action='edit_template_info', cntrller=cntrller, item_type=item_type, library_id=library_id, num_widgets=len( widgets ), folder_id=folder_id, ldda_id=ldda_id, show_deleted=show_deleted )}" method="post"> + <form name="edit_info" id="edit_info" action="${h.url_for( controller='library_common', action='edit_template_info', cntrller=cntrller, item_type=item_type, library_id=library_id, folder_id=folder_id, ldda_id=ldda_id, show_deleted=show_deleted )}" method="post"> %for i, field in enumerate( widgets ): <div class="form-row"><label>${field[ 'label' ]}</label> @@ -59,37 +115,17 @@ </div></div><p/> - %else: - <% contents = False %> - %for i, field in enumerate( widgets ): - %if field[ 'widget' ].value: - <% - contents = True - break - %> - %endif - %endfor - %if contents: - <p/> - <div class="toolForm"> - <div class="toolFormTitle">Other information about ${item.name}</div> - <div class="toolFormBody"> - %for i, field in enumerate( widgets ): - %if field[ 'widget' ].value: - <div class="form-row"> - <label>${field[ 'label' ]}</label> - <pre>${field[ 'widget' ].value}</pre> - <div class="toolParamHelp" style="clear: both;"> - ${field[ 'helptext' ]} - </div> - <div style="clear: both"></div> - </div> - %endif - %endfor - </div> + %elif widget_fields_have_contents: + <p/> + <div class="toolForm"> + <div class="toolFormTitle">Other information about ${item.name}</div> + <div class="toolFormBody"> + %for i, field in enumerate( widgets ): + ${render_template_field( field )} + %endfor </div> - <p/> - %endif + </div> + <p/> %endif %endif </%def> --- a/lib/galaxy/web/controllers/library_common.py +++ b/lib/galaxy/web/controllers/library_common.py @@ -6,7 +6,6 @@ from galaxy.security import RBACAgent from galaxy.util.json import to_json_string from galaxy.tools.actions import upload_common from galaxy.web.controllers.forms import get_all_forms -from galaxy.web.form_builder import SelectField, CheckboxField from galaxy.model.orm import * from galaxy.util.streamball import StreamBall import logging, tempfile, zipfile, tarfile, os, sys @@ -52,7 +51,7 @@ except OSError: pass os.rmdir( tmpd ) -class LibraryCommon( BaseController ): +class LibraryCommon( BaseController, UsesFormDefinitionWidgets ): @web.json def library_item_updates( self, trans, ids=None, states=None ): # Avoid caching @@ -160,9 +159,6 @@ class LibraryCommon( BaseController ): use_panels=use_panels, message=util.sanitize_text( message ), status='error' ) ) - # See if we have any associated templates - info_association, inherited = library.get_info_association() - widgets = library.get_template_widgets( trans ) if params.get( 'library_info_button', False ): # Deny modification if the user is not an admin and does not have the LIBRARY_MODIFY permission. if not ( is_admin or trans.app.security_agent.can_modify_library_item( current_user_roles, library ) ): @@ -201,11 +197,16 @@ class LibraryCommon( BaseController ): show_deleted=show_deleted, message=util.sanitize_text( message ), status='done' ) ) + # See if we have any associated templates + info_association, inherited = library.get_info_association() + widgets = library.get_template_widgets( trans ) + widget_fields_have_contents = self.widget_fields_have_contents( widgets ) return trans.fill_template( '/library/common/library_info.mako', cntrller=cntrller, use_panels=use_panels, library=library, widgets=widgets, + widget_fields_have_contents=widget_fields_have_contents, current_user_roles=current_user_roles, show_deleted=show_deleted, info_association=info_association, @@ -402,11 +403,6 @@ class LibraryCommon( BaseController ): show_deleted=show_deleted, message=util.sanitize_text( message ), status='error' ) ) - # See if we have any associated templates - widgets = [] - info_association, inherited = folder.get_info_association() - if info_association and ( not( inherited ) or info_association.inheritable ): - widgets = folder.get_template_widgets( trans ) if params.get( 'rename_folder_button', False ): # Deny modification if the user is not an admin and does not have the LIBRARY_MODIFY permission if not ( is_admin or trans.app.security_agent.can_modify_library_item( current_user_roles, folder ) ): @@ -439,12 +435,20 @@ class LibraryCommon( BaseController ): show_deleted=show_deleted, message=util.sanitize_text( message ), status='done' ) ) + # See if we have any associated templates + widgets = [] + widget_fields_have_contents = False + info_association, inherited = folder.get_info_association() + if info_association and ( not( inherited ) or info_association.inheritable ): + widgets = folder.get_template_widgets( trans ) + widget_fields_have_contents = self.widget_fields_have_contents( widgets ) return trans.fill_template( '/library/common/folder_info.mako', cntrller=cntrller, use_panels=use_panels, folder=folder, library_id=library_id, widgets=widgets, + widget_fields_have_contents=widget_fields_have_contents, current_user_roles=current_user_roles, show_deleted=show_deleted, info_association=info_association, @@ -677,9 +681,11 @@ class LibraryCommon( BaseController ): associated_lddas = [] # See if we have any associated templates widgets = [] + widget_fields_have_contents = False info_association, inherited = ldda.get_info_association() if info_association and ( not( inherited ) or info_association.inheritable ): widgets = ldda.get_template_widgets( trans ) + widget_fields_have_contents = self.widget_fields_have_contents( widgets ) return trans.fill_template( '/library/common/ldda_info.mako', cntrller=cntrller, use_panels=use_panels, @@ -689,6 +695,7 @@ class LibraryCommon( BaseController ): associated_lddas=associated_lddas, show_deleted=show_deleted, widgets=widgets, + widget_fields_have_contents=widget_fields_have_contents, current_user_roles=current_user_roles, info_association=info_association, inherited=inherited, @@ -1524,11 +1531,6 @@ class LibraryCommon( BaseController ): show_deleted=show_deleted, message=util.sanitize_text( message ), status='error' ) ) - # See if we have any associated templates - widgets = [] - info_association, inherited = library_dataset.library_dataset_dataset_association.get_info_association() - if info_association and ( not( inherited ) or info_association.inheritable ): - widgets = library_dataset.library_dataset_dataset_association.get_template_widgets( trans ) if params.get( 'edit_attributes_button', False ): # Deny access if the user is not an admin and does not have the LIBRARY_MODIFY permission. if not ( is_admin or trans.app.security_agent.can_modify_library_item( current_user_roles, library_dataset ) ): @@ -1553,6 +1555,13 @@ class LibraryCommon( BaseController ): trans.sa_session.flush() message = "Information updated for library dataset '%s'." % library_dataset.name status = 'done' + # See if we have any associated templates + widgets = [] + widget_fields_have_contents = False + info_association, inherited = library_dataset.library_dataset_dataset_association.get_info_association() + if info_association and ( not( inherited ) or info_association.inheritable ): + widgets = library_dataset.library_dataset_dataset_association.get_template_widgets( trans ) + widget_fields_have_contents = self.widget_fields_have_contents( widgets ) return trans.fill_template( '/library/common/library_dataset_info.mako', cntrller=cntrller, use_panels=use_panels, @@ -1562,6 +1571,7 @@ class LibraryCommon( BaseController ): info_association=info_association, inherited=inherited, widgets=widgets, + widget_fields_have_contents=widget_fields_have_contents, show_deleted=show_deleted, message=message, status=status ) @@ -2134,7 +2144,7 @@ class LibraryCommon( BaseController ): **kwd ) ) return trans.response.send_redirect( web.url_for( controller='forms', action='edit', **vars ) ) @web.expose - def edit_template_info( self, trans, cntrller, item_type, library_id, num_widgets, folder_id=None, ldda_id=None, **kwd ): + def edit_template_info( self, trans, cntrller, item_type, library_id, folder_id=None, ldda_id=None, **kwd ): # Edit the contents of the template fields without altering the template itself. params = util.Params( kwd ) show_deleted = util.string_as_bool( params.get( 'show_deleted', False ) ) @@ -2156,10 +2166,28 @@ class LibraryCommon( BaseController ): show_deleted=show_deleted, message=util.sanitize_text( message ), status='error' ) ) + # We need the type of each template field widget + widgets = item.get_template_widgets( trans ) + # The list of widgets may include an AddressField which we need to save if it is new + for index, widget_dict in enumerate( widgets ): + widget = widget_dict[ 'widget' ] + if isinstance( widget, AddressField ): + value = util.restore_text( params.get( 'field_%i' % index, '' ) ) + if value == 'new': + if params.get( 'edit_info_button', False ): + # Save the new address + address = trans.app.model.UserAddress( user=trans.user ) + self.save_widget_field( trans, address, index, **kwd ) + widget.value = str( address.id ) + else: + # Form was submitted via refresh_on_change + widget.value = 'new' + elif value == unicode( 'none' ): + widget.value = '' + else: + widget.value = value # Save updated template field contents - field_contents = [] - for index in range( int( num_widgets ) ): - field_contents.append( util.restore_text( params.get( 'field_%i' % ( index ), '' ) ) ) + field_contents = self.clean_field_contents( widgets, **kwd ) if field_contents: # Since information templates are inherited, the template fields can be displayed on the information # page for a folder or ldda when it has no info_association object. If the user has added --- a/templates/library/common/ldda_info.mako +++ b/templates/library/common/ldda_info.mako @@ -1,6 +1,6 @@ <%inherit file="/base.mako"/><%namespace file="/message.mako" import="render_msg" /> -<%namespace file="/library/common/common.mako" import="render_template_info" /> +<%namespace file="/library/common/common.mako" import="render_template_fields" /><% from galaxy import util from galaxy.web.controllers.library_common import branch_deleted, get_containing_library_from_library_dataset @@ -23,6 +23,34 @@ can_modify = can_manage = False %> +<%def name="javascripts()"> + ${parent.javascripts()} + <script type="text/javascript"> + $( function() { + $( "select[refresh_on_change='true']").change( function() { + var refresh = false; + var refresh_on_change_values = $( this )[0].attributes.getNamedItem( 'refresh_on_change_values' ) + if ( refresh_on_change_values ) { + refresh_on_change_values = refresh_on_change_values.value.split( ',' ); + var last_selected_value = $( this )[0].attributes.getNamedItem( 'last_selected_value' ); + for( i= 0; i < refresh_on_change_values.length; i++ ) { + if ( $( this )[0].value == refresh_on_change_values[i] || ( last_selected_value && last_selected_value.value == refresh_on_change_values[i] ) ){ + refresh = true; + break; + } + } + } + else { + refresh = true; + } + if ( refresh ){ + $( "#edit_info" ).submit(); + } + }); + }); + </script> +</%def> + %if current_version: <b><i>This is the latest version of this library dataset</i></b> %else: @@ -134,7 +162,7 @@ </div></div> %if widgets: - ${render_template_info( cntrller=cntrller, item_type='ldda', library_id=library_id, widgets=widgets, info_association=info_association, inherited=inherited, folder_id=trans.security.encode_id( ldda.library_dataset.folder.id ), ldda_id=trans.security.encode_id( ldda.id ), editable=False )} + ${render_template_fields( cntrller=cntrller, item_type='ldda', library_id=library_id, widgets=widgets, widget_fields_have_contents=widget_fields_have_contents, info_association=info_association, inherited=inherited, folder_id=trans.security.encode_id( ldda.library_dataset.folder.id ), ldda_id=trans.security.encode_id( ldda.id ), editable=False )} %endif %if trans.user_is_admin() and cntrller == 'library_admin': %if associated_hdas: --- a/test/base/test_db_util.py +++ b/test/base/test_db_util.py @@ -109,6 +109,13 @@ def get_user( email ): return sa_session.query( galaxy.model.User ) \ .filter( galaxy.model.User.table.c.email==email ) \ .first() +def get_user_address( user, short_desc ): + return sa_session.query( galaxy.model.UserAddress ) \ + .filter( and_( galaxy.model.UserAddress.table.c.user_id==user.id, + galaxy.model.UserAddress.table.c.desc==short_desc, + galaxy.model.UserAddress.table.c.deleted==False ) ) \ + .order_by( desc( galaxy.model.UserAddress.table.c.create_time ) ) \ + .first() def get_user_group_associations_by_group( group ): return sa_session.query( galaxy.model.UserGroupAssociation ) \ .filter( galaxy.model.UserGroupAssociation.table.c.group_id == group.id ) \ --- a/templates/library/common/ldda_edit_info.mako +++ b/templates/library/common/ldda_edit_info.mako @@ -1,11 +1,35 @@ <%inherit file="/base.mako"/><%namespace file="/message.mako" import="render_msg" /> -<%namespace file="/library/common/common.mako" import="render_template_info" /> +<%namespace file="/library/common/common.mako" import="render_template_fields" /><% from galaxy import util %><%def name="javascripts()"> ${parent.javascripts()} ${h.js("jquery.autocomplete", "autocomplete_tagging" )} + <script type="text/javascript"> + $( function() { + $( "select[refresh_on_change='true']").change( function() { + var refresh = false; + var refresh_on_change_values = $( this )[0].attributes.getNamedItem( 'refresh_on_change_values' ) + if ( refresh_on_change_values ) { + refresh_on_change_values = refresh_on_change_values.value.split( ',' ); + var last_selected_value = $( this )[0].attributes.getNamedItem( 'last_selected_value' ); + for( i= 0; i < refresh_on_change_values.length; i++ ) { + if ( $( this )[0].value == refresh_on_change_values[i] || ( last_selected_value && last_selected_value.value == refresh_on_change_values[i] ) ){ + refresh = true; + break; + } + } + } + else { + refresh = true; + } + if ( refresh ){ + $( "#edit_info" ).submit(); + } + }); + }); + </script></%def><%def name="stylesheets()"> @@ -155,5 +179,5 @@ </div> %endif %if widgets: - ${render_template_info( cntrller=cntrller, item_type='ldda', library_id=library_id, widgets=widgets, info_association=info_association, inherited=inherited, folder_id=trans.security.encode_id( ldda.library_dataset.folder.id ), ldda_id=trans.security.encode_id( ldda.id ) )} + ${render_template_fields( cntrller=cntrller, item_type='ldda', library_id=library_id, widgets=widgets, widget_fields_have_contents=widget_fields_have_contents, info_association=info_association, inherited=inherited, folder_id=trans.security.encode_id( ldda.library_dataset.folder.id ), ldda_id=trans.security.encode_id( ldda.id ) )} %endif
participants (1)
-
commits-noreply@bitbucket.org