[hg] galaxy 2538: LIMS enhancements
details: http://www.bx.psu.edu/hg/galaxy/rev/24ccfa887fcd changeset: 2538:24ccfa887fcd user: rc date: Thu Aug 06 09:52:59 2009 -0400 description: LIMS enhancements - Requests page now displays all samples in grid layout - New samples UI - Requests states added - CSV import for samples - User address management - New AddressField in form_builder - Deletion added for forms, request types, requests & samples - Editing added for requests and samples - Grid filtering added for requests, forms, request types 24 file(s) affected in this change: lib/galaxy/model/__init__.py lib/galaxy/model/mapping.py lib/galaxy/model/migrate/versions/0009_request_table.py lib/galaxy/model/migrate/versions/0012_user_address.py lib/galaxy/web/controllers/admin.py lib/galaxy/web/controllers/forms.py lib/galaxy/web/controllers/requests.py lib/galaxy/web/controllers/requests_admin.py lib/galaxy/web/controllers/user.py lib/galaxy/web/form_builder.py lib/galaxy/web/framework/helpers/grids.py templates/admin/forms/create_form.mako templates/admin/forms/edit_form.mako templates/admin/forms/manage_forms.mako templates/admin/requests/grid.mako templates/admin/requests/manage_request_types.mako templates/admin/samples/bar_codes.mako templates/requests/edit_request.mako templates/requests/grid.mako templates/requests/new_request.mako templates/requests/select_request_type.mako templates/requests/show_request.mako templates/user/address.mako templates/user/index.mako diffs (2925 lines): diff -r 11a2d159e280 -r 24ccfa887fcd lib/galaxy/model/__init__.py --- a/lib/galaxy/model/__init__.py Wed Aug 05 12:59:24 2009 -0400 +++ b/lib/galaxy/model/__init__.py Thu Aug 06 09:52:59 2009 -0400 @@ -1121,15 +1121,18 @@ self.content = content class Request( object ): + states = Bunch( UNSUBMITTED = 'Unsubmitted', + SUBMITTED = 'Submitted', + COMPLETE = 'Complete') def __init__(self, name=None, desc=None, request_type=None, user=None, - form_values=None, library=None, submitted=False): + form_values=None, library=None, state=False): self.name = name self.desc = desc self.type = request_type self.values = form_values self.user = user self.library = library - self.submitted = submitted + self.state = state self.samples_list = [] def add_sample(self, sample_name=None, sample_desc=None, sample_values=None): # create a form_values row @@ -1151,6 +1154,18 @@ if s.name == sample_name: return s return False + def submitted(self): + if self.state == self.states.SUBMITTED: + return True + return False + def unsubmitted(self): + if self.state == self.states.UNSUBMITTED: + return True + return False + def complete(self): + if self.state == self.states.COMPLETE: + return True + return False class RequestType( object ): def __init__(self, name=None, desc=None, request_form=None, sample_form=None): @@ -1160,12 +1175,12 @@ self.sample_form = sample_form class Sample( object ): - def __init__(self, name=None, desc=None, request=None, form_values=None): + def __init__(self, name=None, desc=None, request=None, form_values=None, bar_code=None): self.name = name self.desc = desc self.request = request self.values = form_values - + self.bar_code = bar_code def current_state(self): return self.events[0].state @@ -1180,6 +1195,37 @@ self.sample = sample self.state = sample_state self.comment = comment + +class UserAddress( object ): + def __init__(self, user=None, desc=None, name=None, institution=None, + address=None, city=None, state=None, postal_code=None, + country=None, phone=None): + self.user = user + self.desc = desc + self.name = name + self.institution = institution + self.address = address + self.city = city + self.state = state + self.postal_code = postal_code + self.country = country + self.phone = phone + def display(self): + return self.name+'<br/>'+ \ + self.institution+'<br/>'+ \ + self.address+'<br/>'+ \ + self.city+' '+self.state+' '+self.postal_code+'<br/>'+ \ + self.country+'<br/>'+ \ + 'Phone: '+self.phone + def get_html(self): + return self.name+'<br/>'+ \ + self.institution+'<br/>'+ \ + self.address+'<br/>'+ \ + self.city+' '+self.state+' '+self.postal_code+'<br/>'+ \ + self.country+'<br/>'+ \ + 'Phone: '+self.phone + + diff -r 11a2d159e280 -r 24ccfa887fcd lib/galaxy/model/mapping.py --- a/lib/galaxy/model/mapping.py Wed Aug 05 12:59:24 2009 -0400 +++ b/lib/galaxy/model/mapping.py Thu Aug 06 09:52:59 2009 -0400 @@ -46,7 +46,24 @@ Column( "external", Boolean, default=False ), Column( "deleted", Boolean, index=True, default=False ), Column( "purged", Boolean, index=True, default=False ) ) - + +UserAddress.table = Table( "user_address", metadata, + Column( "id", Integer, primary_key=True), + Column( "create_time", DateTime, default=now ), + Column( "update_time", DateTime, default=now, onupdate=now ), + Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), index=True ), + Column( "desc", TrimmedString( 255 )), + Column( "name", TrimmedString( 255 ), nullable=False), + Column( "institution", TrimmedString( 255 )), + Column( "address", TrimmedString( 255 ), nullable=False), + Column( "city", TrimmedString( 255 ), nullable=False), + Column( "state", TrimmedString( 255 ), nullable=False), + Column( "postal_code", TrimmedString( 255 ), nullable=False), + Column( "country", TrimmedString( 255 ), nullable=False), + Column( "phone", TrimmedString( 255 )), + Column( "deleted", Boolean, index=True, default=False ), + Column( "purged", Boolean, index=True, default=False ) ) + History.table = Table( "history", metadata, Column( "id", Integer, primary_key=True), Column( "create_time", DateTime, default=now ), @@ -558,7 +575,8 @@ Column( "name", TrimmedString( 255 ), nullable=False ), Column( "desc", TEXT ), Column( "request_form_id", Integer, ForeignKey( "form_definition.id" ), index=True ), - Column( "sample_form_id", Integer, ForeignKey( "form_definition.id" ), index=True ) ) + Column( "sample_form_id", Integer, ForeignKey( "form_definition.id" ), index=True ), + Column( "deleted", Boolean, index=True, default=False ) ) FormValues.table = Table('form_values', metadata, Column( "id", Integer, primary_key=True), @@ -577,8 +595,15 @@ Column( "request_type_id", Integer, ForeignKey( "request_type.id" ), index=True ), Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), index=True ), Column( "library_id", Integer, ForeignKey( "library.id" ), index=True ), - Column( "submitted", Boolean, index=True, default=False ), + Column( "state", TrimmedString( 255 ), index=True ), Column( "deleted", Boolean, index=True, default=False ) ) + +RequestState_table = Table('request_state', metadata, + Column( "id", Integer, primary_key=True), + Column( "create_time", DateTime, default=now ), + Column( "update_time", DateTime, default=now, onupdate=now ), + Column( "name", TrimmedString( 255 ), nullable=False ), + Column( "desc", TEXT )) Sample.table = Table('sample', metadata, Column( "id", Integer, primary_key=True), @@ -615,13 +640,14 @@ # relationships between the model objects. assign_mapper( context, Sample, Sample.table, - properties=dict( events=relation( SampleEvent, backref="sample", - order_by=desc(SampleEvent.table.c.update_time) ), - values=relation( FormValues, - primaryjoin=( Sample.table.c.form_values_id == FormValues.table.c.id ) ), - request=relation( Request, - primaryjoin=( Sample.table.c.request_id == Request.table.c.id ) ), - ) ) + properties=dict( + events=relation( SampleEvent, backref="sample", + order_by=desc(SampleEvent.table.c.update_time) ), + values=relation( FormValues, + primaryjoin=( Sample.table.c.form_values_id == FormValues.table.c.id ) ), + request=relation( Request, + primaryjoin=( Sample.table.c.request_id == Request.table.c.id ) ), + ) ) assign_mapper( context, FormValues, FormValues.table, properties=dict( form_definition=relation( FormDefinition, @@ -673,6 +699,15 @@ assign_mapper( context, SampleState, SampleState.table, properties=None ) + +assign_mapper( context, UserAddress, UserAddress.table, + properties=dict( + user=relation( User, + primaryjoin=( UserAddress.table.c.user_id == User.table.c.id ), + backref='addresses', + order_by=desc(UserAddress.table.c.update_time)), + ) ) + assign_mapper( context, ValidationError, ValidationError.table ) @@ -749,7 +784,9 @@ galaxy_sessions=relation( GalaxySession, order_by=desc( GalaxySession.table.c.update_time ) ), stored_workflow_menu_entries=relation( StoredWorkflowMenuEntry, backref="user", cascade="all, delete-orphan", - collection_class=ordering_list( 'order_index' ) ) + collection_class=ordering_list( 'order_index' ) ), +# addresses=relation( UserAddress, +# primaryjoin=( User.table.c.id == UserAddress.table.c.user_id ) ) ) ) assign_mapper( context, Group, Group.table, diff -r 11a2d159e280 -r 24ccfa887fcd lib/galaxy/model/migrate/versions/0009_request_table.py --- a/lib/galaxy/model/migrate/versions/0009_request_table.py Wed Aug 05 12:59:24 2009 -0400 +++ b/lib/galaxy/model/migrate/versions/0009_request_table.py Thu Aug 06 09:52:59 2009 -0400 @@ -32,7 +32,7 @@ col.create( Request_table ) assert col is Request_table.c.submitted except Exception, e: - log.debug( "Adding column 'submitted' to submitted table failed: %s" % ( str( e ) ) ) + log.debug( "Adding column 'submitted' to request table failed: %s" % ( str( e ) ) ) # Add 1 column to the sample table try: @@ -46,7 +46,7 @@ col.create( Sample_table ) assert col is Sample_table.c.bar_code except Exception, e: - log.debug( "Adding column 'bar_code' to submitted table failed: %s" % ( str( e ) ) ) + log.debug( "Adding column 'bar_code' to sample table failed: %s" % ( str( e ) ) ) def downgrade(): pass \ No newline at end of file diff -r 11a2d159e280 -r 24ccfa887fcd lib/galaxy/model/migrate/versions/0012_user_address.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/galaxy/model/migrate/versions/0012_user_address.py Thu Aug 06 09:52:59 2009 -0400 @@ -0,0 +1,118 @@ +from sqlalchemy import * +from sqlalchemy.orm import * +from sqlalchemy.exceptions import * +from migrate import * +from migrate.changeset import * + +import datetime +now = datetime.datetime.utcnow + +import sys, logging +log = logging.getLogger( __name__ ) +log.setLevel(logging.DEBUG) +handler = logging.StreamHandler( sys.stdout ) +format = "%(name)s %(levelname)s %(asctime)s %(message)s" +formatter = logging.Formatter( format ) +handler.setFormatter( formatter ) +log.addHandler( handler ) + +# Need our custom types, but don't import anything else from model +from galaxy.model.custom_types import * + +metadata = MetaData( migrate_engine ) +db_session = scoped_session( sessionmaker( bind=migrate_engine, autoflush=False, transactional=False ) ) + + +UserAddress_table = Table( "user_address", metadata, + Column( "id", Integer, primary_key=True), + Column( "create_time", DateTime, default=now ), + Column( "update_time", DateTime, default=now, onupdate=now ), + Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), index=True ), + Column( "desc", TEXT), + Column( "name", TrimmedString( 255 ), nullable=False), + Column( "institution", TrimmedString( 255 )), + Column( "address", TrimmedString( 255 ), nullable=False), + Column( "city", TrimmedString( 255 ), nullable=False), + Column( "state", TrimmedString( 255 ), nullable=False), + Column( "postal_code", TrimmedString( 255 ), nullable=False), + Column( "country", TrimmedString( 255 ), nullable=False), + Column( "phone", TrimmedString( 255 )), + Column( "deleted", Boolean, index=True, default=False ), + Column( "purged", Boolean, index=True, default=False ) ) + +#RequestState_table = Table('request_state', metadata, +# Column( "id", Integer, primary_key=True), +# Column( "create_time", DateTime, default=now ), +# Column( "update_time", DateTime, default=now, onupdate=now ), +# Column( "name", TrimmedString( 255 ), nullable=False ), +# Column( "desc", TEXT )) + +def upgrade(): + # Load existing tables + metadata.reflect() + + # Add all of the new tables above + try: + UserAddress_table.create() + except Exception, e: + log.debug( "Creating user_address table failed: %s" % str( e ) ) +# try: +# RequestState_table.create() +# except Exception, e: +# log.debug( "Creating request_state table failed: %s" % str( e ) ) + + # Add 1 column to the request_type table + try: + RequestType_table = Table( "request_type", metadata, autoload=True ) + except NoSuchTableError: + RequestType_table = None + log.debug( "Failed loading table request_type" ) + if RequestType_table: + try: + col = Column( "deleted", Boolean, index=True, default=False ) + col.create( RequestType_table ) + assert col is RequestType_table.c.deleted + except Exception, e: + log.debug( "Adding column 'deleted' to request_type table failed: %s" % ( str( e ) ) ) + + # Delete the submitted column + try: + Request_table = Table( "request", metadata, autoload=True ) + except NoSuchTableError: + Request_table = None + log.debug( "Failed loading table request" ) + if Request_table: + try: + Request_table.c.submitted.drop() + except Exception, e: + log.debug( "Deleting column 'submitted' to request table failed: %s" % ( str( e ) ) ) + try: + col = Column( "state", TrimmedString( 255 ), index=True ) + col.create( Request_table ) + assert col is Request_table.c.state + except Exception, e: + log.debug( "Adding column 'state' to request table failed: %s" % ( str( e ) ) ) +# +# # new column which points to the current state in the request_state table +# try: +# col = Column( "request_state_id", Integer, index=True ) +# col.create( Request_table ) +# assert col is Request_table.c.request_state_id +# except Exception, e: +# log.debug( "Adding column 'request_state_id' to request table failed: %s" % ( str( e ) ) ) +# # Add 1 foreign key constraint to the form_definition_current table +# if RequestState_table and Request_table: +# try: +# cons = ForeignKeyConstraint( [Request_table.c.request_state_id], +# [RequestState_table.c.id], +# name='request_request_state_id_fk' ) +# # Create the constraint +# cons.create() +# except Exception, e: +# log.debug( "Adding foreign key constraint 'request_request_state_id_fk' to table 'request' failed: %s" % ( str( e ) ) ) + + +def downgrade(): + pass + + diff -r 11a2d159e280 -r 24ccfa887fcd lib/galaxy/web/controllers/admin.py --- a/lib/galaxy/web/controllers/admin.py Wed Aug 05 12:59:24 2009 -0400 +++ b/lib/galaxy/web/controllers/admin.py Thu Aug 06 09:52:59 2009 -0400 @@ -2120,12 +2120,19 @@ params = util.Params( kwd ) msg = util.restore_text( params.get( 'msg', '' ) ) messagetype = params.get( 'messagetype', 'done' ) + show_filter = util.restore_text( params.get( 'show_filter', 'Active' ) ) forms = self._get_all_forms(trans, all_versions=True) + request_types_list = trans.app.model.RequestType.query().all() + if show_filter == 'All': + request_types = request_types_list + elif show_filter == 'Deleted': + request_types = [rt for rt in request_types_list if rt.deleted] + else: + request_types = [rt for rt in request_types_list if not rt.deleted] return trans.fill_template( '/admin/requests/manage_request_types.mako', - request_types=trans.app.model.RequestType.query().all(), + request_types=request_types, forms=forms, - deleted=False, - show_deleted=False, + show_filter=show_filter, msg=msg, messagetype=messagetype ) @web.expose @@ -2155,13 +2162,10 @@ forms=self._get_all_forms(trans, all_versions=False), msg=msg, messagetype='error') - return trans.fill_template( '/admin/requests/manage_request_types.mako', - request_types=trans.app.model.RequestType.query().all(), - forms=self._get_all_forms(trans, all_versions=True), - deleted=False, - show_deleted=False, - msg=msg, - messagetype=messagetype ) + return trans.response.send_redirect( web.url_for( controller='admin', + action='manage_request_types', + msg='Request type <b>%s</b> has been created' % st.name, + messagetype='done') ) elif params.get('edit', False) == 'True': rt = trans.app.model.RequestType.get(int(util.restore_text( params.id ))) ss_list = trans.app.model.SampleState.filter(trans.app.model.SampleState.table.c.request_type_id == rt.id).all() @@ -2197,8 +2201,8 @@ ss.delete() ss.flush() # unsubmitted state - ss = trans.app.model.SampleState('Unsubmitted', 'Sample not yet submitted', rt) - ss.flush() + #ss = trans.app.model.SampleState('Unsubmitted', 'Sample not yet submitted', rt) + ##ss.flush() for i in range( num_states ): name = util.restore_text( params.get( 'new_element_name_%i' % i, None )) desc = util.restore_text( params.get( 'new_element_description_%i' % i, None )) @@ -2206,3 +2210,31 @@ ss.flush() msg = "The new request type named '%s' with %s state(s) has been created" % (rt.name, num_states) return rt, msg + + @web.expose + @web.require_admin + def delete_request_type( self, trans, **kwd ): + params = util.Params( kwd ) + msg = util.restore_text( params.get( 'msg', '' ) ) + messagetype = params.get( 'messagetype', 'done' ) + rt = trans.app.model.RequestType.get(int(util.restore_text( params.request_type_id ))) + rt.deleted = True + rt.flush() + return trans.response.send_redirect( web.url_for( controller='admin', + action='manage_request_types', + msg='Request type <b>%s</b> has been deleted' % rt.name, + messagetype='done') ) + + @web.expose + @web.require_admin + def undelete_request_type( self, trans, **kwd ): + params = util.Params( kwd ) + msg = util.restore_text( params.get( 'msg', '' ) ) + messagetype = params.get( 'messagetype', 'done' ) + rt = trans.app.model.RequestType.get(int(util.restore_text( params.request_type_id ))) + rt.deleted = False + rt.flush() + return trans.response.send_redirect( web.url_for( controller='admin', + action='manage_request_types', + msg='Request type <b>%s</b> has been deleted' % rt.name, + messagetype='done') ) diff -r 11a2d159e280 -r 24ccfa887fcd lib/galaxy/web/controllers/forms.py --- a/lib/galaxy/web/controllers/forms.py Wed Aug 05 12:59:24 2009 -0400 +++ b/lib/galaxy/web/controllers/forms.py Thu Aug 06 09:52:59 2009 -0400 @@ -29,13 +29,19 @@ params = util.Params( kwd ) msg = util.restore_text( params.get( 'msg', '' ) ) messagetype = params.get( 'messagetype', 'done' ) - return self._show_forms_list(trans, msg, messagetype) - def _show_forms_list(self, trans, msg, messagetype): + show_filter = params.get( 'show_filter', 'Active' ) + return self._show_forms_list(trans, msg, messagetype, show_filter) + def _show_forms_list(self, trans, msg, messagetype, show_filter='Active'): fdc_list = trans.app.model.FormDefinitionCurrent.query().all() + if show_filter == 'All': + forms_list = fdc_list + elif show_filter == 'Deleted': + forms_list = [form for form in fdc_list if form.deleted] + else: + forms_list = [form for form in fdc_list if not form.deleted] return trans.fill_template( '/admin/forms/manage_forms.mako', - fdc_list=fdc_list, - deleted=False, - show_deleted=False, + fdc_list=forms_list, + show_filter=show_filter, msg=msg, messagetype=messagetype ) def _get_all_forms(self, trans, all_versions=False): @@ -73,7 +79,34 @@ self.num_add_fields = 0 fd, msg = self.__save_form(trans, fdc_id=None, **kwd) self.__get_saved_form(fd) - return self._show_forms_list(trans, msg, messagetype) + return trans.response.send_redirect( web.url_for( controller='forms', + action='edit', + form_id=fd.id, + show_form=True) ) + @web.expose + @web.require_admin + def delete( self, trans, **kwd ): + params = util.Params( kwd ) + msg = util.restore_text( params.get( 'msg', '' ) ) + messagetype = params.get( 'messagetype', 'done' ) + fd = trans.app.model.FormDefinition.get(int(util.restore_text( params.form_id ))) + fd.form_definition_current.deleted = True + fd.form_definition_current.flush() + return self._show_forms_list(trans, + msg='The form definition named %s is deleted.' % fd.name, + messagetype='done') + @web.expose + @web.require_admin + def undelete( self, trans, **kwd ): + params = util.Params( kwd ) + msg = util.restore_text( params.get( 'msg', '' ) ) + messagetype = params.get( 'messagetype', 'done' ) + fd = trans.app.model.FormDefinition.get(int(util.restore_text( params.form_id ))) + fd.form_definition_current.deleted = False + fd.form_definition_current.flush() + return self._show_forms_list(trans, + msg='The form definition named %s is undeleted.' % fd.name, + messagetype='done') @web.expose @web.require_admin def edit( self, trans, **kwd ): @@ -241,15 +274,22 @@ ''' import csv fields = [] - reader = csv.reader(open(csv_file)) - for row in reader: - options = row[5].split(',') - fields.append({'label': row[0], - 'helptext': row[1], - 'visible': row[2], - 'required': row[3], - 'type': row[4], - 'selectlist': options}) + try: + reader = csv.reader(open(csv_file)) + for row in reader: + options = row[5].split(',') + fields.append({'label': row[0], + 'helptext': row[1], + 'visible': row[2], + 'required': row[3], + 'type': row[4], + 'selectlist': options}) + except: + return trans.response.send_redirect( web.url_for( controller='forms', + action='new', + status='error', + message='Error in importing <b>%s</b> file' % csv_file, + **kwd)) return fields def __save_form(self, trans, fdc_id=None, **kwd): diff -r 11a2d159e280 -r 24ccfa887fcd lib/galaxy/web/controllers/requests.py --- a/lib/galaxy/web/controllers/requests.py Wed Aug 05 12:59:24 2009 -0400 +++ b/lib/galaxy/web/controllers/requests.py Thu Aug 06 09:52:59 2009 -0400 @@ -14,6 +14,7 @@ title = "Sequencing Requests" model_class = model.Request default_sort_key = "-create_time" + show_filter = model.Request.states.UNSUBMITTED columns = [ grids.GridColumn( "Name", key="name", link=( lambda item: iff( item.deleted, None, dict( operation="show_request", id=item.id ) ) ), @@ -23,18 +24,23 @@ link=( lambda item: iff( item.deleted, None, dict( operation="show_request", id=item.id ) ) ), ), grids.GridColumn( "Type", key="request_type_id", method='get_request_type'), grids.GridColumn( "Last update", key="update_time", format=time_ago ), - grids.GridColumn( "Submitted", method='submitted'), + grids.GridColumn( "State", key='state'), ] operations = [ -# grids.GridOperation( "Edit", allow_multiple=False, condition=( lambda item: not item.deleted ) ), - grids.GridOperation( "Submit", allow_multiple=False, condition=( lambda item: not item.submitted ) ) -# grids.GridOperation( "Delete", condition=( lambda item: not item.deleted ) ), -# grids.GridOperation( "Undelete", condition=( lambda item: item.deleted ) ), + grids.GridOperation( "Submit", allow_multiple=False, condition=( lambda item: not item.deleted and item.unsubmitted() and item.samples ) ), + grids.GridOperation( "Edit", allow_multiple=False, condition=( lambda item: not item.deleted and item.unsubmitted() ) ), + grids.GridOperation( "Delete", allow_multiple=False, condition=( lambda item: not item.deleted and item.unsubmitted() ) ), + grids.GridOperation( "Undelete", allow_multiple=False, condition=( lambda item: item.deleted ) ) + ] standard_filters = [ - grids.GridColumnFilter( "Active", args=dict( deleted=False ) ), + grids.GridColumnFilter( model.Request.states.UNSUBMITTED, + args=dict( state=model.Request.states.UNSUBMITTED, deleted=False ) ), + grids.GridColumnFilter( model.Request.states.SUBMITTED, + args=dict( state=model.Request.states.SUBMITTED, deleted=False ) ), + grids.GridColumnFilter( model.Request.states.COMPLETE, args=dict( state=model.Request.states.COMPLETE, deleted=False ) ), grids.GridColumnFilter( "Deleted", args=dict( deleted=True ) ), - grids.GridColumnFilter( "All", args=dict( deleted='All' ) ) + grids.GridColumnFilter( "All", args={} ) ] #default_filter = dict( deleted=False ) def get_current_item( self, trans ): @@ -45,10 +51,8 @@ return query.filter_by( user=trans.user ) def number_of_samples(self, trans, request): return str(len(request.samples)) - def submitted(self, trans, request): - if request.submitted: - return 'Yes' - return 'No' + def get_state(self, trans, request): + return request.state @@ -73,6 +77,8 @@ List all request made by the current user ''' status = message = None + self.request_grid.default_filter = dict(state=trans.app.model.Request.states.UNSUBMITTED, + deleted=False) if 'operation' in kwargs: operation = kwargs['operation'].lower() if operation == "show_request": @@ -81,6 +87,23 @@ elif operation == "submit": id = trans.security.decode_id(kwargs['id']) return self.__submit(trans, id) + elif operation == "delete": + id = trans.security.decode_id(kwargs['id']) + return self.__delete_request(trans, id) + elif operation == "undelete": + id = trans.security.decode_id(kwargs['id']) + return self.__undelete_request(trans, id) + elif operation == "edit": + id = trans.security.decode_id(kwargs['id']) + return self.__edit_request(trans, id) + if 'show_filter' in kwargs.keys(): + if kwargs['show_filter'] == 'All': + self.request_grid.default_filter = {} + elif kwargs['show_filter'] == 'Deleted': + self.request_grid.default_filter = dict(deleted=True) + else: + self.request_grid.default_filter = dict(state=kwargs['show_filter'], deleted=False) + self.request_grid.show_filter = kwargs.get('show_filter', trans.app.model.Request.states.UNSUBMITTED) # Render the list view return self.request_grid( trans, template='/requests/grid.mako', **kwargs ) @@ -94,21 +117,19 @@ message="Invalid request ID", **kwd) ) self.current_samples = [] + self.edit_mode = False for s in request.samples: self.current_samples.append([s.name, s.values.content]) if add_sample: self.current_samples.append(['Sample_%i' % (len(self.current_samples)+1),['' for field in request.type.sample_form.fields]]) - # selectfield of all samples - copy_list = SelectField('copy_sample') - copy_list.add_option('None', -1, selected=True) - for i, s in enumerate(self.current_samples): - copy_list.add_option(i+1, i) self.details_state = 'Show request details' return trans.fill_template( '/requests/show_request.mako', request=request, request_details=self.request_details(trans, id), current_samples = self.current_samples, - sample_copy=copy_list, details_state=self.details_state) + sample_copy=self.__copy_sample(), + details_state=self.details_state, + edit_mode=self.edit_mode) def request_details(self, trans, id): ''' Shows the request details @@ -128,19 +149,37 @@ value=request.create_time, helptext='')) # library associated - request_details.append(dict(label='Library', - value=request.library.name, - helptext='Associated library where the resultant \ - dataset will be stored')) + if request.library: + request_details.append(dict(label='Library', + value=request.library.name, + helptext='Associated library where the resultant \ + dataset will be stored')) + else: + request_details.append(dict(label='Library', + value=None, + helptext='Associated library where the resultant \ + dataset will be stored')) + # form fields for index, field in enumerate(request.type.request_form.fields): if field['required']: req = 'Required' else: req = 'Optional' - request_details.append(dict(label=field['label'], - value=request.values.content[index], - helptext=field['helptext']+' ('+req+')')) + if field['type'] == 'AddressField': + if request.values.content[index]: + request_details.append(dict(label=field['label'], + value=trans.app.model.UserAddress.get(int(request.values.content[index])).get_html(), + helptext=field['helptext']+' ('+req+')')) + else: + request_details.append(dict(label=field['label'], + value=None, + helptext=field['helptext']+' ('+req+')')) + + else: + request_details.append(dict(label=field['label'], + value=request.values.content[index], + helptext=field['helptext']+' ('+req+')')) return request_details def __update_samples(self, request, **kwd): @@ -156,6 +195,13 @@ for field_index in range(len(request.type.sample_form.fields)): sample_values.append(util.restore_text( params.get( 'sample_%i_field_%i' % (sample_index, field_index), '' ) )) self.current_samples.append([sample_name, sample_values]) + + def __copy_sample(self): + copy_list = SelectField('copy_sample') + copy_list.add_option('None', -1, selected=True) + for i, s in enumerate(self.current_samples): + copy_list.add_option(s[0], i) + return copy_list @web.expose def show_request(self, trans, **kwd): params = util.Params( kwd ) @@ -169,7 +215,28 @@ status='error', message="Invalid request ID", **kwd) ) - if params.get('add_sample_button', False) == 'Add New': + if params.get('import_samples_button', False) == 'Import samples': + import traceback + try: + fname = params.get('import_samples', '') + import csv + reader = csv.reader(open(fname)) + for row in reader: + self.current_samples.append([row[0], row[1:]]) + return trans.fill_template( '/requests/show_request.mako', + request=request, + request_details=self.request_details(trans, request.id), + current_samples=self.current_samples, + sample_copy=self.__copy_sample(), + details_state=self.details_state, + edit_mode=self.edit_mode) + except: + return trans.response.send_redirect( web.url_for( controller='requests', + action='list', + status='error', + message='Error in importing <b>%s</b> samples file' % fname, + **kwd)) + elif params.get('add_sample_button', False) == 'Add New': # save the all (saved+unsaved) sample info in 'current_samples' self.__update_samples(request, **kwd) # add an empty or filled sample @@ -182,17 +249,14 @@ else: self.current_samples.append([self.current_samples[src_sample_index][0]+'_%i' % (len(self.current_samples)+1), [val for val in self.current_samples[src_sample_index][1]]]) - # selectfield of all samples - copy_list = SelectField('copy_sample') - copy_list.add_option('None', -1, selected=True) - for i, s in enumerate(self.current_samples): - copy_list.add_option(i+1, i) return trans.fill_template( '/requests/show_request.mako', request=request, request_details=self.request_details(trans, request.id), - current_samples = self.current_samples, - sample_copy=copy_list, details_state=self.details_state) - if params.get('save_samples_button', False) == 'Save': + current_samples=self.current_samples, + sample_copy=self.__copy_sample(), + details_state=self.details_state, + edit_mode=self.edit_mode) + elif params.get('save_samples_button', False) == 'Save': # update current_samples self.__update_samples(request, **kwd) # check for duplicate sample names @@ -211,35 +275,59 @@ msg = "This request has <b>%i</b> samples with the name <b>%s</b>.\nSamples belonging to a request must have unique names." % (count, sample_name) break if msg: - copy_list = SelectField('copy_sample') - copy_list.add_option('None', -1, selected=True) - for i, s in enumerate(self.current_samples): - copy_list.add_option(i+1, i) return trans.fill_template( '/requests/show_request.mako', request=request, request_details=self.request_details(trans, request.id), current_samples = self.current_samples, - sample_copy=copy_list, details_state=self.details_state, + sample_copy=self.__copy_sample(), details_state=self.details_state, messagetype='error', msg=msg) # save all the new/unsaved samples entered by the user - for index in range(len(self.current_samples)-len(request.samples)): - sample_index = index + len(request.samples) - sample_name = util.restore_text( params.get( 'sample_%i_name' % sample_index, '' ) ) - sample_values = [] - for field_index in range(len(request.type.sample_form.fields)): - sample_values.append(util.restore_text( params.get( 'sample_%i_field_%i' % (sample_index, field_index), '' ) )) - form_values = trans.app.model.FormValues(request.type.sample_form, sample_values) - form_values.flush() - s = trans.app.model.Sample(sample_name, '', request, form_values) - s.flush() - # set the initial state - state = s.request.type.states[0] - event = trans.app.model.SampleEvent(s, state) - event.flush() + if not self.edit_mode: + for index in range(len(self.current_samples)-len(request.samples)): + sample_index = index + len(request.samples) + sample_name = util.restore_text( params.get( 'sample_%i_name' % sample_index, '' ) ) + sample_values = [] + for field_index in range(len(request.type.sample_form.fields)): + sample_values.append(util.restore_text( params.get( 'sample_%i_field_%i' % (sample_index, field_index), '' ) )) + form_values = trans.app.model.FormValues(request.type.sample_form, sample_values) + form_values.flush() + s = trans.app.model.Sample(sample_name, '', request, form_values) + s.flush() + else: + for index in range(len(self.current_samples)): + sample_index = index + sample_name = self.current_samples[sample_index][0] + new_sample_name = util.restore_text( params.get( 'sample_%i_name' % sample_index, '' ) ) + sample_values = [] + for field_index in range(len(request.type.sample_form.fields)): + sample_values.append(util.restore_text( params.get( 'sample_%i_field_%i' % (sample_index, field_index), '' ) )) + sample = request.has_sample(sample_name) + if sample: + form_values = trans.app.model.FormValues.get(sample.values.id) + form_values.content = sample_values + form_values.flush() + sample.name = new_sample_name + sample.flush() return trans.response.send_redirect( web.url_for( controller='requests', action='list', operation='show_request', id=trans.security.encode_id(request.id)) ) + elif params.get('edit_samples_button', False) == 'Edit samples': + self.edit_mode = True + return trans.fill_template( '/requests/show_request.mako', + request=request, + request_details=self.request_details(trans, request.id), + current_samples=self.current_samples, + sample_copy=self.__copy_sample(), + details_state=self.details_state, + edit_mode=self.edit_mode) + elif params.get('cancel_changes_button', False) == 'Cancel': + return trans.response.send_redirect( web.url_for( controller='requests', + action='list', + operation='show_request', + id=trans.security.encode_id(request.id)) ) + + @web.expose def delete_sample(self, trans, **kwd): params = util.Params( kwd ) @@ -253,16 +341,15 @@ s.delete() s.flush() request.flush() - del self.current_samples[sample_index] - copy_list = SelectField('copy_sample') - copy_list.add_option('None', -1, selected=True) - for i, s in enumerate(self.current_samples): - copy_list.add_option(i+1, i) + del self.current_samples[sample_index] return trans.fill_template( '/requests/show_request.mako', request=request, request_details=self.request_details(trans, request.id), current_samples = self.current_samples, - sample_copy=copy_list, details_state=self.details_state) + sample_copy=self.__copy_sample(), + details_state=self.details_state, + edit_mode=self.edit_mode) + @web.expose def toggle_request_details(self, trans, **kwd): params = util.Params( kwd ) @@ -272,121 +359,95 @@ if self.details_state == 'Show request details': self.details_state = 'Hide request details' elif self.details_state == 'Hide request details': - self.details_state = 'Show request details' - copy_list = SelectField('copy_sample') - copy_list.add_option('None', -1, selected=True) - for i, s in enumerate(self.current_samples): - copy_list.add_option(i+1, i) + self.details_state = 'Show request details' return trans.fill_template( '/requests/show_request.mako', request=request, request_details=self.request_details(trans, request.id), current_samples = self.current_samples, - sample_copy=copy_list, details_state=self.details_state) + sample_copy=self.__copy_sample(), + details_state=self.details_state, + edit_mode=self.edit_mode) + def __select_request_type(self, trans, rtid): + rt_ids = ['none'] + for rt in trans.app.model.RequestType.query().all(): + if not rt.deleted: + rt_ids.append(str(rt.id)) + select_reqtype = SelectField('select_request_type', + refresh_on_change=True, + refresh_on_change_values=rt_ids[1:]) + if rtid == 'none': + select_reqtype.add_option('Select one', 'none', selected=True) + else: + select_reqtype.add_option('Select one', 'none') + for rt in trans.app.model.RequestType.query().all(): + if not rt.deleted: + if rtid == rt.id: + select_reqtype.add_option(rt.name, rt.id, selected=True) + else: + select_reqtype.add_option(rt.name, rt.id) + return select_reqtype @web.expose def new(self, trans, **kwd): params = util.Params( kwd ) msg = util.restore_text( params.get( 'msg', '' ) ) messagetype = params.get( 'messagetype', 'done' ) if params.get('select_request_type', False) == 'True': - return trans.fill_template( '/requests/select_request_type.mako', - request_types=trans.app.model.RequestType.query().all(), - libraries=self.get_authorized_libs(trans), + return trans.fill_template( '/requests/new_request.mako', + select_request_type=self.__select_request_type(trans, 'none'), + widgets=[], msg=msg, - messagetype=messagetype ) + messagetype=messagetype) elif params.get('create', False) == 'True': - return self.__show_request_form(trans=trans, - request=None, **kwd) - elif params.get('save', False) == 'True': - request_type = trans.app.model.RequestType.get(int(params.request_type_id)) - msg = self.__validate(trans, - [('name','Name')], - request_type.request_form.fields, - **kwd) - if msg: - kwd['create'] = 'True' - return trans.response.send_redirect( web.url_for( controller='requests', - action='new', - msg=msg, - messagetype='error', - **kwd) ) - request = self.__save_request(trans, None, **kwd) - msg = 'The new request named %s has been created' % request.name - request_type_id = int(util.restore_text( params.request_type_id )) - if params.get('create_request_button', False) == 'Save': - return trans.response.send_redirect( web.url_for( controller='requests', - action='list', - msg=msg , - messagetype='done') ) - elif params.get('create_request_samples_button', False) == 'Add samples': - new_kwd = {} - new_kwd['id'] = trans.security.encode_id(request.id) - new_kwd['operation'] = 'show_request' - new_kwd['add_sample'] = True - return trans.response.send_redirect( web.url_for( controller='requests', - action='list', - msg=msg , - messagetype='done', - **new_kwd) ) + if params.get('create_request_button', False) == 'Save' \ + or params.get('create_request_samples_button', False) == 'Add samples': + request_type = trans.app.model.RequestType.get(int(params.select_request_type)) + if not util.restore_text(params.get('name', '')): + msg = 'Please enter the <b>Name</b> of the request' + kwd['create'] = 'True' + kwd['messagetype'] = 'error' + kwd['msg'] = msg + kwd['create_request_button'] = None + kwd['create_request_samples_button'] = None + return trans.response.send_redirect( web.url_for( controller='requests', + action='new', + **kwd) ) + request = self.__save_request(trans, None, **kwd) + msg = 'The new request named %s has been created' % request.name + if params.get('create_request_button', False) == 'Save': + return trans.response.send_redirect( web.url_for( controller='requests', + action='list', + msg=msg , + messagetype='done') ) + elif params.get('create_request_samples_button', False) == 'Add samples': + new_kwd = {} + new_kwd['id'] = trans.security.encode_id(request.id) + new_kwd['operation'] = 'show_request' + new_kwd['add_sample'] = True + return trans.response.send_redirect( web.url_for( controller='requests', + action='list', + msg=msg , + messagetype='done', + **new_kwd) ) + else: + return self.__show_request_form(trans, **kwd) + elif params.get('refresh', False) == 'true': + return self.__show_request_form(trans, **kwd) - def __validate(self, trans, main_fields=[], form_fields=[], **kwd): - ''' - Validates the request entered by the user - ''' - params = util.Params( kwd ) - for field, field_name in main_fields: - if not util.restore_text(params.get(field, '')): - return 'Please enter the <b>%s</b> of the request' % field_name - # check rest of the fields of the form - for index, field in enumerate(form_fields): - if not util.restore_text(params.get('field_%i' % index, None)) \ - and field['required'] == 'required': - return 'Please enter the <b>%s</b> field of the request' % field['label'] - return None - def __save_request(self, trans, request_id=None, **kwd): - ''' - This method saves a new request if request_id is None. - ''' - params = util.Params( kwd ) - if not request_id: - request_type = trans.app.model.RequestType.get(int(params.request_type_id )) - else: - # TODO editing - pass - name = util.restore_text(params.get('name', '')) - desc = util.restore_text(params.get('desc', '')) - try: - library_id = int(util.restore_text(params.get('library_id', None))) - except: - msg = "Sequencing request could not be saved. Invalid library" - return trans.response.send_redirect( web.url_for( controller='requests', - action='list', - status='error', - message=msg, - **kwd) ) - values = [] - for index, field in enumerate(request_type.request_form.fields): - values.append(util.restore_text(params.get('field_%i' % index, ''))) - if not request_id: - form_values = trans.app.model.FormValues(request_type.request_form, values) - form_values.flush() - request = trans.app.model.Request(name, desc, request_type, - trans.user, form_values, - trans.app.model.Library.get(library_id), - submitted=False) - request.flush() - else: - # TODO editing - pass - return request - def __show_request_form(self, trans, request=None, **kwd): + + def __show_request_form(self, trans, **kwd): params = util.Params( kwd ) msg = util.restore_text( params.get( 'msg', '' ) ) messagetype = params.get( 'messagetype', 'done' ) - request_type = trans.app.model.RequestType.get(int(params.request_type_id)) - if request: - form_values = request.values - else: - form_values = None + try: + request_type = trans.app.model.RequestType.get(int(params.select_request_type)) + except: + return trans.fill_template( '/requests/new_request.mako', + select_request_type=self.__select_request_type(trans, 'none'), + widgets=[], + msg=msg, + messagetype=messagetype) + form_values = None + select_request_type = self.__select_request_type(trans, request_type.id) # list of widgets to be rendered on the request form widgets = [] widgets.append(dict(label='Name', @@ -397,53 +458,305 @@ widget=TextField('desc', 40, util.restore_text( params.get( 'desc', '' ) )), helptext='(Optional)')) + # libraries selectbox libraries = self.get_authorized_libs(trans) - if libraries: - libui = self.__library_ui(libraries, **kwd) - widgets.append(libui) + libui = self.__library_ui(libraries, **kwd) + widgets = widgets + libui widgets = self.__create_form(trans, request_type.request_form_id, widgets, form_values, **kwd) title = 'Add a new request of type: %s' % request_type.name return trans.fill_template( '/requests/new_request.mako', - request_form_id=request_type.request_form_id, - request_type=request_type, - widgets=widgets, - title=title, - msg=msg, - messagetype=messagetype) + select_request_type=select_request_type, + request_type=request_type, + widgets=widgets, + msg=msg, + messagetype=messagetype) - def __library_ui(self, libraries, **kwd): + def __library_ui(self, libraries, request=None, **kwd): params = util.Params( kwd ) - create_lib_str = 'Create a new library' - value = int(params.get( 'library_id', 0 )) - if not value: # if no library previously selected - # show the selectbox with 'create a new library' option selected - lib_list = SelectField('library_id', refresh_on_change=True, - refresh_on_change_values=[create_lib_str]) - #lib_list.add_option(create_lib_str, 0, selected=True) - for lib in libraries: + lib_id = params.get( 'library_id', 'none' ) + lib_list = SelectField('library_id', refresh_on_change=True, + refresh_on_change_values=['new']) + if request and lib_id == 'none': + if request.library: + lib_id = str(request.library.id) + if lib_id == 'none': + lib_list.add_option('Select one', 'none', selected=True) + else: + lib_list.add_option('Select one', 'none') + for lib in libraries: + if str(lib.id) == lib_id: + lib_list.add_option(lib.name, lib.id, selected=True) + else: lib_list.add_option(lib.name, lib.id) - widget = dict(label='Library', - widget=lib_list, - helptext='Associated library where the resultant \ - dataset will be stored.') - else: # if some library previously selected - # show the selectbox with some library selected - lib_list = SelectField('library_id', refresh_on_change=True, - refresh_on_change_values=[create_lib_str]) - #lib_list.add_option(create_lib_str, 0) - for lib in libraries: - if value == lib.id: - lib_list.add_option(lib.name, lib.id, selected=True) + if lib_id == 'new': + lib_list.add_option('Create a new library', 'new', selected=True) + else: + lib_list.add_option('Create a new library', 'new') + widget = dict(label='Library', + widget=lib_list, + helptext='Associated library where the resultant \ + dataset will be stored.') + if lib_id == 'new': + new_lib = dict(label='Create a new Library', + widget=TextField('new_library_name', 40, + util.restore_text( params.get( 'new_library_name', '' ) )), + helptext='Enter a library name here to request a new library') + return [widget, new_lib] + else: + return [widget] + + def __create_form(self, trans, form_id, widgets=[], form_values=None, **kwd): + params = util.Params( kwd ) + form = trans.app.model.FormDefinition.get(form_id) + # form fields + for index, field in enumerate(form.fields): + # value of the field + if field['type'] == 'CheckboxField': + value = util.restore_text( params.get( 'field_%i' % index, False ) ) + else: + value = util.restore_text( params.get( 'field_%i' % index, '' ) ) + if not value: + if form_values: + value = str(form_values.content[index]) + # create the field + fw = eval(field['type'])('field_%i' % index) + if field['type'] == 'TextField': + fw.set_size(40) + fw.value = value + elif field['type'] == 'TextArea': + fw.set_size(3, 40) + fw.value = value + elif field['type'] == 'AddressField': + fw.user = trans.user + fw.value = value + fw.params = params + elif field['type'] == 'SelectField': + for option in field['selectlist']: + if option == value: + fw.add_option(option, option, selected=True) + else: + fw.add_option(option, option) + elif field['type'] == 'CheckboxField': + fw.checked = value + # require/optional + if field['required'] == 'required': + req = 'Required' + else: + req = 'Optional' + widgets.append(dict(label=field['label'], + widget=fw, + helptext=field['helptext']+' ('+req+')')) + return widgets + def __validate(self, trans, request): + ''' + Validates the request entered by the user + ''' + empty_fields = [] + if not request.library: + empty_fields.append('Library') + # check rest of the fields of the form + for index, field in enumerate(request.type.request_form.fields): + if field['required'] == 'required' and request.values.content[index] in ['', None]: + empty_fields.append(field['label']) + if empty_fields: + msg = 'Fill the following fields of the request <b>%s</b> before submitting<br/>' % request.name + for ef in empty_fields: + msg = msg + '<b>' +ef + '</b><br/>' + return msg + return None + def __save_request(self, trans, request=None, **kwd): + ''' + This method saves a new request if request_id is None. + ''' + params = util.Params( kwd ) + request_type = trans.app.model.RequestType.get(int(params.select_request_type)) + name = util.restore_text(params.get('name', '')) + desc = util.restore_text(params.get('desc', '')) + # library + try: + library = trans.app.model.Library.get(int(params.get('library_id', None))) + except: + library = None + # fields + values = [] + for index, field in enumerate(request_type.request_form.fields): + if field['type'] == 'AddressField': + value = util.restore_text(params.get('field_%i' % index, '')) + if value == 'new': + # save this new address in the list of this user's addresses + user_address = trans.app.model.UserAddress( user=trans.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, '')) + user_address.flush() + trans.user.refresh() + values.append(int(user_address.id)) + elif value == unicode('none'): + values.append('') else: - lib_list.add_option(lib.name, lib.id) - widget = dict(label='Library', - widget=lib_list, - helptext='Associated library where the resultant \ - dataset will be stored.') - return widget - + values.append(int(value)) + else: + values.append(util.restore_text(params.get('field_%i' % index, ''))) + form_values = trans.app.model.FormValues(request_type.request_form, values) + form_values.flush() + if not request: + request = trans.app.model.Request(name, desc, request_type, + trans.user, form_values, + library=library, + state=trans.app.model.Request.states.UNSUBMITTED) + request.flush() + else: + request.name = name + request.desc = desc + request.type = request_type + request.user = trans.user + request.values = form_values + request.library = library + request.state = trans.app.model.Request.states.UNSUBMITTED + request.flush() + return request + @web.expose + def edit(self, trans, **kwd): + params = util.Params( kwd ) + msg = util.restore_text( params.get( 'msg', '' ) ) + messagetype = params.get( 'messagetype', 'done' ) + try: + request = trans.app.model.Request.get(int(params.get('request_id', None))) + except: + return trans.response.send_redirect( web.url_for( controller='requests', + action='list', + status='error', + message="Invalid request ID", + **kwd) ) + if params.get('show', False) == 'True': + return self.__edit_request(trans, request.id, **kwd) + elif params.get('save_changes_request_button', False) == 'Save changes' \ + or params.get('edit_samples_button', False) == 'Edit samples': + request_type = trans.app.model.RequestType.get(int(params.select_request_type)) + if not util.restore_text(params.get('name', '')): + msg = 'Please enter the <b>Name</b> of the request' + kwd['messagetype'] = 'error' + kwd['msg'] = msg + kwd['show'] = 'True' + return trans.response.send_redirect( web.url_for( controller='requests', + action='edit', + **kwd) ) + request = self.__save_request(trans, request, **kwd) + msg = 'The changes made to the request named %s has been saved' % request.name + if params.get('save_changes_request_button', False) == 'Save changes': + return trans.response.send_redirect( web.url_for( controller='requests', + action='list', + message=msg , + status='done') ) + elif params.get('edit_samples_button', False) == 'Edit samples': + new_kwd = {} + new_kwd['request_id'] = request.id + new_kwd['edit_samples_button'] = 'Edit samples' + return trans.response.send_redirect( web.url_for( controller='requests', + action='show_request', + msg=msg , + messagetype='done', + **new_kwd) ) + elif params.get('refresh', False) == 'true': + return self.__edit_request(trans, request.id, **kwd) + + def __edit_request(self, trans, id, **kwd): + try: + request = trans.app.model.Request.get(id) + except: + msg = "Invalid request ID" + log.warn( msg ) + return trans.response.send_redirect( web.url_for( controller='requests', + action='list', + status='error', + message=msg) ) + params = util.Params( kwd ) + msg = util.restore_text( params.get( 'msg', '' ) ) + messagetype = params.get( 'messagetype', 'done' ) + select_request_type = self.__select_request_type(trans, request.type.id) + # list of widgets to be rendered on the request form + widgets = [] + if util.restore_text( params.get( 'name', '' ) ): + name = util.restore_text( params.get( 'name', '' ) ) + else: + name = request.name + widgets.append(dict(label='Name', + widget=TextField('name', 40, name), + helptext='(Required)')) + if util.restore_text( params.get( 'desc', '' ) ): + desc = util.restore_text( params.get( 'desc', '' ) ) + else: + desc = request.desc + widgets.append(dict(label='Description', + widget=TextField('desc', 40, desc), + helptext='(Optional)')) + + # libraries selectbox + libraries = self.get_authorized_libs(trans) + libui = self.__library_ui(libraries, request, **kwd) + widgets = widgets + libui + widgets = self.__create_form(trans, request.type.request_form_id, widgets, + request.values, **kwd) + return trans.fill_template( '/requests/edit_request.mako', + select_request_type=select_request_type, + request_type=request.type, + request=request, + widgets=widgets, + msg=msg, + messagetype=messagetype) + return self.__show_request_form(trans) + def __delete_request(self, trans, id): + try: + request = trans.app.model.Request.get(id) + except: + msg = "Invalid request ID" + log.warn( msg ) + return trans.response.send_redirect( web.url_for( controller='requests', + action='list', + status='error', + message=msg, + **kwd) ) + # change request's submitted field + if not request.unsubmitted(): + return trans.response.send_redirect( web.url_for( controller='requests', + action='list', + status='error', + message='This request cannot be deleted as it is already been submitted', + **kwd) ) + request.deleted = True + request.flush() + kwd = {} + kwd['id'] = trans.security.encode_id(request.id) + return trans.response.send_redirect( web.url_for( controller='requests', + action='list', + **kwd) ) + def __undelete_request(self, trans, id): + try: + request = trans.app.model.Request.get(id) + except: + msg = "Invalid request ID" + log.warn( msg ) + return trans.response.send_redirect( web.url_for( controller='requests', + action='list', + status='error', + message=msg, + **kwd) ) + # change request's submitted field + request.deleted = False + request.flush() + kwd = {} + kwd['id'] = trans.security.encode_id(request.id) + return trans.response.send_redirect( web.url_for( controller='requests', + action='list', + **kwd) ) def __submit(self, trans, id): try: request = trans.app.model.Request.get(id) @@ -455,13 +768,21 @@ status='error', message=msg, **kwd) ) + msg = self.__validate(trans, request) + if msg: + return trans.response.send_redirect( web.url_for( controller='requests', + action='edit', + messagetype = 'error', + msg=msg, + request_id=request.id, + show='True') ) # get the new state - new_state = request.type.states[1] + new_state = request.type.states[0] for s in request.samples: event = trans.app.model.SampleEvent(s, new_state, 'Samples submitted to the system') event.flush() # change request's submitted field - request.submitted = True + request.state = request.states.SUBMITTED request.flush() kwd = {} kwd['id'] = trans.security.encode_id(request.id) @@ -482,54 +803,28 @@ status='error', message=msg, **kwd) ) + msg = self.__validate(trans, request) + if msg: + return trans.response.send_redirect( web.url_for( controller='requests', + action='edit', + messagetype = 'error', + msg=msg, + request_id=request.id, + show='True') ) # get the new state - new_state = request.type.states[1] + new_state = request.type.states[0] for s in request.samples: event = trans.app.model.SampleEvent(s, new_state, 'Samples submitted to the system') event.flush() # change request's submitted field - request.submitted = True + request.state = request.states.SUBMITTED request.flush() ## TODO kwd['id'] = trans.security.encode_id(request.id) return trans.response.send_redirect( web.url_for( controller='requests', action='list', **kwd) ) - def __create_form(self, trans, form_id, widgets=[], form_values=None, **kwd): - params = util.Params( kwd ) - form = trans.app.model.FormDefinition.get(form_id) - # form fields - for index, field in enumerate(form.fields): - # value of the field - if field['type'] == 'CheckboxField': - value = util.restore_text( params.get( 'field_%i' % index, False ) ) - else: - value = util.restore_text( params.get( 'field_%i' % index, '' ) ) - # create the field - fw = eval(field['type'])('field_%i' % index) - if field['type'] == 'TextField': - fw.set_size(40) - fw.value = value - elif field['type'] == 'TextArea': - fw.set_size(3, 40) - fw.value = value - elif field['type'] == 'SelectField': - for option in field['selectlist']: - if option == value: - fw.add_option(option, option, selected=True) - else: - fw.add_option(option, option) - elif field['type'] == 'CheckboxField': - fw.checked = value - # require/optional - if field['required'] == 'required': - req = 'Required' - else: - req = 'Optional' - widgets.append(dict(label=field['label'], - widget=fw, - helptext=field['helptext']+' ('+req+')')) - return widgets + @web.expose def show_events(self, trans, **kwd): params = util.Params( kwd ) diff -r 11a2d159e280 -r 24ccfa887fcd lib/galaxy/web/controllers/requests_admin.py --- a/lib/galaxy/web/controllers/requests_admin.py Wed Aug 05 12:59:24 2009 -0400 +++ b/lib/galaxy/web/controllers/requests_admin.py Thu Aug 06 09:52:59 2009 -0400 @@ -26,6 +26,7 @@ link=( lambda item: iff( item.deleted, None, dict( operation="show_request", id=item.id ) ) ), ), grids.GridColumn( "Type", key="request_type_id", method='get_request_type'), grids.GridColumn( "Last update", key="update_time", format=time_ago ), + grids.GridColumn( "State", key='state'), grids.GridColumn( "User", key="user_id", method='get_user') ] @@ -36,9 +37,10 @@ # grids.GridOperation( "Undelete", condition=( lambda item: item.deleted ) ), ] standard_filters = [ - grids.GridColumnFilter( "Active", args=dict( deleted=False ) ), - grids.GridColumnFilter( "Deleted", args=dict( deleted=True ) ), - grids.GridColumnFilter( "All", args=dict( deleted='All' ) ) + grids.GridColumnFilter( model.Request.states.SUBMITTED, + args=dict( state=model.Request.states.SUBMITTED, deleted=False ) ), + grids.GridColumnFilter( model.Request.states.COMPLETE, args=dict( state=model.Request.states.COMPLETE, deleted=False ) ), + grids.GridColumnFilter( "All", args=dict( deleted=False ) ) ] def get_user(self, trans, request): return trans.app.model.User.get(request.user_id).email @@ -48,7 +50,8 @@ request_type = trans.app.model.RequestType.get(request.request_type_id) return request_type.name def apply_default_filter( self, trans, query ): - return query.filter_by(submitted=True) + return query.filter(or_(self.model_class.state==self.model_class.states.SUBMITTED, + self.model_class.state==self.model_class.states.COMPLETE)) def number_of_samples(self, trans, request): return str(len(request.samples)) @@ -59,13 +62,6 @@ @web.require_admin def index( self, trans ): return trans.fill_template( "/admin/requests/index.mako" ) - def get_authorized_libs(self, trans): - all_libraries = trans.app.model.Library.filter(trans.app.model.Library.table.c.deleted == False).order_by(trans.app.model.Library.name).all() - authorized_libraries = [] - for library in all_libraries: - if trans.app.security_agent.allow_action(trans.user, trans.app.security_agent.permitted_actions.LIBRARY_ADD, library_item=library) or trans.app.security_agent.allow_action(trans.user, trans.app.security_agent.permitted_actions.LIBRARY_MODIFY, library_item=library) or trans.app.security_agent.allow_action(trans.user, trans.app.security_agent.permitted_actions.LIBRARY_MANAGE, library_item=library) or trans.app.security_agent.check_folder_contents(trans.user, library) or trans.app.security_agent.show_library_item(trans.user, library): - authorized_libraries.append(library) - return authorized_libraries @web.expose @web.require_admin def list( self, trans, **kwargs ): @@ -73,11 +69,19 @@ List all request made by the current user ''' status = message = None + self.request_grid.default_filter = dict(state=trans.app.model.Request.states.SUBMITTED, + deleted=False) if 'operation' in kwargs: operation = kwargs['operation'].lower() if operation == "show_request": id = trans.security.decode_id(kwargs['id']) return self.__show_request(trans, id) + + if 'show_filter' in kwargs.keys(): + if kwargs['show_filter'] == 'All': + self.request_grid.default_filter = dict(deleted=False) + else: + self.request_grid.default_filter = dict(state=kwargs['show_filter'], deleted=False) # Render the list view return self.request_grid( trans, template='/admin/requests/grid.mako', **kwargs ) def __show_request(self, trans, id): @@ -122,7 +126,6 @@ Shows the request details ''' request = trans.app.model.Request.get(id) - libraries = self.get_authorized_libs(trans) # list of widgets to be rendered on the request form request_details = [] # main details @@ -152,55 +155,124 @@ req = 'Required' else: req = 'Optional' - request_details.append(dict(label=field['label'], - value=request.values.content[index], - helptext=field['helptext']+' ('+req+')')) + if field['type'] == 'AddressField': + if request.values.content[index]: + request_details.append(dict(label=field['label'], + value=trans.app.model.UserAddress.get(int(request.values.content[index])).get_html(), + helptext=field['helptext']+' ('+req+')')) + else: + request_details.append(dict(label=field['label'], + value=None, + helptext=field['helptext']+' ('+req+')')) + else: + request_details.append(dict(label=field['label'], + value=request.values.content[index], + helptext=field['helptext']+' ('+req+')')) return request_details @web.expose @web.require_admin def bar_codes(self, trans, **kwd): params = util.Params( kwd ) - request_id = params.get('request_id', None) - if request_id: - request_id = int(request_id) - request = trans.app.model.Request.get(request_id) - return trans.fill_template( '/admin/samples/bar_codes.mako', - samples_list=[s for s in request.samples], - user=request.user, - request=request) + try: + request = trans.app.model.Request.get(int(params.get('request_id', None))) + except: + return trans.response.send_redirect( web.url_for( controller='requests', + action='list', + status='error', + message="Invalid request ID", + **kwd) ) + widgets = [] + for index, sample in enumerate(request.samples): + if sample.bar_code: + bc = sample.bar_code + else: + bc = util.restore_text(params.get('sample_%i_bar_code' % index, '')) + widgets.append(TextField('sample_%i_bar_code' % index, + 40, + bc)) + return trans.fill_template( '/admin/samples/bar_codes.mako', + samples_list=[s for s in request.samples], + user=request.user, request=request, widgets=widgets) @web.expose @web.require_admin def save_bar_codes(self, trans, **kwd): params = util.Params( kwd ) - request_id = params.get('request_id', None) - if request_id: - request_id = int(request_id) - request = trans.app.model.Request.get(request_id) - # validate - # bar codes need to be globally unique - unique = True - for index in range(len(request.samples)): - bar_code = util.restore_text(params.get('sample_%i_bar_code' % index, '')) - all_samples = trans.app.model.Sample.query.all() - for sample in all_samples: - if bar_code == sample.bar_code: - unique = False - if not unique: - return trans.fill_template( '/admin/samples/bar_codes.mako', - samples_list=[s for s in request.samples], - user=request.user, - request=request, - messagetype='error', - msg='Samples cannot have same bar code.') + try: + request = trans.app.model.Request.get(int(params.get('request_id', None))) + except: + return trans.response.send_redirect( web.url_for( controller='requests', + action='list', + status='error', + message="Invalid request ID", + **kwd) ) + # validate + # bar codes need to be globally unique + msg = '' + for index in range(len(request.samples)): + bar_code = util.restore_text(params.get('sample_%i_bar_code' % index, '')) + # check for empty bar code + if not bar_code.strip(): + msg = 'Please fill the bar code for sample <b>%s</b>.' % request.samples[index].name + break + # check all the unsaved bar codes + count = 0 + for i in range(len(request.samples)): + if bar_code == util.restore_text(params.get('sample_%i_bar_code' % i, '')): + count = count + 1 + if count > 1: + msg = '''The bar code <b>%s</b> of sample <b>%s</b> already belongs + another sample in this request. The sample bar codes must + be unique throughout the system''' % \ + (bar_code, request.samples[index].name) + break + # check all the saved bar codes + all_samples = trans.app.model.Sample.query.all() + for sample in all_samples: + if bar_code == sample.bar_code: + msg = '''The bar code <b>%s</b> of sample <b>%s</b> already + belongs another sample. The sample bar codes must be + unique throughout the system''' % \ + (bar_code, request.samples[index].name) + break + if msg: + break + if msg: + widgets = [] for index, sample in enumerate(request.samples): - bar_code = util.restore_text(params.get('sample_%i_bar_code' % index, '')) - sample.bar_code = bar_code - sample.flush() + if sample.bar_code: + bc = sample.bar_code + else: + bc = util.restore_text(params.get('sample_%i_bar_code' % index, '')) + widgets.append(TextField('sample_%i_bar_code' % index, + 40, + util.restore_text(params.get('sample_%i_bar_code' % index, '')))) + return trans.fill_template( '/admin/samples/bar_codes.mako', + samples_list=[s for s in request.samples], + user=request.user, request=request, widgets=widgets, messagetype='error', + msg=msg) + # now save the bar codes + for index, sample in enumerate(request.samples): + bar_code = util.restore_text(params.get('sample_%i_bar_code' % index, '')) + sample.bar_code = bar_code + sample.flush() return trans.response.send_redirect( web.url_for( controller='requests_admin', action='list', operation='show_request', id=trans.security.encode_id(request.id)) ) + def __set_request_state(self, request): + # check if all the samples of the current request are in the final state + complete = True + for s in request.samples: + if s.current_state().id != request.type.states[-1].id: + complete = False + if complete: + request.state = request.states.COMPLETE + else: + request.state = request.states.SUBMITTED + request.flush() + + def change_state(self, trans, sample): possible_states = sample.request.type.states curr_state = sample.current_state() @@ -236,6 +308,7 @@ and trans.app.model.SampleState.table.c.id == selected_state)[0] event = trans.app.model.SampleEvent(sample, new_state, comments) event.flush() + self.__set_request_state(sample.request) return trans.response.send_redirect( web.url_for( controller='requests_admin', action='show_events', sample_id=sample.id)) diff -r 11a2d159e280 -r 24ccfa887fcd lib/galaxy/web/controllers/user.py --- a/lib/galaxy/web/controllers/user.py Wed Aug 05 12:59:24 2009 -0400 +++ b/lib/galaxy/web/controllers/user.py Thu Aug 06 09:52:59 2009 -0400 @@ -21,7 +21,7 @@ require_login_creation_template = require_login_template % " If you don't already have an account, <a href='%s'>you may create one</a>." class User( BaseController ): - + edit_address_id = None @web.expose def index( self, trans, **kwd ): return trans.fill_template( '/user/index.mako', user=trans.get_user() ) @@ -224,3 +224,186 @@ 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." ) + + @web.expose + def manage_addresses(self, trans, **kwd): + if trans.user: + params = util.Params( kwd ) + show_filter = util.restore_text( params.get( 'show_filter', 'Active' ) ) + if show_filter == 'All': + addresses = [address for address in trans.user.addresses] + elif show_filter == 'Deleted': + addresses = [address for address in trans.user.addresses if address.deleted] + else: + addresses = [address for address in trans.user.addresses if not address.deleted] + return trans.fill_template( 'user/address.mako', + addresses=addresses, + show_filter=show_filter) + 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." ) + + @web.expose + def new_address( self, trans, short_desc='', name='', institution='', address1='', + address2='', city='', state='', postal_code='', country='', phone='' ): + if trans.app.config.require_login: + refresh_frames = [ 'masthead', 'history', 'tools' ] + else: + refresh_frames = [ 'masthead', 'history' ] + 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.' ) + short_desc_error = name_error = institution_error = address1_error = city_error = None + address2_error = state_error = postal_code_error = country_error = phone_error = None + if short_desc: + if not len( short_desc ): + short_desc_error = 'Enter a short description for this address' + elif not len( name ): + name_error = 'Enter the full name' + elif not len( institution ): + institution_error = 'Enter the institution associated with the user' + elif not len ( address1 ): + address1_error = 'Enter the address' + elif not len( city ): + city_error = 'Enter the city' + elif not len( state ): + state_error = 'Enter the state/province/region' + elif not len( postal_code ): + postal_code_error = 'Enter the postal code' + elif not len( country ): + country_error = 'Enter the country' + else: + user_address = trans.app.model.UserAddress( user=trans.user, desc=short_desc, + name=name, institution=institution, + address=address1+' '+address2, city=city, + state=state, postal_code=postal_code, + country=country, phone=phone) + user_address.flush() + return trans.response.send_redirect( web.url_for( controller='user', + action='manage_addresses', + msg='Address <b>%s</b> has been added' % user_address.desc, + messagetype='done') ) + + return trans.show_form( + web.FormBuilder( web.url_for(), "New address", submit_text="Save" ) + .add_text( "short_desc", "Short address description", value=short_desc, error=short_desc_error ) + .add_text( "name", "Name", value=name, error=name_error ) + .add_text( "institution", "Institution", value=institution, error=institution_error ) + .add_text( "address1", "Address Line 1", value=address1, error=address1_error ) + .add_text( "address2", "Address Line 2", value=address2, error=address2_error ) + .add_text( "city", "City", value=city, error=city_error ) + .add_text( "state", "State/Province/Region", value=state, error=state_error ) + .add_text( "postal_code", "Postal Code", value=postal_code, error=postal_code_error ) + .add_text( "country", "Country", value=country, error=country_error ) + .add_text( "phone", "Phone", value=phone, error=phone_error ) ) + + + @web.expose + def edit_address( self, trans, address_id=None, short_desc='', name='', institution='', address1='', + address2='', city='', state='', postal_code='', country='', phone='' ): + import sys + + if trans.app.config.require_login: + refresh_frames = [ 'masthead', 'history', 'tools' ] + else: + refresh_frames = [ 'masthead', 'history' ] + 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.' ) + short_desc_error = name_error = institution_error = address1_error = city_error = None + address2_error = state_error = postal_code_error = country_error = phone_error = None + if short_desc: + if not len( short_desc ): + short_desc_error = 'Enter a short description for this address' + elif not len( name ): + name_error = 'Enter the full name' + elif not len( institution ): + institution_error = 'Enter the institution associated with the user' + elif not len ( address1 ): + address1_error = 'Enter the address' + elif not len( city ): + city_error = 'Enter the city' + elif not len( state ): + state_error = 'Enter the state/province/region' + elif not len( postal_code ): + postal_code_error = 'Enter the postal code' + elif not len( country ): + country_error = 'Enter the country' + else: + if self.edit_address_id: + try: + user_address = trans.app.model.UserAddress.get(int(self.edit_address_id)) + except: + return trans.response.send_redirect( web.url_for( controller='user', + action='manage_addresses', + msg='Invalid address ID', + messagetype='error') ) + user_address.desc = short_desc + user_address.name = name + user_address.institution = institution + user_address.address = address1+' '+address2 + user_address.city = city + user_address.state = state + user_address.postal_code = postal_code + user_address.country = country + user_address.phone = phone + user_address.flush() + self.edit_address_id = None + return trans.response.send_redirect( web.url_for( controller='user', + action='manage_addresses', + msg='Changes made to address <b>%s</b> are saved.' % user_address.desc, + messagetype='done') ) + self.edit_address_id = address_id + return trans.show_form( + web.FormBuilder( web.url_for(), "Edit address", submit_text="Save changes" ) + .add_text( "short_desc", "Short address description", value=short_desc, error=short_desc_error ) + .add_text( "name", "Name", value=name, error=name_error ) + .add_text( "institution", "Institution", value=institution, error=institution_error ) + .add_text( "address1", "Address Line 1", value=address1, error=address1_error ) + .add_text( "address2", "Address Line 2", value=address2, error=address2_error ) + .add_text( "city", "City", value=city, error=city_error ) + .add_text( "state", "State/Province/Region", value=state, error=state_error ) + .add_text( "postal_code", "Postal Code", value=postal_code, error=postal_code_error ) + .add_text( "country", "Country", value=country, error=country_error ) + .add_text( "phone", "Phone", value=phone, error=phone_error ) ) + + @web.expose + def delete_address( self, trans, address_id=None): + if trans.app.config.require_login: + refresh_frames = [ 'masthead', 'history', 'tools' ] + else: + refresh_frames = [ 'masthead', 'history' ] + 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.' ) + try: + user_address = trans.app.model.UserAddress.get(int(address_id)) + except: + return trans.fill_template( 'user/address.mako', + msg='Invalid address ID', + messagetype='error' ) + user_address.deleted = True + user_address.flush() + return trans.response.send_redirect( web.url_for( controller='user', + action='manage_addresses', + msg='Address <b>%s</b> deleted' % user_address.desc, + messagetype='done') ) + + @web.expose + def undelete_address( self, trans, address_id=None): + if trans.app.config.require_login: + refresh_frames = [ 'masthead', 'history', 'tools' ] + else: + refresh_frames = [ 'masthead', 'history' ] + 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.' ) + try: + user_address = trans.app.model.UserAddress.get(int(address_id)) + except: + return trans.fill_template( 'user/address.mako', + msg='Invalid address ID', + messagetype='error' ) + user_address.deleted = False + user_address.flush() + return trans.response.send_redirect( web.url_for( controller='user', + action='manage_addresses', + msg='Address <b>%s</b> is restored' % user_address.desc, + messagetype='done') ) + diff -r 11a2d159e280 -r 24ccfa887fcd lib/galaxy/web/form_builder.py --- a/lib/galaxy/web/form_builder.py Wed Aug 05 12:59:24 2009 -0400 +++ b/lib/galaxy/web/form_builder.py Thu Aug 06 09:52:59 2009 -0400 @@ -11,7 +11,7 @@ raise TypeError( "Abstract Method" ) @staticmethod def form_field_types(): - return ['TextField', 'TextArea', 'SelectField', 'CheckboxField'] + return ['TextField', 'TextArea', 'SelectField', 'CheckboxField', 'AddressField'] class TextField(BaseField): """ @@ -340,6 +340,64 @@ recurse_options( rval, self.options, expanded_options ) rval.append( '</ul></div>' ) return '\n'.join( rval ) + +class AddressField(BaseField): + @staticmethod + def fields(): + return [ ( "short_desc", "Short address description"), + ( "name", "Name" ), + ( "institution", "Institution" ), + ( "address1", "Address Line 1" ), + ( "address2", "Address Line 2" ), + ( "city", "City" ), + ( "state", "State/Province/Region" ), + ( "postal_code", "Postal Code" ), + ( "country", "Country" ), + ( "phone", "Phone" ) ] + def __init__(self, name, user=None, value=None, params=None): + self.name = name + self.user = user + self.value = value + self.select_address = None + self.params = params + def get_html(self): + from galaxy import util + address_html = '' + add_ids = ['none'] + for a in self.user.addresses: + add_ids.append(str(a.id)) + add_ids.append('new') + self.select_address = SelectField(self.name, + refresh_on_change=True, + refresh_on_change_values=add_ids) + if self.value == 'none': + self.select_address.add_option('Select one', 'none', selected=True) + else: + self.select_address.add_option('Select one', 'none') + for a in self.user.addresses: + if not a.deleted: + if self.value == str(a.id): + self.select_address.add_option(a.desc, str(a.id), selected=True) + # display this address + address_html = '''<div class="form-row"> + %s + </div>''' % a.get_html() + else: + self.select_address.add_option(a.desc, str(a.id)) + if self.value == 'new': + self.select_address.add_option('Add a new address', 'new', selected=True) + for field_name, label in self.fields(): + add_field = TextField(self.name+'_'+field_name, + 40, + util.restore_text( self.params.get( self.name+'_'+field_name, '' ) )) + address_html += ''' <div class="form-row"> + <label>%s</label> + %s + </div> + ''' % (label, add_field.get_html()) + else: + self.select_address.add_option('Add a new address', 'new') + return self.select_address.get_html()+address_html def get_suite(): diff -r 11a2d159e280 -r 24ccfa887fcd lib/galaxy/web/framework/helpers/grids.py --- a/lib/galaxy/web/framework/helpers/grids.py Wed Aug 05 12:59:24 2009 -0400 +++ b/lib/galaxy/web/framework/helpers/grids.py Thu Aug 06 09:52:59 2009 -0400 @@ -43,6 +43,8 @@ query = column.filter( query, column_filter, filter_args ) # Carry filter along to newly generated urls extra_url_args[ "f-" + column.key ] = column_filter + if filter_args: + query = query.filter_by( **filter_args ) # Process sort arguments sort_key = sort_order = None if 'sort' in kwargs: diff -r 11a2d159e280 -r 24ccfa887fcd templates/admin/forms/create_form.mako --- a/templates/admin/forms/create_form.mako Wed Aug 05 12:59:24 2009 -0400 +++ b/templates/admin/forms/create_form.mako Thu Aug 06 09:52:59 2009 -0400 @@ -26,7 +26,7 @@ <div style="clear: both"></div> </div> <div class="form-row"> - <input type="submit" name="save_form" value="Save"/> + <input type="submit" name="save_form" value="Add fields"/> </div> </form> </div> diff -r 11a2d159e280 -r 24ccfa887fcd templates/admin/forms/edit_form.mako --- a/templates/admin/forms/edit_form.mako Wed Aug 05 12:59:24 2009 -0400 +++ b/templates/admin/forms/edit_form.mako Thu Aug 06 09:52:59 2009 -0400 @@ -84,7 +84,7 @@ <div style="clear: both"></div> </div> %endfor - <div class="toolFormTitle">Sample fields (${len(form.fields)})</div> + <div class="toolFormTitle">Fields (${len(form.fields)})</div> %for ctr, field in enumerate(field_details): ${render_field( ctr, field )} %endfor diff -r 11a2d159e280 -r 24ccfa887fcd templates/admin/forms/manage_forms.mako --- a/templates/admin/forms/manage_forms.mako Wed Aug 05 12:59:24 2009 -0400 +++ b/templates/admin/forms/manage_forms.mako Thu Aug 06 09:52:59 2009 -0400 @@ -3,6 +3,10 @@ <%def name="title()">Manage Form Definitions</%def> + +%if msg: + ${render_msg( msg, messagetype )} +%endif ## Render a row <%def name="render_row( form, ctr )"> @@ -12,11 +16,18 @@ <tr> %endif <td> - <b><a href="${h.url_for( controller='forms', action='edit', form_id=form.id, read_only=True )}">${form.name}</a></b> + <a href="${h.url_for( controller='forms', action='edit', form_id=form.id, read_only=True )}">${form.name}</a> <a id="form-${form.id}-popup" class="popup-arrow" style="display: none;">▼</a> - <div popupmenu="form-${form.id}-popup"> - <a class="action-button" href="${h.url_for( action='edit', form_id=form.id, show_form=True )}">Edit form definition</a> - </div> + %if form.form_definition_current.deleted: + <div popupmenu="form-${form.id}-popup"> + <a class="action-button" href="${h.url_for( action='undelete', form_id=form.id )}">Undelete</a> + </div> + %else: + <div popupmenu="form-${form.id}-popup"> + <a class="action-button" href="${h.url_for( action='edit', form_id=form.id, show_form=True )}">Edit form definition</a> + <a class="action-button" confirm="Click OK to delete the form ${form.name}." href="${h.url_for( action='delete', form_id=form.id )}">Delete</a> + </div> + %endif </td> <td><i>${form.desc}</i></td> </tr> @@ -24,36 +35,33 @@ <h2> - %if deleted: - Deleted - %endif Forms </h2> - - <ul class="manage-table-actions"> - %if not deleted: - <li> - <a class="action-button" href="${h.url_for( controller='forms', action='new', new=True )}"> - <img src="${h.url_for('/static/images/silk/add.png')}" /> - <span>Define a new form</span></a> - </li> - %endif + <li> + <a class="action-button" href="${h.url_for( controller='forms', action='new', new=True )}"> + <img src="${h.url_for('/static/images/silk/add.png')}" /> + <span>Define a new form</span></a> + </li> </ul> - -%if msg: - ${render_msg( msg, messagetype )} -%endif - +<div class="grid-header"> + ##<span class="title">Filter:</span> + %for i, filter in enumerate( ['Active', 'Deleted', 'All'] ): + %if i > 0: + <span>|</span> + %endif + %if show_filter == filter: + <span class="filter"><a href="${h.url_for( controller='forms', action='manage', show_filter=filter )}"><b>${filter}</b></a></span> + %else: + <span class="filter"><a href="${h.url_for( controller='forms', action='manage', show_filter=filter )}">${filter}</a></span> + %endif + %endfor +</div> %if not fdc_list: - %if deleted: - There are no deleted forms - %else: - There are no forms. - %endif + There are no forms. %else: <table class="grid"> <thead> @@ -70,4 +78,4 @@ %endfor </tbody> </table> -%endif +%endif \ No newline at end of file diff -r 11a2d159e280 -r 24ccfa887fcd templates/admin/requests/grid.mako --- a/templates/admin/requests/grid.mako Wed Aug 05 12:59:24 2009 -0400 +++ b/templates/admin/requests/grid.mako Thu Aug 06 09:52:59 2009 -0400 @@ -76,15 +76,27 @@ <div class="grid-header"> <h2>${grid.title}</h2> -## %if len(query.all()): -## <span class="title">Filter:</span> -## %for i, filter in enumerate( grid.standard_filters ): -## %if i > 0: -## <span>|</span> -## %endif -## <span class="filter"><a href="${url( filter.get_url_args() )}">${filter.label}</a></span> -## %endfor -## %endif + ##%if len(query.all()): + ##<span class="title">Filter:</span> + %for i, filter in enumerate( grid.standard_filters ): + %if i > 0: + <span>|</span> + %endif + %if 'state' in grid.default_filter: + %if grid.default_filter['state'] == filter.label: + <span class="filter"><a href="${h.url_for( controller='requests_admin', action='list', show_filter=filter.label )}"><b>${filter.label}</b></a></span> + %else: + <span class="filter"><a href="${h.url_for( controller='requests_admin', action='list', show_filter=filter.label )}">${filter.label}</a></span> + %endif + %else: + %if filter.label == 'All': + <span class="filter"><a href="${h.url_for( controller='requests_admin', action='list', show_filter=filter.label )}"><b>${filter.label}</b></a></span> + %else: + <span class="filter"><a href="${h.url_for( controller='requests_admin', action='list', show_filter=filter.label )}">${filter.label}</a></span> + %endif + %endif + %endfor + ##%endif </div> @@ -95,7 +107,7 @@ <table class="grid"> <thead> <tr> - <th></th> + ##<th></th> %for column in grid.columns: %if column.visible: <% @@ -137,9 +149,9 @@ %endif > ## Item selection column - <td style="width: 1.5em;"> - <input type="checkbox" name="id" value=${trans.security.encode_id( item.id )} class="grid-row-select-checkbox" /> - </td> + ##<td style="width: 1.5em;"> + ## <input type="checkbox" name="id" value=${trans.security.encode_id( item.id )} class="grid-row-select-checkbox" /> + ##</td> ## Data columns %for column in grid.columns: %if column.visible: diff -r 11a2d159e280 -r 24ccfa887fcd templates/admin/requests/manage_request_types.mako --- a/templates/admin/requests/manage_request_types.mako Wed Aug 05 12:59:24 2009 -0400 +++ b/templates/admin/requests/manage_request_types.mako Thu Aug 06 09:52:59 2009 -0400 @@ -3,10 +3,11 @@ <%def name="title()">request Types</%def> +%if msg: + ${render_msg( msg, messagetype )} +%endif + <h2> - %if deleted: - Deleted - %endif Request Types </h2> @@ -16,16 +17,21 @@ </li> </ul> -%if msg: - ${render_msg( msg, messagetype )} -%endif - +<div class="grid-header"> + ##<span class="title">Filter:</span> + %for i, filter in enumerate( ['Active', 'Deleted', 'All'] ): + %if i > 0: + <span>|</span> + %endif + %if show_filter == filter: + <span class="filter"><a href="${h.url_for( controller='admin', action='manage_request_types', show_filter=filter )}"><b>${filter}</b></a></span> + %else: + <span class="filter"><a href="${h.url_for( controller='admin', action='manage_request_types', show_filter=filter )}">${filter}</a></span> + %endif + %endfor +</div> %if not request_types: - %if deleted: - There are no deleted request types - %else: - There are no request types. - %endif + There are no request types. %else: <table class="grid"> <thead> @@ -39,7 +45,19 @@ <tbody> %for request_type in request_types: <tr> - <td><b><a href="${h.url_for( controller='admin', action='request_type', edit='True', id=request_type.id)}">${request_type.name}</a></b></td> + <td> + <a href="${h.url_for( controller='admin', action='request_type', edit='True', id=request_type.id)}">${request_type.name}</a> + <a id="request_type-${request_type.id}-popup" class="popup-arrow" style="display: none;">▼</a> + %if request_type.deleted: + <div popupmenu="request_type-${request_type.id}-popup"> + <a class="action-button" href="${h.url_for( action='undelete_request_type', request_type_id=request_type.id )}">Undelete</a> + </div> + %else: + <div popupmenu="request_type-${request_type.id}-popup"> + <a class="action-button" confirm="Click OK to delete the request type ${request_type.name}." href="${h.url_for( action='delete_request_type', request_type_id=request_type.id )}">Delete</a> + </div> + %endif + </td> <td><i>${request_type.desc}</i></td> <td><a href="${h.url_for( controller='forms', action='edit', form_id=request_type.request_form.id, read_only=True)}">${request_type.request_form.name}</a></td> <td><a href="${h.url_for( controller='forms', action='edit', form_id=request_type.sample_form.id, read_only=True)}">${request_type.sample_form.name}</a></td> diff -r 11a2d159e280 -r 24ccfa887fcd templates/admin/samples/bar_codes.mako --- a/templates/admin/samples/bar_codes.mako Wed Aug 05 12:59:24 2009 -0400 +++ b/templates/admin/samples/bar_codes.mako Thu Aug 06 09:52:59 2009 -0400 @@ -1,12 +1,14 @@ <%inherit file="/base.mako"/> <%namespace file="/message.mako" import="render_msg" /> -<h2>Bar codes for Samples of Request "${request.name}"</h2> -<h3>User: ${user.email}</h3> %if msg: ${render_msg( msg, messagetype )} %endif + + +<h2>Bar codes for Samples of Request "${request.name}"</h2> +<h3>User: ${user.email}</h3> <ul class="manage-table-actions"> <li> @@ -31,7 +33,7 @@ <td><b><a>${sample.name}</a></b></td> <td><a>${sample.desc}</a></td> <td> - <input type="text" name="sample_${index}_bar_code" value=${sample.bar_code} size="40"/> + ${widgets[index].get_html()} </td> </tr> %endfor diff -r 11a2d159e280 -r 24ccfa887fcd templates/requests/edit_request.mako --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/templates/requests/edit_request.mako Thu Aug 06 09:52:59 2009 -0400 @@ -0,0 +1,84 @@ +<%inherit file="/base.mako"/> +<%namespace file="/message.mako" import="render_msg" /> + +%if msg: + ${render_msg( msg, messagetype )} +%endif + +<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_request" ).submit(); + } + }); +}); +</script> + +<br/> +<br/> +<ul class="manage-table-actions"> + <li> + <a class="action-button" href="${h.url_for( controller='requests', action='list')}"> + <span>Browse requests</span></a> + </li> +</ul> + +<div class="toolForm"> + <div class="toolFormTitle">Edit request "${request.name}"</div> + %if len(select_request_type.options) == 1: + There are no request types created for a new request. + %else: + <div class="toolFormBody"> + <form name="edit_request" id="edit_request" action="${h.url_for( controller='requests', action='edit', request_id=request.id)}" method="post" > + <div class="form-row"> + <label> + Select Request Type: + </label> + ${select_request_type.get_html()} + </div> + + %if select_request_type.get_selected() != ('Select one', 'none'): + %for i, field in enumerate(widgets): + <div class="form-row"> + <label>${field['label']}</label> + ${field['widget'].get_html()} + %if field['label'] == 'Library' and new_library: + ${new_library.get_html()} + %endif + <div class="toolParamHelp" style="clear: both;"> + ${field['helptext']} + </div> + <div style="clear: both"></div> + </div> + %endfor + <div class="form-row"> + <div style="float: left; width: 250px; margin-right: 10px;"> + <input type="hidden" name="refresh" value="true" size="40"/> + </div> + <div style="clear: both"></div> + </div> + <div class="form-row"> + <input type="submit" name="save_changes_request_button" value="Save changes"/> + ##<input type="submit" name="edit_samples_button" value="Edit samples"/> + </div> + %endif + </form> + </div> +</div> +%endif \ No newline at end of file diff -r 11a2d159e280 -r 24ccfa887fcd templates/requests/grid.mako --- a/templates/requests/grid.mako Wed Aug 05 12:59:24 2009 -0400 +++ b/templates/requests/grid.mako Thu Aug 06 09:52:59 2009 -0400 @@ -76,15 +76,19 @@ <div class="grid-header"> <h2>${grid.title}</h2> -## %if len(query.all()): -## <span class="title">Filter:</span> -## %for i, filter in enumerate( grid.standard_filters ): -## %if i > 0: -## <span>|</span> -## %endif -## <span class="filter"><a href="${url( filter.get_url_args() )}">${filter.label}</a></span> -## %endfor -## %endif + ##%if len(query.all()): + ##<span class="title">Filter:</span> + %for i, filter in enumerate( grid.standard_filters ): + %if i > 0: + <span>|</span> + %endif + %if grid.show_filter == filter.label: + <span class="filter"><a href="${h.url_for( controller='requests', action='list', show_filter=filter.label )}"><b>${filter.label}</b></a></span> + %else: + <span class="filter"><a href="${h.url_for( controller='requests', action='list', show_filter=filter.label )}">${filter.label}</a></span> + %endif + %endfor + ##%endif </div> <ul class="manage-table-actions"> @@ -103,7 +107,7 @@ <table class="grid"> <thead> <tr> - <th></th> + ##<th></th> %for column in grid.columns: %if column.visible: <% @@ -145,9 +149,9 @@ %endif > ## Item selection column - <td style="width: 1.5em;"> - <input type="checkbox" name="id" value=${trans.security.encode_id( item.id )} class="grid-row-select-checkbox" /> - </td> + ##<td style="width: 1.5em;"> + ## <input type="checkbox" name="id" value=${trans.security.encode_id( item.id )} class="grid-row-select-checkbox" /> + ##</td> ## Data columns %for column in grid.columns: %if column.visible: @@ -196,7 +200,7 @@ </tr> %endfor </tbody> -## <tfoot> + <tfoot> ## <tr> ## <td></td> ## <td colspan="100"> @@ -208,7 +212,7 @@ ## %endfor ## </td> ## </tr> -## </tfoot> + </tfoot> </table> </form> %endif \ No newline at end of file diff -r 11a2d159e280 -r 24ccfa887fcd templates/requests/new_request.mako --- a/templates/requests/new_request.mako Wed Aug 05 12:59:24 2009 -0400 +++ b/templates/requests/new_request.mako Thu Aug 06 09:52:59 2009 -0400 @@ -1,10 +1,35 @@ <%inherit file="/base.mako"/> <%namespace file="/message.mako" import="render_msg" /> - %if msg: ${render_msg( msg, messagetype )} %endif + +<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 ){ + $( "#new_request" ).submit(); + } + }); +}); +</script> + <br/> <br/> <ul class="manage-table-actions"> @@ -15,32 +40,45 @@ </ul> <div class="toolForm"> - <div class="toolFormTitle">${title}</div> - <div class="toolFormBody"> - <form id="new_request" name="new_request" action="${h.url_for( controller='requests', action='new', save=True, request_form_id=request_form_id, request_type_id=request_type.id )}" method="post" > - %for i, field in enumerate(widgets): + <div class="toolFormTitle">Add a new request</div> + %if len(select_request_type.options) == 1: + There are no request types created for a new request. + %else: + <div class="toolFormBody"> + <form name="new_request" id="new_request" action="${h.url_for( controller='requests', action='new', create=True )}" method="post" > <div class="form-row"> - <label>${field['label']}</label> - ${field['widget'].get_html()} - %if field['label'] == 'Library' and new_library: - ${new_library.get_html()} - %endif - <div class="toolParamHelp" style="clear: both;"> - ${field['helptext']} + <label> + Select Request Type: + </label> + ${select_request_type.get_html()} + </div> + + %if select_request_type.get_selected() != ('Select one', 'none'): + %for i, field in enumerate(widgets): + <div class="form-row"> + <label>${field['label']}</label> + ${field['widget'].get_html()} + %if field['label'] == 'Library' and new_library: + ${new_library.get_html()} + %endif + <div class="toolParamHelp" style="clear: both;"> + ${field['helptext']} + </div> + <div style="clear: both"></div> + </div> + %endfor + <div class="form-row"> + <div style="float: left; width: 250px; margin-right: 10px;"> + <input type="hidden" name="refresh" value="true" size="40"/> + </div> + <div style="clear: both"></div> </div> - <div style="clear: both"></div> - </div> - %endfor - <div class="form-row"> - <div style="float: left; width: 250px; margin-right: 10px;"> - <input type="hidden" name="new" value="submitted" size="40"/> - </div> - <div style="clear: both"></div> - </div> - <div class="form-row"> - <input type="submit" name="create_request_button" value="Save"/> - <input type="submit" name="create_request_samples_button" value="Add samples"/> - </div> + <div class="form-row"> + <input type="submit" name="create_request_button" value="Save"/> + <input type="submit" name="create_request_samples_button" value="Add samples"/> + </div> + %endif </form> </div> -</div> \ No newline at end of file +</div> +%endif \ No newline at end of file diff -r 11a2d159e280 -r 24ccfa887fcd templates/requests/select_request_type.mako --- a/templates/requests/select_request_type.mako Wed Aug 05 12:59:24 2009 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -<%inherit file="/base.mako"/> -<%namespace file="/message.mako" import="render_msg" /> - - -%if msg: - ${render_msg( msg, messagetype )} -%endif -<br/> -<br/> -<ul class="manage-table-actions"> - <li> - <a class="action-button" href="${h.url_for( controller='requests', action='list')}"> - <span>Browse requests</span></a> - </li> -</ul> - -<div class="toolForm"> - <div class="toolFormTitle">Add a new request</div> - %if not request_types: - There are no request types created for a new request. - %else: - <div class="toolFormBody"> - <form name="select_request_type" action="${h.url_for( controller='requests', action='new', create=True )}" method="post" > - <div class="form-row"> - <label> - Select Request Type: - </label> - <select name="request_type_id"> - %for rt in request_types: - <option value="${rt.id}">${rt.name}</option> - %endfor - </select> - <input type="submit" name="create_request" value="Go"/> - </div> - </form> - </div> - %endif -</div> diff -r 11a2d159e280 -r 24ccfa887fcd templates/requests/show_request.mako --- a/templates/requests/show_request.mako Wed Aug 05 12:59:24 2009 -0400 +++ b/templates/requests/show_request.mako Thu Aug 06 09:52:59 2009 -0400 @@ -13,7 +13,7 @@ <ul class="manage-table-actions"> - %if not request.submitted and request.samples: + %if request.unsubmitted() and request.samples: <li> <a class="action-button" confirm="More samples cannot be added to this request once it is submitted. Click OK to submit." href="${h.url_for( controller='requests', action='submit_request', id=request.id)}"> <span>Submit request</span></a> @@ -29,7 +29,7 @@ <%def name="render_sample_form( index, sample_name, sample_values )"> <td> - <input type="text" name=sample_${index}_name value="${sample_name}" size="15"/> + <input type="text" name=sample_${index}_name value="${sample_name}" size="10"/> <div class="toolParamHelp" style="clear: both;"> <i>${' (required)' }</i> </div> @@ -38,7 +38,7 @@ </td> %for field_index, field in enumerate(request.type.sample_form.fields): <td> - <input type="text" name=sample_${index}_field_${field_index} value="${sample_values[field_index]}" size="15"/> + <input type="text" name=sample_${index}_field_${field_index} value="${sample_values[field_index]}" size="7"/> <div class="toolParamHelp" style="clear: both;"> <i>${'('+field['required']+')' }</i> </div> @@ -51,7 +51,11 @@ ${sample.name} </td> <td> - <a href="${h.url_for( controller='requests', action='show_events', sample_id=sample.id)}">${sample.current_state().name}</a> + %if sample.request.unsubmitted(): + Unsubmitted + %else: + <a href="${h.url_for( controller='requests', action='show_events', sample_id=sample.id)}">${sample.current_state().name}</a> + %endif </td> %for field_index, field in enumerate(request.type.sample_form.fields): <td> @@ -77,7 +81,11 @@ <i>None</i> %else: %if rd['label'] == 'Library': - <a href="${h.url_for( controller='library', action='browse_library', id=request.library.id )}">${rd['value']}</a> + %if rd['value']: + <a href="${h.url_for( controller='library', action='browse_library', id=request.library.id )}">${rd['value']}</a> + %else: + <i>None</i> + %endif %else: ${rd['value']} %endif @@ -85,13 +93,23 @@ </div> <div style="clear: both"></div> %endfor + %if request.unsubmitted(): + <div class="form-row"> + <ul class="manage-table-actions"> + <li> + <a class="action-button" href="${h.url_for( controller='requests', action='edit', show=True, request_id=request.id)}"> + <span>Edit request details</span></a> + </li> + </ul> + </div> + %endif %endif </div> </div> <div class="toolForm"> ##<div class="toolFormTitle">Samples (${len(request.samples)})</div> - <form id="edit_form" name="edit_form" action="${h.url_for( controller='requests', action='show_request', request_id=request.id )}" method="post" > + <form id="edit_form" name="edit_form" action="${h.url_for( controller='requests', action='show_request' )}" method="post" > <div class="form-row"> %if current_samples: <table class="grid"> @@ -116,46 +134,77 @@ request.refresh() %> %for sample_index, sample in enumerate(current_samples): - <tr> - <td>${sample_index+1}</td> - %if sample_index in range(len(request.samples)): - ${render_sample( sample_index, request.samples[sample_index] )} - %else: + %if edit_mode: + <tr> + <td>${sample_index+1}</td> ${render_sample_form( sample_index, sample[0], sample[1])} - %endif - <td> - %if not request.submitted: - <a class="action-button" href="${h.url_for( controller='requests', action='delete_sample', request_id=request.id, sample_id=sample_index)}"> - <img src="${h.url_for('/static/images/delete_icon.png')}" /> - <span></span></a> + <td> + %if request.unsubmitted(): + <a class="action-button" href="${h.url_for( controller='requests', action='delete_sample', request_id=request.id, sample_id=sample_index)}"> + <img src="${h.url_for('/static/images/delete_icon.png')}" /> + <span></span></a> + %endif + </td> + </tr> + %else: + <tr> + <td>${sample_index+1}</td> + %if sample_index in range(len(request.samples)): + ${render_sample( sample_index, request.samples[sample_index] )} + %else: + ${render_sample_form( sample_index, sample[0], sample[1])} %endif - </td> - </tr> + <td> + %if request.unsubmitted(): + <a class="action-button" href="${h.url_for( controller='requests', action='delete_sample', request_id=request.id, sample_id=sample_index)}"> + <img src="${h.url_for('/static/images/delete_icon.png')}" /> + <span></span></a> + %endif + </td> + </tr> + %endif %endfor </tbody> </table> %else: - <label>There are no samples.</label> + <div class="form-row"> + <label>There are no samples.</label> + </div> %endif </div> - %if not request.submitted: - <br/> - <br/> - <div class="form-row"> - <ul class="manage-table-actions"> - <li> - %if current_samples: - <a>Copy from sample no. </a> - ${sample_copy.get_html()} - %endif - <input type="submit" name="add_sample_button" value="Add New"/> - - </li> - </ul> - </div> + %if request.unsubmitted() and not edit_mode: + <table class="grid"> + <tbody> + <tr> + <div class="form-row"> + <td> + %if current_samples: + <input type="submit" name="edit_samples_button" value="Edit samples"/> + %endif + </td> + <td> + ##<div class="form-row"> + <label>Import from csv file</label> + <input type="text" name="import_samples" value="" size="20"/> + <input type="submit" name="import_samples_button" value="Import samples"/> + ##</div> + </td> + <td> + ##<div class="form-row"> + %if current_samples: + <label>Copy from sample</label> + ${sample_copy.get_html()} + %endif + <input type="submit" name="add_sample_button" value="Add New"/> + ##</div> + </td> + </div> + </tr> + </tbody> + </table> %endif - %if not request.submitted and (request.samples or current_samples): + %if request.unsubmitted() and (request.samples or current_samples): <div class="form-row"> <div style="float: left; width: 250px; margin-right: 10px;"> <input type="hidden" name="refresh" value="true" size="40"/> @@ -164,8 +213,12 @@ </div> <div class="form-row"> <input type="submit" name="save_samples_button" value="Save"/> + %if edit_mode: + <input type="submit" name="cancel_changes_button" value="Cancel"/> + %endif </div> %endif ##</div> + <input type="hidden" name="request_id" value="${request.id}" /> </form> </div> diff -r 11a2d159e280 -r 24ccfa887fcd templates/user/address.mako --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/templates/user/address.mako Thu Aug 06 09:52:59 2009 -0400 @@ -0,0 +1,83 @@ +<%inherit file="/base.mako"/> +<%namespace file="/message.mako" import="render_msg" /> + + +%if msg: + ${render_msg( msg, messagetype )} +%endif + +<h2>Manage Addresses</h2> +<ul class="manage-table-actions"> + <li> + <a class="action-button" href="${h.url_for( controller='user', action='new_address')}"> + <span>Add a new address</span></a> + <a class="action-button" href="${h.url_for( controller='user', action='index')}"> + <span>User preferences</span></a> + </li> +</ul> +%if not trans.user.addresses: + There are no addresses +%else: +<div class="grid-header"> + ##<span class="title">Filter:</span> + %for i, filter in enumerate( ['Active', 'Deleted', 'All'] ): + %if i > 0: + <span>|</span> + %endif + %if show_filter == filter: + <span class="filter"><a href="${h.url_for( controller='user', action='manage_addresses', show_filter=filter )}"><b>${filter}</b></a></span> + %else: + <span class="filter"><a href="${h.url_for( controller='user', action='manage_addresses', show_filter=filter )}">${filter}</a></span> + %endif + %endfor +</div> + + + +<div class="toolForm"> + ##<div class="toolFormTitle">Addresses</div> + <div class="toolFormBody"> + <% trans.user.refresh() %> + %if not trans.user.addresses: + <label>There are no addresses</label> + %else: + <table class="grid"> + <tbody> + %for index, address in enumerate(addresses): + <tr class="libraryRow libraryOrFolderRow" id="libraryRow"> + + <td> + <div class="form-row"> + <label>${address.desc}</label> + ${address.display()} + </div> + <div class="form-row"> + <ul class="manage-table-actions"> + <li> + %if not address.deleted: + <a class="action-button" href="${h.url_for( controller='user', action='edit_address', address_id=address.id, + short_desc=address.desc, + name=address.name, institution=address.institution, + address1=address.address, city=address.city, + state=address.state, postal_code=address.postal_code, + country=address.country, phone=address.phone)}"> + <span>Edit</span></a> + <a class="action-button" href="${h.url_for( controller='user', action='delete_address', address_id=address.id)}"> + <span>Delete address</span></a> + %else: + <a class="action-button" href="${h.url_for( controller='user', action='undelete_address', address_id=address.id)}"> + <span>Undelete address</span></a> + %endif + + </li> + </ul> + </div> + </td> + </tr> + %endfor + </tbody> + </table> + %endif + </div> +</div> +%endif \ No newline at end of file diff -r 11a2d159e280 -r 24ccfa887fcd templates/user/index.mako --- a/templates/user/index.mako Wed Aug 05 12:59:24 2009 -0400 +++ b/templates/user/index.mako Thu Aug 06 09:52:59 2009 -0400 @@ -1,5 +1,6 @@ <%inherit file="/base.mako"/> <%def name="title()">User preferences</%def> + <h2>${_('User preferences')}</h2> @@ -9,6 +10,7 @@ <li><a href="${h.url_for( action='change_password' )}">${_('Change your password')}</a></li> <li><a href="${h.url_for( action='change_email' )}">${_('Update your email address')}</a></li> <li><a href="${h.url_for( action='set_default_permissions' )}">${_('Change default permissions')}</a> for new histories</li> + <li><a href="${h.url_for( action='manage_addresses' )}">${_('Manage your addresses')}</a></li> <li><a href="${h.url_for( action='logout' )}">${_('Logout')}</a></li> </ul> %else:
participants (1)
-
Greg Von Kuster