details: http://www.bx.psu.edu/hg/galaxy/rev/b46f27137744 changeset: 2471:b46f27137744 user: rc date: Fri Jul 10 11:37:28 2009 -0400 description: First pass of the new Galaxy forms components including requests which based on form definitions and samples. 40 file(s) affected in this change: lib/galaxy/model/__init__.py lib/galaxy/model/mapping.py lib/galaxy/model/migrate/versions/0008_galaxy_forms.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/form_builder.py lib/galaxy/web/framework/__init__.py run_functional_tests.sh templates/admin/forms/create_form.mako templates/admin/forms/edit_form.mako templates/admin/forms/manage_forms.mako templates/admin/forms/show_form_read_only.mako templates/admin/index.mako templates/admin/requests/add_states.mako templates/admin/requests/create_request_type.mako templates/admin/requests/edit_request_type.mako templates/admin/requests/grid.mako templates/admin/requests/manage_request_types.mako templates/admin/requests/view_request.mako templates/admin/samples/change_state.mako templates/admin/samples/edit_sample.mako templates/admin/samples/events.mako templates/admin/samples/grid.mako templates/admin/samples/view_sample.mako templates/base.mako templates/base_panels.mako templates/requests/grid.mako templates/requests/index.mako templates/requests/new_request.mako templates/requests/select_request_type.mako templates/requests/view_request.mako templates/sample/browse_samples.mako templates/sample/edit_sample.mako templates/sample/grid.mako templates/sample/index.mako templates/sample/new_sample.mako templates/sample/sample_events.mako templates/sample/view_sample.mako diffs (truncated from 3714 to 3000 lines): diff -r 267db48a2371 -r b46f27137744 lib/galaxy/model/__init__.py --- a/lib/galaxy/model/__init__.py Thu Jul 09 15:49:26 2009 -0400 +++ b/lib/galaxy/model/__init__.py Fri Jul 10 11:37:28 2009 -0400 @@ -14,6 +14,7 @@ import galaxy.datatypes.registry from galaxy.datatypes.metadata import MetadataCollection from galaxy.security import RBACAgent, get_permitted_actions + import logging log = logging.getLogger( __name__ ) @@ -1095,6 +1096,58 @@ raise # Return filename inside hashed directory return os.path.abspath( os.path.join( path, "metadata_%d.dat" % self.id ) ) + + +class FormDefinition( object ): + def __init__(self, name=None, desc=None, fields=[], current_form_id=None): + self.name = name + self.desc = desc + self.fields = fields + self.form_definition_current_id = current_form_id + +class FormDefinitionCurrent( object ): + def __init__(self, form_definition_id=None): + self.latest_form_id = form_definition_id + +class FormValues( object ): + def __init__(self, form_def_id=None, content=None): + self.form_definition_id = form_def_id + self.content = content + +class Request( object ): + def __init__(self, name=None, desc=None, request_type_id=None, user_id=None, form_values_id=None, library_id=None): + self.name = name + self.desc = desc + self.request_type_id = request_type_id + self.form_values_id = form_values_id + self.user_id = user_id + self.library_id = library_id + +class RequestType( object ): + def __init__(self, request_form_id=None, sample_form_id=None): + self.request_form_id = request_form_id + self.sample_form_id = sample_form_id + +class Sample( object ): + def __init__(self, name=None, desc=None, request_id=None, form_values_id=None): + self.name = name + self.desc = desc + self.request_id = request_id + self.form_values_id = form_values_id + +class SampleState( object ): + def __init__(self, name=None, desc=None, request_type_id=None): + self.name = name + self.desc = desc + self.request_type_id = request_type_id + +class SampleEvent( object ): + def __init__(self, sample_id=None, sample_state_id=None, comment=''): + self.sample_id = sample_id + self.sample_state_id = sample_state_id + self.comment = comment + + ## ---- Utility methods ------------------------------------------------------- diff -r 267db48a2371 -r b46f27137744 lib/galaxy/model/mapping.py --- a/lib/galaxy/model/mapping.py Thu Jul 09 15:49:26 2009 -0400 +++ b/lib/galaxy/model/mapping.py Fri Jul 10 11:37:28 2009 -0400 @@ -520,8 +520,114 @@ Column( "deleted", Boolean, index=True, default=False ), Column( "purged", Boolean, index=True, default=False ) ) + +FormDefinitionCurrent.table = Table('form_definition_current', metadata, + Column( "id", Integer, primary_key=True), + Column( "create_time", DateTime, default=now ), + Column( "update_time", DateTime, default=now, onupdate=now ), + Column( "latest_form_id", Integer, ForeignKey( "form_definition.id" ), index=True ), + Column( "deleted", Boolean, index=True, default=False )) + +# new table to store all the forms which is created by the admin +FormDefinition.table = Table('form_definition', 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 ), + Column( "form_definition_current_id", Integer, ForeignKey( "form_definition_current.id" ), index=True ), + Column( "fields", JSONType())) + +RequestType.table = Table('request_type', 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 ), + Column( "request_form_id", Integer, ForeignKey( "form_definition.id" ), index=True ), + Column( "sample_form_id", Integer, ForeignKey( "form_definition.id" ), index=True ) ) + +FormValues.table = Table('form_values', metadata, + Column( "id", Integer, primary_key=True), + Column( "create_time", DateTime, default=now ), + Column( "update_time", DateTime, default=now, onupdate=now ), + Column( "form_definition_id", Integer, ForeignKey( "form_definition.id" ), index=True ), + Column( "content", JSONType()) ) + +Request.table = Table('request', 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 ), + Column( "form_values_id", Integer, ForeignKey( "form_values.id" ), index=True ), + 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( "deleted", Boolean, index=True, default=False ) ) + +Sample.table = Table('sample', 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 ), + Column( "form_values_id", Integer, ForeignKey( "form_values.id" ), index=True ), + Column( "request_id", Integer, ForeignKey( "request.id" ), index=True ), + Column( "deleted", Boolean, index=True, default=False ) ) + +# new table to store all the possible sample states and the sample type it +# belongs to +SampleState.table = Table('sample_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 ), + Column( "request_type_id", Integer, ForeignKey( "request_type.id" ), index=True ) ) + +SampleEvent.table = Table('sample_event', metadata, + Column( "id", Integer, primary_key=True), + Column( "create_time", DateTime, default=now ), + Column( "update_time", DateTime, default=now, onupdate=now ), + Column( "sample_id", Integer, ForeignKey( "sample.id" ), index=True ), + Column( "sample_state_id", Integer, ForeignKey( "sample_state.id" ), index=True ), + Column( "comment", TEXT ) ) + + + # With the tables defined we can define the mappers and setup the # 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) ), + ) ) + +assign_mapper( context, FormValues, FormValues.table, properties=None) + +assign_mapper( context, Request, Request.table, properties=None) + +assign_mapper( context, RequestType, RequestType.table, + properties=dict( states=relation( SampleState, backref="request_type", + order_by=desc(SampleState.table.c.update_time) ), + ) ) + +assign_mapper( context, FormDefinition, FormDefinition.table, properties=None) + +assign_mapper( context, FormDefinitionCurrent, FormDefinitionCurrent.table, + properties=dict( forms=relation( FormDefinition, backref='form_definition_current', + cascade="all, delete-orphan", + primaryjoin=( FormDefinitionCurrent.table.c.id == FormDefinition.table.c.form_definition_current_id ) ), + latest_form=relation( FormDefinition, post_update=True, + primaryjoin=( FormDefinitionCurrent.table.c.latest_form_id == FormDefinition.table.c.id ) ) + ) ) + +assign_mapper( context, SampleEvent, SampleEvent.table, properties=None) + +assign_mapper( context, SampleState, SampleState.table, + properties=None #dict( sample=relation( Sample, backref="sample" ), + )# ) assign_mapper( context, ValidationError, ValidationError.table ) @@ -590,6 +696,8 @@ assign_mapper( context, User, User.table, properties=dict( histories=relation( History, backref="user", order_by=desc(History.table.c.update_time) ), + requests=relation( Request, backref="user", + order_by=desc(Request.table.c.update_time) ), active_histories=relation( History, primaryjoin=( ( History.table.c.user_id == User.table.c.id ) & ( not_( History.table.c.deleted ) ) ), order_by=desc( History.table.c.update_time ) ), galaxy_sessions=relation( GalaxySession, order_by=desc( GalaxySession.table.c.update_time ) ), stored_workflow_menu_entries=relation( StoredWorkflowMenuEntry, backref="user", diff -r 267db48a2371 -r b46f27137744 lib/galaxy/model/migrate/versions/0008_galaxy_forms.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/galaxy/model/migrate/versions/0008_galaxy_forms.py Fri Jul 10 11:37:28 2009 -0400 @@ -0,0 +1,189 @@ +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 ) ) + + +FormDefinitionCurrent_table = Table('form_definition_current', metadata, + Column( "id", Integer, primary_key=True), + Column( "create_time", DateTime, default=now ), + Column( "update_time", DateTime, default=now, onupdate=now ), + Column( "latest_form_id", Integer, + #ForeignKey( "form_definition.id", use_alter=True, name='form_definition_current_latest_form_id_fk'), + index=True ), + Column( "deleted", Boolean, index=True, default=False )) +FormDefinition_table = Table('form_definition', 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 ), + Column( "form_definition_current_id", Integer, ForeignKey( "form_definition_current.id" ), index=True, nullable=False ), + Column( "fields", JSONType()) ) + +FormValues_table = Table('form_values', metadata, + Column( "id", Integer, primary_key=True), + Column( "create_time", DateTime, default=now ), + Column( "update_time", DateTime, default=now, onupdate=now ), + Column( "form_definition_id", Integer, ForeignKey( "form_definition.id" ), index=True ), + Column( "content", JSONType()) ) + +RequestType_table = Table('request_type', 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 ), + Column( "request_form_id", Integer, ForeignKey( "form_definition.id" ), index=True ), + Column( "sample_form_id", Integer, ForeignKey( "form_definition.id" ), index=True ) ) +# request table +Request_table = Table('request', 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 ), + Column( "form_values_id", Integer, ForeignKey( "form_values.id" ), index=True ), + 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( "deleted", Boolean, index=True, default=False ) ) + +Sample_table = Table('sample', 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 ), + Column( "form_values_id", Integer, ForeignKey( "form_values.id" ), index=True ), + Column( "request_id", Integer, ForeignKey( "request.id" ), index=True ), + Column( "deleted", Boolean, index=True, default=False ) ) + +SampleState_table = Table('sample_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 ), + Column( "request_type_id", Integer, ForeignKey( "request_type.id" ), index=True ) ) + +SampleEvent_table = Table('sample_event', metadata, + Column( "id", Integer, primary_key=True), + Column( "create_time", DateTime, default=now ), + Column( "update_time", DateTime, default=now, onupdate=now ), + Column( "sample_id", Integer, ForeignKey( "sample.id" ), index=True ), + Column( "sample_state_id", Integer, ForeignKey( "sample_state.id" ), index=True ), + Column( "comment", TEXT ) ) + + + + +def upgrade(): + # Load existing tables + metadata.reflect() + + # Add all of the new tables above +# metadata.create_all() + try: + FormDefinitionCurrent_table.create() + except Exception, e: + log.debug( "Creating form_definition_current table failed: %s" % str( e ) ) + try: + FormDefinition_table.create() + except Exception, e: + log.debug( "Creating form_definition table failed: %s" % str( e ) ) + # Add 1 foreign key constraint to the form_definition_current table + if FormDefinitionCurrent_table and FormDefinition_table: + try: + cons = ForeignKeyConstraint( [FormDefinitionCurrent_table.c.latest_form_id], + [FormDefinition_table.c.id], + name='form_definition_current_latest_form_id_fk' ) + # Create the constraint + cons.create() + except Exception, e: + log.debug( "Adding foreign key constraint 'form_definition_current_latest_form_id_fk' to table 'form_definition_current' failed: %s" % ( str( e ) ) ) + try: + FormValues_table.create() + except Exception, e: + log.debug( "Creating form_values table failed: %s" % str( e ) ) + try: + RequestType_table.create() + except Exception, e: + log.debug( "Creating request_type table failed: %s" % str( e ) ) + try: + Request_table.create() + except Exception, e: + log.debug( "Creating request table failed: %s" % str( e ) ) + try: + Sample_table.create() + except Exception, e: + log.debug( "Creating sample table failed: %s" % str( e ) ) + try: + SampleState_table.create() + except Exception, e: + log.debug( "Creating sample_state table failed: %s" % str( e ) ) + try: + SampleEvent_table.create() + except Exception, e: + log.debug( "Creating sample_event table failed: %s" % str( e ) ) + + + +def downgrade(): + # Load existing tables + metadata.reflect() + try: + FormDefinition_table.drop() + except Exception, e: + log.debug( "Dropping form_definition table failed: %s" % str( e ) ) + try: + FormDefinitionCurrent_table.drop() + except Exception, e: + log.debug( "Dropping form_definition_current table failed: %s" % str( e ) ) + try: + FormValues_table.drop() + except Exception, e: + log.debug( "Dropping form_values table failed: %s" % str( e ) ) + try: + Request_table.drop() + except Exception, e: + log.debug( "Dropping request table failed: %s" % str( e ) ) + try: + RequestType_table.drop() + except Exception, e: + log.debug( "Dropping request_type table failed: %s" % str( e ) ) + try: + Sample_table.drop() + except Exception, e: + log.debug( "Dropping sample table failed: %s" % str( e ) ) + try: + SampleState_table.drop() + except Exception, e: + log.debug( "Dropping sample_state table failed: %s" % str( e ) ) + try: + SampleEvent_table.drop() + except Exception, e: + log.debug( "Dropping sample_event table failed: %s" % str( e ) ) + + + + diff -r 267db48a2371 -r b46f27137744 lib/galaxy/web/controllers/admin.py --- a/lib/galaxy/web/controllers/admin.py Thu Jul 09 15:49:26 2009 -0400 +++ b/lib/galaxy/web/controllers/admin.py Fri Jul 10 11:37:28 2009 -0400 @@ -3,6 +3,7 @@ from galaxy import util, datatypes from galaxy.web.base.controller import * from galaxy.model.orm import * +import sys import logging log = logging.getLogger( __name__ ) @@ -2097,4 +2098,123 @@ else: last_updated[job.id] = '%s minutes' % int( delta.seconds / 60 ) return trans.fill_template( '/admin/jobs.mako', jobs = jobs, last_updated = last_updated, cutoff = cutoff, msg = msg, messagetype = messagetype ) - + + def _get_all_forms(self, trans, all_versions=False): + ''' + This method returns all the latest forms from the + form_definition_current table if all_versions is set to True. Otherwise + this method return all the versions of all the forms from form_definition + table + ''' + if all_versions: + return trans.app.model.FormDefinition.query().all() + else: + fdc_list = trans.app.model.FormDefinitionCurrent.query().all() + return [fdc.latest_form for fdc in fdc_list] + @web.expose + @web.require_admin + def manage_request_types( self, trans, **kwd ): + params = util.Params( kwd ) + msg = util.restore_text( params.get( 'msg', '' ) ) + messagetype = params.get( 'messagetype', 'done' ) + forms = self._get_all_forms(trans, all_versions=True) + return trans.fill_template( '/admin/requests/manage_request_types.mako', + request_types=trans.app.model.RequestType.query().all(), + forms=forms, + deleted=False, + show_deleted=False, + msg=msg, + messagetype=messagetype ) + @web.expose + @web.require_admin + def request_type( self, trans, **kwd ): + params = util.Params( kwd ) + msg = util.restore_text( params.get( 'msg', '' ) ) + messagetype = params.get( 'messagetype', 'done' ) + if params.get('create', False) == 'True': + return trans.fill_template( '/admin/requests/create_request_type.mako', + forms=self._get_all_forms(trans, all_versions=False), + msg=msg, + messagetype=messagetype) + elif params.get('add_states', False) == 'True': + return trans.fill_template( '/admin/requests/add_states.mako', + sample_type_name=util.restore_text( params.name ), + desc=util.restore_text( params.description ), + num_states=int(util.restore_text( params.num_states )), + request_form_id=int(util.restore_text( params.request_form_id )), + sample_form_id=int(util.restore_text( params.sample_form_id )), + msg=msg, + messagetype=messagetype) + elif params.get('save_new', False) == 'True': + st, msg = self._save_request_type(trans, params, None) + if not st: + return trans.fill_template( '/admin/requests/create_request_type.mako', + 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 ) + 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() + return trans.fill_template( '/admin/requests/edit_request_type.mako', + request_type=rt, + forms=self._get_all_forms(trans, all_versions=False), + states_list=ss_list, + deleted=False, + show_deleted=False, + msg=msg, + messagetype=messagetype ) + elif params.get('save_changes', False) == 'True': + st = trans.app.model.SampleType.get(int(util.restore_text( params.id ))) + st, msg = self._save_sample_type(trans, params, st.id) + if st: + msg = "The sample type '%s' has been updated with the changes." % st.name + messagetype = 'done' + else: + messagetype = 'error' + ss_list = trans.app.model.SampleState.filter(trans.app.model.SampleState.table.c.sample_type_id == st.id).all() + return trans.fill_template( '/admin/samples/edit_sample_type.mako', + sample_type=st, + forms=self._get_all_forms(trans, all_versions=False), + states_list=ss_list, + deleted=False, + show_deleted=False, + msg=msg, + messagetype=messagetype ) + def _save_request_type(self, trans, params, request_type_id): + num_states = int( params.get( 'num_states', 0 ) ) + proceed = True + for i in range( num_states ): + if not params.get( 'new_element_name_%i' % i, None ): + proceed = False + break + if not proceed: + msg = "All the state name(s) must be completed." + return None, msg + if not request_type_id: # create a new sample type to save + rt = trans.app.model.RequestType() + else: # use the existing sample type to save changes + rt = trans.app.model.RequestType.get(request_type_id) + rt.name = util.restore_text( params.name ) + rt.desc = util.restore_text( params.description ) or "" + rt.request_form_id = int(util.restore_text( params.request_form_id )) + rt.sample_form_id = int(util.restore_text( params.sample_form_id )) + rt.flush() + # set sample states + ss_list = trans.app.model.SampleState.filter(trans.app.model.SampleState.table.c.request_type_id == rt.id).all() + for ss in ss_list: + ss.delete() + ss.flush() + for i in range( num_states ): + name = params.get( 'new_element_name_%i' % i, None ) + desc = params.get( 'new_element_description_%i' % i, None ) + ss = trans.app.model.SampleState(name, desc, rt.id) + ss.flush() + msg = "The new sample type named '%s' with %s state(s) has been created" % (rt.name, num_states) + return rt, msg diff -r 267db48a2371 -r b46f27137744 lib/galaxy/web/controllers/forms.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/galaxy/web/controllers/forms.py Fri Jul 10 11:37:28 2009 -0400 @@ -0,0 +1,323 @@ +from galaxy.web.base.controller import * +from galaxy.model.orm import * +from galaxy.datatypes import sniff +from galaxy import util +import logging, os, sys +from galaxy.web.form_builder import * +from galaxy.tools.parameters.basic import parameter_types +from elementtree.ElementTree import XML, Element +from galaxy.util.odict import odict +import copy + +log = logging.getLogger( __name__ ) + + +class Forms( BaseController ): + @web.expose + @web.require_admin + def index( self, trans, **kwd ): + params = util.Params( kwd ) + msg = util.restore_text( params.get( 'msg', '' ) ) + messagetype = params.get( 'messagetype', 'done' ) + return trans.fill_template( "/sample/index.mako", + default_action=params.get( 'default_action', None ), + msg=msg, + messagetype=messagetype ) + @web.expose + @web.require_admin + def manage( self, trans, **kwd ): + 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): + fdc_list = trans.app.model.FormDefinitionCurrent.query().all() + return trans.fill_template( '/admin/forms/manage_forms.mako', + fdc_list=fdc_list, + deleted=False, + show_deleted=False, + msg=msg, + messagetype=messagetype ) + def _get_all_forms(self, trans, all_versions=False): + ''' + This method returns all the latest forms from the + form_definition_current table if all_versions is set to True. Otherwise + this method return all the versions of all the forms from form_definition + table + ''' + if all_versions: + return trans.app.model.FormDefinition.query().all() + else: + fdc_list = trans.app.model.FormDefinitionCurrent.query().all() + return [fdc.latest_form for fdc in fdc_list] + @web.expose + @web.require_admin + def new( self, trans, **kwd ): + params = util.Params( kwd ) + msg = util.restore_text( params.get( 'msg', '' ) ) + messagetype = params.get( 'messagetype', 'done' ) + if params.get('new', False) and not params.get('create_form', False): + self.current_form = {} + self.current_form['name'] = 'New Form' + self.current_form['desc'] = '' + self.current_form['fields'] = [] + inputs = [ ( 'Name', TextField('name', 40,self.current_form['name'] ) ), + ( 'Description', TextField('description', 40, self.current_form['desc']) ) ] + return trans.fill_template( '/admin/forms/create_form.mako', + inputs=inputs, + msg=msg, + messagetype=messagetype ) + elif params.get('create_form', False) == 'True': + if 'submitted' in params.new: + self.num_add_fields = 0 + fd, msg = self.__save_form(trans, params) + self.__get_saved_form(fd) + return self._show_forms_list(trans, msg, messagetype) + @web.expose + @web.require_admin + def edit( self, trans, **kwd ): + ''' + This callback method is for handling all the editing functions like: + remaning fields, adding/deleting fields, changing fields attributes + ''' + 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 ))) + # SHOW THE FORM FOR EDITING. + if params.get('show_form', False) == 'True': + self.__get_saved_form(fd) + # the following two dicts store the unsaved select box options + self.del_options = {} + self.add_options = {} + return self.__show(trans, params, fd) + # DELETE FIELD + elif params.get('remove_button', False): + self.__update_current_form(params) + index = int(params.get('remove_button', None).split(' ')[2])-1 + self.__remove_field(index) + return self.__show(trans, params, fd) + # SAVE CHANGES + elif params.get('save_changes_button', False) == 'Save': + self.__update_current_form(params) + fd_new, msg = self.__save_form(trans, params, fd.form_definition_current.id) + if not fd_new: + return self.__show(trans, params, fd, msg, 'error') + else: + fd = fd_new + msg = "The form '%s' has been updated with the changes." % fd.name + return self.__show(trans, params, fd, msg) + #ADD A FIELD + elif params.get('add_field_button', False) == 'Add field': + self.__update_current_form(params) + self.__add_field() + # show the form again with one empty field + return self.__show(trans, params, fd) + # SHOW FORM READ ONLY + elif params.get('read_only', False): + return trans.fill_template( '/admin/forms/show_form_read_only.mako', + form=fd, + msg=msg, + messagetype=messagetype ) + # REFRESH PAGE, SelectField is selected/deselected as the type of a field + elif params.get('refresh', False) == 'true': + self.__update_current_form(params) + return self.__show(trans, params, fd) + # REMOVE SelectField OPTION + elif params.get('select_box_options', False) == 'remove': + #self.__update_current_form(params) + index = int(params.get( 'field_index', None )) + option = int(params.get( 'option_index', None )) + del self.current_form['fields'][index]['selectlist'][option] + return self.__show(trans, params, fd) + # ADD SelectField OPTION + elif params.get('select_box_options', False) == 'add': + #self.__update_current_form(params) + index = int(params.get( 'field_index', None )) + self.current_form['fields'][index]['selectlist'].append('') + return self.__show(trans, params, fd) + def __remove_field(self, index): + del self.current_form['fields'][index] + def __add_field(self): + ''' + add an empty field to the fields list + ''' + empty_field = { 'label': '', + 'helptext': '', + 'visible': True, + 'required': False, + 'type': BaseField.form_field_types()[0], + 'selectlist': '' } + self.current_form['fields'].append(empty_field) + def __get_field(self, params, index): + name = params.get( 'field_name_%i' % index, None ) + helptext = params.get( 'field_helptext_%i' % index, None ) + required = params.get( 'field_required_%i' % index, False ) + field_type = params.get( 'field_type_%i' % index, None ) + if field_type == 'SelectField': + selectlist = self.__get_selectbox_options(params, index) + else: + selectlist = None + return {'label': name, + 'helptext': helptext, + 'visible': True, + 'required': required, + 'type': field_type, + 'selectlist': selectlist } + def __get_selectbox_options(self, params, index): + ''' + This method gets all the options entered by the user for field when + the fieldtype is SelectField + ''' + ctr=0 + sb_options = [] + while True: + option = params.get( 'field_'+str(index)+'_option_'+str(ctr), None ) + ctr = ctr+1 + if option: + sb_options.append(option) + else: + return sb_options + def __get_saved_form(self, fd): + self.current_form = {} + self.current_form['name'] = fd.name + self.current_form['desc'] = fd.desc + self.current_form['fields'] = list(copy.deepcopy(fd.fields)) + def __validate_form(self, params): + ''' + This method checks the following text inputs are filled out by the user + - the name of form + - name of all the fields + ''' + # form name + if not util.restore_text( params.name ): + return None, 'Form name must be filled.' + # fields + for i in range( len(self.current_form['fields']) ): + if not params.get( 'field_name_%i' % i, None ): + return None, "All the field label(s) must be completed." + return True, '' + def __get_form(self, params): + name = util.restore_text( params.name ) + desc = util.restore_text( params.description ) or "" + # set form fields + fields = [] + for i in range( len(self.current_form['fields']) ): + fields.append(self.__get_field(params, i)) + fields = fields + return name, desc, fields + def __update_current_form(self, params): + name, desc, fields = self.__get_form(params) + self.current_form = {} + self.current_form['name'] = name + self.current_form['desc'] = desc + self.current_form['fields'] = fields + + def __save_form(self, trans, params, fdc_id=None): + ''' + This method saves the current form + ''' + # check the form for invalid inputs + flag, msg = self.__validate_form(params) + if not flag: + return None, msg + fd = trans.app.model.FormDefinition() + fd.name, fd.desc, fd.fields = self.__get_form(params) + if fdc_id: # save changes to the existing form + # change the pointer in the form_definition_current table to point + # to this new record + fdc = trans.app.model.FormDefinitionCurrent.get(fdc_id) + else: # create a new form + fdc = trans.app.model.FormDefinitionCurrent() + # create corresponding row in the form_definition_current table + fd.form_definition_current = fdc + fdc.latest_form = fd + trans.sa_session.save_or_update( fdc ) + trans.sa_session.flush() + msg = "The new form named '%s' has been created. " % (fd.name) + request_types = trans.app.model.RequestType.query().all() + if not request_types: + msg = msg + "Now you can create requests to associate with this form." + return fd, msg + + class FieldUI(object): + def __init__(self, index, field=None, field_type=None): + ''' + This method returns a list of widgets which describes a field. This + includes label, helptext, type, & required/optional + ''' + self.index = index + self.label = TextField('field_name_'+str(index), 40, '') + self.helptext = TextField('field_helptext_'+str(index), 40, '') + self.fieldtype = SelectField('field_type_'+str(index), + refresh_on_change=True, + refresh_on_change_values=['SelectField']) + self.selectbox_options = [] + for ft in BaseField.form_field_types(): + self.fieldtype.add_option(ft, ft) + self.required = SelectField('field_required_'+str(index), display='radio') + self.required.add_option('Required', 'true') + self.required.add_option('Optional', 'true', selected=True) + if field: + self.fill(field, field_type) + def fill(self, field, field_type=None): + # label + self.label.value = field['label'] + # helptext + self.helptext.value = field['helptext'] + # type + self.fieldtype = SelectField('field_type_'+str(self.index), + refresh_on_change=True, + refresh_on_change_values=['SelectField']) + if field_type: + field['type'] = unicode(field_type) + if field_type == 'SelectField' and not field['selectlist']: + field['selectlist'] = ['', ''] + for ft in BaseField.form_field_types(): + if ft == field['type']: + self.fieldtype.add_option(ft, ft, selected=True) + if ft == 'SelectField': + self.selectbox_ui(field) + else: + self.fieldtype.add_option(ft, ft) + # required/optional + if field['required']: + self.required = SelectField('required_'+str(self.index), display='radio') + self.required.add_option('Required', 'true', selected=True) + self.required.add_option('Optional', 'true') + def selectbox_ui(self, field): + self.selectbox_options = [] + if field['selectlist']: + for ctr, option in enumerate(field['selectlist']): + self.selectbox_options.append(('Option '+str(ctr+1), + TextField('field_'+str(self.index)+'_option_'+str(ctr), + 40, option))) + def get(self): + return [( 'Label', self.label ), + ( 'Help text', self.helptext ), + ( 'Type', self.fieldtype, self.selectbox_options), + ( '', self.required)] + def __repr__(self): + return str(self.index)+'.'+self.label + def label(self): + return str(self.index)+'.'+self.label + + def __show(self, trans, params, form, msg=None, messagetype='done'): + ''' + This method displays the form and any of the changes made to it + ''' + # name & description + form_details = [ ( 'Name', TextField('name', 40, self.current_form['name']) ), + ( 'Description', TextField('description', 40, self.current_form['desc']) ) ] + # fields + field_details = [] + for index, field in enumerate(self.current_form['fields']): + field_ui = self.FieldUI(index, field) + field_details.append( field_ui.get() ) + return trans.fill_template( '/admin/forms/edit_form.mako', + form_details=form_details, + field_details=field_details, + form=form, + field_types=BaseField.form_field_types(), + msg=msg, + messagetype=messagetype ) diff -r 267db48a2371 -r b46f27137744 lib/galaxy/web/controllers/requests.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/galaxy/web/controllers/requests.py Fri Jul 10 11:37:28 2009 -0400 @@ -0,0 +1,429 @@ +from galaxy.web.base.controller import * +from galaxy.web.framework.helpers import time_ago, iff, grids +from galaxy.model.orm import * +from galaxy.datatypes import sniff +from galaxy import util +from galaxy.util.streamball import StreamBall +import logging, tempfile, zipfile, tarfile, os, sys +from galaxy.web.form_builder import * + +log = logging.getLogger( __name__ ) + +# States for passing messages +SUCCESS, INFO, WARNING, ERROR = "done", "info", "warning", "error" + +class RequestsListGrid( grids.Grid ): + title = "Requests" + model_class = model.Request + default_sort_key = "-create_time" + columns = [ + grids.GridColumn( "Name", key="name", + link=( lambda item: iff( item.deleted, None, dict( operation="show_request", id=item.id ) ) ), + attach_popup=True ), + grids.GridColumn( "Description", key='desc'), + grids.GridColumn( "Sample(s)", method='number_of_samples', + link=( lambda item: iff( item.deleted, None, dict( operation="samples", id=item.id ) ) ), ), + grids.GridColumn( "Type", key="request_type_id", method='get_request_type'), + grids.GridColumn( "Last update", key="update_time", format=time_ago ) + ] + operations = [ +# grids.GridOperation( "Edit", allow_multiple=False, condition=( lambda item: not item.deleted ) ), + grids.GridOperation( "Samples", allow_multiple=False, condition=( lambda item: not item.deleted ) ), +# grids.GridOperation( "Delete", condition=( lambda item: not item.deleted ) ), +# 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' ) ) + ] + #default_filter = dict( deleted=False ) + def get_current_item( self, trans ): + return None + def get_request_type(self, trans, request): + 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( user=trans.user ) + def number_of_samples(self, trans, request): + return str(len(trans.app.model.Sample.filter(trans.app.model.Sample.table.c.request_id==request.id).all())) + +class SamplesListGrid( grids.Grid ): + model_class = model.Sample + default_sort_key = "-create_time" + columns = [ + grids.GridColumn( "Name", key="name", + link=( lambda item: iff( item.deleted, None, dict( operation="show_sample", id=item.id ) ) ), + attach_popup=True ), + grids.GridColumn( "Description", key='desc' ), + grids.GridColumn( "Status", method="get_status", + link=( lambda item: iff( item.deleted, None, dict( operation="events", id=item.id ) ) )), + + grids.GridColumn( "Last update", key="update_time", format=time_ago ) + + # Valid for filtering but invisible + #grids.GridColumn( "Deleted", key="deleted", visible=False ) + ] + operations = [ +# grids.GridOperation( "Edit", allow_multiple=False, condition=( lambda item: not item.deleted ) ), +# grids.GridOperation( "Delete", condition=( lambda item: not item.deleted ) ), +# 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' ) ) + ] + def __init__(self, request): + self.request = request + def get_current_item( self, trans ): + return None + def apply_default_filter( self, trans, query ): + return query.filter_by( request_id=self.request.id ) + def get_status(self, trans, sample): + all_states = trans.app.model.SampleEvent.filter(trans.app.model.SampleEvent.table.c.sample_id == sample.id).all() + curr_state = trans.app.model.SampleState.get(all_states[len(all_states)-1].sample_state_id) + return curr_state.name + +class Requests( BaseController ): + request_grid = RequestsListGrid() + + @web.expose + def index( self, trans ): + return trans.fill_template( "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 + def list( self, trans, **kwargs ): + ''' + List all request made by the current user + ''' + status = message = None + if 'operation' in kwargs: + operation = kwargs['operation'].lower() + if operation == "show_request": + id = trans.security.decode_id(kwargs['id']) + return self.show_read_only(trans, id) + elif operation == "samples": + id = trans.security.decode_id(kwargs['id']) + return self.show_samples(trans, id, kwargs) + elif operation == "show_sample": + id = trans.security.decode_id(kwargs['id']) + return self.show_sample_read_only(trans, id) + elif operation == "events": + id = trans.security.decode_id(kwargs['id']) + return self.show_events(trans, id) + # Render the list view + return self.request_grid( trans, status=status, message=message, template='/requests/grid.mako', **kwargs ) + def show_samples(self, trans, id, kwargs): + ''' + Shows all the samples associated with this request + ''' + status = message = None + request = trans.app.model.Request.get(id) + self.samples_grid = SamplesListGrid(request) + return self.samples_grid( trans, status=status, message=message, template='/sample/grid.mako', **kwargs ) + def show_read_only(self, trans, id): + ''' + Shows the request details + ''' + request = trans.app.model.Request.get(id) + request_type = trans.app.model.RequestType.get(request.request_type_id) + request_form = trans.app.model.FormDefinition.get(request_type.request_form_id) + request_values = trans.app.model.FormValues.get(request.form_values_id) + libraries = self.get_authorized_libs(trans) + # list of widgets to be rendered on the request form + request_details = [] + # main details + request_details.append(dict(label='Name', + value=request.name, + helptext='')) + request_details.append(dict(label='Description', + value=request.desc, + helptext='')) + request_details.append(dict(label='Type', + value=request_type.name, + helptext='')) + request_details.append(dict(label='Date created', + value=request.create_time, + helptext='')) + request_details.append(dict(label='Date updated', + value=request.create_time, + helptext='')) + request_details.append(dict(label='User', + value=str(trans.user.email), + helptext='')) + # library associated + request_details.append(dict(label='Library', + value=trans.app.model.Library.get(request.library_id).name, + helptext='Associated library where the resultant \ + dataset will be stored')) + # form fields + for field in request_form.fields: + if field['required']: + req = 'Required' + else: + req = 'Optional' + request_details.append(dict(label=field['label'], + value=request_values.content[field['label']], + helptext=field['helptext']+' ('+req+')')) + return trans.fill_template( '/requests/view_request.mako', + request_form_id=request_form.id, + request_details=request_details, + request_type=request_type) + @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), + msg=msg, + messagetype=messagetype ) + elif params.get('create', False) == 'True': + request_type_id = int(util.restore_text( params.request_type_id )) + return self.__show_request_form(trans, params, request_type_id) + elif params.get('save', False) == 'True': + request = self.__save(trans, params) + msg = 'The new request named %s has been created' % request.name + request_type_id = int(util.restore_text( params.request_type_id )) + return trans.response.send_redirect( web.url_for( controller='requests', + action='list', + msg=msg , + messagetype='done') ) + return self.__show_request_form(trans, params, request_type_id, request=request) + def __save(self, trans, params, request_id=None): + ''' + This method save a new request if request_id is None. + ''' + if not request_id: + request_type_id = int(util.restore_text( params.request_type_id )) + request_form_id = trans.app.model.RequestType.get(request_type_id).request_form_id + request_form = trans.app.model.FormDefinition.get(request_form_id) + else: + request = trans.app.model.Request.get(request_id) + form_values = trans.app.model.FormValues.get(request.form_values_id) + request_form = trans.app.model.FormDefinition.get(form_values.request_form_id) + name = params.get('name', '') + desc = params.get('desc', '') + library_id = params.get('library', '') + values = {} + for field in request_form.fields: + values[field['label']] = params.get(field['label'], '') + if not request_id: + form_values = trans.app.model.FormValues(request_form_id, values) + form_values.flush() + request = trans.app.model.Request(name, desc, request_type_id, + trans.user.id, form_values.id, + library_id) + request.flush() + else: + form_values.content = values + form_values.flush() + return request + def __show_request_form(self, trans, params, request_type_id, request=None): + request_type = trans.app.model.RequestType.get(request_type_id) + request_form_id = request_type.request_form_id + if request: + form_values = trans.app.model.FormValues.get(request.form_values_id) + else: + form_values = None + # list of widgets to be rendered on the request form + widgets = [] + widgets.append(dict(label='Name', + widget=TextField('name'), + helptext='(Required)')) + widgets.append(dict(label='Description', + widget=TextField('desc'), + helptext='(Optional)')) + widgets[0]['widget'].set_size(40) + widgets[1]['widget'].set_size(40) + # libraries selectbox + libraries = self.get_authorized_libs(trans) + lib_list = SelectField('library') + for lib in libraries: + lib_list.add_option(lib.name, lib.id) + widgets.append(dict(label='Library', + widget=lib_list, + helptext='Associated library where the resultant \ + dataset will be stored')) + widgets = self.__create_form(trans, params, request_form_id, widgets, form_values) + title = 'Add a new request of type: %s' % request_type.name + return trans.fill_template( '/requests/new_request.mako', + request_form_id=request_form_id, + request_type=request_type, + widgets=widgets, + title=title) + + def __create_form(self, trans, params, form_id, widgets=[], form_values=None): + form = trans.app.model.FormDefinition.get(form_id) + if not form_values: + values = {} + for field in form.fields: + if field['type'] in ['SelectField' or 'CheckBoxField']: + values[field['label']] = False + else: + values[field['label']] = '' + else: + values = form_values.content + # form fields + for field in form.fields: + fw = eval(field['type'])(field['label']) + if field['type'] == 'TextField': + fw.set_size(40) + fw.value = values[field['label']] + elif field['type'] == 'TextArea': + fw.set_size(3, 40) + fw.value = values[field['label']] + elif field['type'] == 'SelectField': + for option in field['selectlist']: + fw.add_option(option, option, values[field['label']]) + elif field['type'] == 'CheckBoxField': + fw.checked = values[field['label']] + + if field['required']: + req = 'Required' + else: + req = 'Optional' + widgets.append(dict(label=field['label'], + widget=fw, + helptext=field['helptext']+' ('+req+')')) + return widgets + @web.expose + def add_sample(self, trans, **kwd): + params = util.Params( kwd ) + msg = util.restore_text( params.get( 'msg', '' ) ) + messagetype = params.get( 'messagetype', 'done' ) + request_id = int(util.restore_text( params.get( 'id', '' ) )) + return self.__show_sample_form(trans, params, request_id) + + def __show_sample_form(self, trans, params, request_id, sample=None): + request = trans.app.model.Request.get(request_id) + request_type = trans.app.model.RequestType.get(request.request_type_id) + sample_form_id = request_type.sample_form_id + if sample: + form_values = trans.app.model.FormValues.get(sample.form_values_id) + else: + form_values = None + # list of widgets to be rendered on the request form + widgets = [] + widgets.append(dict(label='Name', + widget=TextField('name'), + helptext='(Required)')) + widgets.append(dict(label='Description', + widget=TextField('desc'), + helptext='(Optional)')) + widgets[0]['widget'].set_size(40) + widgets[1]['widget'].set_size(40) + widgets = self.__create_form(trans, params, sample_form_id, widgets, form_values) + title = 'Add a new sample to request: %s of type: %s' % (request.name, request_type.name) + return trans.fill_template( '/sample/new_sample.mako', + sample_form_id=sample_form_id, + request_id=request.id, + widgets=widgets, + title=title) + @web.expose + def samples(self, trans, **kwd): + params = util.Params( kwd ) + if params.get('save', False) == 'True': + sample = self.__save_sample(trans, params) + return trans.response.send_redirect( web.url_for( controller='requests', + action='list', + operation='samples', + id=trans.security.encode_id(sample.request_id)) ) + def __save_sample(self, trans, params, sample_id=None): + if not sample_id: + request = trans.app.model.Request.get(int(util.restore_text( params.request_id ))) + request_type = trans.app.model.RequestType.get(request.request_type_id) + sample_form = trans.app.model.FormDefinition.get(request_type.sample_form_id) + else: + sample = trans.app.model.Sample.get(sample_id) + form_data = trans.app.model.FormData.get(sample.form_data_id) + form = trans.app.model.FormDefinition.get(form_data.form_definition_id) + name = params.get('name', '') + desc = params.get('desc', '') + values = {} + for field in sample_form.fields: + values[field['label']] = params.get(field['label'], '') + if not sample_id: + form_values = trans.app.model.FormValues(sample_form.id, values) + form_values.flush() + sample = trans.app.model.Sample(name, desc, request.id, form_values.id) + sample.flush() + # set the initial state + state = trans.app.model.SampleState.filter(trans.app.model.SampleState.table.c.request_type_id == request_type.id).first() + event = trans.app.model.SampleEvent(sample.id, state.id) + event.flush() + else: + form_data.content = values + form_data.flush() + return sample + def show_sample_read_only(self, trans, sample_id): + ''' + Shows the sample details + ''' + sample = trans.app.model.Sample.get(sample_id) + request = trans.app.model.Request.get(sample.request_id) + request_type = trans.app.model.RequestType.get(request.request_type_id) + sample_form = trans.app.model.FormDefinition.get(request_type.sample_form_id) + sample_values = trans.app.model.FormValues.get(sample.form_values_id) + # list of widgets to be rendered on the request form + sample_details = [] + # main details + sample_details.append(dict(label='Name', + value=sample.name, + helptext='')) + sample_details.append(dict(label='Description', + value=sample.desc, + helptext='')) + sample_details.append(dict(label='Date created', + value=sample.create_time, + helptext='')) + sample_details.append(dict(label='Date updated', + value=sample.create_time, + helptext='')) + sample_details.append(dict(label='User', + value=str(trans.user.email), + helptext='')) + sample_details.append(dict(label='Request', + value=request.name, + helptext='Name/ID of the request this sample belongs to.')) + # get the current state of the sample + all_states = trans.app.model.SampleEvent.filter(trans.app.model.SampleEvent.table.c.sample_id == sample_id).all() + curr_state = trans.app.model.SampleState.get(all_states[len(all_states)-1].sample_state_id) + sample_details.append(dict(label='State', + value=curr_state.name, + helptext=curr_state.desc)) + # form fields + for field in sample_form.fields: + if field['required']: + req = 'Required' + else: + req = 'Optional' + sample_details.append(dict(label=field['label'], + value=sample_values.content[field['label']], + helptext=field['helptext']+' ('+req+')')) + return trans.fill_template( '/sample/view_sample.mako', + sample_details=sample_details) + def show_events(self, trans, sample_id): + sample = trans.app.model.Sample.get(sample_id) + events_list = [] + for event in trans.app.model.SampleEvent.filter(trans.app.model.SampleEvent.table.c.sample_id == sample_id).all(): + state = trans.app.model.SampleState.get(event.sample_state_id) + events_list.append((state.name, event.update_time, state.desc, event.comment)) + return trans.fill_template( '/sample/sample_events.mako', + events_list=events_list, + sample_name=sample.name, + request=trans.app.model.Request.get(sample.request_id).name) + + + + diff -r 267db48a2371 -r b46f27137744 lib/galaxy/web/controllers/requests_admin.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/galaxy/web/controllers/requests_admin.py Fri Jul 10 11:37:28 2009 -0400 @@ -0,0 +1,315 @@ +from galaxy.web.base.controller import * +from galaxy.web.framework.helpers import time_ago, iff, grids +from galaxy.model.orm import * +from galaxy.datatypes import sniff +from galaxy import util +from galaxy.util.streamball import StreamBall +import logging, tempfile, zipfile, tarfile, os, sys +from galaxy.web.form_builder import * +from datetime import datetime, timedelta + +log = logging.getLogger( __name__ ) + + +# States for passing messages +SUCCESS, INFO, WARNING, ERROR = "done", "info", "warning", "error" + +class RequestsListGrid( grids.Grid ): + title = "Requests" + model_class = model.Request + default_sort_key = "-create_time" + columns = [ + grids.GridColumn( "Name", key="name", + link=( lambda item: iff( item.deleted, None, dict( operation="show_request", id=item.id ) ) ), + attach_popup=True ), + grids.GridColumn( "Description", key="desc"), + grids.GridColumn( "Sample(s)", method='number_of_samples', + link=( lambda item: iff( item.deleted, None, dict( operation="samples", 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( "User", key="user_id", method='get_user') + + ] + operations = [ +# grids.GridOperation( "Edit", allow_multiple=False, condition=( lambda item: not item.deleted ) ), + grids.GridOperation( "Samples", allow_multiple=False, condition=( lambda item: not item.deleted ) ), +# grids.GridOperation( "Delete", condition=( lambda item: not item.deleted ) ), +# 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' ) ) + ] + def get_user(self, trans, request): + return trans.app.model.User.get(request.user_id).email + def get_current_item( self, trans ): + return None + def get_request_type(self, trans, request): + request_type = trans.app.model.RequestType.get(request.request_type_id) + return request_type.name + def apply_default_filter( self, trans, query ): + return query + def number_of_samples(self, trans, request): + return str(len(trans.app.model.Sample.filter(trans.app.model.Sample.table.c.request_id==request.id).all())) + +class SamplesListGrid( grids.Grid ): + model_class = model.Sample + default_sort_key = "-create_time" + columns = [ + grids.GridColumn( "Name", key="name", + link=( lambda item: iff( item.deleted, None, dict( operation="show_sample", id=item.id ) ) ), + attach_popup=True ), + grids.GridColumn( "Description", key='desc' ), + grids.GridColumn( "Status", method="get_status", + link=( lambda item: iff( item.deleted, None, dict( operation="events", id=item.id ) ) )), + + grids.GridColumn( "Last update", key="update_time", format=time_ago ) + + # Valid for filtering but invisible + #grids.GridColumn( "Deleted", key="deleted", visible=False ) + ] + operations = [ +# grids.GridOperation( "Edit", allow_multiple=False, condition=( lambda item: not item.deleted ) ), + grids.GridOperation( "Change state", condition=( lambda item: not item.deleted ) ), +# grids.GridOperation( "Delete", condition=( lambda item: not item.deleted ) ), +# 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' ) ) + ] + def __init__(self, request, user): + self.request = request + self.user = user + def get_current_item( self, trans ): + return None + def apply_default_filter( self, trans, query ): + return query.filter_by( request_id=self.request.id ) + def get_status(self, trans, sample): + all_states = trans.app.model.SampleEvent.filter(trans.app.model.SampleEvent.table.c.sample_id == sample.id).all() + curr_state = trans.app.model.SampleState.get(all_states[len(all_states)-1].sample_state_id) + return curr_state.name + +class Requests( BaseController ): + request_grid = RequestsListGrid() + + @web.expose + @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 ): + ''' + List all request made by the current user + ''' + status = message = None + if 'operation' in kwargs: + operation = kwargs['operation'].lower() + if operation == "show_request": + id = trans.security.decode_id(kwargs['id']) + return self.show_read_only(trans, id) + elif operation == "samples": + id = trans.security.decode_id(kwargs['id']) + return self.show_samples(trans, id, kwargs) + elif operation == "show_sample": + id = trans.security.decode_id(kwargs['id']) + return self.show_sample_read_only(trans, id) + elif operation == "change state": + id_list = [trans.security.decode_id(id) for id in util.listify(kwargs['id'])] + return self.change_state(trans, id_list) + elif operation == "events": + id = trans.security.decode_id(kwargs['id']) + return self.show_events(trans, id) + # Render the list view + return self.request_grid( trans, status=status, message=message, template='/admin/requests/grid.mako', **kwargs ) + def show_samples(self, trans, id, kwargs): + ''' + Shows all the samples associated with this request + ''' + status = message = None + request = trans.app.model.Request.get(id) + self.samples_grid = SamplesListGrid(request, trans.app.model.User.get(request.user_id)) + return self.samples_grid( trans, status=status, message=message, template='/admin/samples/grid.mako', **kwargs ) + def show_read_only(self, trans, id): + ''' + Shows the request details + ''' + request = trans.app.model.Request.get(id) + request_type = trans.app.model.RequestType.get(request.request_type_id) + request_form = trans.app.model.FormDefinition.get(request_type.request_form_id) + request_values = trans.app.model.FormValues.get(request.form_values_id) + libraries = self.get_authorized_libs(trans) + # list of widgets to be rendered on the request form + request_details = [] + # main details + request_details.append(dict(label='Name', + value=request.name, + helptext='')) + request_details.append(dict(label='Description', + value=request.desc, + helptext='')) + request_details.append(dict(label='Type', + value=request_type.name, + helptext='')) + request_details.append(dict(label='Date created', + value=request.create_time, + helptext='')) + request_details.append(dict(label='Date updated', + value=request.create_time, + helptext='')) + request_details.append(dict(label='User', + value=str(trans.user.email), + helptext='')) + # library associated + request_details.append(dict(label='Library', + value=trans.app.model.Library.get(request.library_id).name, + helptext='Associated library where the resultant \ + dataset will be stored')) + # form fields + for field in request_form.fields: + if field['required']: + req = 'Required' + else: + req = 'Optional' + request_details.append(dict(label=field['label'], + value=request_values.content[field['label']], + helptext=field['helptext']+' ('+req+')')) + return trans.fill_template( '/admin/requests/view_request.mako', + request_form_id=request_form.id, + request_details=request_details, + request_type=request_type) + + @web.expose + @web.require_admin + def samples(self, trans, **kwd): + params = util.Params( kwd ) + if params.get('save', False) == 'True': + sample = self.__save_sample(trans, params) + return self.show_samples(trans, sample.request_id, {}) + def show_sample_read_only(self, trans, sample_id): + ''' + Shows the sample details + ''' + sample = trans.app.model.Sample.get(sample_id) + request = trans.app.model.Request.get(sample.request_id) + request_type = trans.app.model.RequestType.get(request.request_type_id) + sample_form = trans.app.model.FormDefinition.get(request_type.sample_form_id) + sample_values = trans.app.model.FormValues.get(sample.form_values_id) + # list of widgets to be rendered on the request form + sample_details = [] + # main details + sample_details.append(dict(label='Name', + value=request.name, + helptext='')) + sample_details.append(dict(label='Description', + value=request.desc, + helptext='')) + sample_details.append(dict(label='Date created', + value=sample.create_time, + helptext='')) + sample_details.append(dict(label='Date updated', + value=sample.create_time, + helptext='')) + sample_details.append(dict(label='User', + value=str(trans.user.email), + helptext='')) + sample_details.append(dict(label='Request', + value=request.name, + helptext='Name/ID of the request this sample belongs to.')) + # get the current state of the sample + all_states = trans.app.model.SampleEvent.filter(trans.app.model.SampleEvent.table.c.sample_id == sample_id).all() + curr_state = trans.app.model.SampleState.get(all_states[len(all_states)-1].sample_state_id) + sample_details.append(dict(label='State', + value=curr_state.name, + helptext=curr_state.desc)) + # form fields + for field in sample_form.fields: + if field['required']: + req = 'Required' + else: + req = 'Optional' + sample_details.append(dict(label=field['label'], + value=sample_values.content[field['label']], + helptext=field['helptext']+' ('+req+')')) + return trans.fill_template( '/admin/samples/view_sample.mako', + sample_details=sample_details) + def __get_all_states(self, trans, sample): + request = trans.app.model.Request.get(sample.request_id) + request_type = trans.app.model.RequestType.get(request.request_type_id) + all_states = trans.app.model.SampleEvent.filter(trans.app.model.SampleEvent.table.c.sample_id == sample.id).all() + curr_state = trans.app.model.SampleState.get(all_states[len(all_states)-1].sample_state_id) + states_list = trans.app.model.SampleState.filter(trans.app.model.SampleState.table.c.request_type_id == request_type.id) + return states_list + def __get_curr_state(self, trans, sample): + all_states = trans.app.model.SampleEvent.filter(trans.app.model.SampleEvent.table.c.sample_id == sample.id).all() + curr_state = trans.app.model.SampleState.get(all_states[len(all_states)-1].sample_state_id) + return curr_state + def change_state(self, trans, sample_id_list): + sample = trans.app.model.Sample.get(sample_id_list[0]) + states_list = self.__get_all_states(trans, sample) + curr_state = self.__get_curr_state(trans, sample) + states_input = SelectField('select_state') + for state in states_list: + if len(sample_id_list) == 1: + if curr_state.name == state.name: + states_input.add_option(state.name+' (Current)', state.name, selected=True) + else: + states_input.add_option(state.name, state.name) + else: + states_input.add_option(state.name, state.name) + widgets = [] + widgets.append(('Select the new state of the sample(s) from the list of possible state(s)', + states_input)) + widgets.append(('Comments', TextArea('comment'))) + title = 'Change current state of sample: ' + sample.name + return trans.fill_template( '/admin/samples/change_state.mako', + widgets=widgets, title=title, + sample_id_list=util.object_to_string(sample_id_list)) + @web.expose + @web.require_admin + def save_state(self, trans, **kwd): + params = util.Params( kwd ) + sample_id_list = util.string_to_object(util.restore_text( params.sample_id_list )) + comments = util.restore_text( params.comment ) + sample = trans.app.model.Sample.get(sample_id_list[0]) + request = trans.app.model.Request.get(sample.request_id) + selected_state = util.restore_text( params.select_state ) + new_state = trans.app.model.SampleState.filter(trans.app.model.SampleState.table.c.request_type_id == request.request_type_id + and trans.app.model.SampleState.table.c.name == selected_state)[0] + for sample_id in sample_id_list: + event = trans.app.model.SampleEvent(sample_id, new_state.id, comments) + event.flush() + return trans.response.send_redirect( web.url_for( controller='requests_admin', + action='list', + operation='samples', + id=trans.security.encode_id(request.id)) ) + @web.expose + @web.require_admin + def show_events(self, trans, sample_id): + sample = trans.app.model.Sample.get(sample_id) + request = trans.app.model.Request.get(sample.request_id) + events_list = [] + for event in trans.app.model.SampleEvent.filter(trans.app.model.SampleEvent.table.c.sample_id == sample_id).order_by(trans.app.model.SampleEvent.c.update_time.desc()).all(): + state = trans.app.model.SampleState.get(event.sample_state_id) + delta = datetime.utcnow() - event.update_time + if delta > timedelta( minutes=60 ): + last_update = '%s hours' % int( delta.seconds / 60 / 60 ) + else: + last_update = '%s minutes' % int( delta.seconds / 60 ) + events_list.append((state.name, state.desc, last_update, event.comment)) + return trans.fill_template( '/admin/samples/events.mako', + events_list=events_list, + sample_name=sample.name, user=trans.app.model.User.get(request.user_id), + request=request.name) + \ No newline at end of file diff -r 267db48a2371 -r b46f27137744 lib/galaxy/web/form_builder.py --- a/lib/galaxy/web/form_builder.py Thu Jul 09 15:49:26 2009 -0400 +++ b/lib/galaxy/web/form_builder.py Fri Jul 10 11:37:28 2009 -0400 @@ -9,6 +9,11 @@ def get_html( self, prefix="" ): """Returns the html widget corresponding to the parameter""" raise TypeError( "Abstract Method" ) + @staticmethod + def form_field_types(): + return ['TextField', 'TextArea', 'SelectField', 'CheckboxField'] + + class TextField(BaseField): """ @@ -26,6 +31,8 @@ def get_html( self, prefix="" ): return '<input type="text" name="%s%s" size="%d" value="%s">' \ % ( prefix, self.name, self.size, self.value ) + def set_size(self, size): + self.size = int( size ) class TextArea(BaseField): """ @@ -45,6 +52,9 @@ def get_html( self, prefix="" ): return '<textarea name="%s%s" rows="%d" cols="%d">%s</textarea>' \ % ( prefix, self.name, self.rows, self.cols, self.value ) + def set_size(self, rows, cols): + self.rows = rows + self.cols = cols class CheckboxField(BaseField): """ @@ -215,6 +225,17 @@ rval.insert( 0, '<select name="%s%s"%s%s%s>' % ( prefix, self.name, multiple, self.refresh_on_change_text, last_selected_value ) ) rval.append( '</select>' ) return "\n".join( rval ) + def get_selected(self): + ''' + This method returns the currently selected option's text and value + ''' + for text, value, selected in self.options: + if selected: + return text, value + if self.options: + return self.options[0] + return None + class DrillDownField( BaseField ): diff -r 267db48a2371 -r b46f27137744 lib/galaxy/web/framework/__init__.py --- a/lib/galaxy/web/framework/__init__.py Thu Jul 09 15:49:26 2009 -0400 +++ b/lib/galaxy/web/framework/__init__.py Fri Jul 10 11:37:28 2009 -0400 @@ -607,6 +607,11 @@ if dbkey == ds.dbkey: return ds return None + + def request_types(self): + if self.app.model.RequestType.query().all(): + return True + return False class FormBuilder( object ): """ diff -r 267db48a2371 -r b46f27137744 templates/admin/forms/create_form.mako --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/templates/admin/forms/create_form.mako Fri Jul 10 11:37:28 2009 -0400 @@ -0,0 +1,31 @@ +<%inherit file="/base.mako"/> +<%namespace file="/message.mako" import="render_msg" /> + + +%if msg: + ${render_msg( msg, messagetype )} +%endif + +<div class="toolForm"> + <div class="toolFormTitle">Create a new form definition</div> + <div class="toolFormBody"> + <form name="create_form" action="${h.url_for( controller='forms', action='new', create_form=True, new=False, create_fields=False )}" method="post" > + %for label, input in inputs: + <div class="form-row"> + <label>${label}</label> + <div style="float: left; width: 250px; margin-right: 10px;"> + ${input.get_html()} + </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> + <input type="submit" name="save_form" value="Save"/> + </form> + </div> +</div> diff -r 267db48a2371 -r b46f27137744 templates/admin/forms/edit_form.mako --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/templates/admin/forms/edit_form.mako Fri Jul 10 11:37:28 2009 -0400 @@ -0,0 +1,105 @@ +<%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_form" ).submit(); + } + }); +}); +</script> + +<%def name="render_selectbox_options( index, field_attr )"> + %if field_attr[0] == 'Type': + %if field_attr[1].get_selected()[0] == 'SelectField': + <% options = field_attr[2] %> + <div class="repeat-group-item"> + <label> Options</label> + %for i, option in enumerate(options): + <b> ${i+1}</b> + ${option[1].get_html()} + ##<input type="submit" name="remove_option_${index}" value="Remove option ${i+1}"/><br> + <a class="action-button" href="${h.url_for( controller='forms', action='edit', form_id=form.id, select_box_options='remove', field_index=index, option_index=i )}">Remove</a><br> + %endfor + </div> + <div class="form-row"> + <a class="action-button" href="${h.url_for( controller='forms', action='edit', form_id=form.id, select_box_options='add', field_index=index )}">Add</a> + </div> + ##<div class="form-row"> + ## <input type="submit" name="add_option_field_${index}" value="Add option"/> + ##</div> + %endif + %endif +</%def> + + +<%def name="render_field( index, field )"> + <div class="repeat-group-item"> + <div class="form-row"> + <label>Field ${1+index}</label> + </div> + %for field_attr in field: + <div class="form-row"> + <label>${field_attr[0]}</label> + ${field_attr[1].get_html()} + ${render_selectbox_options( index, field_attr )} + </div> + %endfor + <div class="form-row"> + <input type="submit" name="remove_button" value="Remove field ${index+1}"/> + </div> + </div> +</%def> + +<div class="toolForm"> + <div class="toolFormTitle">Edit form definition '${form.name}'</div> + <form id="edit_form" name="edit_form" action="${h.url_for( controller='forms', action='edit', form_id=form.id, num_fields=len(form.fields) )}" method="post" > + %for label, input in form_details: + <div class="form-row"> + <label>${label}</label> + <div style="float: left; width: 250px; margin-right: 10px;"> + ${input.get_html()} + </div> + <div style="clear: both"></div> + </div> + %endfor + <div class="toolFormTitle">Sample fields (${len(form.fields)})</div> + %for ctr, field in enumerate(field_details): + ${render_field( ctr, field )} + %endfor + <div class="form-row"> + <input type="submit" name="add_field_button" value="Add field"/> + </div> + <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> + <input type="submit" name="save_changes_button" value="Save"/> + </form> + </div> +</div> \ No newline at end of file diff -r 267db48a2371 -r b46f27137744 templates/admin/forms/manage_forms.mako --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/templates/admin/forms/manage_forms.mako Fri Jul 10 11:37:28 2009 -0400 @@ -0,0 +1,73 @@ +<%inherit file="/base.mako"/> +<%namespace file="/message.mako" import="render_msg" /> + + +<%def name="title()">Manage Form Definitions</%def> + +## Render a row +<%def name="render_row( form, ctr )"> + %if ctr % 2 == 1: + <tr class="odd_row"> + %else: + <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 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> + </td> + <td><i>${form.desc}</i></td> + </tr> +</%def> + + +<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 +</ul> + + + +%if msg: + ${render_msg( msg, messagetype )} +%endif + +%if not fdc_list: + %if deleted: + There are no deleted forms + %else: + There are no forms. + %endif +%else: + <table class="grid"> + <thead> + <tr> + <th>Name</th> + <th>Description</th> + </tr> + </thead> + <tbody> + %for ctr, fdc in enumerate( fdc_list ): + <tr> + ${render_row( fdc.latest_form, ctr )} + </tr> + %endfor + </tbody> + </table> +%endif diff -r 267db48a2371 -r b46f27137744 templates/admin/forms/show_form_read_only.mako --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/templates/admin/forms/show_form_read_only.mako Fri Jul 10 11:37:28 2009 -0400 @@ -0,0 +1,67 @@ +<%inherit file="/base.mako"/> +<%namespace file="/message.mako" import="render_msg" /> + + +%if msg: + ${render_msg( msg, messagetype )} +%endif + +<div class="toolForm"> + <div class="toolFormTitle">${form.name} - <i>${form.desc}</i></div> + <form name="library" action="${h.url_for( controller='forms', action='manage' )}" method="post" > + <table class = "grid"> + <tbody> + %for index, field in enumerate(form.fields): + <tr> + <td> + <div class="form-row"> + <label>${1+index}. Label</label> + <a>${field['label']}</a> + %if field['type'] == 'SelectField': + <a id="${field['label']}-popup" class="popup-arrow" style="display: none;">▼</a> + %for option in field['selectlist']: + <div popupmenu="${field['label']}-type-popup"> + <a class="action-button" href="" >${option}</a> + </div> + %endfor + %endif + </div> + </td> + <td> + <div class="form-row"> + <label>Help text </label> + %if not field['helptext']: + <a><i>No helptext</i></a> + %else: + <a>${field['helptext']}</a> + %endif + </div> + </td> + <td> + <div class="form-row"> + <label>Type:</label> + <a>${field['type']}</a> + %if field['type'] == 'SelectField': + <a id="fieldtype-popup" class="popup-arrow" style="display: none;">▼</a> + %for option in field['selectlist']: + <div popupmenu="type-popup"> + <a class="action-button" href="" >${option}</a> + </div> + %endfor + %endif + </div> + </td> + <td> + <div class="form-row"> + <label>Required?</label> + <a>${field['required']}</a> + </div> + </td> + </tr> + %endfor + </tbody> + </table> + ##<input type="submit" name="save_changes_button" value="Back"/> + </form> + </div> +</div> \ No newline at end of file diff -r 267db48a2371 -r b46f27137744 templates/admin/index.mako --- a/templates/admin/index.mako Thu Jul 09 15:49:26 2009 -0400 +++ b/templates/admin/index.mako Fri Jul 10 11:37:28 2009 -0400 @@ -103,13 +103,35 @@ <div class="toolTitle"><a href="${h.url_for( controller='admin', action='jobs' )}" target="galaxy_main">Manage jobs</a></div> </div> </div> + <div class="toolSectionPad"></div> + <div class="toolSectionTitle"> + <span>Forms</span> + </div> + <div class="toolSectionBody"> + <div class="toolSectionBg"> + <div class="toolTitle"><a href="${h.url_for( controller='forms', action='manage' )}" target="galaxy_main">Manage forms</a></div> + </div> + </div> + <div class="toolSectionPad"></div> + <div class="toolSectionTitle"> + <span>Requests</span> + </div> + <div class="toolSectionBody"> + <div class="toolSectionBg"> + <div class="toolTitle"><a href="${h.url_for( controller='admin', action='manage_request_types' )}" target="galaxy_main">Manage request types</a></div> + <div class="toolTitle"><a href="${h.url_for( controller='requests_admin', action='list')}" target="galaxy_main">Manage requests</a></div> + </div> + </div> </div> </div> </div> + ##<iframe name="galaxy_admin" src="${h.url_for( controller='admin', action='index' )}" frameborder="0" style="position: absolute; margin: 0; border: 0 none; height: 100%; width: 100%;"> </iframe> </%def> <%def name="center_panel()"> - - <iframe name="galaxy_main" id="galaxy_main" frameborder="0" style="position: absolute; width: 100%; height: 100%;" src="${h.url_for( action='center' )}"> </iframe> + <% + center_url = h.url_for( action='center' ) + %> + <iframe name="galaxy_main" id="galaxy_main" frameborder="0" style="position: absolute; width: 100%; height: 100%;" src="${center_url}"> </iframe> </%def> diff -r 267db48a2371 -r b46f27137744 templates/admin/requests/add_states.mako --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/templates/admin/requests/add_states.mako Fri Jul 10 11:37:28 2009 -0400 @@ -0,0 +1,26 @@ +<%inherit file="/base.mako"/> +<%namespace file="/message.mako" import="render_msg" /> + +%if msg: + ${render_msg( msg, messagetype )} +%endif + +<div class="toolForm"> + <div class="toolFormTitle">Create ${num_states} states for the '${sample_type_name}' sample type</div> + <form name="new_form_fields" action="${h.url_for( controller='admin', action='request_type', save_new=True, create=False, edit=False, name=sample_type_name, description=desc, num_states=num_states, request_form_id=request_form_id, sample_form_id=sample_form_id)}" method="post" > + <div class="toolFormBody"> + %for element_count in range( num_states ): + <div class="form-row"> + <label>${1+element_count}) State name:</label> + <input type="text" name="new_element_name_${element_count}" value="" size="40"/> + <label>State help text (optional):</label> + <input type="text" name="new_element_description_${element_count}" value="" size="40"/> + </div> + <div style="clear: both"></div> + %endfor + </div> + <div class="toolFormBody"> + <input type="submit" name="save_new_sample_type" value="Save"/> + </div> + </form> +</div> \ No newline at end of file diff -r 267db48a2371 -r b46f27137744 templates/admin/requests/create_request_type.mako --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/templates/admin/requests/create_request_type.mako Fri Jul 10 11:37:28 2009 -0400 @@ -0,0 +1,66 @@ +<%inherit file="/base.mako"/> +<%namespace file="/message.mako" import="render_msg" /> + + +%if msg: + ${render_msg( msg, messagetype )} +%endif + +<div class="toolForm"> + <div class="toolFormTitle">Create a new request type</div> + %if not forms: + Create a form definition first to create a new request type. + %else: + <div class="toolFormBody"> + <form name="create_request_type" action="${h.url_for( controller='admin', action='request_type', add_states=True, create=False, edit=False )}" method="post" > + <div class="form-row"> + <label>Name:</label> + <div style="float: left; width: 250px; margin-right: 10px;"> + <input type="text" name="name" value="New Request Type" size="40"/> + </div> + <div style="clear: both"></div> + </div> + <div class="form-row"> + <label>Description:</label> + <div style="float: left; width: 250px; margin-right: 10px;"> + <input type="text" name="description" value="" size="40"/> + </div> + <div style="clear: both"></div> + </div> + <div class="form-row"> + <label> + Request Form definition: + </label> + <select name="request_form_id"> + %for form in forms: + <option value="${form.id}">${form.name}</option> + %endfor + </select> + </div> + <div class="form-row"> + <label> + Sample Form definition: + </label> + <select name="sample_form_id"> + %for form in forms: + <option value="${form.id}">${form.name}</option> + %endfor + </select> + </div> + <div class="form-row"> + <label>Number of sample states:</label> + <div style="float: left; width: 250px; margin-right: 10px;"> + <input type="text" size="3" name="num_states" value="1"/> + </div> + </div> + <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> + <input type="submit" name="create_library_button" value="Define states"/> + </form> + </div> + %endif +</div> \ No newline at end of file diff -r 267db48a2371 -r b46f27137744 templates/admin/requests/edit_request_type.mako --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/templates/admin/requests/edit_request_type.mako Fri Jul 10 11:37:28 2009 -0400 @@ -0,0 +1,78 @@ +<%inherit file="/base.mako"/> +<%namespace file="/message.mako" import="render_msg" /> + + +%if msg: + ${render_msg( msg, messagetype )} +%endif + +<% num_states=len(states_list) %> + +<div class="toolForm"> + <div class="toolFormTitle">Edit the request type</div> + <div class="toolFormBody"> + <form name="library" action="${h.url_for( controller='admin', action='request_type', save_changes=True, create=False, id=request_type.id, num_states=num_states )}" method="post" > + <div class="form-row"> + <label>Name:</label> + <div style="float: left; width: 250px; margin-right: 10px;"> + <input type="text" name="name" value="${request_type.name}" size="40"/> + </div> + <div style="clear: both"></div> + </div> + <div class="form-row"> + <label>Description:</label> + <div style="float: left; width: 250px; margin-right: 10px;"> + <input type="text" name="description" value="${request_type.desc}" size="40"/> + </div> + <div style="clear: both"></div> + </div> + <div class="form-row"> + <label> + Request Form definition: + </label> + <select name="form_id"> + %for form in forms: + %if form.id == request_type.request_form_id: + <option value="${form.id}" selected>${form.name}</option> + %else: + <option value="${form.id}">${form.name}</option> + %endif + %endfor + </select> + </div> + <div class="form-row"> + <label> + Sample Form definition: + </label> + <select name="form_id"> + %for form in forms: + %if form.id == request_type.sample_form_id: + <option value="${form.id}" selected>${form.name}</option> + %else: + <option value="${form.id}">${form.name}</option> + %endif + %endfor + </select> + </div> + <div class="toolFormBody"> + %for element_count, state in enumerate(states_list): + <div class="form-row"> + <label>${1+element_count}) State name:</label> + <input type="text" name="new_element_name_${element_count}" value="${state.name}" size="40"/> + <label>State help text (optional):</label> + <input type="text" name="new_element_description_${element_count}" value="${state.desc}" size="40"/> + </div> + <div style="clear: both"></div> + %endfor + </div> + <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> + + <input type="submit" name="edit_request_type_button" value="Save"/> + </form> + </div> +</div> \ No newline at end of file diff -r 267db48a2371 -r b46f27137744 templates/admin/requests/grid.mako --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/templates/admin/requests/grid.mako Fri Jul 10 11:37:28 2009 -0400 @@ -0,0 +1,205 @@ +<%inherit file="/base.mako"/> +<%namespace file="/message.mako" import="render_msg" /> + +<%def name="title()">Browse Requests</%def> + +%if message: + <p> + <div class="${message_type}message transient-message">${message}</div> + <div style="clear: both"></div> + </p> +%endif + +<%def name="javascripts()"> + ${parent.javascripts()} + <script type="text/javascript"> + ## TODO: generalize and move into galaxy.base.js + $(document).ready(function() { + $(".grid").each( function() { + var grid = this; + var checkboxes = $(this).find("input.grid-row-select-checkbox"); + var update = $(this).find( "span.grid-selected-count" ); + $(checkboxes).each( function() { + $(this).change( function() { + var n = $(checkboxes).filter("[checked]").size(); + update.text( n ); + }); + }) + }); + }); + ## Can this be moved into base.mako? + %if refresh_frames: + %if 'masthead' in refresh_frames: + ## Refresh masthead == user changes (backward compatibility) + if ( parent.user_changed ) { + %if trans.user: + parent.user_changed( "${trans.user.email}", ${int( app.config.is_admin_user( trans.user ) )} ); + %else: + parent.user_changed( null, false ); + %endif + } + %endif + %if 'history' in refresh_frames: + if ( parent.frames && parent.frames.galaxy_history ) { + parent.frames.galaxy_history.location.href="${h.url_for( controller='root', action='history')}"; + if ( parent.force_right_panel ) { + parent.force_right_panel( 'show' ); + } + } + %endif + %if 'tools' in refresh_frames: + if ( parent.frames && parent.frames.galaxy_tools ) { + parent.frames.galaxy_tools.location.href="${h.url_for( controller='root', action='tool_menu')}"; + if ( parent.force_left_panel ) { + parent.force_left_panel( 'show' ); + } + } + %endif + %endif + </script> +</%def> + +<%def name="stylesheets()"> + <link href="${h.url_for('/static/style/base.css')}" rel="stylesheet" type="text/css" /> + <style> + ## Not generic to all grids -- move to base? + .count-box { + min-width: 1.1em; + padding: 5px; + border-width: 1px; + border-style: solid; + text-align: center; + display: inline-block; + } + </style> +</%def> + +<div class="grid-header"> + <h2>${grid.title}</h2> + %if len(query.all()): + <h3>All Users</h3> + %endif +## %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 +</div> + + +%if not len(query.all()): + There are no request(s). +%else: +<form name="history_actions" action="${url()}" method="post" > + <table class="grid"> + <thead> + <tr> + <th></th> + %for column in grid.columns: + %if column.visible: + <% + href = "" + extra = "" + if column.sortable: + if sort_key == column.key: + if sort_order == "asc": + href = url( sort=( "-" + column.key ) ) + extra = "↓" + else: + href = url( sort=( column.key ) ) + extra = "↑" + else: + href = url( sort=column.key ) + %> + <th\ + %if column.ncells > 1: + colspan="${column.ncells}" + %endif + > + %if href: + <a href="${href}">${column.label}</a> + %else: + ${column.label} + %endif + <span>${extra}</span> + </th> + %endif + %endfor + <th></th> + </tr> + </thead> + <tbody> + %for i, item in enumerate( query ): + <tr \ + %if current_item == item: + class="current" \ + %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> + ## Data columns + %for column in grid.columns: + %if column.visible: + <% + # Link + if column.link and column.link( item ): + href = url( **column.link( item ) ) + else: + href = None + # Value (coerced to list so we can loop) + value = column.get_value( trans, grid, item ) + if column.ncells == 1: + value = [ value ] + %> + %for cellnum, v in enumerate( value ): + <% + # Attach popup menu? + if column.attach_popup and cellnum == 0: + extra = '<a id="grid-%d-popup" class="popup-arrow" style="display: none;">▼</a>' % i + else: + extra = "" + %> + %if href: + <td><a href="${href}">${v}</a> ${extra}</td> + %else: + <td >${v}${extra}</td> + %endif + </td> + %endfor + %endif + %endfor + ## Actions column + <td> + <div popupmenu="grid-${i}-popup"> + %for operation in grid.operations: + %if operation.allowed( item ): + <a class="action-button" href="${url( operation=operation.label, id=item.id )}">${operation.label}</a> + %endif + %endfor + </div> + </td> + </tr> + %endfor + </tbody> +## <tfoot> +## <tr> +## <td></td> +## <td colspan="100"> +## For <span class="grid-selected-count"></span> selected requests: +## %for operation in grid.operations: +## %if operation.allow_multiple: +## <input type="submit" name="operation" value="${operation.label}" class="action-button"> +## %endif +## %endfor +## </td> +## </tr> +## </tfoot> + </table> +</form> +%endif \ No newline at end of file diff -r 267db48a2371 -r b46f27137744 templates/admin/requests/manage_request_types.mako --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/templates/admin/requests/manage_request_types.mako Fri Jul 10 11:37:28 2009 -0400 @@ -0,0 +1,60 @@ +<%inherit file="/base.mako"/> +<%namespace file="/message.mako" import="render_msg" /> + +<%def name="title()">request Types</%def> + +<h2> + %if deleted: + Deleted + %endif + Request Types +</h2> + +<ul class="manage-table-actions"> + <li> + <a class="action-button" href="${h.url_for( controller='admin', action='request_type', create=True )}"><span>Create a new request type</span></a> + </li> +</ul> + +%if msg: + ${render_msg( msg, messagetype )} +%endif + +%if not request_types: + %if deleted: + There are no deleted request types + %else: + There are no request types. + %endif +%else: + <table class="grid"> + <thead> + <tr> + <th>Name</th> + <th>Description</th> + <th>Request Form</th> + <th>Sample Form</th> + </tr> + </thead> + <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><i>${request_type.desc}</i></td> + <% for form in forms: + if form.id == request_type.request_form_id: + form_name = form.name + break + %> + <td><a href="${h.url_for( controller='forms', action='edit', form_id=request_type.request_form_id, read_only=True)}">${form_name}</a></td> + <% for form in forms: + if form.id == request_type.sample_form_id: + form_name = form.name + break + %> + <td><a href="${h.url_for( controller='forms', action='edit', form_id=request_type.sample_form_id, read_only=True)}">${form_name}</a></td> + </tr> + %endfor + </tbody> + </table> +%endif \ No newline at end of file diff -r 267db48a2371 -r b46f27137744 templates/admin/requests/view_request.mako --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/templates/admin/requests/view_request.mako Fri Jul 10 11:37:28 2009 -0400 @@ -0,0 +1,20 @@ +<%inherit file="/base.mako"/> +<%namespace file="/message.mako" import="render_msg" /> + + +%if msg: + ${render_msg( msg, messagetype )} +%endif + +<div class="toolForm"> + <div class="toolFormTitle">Request Details: '${request_details[0]['value']}'</div> + %for index, rd in enumerate(request_details): + <div class="form-row"> + <label>${rd['label']}</label> + ##<i>${rd['helptext']}</i> + ${rd['value']} + </div> + <div style="clear: both"></div> + %endfor + </div> +</div> \ No newline at end of file diff -r 267db48a2371 -r b46f27137744 templates/admin/samples/change_state.mako --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/templates/admin/samples/change_state.mako Fri Jul 10 11:37:28 2009 -0400 @@ -0,0 +1,30 @@ +<%inherit file="/base.mako"/> +<%namespace file="/message.mako" import="render_msg" /> + + +%if msg: + ${render_msg( msg, messagetype )} +%endif +<div class="toolForm"> + <div class="toolFormTitle">${title}</div> + <div class="toolFormBody"> + <form name="event" action="${h.url_for( controller='requests_admin', action='save_state', new=True, sample_id_list=sample_id_list)}" method="post" > + %for w in widgets: + <div class="form-row"> + <label> + ${w[0]} + </label> + ${w[1].get_html()} + %if w[0] == 'Comments': + <div class="toolParamHelp" style="clear: both;"> + Optional + </div> + %endif + </div> + %endfor + <div class="form-row"> + <input type="submit" name="add_event" value="Save"/> + </div> + </form> + </div> +</div> \ No newline at end of file diff -r 267db48a2371 -r b46f27137744 templates/admin/samples/edit_sample.mako --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/templates/admin/samples/edit_sample.mako Fri Jul 10 11:37:28 2009 -0400 @@ -0,0 +1,83 @@ +<%inherit file="/base.mako"/> +<%namespace file="/message.mako" import="render_msg" /> + + +%if msg: + ${render_msg( msg, messagetype )} +%endif + +<div class="toolForm"> + <div class="toolFormTitle">Edit sample named: ${values.content['Name']}</div> + <div class="toolFormBody"> + <form name="sample" action="${h.url_for( controller='sample', action='do', save_changes=True, sample_id=sample.id )}" method="post" > + <div class="form-row"> + <label> + Library: + </label> + <select name="library_id"> + %for library in libraries: + <option value="${library.id}">${library.name}</option> + %endfor + </select> + </div> + %for i, field in enumerate(form.fields): + <div class="form-row"> + <label>${field['label']}</label> + %if field['type'] == 'TextField': + <input type="text" name="${field['label']}" value="${values.content[field['label']]}" size="40"/> + %elif field['type'] == 'TextArea': + <textarea name="${field['label']}" rows="3" cols="35">${values.content[field['label']]}</textarea> + %elif field['type'] == 'CheckBox': + %if values.content[field['label']] == "true": + <input type="checkbox" name="${field['label']}" value="true" checked> + %else: + <input type="checkbox" name="${field['label']}" value="true"> + %endif + %elif field['type'] == 'SelectBox': + <select name="${field['label']}"> + %for ft in field['selectlist']: + %if ft == values.content[field['label']]: + <option value="${ft}" selected>${ft}</option> + %else: + <option value="${ft}">${ft}</option> + %endif + %endfor + </select> + %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="new" value="submitted" size="40"/> + </div> + <div style="clear: both"></div> + </div> + <div class="form-row"> + <input type="submit" name="create_library_button" value="Save"/> + </div> + </form> + </div> +</div> +<div class="toolForm"> + <div class="toolFormBody"> + <form name="event" action="${h.url_for( controller='admin', action='event', new=True, sample_id=sample.id)}" method="post" > + <div class="form-row"> + <label> + Change sample state to: + </label> + <select name="state_id"> + %for state in states: + <option value="${state.id}">${state.name}</option> + %endfor + </select> + </div> + <div class="form-row"> + <input type="submit" name="add_event" value="Save"/> + </div> + </form> + </div> +</div> \ No newline at end of file diff -r 267db48a2371 -r b46f27137744 templates/admin/samples/events.mako --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/templates/admin/samples/events.mako Fri Jul 10 11:37:28 2009 -0400 @@ -0,0 +1,33 @@ +<%inherit file="/base.mako"/> +<%namespace file="/message.mako" import="render_msg" /> + +<%def name="title()">Events for Sample ${sample_name}</%def> + +<h2>Events for Sample "${sample_name}" of Request: ${request}</h2> +<h3>User: ${user.email}</h3> + +%if msg: + ${render_msg( msg, messagetype )} +%endif + + +<table class="grid"> + <thead> + <tr> + <th>State</th> + <th>Description</th> + <th>Last Update</th> + <th>Comments</th> + </tr> + </thead> + <tbody> + %for state, desc, updated, comments in events_list: + <tr class="libraryRow libraryOrFolderRow" id="libraryRow"> + <td><b><a>${state}</a></b></td> + <td><a>${desc}</a></td> + <td><a>${updated}</a></td> + <td><a>${comments}</a></td> + </tr> + %endfor + </tbody> +</table> \ No newline at end of file diff -r 267db48a2371 -r b46f27137744 templates/admin/samples/grid.mako --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/templates/admin/samples/grid.mako Fri Jul 10 11:37:28 2009 -0400 @@ -0,0 +1,203 @@ +<%inherit file="/base.mako"/> +<%namespace file="/message.mako" import="render_msg" /> + +<%def name="title()">Browse Samples</%def> + +%if message: + <p> + <div class="${message_type}message transient-message">${message}</div> + <div style="clear: both"></div> + </p> +%endif + +<%def name="javascripts()"> + ${parent.javascripts()} + <script type="text/javascript"> + ## TODO: generalize and move into galaxy.base.js + $(document).ready(function() { + $(".grid").each( function() { + var grid = this; + var checkboxes = $(this).find("input.grid-row-select-checkbox"); + var update = $(this).find( "span.grid-selected-count" ); + $(checkboxes).each( function() { + $(this).change( function() { + var n = $(checkboxes).filter("[checked]").size(); + update.text( n ); + }); + }) + }); + }); + ## Can this be moved into base.mako? + %if refresh_frames: + %if 'masthead' in refresh_frames: + ## Refresh masthead == user changes (backward compatibility) + if ( parent.user_changed ) { + %if trans.user: + parent.user_changed( "${trans.user.email}", ${int( app.config.is_admin_user( trans.user ) )} ); + %else: + parent.user_changed( null, false ); + %endif + } + %endif + %if 'history' in refresh_frames: + if ( parent.frames && parent.frames.galaxy_history ) { + parent.frames.galaxy_history.location.href="${h.url_for( controller='root', action='history')}"; + if ( parent.force_right_panel ) { + parent.force_right_panel( 'show' ); + } + } + %endif + %if 'tools' in refresh_frames: + if ( parent.frames && parent.frames.galaxy_tools ) { + parent.frames.galaxy_tools.location.href="${h.url_for( controller='root', action='tool_menu')}"; + if ( parent.force_left_panel ) { + parent.force_left_panel( 'show' ); + } + } + %endif + %endif + </script> +</%def> + +<%def name="stylesheets()"> + <link href="${h.url_for('/static/style/base.css')}" rel="stylesheet" type="text/css" /> + <style> + ## Not generic to all grids -- move to base? + .count-box { + min-width: 1.1em; + padding: 5px; + border-width: 1px; + border-style: solid; + text-align: center; + display: inline-block; + } + </style> +</%def> + +<div class="grid-header"> + <h2>Samples associated with request: ${grid.request.name}</h2> + <h3>User: ${grid.user.email}</h3> +## %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 +</div> + +%if not len(query.all()): + There are no sample(s). +%else: +<form name="history_actions" action="${url()}" method="post" > + <table class="grid"> + <thead> + <tr> + <th></th> + %for column in grid.columns: + %if column.visible: + <% + href = "" + extra = "" + if column.sortable: + if sort_key == column.key: + if sort_order == "asc": + href = url( sort=( "-" + column.key ) ) + extra = "↓" + else: + href = url( sort=( column.key ) ) + extra = "↑" + else: + href = url( sort=column.key ) + %> + <th\ + %if column.ncells > 1: + colspan="${column.ncells}" + %endif + > + %if href: + <a href="${href}">${column.label}</a> + %else: + ${column.label} + %endif + <span>${extra}</span> + </th> + %endif + %endfor + <th></th> + </tr> + </thead> + <tbody> + %for i, item in enumerate( query ): + <tr \ + %if current_item == item: + class="current" \ + %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> + ## Data columns + %for column in grid.columns: + %if column.visible: + <% + # Link + if column.link and column.link( item ): + href = url( **column.link( item ) ) + else: + href = None + # Value (coerced to list so we can loop) + value = column.get_value( trans, grid, item ) + if column.ncells == 1: + value = [ value ] + %> + %for cellnum, v in enumerate( value ): + <% + # Attach popup menu? + if column.attach_popup and cellnum == 0: + extra = '<a id="grid-%d-popup" class="popup-arrow" style="display: none;">▼</a>' % i + else: + extra = "" + %> + %if href: + <td><a href="${href}">${v}</a> ${extra}</td> + %else: + <td >${v}${extra}</td> + %endif + </td> + %endfor + %endif + %endfor + ## Actions column + <td> + <div popupmenu="grid-${i}-popup"> + %for operation in grid.operations: + %if operation.allowed( item ): + <a class="action-button" href="${url( operation=operation.label, id=item.id )}">${operation.label}</a> + %endif + %endfor + </div> + </td> + </tr> + %endfor + </tbody> + <tfoot> + <tr> + <td></td> + <td colspan="100"> + For <span class="grid-selected-count"></span> selected requests: + %for operation in grid.operations: + %if operation.allow_multiple: + <input type="submit" name="operation" value="${operation.label}" class="action-button"> + %endif + %endfor + </td> + </tr> + </tfoot> + </table> +</form> + +%endif diff -r 267db48a2371 -r b46f27137744 templates/admin/samples/view_sample.mako --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/templates/admin/samples/view_sample.mako Fri Jul 10 11:37:28 2009 -0400 @@ -0,0 +1,19 @@ +<%inherit file="/base.mako"/> +<%namespace file="/message.mako" import="render_msg" /> + + +%if msg: + ${render_msg( msg, messagetype )} +%endif + +<div class="toolForm"> + <div class="toolFormTitle">Sample Details: '${sample_details[0]['value']}'</div> + %for index, rd in enumerate(sample_details): + <div class="form-row"> + <label>${rd['label']}</label> + ${rd['value']} + </div> + <div style="clear: both"></div> + %endfor + </div> +</div> diff -r 267db48a2371 -r b46f27137744 templates/base.mako --- a/templates/base.mako Thu Jul 09 15:49:26 2009 -0400 +++ b/templates/base.mako Fri Jul 10 11:37:28 2009 -0400 @@ -29,4 +29,33 @@ ## <![endif]--> <script type="text/javascript" src="${h.url_for('/static/scripts/jquery.js')}"></script> <script type="text/javascript" src="${h.url_for('/static/scripts/galaxy.base.js')}"></script> + + </%def> + +<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 ){ + $( ':file' ).each( function() { + var file_value = $( this )[0].value; + } ); + $( "#edit_form" ).submit(); + } + }); +}); \ No newline at end of file diff -r 267db48a2371 -r b46f27137744 templates/base_panels.mako --- a/templates/base_panels.mako Thu Jul 09 15:49:26 2009 -0400 +++ b/templates/base_panels.mako Fri Jul 10 11:37:28 2009 -0400 @@ -153,6 +153,8 @@ ${tab( "workflow", "Workflow", h.url_for( controller='workflow', action='index' ))} ${tab( "libraries", "Libraries", h.url_for( controller='library', action='index' ))} + + ${tab( "requests", "Requests", h.url_for( controller='requests', action='index' ), visible = (trans.user and trans.request_types)) } %if app.config.get_bool( 'enable_tracks', False ): <span class="tab"> diff -r 267db48a2371 -r b46f27137744 templates/requests/grid.mako --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/templates/requests/grid.mako Fri Jul 10 11:37:28 2009 -0400 @@ -0,0 +1,210 @@ +<%inherit file="/base.mako"/> +<%namespace file="/message.mako" import="render_msg" /> + +<%def name="title()">Browse Samples</%def> + +%if message: + <p> + <div class="${message_type}message transient-message">${message}</div> + <div style="clear: both"></div> + </p> +%endif + +<%def name="javascripts()"> + ${parent.javascripts()} + <script type="text/javascript"> + ## TODO: generalize and move into galaxy.base.js + $(document).ready(function() { + $(".grid").each( function() { + var grid = this; + var checkboxes = $(this).find("input.grid-row-select-checkbox"); + var update = $(this).find( "span.grid-selected-count" ); + $(checkboxes).each( function() { + $(this).change( function() { + var n = $(checkboxes).filter("[checked]").size(); + update.text( n ); + }); + }) + }); + }); + ## Can this be moved into base.mako? + %if refresh_frames: + %if 'masthead' in refresh_frames: + ## Refresh masthead == user changes (backward compatibility) + if ( parent.user_changed ) { + %if trans.user: + parent.user_changed( "${trans.user.email}", ${int( app.config.is_admin_user( trans.user ) )} ); + %else: + parent.user_changed( null, false ); + %endif + } + %endif + %if 'history' in refresh_frames: + if ( parent.frames && parent.frames.galaxy_history ) { + parent.frames.galaxy_history.location.href="${h.url_for( controller='root', action='history')}"; + if ( parent.force_right_panel ) { + parent.force_right_panel( 'show' ); + } + } + %endif + %if 'tools' in refresh_frames: + if ( parent.frames && parent.frames.galaxy_tools ) { + parent.frames.galaxy_tools.location.href="${h.url_for( controller='root', action='tool_menu')}"; + if ( parent.force_left_panel ) { + parent.force_left_panel( 'show' ); + } + } + %endif + %endif + </script> +</%def> + +<%def name="stylesheets()">