"""
Classes for generating HTML forms
"""
import logging, sys, os, time
from operator import itemgetter
from cgi import escape
from galaxy.util import restore_text, relpath, nice_size, unicodify
from galaxy.util.json import dumps
from galaxy.web import url_for
from binascii import hexlify
log = logging.getLogger(__name__)
[docs]class BaseField(object):
[docs] def get_html( self, prefix="" ):
"""Returns the html widget corresponding to the parameter"""
raise TypeError( "Abstract Method" )
[docs] def get_disabled_str( self, disabled=False ):
if disabled:
return ' disabled="disabled"'
else:
return ''
[docs]class TextField(BaseField):
"""
A standard text input box.
>>> print TextField( "foo" ).get_html()
<input type="text" name="foo" size="10" value="">
>>> print TextField( "bins", size=4, value="default" ).get_html()
<input type="text" name="bins" size="4" value="default">
"""
def __init__( self, name, size=None, value=None ):
self.name = name
self.size = int( size or 10 )
self.value = value or ""
[docs] def get_html( self, prefix="", disabled=False ):
value = self.value
if not isinstance( value, basestring ):
value = str( value )
value = unicodify( value )
return unicodify( '<input type="text" name="%s%s" size="%d" value="%s"%s>' \
% ( prefix, self.name, self.size, escape( value, quote=True ), self.get_disabled_str( disabled ) ) )
[docs] def set_size(self, size):
self.size = int( size )
[docs]class PasswordField(BaseField):
"""
A password input box. text appears as "******"
>>> print PasswordField( "foo" ).get_html()
<input type="password" name="foo" size="10" value="">
>>> print PasswordField( "bins", size=4, value="default" ).get_html()
<input type="password" name="bins" size="4" value="default">
"""
def __init__( self, name, size=None, value=None ):
self.name = name
self.size = int( size or 10 )
self.value = value or ""
[docs] def get_html( self, prefix="", disabled=False ):
return unicodify( '<input type="password" name="%s%s" size="%d" value="%s"%s>' \
% ( prefix, self.name, self.size, escape( str( self.value ), quote=True ), self.get_disabled_str( disabled ) ) )
[docs] def set_size(self, size):
self.size = int( size )
[docs]class TextArea(BaseField):
"""
A standard text area box.
>>> print TextArea( "foo" ).get_html()
<textarea name="foo" rows="5" cols="25"></textarea>
>>> print TextArea( "bins", size="4x5", value="default" ).get_html()
<textarea name="bins" rows="4" cols="5">default</textarea>
"""
_DEFAULT_SIZE = "5x25"
def __init__( self, name, size=None, value=None ):
self.name = name
size = size or self._DEFAULT_SIZE
self.size = size.split("x")
self.rows = int(self.size[0])
self.cols = int(self.size[-1])
self.value = value or ""
[docs] def get_html( self, prefix="", disabled=False ):
return unicodify( '<textarea name="%s%s" rows="%d" cols="%d"%s>%s</textarea>' \
% ( prefix, self.name, self.rows, self.cols, self.get_disabled_str( disabled ), escape( str( self.value ), quote=True ) ) )
[docs] def set_size(self, rows, cols):
self.rows = rows
self.cols = cols
[docs]class CheckboxField(BaseField):
"""
A checkbox (boolean input)
>>> print CheckboxField( "foo" ).get_html()
<input type="checkbox" id="foo" name="foo" value="true"><input type="hidden" name="foo" value="true">
>>> print CheckboxField( "bar", checked="yes" ).get_html()
<input type="checkbox" id="bar" name="bar" value="true" checked="checked"><input type="hidden" name="bar" value="true">
"""
def __init__( self, name, checked=None, refresh_on_change = False, refresh_on_change_values = None ):
self.name = name
self.checked = ( checked == True ) or ( isinstance( checked, basestring ) and ( checked.lower() in ( "yes", "true", "on" ) ) )
self.refresh_on_change = refresh_on_change
self.refresh_on_change_values = refresh_on_change_values or []
if self.refresh_on_change:
self.refresh_on_change_text = ' refresh_on_change="true" '
if self.refresh_on_change_values:
self.refresh_on_change_text = '%s refresh_on_change_values="%s" ' % ( self.refresh_on_change_text, ",".join( self.refresh_on_change_values ) )
else:
self.refresh_on_change_text = ''
[docs] def get_html( self, prefix="", disabled=False ):
if self.checked:
checked_text = ' checked="checked"'
else:
checked_text = ""
id_name = prefix + self.name
# The hidden field is necessary because if the check box is not checked on the form, it will
# not be included in the request params. The hidden field ensure that this will happen. When
# parsing the request, the value 'true' in the hidden field actually means it is NOT checked.
# See the is_checked() method below. The prefix is necessary in each case to ensure functional
# correctness when the param is inside a conditional.
return unicodify( '<input type="checkbox" id="%s" name="%s" value="true"%s%s%s><input type="hidden" name="%s%s" value="true"%s>' \
% ( id_name, id_name, checked_text, self.get_disabled_str( disabled ), self.refresh_on_change_text, prefix, self.name, self.get_disabled_str( disabled ) ) )
@staticmethod
[docs] def is_checked( value ):
if value == True:
return True
# This may look strange upon initial inspection, but see the comments in the get_html() method
# above for clarification. Basically, if value is not True, then it will always be a list with
# 2 input fields ( a checkbox and a hidden field ) if the checkbox is checked. If it is not
# checked, then value will be only the hidden field.
return isinstance( value, list ) and len( value ) == 2
[docs] def set_checked(self, value):
if isinstance( value, basestring ):
self.checked = value.lower() in [ "yes", "true", "on" ]
else:
self.checked = value
[docs]class FileField(BaseField):
"""
A file upload input.
>>> print FileField( "foo" ).get_html()
<input type="file" name="foo">
>>> print FileField( "foo", ajax = True ).get_html()
<input type="file" name="foo" galaxy-ajax-upload="true">
"""
def __init__( self, name, value = None, ajax=False ):
self.name = name
self.ajax = ajax
self.value = value
[docs] def get_html( self, prefix="" ):
value_text = ""
if self.value:
value_text = ' value="%s"' % escape( str( self.value ), quote=True )
ajax_text = ""
if self.ajax:
ajax_text = ' galaxy-ajax-upload="true"'
return unicodify( '<input type="file" name="%s%s"%s%s>' % ( prefix, self.name, ajax_text, value_text ) )
[docs]class FTPFileField(BaseField):
"""
An FTP file upload input.
"""
thead = '''
<table id="grid-table" class="grid">
<thead id="grid-table-header">
<tr>
<th id="select-header"></th>
<th id="name-header">
File
</th>
<th id="size-header">
Size
</th>
<th id="date-header">
Date
</th>
</tr>
</thead>
<tbody id="grid-table-body">
'''
trow = '''
<tr>
<td><input type="checkbox" name="%s%s" value="%s"/></td>
<td>%s</td>
<td>%s</td>
<td>%s</td>
</tr>
'''
tfoot = '''
</tbody>
</table>
'''
def __init__( self, name, dir, ftp_site, value = None ):
self.name = name
self.dir = dir
self.ftp_site = ftp_site
self.value = value
[docs] def get_html( self, prefix="" ):
rval = FTPFileField.thead
if self.dir is None:
rval += '<tr><td colspan="4"><em>Please <a href="%s">create</a> or <a href="%s">log in to</a> a Galaxy account to view files uploaded via FTP.</em></td></tr>' % ( url_for( controller='user', action='create', cntrller='user', referer=url_for( controller='root' ) ), url_for( controller='user', action='login', cntrller='user', referer=url_for( controller='root' ) ) )
elif not os.path.exists( self.dir ):
rval += '<tr><td colspan="4"><em>Your FTP upload directory contains no files.</em></td></tr>'
else:
uploads = []
for ( dirpath, dirnames, filenames ) in os.walk( self.dir ):
for filename in filenames:
path = relpath( os.path.join( dirpath, filename ), self.dir )
statinfo = os.lstat( os.path.join( dirpath, filename ) )
uploads.append( dict( path=path,
size=nice_size( statinfo.st_size ),
ctime=time.strftime( "%m/%d/%Y %I:%M:%S %p", time.localtime( statinfo.st_ctime ) ) ) )
if not uploads:
rval += '<tr><td colspan="4"><em>Your FTP upload directory contains no files.</em></td></tr>'
uploads = sorted(uploads, key=itemgetter("path"))
for upload in uploads:
rval += FTPFileField.trow % ( prefix, self.name, upload['path'], upload['path'], upload['size'], upload['ctime'] )
rval += FTPFileField.tfoot
rval += '<div class="toolParamHelp">This Galaxy server allows you to upload files via FTP. To upload some files, log in to the FTP server at <strong>%s</strong> using your Galaxy credentials (email address and password).</div>' % self.ftp_site
return rval
[docs]class HiddenField(BaseField):
"""
A hidden field.
>>> print HiddenField( "foo", 100 ).get_html()
<input type="hidden" name="foo" value="100">
"""
def __init__( self, name, value=None ):
self.name = name
self.value = value or ""
[docs] def get_html( self, prefix="" ):
return unicodify( '<input type="hidden" name="%s%s" value="%s">' % ( prefix, self.name, escape( str( self.value ), quote=True ) ) )
[docs]class SelectField(BaseField):
"""
A select field.
>>> t = SelectField( "foo", multiple=True )
>>> t.add_option( "tuti", 1 )
>>> t.add_option( "fruity", "x" )
>>> print t.get_html()
<select name="foo" multiple>
<option value="1">tuti</option>
<option value="x">fruity</option>
</select>
>>> t = SelectField( "bar" )
>>> t.add_option( "automatic", 3 )
>>> t.add_option( "bazooty", 4, selected=True )
>>> print t.get_html()
<select name="bar" last_selected_value="4">
<option value="3">automatic</option>
<option value="4" selected>bazooty</option>
</select>
>>> t = SelectField( "foo", display="radio" )
>>> t.add_option( "tuti", 1 )
>>> t.add_option( "fruity", "x" )
>>> print t.get_html()
<div><input type="radio" name="foo" value="1" id="foo|1"><label class="inline" for="foo|1">tuti</label></div>
<div><input type="radio" name="foo" value="x" id="foo|x"><label class="inline" for="foo|x">fruity</label></div>
>>> t = SelectField( "bar", multiple=True, display="checkboxes" )
>>> t.add_option( "automatic", 3 )
>>> t.add_option( "bazooty", 4, selected=True )
>>> print t.get_html()
<div class="checkUncheckAllPlaceholder" checkbox_name="bar"></div>
<div><input type="checkbox" name="bar" value="3" id="bar|3"><label class="inline" for="bar|3">automatic</label></div>
<div><input type="checkbox" name="bar" value="4" id="bar|4" checked='checked'><label class="inline" for="bar|4">bazooty</label></div>
"""
def __init__( self, name, multiple=None, display=None, refresh_on_change=False, refresh_on_change_values=None, size=None ):
self.name = name
self.multiple = multiple or False
self.size = size
self.options = list()
if display == "checkboxes":
assert multiple, "Checkbox display only supported for multiple select"
elif display == "radio":
assert not( multiple ), "Radio display only supported for single select"
elif display is not None:
raise Exception, "Unknown display type: %s" % display
self.display = display
self.refresh_on_change = refresh_on_change
self.refresh_on_change_values = refresh_on_change_values or []
if self.refresh_on_change:
self.refresh_on_change_text = ' refresh_on_change="true"'
if self.refresh_on_change_values:
self.refresh_on_change_text = '%s refresh_on_change_values="%s"' % ( self.refresh_on_change_text, escape( ",".join( self.refresh_on_change_values ), quote=True ) )
else:
self.refresh_on_change_text = ''
[docs] def add_option( self, text, value, selected = False ):
self.options.append( ( text, value, selected ) )
[docs] def get_html( self, prefix="", disabled=False ):
if self.display == "checkboxes":
return self.get_html_checkboxes( prefix, disabled )
elif self.display == "radio":
return self.get_html_radio( prefix, disabled )
else:
return self.get_html_default( prefix, disabled )
[docs] def get_html_checkboxes( self, prefix="", disabled=False ):
rval = []
ctr = 0
if len( self.options ) > 1:
rval.append ( '<div class="checkUncheckAllPlaceholder" checkbox_name="%s%s"></div>' % ( prefix, self.name ) ) #placeholder for the insertion of the Select All/Unselect All buttons
for text, value, selected in self.options:
style = ""
if not isinstance( value, basestring ):
value = str( value )
if not isinstance( text, basestring ):
text = str( text )
text = unicodify( text )
escaped_value = escape( unicodify( value ), quote=True )
uniq_id = "%s%s|%s" % (prefix, self.name, escaped_value)
if len(self.options) > 2 and ctr % 2 == 1:
style = " class=\"odd_row\""
selected_text = ""
if selected:
selected_text = " checked='checked'"
rval.append( '<div%s><input type="checkbox" name="%s%s" value="%s" id="%s"%s%s><label class="inline" for="%s">%s</label></div>' % \
( style, prefix, self.name, escaped_value, uniq_id, selected_text, self.get_disabled_str( disabled ), uniq_id, escape( text, quote=True ) ) )
ctr += 1
return unicodify( "\n".join( rval ) )
[docs] def get_html_radio( self, prefix="", disabled=False ):
rval = []
ctr = 0
for text, value, selected in self.options:
style = ""
escaped_value = escape( str( value ), quote=True )
uniq_id = "%s%s|%s" % (prefix, self.name, escaped_value)
if len(self.options) > 2 and ctr % 2 == 1:
style = " class=\"odd_row\""
selected_text = ""
if selected:
selected_text = " checked='checked'"
rval.append( '<div%s><input type="radio" name="%s%s"%s value="%s" id="%s"%s%s><label class="inline" for="%s">%s</label></div>' % \
( style,
prefix,
self.name,
self.refresh_on_change_text,
escaped_value,
uniq_id,
selected_text,
self.get_disabled_str( disabled ),
uniq_id,
text ) )
ctr += 1
return unicodify( "\n".join( rval ) )
[docs] def get_html_default( self, prefix="", disabled=False ):
if self.multiple:
multiple = " multiple"
else:
multiple = ""
if self.size:
size = ' size="%s"' % str( self.size )
else:
size = ''
rval = []
last_selected_value = ""
for text, value, selected in self.options:
if selected:
selected_text = " selected"
last_selected_value = value
if not isinstance( last_selected_value, basestring ):
last_selected_value = str( last_selected_value )
else:
selected_text = ""
if not isinstance( value, basestring ):
value = str( value )
if not isinstance( text, basestring ):
text = str( text )
rval.append( '<option value="%s"%s>%s</option>' % ( escape( unicodify( value ), quote=True ), selected_text, escape( unicodify( text ), quote=True ) ) )
if last_selected_value:
last_selected_value = ' last_selected_value="%s"' % escape( unicodify( last_selected_value ), quote=True )
rval.insert( 0, '<select name="%s%s"%s%s%s%s%s>' % \
( prefix, self.name, multiple, size, self.refresh_on_change_text, last_selected_value, self.get_disabled_str( disabled ) ) )
rval.append( '</select>' )
return unicodify( "\n".join( rval ) )
[docs] def get_selected( self, return_label=False, return_value=False, multi=False ):
'''
Return the currently selected option's label, value or both as a tuple. For
multi-select lists, a list is returned.
'''
if multi:
selected_options = []
for label, value, selected in self.options:
if selected:
if return_label and return_value:
if multi:
selected_options.append( ( label, value ) )
else:
return ( label, value )
elif return_label:
if multi:
selected_options.append( label )
else:
return label
elif return_value:
if multi:
selected_options.append( value )
else:
return value
if multi:
return selected_options
return None
[docs] def to_dict( self ):
return dict(
name=self.name,
multiple=self.multiple,
options=self.options
)
[docs]class DrillDownField( BaseField ):
"""
A hierarchical select field, which allows users to 'drill down' a tree-like set of options.
>>> t = DrillDownField( "foo", multiple=True, display="checkbox", options=[{'name': 'Heading 1', 'value': 'heading1', 'options': [{'name': 'Option 1', 'value': 'option1', 'options': []}, {'name': 'Option 2', 'value': 'option2', 'options': []}, {'name': 'Heading 1', 'value': 'heading1', 'options': [{'name': 'Option 3', 'value': 'option3', 'options': []}, {'name': 'Option 4', 'value': 'option4', 'options': []}]}]}, {'name': 'Option 5', 'value': 'option5', 'options': []}] )
>>> print t.get_html()
<div class="form-row drilldown-container" id="drilldown--666f6f">
<div class="form-row-input">
<div><span class="form-toggle icon-button toggle-expand" id="drilldown--666f6f-68656164696e6731-click"></span>
<input type="checkbox" name="foo" value="heading1" >Heading 1
</div><div class="form-row" id="drilldown--666f6f-68656164696e6731-container" style="float: left; margin-left: 1em;">
<div class="form-row-input">
<input type="checkbox" name="foo" value="option1" >Option 1
</div>
<div class="form-row-input">
<input type="checkbox" name="foo" value="option2" >Option 2
</div>
<div class="form-row-input">
<div><span class="form-toggle icon-button toggle-expand" id="drilldown--666f6f-68656164696e6731-68656164696e6731-click"></span>
<input type="checkbox" name="foo" value="heading1" >Heading 1
</div><div class="form-row" id="drilldown--666f6f-68656164696e6731-68656164696e6731-container" style="float: left; margin-left: 1em;">
<div class="form-row-input">
<input type="checkbox" name="foo" value="option3" >Option 3
</div>
<div class="form-row-input">
<input type="checkbox" name="foo" value="option4" >Option 4
</div>
</div>
</div>
</div>
</div>
<div class="form-row-input">
<input type="checkbox" name="foo" value="option5" >Option 5
</div>
</div>
>>> t = DrillDownField( "foo", multiple=False, display="radio", options=[{'name': 'Heading 1', 'value': 'heading1', 'options': [{'name': 'Option 1', 'value': 'option1', 'options': []}, {'name': 'Option 2', 'value': 'option2', 'options': []}, {'name': 'Heading 1', 'value': 'heading1', 'options': [{'name': 'Option 3', 'value': 'option3', 'options': []}, {'name': 'Option 4', 'value': 'option4', 'options': []}]}]}, {'name': 'Option 5', 'value': 'option5', 'options': []}] )
>>> print t.get_html()
<div class="form-row drilldown-container" id="drilldown--666f6f">
<div class="form-row-input">
<div><span class="form-toggle icon-button toggle-expand" id="drilldown--666f6f-68656164696e6731-click"></span>
<input type="radio" name="foo" value="heading1" >Heading 1
</div><div class="form-row" id="drilldown--666f6f-68656164696e6731-container" style="float: left; margin-left: 1em;">
<div class="form-row-input">
<input type="radio" name="foo" value="option1" >Option 1
</div>
<div class="form-row-input">
<input type="radio" name="foo" value="option2" >Option 2
</div>
<div class="form-row-input">
<div><span class="form-toggle icon-button toggle-expand" id="drilldown--666f6f-68656164696e6731-68656164696e6731-click"></span>
<input type="radio" name="foo" value="heading1" >Heading 1
</div><div class="form-row" id="drilldown--666f6f-68656164696e6731-68656164696e6731-container" style="float: left; margin-left: 1em;">
<div class="form-row-input">
<input type="radio" name="foo" value="option3" >Option 3
</div>
<div class="form-row-input">
<input type="radio" name="foo" value="option4" >Option 4
</div>
</div>
</div>
</div>
</div>
<div class="form-row-input">
<input type="radio" name="foo" value="option5" >Option 5
</div>
</div>
"""
def __init__( self, name, multiple=None, display=None, refresh_on_change=False, options = [], value = [], refresh_on_change_values = [] ):
self.name = name
self.multiple = multiple or False
self.options = options
if value and not isinstance( value, list ):
value = [ value ]
elif not value:
value = []
self.value = value
if display == "checkbox":
assert multiple, "Checkbox display only supported for multiple select"
elif display == "radio":
assert not( multiple ), "Radio display only supported for single select"
else:
raise Exception, "Unknown display type: %s" % display
self.display = display
self.refresh_on_change = refresh_on_change
self.refresh_on_change_values = refresh_on_change_values
if self.refresh_on_change:
self.refresh_on_change_text = ' refresh_on_change="true"'
if self.refresh_on_change_values:
self.refresh_on_change_text = '%s refresh_on_change_values="%s"' % ( self.refresh_on_change_text, ",".join( self.refresh_on_change_values ) )
else:
self.refresh_on_change_text = ''
[docs] def get_html( self, prefix="" ):
def find_expanded_options( expanded_options, options, parent_options = [] ):
for option in options:
if option['value'] in self.value:
expanded_options.extend( parent_options )
if option['options']:
new_parents = list( parent_options ) + [ option['value'] ]
find_expanded_options( expanded_options, option['options'], new_parents )
def recurse_options( html, options, base_id, expanded_options = [] ):
for option in options:
escaped_option_value = escape( str( option['value'] ), quote=True )
selected = ( option['value'] in self.value )
if selected:
selected = ' checked'
else:
selected = ''
span_class = 'form-toggle icon-button toggle'
if option['value'] not in expanded_options:
span_class = "%s-expand" % ( span_class )
html.append( '<div class="form-row-input">')
drilldown_group_id = "%s-%s" % ( base_id, hexlify( option['value'] ) )
if option['options']:
html.append( '<div><span class="%s" id="%s-click"></span>' % ( span_class, drilldown_group_id ) )
html.append( '<input type="%s" name="%s%s" value="%s" %s>%s' % ( self.display, prefix, self.name, escaped_option_value, selected, option['name']) )
if option['options']:
html.append( '</div><div class="form-row" id="%s-container" style="float: left; margin-left: 1em;">' % ( drilldown_group_id ) )
recurse_options( html, option['options'], drilldown_group_id, expanded_options )
html.append( '</div>')
html.append( '</div>')
drilldown_id = "drilldown-%s-%s" % ( hexlify( prefix ), hexlify( self.name ) )
rval = []
rval.append( '<div class="form-row drilldown-container" id="%s">' % ( drilldown_id ) )
expanded_options = []
find_expanded_options( expanded_options, self.options )
recurse_options( rval, self.options, drilldown_id, expanded_options )
rval.append( '</div>' )
return unicodify( '\n'.join( rval ) )
[docs]class SwitchingSelectField(BaseField):
def __init__( self, delegate_fields, default_field=None ):
self.delegate_fields = delegate_fields
self.default_field = default_field or delegate_fields.keys()[ 0 ]
@property
def primary_field( self ):
primary_field = self.delegate_fields[ self.delegate_fields.keys()[ 0 ] ]
return primary_field
[docs] def get_html( self, prefix="", disabled=False ):
primary_field = self.primary_field
html = '<div class="switch-option">'
html += primary_field.get_html( prefix=prefix, disabled=disabled )
html += '<input name="__switch_default__" type="hidden" value="%s" />' % self.default_field
options = []
for name, delegate_field in self.delegate_fields.items():
field = escape( dumps( delegate_field.to_dict() ) )
option = " '%s': %s" % ( name, field )
options.append( option )
html += '<script>$(document).ready( function() {\nvar switchOptions = {\n'
html += ','.join( options )
html += '};\n'
html += 'if ( window.enhanced_galaxy_tools ) {\n'
html += 'require( [ "galaxy.tools" ], function( mod_tools ) { new mod_tools.SwitchSelectView({\n'
html += 'el: $(\'[name="%s%s"]\').closest( "div.switch-option" ),' % ( prefix, primary_field.name )
html += 'default_option: "%s",\n' % self.default_field
html += 'prefix: "%s",\n' % prefix
html += 'switch_options: switchOptions }); } )\n'
html += "}"
html += '});\n</script></div>'
return html
[docs]class AddressField(BaseField):
@staticmethod
[docs] def fields():
return [ ( "short_desc", "Short address description", "Required" ),
( "name", "Name", "Required" ),
( "institution", "Institution", "Required" ),
( "address", "Address", "Required" ),
( "city", "City", "Required" ),
( "state", "State/Province/Region", "Required" ),
( "postal_code", "Postal Code", "Required" ),
( "country", "Country", "Required" ),
( "phone", "Phone", "" ) ]
def __init__(self, name, user=None, value=None, params=None):
self.name = name
self.user = user
self.value = value
self.select_address = None
self.params = params
[docs] def get_html( self, disabled=False ):
address_html = ''
add_ids = ['none']
if self.user:
for a in self.user.addresses:
add_ids.append( str( a.id ) )
add_ids.append( 'new' )
self.select_address = SelectField( self.name,
refresh_on_change=True,
refresh_on_change_values=add_ids )
if self.value == 'none':
self.select_address.add_option( 'Select one', 'none', selected=True )
else:
self.select_address.add_option( 'Select one', 'none' )
if self.user:
for a in self.user.addresses:
if not a.deleted:
if self.value == str( a.id ):
self.select_address.add_option( a.desc, str( a.id ), selected=True )
# Display this address
address_html += '''
<div class="form-row">
%s
</div>
''' % a.get_html()
else:
self.select_address.add_option( a.desc, str( a.id ) )
if self.value == 'new':
self.select_address.add_option( 'Add a new address', 'new', selected=True )
for field_name, label, help_text in self.fields():
add_field = TextField( self.name + '_' + field_name,
40,
restore_text( self.params.get( self.name + '_' + field_name, '' ) ) )
address_html += '''
<div class="form-row">
<label>%s</label>
%s
''' % ( label, add_field.get_html( disabled=disabled ) )
if help_text:
address_html += '''
<div class="toolParamHelp" style="clear: both;">
%s
</div>
''' % help_text
address_html += '''
</div>
'''
else:
self.select_address.add_option( 'Add a new address', 'new' )
return self.select_address.get_html( disabled=disabled ) + address_html
[docs]class WorkflowField( BaseField ):
def __init__( self, name, user=None, value=None, params=None ):
self.name = name
self.user = user
self.value = value
self.select_workflow = None
self.params = params
[docs] def get_html( self, disabled=False ):
self.select_workflow = SelectField( self.name )
if self.value == 'none':
self.select_workflow.add_option( 'Select one', 'none', selected=True )
else:
self.select_workflow.add_option( 'Select one', 'none' )
if self.user:
for a in self.user.stored_workflows:
if not a.deleted:
if str( self.value ) == str( a.id ):
self.select_workflow.add_option( a.name, str( a.id ), selected=True )
else:
self.select_workflow.add_option( a.name, str( a.id ) )
return self.select_workflow.get_html( disabled=disabled )
[docs]class WorkflowMappingField( BaseField):
def __init__( self, name, user=None, value=None, params=None, **kwd ):
# DBTODO integrate this with the new __build_workflow approach in requests_common. As it is, not particularly useful.
self.name = name
self.user = user
self.value = value
self.select_workflow = None
self.params = params
self.workflow_inputs = []
[docs] def get_html( self, disabled=False ):
self.select_workflow = SelectField( self.name, refresh_on_change = True )
workflow_inputs = []
if self.value == 'none':
self.select_workflow.add_option( 'Select one', 'none', selected=True )
else:
self.select_workflow.add_option( 'Select one', 'none' )
if self.user:
for a in self.user.stored_workflows:
if not a.deleted:
if str( self.value ) == str( a.id ):
self.select_workflow.add_option( a.name, str( a.id ), selected=True )
else:
self.select_workflow.add_option( a.name, str( a.id ) )
if self.value and self.value != 'none':
# Workflow selected. Find all inputs.
for workflow in self.user.stored_workflows:
if workflow.id == int(self.value):
for step in workflow.latest_workflow.steps:
if step.type == 'data_input':
if step.tool_inputs and "name" in step.tool_inputs:
workflow_inputs.append((step.tool_inputs['name'], TextField( '%s_%s' % (self.name, step.id), 20)))
# Do something more appropriate here and allow selection of inputs
return self.select_workflow.get_html( disabled=disabled ) + ''.join(['<div class="form-row"><label>%s</label>%s</div>' % (s[0], s[1].get_html()) for s in workflow_inputs])
[docs] def get_display_text(self):
if self.value:
return self.value
else:
return '-'
[docs]class HistoryField( BaseField ):
def __init__( self, name, user=None, value=None, params=None ):
self.name = name
self.user = user
self.value = value
self.select_history = None
self.params = params
[docs] def get_html( self, disabled=False ):
self.select_history = SelectField( self.name )
if self.value == 'none':
self.select_history.add_option( 'No Import', 'none', selected=True )
self.select_history.add_option( 'New History', 'new' )
else:
self.select_history.add_option( 'No Import', 'none' )
if self.value == 'new':
self.select_history.add_option( 'New History', 'new', selected=True )
else:
self.select_history.add_option( 'New History', 'new')
if self.user:
for a in self.user.histories:
if not a.deleted:
if str( self.value ) == str( a.id ):
self.select_history.add_option( a.name, str( a.id ), selected=True )
else:
self.select_history.add_option( a.name, str( a.id ) )
return self.select_history.get_html( disabled=disabled )
[docs] def get_display_text(self):
if self.value:
return self.value
else:
return '-'
[docs]class LibraryField( BaseField ):
def __init__( self, name, value=None, trans=None ):
self.name = name
self.lddas = value
self.trans = trans
[docs] def get_html( self, prefix="", disabled=False ):
if not self.lddas:
ldda_ids = ""
text = "Select library dataset(s)"
else:
ldda_ids = "||".join( [ self.trans.security.encode_id( ldda.id ) for ldda in self.lddas ] )
text = "<br />".join( [ "%s. %s" % (i+1, ldda.name) for i, ldda in enumerate(self.lddas)] )
return unicodify( '<a href="javascript:void(0);" class="add-librarydataset">%s</a> \
<input type="hidden" name="%s%s" value="%s">' % ( text, prefix, self.name, escape( str(ldda_ids), quote=True ) ) )
[docs] def get_display_text(self):
if self.ldda:
return self.ldda.name
else:
return 'None'
[docs]def get_suite():
"""Get unittest suite for this module"""
import doctest, sys
return doctest.DocTestSuite( sys.modules[__name__] )
# --------- Utility methods -----------------------------
[docs]def build_select_field( trans, objs, label_attr, select_field_name, initial_value='none',
selected_value='none', refresh_on_change=False, multiple=False, display=None, size=None ):
"""
Build a SelectField given a set of objects. The received params are:
- objs: the set of objects used to populate the option list
- label_attr: the attribute of each obj (e.g., name, email, etc ) whose value is used to populate each option label.
- If the string 'self' is passed as label_attr, each obj in objs is assumed to be a string, so the obj itself is used
- select_field_name: the name of the SelectField
- initial_value: the value of the first option in the SelectField - allows for an option telling the user to select something
- selected_value: the value of the currently selected option
- refresh_on_change: True if the SelectField should perform a refresh_on_change
"""
if initial_value == 'none':
values = [ initial_value ]
else:
values = []
for obj in objs:
if label_attr == 'self':
# Each obj is a string
values.append( obj )
else:
values.append( trans.security.encode_id( obj.id ) )
if refresh_on_change:
refresh_on_change_values = values
else:
refresh_on_change_values = []
select_field = SelectField( name=select_field_name,
multiple=multiple,
display=display,
refresh_on_change=refresh_on_change,
refresh_on_change_values=refresh_on_change_values,
size=size )
for obj in objs:
if label_attr == 'self':
# Each obj is a string
if str( selected_value ) == str( obj ):
select_field.add_option( obj, obj, selected=True )
else:
select_field.add_option( obj, obj )
else:
label = getattr( obj, label_attr )
if str( selected_value ) == str( obj.id ) or str( selected_value ) == trans.security.encode_id( obj.id ):
select_field.add_option( label, trans.security.encode_id( obj.id ), selected=True )
else:
select_field.add_option( label, trans.security.encode_id( obj.id ) )
return select_field