galaxy-commits
Threads by month
- ----- 2026 -----
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- 15302 discussions
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/65206cc6586c/
Changeset: 65206cc6586c
Branch: igv-local-dbkey
User: dannon
Date: 2014-09-12 19:14:24
Summary: Branch prune.
Affected #: 0 files
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: dannon: Merged in lance_parsons/galaxy-central-pull-requests/igv-local-dbkey (pull request #488)
by commits-noreply@bitbucket.org 12 Sep '14
by commits-noreply@bitbucket.org 12 Sep '14
12 Sep '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/f8465681a19d/
Changeset: f8465681a19d
User: dannon
Date: 2014-09-12 19:10:52
Summary: Merged in lance_parsons/galaxy-central-pull-requests/igv-local-dbkey (pull request #488)
Allow local IGV users to visualize custom genomes
Affected #: 2 files
diff -r 2346e098b27e0141fdd3e9821895413e27bc2c2f -r f8465681a19d189317fabebbc3c400c2418e8776 display_applications/igv/bam.xml
--- a/display_applications/igv/bam.xml
+++ b/display_applications/igv/bam.xml
@@ -12,15 +12,19 @@
<dynamic_param name="site_organisms" value="4" split="True" separator="," /><!-- Filter out some of the links based upon matching site_dbkeys to dataset dbkey -->
- <filter>${dataset.dbkey in $site_dbkeys}</filter>
-
+ <filter>${$site_id.startswith( 'local_' ) or $dataset.dbkey in $site_dbkeys}</filter>
+
<!-- We define url and params as normal, but values defined in dynamic_param are available by specified name --><url>${redirect_url}</url><param type="data" name="bam_file" url="galaxy_${DATASET_HASH}.bam" /><param type="data" name="bai_file" url="galaxy_${DATASET_HASH}.bam.bai" metadata="bam_index" /><param type="template" name="site_organism" strip="True" >
- $site_organisms[ $site_dbkeys.index( $bam_file.dbkey ) ]
+ #if ($dataset.dbkey in $site_dbkeys)
+ $site_organisms[ $site_dbkeys.index( $bam_file.dbkey ) ]
+ #else:
+ $bam_file.dbkey
+ #end if
</param><param type="template" name="jnlp" url="galaxy_${DATASET_HASH}.jnlp" viewable="True" mimetype="application/x-java-jnlp-file"><?xml version="1.0" encoding="utf-8"?>
diff -r 2346e098b27e0141fdd3e9821895413e27bc2c2f -r f8465681a19d189317fabebbc3c400c2418e8776 display_applications/igv/vcf.xml
--- a/display_applications/igv/vcf.xml
+++ b/display_applications/igv/vcf.xml
@@ -12,15 +12,19 @@
<dynamic_param name="site_organisms" value="4" split="True" separator="," /><!-- Filter out some of the links based upon matching site_dbkeys to dataset dbkey -->
- <filter>${dataset.dbkey in $site_dbkeys}</filter>
-
+ <filter>${$site_id.startswith( 'local_' ) or $dataset.dbkey in $site_dbkeys}</filter>
+
<!-- We define url and params as normal, but values defined in dynamic_param are available by specified name --><url>${redirect_url}</url><param type="data" name="bgzip_file" url="galaxy_${DATASET_HASH}.vcf.gz" format="vcf_bgzip" /><param type="data" name="tabix_file" dataset="bgzip_file" url="galaxy_${DATASET_HASH}.vcf.gz.tbi" format="tabix" /><param type="template" name="site_organism" strip="True" >
- $site_organisms[ $site_dbkeys.index( $bgzip_file.dbkey ) ]
+ #if ($dataset.dbkey in $site_dbkeys)
+ $site_organisms[ $site_dbkeys.index( $bgzip_file.dbkey ) ]
+ #else:
+ $bgzip_file.dbkey
+ #end if
</param><param type="template" name="jnlp" url="galaxy_${DATASET_HASH}.jnlp" viewable="True" mimetype="application/x-java-jnlp-file"><?xml version="1.0" encoding="utf-8"?>
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/4456e0cf7721/
Changeset: 4456e0cf7721
Branch: igv-local-dbkey
User: lance_parsons
Date: 2014-09-04 21:22:10
Summary: Allow local IGV users to visualize custom genomes
Affected #: 2 files
diff -r 9b6cccb3af2d6b13a1a1da7def87dcc19172be88 -r 4456e0cf7721386a728e9cb05ef7463bbd477d5b display_applications/igv/bam.xml
--- a/display_applications/igv/bam.xml
+++ b/display_applications/igv/bam.xml
@@ -12,15 +12,19 @@
<dynamic_param name="site_organisms" value="4" split="True" separator="," /><!-- Filter out some of the links based upon matching site_dbkeys to dataset dbkey -->
- <filter>${dataset.dbkey in $site_dbkeys}</filter>
-
+ <filter>${$site_id.startswith( 'local_' ) or $dataset.dbkey in $site_dbkeys}</filter>
+
<!-- We define url and params as normal, but values defined in dynamic_param are available by specified name --><url>${redirect_url}</url><param type="data" name="bam_file" url="galaxy_${DATASET_HASH}.bam" /><param type="data" name="bai_file" url="galaxy_${DATASET_HASH}.bam.bai" metadata="bam_index" /><param type="template" name="site_organism" strip="True" >
- $site_organisms[ $site_dbkeys.index( $bam_file.dbkey ) ]
+ #if ($dataset.dbkey in $site_dbkeys)
+ $site_organisms[ $site_dbkeys.index( $bam_file.dbkey ) ]
+ #else:
+ $bam_file.dbkey
+ #end if
</param><param type="template" name="jnlp" url="galaxy_${DATASET_HASH}.jnlp" viewable="True" mimetype="application/x-java-jnlp-file"><?xml version="1.0" encoding="utf-8"?>
diff -r 9b6cccb3af2d6b13a1a1da7def87dcc19172be88 -r 4456e0cf7721386a728e9cb05ef7463bbd477d5b display_applications/igv/vcf.xml
--- a/display_applications/igv/vcf.xml
+++ b/display_applications/igv/vcf.xml
@@ -12,15 +12,19 @@
<dynamic_param name="site_organisms" value="4" split="True" separator="," /><!-- Filter out some of the links based upon matching site_dbkeys to dataset dbkey -->
- <filter>${dataset.dbkey in $site_dbkeys}</filter>
-
+ <filter>${$site_id.startswith( 'local_' ) or $dataset.dbkey in $site_dbkeys}</filter>
+
<!-- We define url and params as normal, but values defined in dynamic_param are available by specified name --><url>${redirect_url}</url><param type="data" name="bgzip_file" url="galaxy_${DATASET_HASH}.vcf.gz" format="vcf_bgzip" /><param type="data" name="tabix_file" dataset="bgzip_file" url="galaxy_${DATASET_HASH}.vcf.gz.tbi" format="tabix" /><param type="template" name="site_organism" strip="True" >
- $site_organisms[ $site_dbkeys.index( $bgzip_file.dbkey ) ]
+ #if ($dataset.dbkey in $site_dbkeys)
+ $site_organisms[ $site_dbkeys.index( $bgzip_file.dbkey ) ]
+ #else:
+ $bgzip_file.dbkey
+ #end if
</param><param type="template" name="jnlp" url="galaxy_${DATASET_HASH}.jnlp" viewable="True" mimetype="application/x-java-jnlp-file"><?xml version="1.0" encoding="utf-8"?>
https://bitbucket.org/galaxy/galaxy-central/commits/f8465681a19d/
Changeset: f8465681a19d
User: dannon
Date: 2014-09-12 19:10:52
Summary: Merged in lance_parsons/galaxy-central-pull-requests/igv-local-dbkey (pull request #488)
Allow local IGV users to visualize custom genomes
Affected #: 2 files
diff -r 2346e098b27e0141fdd3e9821895413e27bc2c2f -r f8465681a19d189317fabebbc3c400c2418e8776 display_applications/igv/bam.xml
--- a/display_applications/igv/bam.xml
+++ b/display_applications/igv/bam.xml
@@ -12,15 +12,19 @@
<dynamic_param name="site_organisms" value="4" split="True" separator="," /><!-- Filter out some of the links based upon matching site_dbkeys to dataset dbkey -->
- <filter>${dataset.dbkey in $site_dbkeys}</filter>
-
+ <filter>${$site_id.startswith( 'local_' ) or $dataset.dbkey in $site_dbkeys}</filter>
+
<!-- We define url and params as normal, but values defined in dynamic_param are available by specified name --><url>${redirect_url}</url><param type="data" name="bam_file" url="galaxy_${DATASET_HASH}.bam" /><param type="data" name="bai_file" url="galaxy_${DATASET_HASH}.bam.bai" metadata="bam_index" /><param type="template" name="site_organism" strip="True" >
- $site_organisms[ $site_dbkeys.index( $bam_file.dbkey ) ]
+ #if ($dataset.dbkey in $site_dbkeys)
+ $site_organisms[ $site_dbkeys.index( $bam_file.dbkey ) ]
+ #else:
+ $bam_file.dbkey
+ #end if
</param><param type="template" name="jnlp" url="galaxy_${DATASET_HASH}.jnlp" viewable="True" mimetype="application/x-java-jnlp-file"><?xml version="1.0" encoding="utf-8"?>
diff -r 2346e098b27e0141fdd3e9821895413e27bc2c2f -r f8465681a19d189317fabebbc3c400c2418e8776 display_applications/igv/vcf.xml
--- a/display_applications/igv/vcf.xml
+++ b/display_applications/igv/vcf.xml
@@ -12,15 +12,19 @@
<dynamic_param name="site_organisms" value="4" split="True" separator="," /><!-- Filter out some of the links based upon matching site_dbkeys to dataset dbkey -->
- <filter>${dataset.dbkey in $site_dbkeys}</filter>
-
+ <filter>${$site_id.startswith( 'local_' ) or $dataset.dbkey in $site_dbkeys}</filter>
+
<!-- We define url and params as normal, but values defined in dynamic_param are available by specified name --><url>${redirect_url}</url><param type="data" name="bgzip_file" url="galaxy_${DATASET_HASH}.vcf.gz" format="vcf_bgzip" /><param type="data" name="tabix_file" dataset="bgzip_file" url="galaxy_${DATASET_HASH}.vcf.gz.tbi" format="tabix" /><param type="template" name="site_organism" strip="True" >
- $site_organisms[ $site_dbkeys.index( $bgzip_file.dbkey ) ]
+ #if ($dataset.dbkey in $site_dbkeys)
+ $site_organisms[ $site_dbkeys.index( $bgzip_file.dbkey ) ]
+ #else:
+ $bgzip_file.dbkey
+ #end if
</param><param type="template" name="jnlp" url="galaxy_${DATASET_HASH}.jnlp" viewable="True" mimetype="application/x-java-jnlp-file"><?xml version="1.0" encoding="utf-8"?>
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
3 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/aa8d4381785e/
Changeset: aa8d4381785e
User: jmchilton
Date: 2014-09-12 15:32:22
Summary: More workflow module documentation improvements.
I nearly understand workflow modules...
Affected #: 2 files
diff -r b8520d9c8269c4c7deca6418d54f2e722886073e -r aa8d4381785ee94746dbdcfd35c9b0798a10be30 lib/galaxy/workflow/modules.py
--- a/lib/galaxy/workflow/modules.py
+++ b/lib/galaxy/workflow/modules.py
@@ -79,10 +79,16 @@
def get_state( self ):
""" Return a serializable representation of the persistable state of
the step - for tools it DefaultToolState.encode returns a string and
- for inputs a json description is dumped out.
+ for simpler module types a json description is dumped out.
"""
return None
+ def update_state( self, incoming ):
+ """ Update the current state of the module against the user supplied
+ parameters in the dict-like object `incoming`.
+ """
+ pass
+
def get_errors( self ):
""" It seems like this is effectively just used as boolean - some places
in the tool shed self.errors is set to boolean, other places 'unavailable',
@@ -97,9 +103,6 @@
def get_data_outputs( self ):
return []
- def update_state( self ):
- pass
-
def get_config_form( self ):
""" Render form that is embedded in workflow editor for modifying the
step state of a node.
@@ -120,33 +123,38 @@
## ---- Run time ---------------------------------------------------------
def get_runtime_inputs( self ):
- """ Used internally to modules and when displaying inputs in display
- and run workflow templates. The ToolModule doesn't implement this and
- these templates contain specialized logic for dealing with the tool and
- state directly in these cases.
+ """ Used internally by modules and when displaying inputs in workflow
+ editor and run workflow templates.
+
+ Note: The ToolModule doesn't implement this and these templates contain
+ specialized logic for dealing with the tool and state directly in the
+ case of ToolModules.
"""
raise TypeError( "Abstract method" )
def encode_runtime_state( self, trans, state ):
- """ Encode the runtime state (loaded from the stored step and
- populated via the WorkflowModuleInjector below) for use in a hidden
- parameter on the webpage.
+ """ Encode the default runtime state at return as a simple `str` for
+ use in a hidden parameter on the workflow run submission form.
- This will combined with runtime parameters supplied by user running
- the workflow to create the final state to pass along to execute during
- workflow invocation.
+ This default runtime state will be combined with user supplied
+ parameters in `compute_runtime_state` below at workflow invocation time to
+ actually describe how each step will be executed.
"""
raise TypeError( "Abstract method" )
- def compute_state( self, trans, step_updates=None ):
- """ Recover the transient "state" attribute to populate corresponding
- step with (currently this is always a DefaultToolState instance,
- though I am not sure this is strictly nessecary).
+ def compute_runtime_state( self, trans, step_updates=None ):
+ """ Determine the runtime state (potentially different from self.state
+ which describes configuration state). This (again unlike self.state) is
+ currently always a `DefaultToolState` object.
If `step_updates` is `None`, this is likely for rendering the run form
for instance and no runtime properties are available and state must be
- solely determined by step. If `step_updates` are available they describe
- the runtime properties supplied by the workflow runner.
+ solely determined by the default runtime state described by the step.
+
+ If `step_updates` are available they describe the runtime properties
+ supplied by the workflow runner (potentially including a `tool_state`
+ parameter which is the serialized default encoding state created with
+ encode_runtime_state above).
"""
raise TypeError( "Abstract method" )
@@ -232,7 +240,7 @@
errors[ name ] = error
return errors
- def compute_state( self, trans, step_updates=None ):
+ def compute_runtime_state( self, trans, step_updates=None ):
if step_updates:
# Fix this for multiple inputs
state = self.decode_runtime_state( trans, step_updates.pop( "tool_state" ) )
@@ -559,7 +567,7 @@
def check_and_update_state( self ):
return self.tool.check_and_update_param_values( self.state.inputs, self.trans, allow_workflow_parameters=True )
- def compute_state( self, trans, step_updates=None ):
+ def compute_runtime_state( self, trans, step_updates=None ):
# Warning: This method destructively modifies existing step state.
step_errors = None
state = self.state
@@ -788,7 +796,7 @@
# are not persisted so we need to do it every time)
module.add_dummy_datasets( connections=step.input_connections )
- state, step_errors = module.compute_state( trans, step_args )
+ state, step_errors = module.compute_runtime_state( trans, step_args )
step.state = state
return step_errors
diff -r b8520d9c8269c4c7deca6418d54f2e722886073e -r aa8d4381785ee94746dbdcfd35c9b0798a10be30 test/unit/workflows/test_modules.py
--- a/test/unit/workflows/test_modules.py
+++ b/test/unit/workflows/test_modules.py
@@ -7,7 +7,6 @@
from galaxy import model
from galaxy.workflow import modules
-from galaxy.tools import parameters
from .workflow_support import MockTrans
@@ -49,17 +48,17 @@
__assert_has_runtime_input( module, label="Cool Input" )
-def test_data_input_compute_state_default():
+def test_data_input_compute_runtime_state_default():
module = __from_step(
type="data_input",
)
- state, errors = module.compute_state( module.trans )
+ state, errors = module.compute_runtime_state( module.trans )
assert not errors
assert 'input' in state.inputs
assert state.inputs[ 'input' ] is None
-def test_data_input_compute_state_args():
+def test_data_input_compute_runtime_state_args():
module = __from_step(
type="data_input",
)
@@ -68,7 +67,7 @@
hda = model.HistoryDatasetAssociation()
with mock.patch('galaxy.workflow.modules.check_param') as check_method:
check_method.return_value = ( hda, None )
- state, errors = module.compute_state( module.trans, { 'input': 4, 'tool_state': tool_state } )
+ state, errors = module.compute_runtime_state( module.trans, { 'input': 4, 'tool_state': tool_state } )
assert not errors
assert 'input' in state.inputs
https://bitbucket.org/galaxy/galaxy-central/commits/945ebcd32f33/
Changeset: 945ebcd32f33
User: jmchilton
Date: 2014-09-12 15:32:22
Summary: Rework workflow modules to reduce duplication and add more consistency..
Adding a recover_state method that to both implementations (though meant to be part of the module interface) that recovers the configuration state (module.state) from a dictionary. This turns out to reduce a lot of duplication between data and data collection input modules.
Affected #: 1 file
diff -r aa8d4381785ee94746dbdcfd35c9b0798a10be30 -r 945ebcd32f336a5b3b97c4c66aa1274a49d8e07b lib/galaxy/workflow/modules.py
--- a/lib/galaxy/workflow/modules.py
+++ b/lib/galaxy/workflow/modules.py
@@ -171,24 +171,41 @@
@classmethod
def new( Class, trans, tool_id=None ):
module = Class( trans )
- module.state = dict( name=Class.default_name )
+ module.state = Class.default_state()
return module
@classmethod
def from_dict( Class, trans, d, secure=True ):
module = Class( trans )
state = loads( d["tool_state"] )
- module.state = dict( name=state.get( "name", Class.default_name ) )
+ module.recover_state( state )
return module
@classmethod
def from_workflow_step( Class, trans, step ):
module = Class( trans )
- module.state = dict( name="Input Dataset" )
- if step.tool_inputs and "name" in step.tool_inputs:
- module.state['name'] = step.tool_inputs[ 'name' ]
+ module.recover_state( step.tool_inputs )
return module
+ @classmethod
+ def default_state( Class ):
+ """ This method should return a dictionary describing each
+ configuration property and its default value.
+ """
+ raise TypeError( "Abstract method" )
+
+ def recover_state( self, state, **kwds ):
+ """ Recover state `dict` from simple dictionary describing configuration
+ state (potentially from persisted step state).
+
+ Sub-classes should supply `default_state` method and `state_fields`
+ attribute which are used to build up the state `dict`.
+ """
+ self.state = self.default_state()
+ for key in self.state_fields:
+ if state and key in state:
+ self.state[ key ] = state[ key ]
+
def save_to_step( self, step ):
step.type = self.type
step.tool_id = None
@@ -277,6 +294,11 @@
type = "data_input"
name = "Input dataset"
default_name = "Input Dataset"
+ state_fields = [ "name" ]
+
+ @classmethod
+ def default_state( Class ):
+ return dict( name=Class.default_name )
class InputDataCollectionModule( InputModule ):
@@ -285,34 +307,11 @@
type = "data_collection_input"
name = "Input dataset collection"
collection_type = default_collection_type
+ state_fields = [ "name", "collection_type" ]
@classmethod
- def new( Class, trans, tool_id=None ):
- module = Class( trans )
- module.state = dict( name=Class.default_name, collection_type=Class.default_collection_type )
- return module
-
- @classmethod
- def from_dict( Class, trans, d, secure=True ):
- module = Class( trans )
- state = loads( d["tool_state"] )
- module.state = dict(
- name=state.get( "name", Class.default_name ),
- collection_type=state.get( "collection_type", Class.default_collection_type )
- )
- return module
-
- @classmethod
- def from_workflow_step( Class, trans, step ):
- module = Class( trans )
- module.state = dict(
- name=Class.default_name,
- collection_type=Class.default_collection_type
- )
- for key in [ "name", "collection_type" ]:
- if step.tool_inputs and key in step.tool_inputs:
- module.state[ key ] = step.tool_inputs[ key ]
- return module
+ def default_state( Class ):
+ return dict( name=Class.default_name, collection_type=Class.default_collection_type )
def get_runtime_inputs( self, filter_set=['data'] ):
label = self.state.get( "name", self.default_name )
@@ -408,10 +407,9 @@
# tool being previously unavailable.
return module_factory.from_dict(trans, loads(step.config), secure=False)
module = Class( trans, tool_id )
- module.state = galaxy.tools.DefaultToolState()
if step.tool_version and (step.tool_version != module.tool.version):
module.version_changes.append("%s: using version '%s' instead of version '%s' indicated in this workflow." % (tool_id, module.tool.version, step.tool_version))
- module.state.inputs = module.tool.params_from_strings( step.tool_inputs, trans.app, ignore_errors=True )
+ module.recover_state( step.tool_inputs )
module.errors = step.tool_errors
module.workflow_outputs = step.workflow_outputs
pjadict = {}
@@ -421,6 +419,17 @@
return module
return None
+ def recover_state( self, state, **kwds ):
+ """ Recover module configuration state property (a `DefaultToolState`
+ object) using the tool's `params_from_strings` method.
+ """
+ app = self.trans.app
+ self.state = galaxy.tools.DefaultToolState()
+ params_from_kwds = dict(
+ ignore_errors=kwds.get( "ignore_errors", True )
+ )
+ self.state.inputs = self.tool.params_from_strings( state, app, **params_from_kwds )
+
@classmethod
def __get_tool_version( cls, trans, tool_id ):
# Return a ToolVersion if one exists for tool_id.
https://bitbucket.org/galaxy/galaxy-central/commits/2346e098b27e/
Changeset: 2346e098b27e
User: jmchilton
Date: 2014-09-12 15:32:22
Summary: Better OOP design for separation between input and input collection modules.
(Lot easier now that I understand what all of the module methods are doing and have an example of a 4th module downstream.) Now with even more unit tests.
Affected #: 2 files
diff -r 945ebcd32f336a5b3b97c4c66aa1274a49d8e07b -r 2346e098b27e0141fdd3e9821895413e27bc2c2f lib/galaxy/workflow/modules.py
--- a/lib/galaxy/workflow/modules.py
+++ b/lib/galaxy/workflow/modules.py
@@ -214,12 +214,8 @@
def get_data_inputs( self ):
return []
- def get_data_outputs( self ):
- return [ dict( name='output', extensions=['input'] ) ]
-
def get_config_form( self ):
- form = formbuilder.FormBuilder( title=self.name ) \
- .add_text( "name", "Name", value=self.state['name'] )
+ form = self._abstract_config_form( )
return self.trans.fill_template( "workflow/editor_generic_form.mako",
module=self, form=form )
@@ -227,11 +223,7 @@
return dumps( self.state )
def update_state( self, incoming ):
- self.state['name'] = incoming.get( 'name', 'Input Dataset' )
-
- def get_runtime_inputs( self, filter_set=['data'] ):
- label = self.state.get( "name", "Input Dataset" )
- return dict( input=DataToolParameter( None, Element( "param", name="input", label=label, multiple=True, type="data", format=', '.join(filter_set) ), self.trans ) )
+ self.recover_state( incoming )
def get_runtime_state( self ):
state = galaxy.tools.DefaultToolState()
@@ -300,6 +292,18 @@
def default_state( Class ):
return dict( name=Class.default_name )
+ def _abstract_config_form( self ):
+ form = formbuilder.FormBuilder( title=self.name ) \
+ .add_text( "name", "Name", value=self.state['name'] )
+ return form
+
+ def get_data_outputs( self ):
+ return [ dict( name='output', extensions=['input'] ) ]
+
+ def get_runtime_inputs( self, filter_set=['data'] ):
+ label = self.state.get( "name", "Input Dataset" )
+ return dict( input=DataToolParameter( None, Element( "param", name="input", label=label, multiple=True, type="data", format=', '.join(filter_set) ), self.trans ) )
+
class InputDataCollectionModule( InputModule ):
default_name = "Input Dataset Collection"
@@ -319,7 +323,7 @@
input_element = Element( "param", name="input", label=label, type="data_collection", collection_type=collection_type )
return dict( input=DataCollectionToolParameter( None, input_element, self.trans ) )
- def get_config_form( self ):
+ def _abstract_config_form( self ):
type_hints = odict.odict()
type_hints[ "list" ] = "List of Datasets"
type_hints[ "paired" ] = "Dataset Pair"
@@ -338,12 +342,7 @@
"name", "Name", value=self.state['name']
)
form.inputs.append( type_input )
- return self.trans.fill_template( "workflow/editor_generic_form.mako",
- module=self, form=form )
-
- def update_state( self, incoming ):
- self.state[ 'name' ] = incoming.get( 'name', self.default_name )
- self.state[ 'collection_type' ] = incoming.get( 'collection_type', self.collection_type )
+ return form
def get_data_outputs( self ):
return [ dict( name='output', extensions=['input_collection'], collection_type=self.state[ 'collection_type' ] ) ]
diff -r 945ebcd32f336a5b3b97c4c66aa1274a49d8e07b -r 2346e098b27e0141fdd3e9821895413e27bc2c2f test/unit/workflows/test_modules.py
--- a/test/unit/workflows/test_modules.py
+++ b/test/unit/workflows/test_modules.py
@@ -74,6 +74,49 @@
assert state.inputs[ 'input' ] is hda
+def test_data_input_connections():
+ module = __from_step(
+ type="data_input",
+ )
+ assert len( module.get_data_inputs() ) == 0
+
+ outputs = module.get_data_outputs()
+ assert len( outputs ) == 1
+ output = outputs[ 0 ]
+ assert output[ 'name' ] == 'output'
+ assert output[ 'extensions' ] == [ 'input' ]
+
+
+def test_data_input_update():
+ module = __from_step(
+ type="data_input",
+ tool_inputs={
+ "name": "Cool Input",
+ },
+ )
+ module.update_state( dict( name="Awesome New Name" ) )
+ assert module.state[ 'name' ] == "Awesome New Name"
+
+
+def test_data_input_get_form():
+ module = __from_step(
+ type="data_input",
+ tool_inputs={
+ "name": "Cool Input",
+ },
+ )
+
+ def test_form(template, **kwds ):
+ assert template == "workflow/editor_generic_form.mako"
+ assert "form" in kwds
+ assert len( kwds[ "form" ].inputs ) == 1
+ return "TEMPLATE"
+
+ fill_mock = mock.Mock( side_effect=test_form )
+ module.trans.fill_template = fill_mock
+ assert module.get_config_form() == "TEMPLATE"
+
+
def test_data_collection_input_default_state():
trans = MockTrans()
module = modules.module_factory.new( trans, "data_collection_input" )
@@ -99,6 +142,55 @@
__assert_has_runtime_input( module, label="Cool Input Collection", collection_type="list:paired" )
+def test_data_collection_input_connections():
+ module = __from_step(
+ type="data_collection_input",
+ tool_inputs={
+ 'collection_type': 'list:paired'
+ }
+ )
+ assert len( module.get_data_inputs() ) == 0
+
+ outputs = module.get_data_outputs()
+ assert len( outputs ) == 1
+ output = outputs[ 0 ]
+ assert output[ 'name' ] == 'output'
+ assert output[ 'extensions' ] == [ 'input_collection' ]
+ assert output[ 'collection_type' ] == 'list:paired'
+
+
+def test_data_collection_input_update():
+ module = __from_step(
+ type="data_collection_input",
+ tool_inputs={
+ 'name': 'Cool Collection',
+ 'collection_type': 'list:paired',
+ }
+ )
+ module.update_state( dict( name="New Collection", collection_type="list" ) )
+ assert module.state[ 'name' ] == "New Collection"
+
+
+def test_data_collection_input_config_form():
+ module = __from_step(
+ type="data_collection_input",
+ tool_inputs={
+ 'name': 'Cool Collection',
+ 'collection_type': 'list:paired',
+ }
+ )
+
+ def test_form(template, **kwds ):
+ assert template == "workflow/editor_generic_form.mako"
+ assert "form" in kwds
+ assert len( kwds[ "form" ].inputs ) == 2
+ return "TEMPLATE"
+
+ fill_mock = mock.Mock( side_effect=test_form )
+ module.trans.fill_template = fill_mock
+ assert module.get_config_form() == "TEMPLATE"
+
+
def test_cannot_create_tool_modules_for_missing_tools():
trans = MockTrans()
exception = False
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
[galaxyproject/usegalaxy-playbook] 14926e: Update pulsar vars for new job_managers.ini templa...
by GitHub 11 Sep '14
by GitHub 11 Sep '14
11 Sep '14
Branch: refs/heads/master
Home: https://github.com/galaxyproject/usegalaxy-playbook
Commit: 14926e345bc4f9e1426398508abf1f1886b175c5
https://github.com/galaxyproject/usegalaxy-playbook/commit/14926e345bc4f9e1…
Author: Nate Coraor <nate(a)bx.psu.edu>
Date: 2014-09-11 (Thu, 11 Sep 2014)
Changed paths:
M stage/host_vars/login5.stampede.tacc.utexas.edu.yml
Log Message:
-----------
Update pulsar vars for new job_managers.ini template style.
1
0
[galaxyproject/usegalaxy-playbook] 87f275: Update galaxyprojectdotorg.pulsar to v0.3
by GitHub 11 Sep '14
by GitHub 11 Sep '14
11 Sep '14
Branch: refs/heads/master
Home: https://github.com/galaxyproject/usegalaxy-playbook
Commit: 87f2751c7c727d57146f436dcf0f10d3f089dbad
https://github.com/galaxyproject/usegalaxy-playbook/commit/87f2751c7c727d57…
Author: Nate Coraor <nate(a)bx.psu.edu>
Date: 2014-09-11 (Thu, 11 Sep 2014)
Changed paths:
M roles/galaxyprojectdotorg.pulsar/README.md
M roles/galaxyprojectdotorg.pulsar/defaults/main.yml
M roles/galaxyprojectdotorg.pulsar/meta/.galaxy_install_info
M roles/galaxyprojectdotorg.pulsar/tasks/main.yml
M roles/galaxyprojectdotorg.pulsar/templates/job_managers.ini.j2
Log Message:
-----------
Update galaxyprojectdotorg.pulsar to v0.3
1
0
7 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/9278a44330b7/
Changeset: 9278a44330b7
User: jmchilton
Date: 2014-09-11 22:01:08
Summary: Initial work on a tags manager.
Rest of UsesTagsMixin needs to be copied over similarly and deprecated, following that I guess all references need to be updated and then the mixin eliminated all together I guess (exhausting :)).
Affected #: 3 files
diff -r da6e8248d7b402783e829f27ee1ab9e6ba4367d7 -r 9278a44330b7343a7f414057669fc1e047cfc1b6 lib/galaxy/dataset_collections/__init__.py
--- a/lib/galaxy/dataset_collections/__init__.py
+++ b/lib/galaxy/dataset_collections/__init__.py
@@ -10,9 +10,9 @@
from galaxy.web.base.controller import (
UsesHistoryDatasetAssociationMixin,
UsesLibraryMixinItems,
- UsesTagsMixin,
)
from galaxy.managers import hdas # TODO: Refactor all mixin use into managers.
+from galaxy.managers import tags
from galaxy.managers.collections_util import validate_input_element_identifiers
from galaxy.util import validation
from galaxy.util import odict
@@ -27,8 +27,7 @@
class DatasetCollectionsService(
UsesHistoryDatasetAssociationMixin,
- UsesLibraryMixinItems,
- UsesTagsMixin,
+ UsesLibraryMixinItems
):
"""
Abstraction for interfacing with dataset collections instance - ideally abstarcts
@@ -41,6 +40,7 @@
self.model = app.model
self.security = app.security
self.hda_manager = hdas.HDAManager()
+ self.tag_manager = tags.TagsManager( app )
def create(
self,
@@ -166,7 +166,7 @@
dataset_collection_instance.add_item_annotation( trans.sa_session, trans.get_user(), dataset_collection_instance, new_data[ 'annotation' ] )
changed[ 'annotation' ] = new_data[ 'annotation' ]
if 'tags' in new_data.keys() and trans.get_user():
- self.set_tags_from_list( trans, dataset_collection_instance, new_data[ 'tags' ], user=trans.user )
+ self.tag_manager.set_tags_from_list( trans, dataset_collection_instance, new_data[ 'tags' ], user=trans.user )
if changed.keys():
trans.sa_session.flush()
diff -r da6e8248d7b402783e829f27ee1ab9e6ba4367d7 -r 9278a44330b7343a7f414057669fc1e047cfc1b6 lib/galaxy/managers/tags.py
--- /dev/null
+++ b/lib/galaxy/managers/tags.py
@@ -0,0 +1,20 @@
+
+
+class TagsManager( object ):
+ """ Manages CRUD operations related to tagging objects.
+ """
+
+ def __init__( self, app ):
+ self.app = app
+ self.tag_handler = app.tag_handler
+
+ def set_tags_from_list( self, trans, item, new_tags_list, user=None ):
+ #precondition: item is already security checked against user
+ #precondition: incoming tags is a list of sanitized/formatted strings
+ user = user or trans.user
+
+ self.tag_handler.delete_item_tags( trans, user, item )
+ new_tags_str = ','.join( new_tags_list )
+ self.tag_handler.apply_item_tags( trans, user, item, unicode( new_tags_str.encode( 'utf-8' ), 'utf-8' ) )
+ trans.sa_session.flush()
+ return item.tags
diff -r da6e8248d7b402783e829f27ee1ab9e6ba4367d7 -r 9278a44330b7343a7f414057669fc1e047cfc1b6 lib/galaxy/web/base/controller.py
--- a/lib/galaxy/web/base/controller.py
+++ b/lib/galaxy/web/base/controller.py
@@ -38,6 +38,7 @@
from galaxy.model import ExtendedMetadata, ExtendedMetadataIndex, LibraryDatasetDatasetAssociation, HistoryDatasetAssociation
from galaxy.managers import api_keys
+from galaxy.managers import tags
from galaxy.datatypes.metadata import FileParameter
from galaxy.tools.parameters import RuntimeValue, visit_input_values
from galaxy.tools.parameters.basic import DataToolParameter
@@ -2808,16 +2809,9 @@
return self.get_tag_handler( trans )._get_item_tag_assoc( user, tagged_item, tag_name )
def set_tags_from_list( self, trans, item, new_tags_list, user=None ):
- #precondition: item is already security checked against user
- #precondition: incoming tags is a list of sanitized/formatted strings
- user = user or trans.user
-
- # based on controllers/tag retag_async: delete all old, reset to entire new
- trans.app.tag_handler.delete_item_tags( trans, user, item )
- new_tags_str = ','.join( new_tags_list )
- trans.app.tag_handler.apply_item_tags( trans, user, item, unicode( new_tags_str.encode( 'utf-8' ), 'utf-8' ) )
- trans.sa_session.flush()
- return item.tags
+ # Method deprecated - try to use TagsHandler instead.
+ tags_manager = tags.TagsManager( trans.app )
+ return tags_manager.set_tags_from_list( trans, item, new_tags_list, user=user )
def get_user_tags_used( self, trans, user=None ):
"""
https://bitbucket.org/galaxy/galaxy-central/commits/6f5195e15d09/
Changeset: 6f5195e15d09
User: jmchilton
Date: 2014-09-11 22:01:08
Summary: Refactor generic controller mixin code for security out for reuse in managers.
Affected #: 2 files
diff -r 9278a44330b7343a7f414057669fc1e047cfc1b6 -r 6f5195e15d0919790db68865dba5e365d67d14c1 lib/galaxy/managers/base.py
--- a/lib/galaxy/managers/base.py
+++ b/lib/galaxy/managers/base.py
@@ -1,7 +1,41 @@
+from galaxy import exceptions
class ModelManager( object ):
pass
+
class ModelSerializer( object ):
pass
+
+
+def security_check( trans, item, check_ownership=False, check_accessible=False ):
+ """ Security checks for an item: checks if (a) user owns item or (b) item
+ is accessible to user. This is a generic method for dealing with objects
+ uniformly from the older controller mixin code - however whenever possible
+ the managers for a particular model should be used to perform security
+ checks.
+ """
+
+ # all items are accessible to an admin
+ if trans.user_is_admin():
+ return item
+
+ # Verify ownership: there is a current user and that user is the same as the item's
+ if check_ownership:
+ if not trans.user:
+ raise exceptions.ItemOwnershipException( "Must be logged in to manage Galaxy items", type='error' )
+ if item.user != trans.user:
+ raise exceptions.ItemOwnershipException( "%s is not owned by the current user" % item.__class__.__name__, type='error' )
+
+ # Verify accessible:
+ # if it's part of a lib - can they access via security
+ # if it's something else (sharable) have they been added to the item's users_shared_with_dot_users
+ if check_accessible:
+ if type( item ) in ( trans.app.model.LibraryFolder, trans.app.model.LibraryDatasetDatasetAssociation, trans.app.model.LibraryDataset ):
+ if not trans.app.security_agent.can_access_library_item( trans.get_current_user_roles(), item, trans.user ):
+ raise exceptions.ItemAccessibilityException( "%s is not accessible to the current user" % item.__class__.__name__, type='error' )
+ else:
+ if ( item.user != trans.user ) and ( not item.importable ) and ( trans.user not in item.users_shared_with_dot_users ):
+ raise exceptions.ItemAccessibilityException( "%s is not accessible to the current user" % item.__class__.__name__, type='error' )
+ return item
diff -r 9278a44330b7343a7f414057669fc1e047cfc1b6 -r 6f5195e15d0919790db68865dba5e365d67d14c1 lib/galaxy/web/base/controller.py
--- a/lib/galaxy/web/base/controller.py
+++ b/lib/galaxy/web/base/controller.py
@@ -39,6 +39,7 @@
from galaxy.managers import api_keys
from galaxy.managers import tags
+from galaxy.managers import base as managers_base
from galaxy.datatypes.metadata import FileParameter
from galaxy.tools.parameters import RuntimeValue, visit_input_values
from galaxy.tools.parameters.basic import DataToolParameter
@@ -301,28 +302,7 @@
def security_check( self, trans, item, check_ownership=False, check_accessible=False ):
""" Security checks for an item: checks if (a) user owns item or (b) item is accessible to user. """
- # all items are accessible to an admin
- if trans.user_is_admin():
- return item
-
- # Verify ownership: there is a current user and that user is the same as the item's
- if check_ownership:
- if not trans.user:
- raise ItemOwnershipException( "Must be logged in to manage Galaxy items", type='error' )
- if item.user != trans.user:
- raise ItemOwnershipException( "%s is not owned by the current user" % item.__class__.__name__, type='error' )
-
- # Verify accessible:
- # if it's part of a lib - can they access via security
- # if it's something else (sharable) have they been added to the item's users_shared_with_dot_users
- if check_accessible:
- if type( item ) in ( trans.app.model.LibraryFolder, trans.app.model.LibraryDatasetDatasetAssociation, trans.app.model.LibraryDataset ):
- if not trans.app.security_agent.can_access_library_item( trans.get_current_user_roles(), item, trans.user ):
- raise ItemAccessibilityException( "%s is not accessible to the current user" % item.__class__.__name__, type='error' )
- else:
- if ( item.user != trans.user ) and ( not item.importable ) and ( trans.user not in item.users_shared_with_dot_users ):
- raise ItemAccessibilityException( "%s is not accessible to the current user" % item.__class__.__name__, type='error' )
- return item
+ return managers_base.security_check( trans, item, check_ownership=check_ownership, check_accessible=check_accessible )
class UsesHistoryMixin( SharableItemSecurityMixin ):
https://bitbucket.org/galaxy/galaxy-central/commits/83016af21151/
Changeset: 83016af21151
User: jmchilton
Date: 2014-09-11 22:01:08
Summary: Refactor generic controller mixin code for loading objects into managers.
Affected #: 2 files
diff -r 6f5195e15d0919790db68865dba5e365d67d14c1 -r 83016af2115156f4ebb640ea231824f23aeecad3 lib/galaxy/managers/base.py
--- a/lib/galaxy/managers/base.py
+++ b/lib/galaxy/managers/base.py
@@ -1,5 +1,12 @@
from galaxy import exceptions
+from galaxy import model
+from galaxy.model import tool_shed_install
+
+
+import logging
+log = logging.getLogger( __name__ )
+
class ModelManager( object ):
pass
@@ -39,3 +46,75 @@
if ( item.user != trans.user ) and ( not item.importable ) and ( trans.user not in item.users_shared_with_dot_users ):
raise exceptions.ItemAccessibilityException( "%s is not accessible to the current user" % item.__class__.__name__, type='error' )
return item
+
+
+def get_class( class_name ):
+ """ Returns the class object that a string denotes. Without this method, we'd have to do eval(<class_name>). """
+ if class_name == 'History':
+ item_class = model.History
+ elif class_name == 'HistoryDatasetAssociation':
+ item_class = model.HistoryDatasetAssociation
+ elif class_name == 'Page':
+ item_class = model.Page
+ elif class_name == 'StoredWorkflow':
+ item_class = model.StoredWorkflow
+ elif class_name == 'Visualization':
+ item_class = model.Visualization
+ elif class_name == 'Tool':
+ item_class = model.Tool
+ elif class_name == 'Job':
+ item_class = model.Job
+ elif class_name == 'User':
+ item_class = model.User
+ elif class_name == 'Group':
+ item_class = model.Group
+ elif class_name == 'Role':
+ item_class = model.Role
+ elif class_name == 'Quota':
+ item_class = model.Quota
+ elif class_name == 'Library':
+ item_class = model.Library
+ elif class_name == 'LibraryFolder':
+ item_class = model.LibraryFolder
+ elif class_name == 'LibraryDatasetDatasetAssociation':
+ item_class = model.LibraryDatasetDatasetAssociation
+ elif class_name == 'LibraryDataset':
+ item_class = model.LibraryDataset
+ elif class_name == 'ToolShedRepository':
+ item_class = tool_shed_install.ToolShedRepository
+ else:
+ item_class = None
+ return item_class
+
+
+def get_object( trans, id, class_name, check_ownership=False, check_accessible=False, deleted=None ):
+ """
+ Convenience method to get a model object with the specified checks. This is
+ a generic method for dealing with objects uniformly from the older
+ controller mixin code - however whenever possible the managers for a
+ particular model should be used to load objects.
+ """
+ try:
+ decoded_id = trans.security.decode_id( id )
+ except:
+ raise exceptions.MessageException( "Malformed %s id ( %s ) specified, unable to decode"
+ % ( class_name, str( id ) ), type='error' )
+ try:
+ item_class = get_class( class_name )
+ assert item_class is not None
+ item = trans.sa_session.query( item_class ).get( decoded_id )
+ assert item is not None
+ except Exception:
+ log.exception( "Invalid %s id ( %s ) specified." % ( class_name, id ) )
+ raise exceptions.MessageException( "Invalid %s id ( %s ) specified" % ( class_name, id ), type="error" )
+
+ if check_ownership or check_accessible:
+ security_check( trans, item, check_ownership, check_accessible )
+ if deleted is True and not item.deleted:
+ raise exceptions.ItemDeletionException( '%s "%s" is not deleted'
+ % ( class_name, getattr( item, 'name', id ) ), type="warning" )
+ elif deleted is False and item.deleted:
+ raise exceptions.ItemDeletionException( '%s "%s" is deleted'
+ % ( class_name, getattr( item, 'name', id ) ), type="warning" )
+ return item
+
diff -r 6f5195e15d0919790db68865dba5e365d67d14c1 -r 83016af2115156f4ebb640ea231824f23aeecad3 lib/galaxy/web/base/controller.py
--- a/lib/galaxy/web/base/controller.py
+++ b/lib/galaxy/web/base/controller.py
@@ -78,70 +78,14 @@
def get_class( self, class_name ):
""" Returns the class object that a string denotes. Without this method, we'd have to do eval(<class_name>). """
- if class_name == 'History':
- item_class = self.app.model.History
- elif class_name == 'HistoryDatasetAssociation':
- item_class = self.app.model.HistoryDatasetAssociation
- elif class_name == 'Page':
- item_class = self.app.model.Page
- elif class_name == 'StoredWorkflow':
- item_class = self.app.model.StoredWorkflow
- elif class_name == 'Visualization':
- item_class = self.app.model.Visualization
- elif class_name == 'Tool':
- item_class = self.app.model.Tool
- elif class_name == 'Job':
- item_class = self.app.model.Job
- elif class_name == 'User':
- item_class = self.app.model.User
- elif class_name == 'Group':
- item_class = self.app.model.Group
- elif class_name == 'Role':
- item_class = self.app.model.Role
- elif class_name == 'Quota':
- item_class = self.app.model.Quota
- elif class_name == 'Library':
- item_class = self.app.model.Library
- elif class_name == 'LibraryFolder':
- item_class = self.app.model.LibraryFolder
- elif class_name == 'LibraryDatasetDatasetAssociation':
- item_class = self.app.model.LibraryDatasetDatasetAssociation
- elif class_name == 'LibraryDataset':
- item_class = self.app.model.LibraryDataset
- elif class_name == 'ToolShedRepository':
- item_class = self.app.install_model.ToolShedRepository
- else:
- item_class = None
- return item_class
+ return managers_base.get_class( class_name )
def get_object( self, trans, id, class_name, check_ownership=False, check_accessible=False, deleted=None ):
"""
Convenience method to get a model object with the specified checks.
"""
- try:
- decoded_id = trans.security.decode_id( id )
- except:
- raise MessageException( "Malformed %s id ( %s ) specified, unable to decode"
- % ( class_name, str( id ) ), type='error' )
- try:
- item_class = self.get_class( class_name )
- assert item_class is not None
- item = trans.sa_session.query( item_class ).get( decoded_id )
- assert item is not None
- except Exception:
- log.exception( "Invalid %s id ( %s ) specified." % ( class_name, id ) )
- raise MessageException( "Invalid %s id ( %s ) specified" % ( class_name, id ), type="error" )
-
- if check_ownership or check_accessible:
- self.security_check( trans, item, check_ownership, check_accessible )
- if deleted == True and not item.deleted:
- raise ItemDeletionException( '%s "%s" is not deleted'
- % ( class_name, getattr( item, 'name', id ) ), type="warning" )
- elif deleted == False and item.deleted:
- raise ItemDeletionException( '%s "%s" is deleted'
- % ( class_name, getattr( item, 'name', id ) ), type="warning" )
- return item
-
+ return managers_base.get_object( trans, id, class_name, check_ownership=check_ownership, check_accessible=check_accessible, deleted=deleted )
+
# this should be here - but catching errors from sharable item controllers that *should* have SharableItemMixin
# but *don't* then becomes difficult
#def security_check( self, trans, item, check_ownership=False, check_accessible=False ):
https://bitbucket.org/galaxy/galaxy-central/commits/355aee34a371/
Changeset: 355aee34a371
User: jmchilton
Date: 2014-09-11 22:01:08
Summary: Introduce LDDA manager stub.
Use it to eliminate awful controller dependencies (and associated circular dependency errors when controllers are not loaded before everything else) in galaxy.dataset_collections.
Affected #: 3 files
diff -r 83016af2115156f4ebb640ea231824f23aeecad3 -r 355aee34a371c99f9251b965ea625066a80419ea lib/galaxy/dataset_collections/__init__.py
--- a/lib/galaxy/dataset_collections/__init__.py
+++ b/lib/galaxy/dataset_collections/__init__.py
@@ -7,11 +7,9 @@
from galaxy.exceptions import MessageException
from galaxy.exceptions import ItemAccessibilityException
from galaxy.exceptions import RequestParameterInvalidException
-from galaxy.web.base.controller import (
- UsesHistoryDatasetAssociationMixin,
- UsesLibraryMixinItems,
-)
from galaxy.managers import hdas # TODO: Refactor all mixin use into managers.
+from galaxy.managers import histories
+from galaxy.managers import lddas
from galaxy.managers import tags
from galaxy.managers.collections_util import validate_input_element_identifiers
from galaxy.util import validation
@@ -25,10 +23,7 @@
ERROR_NO_COLLECTION_TYPE = "Create called without specifing a collection type."
-class DatasetCollectionsService(
- UsesHistoryDatasetAssociationMixin,
- UsesLibraryMixinItems
-):
+class DatasetCollectionsService( object ):
"""
Abstraction for interfacing with dataset collections instance - ideally abstarcts
out model and plugin details.
@@ -40,7 +35,9 @@
self.model = app.model
self.security = app.security
self.hda_manager = hdas.HDAManager()
+ self.history_manager = histories.HistoryManager()
self.tag_manager = tags.TagsManager( app )
+ self.ldda_manager = lddas.LDDAManager( )
def create(
self,
@@ -249,7 +246,7 @@
decoded_id = int( trans.app.security.decode_id( encoded_id ) )
element = self.hda_manager.get( trans, decoded_id, check_ownership=False )
elif src_type == 'ldda':
- element = self.get_library_dataset_dataset_association( trans, encoded_id )
+ element = self.ldda_manager.get( trans, encoded_id )
elif src_type == 'hdca':
# TODO: Option to copy? Force copy? Copy or allow if not owned?
element = self.__get_history_collection_instance( trans, encoded_id ).collection
@@ -281,7 +278,7 @@
def __get_history_collection_instance( self, trans, id, check_ownership=False, check_accessible=True ):
instance_id = int( trans.app.security.decode_id( id ) )
collection_instance = trans.sa_session.query( trans.app.model.HistoryDatasetCollectionAssociation ).get( instance_id )
- self.security_check( trans, collection_instance.history, check_ownership=check_ownership, check_accessible=check_accessible )
+ self.history_manager.secure( trans, collection_instance.history, check_ownership=check_ownership, check_accessible=check_accessible )
return collection_instance
def __get_library_collection_instance( self, trans, id, check_ownership=False, check_accessible=True ):
diff -r 83016af2115156f4ebb640ea231824f23aeecad3 -r 355aee34a371c99f9251b965ea625066a80419ea lib/galaxy/managers/lddas.py
--- /dev/null
+++ b/lib/galaxy/managers/lddas.py
@@ -0,0 +1,16 @@
+from galaxy.managers import base as manager_base
+
+
+class LDDAManager( manager_base.ModelManager ):
+ """ A fairly sparse manager for LDDAs.
+ """
+
+ def __init__( self ):
+ """
+ Set up and initialize other managers needed by lddas.
+ """
+ pass
+
+ def get( self, trans, id, check_accessible=True ):
+ return manager_base.get_object( trans, id, 'LibraryDatasetDatasetAssociation',
+ check_ownership=False, check_accessible=check_accessible )
diff -r 83016af2115156f4ebb640ea231824f23aeecad3 -r 355aee34a371c99f9251b965ea625066a80419ea lib/galaxy/web/base/controller.py
--- a/lib/galaxy/web/base/controller.py
+++ b/lib/galaxy/web/base/controller.py
@@ -875,6 +875,9 @@
check_ownership=False, check_accessible=check_accessible )
def get_library_dataset_dataset_association( self, trans, id, check_ownership=False, check_accessible=True ):
+ # Deprecated in lieu to galaxy.managers.lddas.LDDAManager.get() but not
+ # reusing that exactly because of subtle differences in exception handling
+ # logic (API controller override get_object to be slightly different).
return self.get_object( trans, id, 'LibraryDatasetDatasetAssociation',
check_ownership=False, check_accessible=check_accessible )
https://bitbucket.org/galaxy/galaxy-central/commits/dd31ab49162d/
Changeset: dd31ab49162d
User: jmchilton
Date: 2014-09-11 22:01:08
Summary: Make dataset collections service a manager.
It would hve been arcitected this way from the beginning but my initial work on it predated Carl's managers work and it had those pesky controller dependencies.
Affected #: 3 files
diff -r 355aee34a371c99f9251b965ea625066a80419ea -r dd31ab49162d3faa30818947a80a6165c2f0b4c7 lib/galaxy/app.py
--- a/lib/galaxy/app.py
+++ b/lib/galaxy/app.py
@@ -5,7 +5,7 @@
from galaxy import config, jobs
import galaxy.model
import galaxy.security
-from galaxy import dataset_collections
+from galaxy.managers.collections import DatasetCollectionManager
import galaxy.quota
from galaxy.tags.tag_handler import GalaxyTagHandler
from galaxy.visualization.genomes import Genomes
@@ -57,7 +57,7 @@
# Tag handler
self.tag_handler = GalaxyTagHandler()
# Dataset Collection Plugins
- self.dataset_collections_service = dataset_collections.DatasetCollectionsService(self)
+ self.dataset_collections_service = DatasetCollectionManager(self)
# Tool Data Tables
self._configure_tool_data_tables( from_shed_config=False )
diff -r 355aee34a371c99f9251b965ea625066a80419ea -r dd31ab49162d3faa30818947a80a6165c2f0b4c7 lib/galaxy/dataset_collections/__init__.py
--- a/lib/galaxy/dataset_collections/__init__.py
+++ b/lib/galaxy/dataset_collections/__init__.py
@@ -1,292 +0,0 @@
-from .registry import DatasetCollectionTypesRegistry
-from .matching import MatchingCollections
-from .type_description import CollectionTypeDescriptionFactory
-
-
-from galaxy import model
-from galaxy.exceptions import MessageException
-from galaxy.exceptions import ItemAccessibilityException
-from galaxy.exceptions import RequestParameterInvalidException
-from galaxy.managers import hdas # TODO: Refactor all mixin use into managers.
-from galaxy.managers import histories
-from galaxy.managers import lddas
-from galaxy.managers import tags
-from galaxy.managers.collections_util import validate_input_element_identifiers
-from galaxy.util import validation
-from galaxy.util import odict
-
-import logging
-log = logging.getLogger( __name__ )
-
-
-ERROR_INVALID_ELEMENTS_SPECIFICATION = "Create called with invalid parameters, must specify element identifiers."
-ERROR_NO_COLLECTION_TYPE = "Create called without specifing a collection type."
-
-
-class DatasetCollectionsService( object ):
- """
- Abstraction for interfacing with dataset collections instance - ideally abstarcts
- out model and plugin details.
- """
-
- def __init__( self, app ):
- self.type_registry = DatasetCollectionTypesRegistry( app )
- self.collection_type_descriptions = CollectionTypeDescriptionFactory( self.type_registry )
- self.model = app.model
- self.security = app.security
- self.hda_manager = hdas.HDAManager()
- self.history_manager = histories.HistoryManager()
- self.tag_manager = tags.TagsManager( app )
- self.ldda_manager = lddas.LDDAManager( )
-
- def create(
- self,
- trans,
- parent, # PRECONDITION: security checks on ability to add to parent occurred during load.
- name,
- collection_type,
- element_identifiers=None,
- elements=None,
- implicit_collection_info=None,
- ):
- """
- """
- # Trust embedded, newly created objects created by tool subsystem.
- trusted_identifiers = implicit_collection_info is not None
-
- if element_identifiers and not trusted_identifiers:
- validate_input_element_identifiers( element_identifiers )
-
- dataset_collection = self.__create_dataset_collection(
- trans=trans,
- collection_type=collection_type,
- element_identifiers=element_identifiers,
- elements=elements,
- )
- if isinstance( parent, model.History ):
- dataset_collection_instance = self.model.HistoryDatasetCollectionAssociation(
- collection=dataset_collection,
- name=name,
- )
- if implicit_collection_info:
- for input_name, input_collection in implicit_collection_info[ "implicit_inputs" ]:
- dataset_collection_instance.add_implicit_input_collection( input_name, input_collection )
- for output_dataset in implicit_collection_info.get( "outputs" ):
- output_dataset.hidden_beneath_collection_instance = dataset_collection_instance
- trans.sa_session.add( output_dataset )
-
- dataset_collection_instance.implicit_output_name = implicit_collection_info[ "implicit_output_name" ]
- log.debug("Created collection with %d elements" % ( len( dataset_collection_instance.collection.elements ) ) )
- # Handle setting hid
- parent.add_dataset_collection( dataset_collection_instance )
- elif isinstance( parent, model.LibraryFolder ):
- dataset_collection_instance = self.model.LibraryDatasetCollectionAssociation(
- collection=dataset_collection,
- folder=parent,
- name=name,
- )
- else:
- message = "Internal logic error - create called with unknown parent type %s" % type( parent )
- log.exception( message )
- raise MessageException( message )
-
- return self.__persist( dataset_collection_instance )
-
- def __create_dataset_collection(
- self,
- trans,
- collection_type,
- element_identifiers=None,
- elements=None,
- ):
- if element_identifiers is None and elements is None:
- raise RequestParameterInvalidException( ERROR_INVALID_ELEMENTS_SPECIFICATION )
- if not collection_type:
- raise RequestParameterInvalidException( ERROR_NO_COLLECTION_TYPE )
- collection_type_description = self.collection_type_descriptions.for_collection_type( collection_type )
- # If we have elements, this is an internal request, don't need to load
- # objects from identifiers.
- if elements is None:
- if collection_type_description.has_subcollections( ):
- # Nested collection - recursively create collections and update identifiers.
- self.__recursively_create_collections( trans, element_identifiers )
- elements = self.__load_elements( trans, element_identifiers )
- # else if elements is set, it better be an ordered dict!
-
- type_plugin = collection_type_description.rank_type_plugin()
- dataset_collection = type_plugin.build_collection( elements )
- dataset_collection.collection_type = collection_type
- return dataset_collection
-
- def delete( self, trans, instance_type, id ):
- dataset_collection_instance = self.get_dataset_collection_instance( trans, instance_type, id, check_ownership=True )
- dataset_collection_instance.deleted = True
- trans.sa_session.add( dataset_collection_instance )
- trans.sa_session.flush( )
-
- def update( self, trans, instance_type, id, payload ):
- dataset_collection_instance = self.get_dataset_collection_instance( trans, instance_type, id, check_ownership=True )
- if trans.user is None:
- anon_allowed_payload = {}
- if 'deleted' in payload:
- anon_allowed_payload[ 'deleted' ] = payload[ 'deleted' ]
- if 'visible' in payload:
- anon_allowed_payload[ 'visible' ] = payload[ 'visible' ]
- payload = self._validate_and_parse_update_payload( anon_allowed_payload )
- else:
- payload = self._validate_and_parse_update_payload( payload )
- changed = self._set_from_dict( trans, dataset_collection_instance, payload )
- return changed
-
- def copy(
- self,
- trans,
- parent, # PRECONDITION: security checks on ability to add to parent occurred during load.
- source,
- encoded_source_id,
- ):
- assert source == "hdca" # for now
- source_hdca = self.__get_history_collection_instance( trans, encoded_source_id )
- new_hdca = source_hdca.copy()
- parent.add_dataset_collection( new_hdca )
- trans.sa_session.add( new_hdca )
- trans.sa_session.flush()
- return source_hdca
-
- def _set_from_dict( self, trans, dataset_collection_instance, new_data ):
- # Blatantly stolen from UsesHistoryDatasetAssociationMixin.set_hda_from_dict.
-
- # send what we can down into the model
- changed = dataset_collection_instance.set_from_dict( new_data )
- # the rest (often involving the trans) - do here
- if 'annotation' in new_data.keys() and trans.get_user():
- dataset_collection_instance.add_item_annotation( trans.sa_session, trans.get_user(), dataset_collection_instance, new_data[ 'annotation' ] )
- changed[ 'annotation' ] = new_data[ 'annotation' ]
- if 'tags' in new_data.keys() and trans.get_user():
- self.tag_manager.set_tags_from_list( trans, dataset_collection_instance, new_data[ 'tags' ], user=trans.user )
-
- if changed.keys():
- trans.sa_session.flush()
-
- return changed
-
- def _validate_and_parse_update_payload( self, payload ):
- validated_payload = {}
- for key, val in payload.items():
- if val is None:
- continue
- if key in ( 'name' ):
- val = validation.validate_and_sanitize_basestring( key, val )
- validated_payload[ key ] = val
- if key in ( 'deleted', 'visible' ):
- validated_payload[ key ] = validation.validate_boolean( key, val )
- elif key == 'tags':
- validated_payload[ key ] = validation.validate_and_sanitize_basestring_list( key, val )
- return validated_payload
-
- def history_dataset_collections(self, history, query):
- collections = history.active_dataset_collections
- collections = filter( query.direct_match, collections )
- return collections
-
- def __persist( self, dataset_collection_instance ):
- context = self.model.context
- context.add( dataset_collection_instance )
- context.flush()
- return dataset_collection_instance
-
- def __recursively_create_collections( self, trans, element_identifiers ):
- for index, element_identifier in enumerate( element_identifiers ):
- try:
- if not element_identifier[ "src" ] == "new_collection":
- # not a new collection, keep moving...
- continue
- except KeyError:
- # Not a dictionary, just an id of an HDA - move along.
- continue
-
- # element identifier is a dict with src new_collection...
- collection_type = element_identifier.get( "collection_type", None )
- collection = self.__create_dataset_collection(
- trans=trans,
- collection_type=collection_type,
- element_identifiers=element_identifier[ "element_identifiers" ],
- )
- element_identifier[ "__object__" ] = collection
-
- return element_identifiers
-
- def __load_elements( self, trans, element_identifiers ):
- elements = odict.odict()
- for element_identifier in element_identifiers:
- elements[ element_identifier[ "name" ] ] = self.__load_element( trans, element_identifier )
- return elements
-
- def __load_element( self, trans, element_identifier ):
- #if not isinstance( element_identifier, dict ):
- # # Is allowing this to just be the id of an hda too clever? Somewhat
- # # consistent with other API methods though.
- # element_identifier = dict( src='hda', id=str( element_identifier ) )
-
- # Previously created collection already found in request, just pass
- # through as is.
- if "__object__" in element_identifier:
- return element_identifier[ "__object__" ]
-
- # dateset_identifier is dict {src=hda|ldda|hdca|new_collection, id=<encoded_id>}
- try:
- src_type = element_identifier.get( 'src', 'hda' )
- except AttributeError:
- raise MessageException( "Dataset collection element definition (%s) not dictionary-like." % element_identifier )
- encoded_id = element_identifier.get( 'id', None )
- if not src_type or not encoded_id:
- raise RequestParameterInvalidException( "Problem decoding element identifier %s" % element_identifier )
-
- if src_type == 'hda':
- decoded_id = int( trans.app.security.decode_id( encoded_id ) )
- element = self.hda_manager.get( trans, decoded_id, check_ownership=False )
- elif src_type == 'ldda':
- element = self.ldda_manager.get( trans, encoded_id )
- elif src_type == 'hdca':
- # TODO: Option to copy? Force copy? Copy or allow if not owned?
- element = self.__get_history_collection_instance( trans, encoded_id ).collection
- # TODO: ldca.
- else:
- raise RequestParameterInvalidException( "Unknown src_type parameter supplied '%s'." % src_type )
- return element
-
- def match_collections( self, collections_to_match ):
- """
- May seem odd to place it here, but planning to grow sophistication and
- get plugin types involved so it will likely make sense in the future.
- """
- return MatchingCollections.for_collections( collections_to_match, self.collection_type_descriptions )
-
- def get_dataset_collection_instance( self, trans, instance_type, id, **kwds ):
- """
- """
- if instance_type == "history":
- return self.__get_history_collection_instance( trans, id, **kwds )
- elif instance_type == "library":
- return self.__get_library_collection_instance( trans, id, **kwds )
-
- def get_dataset_collection( self, trans, encoded_id ):
- collection_id = int( trans.app.security.decode_id( encoded_id ) )
- collection = trans.sa_session.query( trans.app.model.DatasetCollection ).get( collection_id )
- return collection
-
- def __get_history_collection_instance( self, trans, id, check_ownership=False, check_accessible=True ):
- instance_id = int( trans.app.security.decode_id( id ) )
- collection_instance = trans.sa_session.query( trans.app.model.HistoryDatasetCollectionAssociation ).get( instance_id )
- self.history_manager.secure( trans, collection_instance.history, check_ownership=check_ownership, check_accessible=check_accessible )
- return collection_instance
-
- def __get_library_collection_instance( self, trans, id, check_ownership=False, check_accessible=True ):
- if check_ownership:
- raise NotImplemented( "Functionality (getting library dataset collection with ownership check) unimplemented." )
- instance_id = int( trans.security.decode_id( id ) )
- collection_instance = trans.sa_session.query( trans.app.model.LibraryDatasetCollectionAssociation ).get( instance_id )
- if check_accessible:
- if not trans.app.security_agent.can_access_library_item( trans.get_current_user_roles(), collection_instance, trans.user ):
- raise ItemAccessibilityException( "LibraryDatasetCollectionAssociation is not accessible to the current user", type='error' )
- return collection_instance
diff -r 355aee34a371c99f9251b965ea625066a80419ea -r dd31ab49162d3faa30818947a80a6165c2f0b4c7 lib/galaxy/managers/collections.py
--- a/lib/galaxy/managers/collections.py
+++ b/lib/galaxy/managers/collections.py
@@ -1,1 +1,291 @@
-""" Future home of dataset collections managers. """
+from galaxy.dataset_collections.registry import DatasetCollectionTypesRegistry
+from galaxy.dataset_collections.matching import MatchingCollections
+from galaxy.dataset_collections.type_description import CollectionTypeDescriptionFactory
+
+from galaxy import model
+from galaxy.exceptions import MessageException
+from galaxy.exceptions import ItemAccessibilityException
+from galaxy.exceptions import RequestParameterInvalidException
+from galaxy.managers import hdas # TODO: Refactor all mixin use into managers.
+from galaxy.managers import histories
+from galaxy.managers import lddas
+from galaxy.managers import tags
+from galaxy.managers.collections_util import validate_input_element_identifiers
+from galaxy.util import validation
+from galaxy.util import odict
+
+import logging
+log = logging.getLogger( __name__ )
+
+
+ERROR_INVALID_ELEMENTS_SPECIFICATION = "Create called with invalid parameters, must specify element identifiers."
+ERROR_NO_COLLECTION_TYPE = "Create called without specifing a collection type."
+
+
+class DatasetCollectionManager( object ):
+ """
+ Abstraction for interfacing with dataset collections instance - ideally abstarcts
+ out model and plugin details.
+ """
+
+ def __init__( self, app ):
+ self.type_registry = DatasetCollectionTypesRegistry( app )
+ self.collection_type_descriptions = CollectionTypeDescriptionFactory( self.type_registry )
+ self.model = app.model
+ self.security = app.security
+ self.hda_manager = hdas.HDAManager()
+ self.history_manager = histories.HistoryManager()
+ self.tag_manager = tags.TagsManager( app )
+ self.ldda_manager = lddas.LDDAManager( )
+
+ def create(
+ self,
+ trans,
+ parent, # PRECONDITION: security checks on ability to add to parent occurred during load.
+ name,
+ collection_type,
+ element_identifiers=None,
+ elements=None,
+ implicit_collection_info=None,
+ ):
+ """
+ """
+ # Trust embedded, newly created objects created by tool subsystem.
+ trusted_identifiers = implicit_collection_info is not None
+
+ if element_identifiers and not trusted_identifiers:
+ validate_input_element_identifiers( element_identifiers )
+
+ dataset_collection = self.__create_dataset_collection(
+ trans=trans,
+ collection_type=collection_type,
+ element_identifiers=element_identifiers,
+ elements=elements,
+ )
+ if isinstance( parent, model.History ):
+ dataset_collection_instance = self.model.HistoryDatasetCollectionAssociation(
+ collection=dataset_collection,
+ name=name,
+ )
+ if implicit_collection_info:
+ for input_name, input_collection in implicit_collection_info[ "implicit_inputs" ]:
+ dataset_collection_instance.add_implicit_input_collection( input_name, input_collection )
+ for output_dataset in implicit_collection_info.get( "outputs" ):
+ output_dataset.hidden_beneath_collection_instance = dataset_collection_instance
+ trans.sa_session.add( output_dataset )
+
+ dataset_collection_instance.implicit_output_name = implicit_collection_info[ "implicit_output_name" ]
+ log.debug("Created collection with %d elements" % ( len( dataset_collection_instance.collection.elements ) ) )
+ # Handle setting hid
+ parent.add_dataset_collection( dataset_collection_instance )
+ elif isinstance( parent, model.LibraryFolder ):
+ dataset_collection_instance = self.model.LibraryDatasetCollectionAssociation(
+ collection=dataset_collection,
+ folder=parent,
+ name=name,
+ )
+ else:
+ message = "Internal logic error - create called with unknown parent type %s" % type( parent )
+ log.exception( message )
+ raise MessageException( message )
+
+ return self.__persist( dataset_collection_instance )
+
+ def __create_dataset_collection(
+ self,
+ trans,
+ collection_type,
+ element_identifiers=None,
+ elements=None,
+ ):
+ if element_identifiers is None and elements is None:
+ raise RequestParameterInvalidException( ERROR_INVALID_ELEMENTS_SPECIFICATION )
+ if not collection_type:
+ raise RequestParameterInvalidException( ERROR_NO_COLLECTION_TYPE )
+ collection_type_description = self.collection_type_descriptions.for_collection_type( collection_type )
+ # If we have elements, this is an internal request, don't need to load
+ # objects from identifiers.
+ if elements is None:
+ if collection_type_description.has_subcollections( ):
+ # Nested collection - recursively create collections and update identifiers.
+ self.__recursively_create_collections( trans, element_identifiers )
+ elements = self.__load_elements( trans, element_identifiers )
+ # else if elements is set, it better be an ordered dict!
+
+ type_plugin = collection_type_description.rank_type_plugin()
+ dataset_collection = type_plugin.build_collection( elements )
+ dataset_collection.collection_type = collection_type
+ return dataset_collection
+
+ def delete( self, trans, instance_type, id ):
+ dataset_collection_instance = self.get_dataset_collection_instance( trans, instance_type, id, check_ownership=True )
+ dataset_collection_instance.deleted = True
+ trans.sa_session.add( dataset_collection_instance )
+ trans.sa_session.flush( )
+
+ def update( self, trans, instance_type, id, payload ):
+ dataset_collection_instance = self.get_dataset_collection_instance( trans, instance_type, id, check_ownership=True )
+ if trans.user is None:
+ anon_allowed_payload = {}
+ if 'deleted' in payload:
+ anon_allowed_payload[ 'deleted' ] = payload[ 'deleted' ]
+ if 'visible' in payload:
+ anon_allowed_payload[ 'visible' ] = payload[ 'visible' ]
+ payload = self._validate_and_parse_update_payload( anon_allowed_payload )
+ else:
+ payload = self._validate_and_parse_update_payload( payload )
+ changed = self._set_from_dict( trans, dataset_collection_instance, payload )
+ return changed
+
+ def copy(
+ self,
+ trans,
+ parent, # PRECONDITION: security checks on ability to add to parent occurred during load.
+ source,
+ encoded_source_id,
+ ):
+ assert source == "hdca" # for now
+ source_hdca = self.__get_history_collection_instance( trans, encoded_source_id )
+ new_hdca = source_hdca.copy()
+ parent.add_dataset_collection( new_hdca )
+ trans.sa_session.add( new_hdca )
+ trans.sa_session.flush()
+ return source_hdca
+
+ def _set_from_dict( self, trans, dataset_collection_instance, new_data ):
+ # Blatantly stolen from UsesHistoryDatasetAssociationMixin.set_hda_from_dict.
+
+ # send what we can down into the model
+ changed = dataset_collection_instance.set_from_dict( new_data )
+ # the rest (often involving the trans) - do here
+ if 'annotation' in new_data.keys() and trans.get_user():
+ dataset_collection_instance.add_item_annotation( trans.sa_session, trans.get_user(), dataset_collection_instance, new_data[ 'annotation' ] )
+ changed[ 'annotation' ] = new_data[ 'annotation' ]
+ if 'tags' in new_data.keys() and trans.get_user():
+ self.tag_manager.set_tags_from_list( trans, dataset_collection_instance, new_data[ 'tags' ], user=trans.user )
+
+ if changed.keys():
+ trans.sa_session.flush()
+
+ return changed
+
+ def _validate_and_parse_update_payload( self, payload ):
+ validated_payload = {}
+ for key, val in payload.items():
+ if val is None:
+ continue
+ if key in ( 'name' ):
+ val = validation.validate_and_sanitize_basestring( key, val )
+ validated_payload[ key ] = val
+ if key in ( 'deleted', 'visible' ):
+ validated_payload[ key ] = validation.validate_boolean( key, val )
+ elif key == 'tags':
+ validated_payload[ key ] = validation.validate_and_sanitize_basestring_list( key, val )
+ return validated_payload
+
+ def history_dataset_collections(self, history, query):
+ collections = history.active_dataset_collections
+ collections = filter( query.direct_match, collections )
+ return collections
+
+ def __persist( self, dataset_collection_instance ):
+ context = self.model.context
+ context.add( dataset_collection_instance )
+ context.flush()
+ return dataset_collection_instance
+
+ def __recursively_create_collections( self, trans, element_identifiers ):
+ for index, element_identifier in enumerate( element_identifiers ):
+ try:
+ if not element_identifier[ "src" ] == "new_collection":
+ # not a new collection, keep moving...
+ continue
+ except KeyError:
+ # Not a dictionary, just an id of an HDA - move along.
+ continue
+
+ # element identifier is a dict with src new_collection...
+ collection_type = element_identifier.get( "collection_type", None )
+ collection = self.__create_dataset_collection(
+ trans=trans,
+ collection_type=collection_type,
+ element_identifiers=element_identifier[ "element_identifiers" ],
+ )
+ element_identifier[ "__object__" ] = collection
+
+ return element_identifiers
+
+ def __load_elements( self, trans, element_identifiers ):
+ elements = odict.odict()
+ for element_identifier in element_identifiers:
+ elements[ element_identifier[ "name" ] ] = self.__load_element( trans, element_identifier )
+ return elements
+
+ def __load_element( self, trans, element_identifier ):
+ #if not isinstance( element_identifier, dict ):
+ # # Is allowing this to just be the id of an hda too clever? Somewhat
+ # # consistent with other API methods though.
+ # element_identifier = dict( src='hda', id=str( element_identifier ) )
+
+ # Previously created collection already found in request, just pass
+ # through as is.
+ if "__object__" in element_identifier:
+ return element_identifier[ "__object__" ]
+
+ # dateset_identifier is dict {src=hda|ldda|hdca|new_collection, id=<encoded_id>}
+ try:
+ src_type = element_identifier.get( 'src', 'hda' )
+ except AttributeError:
+ raise MessageException( "Dataset collection element definition (%s) not dictionary-like." % element_identifier )
+ encoded_id = element_identifier.get( 'id', None )
+ if not src_type or not encoded_id:
+ raise RequestParameterInvalidException( "Problem decoding element identifier %s" % element_identifier )
+
+ if src_type == 'hda':
+ decoded_id = int( trans.app.security.decode_id( encoded_id ) )
+ element = self.hda_manager.get( trans, decoded_id, check_ownership=False )
+ elif src_type == 'ldda':
+ element = self.ldda_manager.get( trans, encoded_id )
+ elif src_type == 'hdca':
+ # TODO: Option to copy? Force copy? Copy or allow if not owned?
+ element = self.__get_history_collection_instance( trans, encoded_id ).collection
+ # TODO: ldca.
+ else:
+ raise RequestParameterInvalidException( "Unknown src_type parameter supplied '%s'." % src_type )
+ return element
+
+ def match_collections( self, collections_to_match ):
+ """
+ May seem odd to place it here, but planning to grow sophistication and
+ get plugin types involved so it will likely make sense in the future.
+ """
+ return MatchingCollections.for_collections( collections_to_match, self.collection_type_descriptions )
+
+ def get_dataset_collection_instance( self, trans, instance_type, id, **kwds ):
+ """
+ """
+ if instance_type == "history":
+ return self.__get_history_collection_instance( trans, id, **kwds )
+ elif instance_type == "library":
+ return self.__get_library_collection_instance( trans, id, **kwds )
+
+ def get_dataset_collection( self, trans, encoded_id ):
+ collection_id = int( trans.app.security.decode_id( encoded_id ) )
+ collection = trans.sa_session.query( trans.app.model.DatasetCollection ).get( collection_id )
+ return collection
+
+ def __get_history_collection_instance( self, trans, id, check_ownership=False, check_accessible=True ):
+ instance_id = int( trans.app.security.decode_id( id ) )
+ collection_instance = trans.sa_session.query( trans.app.model.HistoryDatasetCollectionAssociation ).get( instance_id )
+ self.history_manager.secure( trans, collection_instance.history, check_ownership=check_ownership, check_accessible=check_accessible )
+ return collection_instance
+
+ def __get_library_collection_instance( self, trans, id, check_ownership=False, check_accessible=True ):
+ if check_ownership:
+ raise NotImplemented( "Functionality (getting library dataset collection with ownership check) unimplemented." )
+ instance_id = int( trans.security.decode_id( id ) )
+ collection_instance = trans.sa_session.query( trans.app.model.LibraryDatasetCollectionAssociation ).get( instance_id )
+ if check_accessible:
+ if not trans.app.security_agent.can_access_library_item( trans.get_current_user_roles(), collection_instance, trans.user ):
+ raise ItemAccessibilityException( "LibraryDatasetCollectionAssociation is not accessible to the current user", type='error' )
+ return collection_instance
https://bitbucket.org/galaxy/galaxy-central/commits/d2ec0f230bda/
Changeset: d2ec0f230bda
User: jmchilton
Date: 2014-09-11 22:01:08
Summary: Work on workflow module testing.
Affected #: 3 files
diff -r dd31ab49162d3faa30818947a80a6165c2f0b4c7 -r d2ec0f230bdaed4ce52607b6ac1b6d5348dc1834 lib/galaxy/workflow/modules.py
--- a/lib/galaxy/workflow/modules.py
+++ b/lib/galaxy/workflow/modules.py
@@ -120,6 +120,11 @@
## ---- Run time ---------------------------------------------------------
def get_runtime_inputs( self ):
+ """ Used internally to modules and when displaying inputs in display
+ and run workflow templates. The ToolModule doesn't implement this and
+ these templates contain specialized logic for dealing with the tool and
+ state directly in these cases.
+ """
raise TypeError( "Abstract method" )
def encode_runtime_state( self, trans, state ):
diff -r dd31ab49162d3faa30818947a80a6165c2f0b4c7 -r d2ec0f230bdaed4ce52607b6ac1b6d5348dc1834 test/unit/workflows/test_modules.py
--- a/test/unit/workflows/test_modules.py
+++ b/test/unit/workflows/test_modules.py
@@ -1,16 +1,19 @@
from galaxy import eggs
eggs.require( "mock" )
-
+import json
import mock
+from galaxy import model
+
from galaxy.workflow import modules
+from galaxy.tools import parameters
from .workflow_support import MockTrans
def test_input_has_no_errors():
trans = MockTrans()
- input_step_module = modules.module_factory.new( trans, 'data_input' )
+ input_step_module = modules.module_factory.new( trans, "data_input" )
assert not input_step_module.get_errors()
@@ -18,15 +21,129 @@
trans = MockTrans()
mock_tool = mock.Mock()
trans.app.toolbox.tools[ "cat1" ] = mock_tool
- tool_module = modules.module_factory.new( trans, 'tool', tool_id="cat1" )
+ tool_module = modules.module_factory.new( trans, "tool", tool_id="cat1" )
assert not tool_module.get_errors()
+def test_data_input_default_state():
+ trans = MockTrans()
+ module = modules.module_factory.new( trans, "data_input" )
+ __assert_has_runtime_input( module, label="Input Dataset" )
+
+
+def test_data_input_modified_state():
+ module = __from_state( {
+ "type": "data_input",
+ "tool_state": json.dumps({ "name": "Cool Input" }),
+ } )
+ __assert_has_runtime_input( module, label="Cool Input" )
+
+
+def test_data_input_step_modified_state():
+ module = __from_step(
+ type="data_input",
+ tool_inputs={
+ "name": "Cool Input",
+ },
+ )
+ __assert_has_runtime_input( module, label="Cool Input" )
+
+
+def test_data_input_compute_state_default():
+ module = __from_step(
+ type="data_input",
+ )
+ state, errors = module.compute_state( module.trans )
+ assert not errors
+ assert 'input' in state.inputs
+ assert state.inputs[ 'input' ] is None
+
+
+def test_data_input_compute_state_args():
+ module = __from_step(
+ type="data_input",
+ )
+ tool_state = module.encode_runtime_state( module.trans, module.test_step.state )
+
+ hda = model.HistoryDatasetAssociation()
+ with mock.patch('galaxy.workflow.modules.check_param') as check_method:
+ check_method.return_value = ( hda, None )
+ state, errors = module.compute_state( module.trans, { 'input': 4, 'tool_state': tool_state } )
+
+ assert not errors
+ assert 'input' in state.inputs
+ assert state.inputs[ 'input' ] is hda
+
+
+def test_data_collection_input_default_state():
+ trans = MockTrans()
+ module = modules.module_factory.new( trans, "data_collection_input" )
+ __assert_has_runtime_input( module, label="Input Dataset Collection", collection_type="list" )
+
+
+def test_data_input_collection_modified_state():
+ module = __from_state( {
+ "type": "data_collection_input",
+ "tool_state": json.dumps({ "name": "Cool Input Collection", "collection_type": "list:paired" }),
+ } )
+ __assert_has_runtime_input( module, label="Cool Input Collection", collection_type="list:paired" )
+
+
+def test_data_input_collection_step_modified_state():
+ module = __from_step(
+ type="data_collection_input",
+ tool_inputs={
+ "name": "Cool Input Collection",
+ "collection_type": "list:paired",
+ },
+ )
+ __assert_has_runtime_input( module, label="Cool Input Collection", collection_type="list:paired" )
+
+
def test_cannot_create_tool_modules_for_missing_tools():
trans = MockTrans()
exception = False
try:
- modules.module_factory.new( trans, 'tool', tool_id="cat1" )
+ modules.module_factory.new( trans, "tool", tool_id="cat1" )
except Exception:
exception = True
assert exception
+
+
+def __assert_has_runtime_input( module, label=None, collection_type=None ):
+ inputs = module.get_runtime_inputs()
+ assert len( inputs ) == 1
+ assert "input" in inputs
+
+ input_param = inputs[ "input" ]
+ if label is not None:
+ assert input_param.get_label() == label, input_param.get_label()
+ if collection_type is not None:
+ assert input_param.collection_type == collection_type
+ return input_param
+
+
+def __from_state( state ):
+ trans = MockTrans()
+ module = modules.module_factory.from_dict( trans, state )
+ return module
+
+
+def __from_step( **kwds ):
+ trans = MockTrans()
+ step = __step(
+ **kwds
+ )
+ injector = modules.WorkflowModuleInjector( trans )
+ injector.inject( step )
+ module = step.module
+ module.test_step = step
+ return module
+
+
+def __step( **kwds ):
+ step = model.WorkflowStep()
+ for key, value in kwds.iteritems():
+ setattr( step, key, value )
+
+ return step
diff -r dd31ab49162d3faa30818947a80a6165c2f0b4c7 -r d2ec0f230bdaed4ce52607b6ac1b6d5348dc1834 test/unit/workflows/workflow_support.py
--- a/test/unit/workflows/workflow_support.py
+++ b/test/unit/workflows/workflow_support.py
@@ -11,13 +11,25 @@
class TestApp( object ):
def __init__( self ):
- self.config = bunch.Bunch( )
+ self.config = bunch.Bunch(
+ tool_secret="awesome_secret",
+ )
self.model = mapping.init(
"/tmp",
"sqlite:///:memory:",
create_tables=True
)
self.toolbox = TestToolbox()
+ self.datatypes_registry = TestDatatypesRegistry()
+
+
+class TestDatatypesRegistry( object ):
+
+ def __init__( self ):
+ pass
+
+ def get_datatype_by_extension( self, ext ):
+ return ext
class TestToolbox( object ):
https://bitbucket.org/galaxy/galaxy-central/commits/b8520d9c8269/
Changeset: b8520d9c8269
User: jmchilton
Date: 2014-09-11 22:01:08
Summary: Allow uuid values in to_dict.
Affected #: 1 file
diff -r d2ec0f230bdaed4ce52607b6ac1b6d5348dc1834 -r b8520d9c8269c4c7deca6418d54f2e722886073e lib/galaxy/model/item_attrs.py
--- a/lib/galaxy/model/item_attrs.py
+++ b/lib/galaxy/model/item_attrs.py
@@ -4,6 +4,7 @@
import galaxy
import logging
import datetime
+import uuid
log = logging.getLogger( __name__ )
@@ -186,6 +187,8 @@
return value_mapper.get( key )( item )
if type(item) == datetime.datetime:
return item.isoformat()
+ elif type(item) == uuid.UUID:
+ return str(item)
# Leaving this for future reference, though we may want a more
# generic way to handle special type mappings going forward.
# If the item is of a class that needs to be 'stringified' before being put into a JSON data structure
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
Branch: refs/tags/0.3
Home: https://github.com/galaxyproject/ansible-pulsar
1
0
[galaxyproject/ansible-pulsar] 43d526: Handle install environments for dependencies that ...
by GitHub 11 Sep '14
by GitHub 11 Sep '14
11 Sep '14
Branch: refs/heads/master
Home: https://github.com/galaxyproject/ansible-pulsar
Commit: 43d52683a342f6788a0751c4737ac376aafcb271
https://github.com/galaxyproject/ansible-pulsar/commit/43d52683a342f6788a07…
Author: Nate Coraor <nate(a)bx.psu.edu>
Date: 2014-09-11 (Thu, 11 Sep 2014)
Changed paths:
M tasks/main.yml
Log Message:
-----------
Handle install environments for dependencies that are pinned to a
specific version.
1
0
commit/galaxy-central: carlfeberhard: Fix to 618b02d13329: remove console, add documentation
by commits-noreply@bitbucket.org 11 Sep '14
by commits-noreply@bitbucket.org 11 Sep '14
11 Sep '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/da6e8248d7b4/
Changeset: da6e8248d7b4
User: carlfeberhard
Date: 2014-09-11 20:11:37
Summary: Fix to 618b02d13329: remove console, add documentation
Affected #: 7 files
diff -r 618b02d13329adf2d01b72e9743a8fa00192c6fd -r da6e8248d7b402783e829f27ee1ab9e6ba4367d7 static/scripts/mvc/collection/collection-li.js
--- a/static/scripts/mvc/collection/collection-li.js
+++ b/static/scripts/mvc/collection/collection-li.js
@@ -47,6 +47,7 @@
},
// ......................................................................... foldout
+ /** override to add linktarget to sub-panel */
_getFoldoutPanelOptions : function(){
var options = FoldoutListItemView.prototype._getFoldoutPanelOptions.call( this );
return _.extend( options, {
@@ -54,7 +55,7 @@
});
},
- /** override in the case of sub-panels */
+ /** override to not catch sub-panel selectors */
$selector : function(){
return this.$( '> .selector' );
},
diff -r 618b02d13329adf2d01b72e9743a8fa00192c6fd -r da6e8248d7b402783e829f27ee1ab9e6ba4367d7 static/scripts/mvc/collection/collection-panel.js
--- a/static/scripts/mvc/collection/collection-panel.js
+++ b/static/scripts/mvc/collection/collection-panel.js
@@ -93,7 +93,7 @@
return this;
},
- /** */
+ /** Handle drill down by hiding this panels list and controls and showing the sub-panel */
_expandDrilldownPanel : function( drilldown ){
this.panelStack.push( drilldown );
// hide this panel's controls and list, set the name for back navigation, and attach to the $el
@@ -102,7 +102,7 @@
this.$el.append( drilldown.render().$el );
},
- /** */
+ /** Handle drilldown close by freeing the panel and re-rendering this panel */
_collapseDrilldownPanel : function( drilldown ){
this.panelStack.pop();
this.render();
diff -r 618b02d13329adf2d01b72e9743a8fa00192c6fd -r da6e8248d7b402783e829f27ee1ab9e6ba4367d7 static/scripts/mvc/history/history-panel-edit-current.js
--- a/static/scripts/mvc/history/history-panel-edit-current.js
+++ b/static/scripts/mvc/history/history-panel-edit-current.js
@@ -301,6 +301,7 @@
return this;
},
+ /** Handle drill down by hiding this panels list and controls and showing the sub-panel */
_expandDrilldownPanel : function( drilldown ){
this.panelStack.push( drilldown );
// hide this panel's controls and list, set the name for back navigation, and attach to the $el
@@ -309,6 +310,7 @@
this.$el.append( drilldown.render().$el );
},
+ /** Handle drilldown close by freeing the panel and re-rendering this panel */
_collapseDrilldownPanel : function( drilldown ){
this.panelStack.pop();
//TODO: MEM: free the panel
diff -r 618b02d13329adf2d01b72e9743a8fa00192c6fd -r da6e8248d7b402783e829f27ee1ab9e6ba4367d7 static/scripts/mvc/list/list-item.js
--- a/static/scripts/mvc/list/list-item.js
+++ b/static/scripts/mvc/list/list-item.js
@@ -355,9 +355,18 @@
*/
var FoldoutListItemView = ListItemView.extend({
+ /** If 'foldout': show the sub-panel inside the expanded item
+ * If 'drilldown': only fire events and handle by pub-sub
+ * (allow the panel containing this item to attach it, hide itself, etc.)
+ */
foldoutStyle : 'foldout',
+ /** Panel view class to instantiate for the sub-panel */
foldoutPanelClass : null,
+ /** override to:
+ * add attributes foldoutStyle and foldoutPanelClass for config poly
+ * disrespect attributes.expanded if drilldown
+ */
initialize : function( attributes ){
ListItemView.prototype.initialize.call( this, attributes );
//TODO: hackish
@@ -367,10 +376,10 @@
},
//TODO:?? override to exclude foldout scope?
- $ : function( selector ){
- var $found = ListItemView.prototype.$.call( this, selector );
- return $found;
- },
+ //$ : function( selector ){
+ // var $found = ListItemView.prototype.$.call( this, selector );
+ // return $found;
+ //},
/** in this override, attach the foldout panel when rendering details */
_renderDetails : function(){
@@ -391,11 +400,13 @@
return foldout;
},
+ /** Stub to return proper foldout panel class */
_getFoldoutPanelClass : function(){
// override
return this.foldoutPanelClass;
},
+ /** Stub to return proper foldout panel options */
_getFoldoutPanelOptions : function(){
return {
// propagate foldout style down
@@ -403,7 +414,7 @@
};
},
- /** */
+ /** Render the foldout panel inside the view, hiding controls */
_attachFoldout : function( foldout, $whereTo ){
$whereTo = $whereTo || this.$( '> .details' );
this.foldout = foldout.render( 0 );
@@ -412,10 +423,7 @@
return $whereTo.append( foldout.$el );
},
- /** Render and show the full, detailed body of this view including extra data and controls.
- * note: if the model does not have detailed data, fetch that data before showing the body
- * @fires expanded when a body has been expanded
- */
+ /** In this override, branch on foldoutStyle to show expanded */
expand : function(){
var view = this;
return view._fetchModelDetails()
@@ -428,6 +436,7 @@
});
},
+ /** For foldout, call render details then slide down */
_expandByFoldout : function(){
var view = this;
var $newDetails = view._renderDetails();
@@ -439,6 +448,10 @@
});
},
+ /** For drilldown, set up close handler and fire expanded:drilldown
+ * containing views can listen to this and handle other things
+ * (like hiding themselves) by listening for expanded/collapsed:drilldown
+ */
_expandByDrilldown : function(){
var view = this;
// attachment and rendering done by listener
@@ -455,6 +468,7 @@
/** underscore templates */
FoldoutListItemView.prototype.templates = (function(){
+//TODO:?? unnecessary?
// use element identifier
var detailsTemplate = BASE_MVC.wrapTemplate([
'<div class="details">',
diff -r 618b02d13329adf2d01b72e9743a8fa00192c6fd -r da6e8248d7b402783e829f27ee1ab9e6ba4367d7 static/scripts/mvc/list/list-panel.js
--- a/static/scripts/mvc/list/list-panel.js
+++ b/static/scripts/mvc/list/list-panel.js
@@ -334,15 +334,15 @@
return panel.views;
},
- /**
- */
+ /** Filter the collection to only those models that should be currently viewed */
_filterCollection : function(){
// override this
var panel = this;
return panel.collection.filter( _.bind( panel._filterItem, panel ) );
},
- /**
+ /** Should the model be viewable in the current state?
+ * Checks against this.filters and this.searchFor
*/
_filterItem : function( model ){
// override this
@@ -351,8 +351,7 @@
&& ( !panel.searchFor || model.matchesAll( panel.searchFor ) );
},
- /**
- */
+ /** Create a view for a model and set up it's listeners */
_createItemView : function( model ){
var ViewClass = this._getItemViewClass( model ),
options = _.extend( this._getItemViewOptions( model ), {
@@ -363,15 +362,13 @@
return view;
},
- /**
- */
+ /** Get the bbone view class based on the model */
_getItemViewClass : function( model ){
// override this
return this.viewClass;
},
- /**
- */
+ /** Get the options passed to the new view based on the model */
_getItemViewOptions : function( model ){
// override this
return {
@@ -384,8 +381,7 @@
};
},
- /**
- */
+ /** Set up listeners for new models */
_setUpItemViewListeners : function( view ){
var panel = this;
// send all events to the panel, re-namspaceing them with the view prefix
@@ -404,8 +400,7 @@
return panel;
},
- /**
- */
+ /** Attach views in this.views to the model based on $whereTo */
_attachItems : function( $whereTo ){
this.$list( $whereTo ).append( this.views.map( function( view ){
return view.$el;
@@ -435,8 +430,7 @@
},
// ------------------------------------------------------------------------ collection/views syncing
- /**
- */
+ /** Add a view (if the model should be viewable) to the panel */
addItemView : function( model, collection, options ){
this.log( this + '.addItemView:', model );
var panel = this;
@@ -446,6 +440,7 @@
var view = panel._createItemView( model );
panel.views.push( view );
+ // hide the empty message if only view
$( view ).queue( 'fx', [
function( next ){ panel.$emptyMessage().fadeOut( panel.fxSpeed, next ); },
function( next ){
@@ -458,13 +453,14 @@
return view;
},
- /** */
+ /** Remove a view from the panel (if found) */
removeItemView : function( model, collection, options ){
this.log( this + '.removeItemView:', model );
var panel = this,
view = panel.viewFromModel( model );
if( !view ){ return undefined; }
+ // potentially show the empty message if no views left
// use anonymous queue here - since remove can happen multiple times
$({}).queue( 'fx', [
function( next ){ view.$el.fadeOut( panel.fxSpeed, next ); },
@@ -481,18 +477,6 @@
return view;
},
- /** get views based on model
- */
- viewFromModel : function( model ){
- for( var i=0; i<this.views.length; i++ ){
- var view = this.views[i];
- if( view.model === model ){
- return view;
- }
- }
- return undefined;
- },
-
/** get views based on model.id */
viewFromModelId : function( id ){
for( var i=0; i<this.views.length; i++ ){
@@ -503,8 +487,12 @@
return undefined;
},
- /** get views based on model properties
- */
+ /** get views based on model */
+ viewFromModel : function( model ){
+ return this.viewFromModelId( model.id );
+ },
+
+ /** get views based on model properties */
viewsWhereModel : function( properties ){
return this.views.filter( function( view ){
//return view.model.matches( properties );
@@ -523,8 +511,7 @@
});
},
- /**
- */
+ /** A range of views between (and including) viewA and viewB */
viewRange : function( viewA, viewB ){
if( viewA === viewB ){ return ( viewA )?( [ viewA ] ):( [] ); }
@@ -562,7 +549,9 @@
return $where;
},
+ /** What to do on the first search entered */
_firstSearch : function( searchFor ){
+ // override to load model details if necc.
this.log( 'onFirstSearch', searchFor );
return this.searchItems( searchFor );
},
@@ -591,7 +580,6 @@
this.selecting = true;
this.$( '.list-actions' ).slideDown( speed );
_.each( this.views, function( view ){
-console.debug( view.$el );
view.showSelector( speed );
});
//this.selected = [];
@@ -749,13 +737,16 @@
'<div class="name"><%= view.title %></div>',
'</div>',
'<div class="subtitle"><%= view.subtitle %></div>',
+ // buttons, controls go here
'<div class="actions"></div>',
+ // deleted msg, etc.
'<div class="messages"></div>',
'<div class="search">',
'<div class="search-input"></div>',
'</div>',
+ // show when selectors are shown
'<div class="list-actions">',
'<div class="btn-group">',
'<button class="select-all btn btn-default"',
@@ -779,7 +770,9 @@
//=============================================================================
/** View for a model that has a sub-collection (e.g. History, DatasetCollection)
- *
+ * Allows:
+ * the model to be reset
+ * auto assign panel.collection to panel.model[ panel.modelCollectionKey ]
*
*/
var ModelListPanel = ListPanel.extend({
@@ -791,8 +784,6 @@
ListPanel.prototype.initialize.call( this, attributes );
this.selecting = ( attributes.selecting !== undefined )? attributes.selecting : false;
- // ---- instance vars
- // don't render when setting the first time
this.setModel( this.model, attributes );
},
@@ -862,8 +853,6 @@
var json = this.model? this.model.toJSON() : {},
$controls = $( this.templates.controls( json, this ) );
$newRender.find( '.controls' ).replaceWith( $controls );
- this.debug( '\t .controls:', this.$( '.controls' ) );
- this.debug( '\t $controls:', $controls );
return $controls;
},
@@ -882,6 +871,7 @@
var controlsTemplate = BASE_MVC.wrapTemplate([
'<div class="controls">',
'<div class="title">',
+//TODO: this is really the only difference - consider factoring titlebar out
'<div class="name"><%= model.name %></div>',
'</div>',
'<div class="subtitle"><%= view.subtitle %></div>',
diff -r 618b02d13329adf2d01b72e9743a8fa00192c6fd -r da6e8248d7b402783e829f27ee1ab9e6ba4367d7 static/scripts/packed/mvc/list/list-item.js
--- a/static/scripts/packed/mvc/list/list-item.js
+++ b/static/scripts/packed/mvc/list/list-item.js
@@ -1,1 +1,1 @@
-define(["mvc/base-mvc","utils/localization"],function(b,d){var e=Backbone.View.extend(b.LoggableMixin).extend({initialize:function(f){this.expanded=f.expanded||false;this.fxSpeed=f.fxSpeed||this.fxSpeed},fxSpeed:"fast",render:function(g){var f=this._buildNewRender();this._setUpBehaviors(f);this._queueNewRender(f,g);return this},_buildNewRender:function(){var f=$(this.templates.el(this.model.toJSON(),this));if(this.expanded){this.$details(f).replaceWith(this._renderDetails().show())}return f},_queueNewRender:function(g,h){h=(h===undefined)?(this.fxSpeed):(h);var f=this;$(f).queue("fx",[function(i){this.$el.fadeOut(h,i)},function(i){f._swapNewRender(g);i()},function(i){this.$el.fadeIn(h,i)},function(i){this.trigger("rendered",f);i()}])},_swapNewRender:function(f){return this.$el.empty().attr("class",this.className).append(f.children())},_setUpBehaviors:function(f){f=f||this.$el;f.find("[title]").tooltip({placement:"bottom"})},$details:function(f){f=f||this.$el;return f.find("> .details")},_renderDetails:function(){var f=$(this.templates.details(this.model.toJSON(),this));this._setUpBehaviors(f);return f},toggleExpanded:function(f){f=(f===undefined)?(!this.expanded):(f);if(f){this.expand()}else{this.collapse()}return this},expand:function(){var f=this;return f._fetchModelDetails().always(function(){var g=f._renderDetails();f.$details().replaceWith(g);f.expanded=true;f.$details().slideDown(f.fxSpeed,function(){f.trigger("expanded",f)})})},_fetchModelDetails:function(){if(!this.model.hasDetails()){return this.model.fetch()}return jQuery.when()},collapse:function(){this.debug(this+"(ExpandableView).collapse");var f=this;f.expanded=false;this.$details().slideUp(f.fxSpeed,function(){f.trigger("collapsed",f)})}});var a=e.extend(b.mixin(b.SelectableViewMixin,b.DraggableViewMixin,{tagName:"div",className:"list-item",initialize:function(f){e.prototype.initialize.call(this,f);b.SelectableViewMixin.initialize.call(this,f);b.DraggableViewMixin.initialize.call(this,f);this._setUpListeners()},_setUpListeners:function(){this.on("selectable",function(f){if(f){this.$(".primary-actions").hide()}else{this.$(".primary-actions").show()}},this);return this},_buildNewRender:function(){var f=e.prototype._buildNewRender.call(this);f.children(".warnings").replaceWith(this._renderWarnings());f.children(".title-bar").replaceWith(this._renderTitleBar());f.children(".primary-actions").append(this._renderPrimaryActions());f.find(".title-bar .subtitle").replaceWith(this._renderSubtitle());return f},_swapNewRender:function(f){e.prototype._swapNewRender.call(this,f);if(this.selectable){this.showSelector(0)}if(this.draggable){this.draggableOn()}return this.$el},_renderWarnings:function(){var f=this,h=$('<div class="warnings"></div>'),g=f.model.toJSON();_.each(f.templates.warnings,function(i){h.append($(i(g,f)))});return h},_renderTitleBar:function(){return $(this.templates.titleBar(this.model.toJSON(),this))},_renderPrimaryActions:function(){return[]},_renderSubtitle:function(){return $(this.templates.subtitle(this.model.toJSON(),this))},events:{"click .title-bar":"_clickTitleBar","keydown .title-bar":"_keyDownTitleBar","click .selector":"toggleSelect"},_clickTitleBar:function(f){f.stopPropagation();this.toggleExpanded()},_keyDownTitleBar:function(h){var f=32,g=13;if(h&&(h.type==="keydown")&&(h.keyCode===f||h.keyCode===g)){this.toggleExpanded();h.stopPropagation();return false}return true},toString:function(){var f=(this.model)?(this.model+""):("(no model)");return"ListItemView("+f+")"}}));a.prototype.templates=(function(){var h=b.wrapTemplate(['<div class="list-element">','<div class="warnings"></div>','<div class="selector">','<span class="fa fa-2x fa-square-o"></span>',"</div>",'<div class="primary-actions"></div>','<div class="title-bar"></div>','<div class="details"></div>',"</div>"]);var f={};var i=b.wrapTemplate(['<div class="title-bar clear" tabindex="0">','<span class="state-icon"></span>','<div class="title">','<span class="name"><%- element.name %></span>',"</div>",'<div class="subtitle"></div>',"</div>"],"element");var j=b.wrapTemplate(['<div class="subtitle"></div>']);var g=b.wrapTemplate(['<div class="details"></div>']);return{el:h,warnings:f,titleBar:i,subtitle:j,details:g}}());var c=a.extend({foldoutStyle:"foldout",foldoutPanelClass:null,initialize:function(f){a.prototype.initialize.call(this,f);if(this.foldoutStyle==="drilldown"){this.expanded=false}this.foldoutStyle=f.foldoutStyle||this.foldoutStyle;this.foldoutPanelClass=f.foldoutPanelClass||this.foldoutPanelClass},$:function(f){var g=a.prototype.$.call(this,f);return g},_renderDetails:function(){if(this.foldoutStyle==="drilldown"){return $()}var f=a.prototype._renderDetails.call(this);return this._attachFoldout(this._createFoldoutPanel(),f)},_createFoldoutPanel:function(){var h=this.model;var i=this._getFoldoutPanelClass(h),g=this._getFoldoutPanelOptions(h),f=new i(_.extend(g,{model:h}));return f},_getFoldoutPanelClass:function(){return this.foldoutPanelClass},_getFoldoutPanelOptions:function(){return{foldoutStyle:this.foldoutStyle}},_attachFoldout:function(f,g){g=g||this.$("> .details");this.foldout=f.render(0);f.$("> .controls").hide();return g.append(f.$el)},expand:function(){var f=this;return f._fetchModelDetails().always(function(){if(f.foldoutStyle==="foldout"){f._expandByFoldout()}else{if(f.foldoutStyle==="drilldown"){f._expandByDrilldown()}}})},_expandByFoldout:function(){var f=this;var g=f._renderDetails();f.$details().replaceWith(g);f.expanded=true;f.$details().slideDown(f.fxSpeed,function(){f.trigger("expanded",f)})},_expandByDrilldown:function(){var f=this;f.foldout=this._createFoldoutPanel();f.foldout.on("close",function(){f.trigger("collapsed:drilldown",f,f.foldout)});f.trigger("expanded:drilldown",f,f.foldout)}});c.prototype.templates=(function(){var f=b.wrapTemplate(['<div class="details">',"</div>"],"collection");return _.extend({},a.prototype.templates,{details:f})}());return{ExpandableView:e,ListItemView:a,FoldoutListItemView:c}});
\ No newline at end of file
+define(["mvc/base-mvc","utils/localization"],function(b,d){var e=Backbone.View.extend(b.LoggableMixin).extend({initialize:function(f){this.expanded=f.expanded||false;this.fxSpeed=f.fxSpeed||this.fxSpeed},fxSpeed:"fast",render:function(g){var f=this._buildNewRender();this._setUpBehaviors(f);this._queueNewRender(f,g);return this},_buildNewRender:function(){var f=$(this.templates.el(this.model.toJSON(),this));if(this.expanded){this.$details(f).replaceWith(this._renderDetails().show())}return f},_queueNewRender:function(g,h){h=(h===undefined)?(this.fxSpeed):(h);var f=this;$(f).queue("fx",[function(i){this.$el.fadeOut(h,i)},function(i){f._swapNewRender(g);i()},function(i){this.$el.fadeIn(h,i)},function(i){this.trigger("rendered",f);i()}])},_swapNewRender:function(f){return this.$el.empty().attr("class",this.className).append(f.children())},_setUpBehaviors:function(f){f=f||this.$el;f.find("[title]").tooltip({placement:"bottom"})},$details:function(f){f=f||this.$el;return f.find("> .details")},_renderDetails:function(){var f=$(this.templates.details(this.model.toJSON(),this));this._setUpBehaviors(f);return f},toggleExpanded:function(f){f=(f===undefined)?(!this.expanded):(f);if(f){this.expand()}else{this.collapse()}return this},expand:function(){var f=this;return f._fetchModelDetails().always(function(){var g=f._renderDetails();f.$details().replaceWith(g);f.expanded=true;f.$details().slideDown(f.fxSpeed,function(){f.trigger("expanded",f)})})},_fetchModelDetails:function(){if(!this.model.hasDetails()){return this.model.fetch()}return jQuery.when()},collapse:function(){this.debug(this+"(ExpandableView).collapse");var f=this;f.expanded=false;this.$details().slideUp(f.fxSpeed,function(){f.trigger("collapsed",f)})}});var a=e.extend(b.mixin(b.SelectableViewMixin,b.DraggableViewMixin,{tagName:"div",className:"list-item",initialize:function(f){e.prototype.initialize.call(this,f);b.SelectableViewMixin.initialize.call(this,f);b.DraggableViewMixin.initialize.call(this,f);this._setUpListeners()},_setUpListeners:function(){this.on("selectable",function(f){if(f){this.$(".primary-actions").hide()}else{this.$(".primary-actions").show()}},this);return this},_buildNewRender:function(){var f=e.prototype._buildNewRender.call(this);f.children(".warnings").replaceWith(this._renderWarnings());f.children(".title-bar").replaceWith(this._renderTitleBar());f.children(".primary-actions").append(this._renderPrimaryActions());f.find(".title-bar .subtitle").replaceWith(this._renderSubtitle());return f},_swapNewRender:function(f){e.prototype._swapNewRender.call(this,f);if(this.selectable){this.showSelector(0)}if(this.draggable){this.draggableOn()}return this.$el},_renderWarnings:function(){var f=this,h=$('<div class="warnings"></div>'),g=f.model.toJSON();_.each(f.templates.warnings,function(i){h.append($(i(g,f)))});return h},_renderTitleBar:function(){return $(this.templates.titleBar(this.model.toJSON(),this))},_renderPrimaryActions:function(){return[]},_renderSubtitle:function(){return $(this.templates.subtitle(this.model.toJSON(),this))},events:{"click .title-bar":"_clickTitleBar","keydown .title-bar":"_keyDownTitleBar","click .selector":"toggleSelect"},_clickTitleBar:function(f){f.stopPropagation();this.toggleExpanded()},_keyDownTitleBar:function(h){var f=32,g=13;if(h&&(h.type==="keydown")&&(h.keyCode===f||h.keyCode===g)){this.toggleExpanded();h.stopPropagation();return false}return true},toString:function(){var f=(this.model)?(this.model+""):("(no model)");return"ListItemView("+f+")"}}));a.prototype.templates=(function(){var h=b.wrapTemplate(['<div class="list-element">','<div class="warnings"></div>','<div class="selector">','<span class="fa fa-2x fa-square-o"></span>',"</div>",'<div class="primary-actions"></div>','<div class="title-bar"></div>','<div class="details"></div>',"</div>"]);var f={};var i=b.wrapTemplate(['<div class="title-bar clear" tabindex="0">','<span class="state-icon"></span>','<div class="title">','<span class="name"><%- element.name %></span>',"</div>",'<div class="subtitle"></div>',"</div>"],"element");var j=b.wrapTemplate(['<div class="subtitle"></div>']);var g=b.wrapTemplate(['<div class="details"></div>']);return{el:h,warnings:f,titleBar:i,subtitle:j,details:g}}());var c=a.extend({foldoutStyle:"foldout",foldoutPanelClass:null,initialize:function(f){a.prototype.initialize.call(this,f);if(this.foldoutStyle==="drilldown"){this.expanded=false}this.foldoutStyle=f.foldoutStyle||this.foldoutStyle;this.foldoutPanelClass=f.foldoutPanelClass||this.foldoutPanelClass},_renderDetails:function(){if(this.foldoutStyle==="drilldown"){return $()}var f=a.prototype._renderDetails.call(this);return this._attachFoldout(this._createFoldoutPanel(),f)},_createFoldoutPanel:function(){var h=this.model;var i=this._getFoldoutPanelClass(h),g=this._getFoldoutPanelOptions(h),f=new i(_.extend(g,{model:h}));return f},_getFoldoutPanelClass:function(){return this.foldoutPanelClass},_getFoldoutPanelOptions:function(){return{foldoutStyle:this.foldoutStyle}},_attachFoldout:function(f,g){g=g||this.$("> .details");this.foldout=f.render(0);f.$("> .controls").hide();return g.append(f.$el)},expand:function(){var f=this;return f._fetchModelDetails().always(function(){if(f.foldoutStyle==="foldout"){f._expandByFoldout()}else{if(f.foldoutStyle==="drilldown"){f._expandByDrilldown()}}})},_expandByFoldout:function(){var f=this;var g=f._renderDetails();f.$details().replaceWith(g);f.expanded=true;f.$details().slideDown(f.fxSpeed,function(){f.trigger("expanded",f)})},_expandByDrilldown:function(){var f=this;f.foldout=this._createFoldoutPanel();f.foldout.on("close",function(){f.trigger("collapsed:drilldown",f,f.foldout)});f.trigger("expanded:drilldown",f,f.foldout)}});c.prototype.templates=(function(){var f=b.wrapTemplate(['<div class="details">',"</div>"],"collection");return _.extend({},a.prototype.templates,{details:f})}());return{ExpandableView:e,ListItemView:a,FoldoutListItemView:c}});
\ No newline at end of file
diff -r 618b02d13329adf2d01b72e9743a8fa00192c6fd -r da6e8248d7b402783e829f27ee1ab9e6ba4367d7 static/scripts/packed/mvc/list/list-panel.js
--- a/static/scripts/packed/mvc/list/list-panel.js
+++ b/static/scripts/packed/mvc/list/list-panel.js
@@ -1,1 +1,1 @@
-define(["mvc/list/list-item","mvc/base-mvc","utils/localization"],function(d,b,c){var e=Backbone.View.extend(b.LoggableMixin).extend({viewClass:d.ListItemView,collectionClass:Backbone.Collection,tagName:"div",className:"list-panel",fxSpeed:"fast",emptyMsg:c("This list is empty"),noneFoundMsg:c("No matching items found"),searchPlaceholder:c("search"),multiselectActions:[],initialize:function(f,g){f=f||{};if(f.logger){this.logger=f.logger}this.log(this+".initialize:",f);this.fxSpeed=_.has(f,"fxSpeed")?(f.fxSpeed):(this.fxSpeed);this.filters=[];this.searchFor=f.searchFor||"";this.indicator=new LoadingIndicator(this.$el);this.selecting=(f.selecting!==undefined)?f.selecting:true;this.selected=f.selected||[];this.lastSelected=null;this.viewClass=f.viewClass||this.viewClass;this.views=[];this.collection=f.collection||(new this.collectionClass([]));this.filters=f.filters||[];this.$scrollContainer=f.$scrollContainer||this.$scrollContainer;this.title=f.title||"";this.subtitle=f.subtitle||"";this.multiselectActions=f.multiselectActions||this.multiselectActions;this.actionsPopup=null;this._setUpListeners()},freeViews:function(){_.each(this.views,function(f){f.off()});this.views=[];return this},_setUpListeners:function(){this.off();this.on("error",function(g,j,f,i,h){console.error(g,j,f,i,h)},this);this.on("loading",function(){this._showLoadingIndicator("loading...",40)},this);this.on("loading-done",function(){this._hideLoadingIndicator(40)},this);this.once("rendered",function(){this.trigger("rendered:initial",this)},this);if(this.logger){this.on("all",function(f){this.log(this+"",arguments)},this)}this._setUpCollectionListeners();this._setUpViewListeners();return this},_setUpCollectionListeners:function(){this.log(this+"._setUpCollectionListeners",this.collection);this.collection.off();this.collection.on("error",function(g,j,f,i,h){this.trigger("error",g,j,f,i,h)},this);this.collection.on("reset",function(){this.renderItems()},this);this.collection.on("add",this.addItemView,this);this.collection.on("remove",this.removeItemView,this);if(this.logger){this.collection.on("all",function(f){this.info(this+"(collection)",arguments)},this)}return this},_setUpViewListeners:function(){this.log(this+"._setUpViewListeners");this.on("view:selected",function(f,g){if(g&&g.shiftKey&&this.lastSelected){var h=this.viewFromModelId(this.lastSelected);if(h){this.selectRange(f,h)}}this.selected.push(f.model.id);this.lastSelected=f.model.id},this);this.on("view:de-selected",function(f,g){this.selected=_.without(this.selected,f.model.id)},this)},render:function(g){this.log(this+".render",g);var f=this._buildNewRender();this._setUpBehaviors(f);this._queueNewRender(f,g);return this},_buildNewRender:function(){this.debug(this+"(ListPanel)._buildNewRender");var f=$(this.templates.el({},this));this._renderControls(f);this._renderTitle(f);this._renderSubtitle(f);this._renderSearch(f);this.renderItems(f);return f},_renderControls:function(g){this.debug(this+"(ListPanel)._renderControls");var f=$(this.templates.controls({},this));g.find(".controls").replaceWith(f);return f},_renderTitle:function(f){},_renderSubtitle:function(f){},_queueNewRender:function(g,h){h=(h===undefined)?(this.fxSpeed):(h);var f=this;f.log("_queueNewRender:",g,h);$(f).queue("fx",[function(i){this.$el.fadeOut(h,i)},function(i){f._swapNewRender(g);i()},function(i){this.$el.fadeIn(h,i)},function(i){f.trigger("rendered",f);i()}])},_swapNewRender:function(f){this.$el.empty().attr("class",this.className).append(f.children());if(this.selecting){this.showSelectors(0)}return this},_setUpBehaviors:function(f){f=f||this.$el;f.find(".controls [title]").tooltip({placement:"bottom"});return this},$scrollContainer:function(){return this.$el.parent().parent()},$list:function(f){return(f||this.$el).find("> .list-items")},$messages:function(f){return(f||this.$el).find("> .controls .messages")},$emptyMessage:function(f){return(f||this.$el).find("> .empty-message")},renderItems:function(h){h=h||this.$el;var f=this;f.log(this+".renderItems",h);var g=f.$list(h);f.views=f._filterCollection().map(function(i){return f._createItemView(i).render(0)});g.empty();if(f.views.length){f._attachItems(h);f.$emptyMessage(h).hide()}else{f._renderEmptyMessage(h).show()}return f.views},_filterCollection:function(){var f=this;return f.collection.filter(_.bind(f._filterItem,f))},_filterItem:function(g){var f=this;return(_.every(f.filters.map(function(h){return h.call(g)})))&&(!f.searchFor||g.matchesAll(f.searchFor))},_createItemView:function(h){var i=this._getItemViewClass(h),g=_.extend(this._getItemViewOptions(h),{model:h}),f=new i(g);this._setUpItemViewListeners(f);return f},_getItemViewClass:function(f){return this.viewClass},_getItemViewOptions:function(f){return{fxSpeed:this.fxSpeed,expanded:false,selectable:this.selecting,selected:_.contains(this.selected,f.id),draggable:this.dragging}},_setUpItemViewListeners:function(g){var f=this;g.on("all",function(){var h=Array.prototype.slice.call(arguments,0);h[0]="view:"+h[0];f.trigger.apply(f,h)});return f},_attachItems:function(f){this.$list(f).append(this.views.map(function(g){return g.$el}));return this},_renderEmptyMessage:function(f){this.debug("_renderEmptyMessage",f,this.searchFor);var g=this.searchFor?this.noneFoundMsg:this.emptyMsg;return this.$emptyMessage(f).text(g)},expandAll:function(){_.each(this.views,function(f){f.expand()})},collapseAll:function(){_.each(this.views,function(f){f.collapse()})},addItemView:function(i,j,h){this.log(this+".addItemView:",i);var g=this;if(!g._filterItem(i)){return undefined}var f=g._createItemView(i);g.views.push(f);$(f).queue("fx",[function(k){g.$emptyMessage().fadeOut(g.fxSpeed,k)},function(k){g.$list().append(f.render().$el);k()}]);return f},removeItemView:function(i,j,h){this.log(this+".removeItemView:",i);var g=this,f=g.viewFromModel(i);if(!f){return undefined}$({}).queue("fx",[function(k){f.$el.fadeOut(g.fxSpeed,k)},function(k){g.views=_.without(g.views,f);f.remove();if(!g.views.length){g._renderEmptyMessage().fadeIn(g.fxSpeed,k)}else{k()}}]);return f},viewFromModel:function(g){for(var h=0;h<this.views.length;h++){var f=this.views[h];if(f.model===g){return f}}return undefined},viewFromModelId:function(g){for(var f=0;f<this.views.length;f++){if(this.views[f].model.id===g){return this.views[f]}}return undefined},viewsWhereModel:function(f){return this.views.filter(function(g){var i=g.model.toJSON();for(var h in f){if(f.hasOwnProperty(h)){if(i[h]!==g.model.get(h)){return false}}}return true})},viewRange:function(i,h){if(i===h){return(i)?([i]):([])}var g=this.views.indexOf(i),f=this.views.indexOf(h);if(g===-1||f===-1){if(g===f){return[]}return(g===-1)?([h]):([i])}return(g<f)?this.views.slice(g,f+1):this.views.slice(f,g+1)},_renderSearch:function(f){f.find(".controls .search-input").searchInput({placeholder:this.searchPlaceholder,initialVal:this.searchFor,onfirstsearch:_.bind(this._firstSearch,this),onsearch:_.bind(this.searchItems,this),onclear:_.bind(this.clearSearch,this)});return f},_firstSearch:function(f){this.log("onFirstSearch",f);return this.searchItems(f)},searchItems:function(f){this.searchFor=f;this.trigger("search:searching",f,this);this.renderItems();return this},clearSearch:function(f){this.searchFor="";this.trigger("search:clear",this);this.renderItems();return this},showSelectors:function(f){f=(f!==undefined)?(f):(this.fxSpeed);this.selecting=true;this.$(".list-actions").slideDown(f);_.each(this.views,function(g){console.debug(g.$el);g.showSelector(f)})},hideSelectors:function(f){f=(f!==undefined)?(f):(this.fxSpeed);this.selecting=false;this.$(".list-actions").slideUp(f);_.each(this.views,function(g){g.hideSelector(f)});this.selected=[];this.lastSelected=null},toggleSelectors:function(){if(!this.selecting){this.showSelectors()}else{this.hideSelectors()}},selectAll:function(f){_.each(this.views,function(g){g.select(f)})},deselectAll:function(f){this.lastSelected=null;_.each(this.views,function(g){g.deselect(f)})},selectRange:function(h,g){var f=this.viewRange(h,g);_.each(f,function(i){i.select()});return f},getSelectedViews:function(){return _.filter(this.views,function(f){return f.selected})},getSelectedModels:function(){return new this.collection.constructor(_.map(this.getSelectedViews(),function(f){return f.model}))},_showLoadingIndicator:function(g,f,h){this.debug("_showLoadingIndicator",this.indicator,g,f,h);f=(f!==undefined)?(f):(this.fxSpeed);if(!this.indicator){this.indicator=new LoadingIndicator(this.$el,this.$el.parent());this.debug("\t created",this.indicator)}if(!this.$el.is(":visible")){this.indicator.show(0,h)}else{this.$el.fadeOut(f);this.indicator.show(g,f,h)}},_hideLoadingIndicator:function(f,g){this.debug("_hideLoadingIndicator",this.indicator,f,g);f=(f!==undefined)?(f):(this.fxSpeed);if(this.indicator){this.indicator.hide(f,g)}},scrollPosition:function(){return this.$scrollContainer().scrollTop()},scrollTo:function(f){this.$scrollContainer().scrollTop(f);return this},scrollToTop:function(){this.$scrollContainer().scrollTop(0);return this},scrollToItem:function(f){if(!f){return this}var g=f.$el.offset().top;this.$scrollContainer().scrollTop(g);return this},scrollToId:function(f){return this.scrollToItem(this.viewFromModelId(f))},events:{"click .select-all":"selectAll","click .deselect-all":"deselectAll"},toString:function(){return"ListPanel("+this.collection+")"}});e.prototype.templates=(function(){var g=b.wrapTemplate(["<div>",'<div class="controls"></div>','<div class="list-items"></div>','<div class="empty-message infomessagesmall"></div>',"</div>"]);var f=b.wrapTemplate(['<div class="controls">','<div class="title">','<div class="name"><%= view.title %></div>',"</div>",'<div class="subtitle"><%= view.subtitle %></div>','<div class="actions"></div>','<div class="messages"></div>','<div class="search">','<div class="search-input"></div>',"</div>",'<div class="list-actions">','<div class="btn-group">','<button class="select-all btn btn-default"','data-mode="select">',c("All"),"</button>",'<button class="deselect-all btn btn-default"','data-mode="select">',c("None"),"</button>","</div>","</div>","</div>"]);return{el:g,controls:f}}());var a=e.extend({modelCollectionKey:"contents",initialize:function(f){e.prototype.initialize.call(this,f);this.selecting=(f.selecting!==undefined)?f.selecting:false;this.setModel(this.model,f)},setModel:function(g,f){f=f||{};this.debug(this+".setModel:",g,f);this.freeModel();this.freeViews();if(g){this.model=g;if(this.logger){this.model.logger=this.logger}this._setUpModelListeners();this.collection.off();this.collection=(this.model[this.modelCollectionKey])?this.model[this.modelCollectionKey]:(f.collection||(new this.collectionClass([])));this._setUpCollectionListeners();this.trigger("new-model",this)}return this},freeModel:function(){if(this.model){this.stopListening(this.model)}return this},_setUpModelListeners:function(){this.log(this+"._setUpModelListeners",this.model);this.model.on("error",function(){this.trigger.apply(panel,arguments)},this);return this},_renderControls:function(g){this.debug(this+"(ListPanel)._renderControls");var h=this.model?this.model.toJSON():{},f=$(this.templates.controls(h,this));g.find(".controls").replaceWith(f);this.debug("\t .controls:",this.$(".controls"));this.debug("\t $controls:",f);return f},toString:function(){return"ModelListPanel("+this.model+")"}});a.prototype.templates=(function(){var f=b.wrapTemplate(['<div class="controls">','<div class="title">','<div class="name"><%= model.name %></div>',"</div>",'<div class="subtitle"><%= view.subtitle %></div>','<div class="actions"></div>','<div class="messages"></div>','<div class="search">','<div class="search-input"></div>',"</div>",'<div class="list-actions">','<div class="btn-group">','<button class="select-all btn btn-default"','data-mode="select">',c("All"),"</button>",'<button class="deselect-all btn btn-default"','data-mode="select">',c("None"),"</button>","</div>","</div>","</div>"]);return _.extend(_.clone(e.prototype.templates),{controls:f})}());return{ListPanel:e,ModelListPanel:a}});
\ No newline at end of file
+define(["mvc/list/list-item","mvc/base-mvc","utils/localization"],function(d,b,c){var e=Backbone.View.extend(b.LoggableMixin).extend({viewClass:d.ListItemView,collectionClass:Backbone.Collection,tagName:"div",className:"list-panel",fxSpeed:"fast",emptyMsg:c("This list is empty"),noneFoundMsg:c("No matching items found"),searchPlaceholder:c("search"),multiselectActions:[],initialize:function(f,g){f=f||{};if(f.logger){this.logger=f.logger}this.log(this+".initialize:",f);this.fxSpeed=_.has(f,"fxSpeed")?(f.fxSpeed):(this.fxSpeed);this.filters=[];this.searchFor=f.searchFor||"";this.indicator=new LoadingIndicator(this.$el);this.selecting=(f.selecting!==undefined)?f.selecting:true;this.selected=f.selected||[];this.lastSelected=null;this.viewClass=f.viewClass||this.viewClass;this.views=[];this.collection=f.collection||(new this.collectionClass([]));this.filters=f.filters||[];this.$scrollContainer=f.$scrollContainer||this.$scrollContainer;this.title=f.title||"";this.subtitle=f.subtitle||"";this.multiselectActions=f.multiselectActions||this.multiselectActions;this.actionsPopup=null;this._setUpListeners()},freeViews:function(){_.each(this.views,function(f){f.off()});this.views=[];return this},_setUpListeners:function(){this.off();this.on("error",function(g,j,f,i,h){console.error(g,j,f,i,h)},this);this.on("loading",function(){this._showLoadingIndicator("loading...",40)},this);this.on("loading-done",function(){this._hideLoadingIndicator(40)},this);this.once("rendered",function(){this.trigger("rendered:initial",this)},this);if(this.logger){this.on("all",function(f){this.log(this+"",arguments)},this)}this._setUpCollectionListeners();this._setUpViewListeners();return this},_setUpCollectionListeners:function(){this.log(this+"._setUpCollectionListeners",this.collection);this.collection.off();this.collection.on("error",function(g,j,f,i,h){this.trigger("error",g,j,f,i,h)},this);this.collection.on("reset",function(){this.renderItems()},this);this.collection.on("add",this.addItemView,this);this.collection.on("remove",this.removeItemView,this);if(this.logger){this.collection.on("all",function(f){this.info(this+"(collection)",arguments)},this)}return this},_setUpViewListeners:function(){this.log(this+"._setUpViewListeners");this.on("view:selected",function(f,g){if(g&&g.shiftKey&&this.lastSelected){var h=this.viewFromModelId(this.lastSelected);if(h){this.selectRange(f,h)}}this.selected.push(f.model.id);this.lastSelected=f.model.id},this);this.on("view:de-selected",function(f,g){this.selected=_.without(this.selected,f.model.id)},this)},render:function(g){this.log(this+".render",g);var f=this._buildNewRender();this._setUpBehaviors(f);this._queueNewRender(f,g);return this},_buildNewRender:function(){this.debug(this+"(ListPanel)._buildNewRender");var f=$(this.templates.el({},this));this._renderControls(f);this._renderTitle(f);this._renderSubtitle(f);this._renderSearch(f);this.renderItems(f);return f},_renderControls:function(g){this.debug(this+"(ListPanel)._renderControls");var f=$(this.templates.controls({},this));g.find(".controls").replaceWith(f);return f},_renderTitle:function(f){},_renderSubtitle:function(f){},_queueNewRender:function(g,h){h=(h===undefined)?(this.fxSpeed):(h);var f=this;f.log("_queueNewRender:",g,h);$(f).queue("fx",[function(i){this.$el.fadeOut(h,i)},function(i){f._swapNewRender(g);i()},function(i){this.$el.fadeIn(h,i)},function(i){f.trigger("rendered",f);i()}])},_swapNewRender:function(f){this.$el.empty().attr("class",this.className).append(f.children());if(this.selecting){this.showSelectors(0)}return this},_setUpBehaviors:function(f){f=f||this.$el;f.find(".controls [title]").tooltip({placement:"bottom"});return this},$scrollContainer:function(){return this.$el.parent().parent()},$list:function(f){return(f||this.$el).find("> .list-items")},$messages:function(f){return(f||this.$el).find("> .controls .messages")},$emptyMessage:function(f){return(f||this.$el).find("> .empty-message")},renderItems:function(h){h=h||this.$el;var f=this;f.log(this+".renderItems",h);var g=f.$list(h);f.views=f._filterCollection().map(function(i){return f._createItemView(i).render(0)});g.empty();if(f.views.length){f._attachItems(h);f.$emptyMessage(h).hide()}else{f._renderEmptyMessage(h).show()}return f.views},_filterCollection:function(){var f=this;return f.collection.filter(_.bind(f._filterItem,f))},_filterItem:function(g){var f=this;return(_.every(f.filters.map(function(h){return h.call(g)})))&&(!f.searchFor||g.matchesAll(f.searchFor))},_createItemView:function(h){var i=this._getItemViewClass(h),g=_.extend(this._getItemViewOptions(h),{model:h}),f=new i(g);this._setUpItemViewListeners(f);return f},_getItemViewClass:function(f){return this.viewClass},_getItemViewOptions:function(f){return{fxSpeed:this.fxSpeed,expanded:false,selectable:this.selecting,selected:_.contains(this.selected,f.id),draggable:this.dragging}},_setUpItemViewListeners:function(g){var f=this;g.on("all",function(){var h=Array.prototype.slice.call(arguments,0);h[0]="view:"+h[0];f.trigger.apply(f,h)});return f},_attachItems:function(f){this.$list(f).append(this.views.map(function(g){return g.$el}));return this},_renderEmptyMessage:function(f){this.debug("_renderEmptyMessage",f,this.searchFor);var g=this.searchFor?this.noneFoundMsg:this.emptyMsg;return this.$emptyMessage(f).text(g)},expandAll:function(){_.each(this.views,function(f){f.expand()})},collapseAll:function(){_.each(this.views,function(f){f.collapse()})},addItemView:function(i,j,h){this.log(this+".addItemView:",i);var g=this;if(!g._filterItem(i)){return undefined}var f=g._createItemView(i);g.views.push(f);$(f).queue("fx",[function(k){g.$emptyMessage().fadeOut(g.fxSpeed,k)},function(k){g.$list().append(f.render().$el);k()}]);return f},removeItemView:function(i,j,h){this.log(this+".removeItemView:",i);var g=this,f=g.viewFromModel(i);if(!f){return undefined}$({}).queue("fx",[function(k){f.$el.fadeOut(g.fxSpeed,k)},function(k){g.views=_.without(g.views,f);f.remove();if(!g.views.length){g._renderEmptyMessage().fadeIn(g.fxSpeed,k)}else{k()}}]);return f},viewFromModelId:function(g){for(var f=0;f<this.views.length;f++){if(this.views[f].model.id===g){return this.views[f]}}return undefined},viewFromModel:function(f){return this.viewFromModelId(f.id)},viewsWhereModel:function(f){return this.views.filter(function(g){var i=g.model.toJSON();for(var h in f){if(f.hasOwnProperty(h)){if(i[h]!==g.model.get(h)){return false}}}return true})},viewRange:function(i,h){if(i===h){return(i)?([i]):([])}var g=this.views.indexOf(i),f=this.views.indexOf(h);if(g===-1||f===-1){if(g===f){return[]}return(g===-1)?([h]):([i])}return(g<f)?this.views.slice(g,f+1):this.views.slice(f,g+1)},_renderSearch:function(f){f.find(".controls .search-input").searchInput({placeholder:this.searchPlaceholder,initialVal:this.searchFor,onfirstsearch:_.bind(this._firstSearch,this),onsearch:_.bind(this.searchItems,this),onclear:_.bind(this.clearSearch,this)});return f},_firstSearch:function(f){this.log("onFirstSearch",f);return this.searchItems(f)},searchItems:function(f){this.searchFor=f;this.trigger("search:searching",f,this);this.renderItems();return this},clearSearch:function(f){this.searchFor="";this.trigger("search:clear",this);this.renderItems();return this},showSelectors:function(f){f=(f!==undefined)?(f):(this.fxSpeed);this.selecting=true;this.$(".list-actions").slideDown(f);_.each(this.views,function(g){g.showSelector(f)})},hideSelectors:function(f){f=(f!==undefined)?(f):(this.fxSpeed);this.selecting=false;this.$(".list-actions").slideUp(f);_.each(this.views,function(g){g.hideSelector(f)});this.selected=[];this.lastSelected=null},toggleSelectors:function(){if(!this.selecting){this.showSelectors()}else{this.hideSelectors()}},selectAll:function(f){_.each(this.views,function(g){g.select(f)})},deselectAll:function(f){this.lastSelected=null;_.each(this.views,function(g){g.deselect(f)})},selectRange:function(h,g){var f=this.viewRange(h,g);_.each(f,function(i){i.select()});return f},getSelectedViews:function(){return _.filter(this.views,function(f){return f.selected})},getSelectedModels:function(){return new this.collection.constructor(_.map(this.getSelectedViews(),function(f){return f.model}))},_showLoadingIndicator:function(g,f,h){this.debug("_showLoadingIndicator",this.indicator,g,f,h);f=(f!==undefined)?(f):(this.fxSpeed);if(!this.indicator){this.indicator=new LoadingIndicator(this.$el,this.$el.parent());this.debug("\t created",this.indicator)}if(!this.$el.is(":visible")){this.indicator.show(0,h)}else{this.$el.fadeOut(f);this.indicator.show(g,f,h)}},_hideLoadingIndicator:function(f,g){this.debug("_hideLoadingIndicator",this.indicator,f,g);f=(f!==undefined)?(f):(this.fxSpeed);if(this.indicator){this.indicator.hide(f,g)}},scrollPosition:function(){return this.$scrollContainer().scrollTop()},scrollTo:function(f){this.$scrollContainer().scrollTop(f);return this},scrollToTop:function(){this.$scrollContainer().scrollTop(0);return this},scrollToItem:function(f){if(!f){return this}var g=f.$el.offset().top;this.$scrollContainer().scrollTop(g);return this},scrollToId:function(f){return this.scrollToItem(this.viewFromModelId(f))},events:{"click .select-all":"selectAll","click .deselect-all":"deselectAll"},toString:function(){return"ListPanel("+this.collection+")"}});e.prototype.templates=(function(){var g=b.wrapTemplate(["<div>",'<div class="controls"></div>','<div class="list-items"></div>','<div class="empty-message infomessagesmall"></div>',"</div>"]);var f=b.wrapTemplate(['<div class="controls">','<div class="title">','<div class="name"><%= view.title %></div>',"</div>",'<div class="subtitle"><%= view.subtitle %></div>','<div class="actions"></div>','<div class="messages"></div>','<div class="search">','<div class="search-input"></div>',"</div>",'<div class="list-actions">','<div class="btn-group">','<button class="select-all btn btn-default"','data-mode="select">',c("All"),"</button>",'<button class="deselect-all btn btn-default"','data-mode="select">',c("None"),"</button>","</div>","</div>","</div>"]);return{el:g,controls:f}}());var a=e.extend({modelCollectionKey:"contents",initialize:function(f){e.prototype.initialize.call(this,f);this.selecting=(f.selecting!==undefined)?f.selecting:false;this.setModel(this.model,f)},setModel:function(g,f){f=f||{};this.debug(this+".setModel:",g,f);this.freeModel();this.freeViews();if(g){this.model=g;if(this.logger){this.model.logger=this.logger}this._setUpModelListeners();this.collection.off();this.collection=(this.model[this.modelCollectionKey])?this.model[this.modelCollectionKey]:(f.collection||(new this.collectionClass([])));this._setUpCollectionListeners();this.trigger("new-model",this)}return this},freeModel:function(){if(this.model){this.stopListening(this.model)}return this},_setUpModelListeners:function(){this.log(this+"._setUpModelListeners",this.model);this.model.on("error",function(){this.trigger.apply(panel,arguments)},this);return this},_renderControls:function(g){this.debug(this+"(ListPanel)._renderControls");var h=this.model?this.model.toJSON():{},f=$(this.templates.controls(h,this));g.find(".controls").replaceWith(f);return f},toString:function(){return"ModelListPanel("+this.model+")"}});a.prototype.templates=(function(){var f=b.wrapTemplate(['<div class="controls">','<div class="title">','<div class="name"><%= model.name %></div>',"</div>",'<div class="subtitle"><%= view.subtitle %></div>','<div class="actions"></div>','<div class="messages"></div>','<div class="search">','<div class="search-input"></div>',"</div>",'<div class="list-actions">','<div class="btn-group">','<button class="select-all btn btn-default"','data-mode="select">',c("All"),"</button>",'<button class="deselect-all btn btn-default"','data-mode="select">',c("None"),"</button>","</div>","</div>","</div>"]);return _.extend(_.clone(e.prototype.templates),{controls:f})}());return{ListPanel:e,ModelListPanel:a}});
\ No newline at end of file
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: carlfeberhard: History panels: allow foldout display of collections in display_by_slug, pages, and /view
by commits-noreply@bitbucket.org 11 Sep '14
by commits-noreply@bitbucket.org 11 Sep '14
11 Sep '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/618b02d13329/
Changeset: 618b02d13329
User: carlfeberhard
Date: 2014-09-11 18:23:00
Summary: History panels: allow foldout display of collections in display_by_slug, pages, and /view
Affected #: 24 files
diff -r deb003947e0e02de4613912b14832944954576a5 -r 618b02d13329adf2d01b72e9743a8fa00192c6fd static/scripts/mvc/collection/collection-li.js
--- a/static/scripts/mvc/collection/collection-li.js
+++ b/static/scripts/mvc/collection/collection-li.js
@@ -6,42 +6,26 @@
], function( LIST_ITEM, DATASET_LI, BASE_MVC, _l ){
/* global Backbone, LoggableMixin */
//==============================================================================
-var ListItemView = LIST_ITEM.ListItemView;
+var FoldoutListItemView = LIST_ITEM.FoldoutListItemView,
+ ListItemView = LIST_ITEM.ListItemView;
/** @class Read only view for DatasetCollection.
*/
-var DCListItemView = ListItemView.extend(
+var DCListItemView = FoldoutListItemView.extend(
/** @lends DCListItemView.prototype */{
//TODO: may not be needed
/** logger used to record this.log messages, commonly set to console */
//logger : console,
- className : ListItemView.prototype.className + " dataset-collection",
+ className : FoldoutListItemView.prototype.className + " dataset-collection",
id : function(){
return [ 'dataset_collection', this.model.get( 'id' ) ].join( '-' );
},
- /** jq speed for effects used */
- fxSpeed : 'fast',
-
-//TODO: ununsed
- /** set up */
- initialize : function( attributes ){
- if( attributes.logger ){ this.logger = this.model.logger = attributes.logger; }
- this.log( this + '(DCListItemView).initialize:', attributes );
- ListItemView.prototype.initialize.call( this, attributes );
- },
-
- /** In this override, don't show or render any details (no need to do anything here)
- * - currently the parent control will load a panel for this collection over itself
- * @fires expanded when a body has been expanded
- */
- expand : function(){
- var view = this;
- return view._fetchModelDetails()
- .always(function(){
- view.trigger( 'expanded', view );
- });
+ /** override to add linkTarget */
+ initialize : function( attributes ){
+ FoldoutListItemView.prototype.initialize.call( this, attributes );
+ this.linkTarget = attributes.linkTarget || '_blank';
},
// ......................................................................... rendering
@@ -62,6 +46,19 @@
return $subtitle;
},
+ // ......................................................................... foldout
+ _getFoldoutPanelOptions : function(){
+ var options = FoldoutListItemView.prototype._getFoldoutPanelOptions.call( this );
+ return _.extend( options, {
+ linkTarget : this.linkTarget
+ });
+ },
+
+ /** override in the case of sub-panels */
+ $selector : function(){
+ return this.$( '> .selector' );
+ },
+
// ......................................................................... misc
/** String representation */
toString : function(){
@@ -84,7 +81,7 @@
'</div>'
], 'collection' );
- return _.extend( {}, ListItemView.prototype.templates, {
+ return _.extend( {}, FoldoutListItemView.prototype.templates, {
titleBar : titleBarTemplate
});
}());
diff -r deb003947e0e02de4613912b14832944954576a5 -r 618b02d13329adf2d01b72e9743a8fa00192c6fd static/scripts/mvc/collection/collection-panel.js
--- a/static/scripts/mvc/collection/collection-panel.js
+++ b/static/scripts/mvc/collection/collection-panel.js
@@ -9,7 +9,6 @@
TODO:
============================================================================= */
-// =============================================================================
/** @class non-editable, read-only View/Controller for a dataset collection.
*/
var _super = LIST_PANEL.ModelListPanel;
@@ -23,11 +22,11 @@
className : _super.prototype.className + ' dataset-collection-panel',
/** sub view class used for datasets */
- DatasetDCEViewClass : DC_LI.DatasetDCEListItemView,
+ DatasetDCEViewClass : DC_LI.DatasetDCEListItemView,
/** sub view class used for nested collections */
- NestedDCDCEViewClass : DC_LI.NestedDCDCEListItemView,
+ NestedDCDCEViewClass: DC_LI.NestedDCDCEListItemView,
/** key of attribute in model to assign to this.collection */
- modelCollectionKey : 'elements',
+ modelCollectionKey : 'elements',
// ......................................................................... SET UP
/** Set up the view, set up storage, bind listeners to HistoryContents events
@@ -38,16 +37,19 @@
this.linkTarget = attributes.linkTarget || '_blank';
this.hasUser = attributes.hasUser;
+
+ /** */
this.panelStack = [];
+ /** */
this.parentName = attributes.parentName;
-
- //window.collectionPanel = this;
+ /** */
+ this.foldoutStyle = attributes.foldoutStyle || 'foldout';
},
// ------------------------------------------------------------------------ sub-views
/** In this override, use model.getVisibleContents */
_filterCollection : function(){
-//TODO: should *not* be model.getVisibleContents
+//TODO: should *not* be model.getVisibleContents - visibility is not model related
return this.model.getVisibleContents();
},
@@ -69,59 +71,41 @@
var options = _super.prototype._getItemViewOptions.call( this, model );
return _.extend( options, {
linkTarget : this.linkTarget,
- hasUser : this.hasUser
+ hasUser : this.hasUser,
+//TODO: could move to only nested: list:paired
+ foldoutStyle : this.foldoutStyle
});
},
- /** when a sub-view is clicked in the collection panel that is itself a collection,
- * hide this panel's elements and show the sub-collection in its own panel.
- */
+ // ------------------------------------------------------------------------ collection sub-views
+ /** In this override, add/remove expanded/collapsed model ids to/from web storage */
_setUpItemViewListeners : function( view ){
var panel = this;
_super.prototype._setUpItemViewListeners.call( panel, view );
- //TODO:?? doesn't seem to belong here
- if( view.model.get( 'element_type' ) === 'dataset_collection' ){
- view.on( 'expanded', function( collectionView ){
- panel.info( 'expanded', collectionView );
- panel._addCollectionPanel( collectionView );
- });
- }
- return panel;
+
+ // use pub-sub to: handle drilldown expansion and collapse
+ view.on( 'expanded:drilldown', function( v, drilldown ){
+ this._expandDrilldownPanel( drilldown );
+ }, this );
+ view.on( 'collapsed:drilldown', function( v, drilldown ){
+ this._collapseDrilldownPanel( drilldown );
+ }, this );
+ return this;
},
- /** When a sub-collection is clicked, hide the current panel and render the sub-collection in its own panel */
- _addCollectionPanel : function( collectionView ){
-//TODO: a bit hackish
- var currPanel = this,
- collectionModel = collectionView.model;
+ /** */
+ _expandDrilldownPanel : function( drilldown ){
+ this.panelStack.push( drilldown );
+ // hide this panel's controls and list, set the name for back navigation, and attach to the $el
+ this.$( '> .controls' ).add( this.$list() ).hide();
+ drilldown.parentName = this.model.get( 'name' );
+ this.$el.append( drilldown.render().$el );
+ },
- //this.debug( 'collection panel (stack), collectionView:', collectionView );
- //this.debug( 'collection panel (stack), collectionModel:', collectionModel );
- var panel = new PairCollectionPanel({
- model : collectionModel,
- parentName : this.model.get( 'name' ),
- linkTarget : this.linkTarget
- });
- currPanel.panelStack.push( panel );
-
- currPanel.$( '.controls' ).add( '.list-items' ).hide();
- currPanel.$el.append( panel.$el );
- panel.on( 'close', function(){
- currPanel.render();
- collectionView.collapse();
- currPanel.panelStack.pop();
- });
-
- //TODO: to hdca-model, hasDetails
- if( !panel.model.hasDetails() ){
- var xhr = panel.model.fetch();
- xhr.done( function(){
- //TODO: (re-)render collection contents
- panel.render();
- });
- } else {
- panel.render();
- }
+ /** */
+ _collapseDrilldownPanel : function( drilldown ){
+ this.panelStack.pop();
+ this.render();
},
// ------------------------------------------------------------------------ panel events
@@ -216,7 +200,9 @@
//TODO: not strictly needed - due to switch in CollectionPanel._getContentClass
/** sub view class used for nested collections */
- NestedDCDCEViewClass : DC_LI.NestedDCDCEListItemView,
+ NestedDCDCEViewClass : DC_LI.NestedDCDCEListItemView.extend({
+ foldoutPanelClass : PairCollectionPanel
+ }),
// ........................................................................ misc
/** string rep */
diff -r deb003947e0e02de4613912b14832944954576a5 -r 618b02d13329adf2d01b72e9743a8fa00192c6fd static/scripts/mvc/dataset/dataset-li.js
--- a/static/scripts/mvc/dataset/dataset-li.js
+++ b/static/scripts/mvc/dataset/dataset-li.js
@@ -42,15 +42,7 @@
/** event listeners */
_setUpListeners : function(){
-//TODO:?? may want to move this to ListItemView (although this is only needed in the *narrow* panel views (current))
- // hide the primary actions in the title bar when selectable and narrow
- this.on( 'selectable', function( isSelectable ){
- if( isSelectable ){
- this.$( '.primary-actions' ).hide();
- } else {
- this.$( '.primary-actions' ).show();
- }
- }, this );
+ _super.prototype._setUpListeners.call( this );
// re-rendering on any model changes
this.model.on( 'change', function( model, options ){
@@ -64,10 +56,6 @@
this.render();
}
}, this );
-
- this.on( 'all', function( event ){
- this.log( event );
- }, this );
},
// ......................................................................... expandable
diff -r deb003947e0e02de4613912b14832944954576a5 -r 618b02d13329adf2d01b72e9743a8fa00192c6fd static/scripts/mvc/history/hdca-li.js
--- a/static/scripts/mvc/history/hdca-li.js
+++ b/static/scripts/mvc/history/hdca-li.js
@@ -1,9 +1,10 @@
define([
"mvc/dataset/states",
"mvc/collection/collection-li",
+ "mvc/collection/collection-panel",
"mvc/base-mvc",
"utils/localization"
-], function( STATES, DC_LI, BASE_MVC, _l ){
+], function( STATES, DC_LI, DC_PANEL, BASE_MVC, _l ){
/* global Backbone */
//==============================================================================
var _super = DC_LI.DCListItemView;
@@ -17,6 +18,18 @@
className : _super.prototype.className + " history-content",
+ _getFoldoutPanelClass : function(){
+ switch( this.model.get( 'collection_type' ) ){
+ case 'list':
+ return DC_PANEL.ListCollectionPanel;
+ case 'paired':
+ return DC_PANEL.PairCollectionPanel;
+ case 'list:paired':
+ return DC_PANEL.ListOfPairsCollectionPanel;
+ }
+ throw new TypeError( 'Uknown collection_type: ' + this.model.get( 'collection_type' ) );
+ },
+
/** In this override, add the state as a class for use with state-based CSS */
_swapNewRender : function( $newRender ){
_super.prototype._swapNewRender.call( this, $newRender );
diff -r deb003947e0e02de4613912b14832944954576a5 -r 618b02d13329adf2d01b72e9743a8fa00192c6fd static/scripts/mvc/history/history-panel-edit-current.js
--- a/static/scripts/mvc/history/history-panel-edit-current.js
+++ b/static/scripts/mvc/history/history-panel-edit-current.js
@@ -35,19 +35,26 @@
/** @class View/Controller for the user's current history model as used in the history
* panel (current right hand panel) of the analysis page.
*
- * The only history panel that will poll for updates.
+ * The only history panel that:
+ * will poll for updates.
+ * displays datasets in reverse hid order.
*/
var CurrentHistoryPanel = _super.extend(
/** @lends CurrentHistoryPanel.prototype */{
- className : _super.prototype.className + ' current-history-panel',
-
/** logger used to record this.log messages, commonly set to console */
//logger : console,
+ className : _super.prototype.className + ' current-history-panel',
+
emptyMsg : _l( "This history is empty. Click 'Get Data' on the left tool menu to start" ),
noneFoundMsg : _l( "No matching datasets found" ),
+ /** */
+ HDCAViewClass : _super.prototype.HDCAViewClass.extend({
+ foldoutStyle : 'drilldown'
+ }),
+
// ......................................................................... SET UP
/** Set up the view, set up storage, bind listeners to HistoryContents events */
initialize : function( attributes ){
@@ -220,6 +227,7 @@
panel.preferences.set( 'tagsEditorShown', tagsEditor.hidden );
});
},
+
/** In this override, get and set current panel preferences when editor is used */
_renderAnnotation : function( $where ){
var panel = this;
@@ -236,6 +244,7 @@
},
// ------------------------------------------------------------------------ sub-views
+ // reverse HID order
/** Override to reverse order of views - newest contents on top */
_attachItems : function( $whereTo ){
this.$list( $whereTo ).append( this.views.reverse().map( function( view ){
@@ -244,85 +253,20 @@
return this;
},
- /** In this override, handle collection expansion. */
- _setUpItemViewListeners : function( view ){
- var panel = this;
- _super.prototype._setUpItemViewListeners.call( panel, view );
-
- if( view instanceof panel.HDCAViewClass ){
- view.off( 'expanded' );
- view.on( 'expanded', function( collectionView ){
- panel.info( 'expanded', collectionView );
- panel._addCollectionPanel( collectionView );
- });
- view.off( 'collapsed' );
- }
- },
-
- /** In this override, handle collection expansion. */
- _addCollectionPanel : function( collectionView ){
- var panel = this,
- collectionModel = collectionView.model;
-
- this.debug( 'history panel (stack), collectionModel:', collectionModel );
- var overlaid = new ( this._getCollectionPanelClass( collectionModel ) )({
- model : collectionModel,
- HDAViewClass : this.HDAViewClass,
- parentName : this.model.get( 'name' ),
- linkTarget : this.linkTarget
- });
- panel.panelStack.push( overlaid );
-
- panel.$( '.controls' ).add( panel.$list() ).hide();
- panel.$el.append( overlaid.$el );
- overlaid.on( 'close', function(){
- panel.render();
- collectionView.collapse();
- panel.panelStack.pop();
- });
-
- //TODO: to hdca-model, hasDetails
- if( !overlaid.model.hasDetails() ){
- var xhr = overlaid.model.fetch();
- xhr.done( function(){
- //this.debug( 'collection data fetched' );
- //this.debug( JSON.stringify( overlaid.model.toJSON(), null, ' ' ) );
- //TODO: (re-)render collection contents
- overlaid.render();
- });
- } else {
- overlaid.render();
- }
- },
-
- _getCollectionPanelClass : function( model ){
- switch( model.get( 'collection_type' ) ){
- case 'list':
- return DC_PANEL.ListCollectionPanel;
- case 'paired':
- return DC_PANEL.PairCollectionPanel;
- case 'list:paired':
- return DC_PANEL.ListOfPairsCollectionPanel;
- }
- throw new TypeError( 'Uknown collection_type: ' + model.get( 'collection_type' ) );
- },
-
- /** In this override, check for any overlaid panels first */
+ /** Override to add datasets at the top */
addItemView : function( model, collection, options ){
this.log( this + '.addItemView:', model );
- if( !this._filterItem( model ) ){ return undefined; }
+ var panel = this;
+ if( !panel._filterItem( model ) ){ return undefined; }
+//TODO: alternately, call collapse drilldown
+ // if this panel is currently hidden, return undefined
+ if( panel.panelStack.length ){ return this._collapseDrilldownPanel(); }
- var panel = this;
- // don't show/add if there are panels overlaid on this one
- if( this.panelStack.length ){
- return panel;
- }
+ var view = panel._createItemView( model );
+ // use unshift and prepend to preserve reversed order
+ panel.views.unshift( view );
- // current history item order is reversed - use unshift and prepend
- var view = panel._createItemView( model );
- this.views.unshift( view );
panel.scrollToTop();
-
$({}).queue([
function fadeOutEmptyMsg( next ){
var $emptyMsg = panel.$emptyMessage();
@@ -333,8 +277,7 @@
}
},
function createAndPrepend( next ){
- //view.render().$el.hide();
- panel.scrollToTop();
+ // render as hidden then slide down
panel.$list().prepend( view.render( 0 ).$el.hide() );
view.$el.slideDown( panel.fxSpeed );
}
@@ -342,6 +285,36 @@
return view;
},
+ // ------------------------------------------------------------------------ collection sub-views
+ /** In this override, add/remove expanded/collapsed model ids to/from web storage */
+ _setUpItemViewListeners : function( view ){
+ var panel = this;
+ _super.prototype._setUpItemViewListeners.call( panel, view );
+
+ // use pub-sub to: handle drilldown expansion and collapse
+ view.on( 'expanded:drilldown', function( v, drilldown ){
+ this._expandDrilldownPanel( drilldown );
+ }, this );
+ view.on( 'collapsed:drilldown', function( v, drilldown ){
+ this._collapseDrilldownPanel( drilldown );
+ }, this );
+ return this;
+ },
+
+ _expandDrilldownPanel : function( drilldown ){
+ this.panelStack.push( drilldown );
+ // hide this panel's controls and list, set the name for back navigation, and attach to the $el
+ this.$( '> .controls' ).add( this.$list() ).hide();
+ drilldown.parentName = this.model.get( 'name' );
+ this.$el.append( drilldown.render().$el );
+ },
+
+ _collapseDrilldownPanel : function( drilldown ){
+ this.panelStack.pop();
+//TODO: MEM: free the panel
+ this.render();
+ },
+
// ........................................................................ external objects/MVC
//TODO: remove quota meter from panel and remove this
/** add listeners to an external quota meter (mvc/user/user-quotameter.js) */
diff -r deb003947e0e02de4613912b14832944954576a5 -r 618b02d13329adf2d01b72e9743a8fa00192c6fd static/scripts/mvc/history/history-panel.js
--- a/static/scripts/mvc/history/history-panel.js
+++ b/static/scripts/mvc/history/history-panel.js
@@ -4,10 +4,21 @@
"mvc/history/history-contents",
"mvc/history/hda-li",
"mvc/history/hdca-li",
+ "mvc/collection/collection-panel",
"mvc/user/user-model",
"mvc/base-mvc",
"utils/localization"
-], function( LIST_PANEL, HISTORY_MODEL, HISTORY_CONTENTS, HDA_LI, HDCA_LI, USER, BASE_MVC, _l ){
+], function(
+ LIST_PANEL,
+ HISTORY_MODEL,
+ HISTORY_CONTENTS,
+ HDA_LI,
+ HDCA_LI,
+ COLLECTION_PANEL,
+ USER,
+ BASE_MVC,
+ _l
+){
// ============================================================================
/** session storage for individual history preferences */
var HistoryPrefs = BASE_MVC.SessionStorageModel.extend(
@@ -22,13 +33,13 @@
//TODO: add scroll position?
},
/** add an hda id to the hash of expanded hdas */
- addExpandedHda : function( model ){
+ addExpanded : function( model ){
var key = 'expandedIds';
//TODO:?? is this right anymore?
this.save( key, _.extend( this.get( key ), _.object([ model.id ], [ model.get( 'id' ) ]) ) );
},
/** remove an hda id from the hash of expanded hdas */
- removeExpandedHda : function( model ){
+ removeExpanded : function( model ){
var key = 'expandedIds';
this.save( key, _.omit( this.get( key ), model.id ) );
},
@@ -199,6 +210,15 @@
return xhr;
},
+ /** convenience alias to the model. Updates the item list only (not the history) */
+ refreshContents : function( detailIds, options ){
+ if( this.model ){
+ return this.model.refresh( detailIds, options );
+ }
+ // may have callbacks - so return an empty promise
+ return $.when();
+ },
+
//TODO:?? seems unneccesary
//TODO: Maybe better in History?
/** create a new history model from JSON and call setModel on it */
@@ -319,24 +339,14 @@
//TODO:?? could use 'view:expanded' here?
// maintain a list of items whose bodies are expanded
view.on( 'expanded', function( v ){
- panel.storage.addExpandedHda( v.model );
+ panel.storage.addExpanded( v.model );
});
view.on( 'collapsed', function( v ){
- panel.storage.removeExpandedHda( v.model );
+ panel.storage.removeExpanded( v.model );
});
return this;
},
- // ------------------------------------------------------------------------ collection/views syncing
- /** convenience alias to the model. Updates the item list only (not the history) */
- refreshContents : function( detailIds, options ){
- if( this.model ){
- return this.model.refresh( detailIds, options );
- }
- // may have callbacks - so return an empty promise
- return $.when();
- },
-
// ------------------------------------------------------------------------ selection
/** Override to correctly set the historyId of the new collection */
getSelectedModels : function(){
diff -r deb003947e0e02de4613912b14832944954576a5 -r 618b02d13329adf2d01b72e9743a8fa00192c6fd static/scripts/mvc/list/list-item.js
--- a/static/scripts/mvc/list/list-item.js
+++ b/static/scripts/mvc/list/list-item.js
@@ -87,7 +87,7 @@
/** shortcut to details DOM (as jQ) */
$details : function( $where ){
$where = $where || this.$el;
- return $where.find( '.details' );
+ return $where.find( '> .details' );
},
/** build the DOM for the details and set up behaviors on it */
@@ -123,7 +123,7 @@
view.$details().replaceWith( $newDetails );
// needs to be set after the above or the slide will not show
view.expanded = true;
- $newDetails.slideDown( view.fxSpeed, function(){
+ view.$details().slideDown( view.fxSpeed, function(){
view.trigger( 'expanded', view );
});
});
@@ -143,6 +143,7 @@
* @fires collapsed when a body has been collapsed
*/
collapse : function(){
+ this.debug( this + '(ExpandableView).collapse' );
var view = this;
view.expanded = false;
this.$details().slideUp( view.fxSpeed, function(){
@@ -177,16 +178,33 @@
ExpandableView.prototype.initialize.call( this, attributes );
BASE_MVC.SelectableViewMixin.initialize.call( this, attributes );
BASE_MVC.DraggableViewMixin.initialize.call( this, attributes );
+ this._setUpListeners();
+ },
+
+ /** event listeners */
+ _setUpListeners : function(){
+ // hide the primary actions in the title bar when selectable and narrow
+ this.on( 'selectable', function( isSelectable ){
+ if( isSelectable ){
+ this.$( '.primary-actions' ).hide();
+ } else {
+ this.$( '.primary-actions' ).show();
+ }
+ }, this );
+ //this.on( 'all', function( event ){
+ // this.log( event );
+ //}, this );
+ return this;
},
// ........................................................................ rendering
/** In this override, call methods to build warnings, titlebar and primary actions */
_buildNewRender : function(){
var $newRender = ExpandableView.prototype._buildNewRender.call( this );
- $newRender.find( '.warnings' ).replaceWith( this._renderWarnings() );
- $newRender.find( '.title-bar' ).replaceWith( this._renderTitleBar() );
- $newRender.find( '.primary-actions' ).append( this._renderPrimaryActions() );
- $newRender.find( '.subtitle' ).replaceWith( this._renderSubtitle() );
+ $newRender.children( '.warnings' ).replaceWith( this._renderWarnings() );
+ $newRender.children( '.title-bar' ).replaceWith( this._renderTitleBar() );
+ $newRender.children( '.primary-actions' ).append( this._renderPrimaryActions() );
+ $newRender.find( '.title-bar .subtitle' ).replaceWith( this._renderSubtitle() );
return $newRender;
},
@@ -325,8 +343,135 @@
//==============================================================================
+/** A view that is displayed in some larger list/grid/collection.
+ * *AND* can display some sub-list of it's own when expanded (e.g. dataset collections).
+ * This list will 'foldout' when the item is expanded depending on this.foldoutStyle:
+ * If 'foldout': will expand vertically to show the nested list
+ * If 'drilldown': will overlay the parent list
+ *
+ * Inherits from ListItemView.
+ *
+ * _renderDetails does the work of creating this.details: a sub-view that shows the nested list
+ */
+var FoldoutListItemView = ListItemView.extend({
+
+ foldoutStyle : 'foldout',
+ foldoutPanelClass : null,
+
+ initialize : function( attributes ){
+ ListItemView.prototype.initialize.call( this, attributes );
+//TODO: hackish
+ if( this.foldoutStyle === 'drilldown' ){ this.expanded = false; }
+ this.foldoutStyle = attributes.foldoutStyle || this.foldoutStyle;
+ this.foldoutPanelClass = attributes.foldoutPanelClass || this.foldoutPanelClass;
+ },
+
+//TODO:?? override to exclude foldout scope?
+ $ : function( selector ){
+ var $found = ListItemView.prototype.$.call( this, selector );
+ return $found;
+ },
+
+ /** in this override, attach the foldout panel when rendering details */
+ _renderDetails : function(){
+//TODO: hackish
+ if( this.foldoutStyle === 'drilldown' ){ return $(); }
+ var $newDetails = ListItemView.prototype._renderDetails.call( this );
+ return this._attachFoldout( this._createFoldoutPanel(), $newDetails );
+ },
+
+ /** In this override, handle collection expansion. */
+ _createFoldoutPanel : function(){
+ var model = this.model;
+ var FoldoutClass = this._getFoldoutPanelClass( model ),
+ options = this._getFoldoutPanelOptions( model ),
+ foldout = new FoldoutClass( _.extend( options, {
+ model : model
+ }));
+ return foldout;
+ },
+
+ _getFoldoutPanelClass : function(){
+ // override
+ return this.foldoutPanelClass;
+ },
+
+ _getFoldoutPanelOptions : function(){
+ return {
+ // propagate foldout style down
+ foldoutStyle : this.foldoutStyle
+ };
+ },
+
+ /** */
+ _attachFoldout : function( foldout, $whereTo ){
+ $whereTo = $whereTo || this.$( '> .details' );
+ this.foldout = foldout.render( 0 );
+//TODO: hack
+ foldout.$( '> .controls' ).hide();
+ return $whereTo.append( foldout.$el );
+ },
+
+ /** Render and show the full, detailed body of this view including extra data and controls.
+ * note: if the model does not have detailed data, fetch that data before showing the body
+ * @fires expanded when a body has been expanded
+ */
+ expand : function(){
+ var view = this;
+ return view._fetchModelDetails()
+ .always(function(){
+ if( view.foldoutStyle === 'foldout' ){
+ view._expandByFoldout();
+ } else if( view.foldoutStyle === 'drilldown' ){
+ view._expandByDrilldown();
+ }
+ });
+ },
+
+ _expandByFoldout : function(){
+ var view = this;
+ var $newDetails = view._renderDetails();
+ view.$details().replaceWith( $newDetails );
+ // needs to be set after the above or the slide will not show
+ view.expanded = true;
+ view.$details().slideDown( view.fxSpeed, function(){
+ view.trigger( 'expanded', view );
+ });
+ },
+
+ _expandByDrilldown : function(){
+ var view = this;
+ // attachment and rendering done by listener
+ view.foldout = this._createFoldoutPanel();
+ view.foldout.on( 'close', function(){
+ view.trigger( 'collapsed:drilldown', view, view.foldout );
+ });
+ view.trigger( 'expanded:drilldown', view, view.foldout );
+ }
+
+});
+
+// ............................................................................ TEMPLATES
+/** underscore templates */
+FoldoutListItemView.prototype.templates = (function(){
+
+ // use element identifier
+ var detailsTemplate = BASE_MVC.wrapTemplate([
+ '<div class="details">',
+ // override with more info (that goes above the panel)
+ '</div>'
+ ], 'collection' );
+
+ return _.extend( {}, ListItemView.prototype.templates, {
+ details : detailsTemplate
+ });
+}());
+
+
+//==============================================================================
return {
ExpandableView : ExpandableView,
- ListItemView : ListItemView
+ ListItemView : ListItemView,
+ FoldoutListItemView : FoldoutListItemView
};
});
diff -r deb003947e0e02de4613912b14832944954576a5 -r 618b02d13329adf2d01b72e9743a8fa00192c6fd static/scripts/mvc/list/list-panel.js
--- a/static/scripts/mvc/list/list-panel.js
+++ b/static/scripts/mvc/list/list-panel.js
@@ -184,9 +184,7 @@
// shift to select a range
this.on( 'view:selected', function( view, ev ){
if( ev && ev.shiftKey && this.lastSelected ){
- var lastSelectedView = _.find( this.views, function( view ){
- return view.model.id === this.lastSelected;
- });
+ var lastSelectedView = this.viewFromModelId( this.lastSelected );
if( lastSelectedView ){
this.selectRange( view, lastSelectedView );
}
@@ -294,15 +292,15 @@
},
/** */
$list : function( $where ){
- return ( $where || this.$el ).find( '.list-items' );
+ return ( $where || this.$el ).find( '> .list-items' );
},
/** container where list messages are attached */
$messages : function( $where ){
- return ( $where || this.$el ).find( '.messages' );
+ return ( $where || this.$el ).find( '> .controls .messages' );
},
/** the message displayed when no views can be shown (no views, none matching search) */
$emptyMessage : function( $where ){
- return ( $where || this.$el ).find( '.empty-message' );
+ return ( $where || this.$el ).find( '> .empty-message' );
},
// ------------------------------------------------------------------------ hda sub-views
@@ -593,6 +591,7 @@
this.selecting = true;
this.$( '.list-actions' ).slideDown( speed );
_.each( this.views, function( view ){
+console.debug( view.$el );
view.showSelector( speed );
});
//this.selected = [];
@@ -915,7 +914,7 @@
//=============================================================================
return {
- ListPanel : ListPanel,
- ModelListPanel : ModelListPanel
+ ListPanel : ListPanel,
+ ModelListPanel : ModelListPanel
};
});
diff -r deb003947e0e02de4613912b14832944954576a5 -r 618b02d13329adf2d01b72e9743a8fa00192c6fd static/scripts/packed/mvc/collection/collection-li.js
--- a/static/scripts/packed/mvc/collection/collection-li.js
+++ b/static/scripts/packed/mvc/collection/collection-li.js
@@ -1,1 +1,1 @@
-define(["mvc/list/list-item","mvc/dataset/dataset-li","mvc/base-mvc","utils/localization"],function(a,h,i,d){var e=a.ListItemView;var c=e.extend({className:e.prototype.className+" dataset-collection",id:function(){return["dataset_collection",this.model.get("id")].join("-")},fxSpeed:"fast",initialize:function(j){if(j.logger){this.logger=this.model.logger=j.logger}this.log(this+"(DCListItemView).initialize:",j);e.prototype.initialize.call(this,j)},expand:function(){var j=this;return j._fetchModelDetails().always(function(){j.trigger("expanded",j)})},_renderSubtitle:function(){var j=$('<div class="subtitle"></div>');switch(this.model.get("collection_type")){case"list":return j.text(d("a list of datasets"));case"paired":return j.text(d("a pair of datasets"));case"list:paired":return j.text(d("a list of paired datasets"))}return j},toString:function(){var j=(this.model)?(this.model+""):("(no model)");return"DCListItemView("+j+")"}});c.prototype.templates=(function(){var j=i.wrapTemplate(['<div class="title-bar clear" tabindex="0">','<div class="title">','<span class="name"><%- collection.element_identifier || collection.name %></span>',"</div>",'<div class="subtitle"></div>',"</div>"],"collection");return _.extend({},e.prototype.templates,{titleBar:j})}());var f=e.extend({className:e.prototype.className+" dataset-collection-element",fxSpeed:"fast",initialize:function(j){if(j.logger){this.logger=this.model.logger=j.logger}this.log("DCEListItemView.initialize:",j);e.prototype.initialize.call(this,j)},toString:function(){var j=(this.model)?(this.model+""):("(no model)");return"DCEListItemView("+j+")"}});f.prototype.templates=(function(){var j=i.wrapTemplate(['<div class="title-bar clear" tabindex="0">','<div class="title">','<span class="name"><%- element.element_identifier %></span>',"</div>",'<div class="subtitle"></div>',"</div>"],"element");return _.extend({},e.prototype.templates,{titleBar:j})}());var b=h.DatasetListItemView.extend({className:h.DatasetListItemView.prototype.className+" dataset-collection-element",initialize:function(j){if(j.logger){this.logger=this.model.logger=j.logger}this.log("DatasetDCEListItemView.initialize:",j);h.DatasetListItemView.prototype.initialize.call(this,j)},toString:function(){var j=(this.model)?(this.model+""):("(no model)");return"DatasetDCEListItemView("+j+")"}});b.prototype.templates=(function(){var j=i.wrapTemplate(['<div class="title-bar clear" tabindex="0">','<span class="state-icon"></span>','<div class="title">','<span class="name"><%- element.element_identifier %></span>',"</div>","</div>"],"element");return _.extend({},h.DatasetListItemView.prototype.templates,{titleBar:j})}());var g=c.extend({className:c.prototype.className+" dataset-collection-element",_swapNewRender:function(j){c.prototype._swapNewRender.call(this,j);var k=this.model.get("state")||"ok";this.$el.addClass("state-"+k);return this.$el},toString:function(){var j=(this.model)?(this.model+""):("(no model)");return"NestedDCDCEListItemView("+j+")"}});return{DCListItemView:c,DCEListItemView:f,DatasetDCEListItemView:b,NestedDCDCEListItemView:g}});
\ No newline at end of file
+define(["mvc/list/list-item","mvc/dataset/dataset-li","mvc/base-mvc","utils/localization"],function(a,h,i,d){var j=a.FoldoutListItemView,e=a.ListItemView;var c=j.extend({className:j.prototype.className+" dataset-collection",id:function(){return["dataset_collection",this.model.get("id")].join("-")},initialize:function(k){j.prototype.initialize.call(this,k);this.linkTarget=k.linkTarget||"_blank"},_renderSubtitle:function(){var k=$('<div class="subtitle"></div>');switch(this.model.get("collection_type")){case"list":return k.text(d("a list of datasets"));case"paired":return k.text(d("a pair of datasets"));case"list:paired":return k.text(d("a list of paired datasets"))}return k},_getFoldoutPanelOptions:function(){var k=j.prototype._getFoldoutPanelOptions.call(this);return _.extend(k,{linkTarget:this.linkTarget})},$selector:function(){return this.$("> .selector")},toString:function(){var k=(this.model)?(this.model+""):("(no model)");return"DCListItemView("+k+")"}});c.prototype.templates=(function(){var k=i.wrapTemplate(['<div class="title-bar clear" tabindex="0">','<div class="title">','<span class="name"><%- collection.element_identifier || collection.name %></span>',"</div>",'<div class="subtitle"></div>',"</div>"],"collection");return _.extend({},j.prototype.templates,{titleBar:k})}());var f=e.extend({className:e.prototype.className+" dataset-collection-element",fxSpeed:"fast",initialize:function(k){if(k.logger){this.logger=this.model.logger=k.logger}this.log("DCEListItemView.initialize:",k);e.prototype.initialize.call(this,k)},toString:function(){var k=(this.model)?(this.model+""):("(no model)");return"DCEListItemView("+k+")"}});f.prototype.templates=(function(){var k=i.wrapTemplate(['<div class="title-bar clear" tabindex="0">','<div class="title">','<span class="name"><%- element.element_identifier %></span>',"</div>",'<div class="subtitle"></div>',"</div>"],"element");return _.extend({},e.prototype.templates,{titleBar:k})}());var b=h.DatasetListItemView.extend({className:h.DatasetListItemView.prototype.className+" dataset-collection-element",initialize:function(k){if(k.logger){this.logger=this.model.logger=k.logger}this.log("DatasetDCEListItemView.initialize:",k);h.DatasetListItemView.prototype.initialize.call(this,k)},toString:function(){var k=(this.model)?(this.model+""):("(no model)");return"DatasetDCEListItemView("+k+")"}});b.prototype.templates=(function(){var k=i.wrapTemplate(['<div class="title-bar clear" tabindex="0">','<span class="state-icon"></span>','<div class="title">','<span class="name"><%- element.element_identifier %></span>',"</div>","</div>"],"element");return _.extend({},h.DatasetListItemView.prototype.templates,{titleBar:k})}());var g=c.extend({className:c.prototype.className+" dataset-collection-element",_swapNewRender:function(k){c.prototype._swapNewRender.call(this,k);var l=this.model.get("state")||"ok";this.$el.addClass("state-"+l);return this.$el},toString:function(){var k=(this.model)?(this.model+""):("(no model)");return"NestedDCDCEListItemView("+k+")"}});return{DCListItemView:c,DCEListItemView:f,DatasetDCEListItemView:b,NestedDCDCEListItemView:g}});
\ No newline at end of file
diff -r deb003947e0e02de4613912b14832944954576a5 -r 618b02d13329adf2d01b72e9743a8fa00192c6fd static/scripts/packed/mvc/collection/collection-panel.js
--- a/static/scripts/packed/mvc/collection/collection-panel.js
+++ b/static/scripts/packed/mvc/collection/collection-panel.js
@@ -1,1 +1,1 @@
-define(["mvc/list/list-panel","mvc/collection/collection-model","mvc/collection/collection-li","mvc/base-mvc","utils/localization"],function(a,d,f,j,b){var h=a.ModelListPanel;var g=h.extend({className:h.prototype.className+" dataset-collection-panel",DatasetDCEViewClass:f.DatasetDCEListItemView,NestedDCDCEViewClass:f.NestedDCDCEListItemView,modelCollectionKey:"elements",initialize:function(k){h.prototype.initialize.call(this,k);this.linkTarget=k.linkTarget||"_blank";this.hasUser=k.hasUser;this.panelStack=[];this.parentName=k.parentName},_filterCollection:function(){return this.model.getVisibleContents()},_getItemViewClass:function(k){switch(k.get("element_type")){case"hda":return this.DatasetDCEViewClass;case"dataset_collection":return this.NestedDCDCEViewClass}throw new TypeError("Unknown element type:",k.get("element_type"))},_getItemViewOptions:function(l){var k=h.prototype._getItemViewOptions.call(this,l);return _.extend(k,{linkTarget:this.linkTarget,hasUser:this.hasUser})},_setUpItemViewListeners:function(l){var k=this;h.prototype._setUpItemViewListeners.call(k,l);if(l.model.get("element_type")==="dataset_collection"){l.on("expanded",function(m){k.info("expanded",m);k._addCollectionPanel(m)})}return k},_addCollectionPanel:function(m){var n=this,k=m.model;var l=new i({model:k,parentName:this.model.get("name"),linkTarget:this.linkTarget});n.panelStack.push(l);n.$(".controls").add(".list-items").hide();n.$el.append(l.$el);l.on("close",function(){n.render();m.collapse();n.panelStack.pop()});if(!l.model.hasDetails()){var o=l.model.fetch();o.done(function(){l.render()})}else{l.render()}},events:{"click .navigation .back":"close"},close:function(k){this.$el.remove();this.trigger("close")},toString:function(){return"CollectionPanel("+((this.model)?(this.model.get("name")):(""))+")"}});g.prototype.templates=(function(){var k=j.wrapTemplate(['<div class="controls">','<div class="navigation">','<a class="back" href="javascript:void(0)">','<span class="fa fa-icon fa-angle-left"></span>',b("Back to "),"<%- view.parentName %>","</a>","</div>",'<div class="title">','<div class="name"><%- collection.name || collection.element_identifier %></div>','<div class="subtitle">','<% if( collection.collection_type === "list" ){ %>',b("a list of datasets"),'<% } else if( collection.collection_type === "paired" ){ %>',b("a pair of datasets"),'<% } else if( collection.collection_type === "list:paired" ){ %>',b("a list of paired datasets"),"<% } %>","</div>","</div>","</div>"],"collection");return _.extend(_.clone(h.prototype.templates),{controls:k})}());var e=g.extend({DatasetDCEViewClass:f.DatasetDCEListItemView,toString:function(){return"ListCollectionPanel("+((this.model)?(this.model.get("name")):(""))+")"}});var i=e.extend({toString:function(){return"PairCollectionPanel("+((this.model)?(this.model.get("name")):(""))+")"}});var c=g.extend({NestedDCDCEViewClass:f.NestedDCDCEListItemView,toString:function(){return"ListOfPairsCollectionPanel("+((this.model)?(this.model.get("name")):(""))+")"}});return{CollectionPanel:g,ListCollectionPanel:e,PairCollectionPanel:i,ListOfPairsCollectionPanel:c}});
\ No newline at end of file
+define(["mvc/list/list-panel","mvc/collection/collection-model","mvc/collection/collection-li","mvc/base-mvc","utils/localization"],function(a,d,f,j,b){var h=a.ModelListPanel;var g=h.extend({className:h.prototype.className+" dataset-collection-panel",DatasetDCEViewClass:f.DatasetDCEListItemView,NestedDCDCEViewClass:f.NestedDCDCEListItemView,modelCollectionKey:"elements",initialize:function(k){h.prototype.initialize.call(this,k);this.linkTarget=k.linkTarget||"_blank";this.hasUser=k.hasUser;this.panelStack=[];this.parentName=k.parentName;this.foldoutStyle=k.foldoutStyle||"foldout"},_filterCollection:function(){return this.model.getVisibleContents()},_getItemViewClass:function(k){switch(k.get("element_type")){case"hda":return this.DatasetDCEViewClass;case"dataset_collection":return this.NestedDCDCEViewClass}throw new TypeError("Unknown element type:",k.get("element_type"))},_getItemViewOptions:function(l){var k=h.prototype._getItemViewOptions.call(this,l);return _.extend(k,{linkTarget:this.linkTarget,hasUser:this.hasUser,foldoutStyle:this.foldoutStyle})},_setUpItemViewListeners:function(l){var k=this;h.prototype._setUpItemViewListeners.call(k,l);l.on("expanded:drilldown",function(n,m){this._expandDrilldownPanel(m)},this);l.on("collapsed:drilldown",function(n,m){this._collapseDrilldownPanel(m)},this);return this},_expandDrilldownPanel:function(k){this.panelStack.push(k);this.$("> .controls").add(this.$list()).hide();k.parentName=this.model.get("name");this.$el.append(k.render().$el)},_collapseDrilldownPanel:function(k){this.panelStack.pop();this.render()},events:{"click .navigation .back":"close"},close:function(k){this.$el.remove();this.trigger("close")},toString:function(){return"CollectionPanel("+((this.model)?(this.model.get("name")):(""))+")"}});g.prototype.templates=(function(){var k=j.wrapTemplate(['<div class="controls">','<div class="navigation">','<a class="back" href="javascript:void(0)">','<span class="fa fa-icon fa-angle-left"></span>',b("Back to "),"<%- view.parentName %>","</a>","</div>",'<div class="title">','<div class="name"><%- collection.name || collection.element_identifier %></div>','<div class="subtitle">','<% if( collection.collection_type === "list" ){ %>',b("a list of datasets"),'<% } else if( collection.collection_type === "paired" ){ %>',b("a pair of datasets"),'<% } else if( collection.collection_type === "list:paired" ){ %>',b("a list of paired datasets"),"<% } %>","</div>","</div>","</div>"],"collection");return _.extend(_.clone(h.prototype.templates),{controls:k})}());var e=g.extend({DatasetDCEViewClass:f.DatasetDCEListItemView,toString:function(){return"ListCollectionPanel("+((this.model)?(this.model.get("name")):(""))+")"}});var i=e.extend({toString:function(){return"PairCollectionPanel("+((this.model)?(this.model.get("name")):(""))+")"}});var c=g.extend({NestedDCDCEViewClass:f.NestedDCDCEListItemView.extend({foldoutPanelClass:i}),toString:function(){return"ListOfPairsCollectionPanel("+((this.model)?(this.model.get("name")):(""))+")"}});return{CollectionPanel:g,ListCollectionPanel:e,PairCollectionPanel:i,ListOfPairsCollectionPanel:c}});
\ No newline at end of file
diff -r deb003947e0e02de4613912b14832944954576a5 -r 618b02d13329adf2d01b72e9743a8fa00192c6fd static/scripts/packed/mvc/dataset/dataset-li.js
--- a/static/scripts/packed/mvc/dataset/dataset-li.js
+++ b/static/scripts/packed/mvc/dataset/dataset-li.js
@@ -1,1 +1,1 @@
-define(["mvc/list/list-item","mvc/dataset/states","mvc/base-mvc","utils/localization"],function(d,a,b,c){var f=d.ListItemView;var e=f.extend({className:f.prototype.className+" dataset",id:function(){return["dataset",this.model.get("id")].join("-")},initialize:function(g){if(g.logger){this.logger=this.model.logger=g.logger}this.log(this+".initialize:",g);f.prototype.initialize.call(this,g);this.linkTarget=g.linkTarget||"_blank";this._setUpListeners()},_setUpListeners:function(){this.on("selectable",function(g){if(g){this.$(".primary-actions").hide()}else{this.$(".primary-actions").show()}},this);this.model.on("change",function(h,g){if(this.model.changedAttributes().state&&this.model.inReadyState()&&this.expanded&&!this.model.hasDetails()){this.model.fetch()}else{this.render()}},this);this.on("all",function(g){this.log(g)},this)},_fetchModelDetails:function(){var g=this;if(g.model.inReadyState()&&!g.model.hasDetails()){return g.model.fetch({silent:true})}return jQuery.when()},remove:function(h,i){var g=this;h=h||this.fxSpeed;this.$el.fadeOut(h,function(){Backbone.View.prototype.remove.call(g);if(i){i.call(g)}})},render:function(g){return f.prototype.render.call(this,g)},_swapNewRender:function(g){f.prototype._swapNewRender.call(this,g);if(this.model.has("state")){this.$el.addClass("state-"+this.model.get("state"))}return this.$el},_renderPrimaryActions:function(){return[this._renderDisplayButton()]},_renderDisplayButton:function(){var i=this.model.get("state");if((i===a.NOT_VIEWABLE)||(i===a.DISCARDED)||(!this.model.get("accessible"))){return null}var h={target:this.linkTarget,classes:"display-btn"};if(this.model.get("purged")){h.disabled=true;h.title=c("Cannot display datasets removed from disk")}else{if(i===a.UPLOAD){h.disabled=true;h.title=c("This dataset must finish uploading before it can be viewed")}else{if(i===a.NEW){h.disabled=true;h.title=c("This dataset is not yet viewable")}else{h.title=c("View data");h.href=this.model.urls.display;var g=this;h.onclick=function(j){if(Galaxy.frame&&Galaxy.frame.active){Galaxy.frame.add({title:"Data Viewer: "+g.model.get("name"),type:"other",content:function(k){require(["mvc/data"],function(l){var m=new l.TabularDataset({id:g.model.get("id")});$.when(m.fetch()).then(function(){l.createTabularDatasetChunkedView({model:m,parent_elt:k,embedded:true,height:"100%"})})})}});j.preventDefault()}}}}}h.faIcon="fa-eye";return faIconButton(h)},_renderDetails:function(){if(this.model.get("state")===a.NOT_VIEWABLE){return $(this.templates.noAccess(this.model.toJSON(),this))}var g=f.prototype._renderDetails.call(this);g.find(".actions .left").empty().append(this._renderSecondaryActions());g.find(".summary").html(this._renderSummary()).prepend(this._renderDetailMessages());g.find(".display-applications").html(this._renderDisplayApplications());this._setUpBehaviors(g);return g},_renderSummary:function(){var g=this.model.toJSON(),h=this.templates.summaries[g.state];h=h||this.templates.summaries.unknown;return h(g,this)},_renderDetailMessages:function(){var g=this,i=$('<div class="detail-messages"></div>'),h=g.model.toJSON();_.each(g.templates.detailMessages,function(j){i.append($(j(h,g)))});return i},_renderDisplayApplications:function(){if(this.model.isDeletedOrPurged()){return""}return[this.templates.displayApplications(this.model.get("display_apps"),this),this.templates.displayApplications(this.model.get("display_types"),this)].join("")},_renderSecondaryActions:function(){this.debug("_renderSecondaryActions");switch(this.model.get("state")){case a.NOT_VIEWABLE:return[];case a.OK:case a.FAILED_METADATA:case a.ERROR:return[this._renderDownloadButton(),this._renderShowParamsButton()]}return[this._renderShowParamsButton()]},_renderShowParamsButton:function(){return faIconButton({title:c("View details"),classes:"params-btn",href:this.model.urls.show_params,target:this.linkTarget,faIcon:"fa-info-circle"})},_renderDownloadButton:function(){if(this.model.get("purged")||!this.model.hasData()){return null}if(!_.isEmpty(this.model.get("meta_files"))){return this._renderMetaFileDownloadButton()}return $(['<a class="download-btn icon-btn" href="',this.model.urls.download,'" title="'+c("Download")+'">','<span class="fa fa-floppy-o"></span>',"</a>"].join(""))},_renderMetaFileDownloadButton:function(){var g=this.model.urls;return $(['<div class="metafile-dropdown dropdown">','<a class="download-btn icon-btn" href="javascript:void(0)" data-toggle="dropdown"',' title="'+c("Download")+'">','<span class="fa fa-floppy-o"></span>',"</a>",'<ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">','<li><a href="'+g.download+'">',c("Download dataset"),"</a></li>",_.map(this.model.get("meta_files"),function(h){return['<li><a href="',g.meta_download+h.file_type,'">',c("Download")," ",h.file_type,"</a></li>"].join("")}).join("\n"),"</ul>","</div>"].join("\n"))},toString:function(){var g=(this.model)?(this.model+""):("(no model)");return"DatasetListItemView("+g+")"}});e.prototype.templates=(function(){var i=_.extend({},f.prototype.templates.warnings,{failed_metadata:b.wrapTemplate(['<% if( model.state === "failed_metadata" ){ %>','<div class="warningmessagesmall">',c("An error occurred setting the metadata for this dataset"),"</div>","<% } %>"]),error:b.wrapTemplate(["<% if( model.error ){ %>",'<div class="errormessagesmall">',c("There was an error getting the data for this dataset"),": <%- model.error %>","</div>","<% } %>"]),purged:b.wrapTemplate(["<% if( model.purged ){ %>",'<div class="purged-msg warningmessagesmall">',c("This dataset has been deleted and removed from disk"),"</div>","<% } %>"]),deleted:b.wrapTemplate(["<% if( model.deleted && !model.purged ){ %>",'<div class="deleted-msg warningmessagesmall">',c("This dataset has been deleted"),"</div>","<% } %>"])});var j=b.wrapTemplate(['<div class="details">','<div class="summary"></div>','<div class="actions clear">','<div class="left"></div>','<div class="right"></div>',"</div>","<% if( !dataset.deleted && !dataset.purged ){ %>",'<div class="tags-display"></div>','<div class="annotation-display"></div>','<div class="display-applications"></div>',"<% if( dataset.peek ){ %>",'<pre class="dataset-peek"><%= dataset.peek %></pre>',"<% } %>","<% } %>","</div>"],"dataset");var h=b.wrapTemplate(['<div class="details">','<div class="summary">',c("You do not have permission to view this dataset"),"</div>","</div>"],"dataset");var k={};k[a.OK]=k[a.FAILED_METADATA]=b.wrapTemplate(["<% if( dataset.misc_blurb ){ %>",'<div class="blurb">','<span class="value"><%- dataset.misc_blurb %></span>',"</div>","<% } %>","<% if( dataset.file_ext ){ %>",'<div class="datatype">','<label class="prompt">',c("format"),"</label>",'<span class="value"><%- dataset.file_ext %></span>',"</div>","<% } %>","<% if( dataset.metadata_dbkey ){ %>",'<div class="dbkey">','<label class="prompt">',c("database"),"</label>",'<span class="value">',"<%- dataset.metadata_dbkey %>","</span>","</div>","<% } %>","<% if( dataset.misc_info ){ %>",'<div class="info">','<span class="value"><%- dataset.misc_info %></span>',"</div>","<% } %>"],"dataset");k[a.NEW]=b.wrapTemplate(["<div>",c("This is a new dataset and not all of its data are available yet"),"</div>"],"dataset");k[a.NOT_VIEWABLE]=b.wrapTemplate(["<div>",c("You do not have permission to view this dataset"),"</div>"],"dataset");k[a.DISCARDED]=b.wrapTemplate(["<div>",c("The job creating this dataset was cancelled before completion"),"</div>"],"dataset");k[a.QUEUED]=b.wrapTemplate(["<div>",c("This job is waiting to run"),"</div>"],"dataset");k[a.RUNNING]=b.wrapTemplate(["<div>",c("This job is currently running"),"</div>"],"dataset");k[a.UPLOAD]=b.wrapTemplate(["<div>",c("This dataset is currently uploading"),"</div>"],"dataset");k[a.SETTING_METADATA]=b.wrapTemplate(["<div>",c("Metadata is being auto-detected"),"</div>"],"dataset");k[a.PAUSED]=b.wrapTemplate(["<div>",c('This job is paused. Use the "Resume Paused Jobs" in the history menu to resume'),"</div>"],"dataset");k[a.ERROR]=b.wrapTemplate(["<% if( !dataset.purged ){ %>","<div><%- dataset.misc_blurb %></div>","<% } %>",'<span class="help-text">',c("An error occurred with this dataset"),":</span>",'<div class="job-error-text"><%- dataset.misc_info %></div>'],"dataset");k[a.EMPTY]=b.wrapTemplate(["<div>",c("No data"),": <i><%- dataset.misc_blurb %></i></div>"],"dataset");k.unknown=b.wrapTemplate(['<div>Error: unknown dataset state: "<%- dataset.state %>"</div>'],"dataset");var l={resubmitted:b.wrapTemplate(["<% if( model.resubmitted ){ %>",'<div class="resubmitted-msg infomessagesmall">',c("The job creating this dataset has been resubmitted"),"</div>","<% } %>"])};var g=b.wrapTemplate(["<% _.each( apps, function( app ){ %>",'<div class="display-application">','<span class="display-application-location"><%- app.label %></span> ','<span class="display-application-links">',"<% _.each( app.links, function( link ){ %>",'<a target="<%= link.target %>" href="<%= link.href %>">',"<% print( _l( link.text ) ); %>","</a> ","<% }); %>","</span>","</div>","<% }); %>"],"apps");return _.extend({},f.prototype.templates,{warnings:i,details:j,noAccess:h,summaries:k,detailMessages:l,displayApplications:g})}());return{DatasetListItemView:e}});
\ No newline at end of file
+define(["mvc/list/list-item","mvc/dataset/states","mvc/base-mvc","utils/localization"],function(d,a,b,c){var f=d.ListItemView;var e=f.extend({className:f.prototype.className+" dataset",id:function(){return["dataset",this.model.get("id")].join("-")},initialize:function(g){if(g.logger){this.logger=this.model.logger=g.logger}this.log(this+".initialize:",g);f.prototype.initialize.call(this,g);this.linkTarget=g.linkTarget||"_blank";this._setUpListeners()},_setUpListeners:function(){f.prototype._setUpListeners.call(this);this.model.on("change",function(h,g){if(this.model.changedAttributes().state&&this.model.inReadyState()&&this.expanded&&!this.model.hasDetails()){this.model.fetch()}else{this.render()}},this)},_fetchModelDetails:function(){var g=this;if(g.model.inReadyState()&&!g.model.hasDetails()){return g.model.fetch({silent:true})}return jQuery.when()},remove:function(h,i){var g=this;h=h||this.fxSpeed;this.$el.fadeOut(h,function(){Backbone.View.prototype.remove.call(g);if(i){i.call(g)}})},render:function(g){return f.prototype.render.call(this,g)},_swapNewRender:function(g){f.prototype._swapNewRender.call(this,g);if(this.model.has("state")){this.$el.addClass("state-"+this.model.get("state"))}return this.$el},_renderPrimaryActions:function(){return[this._renderDisplayButton()]},_renderDisplayButton:function(){var i=this.model.get("state");if((i===a.NOT_VIEWABLE)||(i===a.DISCARDED)||(!this.model.get("accessible"))){return null}var h={target:this.linkTarget,classes:"display-btn"};if(this.model.get("purged")){h.disabled=true;h.title=c("Cannot display datasets removed from disk")}else{if(i===a.UPLOAD){h.disabled=true;h.title=c("This dataset must finish uploading before it can be viewed")}else{if(i===a.NEW){h.disabled=true;h.title=c("This dataset is not yet viewable")}else{h.title=c("View data");h.href=this.model.urls.display;var g=this;h.onclick=function(j){if(Galaxy.frame&&Galaxy.frame.active){Galaxy.frame.add({title:"Data Viewer: "+g.model.get("name"),type:"other",content:function(k){require(["mvc/data"],function(l){var m=new l.TabularDataset({id:g.model.get("id")});$.when(m.fetch()).then(function(){l.createTabularDatasetChunkedView({model:m,parent_elt:k,embedded:true,height:"100%"})})})}});j.preventDefault()}}}}}h.faIcon="fa-eye";return faIconButton(h)},_renderDetails:function(){if(this.model.get("state")===a.NOT_VIEWABLE){return $(this.templates.noAccess(this.model.toJSON(),this))}var g=f.prototype._renderDetails.call(this);g.find(".actions .left").empty().append(this._renderSecondaryActions());g.find(".summary").html(this._renderSummary()).prepend(this._renderDetailMessages());g.find(".display-applications").html(this._renderDisplayApplications());this._setUpBehaviors(g);return g},_renderSummary:function(){var g=this.model.toJSON(),h=this.templates.summaries[g.state];h=h||this.templates.summaries.unknown;return h(g,this)},_renderDetailMessages:function(){var g=this,i=$('<div class="detail-messages"></div>'),h=g.model.toJSON();_.each(g.templates.detailMessages,function(j){i.append($(j(h,g)))});return i},_renderDisplayApplications:function(){if(this.model.isDeletedOrPurged()){return""}return[this.templates.displayApplications(this.model.get("display_apps"),this),this.templates.displayApplications(this.model.get("display_types"),this)].join("")},_renderSecondaryActions:function(){this.debug("_renderSecondaryActions");switch(this.model.get("state")){case a.NOT_VIEWABLE:return[];case a.OK:case a.FAILED_METADATA:case a.ERROR:return[this._renderDownloadButton(),this._renderShowParamsButton()]}return[this._renderShowParamsButton()]},_renderShowParamsButton:function(){return faIconButton({title:c("View details"),classes:"params-btn",href:this.model.urls.show_params,target:this.linkTarget,faIcon:"fa-info-circle"})},_renderDownloadButton:function(){if(this.model.get("purged")||!this.model.hasData()){return null}if(!_.isEmpty(this.model.get("meta_files"))){return this._renderMetaFileDownloadButton()}return $(['<a class="download-btn icon-btn" href="',this.model.urls.download,'" title="'+c("Download")+'">','<span class="fa fa-floppy-o"></span>',"</a>"].join(""))},_renderMetaFileDownloadButton:function(){var g=this.model.urls;return $(['<div class="metafile-dropdown dropdown">','<a class="download-btn icon-btn" href="javascript:void(0)" data-toggle="dropdown"',' title="'+c("Download")+'">','<span class="fa fa-floppy-o"></span>',"</a>",'<ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">','<li><a href="'+g.download+'">',c("Download dataset"),"</a></li>",_.map(this.model.get("meta_files"),function(h){return['<li><a href="',g.meta_download+h.file_type,'">',c("Download")," ",h.file_type,"</a></li>"].join("")}).join("\n"),"</ul>","</div>"].join("\n"))},toString:function(){var g=(this.model)?(this.model+""):("(no model)");return"DatasetListItemView("+g+")"}});e.prototype.templates=(function(){var i=_.extend({},f.prototype.templates.warnings,{failed_metadata:b.wrapTemplate(['<% if( model.state === "failed_metadata" ){ %>','<div class="warningmessagesmall">',c("An error occurred setting the metadata for this dataset"),"</div>","<% } %>"]),error:b.wrapTemplate(["<% if( model.error ){ %>",'<div class="errormessagesmall">',c("There was an error getting the data for this dataset"),": <%- model.error %>","</div>","<% } %>"]),purged:b.wrapTemplate(["<% if( model.purged ){ %>",'<div class="purged-msg warningmessagesmall">',c("This dataset has been deleted and removed from disk"),"</div>","<% } %>"]),deleted:b.wrapTemplate(["<% if( model.deleted && !model.purged ){ %>",'<div class="deleted-msg warningmessagesmall">',c("This dataset has been deleted"),"</div>","<% } %>"])});var j=b.wrapTemplate(['<div class="details">','<div class="summary"></div>','<div class="actions clear">','<div class="left"></div>','<div class="right"></div>',"</div>","<% if( !dataset.deleted && !dataset.purged ){ %>",'<div class="tags-display"></div>','<div class="annotation-display"></div>','<div class="display-applications"></div>',"<% if( dataset.peek ){ %>",'<pre class="dataset-peek"><%= dataset.peek %></pre>',"<% } %>","<% } %>","</div>"],"dataset");var h=b.wrapTemplate(['<div class="details">','<div class="summary">',c("You do not have permission to view this dataset"),"</div>","</div>"],"dataset");var k={};k[a.OK]=k[a.FAILED_METADATA]=b.wrapTemplate(["<% if( dataset.misc_blurb ){ %>",'<div class="blurb">','<span class="value"><%- dataset.misc_blurb %></span>',"</div>","<% } %>","<% if( dataset.file_ext ){ %>",'<div class="datatype">','<label class="prompt">',c("format"),"</label>",'<span class="value"><%- dataset.file_ext %></span>',"</div>","<% } %>","<% if( dataset.metadata_dbkey ){ %>",'<div class="dbkey">','<label class="prompt">',c("database"),"</label>",'<span class="value">',"<%- dataset.metadata_dbkey %>","</span>","</div>","<% } %>","<% if( dataset.misc_info ){ %>",'<div class="info">','<span class="value"><%- dataset.misc_info %></span>',"</div>","<% } %>"],"dataset");k[a.NEW]=b.wrapTemplate(["<div>",c("This is a new dataset and not all of its data are available yet"),"</div>"],"dataset");k[a.NOT_VIEWABLE]=b.wrapTemplate(["<div>",c("You do not have permission to view this dataset"),"</div>"],"dataset");k[a.DISCARDED]=b.wrapTemplate(["<div>",c("The job creating this dataset was cancelled before completion"),"</div>"],"dataset");k[a.QUEUED]=b.wrapTemplate(["<div>",c("This job is waiting to run"),"</div>"],"dataset");k[a.RUNNING]=b.wrapTemplate(["<div>",c("This job is currently running"),"</div>"],"dataset");k[a.UPLOAD]=b.wrapTemplate(["<div>",c("This dataset is currently uploading"),"</div>"],"dataset");k[a.SETTING_METADATA]=b.wrapTemplate(["<div>",c("Metadata is being auto-detected"),"</div>"],"dataset");k[a.PAUSED]=b.wrapTemplate(["<div>",c('This job is paused. Use the "Resume Paused Jobs" in the history menu to resume'),"</div>"],"dataset");k[a.ERROR]=b.wrapTemplate(["<% if( !dataset.purged ){ %>","<div><%- dataset.misc_blurb %></div>","<% } %>",'<span class="help-text">',c("An error occurred with this dataset"),":</span>",'<div class="job-error-text"><%- dataset.misc_info %></div>'],"dataset");k[a.EMPTY]=b.wrapTemplate(["<div>",c("No data"),": <i><%- dataset.misc_blurb %></i></div>"],"dataset");k.unknown=b.wrapTemplate(['<div>Error: unknown dataset state: "<%- dataset.state %>"</div>'],"dataset");var l={resubmitted:b.wrapTemplate(["<% if( model.resubmitted ){ %>",'<div class="resubmitted-msg infomessagesmall">',c("The job creating this dataset has been resubmitted"),"</div>","<% } %>"])};var g=b.wrapTemplate(["<% _.each( apps, function( app ){ %>",'<div class="display-application">','<span class="display-application-location"><%- app.label %></span> ','<span class="display-application-links">',"<% _.each( app.links, function( link ){ %>",'<a target="<%= link.target %>" href="<%= link.href %>">',"<% print( _l( link.text ) ); %>","</a> ","<% }); %>","</span>","</div>","<% }); %>"],"apps");return _.extend({},f.prototype.templates,{warnings:i,details:j,noAccess:h,summaries:k,detailMessages:l,displayApplications:g})}());return{DatasetListItemView:e}});
\ No newline at end of file
diff -r deb003947e0e02de4613912b14832944954576a5 -r 618b02d13329adf2d01b72e9743a8fa00192c6fd static/scripts/packed/mvc/history/hdca-li.js
--- a/static/scripts/packed/mvc/history/hdca-li.js
+++ b/static/scripts/packed/mvc/history/hdca-li.js
@@ -1,1 +1,1 @@
-define(["mvc/dataset/states","mvc/collection/collection-li","mvc/base-mvc","utils/localization"],function(a,e,c,d){var f=e.DCListItemView;var b=f.extend({className:f.prototype.className+" history-content",_swapNewRender:function(g){f.prototype._swapNewRender.call(this,g);var h=this.model.get("state")||a.OK;this.$el.addClass("state-"+h);return this.$el},toString:function(){var g=(this.model)?(this.model+""):("(no model)");return"HDCAListItemView("+g+")"}});b.prototype.templates=(function(){var g=c.wrapTemplate(['<div class="title-bar clear" tabindex="0">','<span class="state-icon"></span>','<div class="title">','<span class="hid"><%- collection.hid %></span> ','<span class="name"><%- collection.name %></span>',"</div>",'<div class="subtitle"></div>',"</div>"],"collection");return _.extend({},f.prototype.templates,{titleBar:g})}());return{HDCAListItemView:b}});
\ No newline at end of file
+define(["mvc/dataset/states","mvc/collection/collection-li","mvc/collection/collection-panel","mvc/base-mvc","utils/localization"],function(a,e,g,c,d){var f=e.DCListItemView;var b=f.extend({className:f.prototype.className+" history-content",_getFoldoutPanelClass:function(){switch(this.model.get("collection_type")){case"list":return g.ListCollectionPanel;case"paired":return g.PairCollectionPanel;case"list:paired":return g.ListOfPairsCollectionPanel}throw new TypeError("Uknown collection_type: "+this.model.get("collection_type"))},_swapNewRender:function(h){f.prototype._swapNewRender.call(this,h);var i=this.model.get("state")||a.OK;this.$el.addClass("state-"+i);return this.$el},toString:function(){var h=(this.model)?(this.model+""):("(no model)");return"HDCAListItemView("+h+")"}});b.prototype.templates=(function(){var h=c.wrapTemplate(['<div class="title-bar clear" tabindex="0">','<span class="state-icon"></span>','<div class="title">','<span class="hid"><%- collection.hid %></span> ','<span class="name"><%- collection.name %></span>',"</div>",'<div class="subtitle"></div>',"</div>"],"collection");return _.extend({},f.prototype.templates,{titleBar:h})}());return{HDCAListItemView:b}});
\ No newline at end of file
diff -r deb003947e0e02de4613912b14832944954576a5 -r 618b02d13329adf2d01b72e9743a8fa00192c6fd static/scripts/packed/mvc/history/history-panel-edit-current.js
--- a/static/scripts/packed/mvc/history/history-panel-edit-current.js
+++ b/static/scripts/packed/mvc/history/history-panel-edit-current.js
@@ -1,1 +1,1 @@
-define(["mvc/history/history-model","mvc/history/history-panel-edit","mvc/collection/collection-panel","mvc/base-mvc","utils/localization"],function(d,c,a,h,b){var e=h.SessionStorageModel.extend({defaults:{tagsEditorShown:false,annotationEditorShown:false},toString:function(){return"HistoryPanelPrefs("+JSON.stringify(this.toJSON())+")"}});e.storageKey=function f(){return("history-panel")};var g=c.HistoryPanelEdit;var i=g.extend({className:g.prototype.className+" current-history-panel",emptyMsg:b("This history is empty. Click 'Get Data' on the left tool menu to start"),noneFoundMsg:b("No matching datasets found"),initialize:function(j){j=j||{};this.preferences=new e(_.extend({id:e.storageKey()},_.pick(j,_.keys(e.prototype.defaults))));g.prototype.initialize.call(this,j);this.panelStack=[]},loadCurrentHistory:function(k){this.debug(this+".loadCurrentHistory");var j=this;return this.loadHistoryWithDetails("current",k).then(function(m,l){j.trigger("current-history",j)})},switchToHistory:function(m,l){var j=this,k=function(){return jQuery.getJSON(galaxy_config.root+"history/set_as_current?id="+m)};return this.loadHistoryWithDetails(m,l,k).then(function(o,n){j.trigger("switched-history",j)})},createNewHistory:function(l){if(!Galaxy||!Galaxy.currUser||Galaxy.currUser.isAnonymous()){this.displayMessage("error",b("You must be logged in to create histories"));return $.when()}var j=this,k=function(){return jQuery.getJSON(galaxy_config.root+"history/create_new_current")};return this.loadHistory(undefined,l,k).then(function(n,m){j.trigger("new-history",j)})},setModel:function(k,j,l){g.prototype.setModel.call(this,k,j,l);if(this.model){this.log("checking for updates");this.model.checkForUpdates()}return this},_setUpCollectionListeners:function(){g.prototype._setUpCollectionListeners.call(this);this.collection.on("state:ready",function(k,l,j){if((!k.get("visible"))&&(!this.storage.get("show_hidden"))){this.removeItemView(this.viewFromModel(k))}},this)},_setUpModelListeners:function(){g.prototype._setUpModelListeners.call(this);if(Galaxy&&Galaxy.quotaMeter){this.listenTo(this.model,"change:nice_size",function(){Galaxy.quotaMeter.update()})}},_buildNewRender:function(){if(!this.model){return $()}var j=g.prototype._buildNewRender.call(this);j.find(".search").prependTo(j.find(".controls"));this._renderQuotaMessage(j);return j},_renderQuotaMessage:function(j){j=j||this.$el;return $(this.templates.quotaMsg({},this)).prependTo(j.find(".messages"))},_renderEmptyMessage:function(l){var k=this,j=k.$emptyMessage(l),m=$(".toolMenuContainer");if((_.isEmpty(k.views)&&!k.searchFor)&&(Galaxy&&Galaxy.upload&&m.size())){j.empty();j.html([b("This history is empty"),". ",b("You can "),'<a class="uploader-link" href="javascript:void(0)">',b("load your own data"),"</a>",b(" or "),'<a class="get-data-link" href="javascript:void(0)">',b("get data from an external source"),"</a>"].join(""));j.find(".uploader-link").click(function(n){Galaxy.upload._eventShow(n)});j.find(".get-data-link").click(function(n){m.parent().scrollTop(0);m.find('span:contains("Get Data")').click()});return j.show()}return g.prototype._renderEmptyMessage.call(this,l)},_renderTags:function(j){var k=this;g.prototype._renderTags.call(this,j);if(this.preferences.get("tagsEditorShown")){this.tagsEditor.toggle(true)}this.tagsEditor.on("hiddenUntilActivated:shown hiddenUntilActivated:hidden",function(l){k.preferences.set("tagsEditorShown",l.hidden)})},_renderAnnotation:function(j){var k=this;g.prototype._renderAnnotation.call(this,j);if(this.preferences.get("annotationEditorShown")){this.annotationEditor.toggle(true)}this.annotationEditor.on("hiddenUntilActivated:shown hiddenUntilActivated:hidden",function(l){k.preferences.set("annotationEditorShown",l.hidden)})},_attachItems:function(j){this.$list(j).append(this.views.reverse().map(function(k){return k.$el}));return this},_setUpItemViewListeners:function(k){var j=this;g.prototype._setUpItemViewListeners.call(j,k);if(k instanceof j.HDCAViewClass){k.off("expanded");k.on("expanded",function(l){j.info("expanded",l);j._addCollectionPanel(l)});k.off("collapsed")}},_addCollectionPanel:function(l){var k=this,j=l.model;this.debug("history panel (stack), collectionModel:",j);var n=new (this._getCollectionPanelClass(j))({model:j,HDAViewClass:this.HDAViewClass,parentName:this.model.get("name"),linkTarget:this.linkTarget});k.panelStack.push(n);k.$(".controls").add(k.$list()).hide();k.$el.append(n.$el);n.on("close",function(){k.render();l.collapse();k.panelStack.pop()});if(!n.model.hasDetails()){var m=n.model.fetch();m.done(function(){n.render()})}else{n.render()}},_getCollectionPanelClass:function(j){switch(j.get("collection_type")){case"list":return a.ListCollectionPanel;case"paired":return a.PairCollectionPanel;case"list:paired":return a.ListOfPairsCollectionPanel}throw new TypeError("Uknown collection_type: "+j.get("collection_type"))},addItemView:function(o,p,n){this.log(this+".addItemView:",o);if(!this._filterItem(o)){return undefined}var l=this;if(this.panelStack.length){return l}var k=l._createItemView(o);this.views.unshift(k);l.scrollToTop();$({}).queue([function m(r){var q=l.$emptyMessage();if(q.is(":visible")){q.fadeOut(l.fxSpeed,r)}else{r()}},function j(q){l.scrollToTop();l.$list().prepend(k.render(0).$el.hide());k.$el.slideDown(l.fxSpeed)}]);return k},connectToQuotaMeter:function(j){if(!j){return this}this.listenTo(j,"quota:over",this.showQuotaMessage);this.listenTo(j,"quota:under",this.hideQuotaMessage);this.on("rendered rendered:initial",function(){if(j&&j.isOverQuota()){this.showQuotaMessage()}});return this},showQuotaMessage:function(){var j=this.$el.find(".quota-message");if(j.is(":hidden")){j.slideDown(this.fxSpeed)}},hideQuotaMessage:function(){var j=this.$el.find(".quota-message");if(!j.is(":hidden")){j.slideUp(this.fxSpeed)}},connectToOptionsMenu:function(j){if(!j){return this}this.on("new-storage",function(l,k){if(j&&l){j.findItemByHtml(b("Include Deleted Datasets")).checked=l.get("show_deleted");j.findItemByHtml(b("Include Hidden Datasets")).checked=l.get("show_hidden")}});return this},toString:function(){return"CurrentHistoryPanel("+((this.model)?(this.model.get("name")):(""))+")"}});i.prototype.templates=(function(){var j=h.wrapTemplate(['<div class="quota-message errormessage">',b("You are over your disk quota"),". ",b("Tool execution is on hold until your disk usage drops below your allocated quota"),".","</div>"],"history");return _.extend(_.clone(g.prototype.templates),{quotaMsg:j})}());return{CurrentHistoryPanel:i}});
\ No newline at end of file
+define(["mvc/history/history-model","mvc/history/history-panel-edit","mvc/collection/collection-panel","mvc/base-mvc","utils/localization"],function(d,c,a,h,b){var e=h.SessionStorageModel.extend({defaults:{tagsEditorShown:false,annotationEditorShown:false},toString:function(){return"HistoryPanelPrefs("+JSON.stringify(this.toJSON())+")"}});e.storageKey=function f(){return("history-panel")};var g=c.HistoryPanelEdit;var i=g.extend({className:g.prototype.className+" current-history-panel",emptyMsg:b("This history is empty. Click 'Get Data' on the left tool menu to start"),noneFoundMsg:b("No matching datasets found"),HDCAViewClass:g.prototype.HDCAViewClass.extend({foldoutStyle:"drilldown"}),initialize:function(j){j=j||{};this.preferences=new e(_.extend({id:e.storageKey()},_.pick(j,_.keys(e.prototype.defaults))));g.prototype.initialize.call(this,j);this.panelStack=[]},loadCurrentHistory:function(k){this.debug(this+".loadCurrentHistory");var j=this;return this.loadHistoryWithDetails("current",k).then(function(m,l){j.trigger("current-history",j)})},switchToHistory:function(m,l){var j=this,k=function(){return jQuery.getJSON(galaxy_config.root+"history/set_as_current?id="+m)};return this.loadHistoryWithDetails(m,l,k).then(function(o,n){j.trigger("switched-history",j)})},createNewHistory:function(l){if(!Galaxy||!Galaxy.currUser||Galaxy.currUser.isAnonymous()){this.displayMessage("error",b("You must be logged in to create histories"));return $.when()}var j=this,k=function(){return jQuery.getJSON(galaxy_config.root+"history/create_new_current")};return this.loadHistory(undefined,l,k).then(function(n,m){j.trigger("new-history",j)})},setModel:function(k,j,l){g.prototype.setModel.call(this,k,j,l);if(this.model){this.log("checking for updates");this.model.checkForUpdates()}return this},_setUpCollectionListeners:function(){g.prototype._setUpCollectionListeners.call(this);this.collection.on("state:ready",function(k,l,j){if((!k.get("visible"))&&(!this.storage.get("show_hidden"))){this.removeItemView(this.viewFromModel(k))}},this)},_setUpModelListeners:function(){g.prototype._setUpModelListeners.call(this);if(Galaxy&&Galaxy.quotaMeter){this.listenTo(this.model,"change:nice_size",function(){Galaxy.quotaMeter.update()})}},_buildNewRender:function(){if(!this.model){return $()}var j=g.prototype._buildNewRender.call(this);j.find(".search").prependTo(j.find(".controls"));this._renderQuotaMessage(j);return j},_renderQuotaMessage:function(j){j=j||this.$el;return $(this.templates.quotaMsg({},this)).prependTo(j.find(".messages"))},_renderEmptyMessage:function(l){var k=this,j=k.$emptyMessage(l),m=$(".toolMenuContainer");if((_.isEmpty(k.views)&&!k.searchFor)&&(Galaxy&&Galaxy.upload&&m.size())){j.empty();j.html([b("This history is empty"),". ",b("You can "),'<a class="uploader-link" href="javascript:void(0)">',b("load your own data"),"</a>",b(" or "),'<a class="get-data-link" href="javascript:void(0)">',b("get data from an external source"),"</a>"].join(""));j.find(".uploader-link").click(function(n){Galaxy.upload._eventShow(n)});j.find(".get-data-link").click(function(n){m.parent().scrollTop(0);m.find('span:contains("Get Data")').click()});return j.show()}return g.prototype._renderEmptyMessage.call(this,l)},_renderTags:function(j){var k=this;g.prototype._renderTags.call(this,j);if(this.preferences.get("tagsEditorShown")){this.tagsEditor.toggle(true)}this.tagsEditor.on("hiddenUntilActivated:shown hiddenUntilActivated:hidden",function(l){k.preferences.set("tagsEditorShown",l.hidden)})},_renderAnnotation:function(j){var k=this;g.prototype._renderAnnotation.call(this,j);if(this.preferences.get("annotationEditorShown")){this.annotationEditor.toggle(true)}this.annotationEditor.on("hiddenUntilActivated:shown hiddenUntilActivated:hidden",function(l){k.preferences.set("annotationEditorShown",l.hidden)})},_attachItems:function(j){this.$list(j).append(this.views.reverse().map(function(k){return k.$el}));return this},addItemView:function(o,p,n){this.log(this+".addItemView:",o);var l=this;if(!l._filterItem(o)){return undefined}if(l.panelStack.length){return this._collapseDrilldownPanel()}var k=l._createItemView(o);l.views.unshift(k);l.scrollToTop();$({}).queue([function m(r){var q=l.$emptyMessage();if(q.is(":visible")){q.fadeOut(l.fxSpeed,r)}else{r()}},function j(q){l.$list().prepend(k.render(0).$el.hide());k.$el.slideDown(l.fxSpeed)}]);return k},_setUpItemViewListeners:function(k){var j=this;g.prototype._setUpItemViewListeners.call(j,k);k.on("expanded:drilldown",function(m,l){this._expandDrilldownPanel(l)},this);k.on("collapsed:drilldown",function(m,l){this._collapseDrilldownPanel(l)},this);return this},_expandDrilldownPanel:function(j){this.panelStack.push(j);this.$("> .controls").add(this.$list()).hide();j.parentName=this.model.get("name");this.$el.append(j.render().$el)},_collapseDrilldownPanel:function(j){this.panelStack.pop();this.render()},connectToQuotaMeter:function(j){if(!j){return this}this.listenTo(j,"quota:over",this.showQuotaMessage);this.listenTo(j,"quota:under",this.hideQuotaMessage);this.on("rendered rendered:initial",function(){if(j&&j.isOverQuota()){this.showQuotaMessage()}});return this},showQuotaMessage:function(){var j=this.$el.find(".quota-message");if(j.is(":hidden")){j.slideDown(this.fxSpeed)}},hideQuotaMessage:function(){var j=this.$el.find(".quota-message");if(!j.is(":hidden")){j.slideUp(this.fxSpeed)}},connectToOptionsMenu:function(j){if(!j){return this}this.on("new-storage",function(l,k){if(j&&l){j.findItemByHtml(b("Include Deleted Datasets")).checked=l.get("show_deleted");j.findItemByHtml(b("Include Hidden Datasets")).checked=l.get("show_hidden")}});return this},toString:function(){return"CurrentHistoryPanel("+((this.model)?(this.model.get("name")):(""))+")"}});i.prototype.templates=(function(){var j=h.wrapTemplate(['<div class="quota-message errormessage">',b("You are over your disk quota"),". ",b("Tool execution is on hold until your disk usage drops below your allocated quota"),".","</div>"],"history");return _.extend(_.clone(g.prototype.templates),{quotaMsg:j})}());return{CurrentHistoryPanel:i}});
\ No newline at end of file
diff -r deb003947e0e02de4613912b14832944954576a5 -r 618b02d13329adf2d01b72e9743a8fa00192c6fd static/scripts/packed/mvc/history/history-panel.js
--- a/static/scripts/packed/mvc/history/history-panel.js
+++ b/static/scripts/packed/mvc/history/history-panel.js
@@ -1,1 +1,1 @@
-define(["mvc/list/list-panel","mvc/history/history-model","mvc/history/history-contents","mvc/history/hda-li","mvc/history/hdca-li","mvc/user/user-model","mvc/base-mvc","utils/localization"],function(d,f,l,b,a,g,n,e){var j=n.SessionStorageModel.extend({defaults:{expandedIds:{},show_deleted:false,show_hidden:false},addExpandedHda:function(o){var p="expandedIds";this.save(p,_.extend(this.get(p),_.object([o.id],[o.get("id")])))},removeExpandedHda:function(o){var p="expandedIds";this.save(p,_.omit(this.get(p),o.id))},toString:function(){return"HistoryPrefs("+this.id+")"}});j.storageKeyPrefix="history:";j.historyStorageKey=function h(o){if(!o){throw new Error("HistoryPrefs.historyStorageKey needs valid id: "+o)}return(j.storageKeyPrefix+o)};j.get=function c(o){return new j({id:j.historyStorageKey(o)})};j.clearAll=function i(p){for(var o in sessionStorage){if(o.indexOf(j.storageKeyPrefix)===0){sessionStorage.removeItem(o)}}};var m=d.ModelListPanel;var k=m.extend({HDAViewClass:b.HDAListItemView,HDCAViewClass:a.HDCAListItemView,collectionClass:l.HistoryContents,modelCollectionKey:"contents",tagName:"div",className:m.prototype.className+" history-panel",emptyMsg:e("This history is empty"),noneFoundMsg:e("No matching datasets found"),searchPlaceholder:e("search datasets"),initialize:function(o){m.prototype.initialize.call(this,o);this.linkTarget=o.linkTarget||"_blank"},freeModel:function(){m.prototype.freeModel.call(this);if(this.model){this.model.clearUpdateTimeout()}return this},_setUpListeners:function(){m.prototype._setUpListeners.call(this);this.on("error",function(p,s,o,r,q){this.errorHandler(p,s,o,r,q)});this.on("loading-done",function(){if(!this.views.length){this.trigger("empty-history",this)}})},loadHistoryWithDetails:function(r,q,p,s){this.info("loadHistoryWithDetails:",r,q,p,s);var o=function(t){return _.values(j.get(t.id).get("expandedIds"))};return this.loadHistory(r,q,p,s,o)},loadHistory:function(s,r,q,t,o){this.info("loadHistory:",s,r,q,t,o);var p=this;r=r||{};p.trigger("loading",p);var u=f.History.getHistoryData(s,{historyFn:q,contentsFn:t,detailIdsFn:r.initiallyExpanded||o});return p._loadHistoryFromXHR(u,r).fail(function(x,v,w){p.trigger("error",p,x,r,e("An error was encountered while "+v),{historyId:s,history:w||{}})}).always(function(){p.trigger("loading-done",p)})},_loadHistoryFromXHR:function(q,p){var o=this;q.then(function(r,s){o.JSONToModel(r,s,p);o.render()});q.fail(function(s,r){o.render()});return q},JSONToModel:function(r,o,p){this.log("JSONToModel:",r,o,p);p=p||{};var q=new f.History(r,o,p);this.setModel(q);return q},setModel:function(p,o){o=o||{};m.prototype.setModel.call(this,p,o);if(this.model){this._setUpWebStorage(o.initiallyExpanded,o.show_deleted,o.show_hidden)}},_setUpWebStorage:function(p,o,q){this.storage=new j({id:j.historyStorageKey(this.model.get("id"))});if(_.isObject(p)){this.storage.set("expandedIds",p)}if(_.isBoolean(o)){this.storage.set("show_deleted",o)}if(_.isBoolean(q)){this.storage.set("show_hidden",q)}this.trigger("new-storage",this.storage,this);this.log(this+" (init'd) storage:",this.storage.get());return this},_buildNewRender:function(){var o=m.prototype._buildNewRender.call(this);if(this.multiselectActions.length){o.find(".controls .actions").prepend(this._renderSelectButton())}return o},_renderSelectButton:function(o){return faIconButton({title:e("Operations on multiple datasets"),classes:"show-selectors-btn",faIcon:"fa-check-square-o"})},_getItemViewClass:function(o){var p=o.get("history_content_type");switch(p){case"dataset":return this.HDAViewClass;case"dataset_collection":return this.HDCAViewClass}throw new TypeError("Unknown history_content_type: "+p)},_filterItem:function(p){var o=this;return(m.prototype._filterItem.call(o,p)&&(!p.hidden()||o.storage.get("show_hidden"))&&(!p.isDeletedOrPurged()||o.storage.get("show_deleted")))},_getItemViewOptions:function(p){var o=m.prototype._getItemViewOptions.call(this,p);return _.extend(o,{linkTarget:this.linkTarget,expanded:!!this.storage.get("expandedIds")[p.id],hasUser:this.model.ownedByCurrUser()})},_setUpItemViewListeners:function(p){var o=this;m.prototype._setUpItemViewListeners.call(o,p);p.on("expanded",function(q){o.storage.addExpandedHda(q.model)});p.on("collapsed",function(q){o.storage.removeExpandedHda(q.model)});return this},refreshContents:function(p,o){if(this.model){return this.model.refresh(p,o)}return $.when()},getSelectedModels:function(){var o=m.prototype.getSelectedModels.call(this);o.historyId=this.collection.historyId;return o},events:_.extend(_.clone(m.prototype.events),{"click .show-selectors-btn":"toggleSelectors"}),toggleShowDeleted:function(o){o=(o!==undefined)?(o):(!this.storage.get("show_deleted"));this.storage.set("show_deleted",o);this.renderItems();return this.storage.get("show_deleted")},toggleShowHidden:function(o){o=(o!==undefined)?(o):(!this.storage.get("show_hidden"));this.storage.set("show_hidden",o);this.renderItems();return this.storage.get("show_hidden")},_firstSearch:function(o){var p=this,q=".history-search-input";this.log("onFirstSearch",o);if(p.model.contents.haveDetails()){p.searchItems(o);return}p.$el.find(q).searchInput("toggle-loading");p.model.contents.fetchAllDetails({silent:true}).always(function(){p.$el.find(q).searchInput("toggle-loading")}).done(function(){p.searchItems(o)})},errorHandler:function(q,t,p,s,r){this.error(q,t,p,s,r);if(t&&t.status===0&&t.readyState===0){}else{if(t&&t.status===502){}else{var o=this._parseErrorMessage(q,t,p,s,r);if(!this.$messages().is(":visible")){this.once("rendered",function(){this.displayMessage("error",o.message,o.details)})}else{this.displayMessage("error",o.message,o.details)}}}},_parseErrorMessage:function(s,v,w,q,o,t){var r=Galaxy.currUser,u={message:this._bePolite(q),details:{message:q,raven:(window.Raven&&_.isFunction(Raven.lastEventId))?(Raven.lastEventId()):(undefined),agent:navigator.userAgent,url:(window.Galaxy)?(Galaxy.lastAjax.url):(undefined),data:(window.Galaxy)?(Galaxy.lastAjax.data):(undefined),options:(v)?(_.omit(w,"xhr")):(w),xhr:v,source:(_.isFunction(s.toJSON))?(s.toJSON()):(s+""),user:(r instanceof g.User)?(r.toJSON()):(r+"")}};_.extend(u.details,o||{});if(v&&_.isFunction(v.getAllResponseHeaders)){var p=v.getAllResponseHeaders();p=_.compact(p.split("\n"));p=_.map(p,function(x){return x.split(": ")});u.details.xhr.responseHeaders=_.object(p)}return u},_bePolite:function(o){o=o||e("An error occurred while getting updates from the server");return o+". "+e("Please contact a Galaxy administrator if the problem persists")+"."},displayMessage:function(t,u,s){var q=this;this.scrollToTop();var r=this.$messages(),o=$("<div/>").addClass(t+"message").html(u);if(!_.isEmpty(s)){var p=$('<a href="javascript:void(0)">Details</a>').click(function(){Galaxy.modal.show(q._messageToModalOptions(t,u,s));return false});o.append(" ",p)}return r.html(o)},_messageToModalOptions:function(r,u,q){var o=this,p={title:"Details"};if(_.isObject(q)){q=_.omit(q,_.functions(q));var t=JSON.stringify(q,null," "),s=$("<pre/>").text(t);p.body=$("<div/>").append(s)}else{p.body=$("<div/>").html(q)}p.buttons={Ok:function(){Galaxy.modal.hide();o.clearMessages()}};return p},clearMessages:function(o){$(o.currentTarget).fadeOut(this.fxSpeed,function(){$(this).remove()});return this},scrollToHid:function(o){return this.scrollToItem(_.first(this.viewsWhereModel({hid:o})))},toString:function(){return"HistoryPanel("+((this.model)?(this.model.get("name")):(""))+")"}});k.prototype.templates=(function(){var o=n.wrapTemplate(['<div class="controls">','<div class="title">','<div class="name"><%= history.name %></div>',"</div>",'<div class="subtitle">',"</div>",'<div class="history-size"><%= history.nice_size %></div>','<div class="actions"></div>','<div class="messages">',"<% if( history.deleted ){ %>",'<div class="deleted-msg warningmessagesmall">',e("This history has been deleted"),"</div>","<% } %>","<% if( history.message ){ %>",'<div class="<%= history.message.level || "info" %>messagesmall">',"<%= history.message.text %>","</div>","<% } %>","</div>",'<div class="tags-display"></div>','<div class="annotation-display"></div>','<div class="search">','<div class="search-input"></div>',"</div>",'<div class="list-actions">','<div class="btn-group">','<button class="select-all btn btn-default"','data-mode="select">',e("All"),"</button>",'<button class="deselect-all btn btn-default"','data-mode="select">',e("None"),"</button>","</div>",'<button class="list-action-popup-btn btn btn-default">',e("For all selected"),"...</button>","</div>","</div>"],"history");return _.extend(_.clone(m.prototype.templates),{controls:o})}());return{HistoryPanel:k}});
\ No newline at end of file
+define(["mvc/list/list-panel","mvc/history/history-model","mvc/history/history-contents","mvc/history/hda-li","mvc/history/hdca-li","mvc/collection/collection-panel","mvc/user/user-model","mvc/base-mvc","utils/localization"],function(d,f,l,b,a,m,g,o,e){var j=o.SessionStorageModel.extend({defaults:{expandedIds:{},show_deleted:false,show_hidden:false},addExpanded:function(p){var q="expandedIds";this.save(q,_.extend(this.get(q),_.object([p.id],[p.get("id")])))},removeExpanded:function(p){var q="expandedIds";this.save(q,_.omit(this.get(q),p.id))},toString:function(){return"HistoryPrefs("+this.id+")"}});j.storageKeyPrefix="history:";j.historyStorageKey=function h(p){if(!p){throw new Error("HistoryPrefs.historyStorageKey needs valid id: "+p)}return(j.storageKeyPrefix+p)};j.get=function c(p){return new j({id:j.historyStorageKey(p)})};j.clearAll=function i(q){for(var p in sessionStorage){if(p.indexOf(j.storageKeyPrefix)===0){sessionStorage.removeItem(p)}}};var n=d.ModelListPanel;var k=n.extend({HDAViewClass:b.HDAListItemView,HDCAViewClass:a.HDCAListItemView,collectionClass:l.HistoryContents,modelCollectionKey:"contents",tagName:"div",className:n.prototype.className+" history-panel",emptyMsg:e("This history is empty"),noneFoundMsg:e("No matching datasets found"),searchPlaceholder:e("search datasets"),initialize:function(p){n.prototype.initialize.call(this,p);this.linkTarget=p.linkTarget||"_blank"},freeModel:function(){n.prototype.freeModel.call(this);if(this.model){this.model.clearUpdateTimeout()}return this},_setUpListeners:function(){n.prototype._setUpListeners.call(this);this.on("error",function(q,t,p,s,r){this.errorHandler(q,t,p,s,r)});this.on("loading-done",function(){if(!this.views.length){this.trigger("empty-history",this)}})},loadHistoryWithDetails:function(s,r,q,t){this.info("loadHistoryWithDetails:",s,r,q,t);var p=function(u){return _.values(j.get(u.id).get("expandedIds"))};return this.loadHistory(s,r,q,t,p)},loadHistory:function(t,s,r,u,p){this.info("loadHistory:",t,s,r,u,p);var q=this;s=s||{};q.trigger("loading",q);var v=f.History.getHistoryData(t,{historyFn:r,contentsFn:u,detailIdsFn:s.initiallyExpanded||p});return q._loadHistoryFromXHR(v,s).fail(function(y,w,x){q.trigger("error",q,y,s,e("An error was encountered while "+w),{historyId:t,history:x||{}})}).always(function(){q.trigger("loading-done",q)})},_loadHistoryFromXHR:function(r,q){var p=this;r.then(function(s,t){p.JSONToModel(s,t,q);p.render()});r.fail(function(t,s){p.render()});return r},refreshContents:function(q,p){if(this.model){return this.model.refresh(q,p)}return $.when()},JSONToModel:function(s,p,q){this.log("JSONToModel:",s,p,q);q=q||{};var r=new f.History(s,p,q);this.setModel(r);return r},setModel:function(q,p){p=p||{};n.prototype.setModel.call(this,q,p);if(this.model){this._setUpWebStorage(p.initiallyExpanded,p.show_deleted,p.show_hidden)}},_setUpWebStorage:function(q,p,r){this.storage=new j({id:j.historyStorageKey(this.model.get("id"))});if(_.isObject(q)){this.storage.set("expandedIds",q)}if(_.isBoolean(p)){this.storage.set("show_deleted",p)}if(_.isBoolean(r)){this.storage.set("show_hidden",r)}this.trigger("new-storage",this.storage,this);this.log(this+" (init'd) storage:",this.storage.get());return this},_buildNewRender:function(){var p=n.prototype._buildNewRender.call(this);if(this.multiselectActions.length){p.find(".controls .actions").prepend(this._renderSelectButton())}return p},_renderSelectButton:function(p){return faIconButton({title:e("Operations on multiple datasets"),classes:"show-selectors-btn",faIcon:"fa-check-square-o"})},_getItemViewClass:function(p){var q=p.get("history_content_type");switch(q){case"dataset":return this.HDAViewClass;case"dataset_collection":return this.HDCAViewClass}throw new TypeError("Unknown history_content_type: "+q)},_filterItem:function(q){var p=this;return(n.prototype._filterItem.call(p,q)&&(!q.hidden()||p.storage.get("show_hidden"))&&(!q.isDeletedOrPurged()||p.storage.get("show_deleted")))},_getItemViewOptions:function(q){var p=n.prototype._getItemViewOptions.call(this,q);return _.extend(p,{linkTarget:this.linkTarget,expanded:!!this.storage.get("expandedIds")[q.id],hasUser:this.model.ownedByCurrUser()})},_setUpItemViewListeners:function(q){var p=this;n.prototype._setUpItemViewListeners.call(p,q);q.on("expanded",function(r){p.storage.addExpanded(r.model)});q.on("collapsed",function(r){p.storage.removeExpanded(r.model)});return this},getSelectedModels:function(){var p=n.prototype.getSelectedModels.call(this);p.historyId=this.collection.historyId;return p},events:_.extend(_.clone(n.prototype.events),{"click .show-selectors-btn":"toggleSelectors"}),toggleShowDeleted:function(p){p=(p!==undefined)?(p):(!this.storage.get("show_deleted"));this.storage.set("show_deleted",p);this.renderItems();return this.storage.get("show_deleted")},toggleShowHidden:function(p){p=(p!==undefined)?(p):(!this.storage.get("show_hidden"));this.storage.set("show_hidden",p);this.renderItems();return this.storage.get("show_hidden")},_firstSearch:function(p){var q=this,r=".history-search-input";this.log("onFirstSearch",p);if(q.model.contents.haveDetails()){q.searchItems(p);return}q.$el.find(r).searchInput("toggle-loading");q.model.contents.fetchAllDetails({silent:true}).always(function(){q.$el.find(r).searchInput("toggle-loading")}).done(function(){q.searchItems(p)})},errorHandler:function(r,u,q,t,s){this.error(r,u,q,t,s);if(u&&u.status===0&&u.readyState===0){}else{if(u&&u.status===502){}else{var p=this._parseErrorMessage(r,u,q,t,s);if(!this.$messages().is(":visible")){this.once("rendered",function(){this.displayMessage("error",p.message,p.details)})}else{this.displayMessage("error",p.message,p.details)}}}},_parseErrorMessage:function(t,w,x,r,p,u){var s=Galaxy.currUser,v={message:this._bePolite(r),details:{message:r,raven:(window.Raven&&_.isFunction(Raven.lastEventId))?(Raven.lastEventId()):(undefined),agent:navigator.userAgent,url:(window.Galaxy)?(Galaxy.lastAjax.url):(undefined),data:(window.Galaxy)?(Galaxy.lastAjax.data):(undefined),options:(w)?(_.omit(x,"xhr")):(x),xhr:w,source:(_.isFunction(t.toJSON))?(t.toJSON()):(t+""),user:(s instanceof g.User)?(s.toJSON()):(s+"")}};_.extend(v.details,p||{});if(w&&_.isFunction(w.getAllResponseHeaders)){var q=w.getAllResponseHeaders();q=_.compact(q.split("\n"));q=_.map(q,function(y){return y.split(": ")});v.details.xhr.responseHeaders=_.object(q)}return v},_bePolite:function(p){p=p||e("An error occurred while getting updates from the server");return p+". "+e("Please contact a Galaxy administrator if the problem persists")+"."},displayMessage:function(u,v,t){var r=this;this.scrollToTop();var s=this.$messages(),p=$("<div/>").addClass(u+"message").html(v);if(!_.isEmpty(t)){var q=$('<a href="javascript:void(0)">Details</a>').click(function(){Galaxy.modal.show(r._messageToModalOptions(u,v,t));return false});p.append(" ",q)}return s.html(p)},_messageToModalOptions:function(s,v,r){var p=this,q={title:"Details"};if(_.isObject(r)){r=_.omit(r,_.functions(r));var u=JSON.stringify(r,null," "),t=$("<pre/>").text(u);q.body=$("<div/>").append(t)}else{q.body=$("<div/>").html(r)}q.buttons={Ok:function(){Galaxy.modal.hide();p.clearMessages()}};return q},clearMessages:function(p){$(p.currentTarget).fadeOut(this.fxSpeed,function(){$(this).remove()});return this},scrollToHid:function(p){return this.scrollToItem(_.first(this.viewsWhereModel({hid:p})))},toString:function(){return"HistoryPanel("+((this.model)?(this.model.get("name")):(""))+")"}});k.prototype.templates=(function(){var p=o.wrapTemplate(['<div class="controls">','<div class="title">','<div class="name"><%= history.name %></div>',"</div>",'<div class="subtitle">',"</div>",'<div class="history-size"><%= history.nice_size %></div>','<div class="actions"></div>','<div class="messages">',"<% if( history.deleted ){ %>",'<div class="deleted-msg warningmessagesmall">',e("This history has been deleted"),"</div>","<% } %>","<% if( history.message ){ %>",'<div class="<%= history.message.level || "info" %>messagesmall">',"<%= history.message.text %>","</div>","<% } %>","</div>",'<div class="tags-display"></div>','<div class="annotation-display"></div>','<div class="search">','<div class="search-input"></div>',"</div>",'<div class="list-actions">','<div class="btn-group">','<button class="select-all btn btn-default"','data-mode="select">',e("All"),"</button>",'<button class="deselect-all btn btn-default"','data-mode="select">',e("None"),"</button>","</div>",'<button class="list-action-popup-btn btn btn-default">',e("For all selected"),"...</button>","</div>","</div>"],"history");return _.extend(_.clone(n.prototype.templates),{controls:p})}());return{HistoryPanel:k}});
\ No newline at end of file
diff -r deb003947e0e02de4613912b14832944954576a5 -r 618b02d13329adf2d01b72e9743a8fa00192c6fd static/scripts/packed/mvc/list/list-item.js
--- a/static/scripts/packed/mvc/list/list-item.js
+++ b/static/scripts/packed/mvc/list/list-item.js
@@ -1,1 +1,1 @@
-define(["mvc/base-mvc","utils/localization"],function(b,c){var d=Backbone.View.extend(b.LoggableMixin).extend({initialize:function(e){this.expanded=e.expanded||false;this.fxSpeed=e.fxSpeed||this.fxSpeed},fxSpeed:"fast",render:function(f){var e=this._buildNewRender();this._setUpBehaviors(e);this._queueNewRender(e,f);return this},_buildNewRender:function(){var e=$(this.templates.el(this.model.toJSON(),this));if(this.expanded){this.$details(e).replaceWith(this._renderDetails().show())}return e},_queueNewRender:function(f,g){g=(g===undefined)?(this.fxSpeed):(g);var e=this;$(e).queue("fx",[function(h){this.$el.fadeOut(g,h)},function(h){e._swapNewRender(f);h()},function(h){this.$el.fadeIn(g,h)},function(h){this.trigger("rendered",e);h()}])},_swapNewRender:function(e){return this.$el.empty().attr("class",this.className).append(e.children())},_setUpBehaviors:function(e){e=e||this.$el;e.find("[title]").tooltip({placement:"bottom"})},$details:function(e){e=e||this.$el;return e.find(".details")},_renderDetails:function(){var e=$(this.templates.details(this.model.toJSON(),this));this._setUpBehaviors(e);return e},toggleExpanded:function(e){e=(e===undefined)?(!this.expanded):(e);if(e){this.expand()}else{this.collapse()}return this},expand:function(){var e=this;return e._fetchModelDetails().always(function(){var f=e._renderDetails();e.$details().replaceWith(f);e.expanded=true;f.slideDown(e.fxSpeed,function(){e.trigger("expanded",e)})})},_fetchModelDetails:function(){if(!this.model.hasDetails()){return this.model.fetch()}return jQuery.when()},collapse:function(){var e=this;e.expanded=false;this.$details().slideUp(e.fxSpeed,function(){e.trigger("collapsed",e)})}});var a=d.extend(b.mixin(b.SelectableViewMixin,b.DraggableViewMixin,{tagName:"div",className:"list-item",initialize:function(e){d.prototype.initialize.call(this,e);b.SelectableViewMixin.initialize.call(this,e);b.DraggableViewMixin.initialize.call(this,e)},_buildNewRender:function(){var e=d.prototype._buildNewRender.call(this);e.find(".warnings").replaceWith(this._renderWarnings());e.find(".title-bar").replaceWith(this._renderTitleBar());e.find(".primary-actions").append(this._renderPrimaryActions());e.find(".subtitle").replaceWith(this._renderSubtitle());return e},_swapNewRender:function(e){d.prototype._swapNewRender.call(this,e);if(this.selectable){this.showSelector(0)}if(this.draggable){this.draggableOn()}return this.$el},_renderWarnings:function(){var e=this,g=$('<div class="warnings"></div>'),f=e.model.toJSON();_.each(e.templates.warnings,function(h){g.append($(h(f,e)))});return g},_renderTitleBar:function(){return $(this.templates.titleBar(this.model.toJSON(),this))},_renderPrimaryActions:function(){return[]},_renderSubtitle:function(){return $(this.templates.subtitle(this.model.toJSON(),this))},events:{"click .title-bar":"_clickTitleBar","keydown .title-bar":"_keyDownTitleBar","click .selector":"toggleSelect"},_clickTitleBar:function(e){e.stopPropagation();this.toggleExpanded()},_keyDownTitleBar:function(g){var e=32,f=13;if(g&&(g.type==="keydown")&&(g.keyCode===e||g.keyCode===f)){this.toggleExpanded();g.stopPropagation();return false}return true},toString:function(){var e=(this.model)?(this.model+""):("(no model)");return"ListItemView("+e+")"}}));a.prototype.templates=(function(){var g=b.wrapTemplate(['<div class="list-element">','<div class="warnings"></div>','<div class="selector">','<span class="fa fa-2x fa-square-o"></span>',"</div>",'<div class="primary-actions"></div>','<div class="title-bar"></div>','<div class="details"></div>',"</div>"]);var e={};var h=b.wrapTemplate(['<div class="title-bar clear" tabindex="0">','<span class="state-icon"></span>','<div class="title">','<span class="name"><%- element.name %></span>',"</div>",'<div class="subtitle"></div>',"</div>"],"element");var i=b.wrapTemplate(['<div class="subtitle"></div>']);var f=b.wrapTemplate(['<div class="details"></div>']);return{el:g,warnings:e,titleBar:h,subtitle:i,details:f}}());return{ExpandableView:d,ListItemView:a}});
\ No newline at end of file
+define(["mvc/base-mvc","utils/localization"],function(b,d){var e=Backbone.View.extend(b.LoggableMixin).extend({initialize:function(f){this.expanded=f.expanded||false;this.fxSpeed=f.fxSpeed||this.fxSpeed},fxSpeed:"fast",render:function(g){var f=this._buildNewRender();this._setUpBehaviors(f);this._queueNewRender(f,g);return this},_buildNewRender:function(){var f=$(this.templates.el(this.model.toJSON(),this));if(this.expanded){this.$details(f).replaceWith(this._renderDetails().show())}return f},_queueNewRender:function(g,h){h=(h===undefined)?(this.fxSpeed):(h);var f=this;$(f).queue("fx",[function(i){this.$el.fadeOut(h,i)},function(i){f._swapNewRender(g);i()},function(i){this.$el.fadeIn(h,i)},function(i){this.trigger("rendered",f);i()}])},_swapNewRender:function(f){return this.$el.empty().attr("class",this.className).append(f.children())},_setUpBehaviors:function(f){f=f||this.$el;f.find("[title]").tooltip({placement:"bottom"})},$details:function(f){f=f||this.$el;return f.find("> .details")},_renderDetails:function(){var f=$(this.templates.details(this.model.toJSON(),this));this._setUpBehaviors(f);return f},toggleExpanded:function(f){f=(f===undefined)?(!this.expanded):(f);if(f){this.expand()}else{this.collapse()}return this},expand:function(){var f=this;return f._fetchModelDetails().always(function(){var g=f._renderDetails();f.$details().replaceWith(g);f.expanded=true;f.$details().slideDown(f.fxSpeed,function(){f.trigger("expanded",f)})})},_fetchModelDetails:function(){if(!this.model.hasDetails()){return this.model.fetch()}return jQuery.when()},collapse:function(){this.debug(this+"(ExpandableView).collapse");var f=this;f.expanded=false;this.$details().slideUp(f.fxSpeed,function(){f.trigger("collapsed",f)})}});var a=e.extend(b.mixin(b.SelectableViewMixin,b.DraggableViewMixin,{tagName:"div",className:"list-item",initialize:function(f){e.prototype.initialize.call(this,f);b.SelectableViewMixin.initialize.call(this,f);b.DraggableViewMixin.initialize.call(this,f);this._setUpListeners()},_setUpListeners:function(){this.on("selectable",function(f){if(f){this.$(".primary-actions").hide()}else{this.$(".primary-actions").show()}},this);return this},_buildNewRender:function(){var f=e.prototype._buildNewRender.call(this);f.children(".warnings").replaceWith(this._renderWarnings());f.children(".title-bar").replaceWith(this._renderTitleBar());f.children(".primary-actions").append(this._renderPrimaryActions());f.find(".title-bar .subtitle").replaceWith(this._renderSubtitle());return f},_swapNewRender:function(f){e.prototype._swapNewRender.call(this,f);if(this.selectable){this.showSelector(0)}if(this.draggable){this.draggableOn()}return this.$el},_renderWarnings:function(){var f=this,h=$('<div class="warnings"></div>'),g=f.model.toJSON();_.each(f.templates.warnings,function(i){h.append($(i(g,f)))});return h},_renderTitleBar:function(){return $(this.templates.titleBar(this.model.toJSON(),this))},_renderPrimaryActions:function(){return[]},_renderSubtitle:function(){return $(this.templates.subtitle(this.model.toJSON(),this))},events:{"click .title-bar":"_clickTitleBar","keydown .title-bar":"_keyDownTitleBar","click .selector":"toggleSelect"},_clickTitleBar:function(f){f.stopPropagation();this.toggleExpanded()},_keyDownTitleBar:function(h){var f=32,g=13;if(h&&(h.type==="keydown")&&(h.keyCode===f||h.keyCode===g)){this.toggleExpanded();h.stopPropagation();return false}return true},toString:function(){var f=(this.model)?(this.model+""):("(no model)");return"ListItemView("+f+")"}}));a.prototype.templates=(function(){var h=b.wrapTemplate(['<div class="list-element">','<div class="warnings"></div>','<div class="selector">','<span class="fa fa-2x fa-square-o"></span>',"</div>",'<div class="primary-actions"></div>','<div class="title-bar"></div>','<div class="details"></div>',"</div>"]);var f={};var i=b.wrapTemplate(['<div class="title-bar clear" tabindex="0">','<span class="state-icon"></span>','<div class="title">','<span class="name"><%- element.name %></span>',"</div>",'<div class="subtitle"></div>',"</div>"],"element");var j=b.wrapTemplate(['<div class="subtitle"></div>']);var g=b.wrapTemplate(['<div class="details"></div>']);return{el:h,warnings:f,titleBar:i,subtitle:j,details:g}}());var c=a.extend({foldoutStyle:"foldout",foldoutPanelClass:null,initialize:function(f){a.prototype.initialize.call(this,f);if(this.foldoutStyle==="drilldown"){this.expanded=false}this.foldoutStyle=f.foldoutStyle||this.foldoutStyle;this.foldoutPanelClass=f.foldoutPanelClass||this.foldoutPanelClass},$:function(f){var g=a.prototype.$.call(this,f);return g},_renderDetails:function(){if(this.foldoutStyle==="drilldown"){return $()}var f=a.prototype._renderDetails.call(this);return this._attachFoldout(this._createFoldoutPanel(),f)},_createFoldoutPanel:function(){var h=this.model;var i=this._getFoldoutPanelClass(h),g=this._getFoldoutPanelOptions(h),f=new i(_.extend(g,{model:h}));return f},_getFoldoutPanelClass:function(){return this.foldoutPanelClass},_getFoldoutPanelOptions:function(){return{foldoutStyle:this.foldoutStyle}},_attachFoldout:function(f,g){g=g||this.$("> .details");this.foldout=f.render(0);f.$("> .controls").hide();return g.append(f.$el)},expand:function(){var f=this;return f._fetchModelDetails().always(function(){if(f.foldoutStyle==="foldout"){f._expandByFoldout()}else{if(f.foldoutStyle==="drilldown"){f._expandByDrilldown()}}})},_expandByFoldout:function(){var f=this;var g=f._renderDetails();f.$details().replaceWith(g);f.expanded=true;f.$details().slideDown(f.fxSpeed,function(){f.trigger("expanded",f)})},_expandByDrilldown:function(){var f=this;f.foldout=this._createFoldoutPanel();f.foldout.on("close",function(){f.trigger("collapsed:drilldown",f,f.foldout)});f.trigger("expanded:drilldown",f,f.foldout)}});c.prototype.templates=(function(){var f=b.wrapTemplate(['<div class="details">',"</div>"],"collection");return _.extend({},a.prototype.templates,{details:f})}());return{ExpandableView:e,ListItemView:a,FoldoutListItemView:c}});
\ No newline at end of file
diff -r deb003947e0e02de4613912b14832944954576a5 -r 618b02d13329adf2d01b72e9743a8fa00192c6fd static/scripts/packed/mvc/list/list-panel.js
--- a/static/scripts/packed/mvc/list/list-panel.js
+++ b/static/scripts/packed/mvc/list/list-panel.js
@@ -1,1 +1,1 @@
-define(["mvc/list/list-item","mvc/base-mvc","utils/localization"],function(d,b,c){var e=Backbone.View.extend(b.LoggableMixin).extend({viewClass:d.ListItemView,collectionClass:Backbone.Collection,tagName:"div",className:"list-panel",fxSpeed:"fast",emptyMsg:c("This list is empty"),noneFoundMsg:c("No matching items found"),searchPlaceholder:c("search"),multiselectActions:[],initialize:function(f,g){f=f||{};if(f.logger){this.logger=f.logger}this.log(this+".initialize:",f);this.fxSpeed=_.has(f,"fxSpeed")?(f.fxSpeed):(this.fxSpeed);this.filters=[];this.searchFor=f.searchFor||"";this.indicator=new LoadingIndicator(this.$el);this.selecting=(f.selecting!==undefined)?f.selecting:true;this.selected=f.selected||[];this.lastSelected=null;this.viewClass=f.viewClass||this.viewClass;this.views=[];this.collection=f.collection||(new this.collectionClass([]));this.filters=f.filters||[];this.$scrollContainer=f.$scrollContainer||this.$scrollContainer;this.title=f.title||"";this.subtitle=f.subtitle||"";this.multiselectActions=f.multiselectActions||this.multiselectActions;this.actionsPopup=null;this._setUpListeners()},freeViews:function(){_.each(this.views,function(f){f.off()});this.views=[];return this},_setUpListeners:function(){this.off();this.on("error",function(g,j,f,i,h){console.error(g,j,f,i,h)},this);this.on("loading",function(){this._showLoadingIndicator("loading...",40)},this);this.on("loading-done",function(){this._hideLoadingIndicator(40)},this);this.once("rendered",function(){this.trigger("rendered:initial",this)},this);if(this.logger){this.on("all",function(f){this.log(this+"",arguments)},this)}this._setUpCollectionListeners();this._setUpViewListeners();return this},_setUpCollectionListeners:function(){this.log(this+"._setUpCollectionListeners",this.collection);this.collection.off();this.collection.on("error",function(g,j,f,i,h){this.trigger("error",g,j,f,i,h)},this);this.collection.on("reset",function(){this.renderItems()},this);this.collection.on("add",this.addItemView,this);this.collection.on("remove",this.removeItemView,this);if(this.logger){this.collection.on("all",function(f){this.info(this+"(collection)",arguments)},this)}return this},_setUpViewListeners:function(){this.log(this+"._setUpViewListeners");this.on("view:selected",function(f,g){if(g&&g.shiftKey&&this.lastSelected){var h=_.find(this.views,function(i){return i.model.id===this.lastSelected});if(h){this.selectRange(f,h)}}this.selected.push(f.model.id);this.lastSelected=f.model.id},this);this.on("view:de-selected",function(f,g){this.selected=_.without(this.selected,f.model.id)},this)},render:function(g){this.log(this+".render",g);var f=this._buildNewRender();this._setUpBehaviors(f);this._queueNewRender(f,g);return this},_buildNewRender:function(){this.debug(this+"(ListPanel)._buildNewRender");var f=$(this.templates.el({},this));this._renderControls(f);this._renderTitle(f);this._renderSubtitle(f);this._renderSearch(f);this.renderItems(f);return f},_renderControls:function(g){this.debug(this+"(ListPanel)._renderControls");var f=$(this.templates.controls({},this));g.find(".controls").replaceWith(f);return f},_renderTitle:function(f){},_renderSubtitle:function(f){},_queueNewRender:function(g,h){h=(h===undefined)?(this.fxSpeed):(h);var f=this;f.log("_queueNewRender:",g,h);$(f).queue("fx",[function(i){this.$el.fadeOut(h,i)},function(i){f._swapNewRender(g);i()},function(i){this.$el.fadeIn(h,i)},function(i){f.trigger("rendered",f);i()}])},_swapNewRender:function(f){this.$el.empty().attr("class",this.className).append(f.children());if(this.selecting){this.showSelectors(0)}return this},_setUpBehaviors:function(f){f=f||this.$el;f.find(".controls [title]").tooltip({placement:"bottom"});return this},$scrollContainer:function(){return this.$el.parent().parent()},$list:function(f){return(f||this.$el).find(".list-items")},$messages:function(f){return(f||this.$el).find(".messages")},$emptyMessage:function(f){return(f||this.$el).find(".empty-message")},renderItems:function(h){h=h||this.$el;var f=this;f.log(this+".renderItems",h);var g=f.$list(h);f.views=f._filterCollection().map(function(i){return f._createItemView(i).render(0)});g.empty();if(f.views.length){f._attachItems(h);f.$emptyMessage(h).hide()}else{f._renderEmptyMessage(h).show()}return f.views},_filterCollection:function(){var f=this;return f.collection.filter(_.bind(f._filterItem,f))},_filterItem:function(g){var f=this;return(_.every(f.filters.map(function(h){return h.call(g)})))&&(!f.searchFor||g.matchesAll(f.searchFor))},_createItemView:function(h){var i=this._getItemViewClass(h),g=_.extend(this._getItemViewOptions(h),{model:h}),f=new i(g);this._setUpItemViewListeners(f);return f},_getItemViewClass:function(f){return this.viewClass},_getItemViewOptions:function(f){return{fxSpeed:this.fxSpeed,expanded:false,selectable:this.selecting,selected:_.contains(this.selected,f.id),draggable:this.dragging}},_setUpItemViewListeners:function(g){var f=this;g.on("all",function(){var h=Array.prototype.slice.call(arguments,0);h[0]="view:"+h[0];f.trigger.apply(f,h)});return f},_attachItems:function(f){this.$list(f).append(this.views.map(function(g){return g.$el}));return this},_renderEmptyMessage:function(f){this.debug("_renderEmptyMessage",f,this.searchFor);var g=this.searchFor?this.noneFoundMsg:this.emptyMsg;return this.$emptyMessage(f).text(g)},expandAll:function(){_.each(this.views,function(f){f.expand()})},collapseAll:function(){_.each(this.views,function(f){f.collapse()})},addItemView:function(i,j,h){this.log(this+".addItemView:",i);var g=this;if(!g._filterItem(i)){return undefined}var f=g._createItemView(i);g.views.push(f);$(f).queue("fx",[function(k){g.$emptyMessage().fadeOut(g.fxSpeed,k)},function(k){g.$list().append(f.render().$el);k()}]);return f},removeItemView:function(i,j,h){this.log(this+".removeItemView:",i);var g=this,f=g.viewFromModel(i);if(!f){return undefined}$({}).queue("fx",[function(k){f.$el.fadeOut(g.fxSpeed,k)},function(k){g.views=_.without(g.views,f);f.remove();if(!g.views.length){g._renderEmptyMessage().fadeIn(g.fxSpeed,k)}else{k()}}]);return f},viewFromModel:function(g){for(var h=0;h<this.views.length;h++){var f=this.views[h];if(f.model===g){return f}}return undefined},viewFromModelId:function(g){for(var f=0;f<this.views.length;f++){if(this.views[f].model.id===g){return this.views[f]}}return undefined},viewsWhereModel:function(f){return this.views.filter(function(g){var i=g.model.toJSON();for(var h in f){if(f.hasOwnProperty(h)){if(i[h]!==g.model.get(h)){return false}}}return true})},viewRange:function(i,h){if(i===h){return(i)?([i]):([])}var g=this.views.indexOf(i),f=this.views.indexOf(h);if(g===-1||f===-1){if(g===f){return[]}return(g===-1)?([h]):([i])}return(g<f)?this.views.slice(g,f+1):this.views.slice(f,g+1)},_renderSearch:function(f){f.find(".controls .search-input").searchInput({placeholder:this.searchPlaceholder,initialVal:this.searchFor,onfirstsearch:_.bind(this._firstSearch,this),onsearch:_.bind(this.searchItems,this),onclear:_.bind(this.clearSearch,this)});return f},_firstSearch:function(f){this.log("onFirstSearch",f);return this.searchItems(f)},searchItems:function(f){this.searchFor=f;this.trigger("search:searching",f,this);this.renderItems();return this},clearSearch:function(f){this.searchFor="";this.trigger("search:clear",this);this.renderItems();return this},showSelectors:function(f){f=(f!==undefined)?(f):(this.fxSpeed);this.selecting=true;this.$(".list-actions").slideDown(f);_.each(this.views,function(g){g.showSelector(f)})},hideSelectors:function(f){f=(f!==undefined)?(f):(this.fxSpeed);this.selecting=false;this.$(".list-actions").slideUp(f);_.each(this.views,function(g){g.hideSelector(f)});this.selected=[];this.lastSelected=null},toggleSelectors:function(){if(!this.selecting){this.showSelectors()}else{this.hideSelectors()}},selectAll:function(f){_.each(this.views,function(g){g.select(f)})},deselectAll:function(f){this.lastSelected=null;_.each(this.views,function(g){g.deselect(f)})},selectRange:function(h,g){var f=this.viewRange(h,g);_.each(f,function(i){i.select()});return f},getSelectedViews:function(){return _.filter(this.views,function(f){return f.selected})},getSelectedModels:function(){return new this.collection.constructor(_.map(this.getSelectedViews(),function(f){return f.model}))},_showLoadingIndicator:function(g,f,h){this.debug("_showLoadingIndicator",this.indicator,g,f,h);f=(f!==undefined)?(f):(this.fxSpeed);if(!this.indicator){this.indicator=new LoadingIndicator(this.$el,this.$el.parent());this.debug("\t created",this.indicator)}if(!this.$el.is(":visible")){this.indicator.show(0,h)}else{this.$el.fadeOut(f);this.indicator.show(g,f,h)}},_hideLoadingIndicator:function(f,g){this.debug("_hideLoadingIndicator",this.indicator,f,g);f=(f!==undefined)?(f):(this.fxSpeed);if(this.indicator){this.indicator.hide(f,g)}},scrollPosition:function(){return this.$scrollContainer().scrollTop()},scrollTo:function(f){this.$scrollContainer().scrollTop(f);return this},scrollToTop:function(){this.$scrollContainer().scrollTop(0);return this},scrollToItem:function(f){if(!f){return this}var g=f.$el.offset().top;this.$scrollContainer().scrollTop(g);return this},scrollToId:function(f){return this.scrollToItem(this.viewFromModelId(f))},events:{"click .select-all":"selectAll","click .deselect-all":"deselectAll"},toString:function(){return"ListPanel("+this.collection+")"}});e.prototype.templates=(function(){var g=b.wrapTemplate(["<div>",'<div class="controls"></div>','<div class="list-items"></div>','<div class="empty-message infomessagesmall"></div>',"</div>"]);var f=b.wrapTemplate(['<div class="controls">','<div class="title">','<div class="name"><%= view.title %></div>',"</div>",'<div class="subtitle"><%= view.subtitle %></div>','<div class="actions"></div>','<div class="messages"></div>','<div class="search">','<div class="search-input"></div>',"</div>",'<div class="list-actions">','<div class="btn-group">','<button class="select-all btn btn-default"','data-mode="select">',c("All"),"</button>",'<button class="deselect-all btn btn-default"','data-mode="select">',c("None"),"</button>","</div>","</div>","</div>"]);return{el:g,controls:f}}());var a=e.extend({modelCollectionKey:"contents",initialize:function(f){e.prototype.initialize.call(this,f);this.selecting=(f.selecting!==undefined)?f.selecting:false;this.setModel(this.model,f)},setModel:function(g,f){f=f||{};this.debug(this+".setModel:",g,f);this.freeModel();this.freeViews();if(g){this.model=g;if(this.logger){this.model.logger=this.logger}this._setUpModelListeners();this.collection.off();this.collection=(this.model[this.modelCollectionKey])?this.model[this.modelCollectionKey]:(f.collection||(new this.collectionClass([])));this._setUpCollectionListeners();this.trigger("new-model",this)}return this},freeModel:function(){if(this.model){this.stopListening(this.model)}return this},_setUpModelListeners:function(){this.log(this+"._setUpModelListeners",this.model);this.model.on("error",function(){this.trigger.apply(panel,arguments)},this);return this},_renderControls:function(g){this.debug(this+"(ListPanel)._renderControls");var h=this.model?this.model.toJSON():{},f=$(this.templates.controls(h,this));g.find(".controls").replaceWith(f);this.debug("\t .controls:",this.$(".controls"));this.debug("\t $controls:",f);return f},toString:function(){return"ModelListPanel("+this.model+")"}});a.prototype.templates=(function(){var f=b.wrapTemplate(['<div class="controls">','<div class="title">','<div class="name"><%= model.name %></div>',"</div>",'<div class="subtitle"><%= view.subtitle %></div>','<div class="actions"></div>','<div class="messages"></div>','<div class="search">','<div class="search-input"></div>',"</div>",'<div class="list-actions">','<div class="btn-group">','<button class="select-all btn btn-default"','data-mode="select">',c("All"),"</button>",'<button class="deselect-all btn btn-default"','data-mode="select">',c("None"),"</button>","</div>","</div>","</div>"]);return _.extend(_.clone(e.prototype.templates),{controls:f})}());return{ListPanel:e,ModelListPanel:a}});
\ No newline at end of file
+define(["mvc/list/list-item","mvc/base-mvc","utils/localization"],function(d,b,c){var e=Backbone.View.extend(b.LoggableMixin).extend({viewClass:d.ListItemView,collectionClass:Backbone.Collection,tagName:"div",className:"list-panel",fxSpeed:"fast",emptyMsg:c("This list is empty"),noneFoundMsg:c("No matching items found"),searchPlaceholder:c("search"),multiselectActions:[],initialize:function(f,g){f=f||{};if(f.logger){this.logger=f.logger}this.log(this+".initialize:",f);this.fxSpeed=_.has(f,"fxSpeed")?(f.fxSpeed):(this.fxSpeed);this.filters=[];this.searchFor=f.searchFor||"";this.indicator=new LoadingIndicator(this.$el);this.selecting=(f.selecting!==undefined)?f.selecting:true;this.selected=f.selected||[];this.lastSelected=null;this.viewClass=f.viewClass||this.viewClass;this.views=[];this.collection=f.collection||(new this.collectionClass([]));this.filters=f.filters||[];this.$scrollContainer=f.$scrollContainer||this.$scrollContainer;this.title=f.title||"";this.subtitle=f.subtitle||"";this.multiselectActions=f.multiselectActions||this.multiselectActions;this.actionsPopup=null;this._setUpListeners()},freeViews:function(){_.each(this.views,function(f){f.off()});this.views=[];return this},_setUpListeners:function(){this.off();this.on("error",function(g,j,f,i,h){console.error(g,j,f,i,h)},this);this.on("loading",function(){this._showLoadingIndicator("loading...",40)},this);this.on("loading-done",function(){this._hideLoadingIndicator(40)},this);this.once("rendered",function(){this.trigger("rendered:initial",this)},this);if(this.logger){this.on("all",function(f){this.log(this+"",arguments)},this)}this._setUpCollectionListeners();this._setUpViewListeners();return this},_setUpCollectionListeners:function(){this.log(this+"._setUpCollectionListeners",this.collection);this.collection.off();this.collection.on("error",function(g,j,f,i,h){this.trigger("error",g,j,f,i,h)},this);this.collection.on("reset",function(){this.renderItems()},this);this.collection.on("add",this.addItemView,this);this.collection.on("remove",this.removeItemView,this);if(this.logger){this.collection.on("all",function(f){this.info(this+"(collection)",arguments)},this)}return this},_setUpViewListeners:function(){this.log(this+"._setUpViewListeners");this.on("view:selected",function(f,g){if(g&&g.shiftKey&&this.lastSelected){var h=this.viewFromModelId(this.lastSelected);if(h){this.selectRange(f,h)}}this.selected.push(f.model.id);this.lastSelected=f.model.id},this);this.on("view:de-selected",function(f,g){this.selected=_.without(this.selected,f.model.id)},this)},render:function(g){this.log(this+".render",g);var f=this._buildNewRender();this._setUpBehaviors(f);this._queueNewRender(f,g);return this},_buildNewRender:function(){this.debug(this+"(ListPanel)._buildNewRender");var f=$(this.templates.el({},this));this._renderControls(f);this._renderTitle(f);this._renderSubtitle(f);this._renderSearch(f);this.renderItems(f);return f},_renderControls:function(g){this.debug(this+"(ListPanel)._renderControls");var f=$(this.templates.controls({},this));g.find(".controls").replaceWith(f);return f},_renderTitle:function(f){},_renderSubtitle:function(f){},_queueNewRender:function(g,h){h=(h===undefined)?(this.fxSpeed):(h);var f=this;f.log("_queueNewRender:",g,h);$(f).queue("fx",[function(i){this.$el.fadeOut(h,i)},function(i){f._swapNewRender(g);i()},function(i){this.$el.fadeIn(h,i)},function(i){f.trigger("rendered",f);i()}])},_swapNewRender:function(f){this.$el.empty().attr("class",this.className).append(f.children());if(this.selecting){this.showSelectors(0)}return this},_setUpBehaviors:function(f){f=f||this.$el;f.find(".controls [title]").tooltip({placement:"bottom"});return this},$scrollContainer:function(){return this.$el.parent().parent()},$list:function(f){return(f||this.$el).find("> .list-items")},$messages:function(f){return(f||this.$el).find("> .controls .messages")},$emptyMessage:function(f){return(f||this.$el).find("> .empty-message")},renderItems:function(h){h=h||this.$el;var f=this;f.log(this+".renderItems",h);var g=f.$list(h);f.views=f._filterCollection().map(function(i){return f._createItemView(i).render(0)});g.empty();if(f.views.length){f._attachItems(h);f.$emptyMessage(h).hide()}else{f._renderEmptyMessage(h).show()}return f.views},_filterCollection:function(){var f=this;return f.collection.filter(_.bind(f._filterItem,f))},_filterItem:function(g){var f=this;return(_.every(f.filters.map(function(h){return h.call(g)})))&&(!f.searchFor||g.matchesAll(f.searchFor))},_createItemView:function(h){var i=this._getItemViewClass(h),g=_.extend(this._getItemViewOptions(h),{model:h}),f=new i(g);this._setUpItemViewListeners(f);return f},_getItemViewClass:function(f){return this.viewClass},_getItemViewOptions:function(f){return{fxSpeed:this.fxSpeed,expanded:false,selectable:this.selecting,selected:_.contains(this.selected,f.id),draggable:this.dragging}},_setUpItemViewListeners:function(g){var f=this;g.on("all",function(){var h=Array.prototype.slice.call(arguments,0);h[0]="view:"+h[0];f.trigger.apply(f,h)});return f},_attachItems:function(f){this.$list(f).append(this.views.map(function(g){return g.$el}));return this},_renderEmptyMessage:function(f){this.debug("_renderEmptyMessage",f,this.searchFor);var g=this.searchFor?this.noneFoundMsg:this.emptyMsg;return this.$emptyMessage(f).text(g)},expandAll:function(){_.each(this.views,function(f){f.expand()})},collapseAll:function(){_.each(this.views,function(f){f.collapse()})},addItemView:function(i,j,h){this.log(this+".addItemView:",i);var g=this;if(!g._filterItem(i)){return undefined}var f=g._createItemView(i);g.views.push(f);$(f).queue("fx",[function(k){g.$emptyMessage().fadeOut(g.fxSpeed,k)},function(k){g.$list().append(f.render().$el);k()}]);return f},removeItemView:function(i,j,h){this.log(this+".removeItemView:",i);var g=this,f=g.viewFromModel(i);if(!f){return undefined}$({}).queue("fx",[function(k){f.$el.fadeOut(g.fxSpeed,k)},function(k){g.views=_.without(g.views,f);f.remove();if(!g.views.length){g._renderEmptyMessage().fadeIn(g.fxSpeed,k)}else{k()}}]);return f},viewFromModel:function(g){for(var h=0;h<this.views.length;h++){var f=this.views[h];if(f.model===g){return f}}return undefined},viewFromModelId:function(g){for(var f=0;f<this.views.length;f++){if(this.views[f].model.id===g){return this.views[f]}}return undefined},viewsWhereModel:function(f){return this.views.filter(function(g){var i=g.model.toJSON();for(var h in f){if(f.hasOwnProperty(h)){if(i[h]!==g.model.get(h)){return false}}}return true})},viewRange:function(i,h){if(i===h){return(i)?([i]):([])}var g=this.views.indexOf(i),f=this.views.indexOf(h);if(g===-1||f===-1){if(g===f){return[]}return(g===-1)?([h]):([i])}return(g<f)?this.views.slice(g,f+1):this.views.slice(f,g+1)},_renderSearch:function(f){f.find(".controls .search-input").searchInput({placeholder:this.searchPlaceholder,initialVal:this.searchFor,onfirstsearch:_.bind(this._firstSearch,this),onsearch:_.bind(this.searchItems,this),onclear:_.bind(this.clearSearch,this)});return f},_firstSearch:function(f){this.log("onFirstSearch",f);return this.searchItems(f)},searchItems:function(f){this.searchFor=f;this.trigger("search:searching",f,this);this.renderItems();return this},clearSearch:function(f){this.searchFor="";this.trigger("search:clear",this);this.renderItems();return this},showSelectors:function(f){f=(f!==undefined)?(f):(this.fxSpeed);this.selecting=true;this.$(".list-actions").slideDown(f);_.each(this.views,function(g){console.debug(g.$el);g.showSelector(f)})},hideSelectors:function(f){f=(f!==undefined)?(f):(this.fxSpeed);this.selecting=false;this.$(".list-actions").slideUp(f);_.each(this.views,function(g){g.hideSelector(f)});this.selected=[];this.lastSelected=null},toggleSelectors:function(){if(!this.selecting){this.showSelectors()}else{this.hideSelectors()}},selectAll:function(f){_.each(this.views,function(g){g.select(f)})},deselectAll:function(f){this.lastSelected=null;_.each(this.views,function(g){g.deselect(f)})},selectRange:function(h,g){var f=this.viewRange(h,g);_.each(f,function(i){i.select()});return f},getSelectedViews:function(){return _.filter(this.views,function(f){return f.selected})},getSelectedModels:function(){return new this.collection.constructor(_.map(this.getSelectedViews(),function(f){return f.model}))},_showLoadingIndicator:function(g,f,h){this.debug("_showLoadingIndicator",this.indicator,g,f,h);f=(f!==undefined)?(f):(this.fxSpeed);if(!this.indicator){this.indicator=new LoadingIndicator(this.$el,this.$el.parent());this.debug("\t created",this.indicator)}if(!this.$el.is(":visible")){this.indicator.show(0,h)}else{this.$el.fadeOut(f);this.indicator.show(g,f,h)}},_hideLoadingIndicator:function(f,g){this.debug("_hideLoadingIndicator",this.indicator,f,g);f=(f!==undefined)?(f):(this.fxSpeed);if(this.indicator){this.indicator.hide(f,g)}},scrollPosition:function(){return this.$scrollContainer().scrollTop()},scrollTo:function(f){this.$scrollContainer().scrollTop(f);return this},scrollToTop:function(){this.$scrollContainer().scrollTop(0);return this},scrollToItem:function(f){if(!f){return this}var g=f.$el.offset().top;this.$scrollContainer().scrollTop(g);return this},scrollToId:function(f){return this.scrollToItem(this.viewFromModelId(f))},events:{"click .select-all":"selectAll","click .deselect-all":"deselectAll"},toString:function(){return"ListPanel("+this.collection+")"}});e.prototype.templates=(function(){var g=b.wrapTemplate(["<div>",'<div class="controls"></div>','<div class="list-items"></div>','<div class="empty-message infomessagesmall"></div>',"</div>"]);var f=b.wrapTemplate(['<div class="controls">','<div class="title">','<div class="name"><%= view.title %></div>',"</div>",'<div class="subtitle"><%= view.subtitle %></div>','<div class="actions"></div>','<div class="messages"></div>','<div class="search">','<div class="search-input"></div>',"</div>",'<div class="list-actions">','<div class="btn-group">','<button class="select-all btn btn-default"','data-mode="select">',c("All"),"</button>",'<button class="deselect-all btn btn-default"','data-mode="select">',c("None"),"</button>","</div>","</div>","</div>"]);return{el:g,controls:f}}());var a=e.extend({modelCollectionKey:"contents",initialize:function(f){e.prototype.initialize.call(this,f);this.selecting=(f.selecting!==undefined)?f.selecting:false;this.setModel(this.model,f)},setModel:function(g,f){f=f||{};this.debug(this+".setModel:",g,f);this.freeModel();this.freeViews();if(g){this.model=g;if(this.logger){this.model.logger=this.logger}this._setUpModelListeners();this.collection.off();this.collection=(this.model[this.modelCollectionKey])?this.model[this.modelCollectionKey]:(f.collection||(new this.collectionClass([])));this._setUpCollectionListeners();this.trigger("new-model",this)}return this},freeModel:function(){if(this.model){this.stopListening(this.model)}return this},_setUpModelListeners:function(){this.log(this+"._setUpModelListeners",this.model);this.model.on("error",function(){this.trigger.apply(panel,arguments)},this);return this},_renderControls:function(g){this.debug(this+"(ListPanel)._renderControls");var h=this.model?this.model.toJSON():{},f=$(this.templates.controls(h,this));g.find(".controls").replaceWith(f);this.debug("\t .controls:",this.$(".controls"));this.debug("\t $controls:",f);return f},toString:function(){return"ModelListPanel("+this.model+")"}});a.prototype.templates=(function(){var f=b.wrapTemplate(['<div class="controls">','<div class="title">','<div class="name"><%= model.name %></div>',"</div>",'<div class="subtitle"><%= view.subtitle %></div>','<div class="actions"></div>','<div class="messages"></div>','<div class="search">','<div class="search-input"></div>',"</div>",'<div class="list-actions">','<div class="btn-group">','<button class="select-all btn btn-default"','data-mode="select">',c("All"),"</button>",'<button class="deselect-all btn btn-default"','data-mode="select">',c("None"),"</button>","</div>","</div>","</div>"]);return _.extend(_.clone(e.prototype.templates),{controls:f})}());return{ListPanel:e,ModelListPanel:a}});
\ No newline at end of file
diff -r deb003947e0e02de4613912b14832944954576a5 -r 618b02d13329adf2d01b72e9743a8fa00192c6fd static/scripts/packed/mvc/tools/tools-form.js
--- a/static/scripts/packed/mvc/tools/tools-form.js
+++ b/static/scripts/packed/mvc/tools/tools-form.js
@@ -1,1 +1,1 @@
-define(["mvc/ui/ui-portlet","mvc/ui/ui-misc","mvc/citation/citation-model","mvc/citation/citation-view","mvc/tools","mvc/tools/tools-template","mvc/tools/tools-datasets","mvc/tools/tools-section","mvc/tools/tools-tree"],function(g,k,i,a,f,d,h,j,c){var e=Backbone.Model.extend({initialize:function(l){this.url=galaxy_config.root+"api/tools/"+l.id+"?io_details=true"}});var b=Backbone.View.extend({main_el:"body",initialize:function(m){var l=this;this.options=m;this.model=new e({id:m.id});this.tree=new c(this);this.field_list={};this.input_list={};this.datasets=new h({history_id:this.options.history_id,success:function(){l._initializeToolForm()}})},_initializeToolForm:function(){var m=this;var n=new k.ButtonIcon({icon:"fa-question-circle",title:"Question?",tooltip:"Ask a question about this tool (Biostar)",onclick:function(){window.open(m.options.biostar_url+"/p/new/post/")}});var o=new k.ButtonIcon({icon:"fa-search",title:"Search",tooltip:"Search help for this tool (Biostar)",onclick:function(){window.open(m.options.biostar_url+"/t/"+m.options.id+"/")}});var l=new k.ButtonIcon({icon:"fa-share",title:"Share",tooltip:"Share this tool",onclick:function(){prompt("Copy to clipboard: Ctrl+C, Enter",galaxy_config.root+"root?tool_id="+m.options.id)}});this.model.fetch({error:function(p){console.debug("tools-form::_initializeToolForm() : Attempt to fetch tool model failed.")},success:function(){m.inputs=m.model.get("inputs");m.portlet=new g.View({icon:"fa-wrench",title:"<b>"+m.model.get("name")+"</b> "+m.model.get("description"),buttons:{execute:new k.ButtonIcon({icon:"fa-check",tooltip:"Execute the tool",title:"Execute",floating:"clear",onclick:function(){m._submit()}})},operations:{button_question:n,button_search:o,button_share:l}});if(!m.options.biostar_url){n.$el.hide();o.$el.hide()}m.message=new k.Message();m.portlet.append(m.message.$el);$(m.main_el).append(m.portlet.$el);if(m.options.help!=""){$(m.main_el).append(d.help(m.options.help))}if(m.options.citations){$(m.main_el).append(d.citations());var p=new i.ToolCitationCollection();p.tool_id=m.options.id;var q=new a.CitationListView({collection:p});q.render();p.fetch()}m.setElement(m.portlet.content());m.section=new j.View(m,{inputs:m.model.get("inputs")});m.portlet.append(m.section.$el);m.refresh();m._submit()}})},refresh:function(){this.tree.refresh();for(var l in this.field_list){this.field_list[l].trigger("change")}console.debug("tools-form::refresh() - Recreated tree structure. Refresh.")},_submit:function(){console.log(this.tree.finalize())}});return{View:b}});
\ No newline at end of file
+define(["mvc/ui/ui-portlet","mvc/ui/ui-misc","mvc/citation/citation-model","mvc/citation/citation-view","mvc/tools","mvc/tools/tools-template","mvc/tools/tools-datasets","mvc/tools/tools-section","mvc/tools/tools-tree","mvc/tools/tools-jobs"],function(h,l,j,a,f,d,i,k,c,g){var e=Backbone.Model.extend({initialize:function(m){this.url=galaxy_config.root+"api/tools/"+m.id+"?io_details=true"}});var b=Backbone.View.extend({main_el:"body",initialize:function(n){var m=this;this.options=n;this.model=new e({id:n.id});this.tree=new c(this);this.job_handler=new g(this);this.field_list={};this.input_list={};this.element_list={};this.datasets=new i({history_id:this.options.history_id,success:function(){m._initializeToolForm()}})},reset:function(){for(var m in this.element_list){this.element_list[m].reset()}},_initializeToolForm:function(){var n=this;var o=new l.ButtonIcon({icon:"fa-question-circle",title:"Question?",tooltip:"Ask a question about this tool (Biostar)",onclick:function(){window.open(n.options.biostar_url+"/p/new/post/")}});var p=new l.ButtonIcon({icon:"fa-search",title:"Search",tooltip:"Search help for this tool (Biostar)",onclick:function(){window.open(n.options.biostar_url+"/t/"+n.options.id+"/")}});var m=new l.ButtonIcon({icon:"fa-share",title:"Share",tooltip:"Share this tool",onclick:function(){prompt("Copy to clipboard: Ctrl+C, Enter",galaxy_config.root+"root?tool_id="+n.options.id)}});this.model.fetch({error:function(q){console.debug("tools-form::_initializeToolForm() : Attempt to fetch tool model failed.")},success:function(){n.inputs=n.model.get("inputs");n.portlet=new h.View({icon:"fa-wrench",title:"<b>"+n.model.get("name")+"</b> "+n.model.get("description"),buttons:{execute:new l.ButtonIcon({icon:"fa-check",tooltip:"Execute the tool",title:"Execute",floating:"clear",onclick:function(){n.job_handler.submit()}})},operations:{button_question:o,button_search:p,button_share:m}});if(!n.options.biostar_url){o.$el.hide();p.$el.hide()}n.message=new l.Message();n.portlet.append(n.message.$el);$(n.main_el).append(n.portlet.$el);if(n.options.help!=""){$(n.main_el).append(d.help(n.options.help))}if(n.options.citations){$(n.main_el).append(d.citations());var q=new j.ToolCitationCollection();q.tool_id=n.options.id;var r=new a.CitationListView({collection:q});r.render();q.fetch()}n.setElement(n.portlet.content());n.section=new k.View(n,{inputs:n.model.get("inputs")});n.portlet.append(n.section.$el);n.refresh()}})},refresh:function(){this.tree.refresh();for(var m in this.field_list){this.field_list[m].trigger("change")}console.debug("tools-form::refresh() - Recreated tree structure. Refresh.")}});return{View:b}});
\ No newline at end of file
diff -r deb003947e0e02de4613912b14832944954576a5 -r 618b02d13329adf2d01b72e9743a8fa00192c6fd static/scripts/packed/mvc/tools/tools-jobs.js
--- a/static/scripts/packed/mvc/tools/tools-jobs.js
+++ b/static/scripts/packed/mvc/tools/tools-jobs.js
@@ -1,1 +1,1 @@
-define(["utils/utils"],function(a){return Backbone.Model.extend({initialize:function(c,b){this.app=c;this.options=a.merge(b,this.optionsDefault)},submit:function(d,e,c){var b=this;a.request("POST",config.root+"api/tools",d,function(f){if(!f.outputs||f.outputs.length==0){c&&c()}else{console.log(f)}},function(f){var g="";if(f&&f.message&&f.message.data&&f.message.data.input){g=f.message.data.input+"."}c&&c()})}})});
\ No newline at end of file
+define(["utils/utils"],function(a){return Backbone.Model.extend({initialize:function(c,b){this.app=c;this.options=a.merge(b,this.optionsDefault)},submit:function(){var b=this;var c={tool_id:this.app.options.id,inputs:this.app.tree.finalize()};this.app.reset();a.request("POST",galaxy_config.root+"api/tools",c,function(d){if(!d.outputs||d.outputs.length==0){console.log(d)}b._refreshHdas()},function(d){if(d&&d.message&&d.message.data){var g=b.app.tree.match(d.message.data);for(var f in g){var e=g[f];if(!e){e="Please verify this parameter."}b.app.element_list[f].error(e)}}})},_refreshHdas:function(){if(parent.Galaxy&&parent.Galaxy.currHistoryPanel){parent.Galaxy.currHistoryPanel.refreshContents()}}})});
\ No newline at end of file
diff -r deb003947e0e02de4613912b14832944954576a5 -r 618b02d13329adf2d01b72e9743a8fa00192c6fd static/scripts/packed/mvc/tools/tools-tree.js
--- a/static/scripts/packed/mvc/tools/tools-tree.js
+++ b/static/scripts/packed/mvc/tools/tools-tree.js
@@ -1,1 +1,1 @@
-define([],function(){return Backbone.Model.extend({initialize:function(a){this.app=a},refresh:function(){this.dict={};this.xml=$("<div/>");if(!this.app.section){return{}}this._iterate(this.app.section.$el,this.dict,this.xml)},finalize:function(){var a=this;var b={};function c(k,l){for(var f in l){var d=l[f];if(d.input){var m=d.input;var h=k;if(k!=""){h+="|"}h+=m.name;switch(m.type){case"repeat":var g=0;for(var e in d){if(e.indexOf("section")!=-1){c(h+"_"+g++,d[e])}}break;case"conditional":var n=a.app.field_list[m.id].value();for(var e in m.cases){if(m.cases[e].value==n){c(h,l[m.id+"-section-"+e]);break}}break;default:var n=a.app.field_list[m.id].value();b[h]=n}}}}c("",this.dict);return b},findReferences:function(c,e){var g=[];var b=this;function d(h,j){var i=$(j).children();var l=[];var k=false;i.each(function(){var o=this;var n=$(o).attr("id");if(n!==c){var m=b.app.input_list[n];if(m){if(m.name==h){k=true;return false}if(m.data_ref==h&&m.type==e){l.push(n)}}}});if(!k){g=g.concat(l);i.each(function(){d(h,this)})}}var f=this.xml.find("#"+c);if(f.length>0){var a=this.app.input_list[c];if(a){d(a.name,f.parent())}}return g},_iterate:function(d,e,b){var a=this;var c=$(d).children();c.each(function(){var i=this;var h=$(i).attr("id");if($(i).hasClass("section-row")||$(i).hasClass("tab-pane")){e[h]={};var f=a.app.input_list[h];if(f){e[h]={input:f}}var g=$('<div id="'+h+'"/>');b.append(g);a._iterate(i,e[h],g)}else{a._iterate(i,e,b)}})}})});
\ No newline at end of file
+define([],function(){return Backbone.Model.extend({initialize:function(a){this.app=a},refresh:function(){this.dict={};this.xml=$("<div/>");if(!this.app.section){return{}}this._iterate(this.app.section.$el,this.dict,this.xml)},finalize:function(){var a=this;this.job_def={};this.job_ids={};function c(f,e,d){a.job_def[f]=d;a.job_ids[f]=e}function b(k,l){for(var f in l){var d=l[f];if(d.input){var m=d.input;var h=k;if(k!=""){h+="|"}h+=m.name;switch(m.type){case"repeat":var g=0;for(var e in d){if(e.indexOf("section")!=-1){b(h+"_"+g++,d[e])}}break;case"conditional":var n=a.app.field_list[m.id].value();c(h+"|"+m.test_param.name,m.id,n);for(var e in m.cases){if(m.cases[e].value==n){b(h,l[m.id+"-section-"+e]);break}}break;case"data":var n={id:a.app.field_list[m.id].value(),src:"hda"};c(h,m.id,n);break;case"boolean":var n=a.app.field_list[m.id].value();if(n==="true"){n=m.truevalue}else{n=m.falsevalue}c(h,m.id,n);break;default:c(h,m.id,a.app.field_list[m.id].value())}}}}b("",this.dict);return this.job_def},match:function(c){var a={};var b=this;function d(j,h){if(typeof h==="string"){var f=b.app.tree.job_ids[j];if(f){a[f]=h}}else{for(var g in h){var e=g;if(j!==""){e=j+"|"+e}d(e,h[g])}}}d("",c);return a},references:function(c,e){var g=[];var b=this;function d(h,j){var i=$(j).children();var l=[];var k=false;i.each(function(){var o=this;var n=$(o).attr("id");if(n!==c){var m=b.app.input_list[n];if(m){if(m.name==h){k=true;return false}if(m.data_ref==h&&m.type==e){l.push(n)}}}});if(!k){g=g.concat(l);i.each(function(){d(h,this)})}}var f=this.xml.find("#"+c);if(f.length>0){var a=this.app.input_list[c];if(a){d(a.name,f.parent())}}return g},_iterate:function(d,e,b){var a=this;var c=$(d).children();c.each(function(){var i=this;var h=$(i).attr("id");if($(i).hasClass("section-row")||$(i).hasClass("tab-pane")){e[h]={};var f=a.app.input_list[h];if(f){e[h]={input:f}}var g=$('<div id="'+h+'"/>');b.append(g);a._iterate(i,e[h],g)}else{a._iterate(i,e,b)}})}})});
\ No newline at end of file
diff -r deb003947e0e02de4613912b14832944954576a5 -r 618b02d13329adf2d01b72e9743a8fa00192c6fd static/style/blue/base.css
--- a/static/style/blue/base.css
+++ b/static/style/blue/base.css
@@ -1644,7 +1644,9 @@
.list-item{border:1px solid #bfbfbf}.list-item .vertical-spacing{margin-bottom:8px}
.list-item .info-section{border-radius:3px;border:1px solid rgba(153,153,153,0.30000000000000004);padding:4px}
.list-item .padded{padding:6px 10px 6px 8px}
-.list-item .warnings [class$=messagesmall]{margin:6px 10px 2px 8px;font-size:90%}
+.list-item .warnings:not(:empty){padding-top:4px}
+.list-item .warnings [class$=messagesmall]{margin:6px 10px 2px 8px;font-size:90%}.list-item .warnings [class$=messagesmall]:first-child{margin-top:0px}
+.list-item .warnings [class$=messagesmall]:last-child{margin-bottom:0px}
.list-item .help-text{font-weight:normal;color:#555}
.list-item .selector{float:left;display:none;width:32px;height:32px;margin:0 0 -6px 0;padding:8px 0 2px 7px;font-size:80%;color:#333;cursor:pointer;vertical-align:middle}
.list-item .selector:hover{color:maroon}
@@ -1654,7 +1656,7 @@
.list-item .primary-actions .icon-btn:last-child{margin-left:0px;border-radius:0px 3px 3px 0px}
.list-item .primary-actions .icon-btn:only-child{margin:0px;border-radius:3px}
.list-item .primary-actions .icon-btn{margin-left:2px}
-.list-item .details{display:none;padding:0 10px 6px 8px}.list-item .details [class$=messagesmall]{margin:0px 0px 8px 0px}
+.list-item .details{display:none;padding:0 10px 6px 8px}.list-item .details>[class$=messagesmall]{margin:0px 0px 8px 0px}
.list-item .details label{margin:0px;padding:0px;font-weight:normal}
.list-item .details .prompt{font-weight:normal;color:#555}
.list-item .details .prompt:after{content:':';margin-right:4px}
@@ -1679,6 +1681,8 @@
.list-panel .controls .list-actions .btn{padding-top:2px;padding-bottom:2px;font-size:90%}
.list-panel .list-items .list-item:not(:last-child){border-bottom-width:0px}
.list-panel .empty-message{display:none;margin:0px}
+.list-item .details .list-panel{margin-top:8px;border-radius:3px;background:white;padding:4px}.list-item .details .list-panel .list-items{border:1px solid #bfbfbf;border-radius:3px}.list-item .details .list-panel .list-items .list-item:first-child{border-top-width:0px;border-radius:3px 3px 0px 0px}
+.list-item .details .list-panel .list-items .list-item:last-child{border-bottom-width:0px;border-radius:0px 0px 3px 3px}
.search-input .search-query{width:100%;padding-right:24px}
.search-input .search-clear,.search-input .search-loading{position:relative;display:inline-block;float:right;margin-top:-24px;margin-right:4px;font-size:1.4em;line-height:23px;color:grey}
.search-input .search-clear:hover{color:#303030}
@@ -1760,10 +1764,11 @@
.annotated-history-panel table.list-items .headers th{padding:8px}
.annotated-history-panel table.list-items>tbody>tr{cursor:pointer;border-bottom:1px solid grey}.annotated-history-panel table.list-items>tbody>tr>td{margin:0px;padding:0px;vertical-align:top}.annotated-history-panel table.list-items>tbody>tr>td:nth-child(1){width:50%}
.annotated-history-panel table.list-items>tbody>tr>td:nth-child(2){padding:8px 16px 8px 16px;white-space:pre-wrap}
-.annotated-history-panel table.list-items>tbody>tr .list-item{border:0px}
+.annotated-history-panel table.list-items>tbody>tr>td>.list-item{border:0px}
.annotated-history-panel .empty-message{margin-top:8px}
.history-panel .dataset-collection .subtitle{margin-top:2px;font-size:90%;color:#777}
.history-panel .dataset-collection-panel .controls{padding:0px}
+.history-panel .dataset-collection-panel .list-items{margin-top:0px}
body.historyPage{background:#dfe5f9;color:#000;margin:5px;border:0;padding:0}
div.historyLinks{margin:5px 5px}
div.historyItem{margin:0 -5px;padding:8px 10px;border-top:solid #bfbfbf 1px;border-right:none;word-wrap:break-word;background:#eee}div.historyItem .state-icon{display:inline-block;vertical-align:middle;width:16px;height:16px;background-position:0 1px;background-repeat:no-repeat}
diff -r deb003947e0e02de4613912b14832944954576a5 -r 618b02d13329adf2d01b72e9743a8fa00192c6fd static/style/src/less/history.less
--- a/static/style/src/less/history.less
+++ b/static/style/src/less/history.less
@@ -553,10 +553,10 @@
// do not html format
white-space: pre-wrap;
}
- }
- // tr has border - remove from items
- .list-item {
- border: 0px;
+ // tr has border - remove from items
+ & > .list-item {
+ border: 0px;
+ }
}
}
}
@@ -579,6 +579,9 @@
.controls {
padding: 0px;
}
+ .list-items {
+ margin-top: 0px;
+ }
}
}
diff -r deb003947e0e02de4613912b14832944954576a5 -r 618b02d13329adf2d01b72e9743a8fa00192c6fd static/style/src/less/list-item.less
--- a/static/style/src/less/list-item.less
+++ b/static/style/src/less/list-item.less
@@ -22,9 +22,18 @@
}
.warnings {
+ &:not(:empty) {
+ padding-top: 4px;
+ }
[class$=messagesmall] {
margin: @spacing-top @spacing-right ( @spacing-bottom - 4 ) @spacing-left;
font-size: 90%;
+ &:first-child {
+ margin-top: 0px;
+ }
+ &:last-child {
+ margin-bottom: 0px;
+ }
}
}
@@ -79,7 +88,7 @@
display: none;
padding: 0px @spacing-right @spacing-bottom @spacing-left;
- [class$=messagesmall] {
+ & > [class$=messagesmall] {
margin: 0px 0px 8px 0px;
}
@@ -160,3 +169,25 @@
margin: 0px;
}
}
+
+// ---------------------------------------------------------------------------- a list panel nested inside a list-item
+.list-item .details .list-panel {
+ margin-top: 8px;
+ border-radius: 3px;
+ background: white;
+ padding: 4px;
+ .list-items {
+ border: 1px solid @border-default-color;
+ border-radius: 3px;
+ .list-item {
+ &:first-child {
+ border-top-width: 0px;
+ border-radius: 3px 3px 0px 0px;
+ }
+ &:last-child {
+ border-bottom-width: 0px;
+ border-radius: 0px 0px 3px 3px;
+ }
+ }
+ }
+}
diff -r deb003947e0e02de4613912b14832944954576a5 -r 618b02d13329adf2d01b72e9743a8fa00192c6fd templates/webapps/galaxy/history/display.mako
--- a/templates/webapps/galaxy/history/display.mako
+++ b/templates/webapps/galaxy/history/display.mako
@@ -45,7 +45,7 @@
<div id="history-${ history_dict[ 'id' ] }" class="history-panel"></div><script type="text/javascript">
- var historyJSON = ${h.to_json_string( history_dict )},
+ var historyJSON = ${h.dumps( history_dict )},
hdaJSON = ${h.dumps( hda_dicts )};
require.config({
@@ -62,6 +62,7 @@
el : $( "#history-" + historyJSON.id ),
model : history
}).render();
+ console.debug( historyPanel.$el )
});
</script></%def>
diff -r deb003947e0e02de4613912b14832944954576a5 -r 618b02d13329adf2d01b72e9743a8fa00192c6fd templates/webapps/galaxy/root/history.mako
--- a/templates/webapps/galaxy/root/history.mako
+++ b/templates/webapps/galaxy/root/history.mako
@@ -22,23 +22,23 @@
require([
//'mvc/history/history-panel'
//'mvc/history/history-panel-annotated'
- //'mvc/history/history-panel-edit'
- 'mvc/history/history-panel-edit-current'
+ 'mvc/history/history-panel-edit'
+ //'mvc/history/history-panel-edit-current'
], function( historyPanel ){
$(function(){
// history module is already in the dpn chain from the panel. We can re-scope it here.
var historyModel = require( 'mvc/history/history-model' );
//window.panel = new historyPanel.HistoryPanel({
//window.panel = new historyPanel.AnnotatedHistoryPanel({
- //window.panel = new historyPanel.HistoryPanelEdit({
- window.panel = new historyPanel.CurrentHistoryPanel({
+ window.panel = new historyPanel.HistoryPanelEdit({
+ //window.panel = new historyPanel.CurrentHistoryPanel({
show_deleted : bootstrapped.show_deleted,
show_hidden : bootstrapped.show_hidden,
purgeAllowed : Galaxy.config.allow_user_dataset_purge,
model : new historyModel.History( bootstrapped.history, bootstrapped.hdas )
});
panel.render().$el.appendTo( 'body' );
- $( 'body' ).css( 'padding', '10px' );
+ //$( 'body' ).css( 'padding', '10px' );
});
});
});
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: guerler: ToolForm: Implements error handling, applies fixes to styles and structure, UI: Fixes code style for frames
by commits-noreply@bitbucket.org 11 Sep '14
by commits-noreply@bitbucket.org 11 Sep '14
11 Sep '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/deb003947e0e/
Changeset: deb003947e0e
User: guerler
Date: 2014-09-11 18:02:21
Summary: ToolForm: Implements error handling, applies fixes to styles and structure, UI: Fixes code style for frames
Affected #: 11 files
diff -r d1f6d05706d0f03c7a31cd5f8b3890c55e565af0 -r deb003947e0e02de4613912b14832944954576a5 static/scripts/mvc/tools/tools-form.js
--- a/static/scripts/mvc/tools/tools-form.js
+++ b/static/scripts/mvc/tools/tools-form.js
@@ -1,8 +1,11 @@
+/*
+ This is the main class of the tool form plugin. It is referenced as 'app' in all lower level modules.
+*/
define(['mvc/ui/ui-portlet', 'mvc/ui/ui-misc',
'mvc/citation/citation-model', 'mvc/citation/citation-view',
- 'mvc/tools', 'mvc/tools/tools-template', 'mvc/tools/tools-datasets', 'mvc/tools/tools-section', 'mvc/tools/tools-tree'],
+ 'mvc/tools', 'mvc/tools/tools-template', 'mvc/tools/tools-datasets', 'mvc/tools/tools-section', 'mvc/tools/tools-tree', 'mvc/tools/tools-jobs'],
function(Portlet, Ui, CitationModel, CitationView,
- Tools, ToolTemplate, ToolDatasets, ToolSection, ToolTree) {
+ Tools, ToolTemplate, ToolDatasets, ToolSection, ToolTree, ToolJobs) {
// create tool model
var Model = Backbone.Model.extend({
@@ -32,12 +35,18 @@
// creates a tree/json structure from the input form
this.tree = new ToolTree(this);
+ // creates the job handler
+ this.job_handler = new ToolJobs(this);
+
// reset field list
this.field_list = {};
// reset sequential input definition list
this.input_list = {};
+ // reset input element definition list
+ this.element_list = {};
+
// initialize datasets
this.datasets = new ToolDatasets({
history_id : this.options.history_id,
@@ -47,6 +56,13 @@
});
},
+ // reset form
+ reset: function() {
+ for (var i in this.element_list) {
+ this.element_list[i].reset();
+ }
+ },
+
// initialize tool form
_initializeToolForm: function() {
// link this
@@ -102,7 +118,7 @@
title : 'Execute',
floating : 'clear',
onclick : function() {
- self._submit();
+ self.job_handler.submit();
}
})
},
@@ -157,7 +173,7 @@
// trigger refresh
self.refresh();
- self._submit();
+ //self.job_handler.submit();
}
});
},
@@ -174,11 +190,6 @@
// log
console.debug('tools-form::refresh() - Recreated tree structure. Refresh.');
- },
-
- // submit
- _submit: function() {
- console.log(this.tree.finalize());
}
});
diff -r d1f6d05706d0f03c7a31cd5f8b3890c55e565af0 -r deb003947e0e02de4613912b14832944954576a5 static/scripts/mvc/tools/tools-jobs.js
--- a/static/scripts/mvc/tools/tools-jobs.js
+++ b/static/scripts/mvc/tools/tools-jobs.js
@@ -1,9 +1,7 @@
-// dependencies
+/*
+ This class handles job submissions and the error handling.
+*/
define(['utils/utils'], function(Utils) {
-
-/**
- * This class handles job submissions.
- */
return Backbone.Model.extend({
// initialize
initialize: function(app, options) {
@@ -15,34 +13,49 @@
},
// create job
- submit: function(data, success, error) {
+ submit: function() {
// link this
var self = this;
+ // create job definition for submission to tools api
+ var job_def = {
+ tool_id : this.app.options.id,
+ inputs : this.app.tree.finalize()
+ }
+
+ // reset
+ this.app.reset();
+
// post job
- Utils.request('POST', config.root + 'api/tools', data,
+ Utils.request('POST', galaxy_config.root + 'api/tools', job_def,
// success handler
function(response) {
if (!response.outputs || response.outputs.length == 0) {
- // call error
- error && error();
- } else {
- // update galaxy history
console.log(response);
}
+ self._refreshHdas();
},
// error handler
function(response) {
- var message = '';
- if (response && response.message && response.message.data && response.message.data.input) {
- message = response.message.data.input + '.';
+ if (response && response.message && response.message.data) {
+ var error_messages = self.app.tree.match(response.message.data);
+ for (var id in error_messages) {
+ var error_text = error_messages[id];
+ if (!error_text) {
+ error_text = 'Please verify this parameter.';
+ }
+ self.app.element_list[id].error(error_text);
+ }
}
-
- // call error
- error && error();
-
}
);
+ },
+
+ // refresh history panel
+ _refreshHdas: function() {
+ if (parent.Galaxy && parent.Galaxy.currHistoryPanel) {
+ parent.Galaxy.currHistoryPanel.refreshContents();
+ }
}
});
diff -r d1f6d05706d0f03c7a31cd5f8b3890c55e565af0 -r deb003947e0e02de4613912b14832944954576a5 static/scripts/mvc/tools/tools-section.js
--- a/static/scripts/mvc/tools/tools-section.js
+++ b/static/scripts/mvc/tools/tools-section.js
@@ -1,6 +1,60 @@
+/*
+ This class creates a tool form section and populates it with input elements. It also handles repeat blocks and conditionals by recursively creating new sub sections. New input elements can be plugged in by adding cases to the switch block defined in the _addRow() function.
+*/
define(['utils/utils', 'mvc/ui/ui-table', 'mvc/ui/ui-misc', 'mvc/ui/ui-tabs', 'mvc/tools/tools-select-dataset'],
function(Utils, Table, Ui, Tabs, SelectDataset) {
+ // input field element wrapper
+ var InputElement = Backbone.View.extend({
+ // initialize input wrapper
+ initialize: function(options) {
+ this.setElement(this._template(options));
+ },
+
+ // set error text
+ error: function(text) {
+ // set text
+ this.$el.find('.ui-table-form-error-text').html(text);
+ this.$el.find('.ui-table-form-error').fadeIn();
+ this.$el.addClass('ui-table-row-error');
+ },
+
+ // reset
+ reset: function() {
+ this.$el.find('.ui-table-form-error').hide();
+ this.$el.removeClass('ui-table-form-error');
+ },
+
+ // template
+ _template: function(options) {
+ var $input;
+ if (options.highlight) {
+ $input = $('<div class="ui-table-element ui-table-form-section"/>');
+ } else {
+ $input = $('<div class="ui-table-element"/>');
+ }
+
+ // add error
+ $input.append('<div class="ui-table-form-error"><span class="fa fa-arrow-down"/><span class="ui-table-form-error-text"></div>');
+
+ // add label
+ if (options.label) {
+ $input.append('<div class="ui-table-form-title-strong">' + options.label + '</div>');
+ }
+
+ // add input element
+ $input.append(options.$el);
+
+ // add help
+ if (options.help) {
+ $input.append('<div class="ui-table-form-info">' + options.help + '</div>');
+ }
+
+ // return input element
+ return $input;
+ }
+ });
+
// create form view
var View = Backbone.View.extend({
// initialize
@@ -76,7 +130,7 @@
input_def.value = input_def.test_param.value;
// build options field
- this._addRow('conditional', input_def);
+ var table_row = this._addRow('conditional', input_def);
// add fields
for (var i in input_def.cases) {
@@ -89,13 +143,16 @@
cls : 'ui-table-plain'
});
+ // create input field wrapper
+ var input_element = new InputElement({
+ label : '',
+ help : input_def.help,
+ $el : sub_section.$el,
+ highlight : true
+ });
+
// create table row
- this.table.add(this._create_field({
- label : '',
- help : input_def.help,
- $el : sub_section.$el,
- color : true
- }));
+ this.table.add(input_element.$el);
// append to table
this.table.append(sub_section_id);
@@ -175,13 +232,16 @@
// retitle tabs
tabs.retitle(input_def.title);
+ // create input field wrapper
+ var input_element = new InputElement({
+ label : input_def.title,
+ help : input_def.help,
+ $el : tabs.$el,
+ highlight : true
+ });
+
// create table row
- this.table.add(this._create_field({
- label : input_def.title,
- help : input_def.help,
- $el : tabs.$el,
- color : true
- }));
+ this.table.add(input_element.$el);
// append row to table
this.table.append(input_def.id);
@@ -265,15 +325,24 @@
// add to field list
this.app.field_list[id] = field;
- // create table row
- this.table.add(this._create_field({
+ // create input field wrapper
+ var input_element = new InputElement({
label : input_def.label,
help : input_def.help,
$el : field.$el
- }));
+ });
+
+ // add to element list
+ this.app.element_list[id] = input_element;
+
+ // create table row
+ this.table.add(input_element.$el);
// append to table
this.table.append(id);
+
+ // return table row
+ return this.table.get(id)
},
// conditional input field
@@ -349,7 +418,7 @@
}
// get referenced columns
- var column_list = self.app.tree.findReferences(id, 'data_column');
+ var column_list = self.app.tree.references(id, 'data_column');
// find selected dataset
var dataset = self.app.datasets.filter(value);
@@ -385,11 +454,20 @@
// get column type
var column_type = meta[key];
+ // column index
+ var column_index = (parseInt(key) + 1);
+
+ // column type label
+ var column_label = 'Text';
+ if (column_type == 'int' || column_type == 'float') {
+ column_label = 'Number';
+ }
+
// add to selection
if (column_type == 'int' || column_type == 'float' || !numerical) {
columns.push({
- 'label' : 'Column: ' + (parseInt(key) + 1) + ' [' + meta[key] + ']',
- 'value' : key
+ 'label' : 'Column: ' + column_index + ' [' + column_label + ']',
+ 'value' : column_index
});
}
}
@@ -485,27 +563,9 @@
_field_boolean : function(input_def) {
return new Ui.RadioButton.View({
id : 'field-' + input_def.id,
- data : [ { label : 'Yes', value : true },
- { label : 'No', value : false }]
+ data : [ { label : 'Yes', value : 'true' },
+ { label : 'No', value : 'false' }]
});
- },
-
- // create a field element with title and help information
- _create_field: function(options) {
- var $input;
- if (options.color) {
- $input = $('<div class="ui-table-form-section"/>');
- } else {
- $input = $('<div/>');
- }
- if (options.label) {
- $input.append('<div class="ui-table-form-title-strong">' + options.label + '</div>');
- }
- $input.append(options.$el);
- if (options.help) {
- $input.append('<div class="ui-table-form-info">' + options.help + '</div>');
- }
- return $input;
}
});
diff -r d1f6d05706d0f03c7a31cd5f8b3890c55e565af0 -r deb003947e0e02de4613912b14832944954576a5 static/scripts/mvc/tools/tools-tree.js
--- a/static/scripts/mvc/tools/tools-tree.js
+++ b/static/scripts/mvc/tools/tools-tree.js
@@ -1,3 +1,6 @@
+/*
+ This class maps the tool form to javascript datastructures. Once refreshed it converts the tool form (including sub sections) into a xml (containing only ids) and a detailed dictionary representation. The xml object is a jquery element and can be searched/filtered e.g. in order to hierarchically identify referenced fields. Once the job is ready for submission, the finalize function will transform the generic dictionary representation into the specific flat dictionary format required by the tools api.
+*/
// dependencies
define([], function() {
@@ -9,7 +12,8 @@
this.app = app;
},
- // creates tree structure
+ /** Refresh the datastructures representing the ToolForm.
+ */
refresh: function() {
// create dictionary
this.dict = {};
@@ -26,13 +30,23 @@
this._iterate(this.app.section.$el, this.dict, this.xml);
},
- // convert to job dictionary
+ /** Convert dictionary representation into tool api specific flat dictionary format.
+ */
finalize: function() {
// link this
var self = this;
// dictionary formatted for job submission
- var job_def = {};
+ this.job_def = {};
+
+ // dictionary with api specific identifiers
+ this.job_ids = {};
+
+ // add identifier and value to job definition
+ function add(job_input_id, input_id, input_value) {
+ self.job_def[job_input_id] = input_value;
+ self.job_ids[job_input_id] = input_id;
+ };
// converter between raw dictionary and job dictionary
function convert(identifier, head) {
@@ -65,6 +79,9 @@
// get conditional value
var value = self.app.field_list[input.id].value();
+ // add conditional value
+ add (job_input_id + '|' + input.test_param.name, input.id, value);
+
// find selected case
for (var j in input.cases) {
if (input.cases[j].value == value) {
@@ -72,13 +89,28 @@
break;
}
}
-
- // break
+ break;
+ // handle data inputs
+ case 'data':
+ var value = {
+ id : self.app.field_list[input.id].value(),
+ src : 'hda'
+ }
+ add(job_input_id, input.id, value);
+ break;
+ // handle boolean input
+ case 'boolean':
+ var value = self.app.field_list[input.id].value();
+ if (value === 'true') {
+ value = input.truevalue;
+ } else {
+ value = input.falsevalue;
+ }
+ add (job_input_id, input.id, value);
break;
default:
// handle default value
- var value = self.app.field_list[input.id].value();
- job_def[job_input_id] = value;
+ add (job_input_id, input.id, self.app.field_list[input.id].value());
}
}
}
@@ -88,11 +120,46 @@
convert('', this.dict);
// return result
- return job_def;
+ return this.job_def;
},
- // find referenced elements
- findReferences: function(identifier, type) {
+ /** Matches identifier from api response to input element
+ */
+ match: function(response) {
+ // final result dictionary
+ var result = {};
+
+ // link this
+ var self = this;
+
+ // search throughout response
+ function search (id, head) {
+ if (typeof head === 'string') {
+ var input_id = self.app.tree.job_ids[id];
+ if (input_id) {
+ result[input_id] = head;
+ }
+ } else {
+ for (var i in head) {
+ var new_id = i;
+ if (id !== '') {
+ new_id = id + '|' + new_id;
+ }
+ search (new_id, head[i]);
+ }
+ }
+ }
+
+ // match all ids and return messages
+ search('', response);
+
+ // return matched results
+ return result;
+ },
+
+ /** Find referenced elements.
+ */
+ references: function(identifier, type) {
// referenced elements
var referenced = [];
@@ -164,7 +231,8 @@
return referenced;
},
- // iterate
+ /** Iterate through the tool form dom and map it to the dictionary and xml representation.
+ */
_iterate: function(parent, dict, xml) {
// get child nodes
var self = this;
diff -r d1f6d05706d0f03c7a31cd5f8b3890c55e565af0 -r deb003947e0e02de4613912b14832944954576a5 static/scripts/mvc/ui/ui-frames.js
--- a/static/scripts/mvc/ui/ui-frames.js
+++ b/static/scripts/mvc/ui/ui-frames.js
@@ -83,10 +83,10 @@
this.setElement(this._template());
// load background
- $(this.el).append(this._template_background());
+ $(this.el).append(this._templateBackground());
// load menu buttons
- $(this.el).append(this._template_menu());
+ $(this.el).append(this._templateMenu());
// load to main frame
$(this.el_main).append($(this.el));
@@ -97,7 +97,7 @@
var id_shadow = '#frame-shadow';
// add shadow template
- $(this.el).append(this._template_shadow(id_shadow.substring(1)));
+ $(this.el).append(this._templateShadow(id_shadow.substring(1)));
// initialize frame
this.frame_shadow = {
@@ -109,13 +109,13 @@
};
// initialize size
- this._frame_resize(this.frame_shadow, {width: 0, height: 0});
+ this._frameResize(this.frame_shadow, {width: 0, height: 0});
// add shadow to frame list
this.frame_list[id_shadow] = this.frame_shadow;
// initialize panel
- this._panel_refresh();
+ this._panelRefresh();
// apply visibility
if (!this.visible) {
@@ -128,7 +128,7 @@
var self = this;
$(window).resize(function () {
if (self.visible)
- self._panel_refresh();
+ self._panelRefresh();
});
},
@@ -183,9 +183,9 @@
// append
var $frame_el = null;
if (options.type === 'url') {
- $frame_el = $(this._template_frame_url(frame_id.substring(1), options.title, options.content));
+ $frame_el = $(this._templateFrameUrl(frame_id.substring(1), options.title, options.content));
} else if (options.type === 'other') {
- $frame_el = $(this._template_frame(frame_id.substring(1), options.title));
+ $frame_el = $(this._templateFrame(frame_id.substring(1), options.title));
// Load content into frame.
var content_elt = $frame_el.find('.f-content');
@@ -208,8 +208,8 @@
};
// set dimensions
- options.width = this._to_pixel_coord('width', this.options.frame.cols);
- options.height = this._to_pixel_coord('height', this.options.frame.rows);
+ options.width = this._toPixelCoord('width', this.options.frame.cols);
+ options.height = this._toPixelCoord('height', this.options.frame.rows);
// default z-index
this.frame_z = parseInt($(frame.id).css('z-index'));
@@ -221,10 +221,10 @@
this.frame_counter++;
// resize
- this._frame_resize(frame, {width: options.width, height: options.height});
+ this._frameResize(frame, {width: options.width, height: options.height});
// place frame
- this._frame_insert(frame, {top: 0, left: 0}, true);
+ this._frameInsert(frame, {top: 0, left: 0}, true);
// show frames if hidden
if (!this.visible) {
@@ -247,10 +247,10 @@
this.$el.find(".frame-background").show();
// show panel
- this._panel_refresh();
+ this._panelRefresh();
// refresh
- this._menu_refresh();
+ this._menuRefresh();
},
// hide panel
@@ -272,7 +272,7 @@
this.$el.find(".frame-menu").hide();
// refresh
- this._menu_refresh();
+ this._menuRefresh();
},
// length
@@ -299,23 +299,23 @@
// events
events: {
// global frame events
- 'mousemove' : '_event_frame_mouse_move',
- 'mouseup' : '_event_frame_mouse_up',
- 'mouseleave' : '_event_frame_mouse_up',
- 'mousewheel' : '_event_panel_scroll',
- 'DOMMouseScroll' : '_event_panel_scroll',
+ 'mousemove' : '_eventFrameMouseMove',
+ 'mouseup' : '_eventFrameMouseUp',
+ 'mouseleave' : '_eventFrameMouseUp',
+ 'mousewheel' : '_eventPanelScroll',
+ 'DOMMouseScroll' : '_eventPanelScroll',
// events fixed to elements
- 'mousedown .frame' : '_event_frame_mouse_down',
- 'mousedown .frame-background' : '_event_hide',
- 'mousedown .frame-scroll-up' : '_event_panel_scroll_up',
- 'mousedown .frame-scroll-down' : '_event_panel_scroll_down',
- 'mousedown .f-close' : '_event_frame_close',
- 'mousedown .f-pin' : '_event_frame_lock'
+ 'mousedown .frame' : '_eventFrameMouseDown',
+ 'mousedown .frame-background' : '_eventHide',
+ 'mousedown .frame-scroll-up' : '_eventPanelScroll_up',
+ 'mousedown .frame-scroll-down' : '_eventPanelScroll_down',
+ 'mousedown .f-close' : '_eventFrameClose',
+ 'mousedown .f-pin' : '_eventFrameLock'
},
// drag start
- _event_frame_mouse_down: function (e) {
+ _eventFrameMouseDown: function (e) {
// skip if event is already active
if (this.event.type !== null) {
return;
@@ -340,7 +340,7 @@
e.preventDefault();
// identify frame
- this.event.target = this._frame_identify(e.target);
+ this.event.target = this._frameIdentify(e.target);
// check if frame is locked
if (this.event.target.grid_lock) {
@@ -355,11 +355,11 @@
};
// prepare drag/resize
- this._frame_drag_start(this.event.target);
+ this._frameDragStart(this.event.target);
},
// mouse move event
- _event_frame_mouse_move: function (e) {
+ _eventFrameMouseMove: function (e) {
// check
if (this.event.type != 'drag' && this.event.type != 'resize') {
return;
@@ -381,7 +381,7 @@
this.event.xy = event_xy_new;
// object position / size
- var p = this._frame_screen (this.event.target);
+ var p = this._frameScreen (this.event.target);
// resize event
if (this.event.type == 'resize') {
@@ -395,23 +395,23 @@
p.height = Math.max(p.height, min_dim);
// apply resize to frame
- this._frame_resize(this.event.target, p);
+ this._frameResize(this.event.target, p);
// break down to grid coordinates
- p.width = this._to_grid_coord('width', p.width) + 1;
- p.height = this._to_grid_coord('height', p.height) + 1;
+ p.width = this._toGridCoord('width', p.width) + 1;
+ p.height = this._toGridCoord('height', p.height) + 1;
// transfer back to pixels
- p.width = this._to_pixel_coord('width', p.width);
- p.height = this._to_pixel_coord('height', p.height);
+ p.width = this._toPixelCoord('width', p.width);
+ p.height = this._toPixelCoord('height', p.height);
// apply
- this._frame_resize(this.frame_shadow, p);
+ this._frameResize(this.frame_shadow, p);
// fix position
- this._frame_insert(this.frame_shadow, {
- top : this._to_grid_coord('top', p.top),
- left : this._to_grid_coord('left', p.left)
+ this._frameInsert(this.frame_shadow, {
+ top : this._toGridCoord('top', p.top),
+ left : this._toGridCoord('left', p.left)
});
}
@@ -422,12 +422,12 @@
p.top += event_xy_delta.y;
// apply
- this._frame_offset(this.event.target, p);
+ this._frameOffset(this.event.target, p);
// get location of shadow
var l = {
- top : this._to_grid_coord('top', p.top),
- left : this._to_grid_coord('left', p.left)
+ top : this._toGridCoord('top', p.top),
+ left : this._toGridCoord('left', p.left)
};
// increase priority of current frame
@@ -436,26 +436,26 @@
}
// fix position
- this._frame_insert(this.frame_shadow, l);
+ this._frameInsert(this.frame_shadow, l);
}
},
// mouse up
- _event_frame_mouse_up: function (e) {
+ _eventFrameMouseUp: function (e) {
// check
if (this.event.type != 'drag' && this.event.type != 'resize') {
return;
}
// stop
- this._frame_drag_stop(this.event.target);
+ this._frameDragStop(this.event.target);
// reset event
this.event.type = null;
},
// drag start
- _event_frame_close: function (e) {
+ _eventFrameClose: function (e) {
// check
if (this.event.type !== null) {
return;
@@ -465,7 +465,7 @@
e.preventDefault();
// get frame
- var frame = this._frame_identify(e.target);
+ var frame = this._frameIdentify(e.target);
var self = this;
// fade out
@@ -480,10 +480,10 @@
self.frame_counter--;
// reload
- self._panel_refresh(true);
+ self._panelRefresh(true);
// refresh scroll state once all animations completed
- self._panel_animation_complete();
+ self._panelAnimationComplete();
// hide if no frames left
if (self.visible && self.frame_counter == 0)
@@ -492,7 +492,7 @@
},
// drag start
- _event_frame_lock: function (e) {
+ _eventFrameLock: function (e) {
// check
if (this.event.type !== null) {
return;
@@ -502,7 +502,7 @@
e.preventDefault();
// get frame
- var frame = this._frame_identify(e.target);
+ var frame = this._frameIdentify(e.target);
// check
if (frame.grid_lock) {
@@ -529,7 +529,7 @@
},
// show/hide panel
- _event_hide: function (e) {
+ _eventHide: function (e) {
// check
if (this.event.type !== null) {
return;
@@ -542,7 +542,7 @@
/**
* Fired when scrolling occurs on panel.
*/
- _event_panel_scroll: function(e) {
+ _eventPanelScroll: function(e) {
// check
if (this.event.type !== null || !this.visible) {
return;
@@ -563,11 +563,11 @@
var delta = e.originalEvent.detail ? e.originalEvent.detail : e.originalEvent.wheelDelta / -3;
// refresh panel
- this._panel_scroll(delta);
+ this._panelScroll(delta);
},
// scroll up
- _event_panel_scroll_up: function(e) {
+ _eventPanelScroll_up: function(e) {
// check
if (this.event.type !== null)
return;
@@ -576,11 +576,11 @@
e.preventDefault();
// scroll up
- this._panel_scroll(-this.options.scroll);
+ this._panelScroll(-this.options.scroll);
},
// scroll down
- _event_panel_scroll_down: function(e) {
+ _eventPanelScroll_down: function(e) {
// check
if (this.event.type !== null)
return;
@@ -589,7 +589,7 @@
e.preventDefault();
// scroll down
- this._panel_scroll(this.options.scroll);
+ this._panelScroll(this.options.scroll);
},
/*
@@ -597,21 +597,21 @@
*/
// identify
- _frame_identify: function(target) {
+ _frameIdentify: function(target) {
return this.frame_list['#' + $(target).closest('.frame').attr('id')];
},
// drag start
- _frame_drag_start : function (frame) {
+ _frameDragStart : function (frame) {
// set focus
- this._frame_focus(frame, true);
+ this._frameFocus(frame, true);
// get current dimensions
- var p = this._frame_screen (frame);
+ var p = this._frameScreen (frame);
// initialize shadow
- this._frame_resize(this.frame_shadow, p);
- this._frame_grid(this.frame_shadow, frame.grid_location);
+ this._frameResize(this.frame_shadow, p);
+ this._frameGrid(this.frame_shadow, frame.grid_location);
// reset location
frame.grid_location = null;
@@ -624,16 +624,16 @@
},
// drag stop
- _frame_drag_stop : function (frame) {
+ _frameDragStop : function (frame) {
// remove focus
- this._frame_focus(frame, false);
+ this._frameFocus(frame, false);
// get new dimensions
- var p = this._frame_screen(this.frame_shadow);
+ var p = this._frameScreen(this.frame_shadow);
// update frame
- this._frame_resize(frame, p);
- this._frame_grid(frame, this.frame_shadow.grid_location, true);
+ this._frameResize(frame, p);
+ this._frameGrid(frame, this.frame_shadow.grid_location, true);
// reset location of shadow
this.frame_shadow.grid_location = null;
@@ -645,7 +645,7 @@
$('.f-cover').hide();
// refresh scroll state once all animations completed
- this._panel_animation_complete();
+ this._panelAnimationComplete();
},
/*
@@ -653,7 +653,7 @@
*/
// converts a pixel coordinate to grids
- _to_grid_coord: function (type, px) {
+ _toGridCoord: function (type, px) {
// determine sign
var sign = (type == 'width' || type == 'height') ? 1 : -1;
@@ -664,7 +664,7 @@
},
// converts a grid coordinate to pixels
- _to_pixel_coord: function (type, g) {
+ _toPixelCoord: function (type, g) {
// determine sign
var sign = (type == 'width' || type == 'height') ? 1 : -1;
@@ -677,23 +677,23 @@
},
// get grid coordinates
- _to_grid: function (px) {
+ _toGrid: function (px) {
// full set
return {
- top : this._to_grid_coord('top', px.top),
- left : this._to_grid_coord('left', px.left),
- width : this._to_grid_coord('width', px.width),
- height : this._to_grid_coord('height', px.height)
+ top : this._toGridCoord('top', px.top),
+ left : this._toGridCoord('left', px.left),
+ width : this._toGridCoord('width', px.width),
+ height : this._toGridCoord('height', px.height)
};
},
// get pixel coordinates
- _to_pixel: function(g) {
+ _toPixel: function(g) {
return {
- top : this._to_pixel_coord('top', g.top),
- left : this._to_pixel_coord('left', g.left),
- width : this._to_pixel_coord('width', g.width),
- height : this._to_pixel_coord('height', g.height)
+ top : this._toPixelCoord('top', g.top),
+ left : this._toPixelCoord('left', g.left),
+ width : this._toPixelCoord('width', g.width),
+ height : this._toPixelCoord('height', g.height)
};
},
@@ -702,7 +702,7 @@
*/
// check collision
- _is_collision: function(g) {
+ _isCollision: function(g) {
// is collision pair
function is_collision_pair (a, b) {
return !(a.left > b.left + b.width - 1 || a.left + a.width - 1 < b.left ||
@@ -728,7 +728,7 @@
},
// location/grid rank
- _location_rank: function(loc) {
+ _locationRank: function(loc) {
return (loc.top * this.cols) + loc.left;
},
@@ -737,7 +737,7 @@
*/
// update frame counter
- _menu_refresh: function() {
+ _menuRefresh: function() {
// scroll up possible?
if (this.visible) {
if (this.top == this.options.top_min)
@@ -763,22 +763,22 @@
*/
// panel on animation complete / frames not moving
- _panel_animation_complete: function() {
+ _panelAnimationComplete: function() {
var self = this;
- $(".frame").promise().done(function() {self._panel_scroll(0, true)});
+ $(".frame").promise().done(function() {self._panelScroll(0, true)});
},
// refresh panel
- _panel_refresh: function(animate) {
+ _panelRefresh: function(animate) {
// get current size
this.cols = parseInt($(window).width() / this.options.cell, 10) + 1;
// recalculate frame positions
- this._frame_insert(null, null, animate);
+ this._frameInsert(null, null, animate);
},
// update scroll
- _panel_scroll: function(delta, animate) {
+ _panelScroll: function(delta, animate) {
// new top value
var top_new = this.top - this.options.scroll * delta;
@@ -799,7 +799,7 @@
top : frame.screen_location.top - (this.top - top_new),
left : frame.screen_location.left
}
- this._frame_offset(frame, screen_location, animate);
+ this._frameOffset(frame, screen_location, animate);
}
}
@@ -808,7 +808,7 @@
}
// refresh
- this._menu_refresh();
+ this._menuRefresh();
},
/*
@@ -816,7 +816,7 @@
*/
// frame insert at given location
- _frame_insert: function(frame, new_loc, animate) {
+ _frameInsert: function(frame, new_loc, animate) {
// define
var place_list = [];
@@ -826,7 +826,7 @@
frame.grid_location = null;
// set first one to be placed
- place_list.push([frame, this._location_rank(new_loc)]);
+ place_list.push([frame, this._locationRank(new_loc)]);
}
// search
@@ -854,7 +854,7 @@
// place
for (i = 0; i < place_list.length; i++) {
- this._frame_place(place_list[i][0], animate);
+ this._framePlace(place_list[i][0], animate);
}
// identify maximum viewport size
@@ -875,16 +875,16 @@
this.top_max = Math.min(this.top_max, this.options.top_min);
// panel menu
- this._menu_refresh();
+ this._menuRefresh();
},
// naive frame place
- _frame_place: function(frame, animate) {
+ _framePlace: function(frame, animate) {
// reset grid location
frame.grid_location = null;
// grid coordinates of new frame
- var g = this._to_grid(this._frame_screen(frame));
+ var g = this._toGrid(this._frameScreen(frame));
// try grid coordinates
var done = false;
@@ -896,7 +896,7 @@
g.left = j;
// no collision
- if (!this._is_collision(g)) {
+ if (!this._isCollision(g)) {
done = true;
break;
}
@@ -910,14 +910,14 @@
// check if valid spot was found
if (done) {
- this._frame_grid(frame, g, animate);
+ this._frameGrid(frame, g, animate);
} else {
console.log("Grid dimensions exceeded.");
}
},
// focus
- _frame_focus: function(frame, has_focus) {
+ _frameFocus: function(frame, has_focus) {
// get new z-value
var z = this.frame_z + (has_focus ? 1 : 0);
@@ -926,7 +926,7 @@
},
// new left/top position frame
- _frame_offset: function(frame, p, animate) {
+ _frameOffset: function(frame, p, animate) {
// update screen location
frame.screen_location.left = p.left;
frame.screen_location.top = p.top;
@@ -934,7 +934,7 @@
// animate
if (animate) {
// set focus on animated
- this._frame_focus(frame, true);
+ this._frameFocus(frame, true);
// prepare for callback
var self = this;
@@ -943,7 +943,7 @@
$(frame.id).animate({top: p.top, left: p.left}, 'fast', function()
{
// remove focus
- self._frame_focus(frame, false);
+ self._frameFocus(frame, false);
});
} else
// update css
@@ -951,7 +951,7 @@
},
// resize frame
- _frame_resize: function(frame, p) {
+ _frameResize: function(frame, p) {
// update css
$(frame.id).css({width: p.width, height: p.height});
@@ -961,19 +961,19 @@
},
// new grid location
- _frame_grid: function (frame, l, animate) {
+ _frameGrid: function (frame, l, animate) {
// update grid location
frame.grid_location = l;
// place frame
- this._frame_offset(frame, this._to_pixel(l), animate);
+ this._frameOffset(frame, this._toPixel(l), animate);
// update grid rank
- frame.grid_rank = this._location_rank(l);
+ frame.grid_rank = this._locationRank(l);
},
// get frame dimensions
- _frame_screen: function(frame) {
+ _frameScreen: function(frame) {
var p = frame.screen_location;
return {top: p.top, left: p.left, width: p.width, height: p.height};
},
@@ -988,7 +988,7 @@
},
// fill regular frame template
- _template_frame: function(id, title) {
+ _templateFrame: function(id, title) {
// check title
if (!title)
title = '';
@@ -1008,7 +1008,7 @@
},
// fill regular frame template
- _template_frame_url: function(id, title, url) {
+ _templateFrameUrl: function(id, title, url) {
// url
if (url.indexOf('?') == -1)
url += '?';
@@ -1017,7 +1017,7 @@
url += 'widget=True';
// element
- var $el = $(this._template_frame(id, title));
+ var $el = $(this._templateFrame(id, title));
$el.find('.f-content').append('<iframe scrolling="auto" class="f-iframe" src="' + url + '"></iframe>');
// load template
@@ -1025,17 +1025,17 @@
},
// fill shadow template
- _template_shadow: function(id) {
+ _templateShadow: function(id) {
return '<div id="' + id + '" class="frame-shadow corner"></div>';
},
// fill background template in order to cover underlying iframes
- _template_background: function() {
+ _templateBackground: function() {
return '<div class="frame-background"></div>';
},
// fill menu button template
- _template_menu: function() {
+ _templateMenu: function() {
return '<div class="frame-scroll-up frame-menu fa fa-chevron-up fa-2x"></div>' +
'<div class="frame-scroll-down frame-menu fa fa-chevron-down fa-2x"></div>';
}
diff -r d1f6d05706d0f03c7a31cd5f8b3890c55e565af0 -r deb003947e0e02de4613912b14832944954576a5 static/scripts/mvc/ui/ui-portlet.js
--- a/static/scripts/mvc/ui/ui-portlet.js
+++ b/static/scripts/mvc/ui/ui-portlet.js
@@ -1,9 +1,8 @@
// dependencies
define(['utils/utils'], function(Utils) {
-// return
-var View = Backbone.View.extend(
-{
+// portlet view class
+var View = Backbone.View.extend({
// visibility
visible: false,
diff -r d1f6d05706d0f03c7a31cd5f8b3890c55e565af0 -r deb003947e0e02de4613912b14832944954576a5 static/scripts/packed/mvc/tools/tools-section.js
--- a/static/scripts/packed/mvc/tools/tools-section.js
+++ b/static/scripts/packed/mvc/tools/tools-section.js
@@ -1,1 +1,1 @@
-define(["utils/utils","mvc/ui/ui-table","mvc/ui/ui-misc","mvc/ui/ui-tabs","mvc/tools/tools-select-dataset"],function(d,b,f,a,c){var e=Backbone.View.extend({initialize:function(h,g){this.app=h;this.inputs=g.inputs;g.cls_tr="section-row";this.table=new b.View(g);this.setElement(this.table.$el);this.render()},render:function(){this.table.delAll();for(var g in this.inputs){this._add(this.inputs[g])}},_add:function(i){var h=this;var g=jQuery.extend(true,{},i);g.id=d.uuid();this.app.input_list[g.id]=g;var j=g.type;switch(j){case"conditional":this._addConditional(g);break;case"repeat":this._addRepeat(g);break;default:this._addRow(j,g)}},_addConditional:function(g){g.label=g.test_param.label;g.value=g.test_param.value;this._addRow("conditional",g);for(var j in g.cases){var h=g.id+"-section-"+j;var k=new e(this.app,{inputs:g.cases[j].inputs,cls:"ui-table-plain"});this.table.add(this._create_field({label:"",help:g.help,$el:k.$el,color:true}));this.table.append(h)}},_addRepeat:function(g){var h=this;var l=new a.View({title_new:"Add "+g.title,max:g.max,onnew:function(){var i=g.id+"-section-"+d.uuid();var n=new e(h.app,{inputs:g.inputs,cls:"ui-table-plain"});l.add({id:i,title:g.title,$el:n.$el,ondel:function(){l.del(i);l.retitle(g.title);h.app.refresh()}});l.retitle(g.title);l.show(i);h.app.refresh()}});for(var k=0;k<g.min;k++){var j=g.id+"-section-"+d.uuid();var m=new e(h.app,{inputs:g.inputs,cls:"ui-table-plain"});l.add({id:j,title:g.title,$el:m.$el})}l.retitle(g.title);this.table.add(this._create_field({label:g.title,help:g.help,$el:l.$el,color:true}));this.table.append(g.id)},_addRow:function(i,g){var j=g.id;var h=null;switch(i){case"text":h=this._field_text(g);break;case"select":h=this._field_select(g);break;case"data":h=this._field_data(g);break;case"data_column":h=this._field_data_colum(g);break;case"conditional":h=this._field_conditional(g);break;case"hidden":h=this._field_hidden(g);break;case"integer":h=this._field_slider(g);break;case"float":h=this._field_slider(g);break;case"boolean":h=this._field_boolean(g);break}if(!h){if(g.options){h=this._field_select(g)}else{h=this._field_text(g)}console.debug("tools-form::_addRow() : Auto matched field type ("+i+").")}if(g.value!==undefined){h.value(g.value)}this.app.field_list[j]=h;this.table.add(this._create_field({label:g.label,help:g.help,$el:h.$el}));this.table.append(j)},_field_conditional:function(g){var h=this;var j=[];for(var k in g.test_param.options){var l=g.test_param.options[k];j.push({label:l[0],value:l[1]})}return new f.Select.View({id:"field-"+g.id,data:j,onchange:function(t){for(var r in g.cases){var n=g.cases[r];var q=g.id+"-section-"+r;var m=h.table.get(q);var p=false;for(var o in n.inputs){var s=n.inputs[o].type;if(s&&s!=="hidden"){p=true;break}}if(n.value==t&&p){m.fadeIn("fast")}else{m.hide()}}}})},_field_data:function(g){var h=this;var i=g.id;return new c.View(this.app,{id:"field-"+i,extensions:g.extensions,multiple:g.multiple,onchange:function(r){if(r instanceof Array){r=r[0]}var p=h.app.tree.findReferences(i,"data_column");var k=h.app.datasets.filter(r);if(k&&p.length>0){console.debug("tool-form::field_data() - Selected dataset "+r+".");var t=k.get("metadata_column_types");if(!t){console.debug("tool-form::field_data() - FAILED: Could not find metadata for dataset "+r+".")}for(var m in p){var n=h.app.input_list[p[m]];var o=h.app.field_list[p[m]];if(!n||!o){console.debug("tool-form::field_data() - FAILED: Column not found.")}var l=n.numerical;var j=[];for(var s in t){var q=t[s];if(q=="int"||q=="float"||!l){j.push({label:"Column: "+(parseInt(s)+1)+" ["+t[s]+"]",value:s})}}if(o){o.update(j);if(!o.exists(o.value())){o.value(o.first())}}}}else{console.debug("tool-form::field_data() - FAILED: Could not find dataset "+r+".")}}})},_field_select:function(g){var h=[];for(var j in g.options){var k=g.options[j];h.push({label:k[0],value:k[1]})}var l=f.Select;switch(g.display){case"checkboxes":l=f.Checkbox;break;case"radio":l=f.RadioButton;break}return new l.View({id:"field-"+g.id,data:h,multiple:g.multiple})},_field_data_colum:function(g){return new f.Select.View({id:"field-"+g.id,multiple:g.multiple})},_field_text:function(g){return new f.Input({id:"field-"+g.id,area:g.area})},_field_slider:function(g){var h=1;if(g.type=="float"){h=(g.max-g.min)/10000}return new f.Slider.View({id:"field-"+g.id,min:g.min||0,max:g.max||1000,step:h})},_field_hidden:function(g){return new f.Hidden({id:"field-"+g.id})},_field_boolean:function(g){return new f.RadioButton.View({id:"field-"+g.id,data:[{label:"Yes",value:true},{label:"No",value:false}]})},_create_field:function(g){var h;if(g.color){h=$('<div class="ui-table-form-section"/>')}else{h=$("<div/>")}if(g.label){h.append('<div class="ui-table-form-title-strong">'+g.label+"</div>")}h.append(g.$el);if(g.help){h.append('<div class="ui-table-form-info">'+g.help+"</div>")}return h}});return{View:e}});
\ No newline at end of file
+define(["utils/utils","mvc/ui/ui-table","mvc/ui/ui-misc","mvc/ui/ui-tabs","mvc/tools/tools-select-dataset"],function(d,b,g,a,c){var e=Backbone.View.extend({initialize:function(h){this.setElement(this._template(h))},error:function(h){this.$el.find(".ui-table-form-error-text").html(h);this.$el.find(".ui-table-form-error").fadeIn();this.$el.addClass("ui-table-row-error")},reset:function(){this.$el.find(".ui-table-form-error").hide();this.$el.removeClass("ui-table-form-error")},_template:function(h){var i;if(h.highlight){i=$('<div class="ui-table-element ui-table-form-section"/>')}else{i=$('<div class="ui-table-element"/>')}i.append('<div class="ui-table-form-error"><span class="fa fa-arrow-down"/><span class="ui-table-form-error-text"></div>');if(h.label){i.append('<div class="ui-table-form-title-strong">'+h.label+"</div>")}i.append(h.$el);if(h.help){i.append('<div class="ui-table-form-info">'+h.help+"</div>")}return i}});var f=Backbone.View.extend({initialize:function(i,h){this.app=i;this.inputs=h.inputs;h.cls_tr="section-row";this.table=new b.View(h);this.setElement(this.table.$el);this.render()},render:function(){this.table.delAll();for(var h in this.inputs){this._add(this.inputs[h])}},_add:function(j){var i=this;var h=jQuery.extend(true,{},j);h.id=d.uuid();this.app.input_list[h.id]=h;var k=h.type;switch(k){case"conditional":this._addConditional(h);break;case"repeat":this._addRepeat(h);break;default:this._addRow(k,h)}},_addConditional:function(h){h.label=h.test_param.label;h.value=h.test_param.value;var j=this._addRow("conditional",h);for(var l in h.cases){var k=h.id+"-section-"+l;var n=new f(this.app,{inputs:h.cases[l].inputs,cls:"ui-table-plain"});var m=new e({label:"",help:h.help,$el:n.$el,highlight:true});this.table.add(m.$el);this.table.append(k)}},_addRepeat:function(h){var j=this;var m=new a.View({title_new:"Add "+h.title,max:h.max,onnew:function(){var i=h.id+"-section-"+d.uuid();var p=new f(j.app,{inputs:h.inputs,cls:"ui-table-plain"});m.add({id:i,title:h.title,$el:p.$el,ondel:function(){m.del(i);m.retitle(h.title);j.app.refresh()}});m.retitle(h.title);m.show(i);j.app.refresh()}});for(var l=0;l<h.min;l++){var k=h.id+"-section-"+d.uuid();var o=new f(j.app,{inputs:h.inputs,cls:"ui-table-plain"});m.add({id:k,title:h.title,$el:o.$el})}m.retitle(h.title);var n=new e({label:h.title,help:h.help,$el:m.$el,highlight:true});this.table.add(n.$el);this.table.append(h.id)},_addRow:function(j,h){var l=h.id;var i=null;switch(j){case"text":i=this._field_text(h);break;case"select":i=this._field_select(h);break;case"data":i=this._field_data(h);break;case"data_column":i=this._field_data_colum(h);break;case"conditional":i=this._field_conditional(h);break;case"hidden":i=this._field_hidden(h);break;case"integer":i=this._field_slider(h);break;case"float":i=this._field_slider(h);break;case"boolean":i=this._field_boolean(h);break}if(!i){if(h.options){i=this._field_select(h)}else{i=this._field_text(h)}console.debug("tools-form::_addRow() : Auto matched field type ("+j+").")}if(h.value!==undefined){i.value(h.value)}this.app.field_list[l]=i;var k=new e({label:h.label,help:h.help,$el:i.$el});this.app.element_list[l]=k;this.table.add(k.$el);this.table.append(l);return this.table.get(l)},_field_conditional:function(h){var j=this;var k=[];for(var l in h.test_param.options){var m=h.test_param.options[l];k.push({label:m[0],value:m[1]})}return new g.Select.View({id:"field-"+h.id,data:k,onchange:function(u){for(var s in h.cases){var o=h.cases[s];var r=h.id+"-section-"+s;var n=j.table.get(r);var q=false;for(var p in o.inputs){var t=o.inputs[p].type;if(t&&t!=="hidden"){q=true;break}}if(o.value==u&&q){n.fadeIn("fast")}else{n.hide()}}}})},_field_data:function(h){var i=this;var j=h.id;return new c.View(this.app,{id:"field-"+j,extensions:h.extensions,multiple:h.multiple,onchange:function(u){if(u instanceof Array){u=u[0]}var s=i.app.tree.references(j,"data_column");var m=i.app.datasets.filter(u);if(m&&s.length>0){console.debug("tool-form::field_data() - Selected dataset "+u+".");var w=m.get("metadata_column_types");if(!w){console.debug("tool-form::field_data() - FAILED: Could not find metadata for dataset "+u+".")}for(var o in s){var q=i.app.input_list[s[o]];var r=i.app.field_list[s[o]];if(!q||!r){console.debug("tool-form::field_data() - FAILED: Column not found.")}var n=q.numerical;var l=[];for(var v in w){var t=w[v];var k=(parseInt(v)+1);var p="Text";if(t=="int"||t=="float"){p="Number"}if(t=="int"||t=="float"||!n){l.push({label:"Column: "+k+" ["+p+"]",value:k})}}if(r){r.update(l);if(!r.exists(r.value())){r.value(r.first())}}}}else{console.debug("tool-form::field_data() - FAILED: Could not find dataset "+u+".")}}})},_field_select:function(h){var j=[];for(var k in h.options){var l=h.options[k];j.push({label:l[0],value:l[1]})}var m=g.Select;switch(h.display){case"checkboxes":m=g.Checkbox;break;case"radio":m=g.RadioButton;break}return new m.View({id:"field-"+h.id,data:j,multiple:h.multiple})},_field_data_colum:function(h){return new g.Select.View({id:"field-"+h.id,multiple:h.multiple})},_field_text:function(h){return new g.Input({id:"field-"+h.id,area:h.area})},_field_slider:function(h){var i=1;if(h.type=="float"){i=(h.max-h.min)/10000}return new g.Slider.View({id:"field-"+h.id,min:h.min||0,max:h.max||1000,step:i})},_field_hidden:function(h){return new g.Hidden({id:"field-"+h.id})},_field_boolean:function(h){return new g.RadioButton.View({id:"field-"+h.id,data:[{label:"Yes",value:"true"},{label:"No",value:"false"}]})}});return{View:f}});
\ No newline at end of file
diff -r d1f6d05706d0f03c7a31cd5f8b3890c55e565af0 -r deb003947e0e02de4613912b14832944954576a5 static/scripts/packed/mvc/ui/ui-frames.js
--- a/static/scripts/packed/mvc/ui/ui-frames.js
+++ b/static/scripts/packed/mvc/ui/ui-frames.js
@@ -1,1 +1,1 @@
-define([],function(){var a=Backbone.View.extend({options:{frame:{cols:6,rows:3},rows:1000,cell:130,margin:5,scroll:5,top_min:40,frame_max:9,visible:true,onchange:null},cols:0,top:0,top_max:0,frame_z:0,frame_counter:0,frame_counter_id:0,frame_list:[],frame_shadow:null,visible:null,initialize:function(c){var b=this;if(c){this.options=_.defaults(c,this.options)}this.visible=this.options.visible;this.top=this.top_max=this.options.top_min;this.setElement(this._template());$(this.el).append(this._template_background());$(this.el).append(this._template_menu());$(this.el_main).append($(this.el));var d="#frame-shadow";$(this.el).append(this._template_shadow(d.substring(1)));this.frame_shadow={id:d,screen_location:{},grid_location:{},grid_rank:null,grid_lock:false};this._frame_resize(this.frame_shadow,{width:0,height:0});this.frame_list[d]=this.frame_shadow;this._panel_refresh();if(!this.visible){this.hide()}else{this.show()}var b=this;$(window).resize(function(){if(b.visible){b._panel_refresh()}})},add:function(c){var f={title:"",content:null,target:"",type:null};if(c){c=_.defaults(c,f)}else{c=f}if(!c.content){return}if(this.frame_counter>=this.options.frame_max){alert("You have reached the maximum number of allowed frames ("+this.options.frame_max+").");return}var d="#frame-"+(this.frame_counter_id++);if($(d).length!==0){alert("This frame already exists. This page might contain multiple frame managers.");return}this.top=this.options.top_min;var e=null;if(c.type==="url"){e=$(this._template_frame_url(d.substring(1),c.title,c.content))}else{if(c.type==="other"){e=$(this._template_frame(d.substring(1),c.title));var b=e.find(".f-content");if(_.isFunction(c.content)){c.content(b)}else{b.append(c.content)}}}$(this.el).append(e);var g={id:d,screen_location:{},grid_location:{},grid_rank:null,grid_lock:false};c.width=this._to_pixel_coord("width",this.options.frame.cols);c.height=this._to_pixel_coord("height",this.options.frame.rows);this.frame_z=parseInt($(g.id).css("z-index"));this.frame_list[d]=g;this.frame_counter++;this._frame_resize(g,{width:c.width,height:c.height});this._frame_insert(g,{top:0,left:0},true);if(!this.visible){this.show()}},show:function(){this.visible=true;this.$el.find(".frame").fadeIn("fast");this.$el.find(this.frame_shadow.id).hide();this.$el.find(".frame-background").show();this._panel_refresh();this._menu_refresh()},hide:function(){if(this.event.type!==null){return}this.visible=false;this.$el.find(".frame").fadeOut("fast");this.$el.find(".frame-background").hide();this.$el.find(".frame-menu").hide();this._menu_refresh()},length:function(){return this.frame_counter},setOnChange:function(b){this.options.onchange=b},event:{type:null,target:null,xy:null},events:{mousemove:"_event_frame_mouse_move",mouseup:"_event_frame_mouse_up",mouseleave:"_event_frame_mouse_up",mousewheel:"_event_panel_scroll",DOMMouseScroll:"_event_panel_scroll","mousedown .frame":"_event_frame_mouse_down","mousedown .frame-background":"_event_hide","mousedown .frame-scroll-up":"_event_panel_scroll_up","mousedown .frame-scroll-down":"_event_panel_scroll_down","mousedown .f-close":"_event_frame_close","mousedown .f-pin":"_event_frame_lock"},_event_frame_mouse_down:function(b){if(this.event.type!==null){return}if($(b.target).hasClass("f-header")||$(b.target).hasClass("f-title")){this.event.type="drag"}if($(b.target).hasClass("f-resize")){this.event.type="resize"}if(this.event.type===null){return}b.preventDefault();this.event.target=this._frame_identify(b.target);if(this.event.target.grid_lock){this.event.type=null;return}this.event.xy={x:b.originalEvent.pageX,y:b.originalEvent.pageY};this._frame_drag_start(this.event.target)},_event_frame_mouse_move:function(h){if(this.event.type!="drag"&&this.event.type!="resize"){return}var f={x:h.originalEvent.pageX,y:h.originalEvent.pageY};var c={x:f.x-this.event.xy.x,y:f.y-this.event.xy.y};this.event.xy=f;var g=this._frame_screen(this.event.target);if(this.event.type=="resize"){g.width+=c.x;g.height+=c.y;var d=this.options.cell-this.options.margin-1;g.width=Math.max(g.width,d);g.height=Math.max(g.height,d);this._frame_resize(this.event.target,g);g.width=this._to_grid_coord("width",g.width)+1;g.height=this._to_grid_coord("height",g.height)+1;g.width=this._to_pixel_coord("width",g.width);g.height=this._to_pixel_coord("height",g.height);this._frame_resize(this.frame_shadow,g);this._frame_insert(this.frame_shadow,{top:this._to_grid_coord("top",g.top),left:this._to_grid_coord("left",g.left)})}if(this.event.type=="drag"){g.left+=c.x;g.top+=c.y;this._frame_offset(this.event.target,g);var b={top:this._to_grid_coord("top",g.top),left:this._to_grid_coord("left",g.left)};if(b.left!==0){b.left++}this._frame_insert(this.frame_shadow,b)}},_event_frame_mouse_up:function(b){if(this.event.type!="drag"&&this.event.type!="resize"){return}this._frame_drag_stop(this.event.target);this.event.type=null},_event_frame_close:function(c){if(this.event.type!==null){return}c.preventDefault();var d=this._frame_identify(c.target);var b=this;$(d.id).fadeOut("fast",function(){$(d.id).remove();delete b.frame_list[d.id];b.frame_counter--;b._panel_refresh(true);b._panel_animation_complete();if(b.visible&&b.frame_counter==0){b.hide()}})},_event_frame_lock:function(b){if(this.event.type!==null){return}b.preventDefault();var c=this._frame_identify(b.target);if(c.grid_lock){c.grid_lock=false;$(c.id).find(".f-pin").removeClass("toggle");$(c.id).find(".f-header").removeClass("f-not-allowed");$(c.id).find(".f-title").removeClass("f-not-allowed");$(c.id).find(".f-resize").show();$(c.id).find(".f-close").show()}else{c.grid_lock=true;$(c.id).find(".f-pin").addClass("toggle");$(c.id).find(".f-header").addClass("f-not-allowed");$(c.id).find(".f-title").addClass("f-not-allowed");$(c.id).find(".f-resize").hide();$(c.id).find(".f-close").hide()}},_event_hide:function(b){if(this.event.type!==null){return}this.hide()},_event_panel_scroll:function(b){if(this.event.type!==null||!this.visible){return}var c=$(b.srcElement).parents(".frame");if(c.length!==0){b.stopPropagation();return}b.preventDefault();var d=b.originalEvent.detail?b.originalEvent.detail:b.originalEvent.wheelDelta/-3;this._panel_scroll(d)},_event_panel_scroll_up:function(b){if(this.event.type!==null){return}b.preventDefault();this._panel_scroll(-this.options.scroll)},_event_panel_scroll_down:function(b){if(this.event.type!==null){return}b.preventDefault();this._panel_scroll(this.options.scroll)},_frame_identify:function(b){return this.frame_list["#"+$(b).closest(".frame").attr("id")]},_frame_drag_start:function(c){this._frame_focus(c,true);var b=this._frame_screen(c);this._frame_resize(this.frame_shadow,b);this._frame_grid(this.frame_shadow,c.grid_location);c.grid_location=null;$(this.frame_shadow.id).show();$(".f-cover").show()},_frame_drag_stop:function(c){this._frame_focus(c,false);var b=this._frame_screen(this.frame_shadow);this._frame_resize(c,b);this._frame_grid(c,this.frame_shadow.grid_location,true);this.frame_shadow.grid_location=null;$(this.frame_shadow.id).hide();$(".f-cover").hide();this._panel_animation_complete()},_to_grid_coord:function(d,c){var b=(d=="width"||d=="height")?1:-1;if(d=="top"){c-=this.top}return parseInt((c+b*this.options.margin)/this.options.cell,10)},_to_pixel_coord:function(d,e){var b=(d=="width"||d=="height")?1:-1;var c=(e*this.options.cell)-b*this.options.margin;if(d=="top"){c+=this.top}return c},_to_grid:function(b){return{top:this._to_grid_coord("top",b.top),left:this._to_grid_coord("left",b.left),width:this._to_grid_coord("width",b.width),height:this._to_grid_coord("height",b.height)}},_to_pixel:function(b){return{top:this._to_pixel_coord("top",b.top),left:this._to_pixel_coord("left",b.left),width:this._to_pixel_coord("width",b.width),height:this._to_pixel_coord("height",b.height)}},_is_collision:function(d){function b(g,f){return !(g.left>f.left+f.width-1||g.left+g.width-1<f.left||g.top>f.top+f.height-1||g.top+g.height-1<f.top)}for(var c in this.frame_list){var e=this.frame_list[c];if(e.grid_location===null){continue}if(b(d,e.grid_location)){return true}}return false},_location_rank:function(b){return(b.top*this.cols)+b.left},_menu_refresh:function(){if(this.visible){if(this.top==this.options.top_min){$(".frame-scroll-up").hide()}else{$(".frame-scroll-up").show()}if(this.top==this.top_max){$(".frame-scroll-down").hide()}else{$(".frame-scroll-down").show()}}if(this.options.onchange){this.options.onchange()}},_panel_animation_complete:function(){var b=this;$(".frame").promise().done(function(){b._panel_scroll(0,true)})},_panel_refresh:function(b){this.cols=parseInt($(window).width()/this.options.cell,10)+1;this._frame_insert(null,null,b)},_panel_scroll:function(g,b){var d=this.top-this.options.scroll*g;d=Math.max(d,this.top_max);d=Math.min(d,this.options.top_min);if(this.top!=d){for(var c in this.frame_list){var f=this.frame_list[c];if(f.grid_location!==null){var e={top:f.screen_location.top-(this.top-d),left:f.screen_location.left};this._frame_offset(f,e,b)}}this.top=d}this._menu_refresh()},_frame_insert:function(h,b,d){var c=[];if(h){h.grid_location=null;c.push([h,this._location_rank(b)])}var e=null;for(e in this.frame_list){var g=this.frame_list[e];if(g.grid_location!==null&&!g.grid_lock){g.grid_location=null;c.push([g,g.grid_rank])}}c.sort(function(k,f){var m=k[1];var l=f[1];return m<l?-1:(m>l?1:0)});for(e=0;e<c.length;e++){this._frame_place(c[e][0],d)}this.top_max=0;for(var e in this.frame_list){var h=this.frame_list[e];if(h.grid_location!==null){this.top_max=Math.max(this.top_max,h.grid_location.top+h.grid_location.height)}}this.top_max=$(window).height()-this.top_max*this.options.cell-2*this.options.margin;this.top_max=Math.min(this.top_max,this.options.top_min);this._menu_refresh()},_frame_place:function(h,c){h.grid_location=null;var f=this._to_grid(this._frame_screen(h));var b=false;for(var e=0;e<this.options.rows;e++){for(var d=0;d<Math.max(1,this.cols-f.width);d++){f.top=e;f.left=d;if(!this._is_collision(f)){b=true;break}}if(b){break}}if(b){this._frame_grid(h,f,c)}else{console.log("Grid dimensions exceeded.")}},_frame_focus:function(d,b){var c=this.frame_z+(b?1:0);$(d.id).css("z-index",c)},_frame_offset:function(e,d,c){e.screen_location.left=d.left;e.screen_location.top=d.top;if(c){this._frame_focus(e,true);var b=this;$(e.id).animate({top:d.top,left:d.left},"fast",function(){b._frame_focus(e,false)})}else{$(e.id).css({top:d.top,left:d.left})}},_frame_resize:function(c,b){$(c.id).css({width:b.width,height:b.height});c.screen_location.width=b.width;c.screen_location.height=b.height},_frame_grid:function(d,b,c){d.grid_location=b;this._frame_offset(d,this._to_pixel(b),c);d.grid_rank=this._location_rank(b)},_frame_screen:function(c){var b=c.screen_location;return{top:b.top,left:b.left,width:b.width,height:b.height}},_template:function(){return'<div class="galaxy-frame"></div>'},_template_frame:function(c,b){if(!b){b=""}return'<div id="'+c+'" class="frame corner"><div class="f-header corner"><span class="f-title">'+b+'</span><span class="f-icon f-close fa fa-trash-o"></span><span class="f-icon f-pin fa fa-thumb-tack"></span></div><div class="f-content"><div class="f-cover"></div></div><span class="f-resize f-icon corner fa fa-resize-full"></span></div>'},_template_frame_url:function(e,d,b){if(b.indexOf("?")==-1){b+="?"}else{b+="&"}b+="widget=True";var c=$(this._template_frame(e,d));c.find(".f-content").append('<iframe scrolling="auto" class="f-iframe" src="'+b+'"></iframe>');return c},_template_shadow:function(b){return'<div id="'+b+'" class="frame-shadow corner"></div>'},_template_background:function(){return'<div class="frame-background"></div>'},_template_menu:function(){return'<div class="frame-scroll-up frame-menu fa fa-chevron-up fa-2x"></div><div class="frame-scroll-down frame-menu fa fa-chevron-down fa-2x"></div>'}});return{View:a}});
\ No newline at end of file
+define([],function(){var a=Backbone.View.extend({options:{frame:{cols:6,rows:3},rows:1000,cell:130,margin:5,scroll:5,top_min:40,frame_max:9,visible:true,onchange:null},cols:0,top:0,top_max:0,frame_z:0,frame_counter:0,frame_counter_id:0,frame_list:[],frame_shadow:null,visible:null,initialize:function(c){var b=this;if(c){this.options=_.defaults(c,this.options)}this.visible=this.options.visible;this.top=this.top_max=this.options.top_min;this.setElement(this._template());$(this.el).append(this._templateBackground());$(this.el).append(this._templateMenu());$(this.el_main).append($(this.el));var d="#frame-shadow";$(this.el).append(this._templateShadow(d.substring(1)));this.frame_shadow={id:d,screen_location:{},grid_location:{},grid_rank:null,grid_lock:false};this._frameResize(this.frame_shadow,{width:0,height:0});this.frame_list[d]=this.frame_shadow;this._panelRefresh();if(!this.visible){this.hide()}else{this.show()}var b=this;$(window).resize(function(){if(b.visible){b._panelRefresh()}})},add:function(c){var f={title:"",content:null,target:"",type:null};if(c){c=_.defaults(c,f)}else{c=f}if(!c.content){return}if(this.frame_counter>=this.options.frame_max){alert("You have reached the maximum number of allowed frames ("+this.options.frame_max+").");return}var d="#frame-"+(this.frame_counter_id++);if($(d).length!==0){alert("This frame already exists. This page might contain multiple frame managers.");return}this.top=this.options.top_min;var e=null;if(c.type==="url"){e=$(this._templateFrameUrl(d.substring(1),c.title,c.content))}else{if(c.type==="other"){e=$(this._templateFrame(d.substring(1),c.title));var b=e.find(".f-content");if(_.isFunction(c.content)){c.content(b)}else{b.append(c.content)}}}$(this.el).append(e);var g={id:d,screen_location:{},grid_location:{},grid_rank:null,grid_lock:false};c.width=this._toPixelCoord("width",this.options.frame.cols);c.height=this._toPixelCoord("height",this.options.frame.rows);this.frame_z=parseInt($(g.id).css("z-index"));this.frame_list[d]=g;this.frame_counter++;this._frameResize(g,{width:c.width,height:c.height});this._frameInsert(g,{top:0,left:0},true);if(!this.visible){this.show()}},show:function(){this.visible=true;this.$el.find(".frame").fadeIn("fast");this.$el.find(this.frame_shadow.id).hide();this.$el.find(".frame-background").show();this._panelRefresh();this._menuRefresh()},hide:function(){if(this.event.type!==null){return}this.visible=false;this.$el.find(".frame").fadeOut("fast");this.$el.find(".frame-background").hide();this.$el.find(".frame-menu").hide();this._menuRefresh()},length:function(){return this.frame_counter},setOnChange:function(b){this.options.onchange=b},event:{type:null,target:null,xy:null},events:{mousemove:"_eventFrameMouseMove",mouseup:"_eventFrameMouseUp",mouseleave:"_eventFrameMouseUp",mousewheel:"_eventPanelScroll",DOMMouseScroll:"_eventPanelScroll","mousedown .frame":"_eventFrameMouseDown","mousedown .frame-background":"_eventHide","mousedown .frame-scroll-up":"_eventPanelScroll_up","mousedown .frame-scroll-down":"_eventPanelScroll_down","mousedown .f-close":"_eventFrameClose","mousedown .f-pin":"_eventFrameLock"},_eventFrameMouseDown:function(b){if(this.event.type!==null){return}if($(b.target).hasClass("f-header")||$(b.target).hasClass("f-title")){this.event.type="drag"}if($(b.target).hasClass("f-resize")){this.event.type="resize"}if(this.event.type===null){return}b.preventDefault();this.event.target=this._frameIdentify(b.target);if(this.event.target.grid_lock){this.event.type=null;return}this.event.xy={x:b.originalEvent.pageX,y:b.originalEvent.pageY};this._frameDragStart(this.event.target)},_eventFrameMouseMove:function(h){if(this.event.type!="drag"&&this.event.type!="resize"){return}var f={x:h.originalEvent.pageX,y:h.originalEvent.pageY};var c={x:f.x-this.event.xy.x,y:f.y-this.event.xy.y};this.event.xy=f;var g=this._frameScreen(this.event.target);if(this.event.type=="resize"){g.width+=c.x;g.height+=c.y;var d=this.options.cell-this.options.margin-1;g.width=Math.max(g.width,d);g.height=Math.max(g.height,d);this._frameResize(this.event.target,g);g.width=this._toGridCoord("width",g.width)+1;g.height=this._toGridCoord("height",g.height)+1;g.width=this._toPixelCoord("width",g.width);g.height=this._toPixelCoord("height",g.height);this._frameResize(this.frame_shadow,g);this._frameInsert(this.frame_shadow,{top:this._toGridCoord("top",g.top),left:this._toGridCoord("left",g.left)})}if(this.event.type=="drag"){g.left+=c.x;g.top+=c.y;this._frameOffset(this.event.target,g);var b={top:this._toGridCoord("top",g.top),left:this._toGridCoord("left",g.left)};if(b.left!==0){b.left++}this._frameInsert(this.frame_shadow,b)}},_eventFrameMouseUp:function(b){if(this.event.type!="drag"&&this.event.type!="resize"){return}this._frameDragStop(this.event.target);this.event.type=null},_eventFrameClose:function(c){if(this.event.type!==null){return}c.preventDefault();var d=this._frameIdentify(c.target);var b=this;$(d.id).fadeOut("fast",function(){$(d.id).remove();delete b.frame_list[d.id];b.frame_counter--;b._panelRefresh(true);b._panelAnimationComplete();if(b.visible&&b.frame_counter==0){b.hide()}})},_eventFrameLock:function(b){if(this.event.type!==null){return}b.preventDefault();var c=this._frameIdentify(b.target);if(c.grid_lock){c.grid_lock=false;$(c.id).find(".f-pin").removeClass("toggle");$(c.id).find(".f-header").removeClass("f-not-allowed");$(c.id).find(".f-title").removeClass("f-not-allowed");$(c.id).find(".f-resize").show();$(c.id).find(".f-close").show()}else{c.grid_lock=true;$(c.id).find(".f-pin").addClass("toggle");$(c.id).find(".f-header").addClass("f-not-allowed");$(c.id).find(".f-title").addClass("f-not-allowed");$(c.id).find(".f-resize").hide();$(c.id).find(".f-close").hide()}},_eventHide:function(b){if(this.event.type!==null){return}this.hide()},_eventPanelScroll:function(b){if(this.event.type!==null||!this.visible){return}var c=$(b.srcElement).parents(".frame");if(c.length!==0){b.stopPropagation();return}b.preventDefault();var d=b.originalEvent.detail?b.originalEvent.detail:b.originalEvent.wheelDelta/-3;this._panelScroll(d)},_eventPanelScroll_up:function(b){if(this.event.type!==null){return}b.preventDefault();this._panelScroll(-this.options.scroll)},_eventPanelScroll_down:function(b){if(this.event.type!==null){return}b.preventDefault();this._panelScroll(this.options.scroll)},_frameIdentify:function(b){return this.frame_list["#"+$(b).closest(".frame").attr("id")]},_frameDragStart:function(c){this._frameFocus(c,true);var b=this._frameScreen(c);this._frameResize(this.frame_shadow,b);this._frameGrid(this.frame_shadow,c.grid_location);c.grid_location=null;$(this.frame_shadow.id).show();$(".f-cover").show()},_frameDragStop:function(c){this._frameFocus(c,false);var b=this._frameScreen(this.frame_shadow);this._frameResize(c,b);this._frameGrid(c,this.frame_shadow.grid_location,true);this.frame_shadow.grid_location=null;$(this.frame_shadow.id).hide();$(".f-cover").hide();this._panelAnimationComplete()},_toGridCoord:function(d,c){var b=(d=="width"||d=="height")?1:-1;if(d=="top"){c-=this.top}return parseInt((c+b*this.options.margin)/this.options.cell,10)},_toPixelCoord:function(d,e){var b=(d=="width"||d=="height")?1:-1;var c=(e*this.options.cell)-b*this.options.margin;if(d=="top"){c+=this.top}return c},_toGrid:function(b){return{top:this._toGridCoord("top",b.top),left:this._toGridCoord("left",b.left),width:this._toGridCoord("width",b.width),height:this._toGridCoord("height",b.height)}},_toPixel:function(b){return{top:this._toPixelCoord("top",b.top),left:this._toPixelCoord("left",b.left),width:this._toPixelCoord("width",b.width),height:this._toPixelCoord("height",b.height)}},_isCollision:function(d){function b(g,f){return !(g.left>f.left+f.width-1||g.left+g.width-1<f.left||g.top>f.top+f.height-1||g.top+g.height-1<f.top)}for(var c in this.frame_list){var e=this.frame_list[c];if(e.grid_location===null){continue}if(b(d,e.grid_location)){return true}}return false},_locationRank:function(b){return(b.top*this.cols)+b.left},_menuRefresh:function(){if(this.visible){if(this.top==this.options.top_min){$(".frame-scroll-up").hide()}else{$(".frame-scroll-up").show()}if(this.top==this.top_max){$(".frame-scroll-down").hide()}else{$(".frame-scroll-down").show()}}if(this.options.onchange){this.options.onchange()}},_panelAnimationComplete:function(){var b=this;$(".frame").promise().done(function(){b._panelScroll(0,true)})},_panelRefresh:function(b){this.cols=parseInt($(window).width()/this.options.cell,10)+1;this._frameInsert(null,null,b)},_panelScroll:function(g,b){var d=this.top-this.options.scroll*g;d=Math.max(d,this.top_max);d=Math.min(d,this.options.top_min);if(this.top!=d){for(var c in this.frame_list){var f=this.frame_list[c];if(f.grid_location!==null){var e={top:f.screen_location.top-(this.top-d),left:f.screen_location.left};this._frameOffset(f,e,b)}}this.top=d}this._menuRefresh()},_frameInsert:function(h,b,d){var c=[];if(h){h.grid_location=null;c.push([h,this._locationRank(b)])}var e=null;for(e in this.frame_list){var g=this.frame_list[e];if(g.grid_location!==null&&!g.grid_lock){g.grid_location=null;c.push([g,g.grid_rank])}}c.sort(function(k,f){var m=k[1];var l=f[1];return m<l?-1:(m>l?1:0)});for(e=0;e<c.length;e++){this._framePlace(c[e][0],d)}this.top_max=0;for(var e in this.frame_list){var h=this.frame_list[e];if(h.grid_location!==null){this.top_max=Math.max(this.top_max,h.grid_location.top+h.grid_location.height)}}this.top_max=$(window).height()-this.top_max*this.options.cell-2*this.options.margin;this.top_max=Math.min(this.top_max,this.options.top_min);this._menuRefresh()},_framePlace:function(h,c){h.grid_location=null;var f=this._toGrid(this._frameScreen(h));var b=false;for(var e=0;e<this.options.rows;e++){for(var d=0;d<Math.max(1,this.cols-f.width);d++){f.top=e;f.left=d;if(!this._isCollision(f)){b=true;break}}if(b){break}}if(b){this._frameGrid(h,f,c)}else{console.log("Grid dimensions exceeded.")}},_frameFocus:function(d,b){var c=this.frame_z+(b?1:0);$(d.id).css("z-index",c)},_frameOffset:function(e,d,c){e.screen_location.left=d.left;e.screen_location.top=d.top;if(c){this._frameFocus(e,true);var b=this;$(e.id).animate({top:d.top,left:d.left},"fast",function(){b._frameFocus(e,false)})}else{$(e.id).css({top:d.top,left:d.left})}},_frameResize:function(c,b){$(c.id).css({width:b.width,height:b.height});c.screen_location.width=b.width;c.screen_location.height=b.height},_frameGrid:function(d,b,c){d.grid_location=b;this._frameOffset(d,this._toPixel(b),c);d.grid_rank=this._locationRank(b)},_frameScreen:function(c){var b=c.screen_location;return{top:b.top,left:b.left,width:b.width,height:b.height}},_template:function(){return'<div class="galaxy-frame"></div>'},_templateFrame:function(c,b){if(!b){b=""}return'<div id="'+c+'" class="frame corner"><div class="f-header corner"><span class="f-title">'+b+'</span><span class="f-icon f-close fa fa-trash-o"></span><span class="f-icon f-pin fa fa-thumb-tack"></span></div><div class="f-content"><div class="f-cover"></div></div><span class="f-resize f-icon corner fa fa-resize-full"></span></div>'},_templateFrameUrl:function(e,d,b){if(b.indexOf("?")==-1){b+="?"}else{b+="&"}b+="widget=True";var c=$(this._templateFrame(e,d));c.find(".f-content").append('<iframe scrolling="auto" class="f-iframe" src="'+b+'"></iframe>');return c},_templateShadow:function(b){return'<div id="'+b+'" class="frame-shadow corner"></div>'},_templateBackground:function(){return'<div class="frame-background"></div>'},_templateMenu:function(){return'<div class="frame-scroll-up frame-menu fa fa-chevron-up fa-2x"></div><div class="frame-scroll-down frame-menu fa fa-chevron-down fa-2x"></div>'}});return{View:a}});
\ No newline at end of file
diff -r d1f6d05706d0f03c7a31cd5f8b3890c55e565af0 -r deb003947e0e02de4613912b14832944954576a5 static/style/blue/base.css
--- a/static/style/blue/base.css
+++ b/static/style/blue/base.css
@@ -1278,6 +1278,8 @@
.upload-ftp .upload-ftp-help{margin-bottom:10px}
.upload-ftp .upload-ftp-warning{text-align:center;margin-top:20px}
.upload-settings .upload-settings-cover{position:absolute;width:100%;height:100%;top:0px;left:0px;background:#fff;opacity:0.4;cursor:no-drop}
+.ui-table-row-error{-moz-border-radius:3px;border-radius:3px;background:#f9c7c5;padding:5px}
+.ui-table-form-error{display:none}.ui-table-form-error .ui-table-form-error-text{padding-left:5px}
.ui-form-slider .ui-form-slider-text{width:100px;float:left}
.ui-form-slider .ui-form-slider-element{width:calc(100% - 110px);float:left;top:8px;left:10px}
.ui-radiobutton label{height:23px;line-height:1em}
diff -r d1f6d05706d0f03c7a31cd5f8b3890c55e565af0 -r deb003947e0e02de4613912b14832944954576a5 static/style/src/less/frame.less
--- a/static/style/src/less/frame.less
+++ b/static/style/src/less/frame.less
@@ -1,18 +1,14 @@
-.galaxy-frame
-{
- .corner
- {
+.galaxy-frame{
+ .corner {
-moz-border-radius: @border-radius-large;
border-radius: @border-radius-large;
}
- .toggle
- {
+ .toggle {
color: gold;
}
- .frame-background
- {
+ .frame-background {
z-index : @zindex-navbar;
position : absolute;
display : none;
@@ -25,8 +21,7 @@
overflow : auto;
}
- .frame-shadow
- {
+ .frame-shadow {
z-index : @zindex-navbar + 1;
position : absolute;
display : none;
@@ -40,8 +35,7 @@
/*
panel menu button
*/
- .frame-menu
- {
+ .frame-menu {
z-index : @zindex-navbar + 5;
position : absolute;
cursor : pointer;
@@ -49,13 +43,11 @@
right : 10px;
}
- .frame-scroll-up
- {
+ .frame-scroll-up {
top : 50px;
}
- .frame-scroll-down
- {
+ .frame-scroll-down {
bottom : 20px;
}
@@ -63,8 +55,7 @@
frame components
*/
- .frame
- {
+ .frame {
z-index : @zindex-navbar + 2;
overflow : hidden;
position : absolute;
@@ -72,8 +63,7 @@
border : 1px solid @navbar-default-border;
-webkit-box-shadow: 0 0 5px rgba(0,0,0,0.3);
- .f-content
- {
+ .f-content{
position : absolute;
overflow : hidden;
background : @white;
@@ -84,8 +74,7 @@
right : 3px;
}
- .f-cover
- {
+ .f-cover{
position : absolute;
display : none;
top : 0px;
@@ -96,15 +85,13 @@
background : @white;
}
- .f-iframe
- {
+ .f-iframe{
border : none;
width : 100%;
height : 100%;
}
- .f-header
- {
+ .f-header{
height : 17px;
margin : 2px;
cursor : pointer;
@@ -113,8 +100,7 @@
color : @white;
}
- .f-title
- {
+ .f-title {
position : absolute;
top : 2px;
left : 16px;
@@ -128,32 +114,27 @@
frame icons
*/
- .f-icon
- {
+ .f-icon{
position : absolute;
cursor : pointer;
font-size : 14px;
}
- .f-not-allowed
- {
+ .f-not-allowed{
cursor : not-allowed;
}
- .f-close
- {
+ .f-close{
right : 5px;
top : 3px;
}
- .f-pin
- {
+ .f-pin{
left : 6px;
top : 3px;
}
- .f-resize
- {
+ .f-resize{
right : 0px;
bottom : 0px;
background : @white;
diff -r d1f6d05706d0f03c7a31cd5f8b3890c55e565af0 -r deb003947e0e02de4613912b14832944954576a5 static/style/src/less/ui.less
--- a/static/style/src/less/ui.less
+++ b/static/style/src/less/ui.less
@@ -1,3 +1,17 @@
+.ui-table-row-error {
+ -moz-border-radius: @border-radius-base;
+ border-radius: @border-radius-base;
+ background: @state-danger-bg;
+ padding: 5px;
+}
+
+.ui-table-form-error {
+ display: none;
+ .ui-table-form-error-text {
+ padding-left: 5px;
+ }
+}
+
.ui-form-slider {
.ui-form-slider-text {
&:extend(.form-control);
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
10 Sep '14
Branch: refs/heads/master
Home: https://github.com/galaxyproject/usegalaxy-playbook
Commit: 9b4c92fc5f5de88e73d91a4850e0a02af5681ca9
https://github.com/galaxyproject/usegalaxy-playbook/commit/9b4c92fc5f5de88e…
Author: Nate Coraor <nate(a)bx.psu.edu>
Date: 2014-09-10 (Wed, 10 Sep 2014)
Changed paths:
A files/galaxy/test.galaxyproject.org/var/integrated_tool_panel.xml
A files/galaxy/usegalaxy.org/var/integrated_tool_panel.xml
A files/galaxy/usegalaxy.org/var/shed_data_manager_conf.xml
Log Message:
-----------
Add more mutable configs.
Commit: f86d4395ec4e603aa6dfb6d4706c864ac5856219
https://github.com/galaxyproject/usegalaxy-playbook/commit/f86d4395ec4e603a…
Author: Nate Coraor <nate(a)bx.psu.edu>
Date: 2014-09-10 (Wed, 10 Sep 2014)
Changed paths:
M stage/group_vars/pulsarservers.yml
M templates/galaxy/test.galaxyproject.org/config/job_conf.xml.j2
Log Message:
-----------
A few Pulsar fixes.
Compare: https://github.com/galaxyproject/usegalaxy-playbook/compare/adb284076c7c...…
1
0
[galaxyproject/usegalaxy-playbook] 6e84ae: Distribute integrated_tool_panel.xml
by GitHub 10 Sep '14
by GitHub 10 Sep '14
10 Sep '14
Branch: refs/heads/master
Home: https://github.com/galaxyproject/usegalaxy-playbook
Commit: 6e84aeb5fece00bcfa7e5e3df70a82da105d13e7
https://github.com/galaxyproject/usegalaxy-playbook/commit/6e84aeb5fece00bc…
Author: Nate Coraor <nate(a)bx.psu.edu>
Date: 2014-09-10 (Wed, 10 Sep 2014)
Changed paths:
M roles/usegalaxy/tasks/main.yml
Log Message:
-----------
Distribute integrated_tool_panel.xml
Commit: 50b76df7b812a6ce240dc8ff1f8e1536ead0a73e
https://github.com/galaxyproject/usegalaxy-playbook/commit/50b76df7b812a6ce…
Author: Nate Coraor <nate(a)bx.psu.edu>
Date: 2014-09-10 (Wed, 10 Sep 2014)
Changed paths:
M README.md
Log Message:
-----------
Notes on pulsar dependencies.
Commit: adb284076c7c626dc192fce7b02069a8965e4809
https://github.com/galaxyproject/usegalaxy-playbook/commit/adb284076c7c626d…
Author: Nate Coraor <nate(a)bx.psu.edu>
Date: 2014-09-10 (Wed, 10 Sep 2014)
Changed paths:
M files/galaxy/test.galaxyproject.org/var/shed_tool_conf.xml
M files/galaxy/test.galaxyproject.org/var/shed_tool_data_table_conf.xml
Log Message:
-----------
Install bamtools on Test.
Compare: https://github.com/galaxyproject/usegalaxy-playbook/compare/a0a3a459d10c...…
1
0
[galaxyproject/usegalaxy-playbook] 902e01: I accidentally a word in the downtime banner (than...
by GitHub 10 Sep '14
by GitHub 10 Sep '14
10 Sep '14
Branch: refs/heads/master
Home: https://github.com/galaxyproject/usegalaxy-playbook
Commit: 902e019be3c29da5d60ddfda43d036f6944f62b5
https://github.com/galaxyproject/usegalaxy-playbook/commit/902e019be3c29da5…
Author: Nate Coraor <nate(a)bx.psu.edu>
Date: 2014-09-10 (Wed, 10 Sep 2014)
Changed paths:
M production/group_vars/galaxyservers.yml
M stage/group_vars/galaxyservers.yml
Log Message:
-----------
I accidentally a word in the downtime banner (thanks @martenson).
Commit: a0a3a459d10ce80ebd380c25a8ac09d9958b7700
https://github.com/galaxyproject/usegalaxy-playbook/commit/a0a3a459d10ce80e…
Author: Nate Coraor <nate(a)bx.psu.edu>
Date: 2014-09-10 (Wed, 10 Sep 2014)
Changed paths:
M production/group_vars/all.yml
Log Message:
-----------
Upgrade Main
Compare: https://github.com/galaxyproject/usegalaxy-playbook/compare/4c1d5fce940b...…
1
0
Branch: refs/heads/master
Home: https://github.com/galaxyproject/usegalaxy-playbook
Commit: 4c1d5fce940b9d23dfc23f88291f5ed20fffaa6c
https://github.com/galaxyproject/usegalaxy-playbook/commit/4c1d5fce940b9d23…
Author: Nate Coraor <nate(a)bx.psu.edu>
Date: 2014-09-10 (Wed, 10 Sep 2014)
Changed paths:
M stage/group_vars/all.yml
Log Message:
-----------
Update Test.
1
0
commit/galaxy-central: natefoo: Fix references to config.ucsc_display_sites that I missed.
by commits-noreply@bitbucket.org 10 Sep '14
by commits-noreply@bitbucket.org 10 Sep '14
10 Sep '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/d1f6d05706d0/
Changeset: d1f6d05706d0
User: natefoo
Date: 2014-09-10 20:37:33
Summary: Fix references to config.ucsc_display_sites that I missed.
Affected #: 6 files
diff -r f68f8c8f147b863ec968475216cc9a72044a722b -r d1f6d05706d0f03c7a31cd5f8b3890c55e565af0 display_applications/ucsc/bam.xml
--- a/display_applications/ucsc/bam.xml
+++ b/display_applications/ucsc/bam.xml
@@ -6,7 +6,7 @@
<dynamic_param name="ucsc_link" value="1"/><dynamic_param name="builds" value="2" split="True" separator="," /><!-- Filter out some of the links based upon matching site_id to a Galaxy application configuration parameter and by dataset dbkey -->
- <filter>${site_id in $APP.config.ucsc_display_sites}</filter>
+ <filter>${site_id in $APP.datatypes_registry.get_display_sites('ucsc')}</filter><filter>${dataset.dbkey in $builds}</filter><!-- We define url and params as normal, but values defined in dynamic_param are available by specified name --><url>${ucsc_link}db=${qp($bam_file.dbkey)}&hgt.customText=${qp($track.url)}</url>
diff -r f68f8c8f147b863ec968475216cc9a72044a722b -r d1f6d05706d0f03c7a31cd5f8b3890c55e565af0 display_applications/ucsc/bigbed.xml
--- a/display_applications/ucsc/bigbed.xml
+++ b/display_applications/ucsc/bigbed.xml
@@ -6,7 +6,7 @@
<dynamic_param name="ucsc_link" value="1"/><dynamic_param name="builds" value="2" split="True" separator="," /><!-- Filter out some of the links based upon matching site_id to a Galaxy application configuration parameter and by dataset dbkey -->
- <filter>${site_id in $APP.config.ucsc_display_sites}</filter>
+ <filter>${site_id in $APP.datatypes_registry.get_display_sites('ucsc')}</filter><filter>${dataset.dbkey in $builds}</filter><!-- We define url and params as normal, but values defined in dynamic_param are available by specified name --><url>${ucsc_link}db=${qp($bigbed_file.dbkey)}&hgt.customText=${qp($track.url)}</url>
diff -r f68f8c8f147b863ec968475216cc9a72044a722b -r d1f6d05706d0f03c7a31cd5f8b3890c55e565af0 display_applications/ucsc/bigwig.xml
--- a/display_applications/ucsc/bigwig.xml
+++ b/display_applications/ucsc/bigwig.xml
@@ -6,7 +6,7 @@
<dynamic_param name="ucsc_link" value="1"/><dynamic_param name="builds" value="2" split="True" separator="," /><!-- Filter out some of the links based upon matching site_id to a Galaxy application configuration parameter and by dataset dbkey -->
- <filter>${site_id in $APP.config.ucsc_display_sites}</filter>
+ <filter>${site_id in $APP.datatypes_registry.get_display_sites('ucsc')}</filter><filter>${dataset.dbkey in $builds}</filter><!-- We define url and params as normal, but values defined in dynamic_param are available by specified name --><url>${ucsc_link}db=${qp($bigwig_file.dbkey)}&hgt.customText=${qp($track.url)}</url>
diff -r f68f8c8f147b863ec968475216cc9a72044a722b -r d1f6d05706d0f03c7a31cd5f8b3890c55e565af0 display_applications/ucsc/interval_as_bed.xml
--- a/display_applications/ucsc/interval_as_bed.xml
+++ b/display_applications/ucsc/interval_as_bed.xml
@@ -6,7 +6,7 @@
<dynamic_param name="ucsc_link" value="1"/><dynamic_param name="builds" value="2" split="True" separator="," /><!-- Filter out some of the links based upon matching site_id to a Galaxy application configuration parameter and by dataset dbkey -->
- <filter>${site_id in $APP.config.ucsc_display_sites}</filter>
+ <filter>${site_id in $APP.datatypes_registry.get_display_sites('ucsc')}</filter><filter>${dataset.dbkey in $builds}</filter><!-- We define url and params as normal, but values defined in dynamic_param are available by specified name --><url>${ucsc_link}db=${qp($bed_file.dbkey)}&position=${position.qp}&hgt.customText=${bed_file.qp}</url>
diff -r f68f8c8f147b863ec968475216cc9a72044a722b -r d1f6d05706d0f03c7a31cd5f8b3890c55e565af0 display_applications/ucsc/maf_customtrack.xml
--- a/display_applications/ucsc/maf_customtrack.xml
+++ b/display_applications/ucsc/maf_customtrack.xml
@@ -6,7 +6,7 @@
<dynamic_param name="ucsc_link" value="1"/><dynamic_param name="builds" value="2" split="True" separator="," /><!-- Filter out some of the links based upon matching site_id to a Galaxy application configuration parameter and by dataset dbkey -->
- <filter>${site_id in $APP.config.ucsc_display_sites}</filter>
+ <filter>${site_id in $APP.datatypes_registry.get_display_sites('ucsc')}</filter><filter>${dataset.dbkey in $builds}</filter><!-- We define url and params as normal, but values defined in dynamic_param are available by specified name --><url>${ucsc_link}db=${qp($maf_customtrack_file.dbkey)}&position=${maf_customtrack_file.metadata.vp_chromosome}:${maf_customtrack_file.metadata.vp_start}-${maf_customtrack_file.metadata.vp_end}&hgt.customText=${maf_customtrack_file.qp}</url>
diff -r f68f8c8f147b863ec968475216cc9a72044a722b -r d1f6d05706d0f03c7a31cd5f8b3890c55e565af0 display_applications/ucsc/vcf.xml
--- a/display_applications/ucsc/vcf.xml
+++ b/display_applications/ucsc/vcf.xml
@@ -6,7 +6,7 @@
<dynamic_param name="ucsc_link" value="1"/><dynamic_param name="builds" value="2" split="True" separator="," /><!-- Filter out some of the links based upon matching site_id to a Galaxy application configuration parameter and by dataset dbkey -->
- <filter>${site_id in $APP.config.ucsc_display_sites}</filter>
+ <filter>${site_id in $APP.datatypes_registry.get_display_sites('ucsc')}</filter><filter>${dataset.dbkey in $builds}</filter><!-- We define url and params as normal, but values defined in dynamic_param are available by specified name --><url>${ucsc_link}db=${qp($bgzip_file.dbkey)}&hgt.customText=${qp($track.url)}</url>
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
7 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/fa92c5497232/
Changeset: fa92c5497232
User: jmchilton
Date: 2014-09-10 17:51:10
Summary: Synchronize validation of workflows between web and API controllers.
Reduces code duplication and does more correct checking of workflow step replacement parameters. More parameter checking functional tests.
Affected #: 6 files
diff -r d85d039b8eeb2781619683f62dddf0f4c20af773 -r fa92c5497232444ade0e7044184fb8ccf419177c lib/galaxy/workflow/run.py
--- a/lib/galaxy/workflow/run.py
+++ b/lib/galaxy/workflow/run.py
@@ -231,10 +231,10 @@
# Build the state for each step
module_injector = modules.WorkflowModuleInjector( self.trans )
for step in self.workflow.steps:
- step_errors = module_injector.inject( step )
+ step_args = self.param_map.get( step.id, {} )
+ step_errors = module_injector.inject( step, step_args=step_args )
if step.type == 'tool' or step.type is None:
- _update_step_parameters( step, self.param_map )
- if step.tool_errors:
+ if step_errors:
message = "Workflow cannot be run because of validation errors in some steps: %s" % step_errors
raise exceptions.MessageException( message )
if step.upgrade_messages:
@@ -242,10 +242,4 @@
raise exceptions.MessageException( message )
-def _update_step_parameters(step, normalized_param_map):
- param_dict = normalized_param_map.get(step.id, {})
- if param_dict:
- step.state.inputs.update(param_dict)
-
-
__all__ = [ invoke, WorkflowRunConfig ]
diff -r d85d039b8eeb2781619683f62dddf0f4c20af773 -r fa92c5497232444ade0e7044184fb8ccf419177c test/api/helpers.py
--- a/test/api/helpers.py
+++ b/test/api/helpers.py
@@ -131,8 +131,9 @@
elif "dataset" in kwds:
dataset_id = kwds[ "dataset" ][ "id" ]
else:
+ hid = kwds.get( "hid", -1 ) # If not hid, just grab last dataset
dataset_contents = self.galaxy_interactor.get( contents_url ).json()
- dataset_id = dataset_contents[ -1 ][ "id" ]
+ dataset_id = dataset_contents[ hid ][ "id" ]
display_response = self.galaxy_interactor.get( "%s/%s/display" % ( contents_url, dataset_id ) )
assert display_response.status_code == 200
diff -r d85d039b8eeb2781619683f62dddf0f4c20af773 -r fa92c5497232444ade0e7044184fb8ccf419177c test/api/test_tools.py
--- a/test/api/test_tools.py
+++ b/test/api/test_tools.py
@@ -109,6 +109,15 @@
output1_content = self.dataset_populator.get_history_dataset_content( history_id, dataset=output1 )
self.assertEqual( output1_content.strip(), "Cat1Test" )
+ @skip_without_tool( "validation_default" )
+ def test_validation( self ):
+ history_id = self.dataset_populator.new_history()
+ inputs = {
+ 'select_param': "\" ; echo \"moo",
+ }
+ response = self._run( "validation_default", history_id, inputs )
+ self._assert_status_code_is( response, 400 )
+
@skip_without_tool( "cat1" )
def test_run_cat1_with_two_inputs( self ):
# Run tool with an multiple data parameter and grouping (repeat)
diff -r d85d039b8eeb2781619683f62dddf0f4c20af773 -r fa92c5497232444ade0e7044184fb8ccf419177c test/api/test_workflow_validation_1.ga
--- a/test/api/test_workflow_validation_1.ga
+++ b/test/api/test_workflow_validation_1.ga
@@ -23,7 +23,7 @@
"post_job_actions": {},
"tool_errors": null,
"tool_id": "validation_default",
- "tool_state": "{\"__page__\": 0, \"__rerun_remap_job_id__\": null, \"input1\": \"\\\"cow\\\"\", \"chromInfo\": \"\\\"/home/john/workspace/galaxy-central/tool-data/shared/ucsc/chrom/?.len\\\"\"}",
+ "tool_state": "{\"__page__\": 0, \"__rerun_remap_job_id__\": null, \"input1\": \"\\\"cow\\\"\", \"float_param\": \"8.0\", \"select_param\": \"\\\"opt1\\\"\", \"chromInfo\": \"\\\"/home/john/workspace/galaxy-central/tool-data/shared/ucsc/chrom/?.len\\\"\"}",
"tool_version": null,
"type": "tool",
"user_outputs": []
diff -r d85d039b8eeb2781619683f62dddf0f4c20af773 -r fa92c5497232444ade0e7044184fb8ccf419177c test/api/test_workflows.py
--- a/test/api/test_workflows.py
+++ b/test/api/test_workflows.py
@@ -480,18 +480,30 @@
@skip_without_tool( "validation_default" )
def test_parameter_substitution_validation( self ):
+ substitions = dict( input1="\" ; echo \"moo" )
+ run_workflow_response, history_id = self._run_validation_workflow_with_substitions( substitions )
+
+ self.dataset_populator.wait_for_history( history_id, assert_ok=True )
+ self.assertEquals("__dq__ X echo __dq__moo\n", self.dataset_populator.get_history_dataset_content( history_id, hid=1 ) )
+
+ @skip_without_tool( "validation_default" )
+ def test_parameter_substitution_validation_value_errors_1( self ):
+ substitions = dict( select_param="\" ; echo \"moo" )
+ run_workflow_response, history_id = self._run_validation_workflow_with_substitions( substitions )
+
+ self._assert_status_code_is( run_workflow_response, 400 )
+
+ def _run_validation_workflow_with_substitions( self, substitions ):
workflow = self.workflow_populator.load_workflow_from_resource( "test_workflow_validation_1" )
uploaded_workflow_id = self.workflow_populator.create_workflow( workflow )
history_id = self.dataset_populator.new_history()
workflow_request = dict(
history="hist_id=%s" % history_id,
workflow_id=uploaded_workflow_id,
- parameters=dumps( dict( validation_default=dict( input1="\" ; echo \"moo" ) ) )
+ parameters=dumps( dict( validation_default=substitions ) )
)
run_workflow_response = self._post( "workflows", data=workflow_request )
- self._assert_status_code_is( run_workflow_response, 200 )
- self.dataset_populator.wait_for_history( history_id, assert_ok=True )
- self.assertEquals("__dq__ X echo __dq__moo\n", self.dataset_populator.get_history_dataset_content( history_id ) )
+ return run_workflow_response, history_id
@skip_without_tool( "random_lines1" )
def test_run_replace_params_by_steps( self ):
diff -r d85d039b8eeb2781619683f62dddf0f4c20af773 -r fa92c5497232444ade0e7044184fb8ccf419177c test/functional/tools/validation_default.xml
--- a/test/functional/tools/validation_default.xml
+++ b/test/functional/tools/validation_default.xml
@@ -1,16 +1,27 @@
<tool id="validation_default" name="Validation (default)"><command>
echo "$input1" > out1;
+ echo $float_param > out2;
+ echo $select_param > out3;
</command><inputs>
- <param name="input1" type="text" label="Concatenate Dataset" />
+ <param name="input1" type="text" label="text input" />
+ <param name="float_param" type="float" label="float input" value="8.0" />
+ <param name="select_param" type="select" label="select_param">
+ <option value="opt1">Option 1</option>
+ <option value="opt2">Option 2</option>
+ </param></inputs><outputs><data name="out_file1" from_work_dir="out1" />
+ <data name="out_file2" from_work_dir="out2" />
+ <data name="out_file3" from_work_dir="out3" /></outputs><tests><test><param name="input1" value="" ; echo "moo" />
+ <param name="float_param" value="5" />
+ <param name="select_param" value="opt1" /><output name="out_file1"><assert_contents><has_line line="__dq__ X echo __dq__moo" />
https://bitbucket.org/galaxy/galaxy-central/commits/144af99ca953/
Changeset: 144af99ca953
User: jmchilton
Date: 2014-09-10 17:51:10
Summary: More workflow module commenting.
This time add small comment about config form method.
Affected #: 1 file
diff -r fa92c5497232444ade0e7044184fb8ccf419177c -r 144af99ca9536f5924fae66c8fb372f150599f73 lib/galaxy/workflow/modules.py
--- a/lib/galaxy/workflow/modules.py
+++ b/lib/galaxy/workflow/modules.py
@@ -96,6 +96,9 @@
pass
def get_config_form( self ):
+ """ Render form that is embedded in workflow editor for modifying the
+ step state of a node.
+ """
raise TypeError( "Abstract method" )
def check_and_update_state( self ):
https://bitbucket.org/galaxy/galaxy-central/commits/51799404c770/
Changeset: 51799404c770
User: jmchilton
Date: 2014-09-10 17:51:10
Summary: Unify runtime state handling methods across tool and input modules.
The abstract interface WorkflowModule declared three methods that WorkflowToolModule didn't implement and logic for updating tool state wasn't restricted to the module itself. This introduces a new compute_state method that unifies all of that and includes some documentation.
In addition to simplifing the interface new modules must adhere to, this allows eliminating the switch on module type when injecting trasient state attribute into steps - moving that logic into the module itself. In my opinion this makes WorkflowModule closer to being an abstract interface - allowing components to uniformly reason about workflow modules as a black box (and not dispatch on type attributes).
These changes did require adding add_dummy_datasets to the base class - and while the input modules don't need to utilize the ability to override this - my pause module downstream did so I think it makes sense to place on the interface.
Affected #: 1 file
diff -r 144af99ca9536f5924fae66c8fb372f150599f73 -r 51799404c770249f71ffd540c352011509f01329 lib/galaxy/workflow/modules.py
--- a/lib/galaxy/workflow/modules.py
+++ b/lib/galaxy/workflow/modules.py
@@ -108,14 +108,15 @@
"""
pass
+ def add_dummy_datasets( self, connections=None):
+ # Replaced connected inputs with DummyDataset values.
+ pass
+
## ---- Run time ---------------------------------------------------------
def get_runtime_inputs( self ):
raise TypeError( "Abstract method" )
- def get_runtime_state( self ):
- raise TypeError( "Abstract method" )
-
def encode_runtime_state( self, trans, state ):
""" Encode the runtime state (loaded from the stored step and
populated via the WorkflowModuleInjector below) for use in a hidden
@@ -127,10 +128,16 @@
"""
raise TypeError( "Abstract method" )
- def decode_runtime_state( self, trans, string ):
- raise TypeError( "Abstract method" )
+ def compute_state( self, trans, step_updates=None ):
+ """ Recover the transient "state" attribute to populate corresponding
+ step with (currently this is always a DefaultToolState instance,
+ though I am not sure this is strictly nessecary).
- def update_runtime_state( self, trans, state, values ):
+ If `step_updates` is `None`, this is likely for rendering the run form
+ for instance and no runtime properties are available and state must be
+ solely determined by step. If `step_updates` are available they describe
+ the runtime properties supplied by the workflow runner.
+ """
raise TypeError( "Abstract method" )
def execute( self, trans, state ):
@@ -211,6 +218,17 @@
errors[ name ] = error
return errors
+ def compute_state( self, trans, step_updates=None ):
+ if step_updates:
+ # Fix this for multiple inputs
+ state = self.decode_runtime_state( trans, step_updates.pop( "tool_state" ) )
+ step_errors = self.update_runtime_state( trans, state, step_updates )
+ else:
+ state = self.get_runtime_state()
+ step_errors = {}
+
+ return state, step_errors
+
def execute( self, trans, state ):
return None, dict( output=state.inputs['input'])
@@ -509,6 +527,21 @@
def check_and_update_state( self ):
return self.tool.check_and_update_param_values( self.state.inputs, self.trans, allow_workflow_parameters=True )
+ def compute_state( self, trans, step_updates=None ):
+ # Warning: This method destructively modifies existing step state.
+ step_errors = None
+ state = self.state
+ if step_updates:
+ # Get the tool
+ tool = self.tool
+ # Get old errors
+ old_errors = state.inputs.pop( "__errors__", {} )
+ # Update the state
+ step_errors = tool.update_state( trans, tool.inputs, state.inputs, step_updates,
+ update_only=True, old_errors=old_errors )
+ else:
+ return state, step_errors
+
def add_dummy_datasets( self, connections=None):
if connections:
# Store onnections by input name
@@ -619,36 +652,19 @@
module = step.module = module_factory.from_workflow_step( trans, step )
# Calculating step errors and state depends on whether step is a tool step or not.
- if step.type == 'tool' or step.type is None:
- if not module:
- step.module = None
- step.state = None
- raise MissingToolException()
+ if not module:
+ step.module = None
+ step.state = None
+ raise MissingToolException()
- # Fix any missing parameters
- step.upgrade_messages = module.check_and_update_state()
+ # Fix any missing parameters
+ step.upgrade_messages = module.check_and_update_state()
- # Any connected input needs to have value DummyDataset (these
- # are not persisted so we need to do it every time)
- module.add_dummy_datasets( connections=step.input_connections )
+ # Any connected input needs to have value DummyDataset (these
+ # are not persisted so we need to do it every time)
+ module.add_dummy_datasets( connections=step.input_connections )
- state = module.state
- step.state = state
- if step_args is not None:
- # Get the tool
- tool = module.tool
- # Get old errors
- old_errors = state.inputs.pop( "__errors__", {} )
- # Update the state
- step_errors = tool.update_state( trans, tool.inputs, step.state.inputs, step_args,
- update_only=True, old_errors=old_errors )
-
- else:
- if step_args:
- # Fix this for multiple inputs
- state = step.state = module.decode_runtime_state( trans, step_args.pop( "tool_state" ) )
- step_errors = module.update_runtime_state( trans, state, step_args )
- else:
- step.state = step.module.get_runtime_state()
+ state, step_errors = module.compute_state( trans, step_args )
+ step.state = state
return step_errors
https://bitbucket.org/galaxy/galaxy-central/commits/952e1f153a2d/
Changeset: 952e1f153a2d
User: jmchilton
Date: 2014-09-10 17:51:10
Summary: Remove some old commented out client-side stuff.
(Let me know if these were important.)
Affected #: 1 file
diff -r 51799404c770249f71ffd540c352011509f01329 -r 952e1f153a2d71673d71952f990f3e5b67495505 templates/webapps/galaxy/workflow/editor.mako
--- a/templates/webapps/galaxy/workflow/editor.mako
+++ b/templates/webapps/galaxy/workflow/editor.mako
@@ -7,16 +7,6 @@
%></%def>
-## <%def name="late_javascripts()">
-## <script type='text/javascript' src="${h.url_for('/static/scripts/galaxy.panels.js')}"></script>
-## <script type="text/javascript">
-## ensure_dd_helper();
-## make_left_panel( $("#left"), $("#center"), $("#left-border" ) );
-## make_right_panel( $("#right"), $("#center"), $("#right-border" ) );
-## ## handle_minwidth_hint = rp.handle_minwidth_hint;
-## </script>
-## </%def>
-
<%def name="javascripts()">
${parent.javascripts()}
@@ -87,18 +77,6 @@
<style type="text/css">
body { margin: 0; padding: 0; overflow: hidden; }
- /* Wider right panel */
- ## #center { right: 309px; }
- ## #right-border { right: 300px; }
- ## #right { width: 300px; }
- ## /* Relative masthead size */
- ## #masthead { height: 2.5em; }
- ## #masthead div.title { font-size: 1.8em; }
- ## #left, #left-border, #center, #right-border, #right {
- ## top: 2.5em;
- ## margin-top: 7px;
- ## }
-
#left {
background: #C1C9E5 url(${h.url_for('/static/style/menu_bg.png')}) top repeat-x;
}
https://bitbucket.org/galaxy/galaxy-central/commits/3656bf3ec7c4/
Changeset: 3656bf3ec7c4
User: jmchilton
Date: 2014-09-10 17:51:10
Summary: Refactor logic for tracking workflow progress out of WorkflowInvoker.
Creates a new class WorkflowProgress. This has class achives two objectives:
- I am trying to move specialized per-module-type logic out of WorkflowInvoker and into the modules themselves - making it easier to add new modules and because it is better OOP design (invoker shouldn't be dispatching on .type - the modules should provide a consistent interface for invoking themselves). WorkflowProgress will give something that WorkflowInvoker can pass along to the modules to allow them to find their connections and record their outputs.
- Downstream in workflow scheduling branch I am placing logic in here for rebuilding the in-memory state of the workflow progress when re-evaluating progress.
Affected #: 3 files
diff -r 952e1f153a2d71673d71952f990f3e5b67495505 -r 3656bf3ec7c487b8635ceb20de1ae5fe8f2e4f87 lib/galaxy/webapps/galaxy/api/workflows.py
--- a/lib/galaxy/webapps/galaxy/api/workflows.py
+++ b/lib/galaxy/webapps/galaxy/api/workflows.py
@@ -228,6 +228,7 @@
trans=trans,
workflow=workflow,
workflow_run_config=run_config,
+ populate_state=True,
)
trans.sa_session.flush()
diff -r 952e1f153a2d71673d71952f990f3e5b67495505 -r 3656bf3ec7c487b8635ceb20de1ae5fe8f2e4f87 lib/galaxy/workflow/modules.py
--- a/lib/galaxy/workflow/modules.py
+++ b/lib/galaxy/workflow/modules.py
@@ -11,6 +11,7 @@
from elementtree.ElementTree import Element
import galaxy.tools
+from galaxy import exceptions
from galaxy.web.framework import formbuilder
from galaxy.jobs.actions.post import ActionBox
from galaxy.model import PostJobAction
@@ -668,3 +669,20 @@
step.state = state
return step_errors
+
+
+def populate_module_and_state( trans, workflow, param_map ):
+ """ Used by API but not web controller, walks through a workflow's steps
+ and populates transient module and state attributes on each.
+ """
+ module_injector = WorkflowModuleInjector( trans )
+ for step in workflow.steps:
+ step_args = param_map.get( step.id, {} )
+ step_errors = module_injector.inject( step, step_args=step_args )
+ if step.type == 'tool' or step.type is None:
+ if step_errors:
+ message = "Workflow cannot be run because of validation errors in some steps: %s" % step_errors
+ raise exceptions.MessageException( message )
+ if step.upgrade_messages:
+ message = "Workflow cannot be run because of step upgrade messages: %s" % step.upgrade_messages
+ raise exceptions.MessageException( message )
diff -r 952e1f153a2d71673d71952f990f3e5b67495505 -r 3656bf3ec7c487b8635ceb20de1ae5fe8f2e4f87 lib/galaxy/workflow/run.py
--- a/lib/galaxy/workflow/run.py
+++ b/lib/galaxy/workflow/run.py
@@ -21,9 +21,12 @@
log = logging.getLogger( __name__ )
-def invoke( trans, workflow, workflow_run_config ):
+def invoke( trans, workflow, workflow_run_config, populate_state=False ):
""" Run the supplied workflow in the supplied target_history.
"""
+ if populate_state:
+ modules.populate_module_and_state( trans, workflow, workflow_run_config.param_map )
+
return WorkflowInvoker(
trans,
workflow,
@@ -36,29 +39,21 @@
def __init__( self, trans, workflow, workflow_run_config ):
self.trans = trans
self.workflow = workflow
+ workflow_invocation = model.WorkflowInvocation()
+ workflow_invocation.workflow = self.workflow
+ self.workflow_invocation = workflow_invocation
self.target_history = workflow_run_config.target_history
self.replacement_dict = workflow_run_config.replacement_dict
self.copy_inputs_to_history = workflow_run_config.copy_inputs_to_history
- self.inputs_by_step_id = workflow_run_config.inputs
- self.param_map = workflow_run_config.param_map
+ self.progress = WorkflowProgress( self.workflow_invocation, workflow_run_config.inputs )
- self.outputs = odict()
# TODO: Attach to actual model object and persist someday...
self.invocation_uuid = uuid.uuid1().hex
def invoke( self ):
- workflow_invocation = model.WorkflowInvocation()
- workflow_invocation.workflow = self.workflow
-
- # Web controller will populate state on each step before calling
- # invoke but not API controller. More work should be done to further
- # harmonize these methods going forward if possible - if possible
- # moving more web controller logic here.
- state_populated = not self.workflow.steps or hasattr( self.workflow.steps[ 0 ], "state" )
- if not state_populated:
- self._populate_state( )
-
- for step in self.workflow.steps:
+ workflow_invocation = self.workflow_invocation
+ remaining_steps = self.progress.remaining_steps()
+ for step in remaining_steps:
jobs = self._invoke_step( step )
for job in util.listify( jobs ):
# Record invocation
@@ -72,7 +67,7 @@
# Not flushing in here, because web controller may create multiple
# invocations.
- return self.outputs
+ return self.progress.outputs
def _invoke_step( self, step ):
if step.type == 'tool' or step.type is None:
@@ -84,7 +79,6 @@
def _execute_tool_step( self, step ):
trans = self.trans
- outputs = self.outputs
tool = trans.app.toolbox.get_tool( step.tool_id )
tool_state = step.state
@@ -119,7 +113,7 @@
# If collection - just use element model object.
replacement = iteration_elements[ prefixed_name ]
else:
- replacement = self._replacement_for_input( input, prefixed_name, step )
+ replacement = self.progress.replacement_for_tool_input( step, input, prefixed_name )
return replacement
try:
# Replace DummyDatasets with historydatasetassociations
@@ -139,10 +133,11 @@
workflow_invocation_uuid=self.invocation_uuid
)
if collection_info:
- outputs[ step.id ] = dict( execution_tracker.created_collections )
+ step_outputs = dict( execution_tracker.created_collections )
+
else:
- outputs[ step.id ] = dict( execution_tracker.output_datasets )
-
+ step_outputs = dict( execution_tracker.output_datasets )
+ self.progress.set_step_outputs( step, step_outputs )
jobs = execution_tracker.successful_jobs
for job in jobs:
self._handle_post_job_actions( step, job )
@@ -154,13 +149,13 @@
def callback( input, value, prefixed_name, prefixed_label ):
is_data_param = isinstance( input, DataToolParameter )
if is_data_param and not input.multiple:
- data = self._replacement_for_input( input, prefixed_name, step )
+ data = self.progress.replacement_for_tool_input( step, input, prefixed_name )
if isinstance( data, model.HistoryDatasetCollectionAssociation ):
collections_to_match.add( prefixed_name, data )
is_data_collection_param = isinstance( input, DataCollectionToolParameter )
if is_data_collection_param and not input.multiple:
- data = self._replacement_for_input( input, prefixed_name, step )
+ data = self.progress.replacement_for_tool_input( step, input, prefixed_name )
history_query = input._history_query( self.trans )
if history_query.can_map_over( data ):
collections_to_match.add( prefixed_name, data, subcollection_type=input.collection_type )
@@ -170,29 +165,25 @@
def _execute_input_step( self, step ):
trans = self.trans
- outputs = self.outputs
- job, out_data = step.module.execute( trans, step.state )
- outputs[ step.id ] = out_data
+ job, step_outputs = step.module.execute( trans, step.state )
# Web controller may set copy_inputs_to_history, API controller always sets
# inputs.
if self.copy_inputs_to_history:
- for input_dataset_hda in out_data.values():
+ for input_dataset_hda in step_outputs.values():
content_type = input_dataset_hda.history_content_type
if content_type == "dataset":
new_hda = input_dataset_hda.copy( copy_children=True )
self.target_history.add_dataset( new_hda )
- outputs[ step.id ][ 'input_ds_copy' ] = new_hda
+ step_outputs[ 'input_ds_copy' ] = new_hda
elif content_type == "dataset_collection":
new_hdca = input_dataset_hda.copy()
self.target_history.add_dataset_collection( new_hdca )
- outputs[ step.id ][ 'input_ds_copy' ] = new_hdca
+ step_outputs[ 'input_ds_copy' ] = new_hdca
else:
raise Exception("Unknown history content encountered")
- if self.inputs_by_step_id:
- outputs[ step.id ][ 'output' ] = self.inputs_by_step_id[ step.id ]
-
+ self.progress.set_outputs_for_input( step, step_outputs )
return job
def _handle_post_job_actions( self, step, job ):
@@ -205,7 +196,20 @@
else:
job.add_post_job_action( pja )
- def _replacement_for_input( self, input, prefixed_name, step ):
+
+class WorkflowProgress( object ):
+
+ def __init__( self, workflow_invocation, inputs_by_step_id ):
+ self.outputs = odict()
+ self.workflow_invocation = workflow_invocation
+ self.inputs_by_step_id = inputs_by_step_id
+
+ def remaining_steps(self):
+ steps = self.workflow_invocation.workflow.steps
+
+ return steps
+
+ def replacement_for_tool_input( self, step, input, prefixed_name ):
""" For given workflow 'step' that has had input_connections_by_name
populated fetch the actual runtime input for the given tool 'input'.
"""
@@ -213,7 +217,7 @@
if prefixed_name in step.input_connections_by_name:
connection = step.input_connections_by_name[ prefixed_name ]
if input.multiple:
- replacement = [ self._replacement_for_connection( c ) for c in connection ]
+ replacement = [ self.replacement_for_connection( c ) for c in connection ]
# If replacement is just one dataset collection, replace tool
# input with dataset collection - tool framework will extract
# datasets properly.
@@ -221,25 +225,21 @@
if isinstance( replacement[ 0 ], model.HistoryDatasetCollectionAssociation ):
replacement = replacement[ 0 ]
else:
- replacement = self._replacement_for_connection( connection[ 0 ] )
+ replacement = self.replacement_for_connection( connection[ 0 ] )
return replacement
- def _replacement_for_connection( self, connection ):
- return self.outputs[ connection.output_step.id ][ connection.output_name ]
+ def replacement_for_connection( self, connection ):
+ step_outputs = self.outputs[ connection.output_step.id ]
+ return step_outputs[ connection.output_name ]
- def _populate_state( self ):
- # Build the state for each step
- module_injector = modules.WorkflowModuleInjector( self.trans )
- for step in self.workflow.steps:
- step_args = self.param_map.get( step.id, {} )
- step_errors = module_injector.inject( step, step_args=step_args )
- if step.type == 'tool' or step.type is None:
- if step_errors:
- message = "Workflow cannot be run because of validation errors in some steps: %s" % step_errors
- raise exceptions.MessageException( message )
- if step.upgrade_messages:
- message = "Workflow cannot be run because of step upgrade messages: %s" % step.upgrade_messages
- raise exceptions.MessageException( message )
+ def set_outputs_for_input( self, step, outputs={} ):
+ if self.inputs_by_step_id:
+ outputs[ 'output' ] = self.inputs_by_step_id[ step.id ]
+
+ self.set_step_outputs( step, outputs )
+
+ def set_step_outputs(self, step, outputs):
+ self.outputs[ step.id ] = outputs
__all__ = [ invoke, WorkflowRunConfig ]
https://bitbucket.org/galaxy/galaxy-central/commits/bbe9be042b34/
Changeset: bbe9be042b34
User: jmchilton
Date: 2014-09-10 17:51:10
Summary: Unify execute method across tool and input workflow modules.
Previously tool module class did not contain this method (though it was abstract in the base class) and extra logic for dealing with tools was located outside of the module itself. Moving everything into the module (made possible by previously committed WorkflowProgress class and attaching some properties to workflow invocations and sending them in) means that now the worklfow invocation logic can uniformly deal with modules and doesn't need to dispatch on type. This should allow extending the capabilities of the workflow invoker and adding new modules independently.
Affected #: 2 files
diff -r 3656bf3ec7c487b8635ceb20de1ae5fe8f2e4f87 -r bbe9be042b34268c649b42c8c85d238149e910f0 lib/galaxy/workflow/modules.py
--- a/lib/galaxy/workflow/modules.py
+++ b/lib/galaxy/workflow/modules.py
@@ -12,11 +12,15 @@
import galaxy.tools
from galaxy import exceptions
+from galaxy import model
+from galaxy.dataset_collections import matching
from galaxy.web.framework import formbuilder
from galaxy.jobs.actions.post import ActionBox
from galaxy.model import PostJobAction
from galaxy.tools.parameters import check_param, DataToolParameter, DummyDataset, RuntimeValue, visit_input_values
from galaxy.tools.parameters import DataCollectionToolParameter
+from galaxy.tools.parameters.wrapped import make_dict_copy
+from galaxy.tools.execute import execute
from galaxy.util.bunch import Bunch
from galaxy.util import odict
from galaxy.util.json import loads
@@ -141,7 +145,11 @@
"""
raise TypeError( "Abstract method" )
- def execute( self, trans, state ):
+ def execute( self, trans, progress, invocation, step ):
+ """ Execute the given workflow step in the given workflow invocation.
+ Use the supplied workflow progress object to track outputs, find
+ inputs, etc...
+ """
raise TypeError( "Abstract method" )
@@ -230,8 +238,26 @@
return state, step_errors
- def execute( self, trans, state ):
- return None, dict( output=state.inputs['input'])
+ def execute( self, trans, progress, invocation, step ):
+ job, step_outputs = None, dict( output=step.state.inputs['input'])
+
+ # Web controller may set copy_inputs_to_history, API controller always sets
+ # inputs.
+ if invocation.copy_inputs_to_history:
+ for input_dataset_hda in step_outputs.values():
+ content_type = input_dataset_hda.history_content_type
+ if content_type == "dataset":
+ new_hda = input_dataset_hda.copy( copy_children=True )
+ invocation.history.add_dataset( new_hda )
+ step_outputs[ 'input_ds_copy' ] = new_hda
+ elif content_type == "dataset_collection":
+ new_hdca = input_dataset_hda.copy()
+ invocation.history.add_dataset_collection( new_hdca )
+ step_outputs[ 'input_ds_copy' ] = new_hdca
+ else:
+ raise Exception("Unknown history content encountered")
+ progress.set_outputs_for_input( step, step_outputs )
+ return job
class InputDataModule( InputModule ):
@@ -540,8 +566,100 @@
# Update the state
step_errors = tool.update_state( trans, tool.inputs, state.inputs, step_updates,
update_only=True, old_errors=old_errors )
+ return state, step_errors
+
+ def execute( self, trans, progress, invocation, step ):
+ tool = trans.app.toolbox.get_tool( step.tool_id )
+ tool_state = step.state
+
+ collections_to_match = self._find_collections_to_match( tool, progress, step )
+ # Have implicit collections...
+ if collections_to_match.has_collections():
+ collection_info = self.trans.app.dataset_collections_service.match_collections( collections_to_match )
else:
- return state, step_errors
+ collection_info = None
+
+ param_combinations = []
+ if collection_info:
+ iteration_elements_iter = collection_info.slice_collections()
+ else:
+ iteration_elements_iter = [ None ]
+
+ for iteration_elements in iteration_elements_iter:
+ execution_state = tool_state.copy()
+ # TODO: Move next step into copy()
+ execution_state.inputs = make_dict_copy( execution_state.inputs )
+
+ # Connect up
+ def callback( input, value, prefixed_name, prefixed_label ):
+ replacement = None
+ if isinstance( input, DataToolParameter ) or isinstance( input, DataCollectionToolParameter ):
+ if iteration_elements and prefixed_name in iteration_elements:
+ if isinstance( input, DataToolParameter ):
+ # Pull out dataset instance from element.
+ replacement = iteration_elements[ prefixed_name ].dataset_instance
+ else:
+ # If collection - just use element model object.
+ replacement = iteration_elements[ prefixed_name ]
+ else:
+ replacement = progress.replacement_for_tool_input( step, input, prefixed_name )
+ return replacement
+ try:
+ # Replace DummyDatasets with historydatasetassociations
+ visit_input_values( tool.inputs, execution_state.inputs, callback )
+ except KeyError, k:
+ message_template = "Error due to input mapping of '%s' in '%s'. A common cause of this is conditional outputs that cannot be determined until runtime, please review your workflow."
+ message = message_template % (tool.name, k.message)
+ raise exceptions.MessageException( message )
+ param_combinations.append( execution_state.inputs )
+
+ execution_tracker = execute(
+ trans=self.trans,
+ tool=tool,
+ param_combinations=param_combinations,
+ history=invocation.history,
+ collection_info=collection_info,
+ workflow_invocation_uuid=invocation.uuid
+ )
+ if collection_info:
+ step_outputs = dict( execution_tracker.created_collections )
+ else:
+ step_outputs = dict( execution_tracker.output_datasets )
+ progress.set_step_outputs( step, step_outputs )
+ jobs = execution_tracker.successful_jobs
+ for job in jobs:
+ self._handle_post_job_actions( step, job, invocation.replacement_dict )
+ return jobs
+
+ def _find_collections_to_match( self, tool, progress, step ):
+ collections_to_match = matching.CollectionsToMatch()
+
+ def callback( input, value, prefixed_name, prefixed_label ):
+ is_data_param = isinstance( input, DataToolParameter )
+ if is_data_param and not input.multiple:
+ data = progress.replacement_for_tool_input( step, input, prefixed_name )
+ if isinstance( data, model.HistoryDatasetCollectionAssociation ):
+ collections_to_match.add( prefixed_name, data )
+
+ is_data_collection_param = isinstance( input, DataCollectionToolParameter )
+ if is_data_collection_param and not input.multiple:
+ data = progress.replacement_for_tool_input( step, input, prefixed_name )
+ history_query = input._history_query( self.trans )
+ if history_query.can_map_over( data ):
+ collections_to_match.add( prefixed_name, data, subcollection_type=input.collection_type )
+
+ visit_input_values( tool.inputs, step.state.inputs, callback )
+ return collections_to_match
+
+ def _handle_post_job_actions( self, step, job, replacement_dict ):
+ # Create new PJA associations with the created job, to be run on completion.
+ # PJA Parameter Replacement (only applies to immediate actions-- rename specifically, for now)
+ # Pass along replacement dict with the execution of the PJA so we don't have to modify the object.
+ for pja in step.post_job_actions:
+ if pja.action_type in ActionBox.immediate_actions:
+ ActionBox.execute( self.trans.app, self.trans.sa_session, pja, job, replacement_dict )
+ else:
+ job.add_post_job_action( pja )
def add_dummy_datasets( self, connections=None):
if connections:
diff -r 3656bf3ec7c487b8635ceb20de1ae5fe8f2e4f87 -r bbe9be042b34268c649b42c8c85d238149e910f0 lib/galaxy/workflow/run.py
--- a/lib/galaxy/workflow/run.py
+++ b/lib/galaxy/workflow/run.py
@@ -1,18 +1,8 @@
import uuid
from galaxy import model
-from galaxy import exceptions
from galaxy import util
-from galaxy.dataset_collections import matching
-
-from galaxy.jobs.actions.post import ActionBox
-
-from galaxy.tools.parameters.basic import DataToolParameter
-from galaxy.tools.parameters.basic import DataCollectionToolParameter
-from galaxy.tools.parameters import visit_input_values
-from galaxy.tools.parameters.wrapped import make_dict_copy
-from galaxy.tools.execute import execute
from galaxy.util.odict import odict
from galaxy.workflow import modules
from galaxy.workflow.run_request import WorkflowRunConfig
@@ -42,13 +32,16 @@
workflow_invocation = model.WorkflowInvocation()
workflow_invocation.workflow = self.workflow
self.workflow_invocation = workflow_invocation
- self.target_history = workflow_run_config.target_history
- self.replacement_dict = workflow_run_config.replacement_dict
- self.copy_inputs_to_history = workflow_run_config.copy_inputs_to_history
self.progress = WorkflowProgress( self.workflow_invocation, workflow_run_config.inputs )
- # TODO: Attach to actual model object and persist someday...
- self.invocation_uuid = uuid.uuid1().hex
+ invocation_uuid = uuid.uuid1().hex
+
+ # In one way or another, following attributes will become persistent
+ # so they are available during delayed/revisited workflow scheduling.
+ self.workflow_invocation.uuid = invocation_uuid
+ self.workflow_invocation.history = workflow_run_config.target_history
+ self.workflow_invocation.copy_inputs_to_history = workflow_run_config.copy_inputs_to_history
+ self.workflow_invocation.replacement_dict = workflow_run_config.replacement_dict
def invoke( self ):
workflow_invocation = self.workflow_invocation
@@ -70,132 +63,9 @@
return self.progress.outputs
def _invoke_step( self, step ):
- if step.type == 'tool' or step.type is None:
- jobs = self._execute_tool_step( step )
- else:
- jobs = self._execute_input_step( step )
-
+ jobs = step.module.execute( self.trans, self.progress, self.workflow_invocation, step )
return jobs
- def _execute_tool_step( self, step ):
- trans = self.trans
-
- tool = trans.app.toolbox.get_tool( step.tool_id )
- tool_state = step.state
-
- collections_to_match = self._find_collections_to_match( tool, step )
- # Have implicit collections...
- if collections_to_match.has_collections():
- collection_info = self.trans.app.dataset_collections_service.match_collections( collections_to_match )
- else:
- collection_info = None
-
- param_combinations = []
- if collection_info:
- iteration_elements_iter = collection_info.slice_collections()
- else:
- iteration_elements_iter = [ None ]
-
- for iteration_elements in iteration_elements_iter:
- execution_state = tool_state.copy()
- # TODO: Move next step into copy()
- execution_state.inputs = make_dict_copy( execution_state.inputs )
-
- # Connect up
- def callback( input, value, prefixed_name, prefixed_label ):
- replacement = None
- if isinstance( input, DataToolParameter ) or isinstance( input, DataCollectionToolParameter ):
- if iteration_elements and prefixed_name in iteration_elements:
- if isinstance( input, DataToolParameter ):
- # Pull out dataset instance from element.
- replacement = iteration_elements[ prefixed_name ].dataset_instance
- else:
- # If collection - just use element model object.
- replacement = iteration_elements[ prefixed_name ]
- else:
- replacement = self.progress.replacement_for_tool_input( step, input, prefixed_name )
- return replacement
- try:
- # Replace DummyDatasets with historydatasetassociations
- visit_input_values( tool.inputs, execution_state.inputs, callback )
- except KeyError, k:
- message_template = "Error due to input mapping of '%s' in '%s'. A common cause of this is conditional outputs that cannot be determined until runtime, please review your workflow."
- message = message_template % (tool.name, k.message)
- raise exceptions.MessageException( message )
- param_combinations.append( execution_state.inputs )
-
- execution_tracker = execute(
- trans=self.trans,
- tool=tool,
- param_combinations=param_combinations,
- history=self.target_history,
- collection_info=collection_info,
- workflow_invocation_uuid=self.invocation_uuid
- )
- if collection_info:
- step_outputs = dict( execution_tracker.created_collections )
-
- else:
- step_outputs = dict( execution_tracker.output_datasets )
- self.progress.set_step_outputs( step, step_outputs )
- jobs = execution_tracker.successful_jobs
- for job in jobs:
- self._handle_post_job_actions( step, job )
- return jobs
-
- def _find_collections_to_match( self, tool, step ):
- collections_to_match = matching.CollectionsToMatch()
-
- def callback( input, value, prefixed_name, prefixed_label ):
- is_data_param = isinstance( input, DataToolParameter )
- if is_data_param and not input.multiple:
- data = self.progress.replacement_for_tool_input( step, input, prefixed_name )
- if isinstance( data, model.HistoryDatasetCollectionAssociation ):
- collections_to_match.add( prefixed_name, data )
-
- is_data_collection_param = isinstance( input, DataCollectionToolParameter )
- if is_data_collection_param and not input.multiple:
- data = self.progress.replacement_for_tool_input( step, input, prefixed_name )
- history_query = input._history_query( self.trans )
- if history_query.can_map_over( data ):
- collections_to_match.add( prefixed_name, data, subcollection_type=input.collection_type )
-
- visit_input_values( tool.inputs, step.state.inputs, callback )
- return collections_to_match
-
- def _execute_input_step( self, step ):
- trans = self.trans
-
- job, step_outputs = step.module.execute( trans, step.state )
-
- # Web controller may set copy_inputs_to_history, API controller always sets
- # inputs.
- if self.copy_inputs_to_history:
- for input_dataset_hda in step_outputs.values():
- content_type = input_dataset_hda.history_content_type
- if content_type == "dataset":
- new_hda = input_dataset_hda.copy( copy_children=True )
- self.target_history.add_dataset( new_hda )
- step_outputs[ 'input_ds_copy' ] = new_hda
- elif content_type == "dataset_collection":
- new_hdca = input_dataset_hda.copy()
- self.target_history.add_dataset_collection( new_hdca )
- step_outputs[ 'input_ds_copy' ] = new_hdca
- else:
- raise Exception("Unknown history content encountered")
- self.progress.set_outputs_for_input( step, step_outputs )
- return job
-
- def _handle_post_job_actions( self, step, job ):
- # Create new PJA associations with the created job, to be run on completion.
- # PJA Parameter Replacement (only applies to immediate actions-- rename specifically, for now)
- # Pass along replacement dict with the execution of the PJA so we don't have to modify the object.
- for pja in step.post_job_actions:
- if pja.action_type in ActionBox.immediate_actions:
- ActionBox.execute( self.trans.app, self.trans.sa_session, pja, job, self.replacement_dict )
- else:
- job.add_post_job_action( pja )
-
class WorkflowProgress( object ):
https://bitbucket.org/galaxy/galaxy-central/commits/f68f8c8f147b/
Changeset: f68f8c8f147b
User: jmchilton
Date: 2014-09-10 17:51:10
Summary: API functional test for workflow 'replacement_params' and PJA renaming.
Affected #: 2 files
diff -r bbe9be042b34268c649b42c8c85d238149e910f0 -r f68f8c8f147b863ec968475216cc9a72044a722b test/api/helpers.py
--- a/test/api/helpers.py
+++ b/test/api/helpers.py
@@ -120,24 +120,38 @@
return tool_response.json()
def get_history_dataset_content( self, history_id, wait=True, **kwds ):
+ dataset_id = self.__history_dataset_id( history_id, wait=wait, **kwds )
+ display_response = self.__get_contents_request( history_id, "/%s/display" % dataset_id )
+ assert display_response.status_code == 200, display_response.content
+ return display_response.content
+
+ def get_history_dataset_details( self, history_id, **kwds ):
+ dataset_id = self.__history_dataset_id( history_id, **kwds )
+ details_response = self.__get_contents_request( history_id, "/%s" % dataset_id )
+ assert details_response.status_code == 200
+ return details_response.json()
+
+ def __history_dataset_id( self, history_id, wait=True, **kwds ):
if wait:
assert_ok = kwds.get( "assert_ok", True )
self.wait_for_history( history_id, assert_ok=assert_ok )
# kwds should contain a 'dataset' object response, a 'dataset_id' or
# the last dataset in the history will be fetched.
- contents_url = "histories/%s/contents" % history_id
if "dataset_id" in kwds:
dataset_id = kwds[ "dataset_id" ]
elif "dataset" in kwds:
dataset_id = kwds[ "dataset" ][ "id" ]
else:
hid = kwds.get( "hid", -1 ) # If not hid, just grab last dataset
- dataset_contents = self.galaxy_interactor.get( contents_url ).json()
- dataset_id = dataset_contents[ hid ][ "id" ]
+ dataset_contents = self.__get_contents_request( history_id ).json()
+ dataset_id = dataset_contents[ hid - 1 ][ "id" ]
+ return dataset_id
- display_response = self.galaxy_interactor.get( "%s/%s/display" % ( contents_url, dataset_id ) )
- assert display_response.status_code == 200
- return display_response.content
+ def __get_contents_request( self, history_id, suffix=""):
+ url = "histories/%s/contents" % history_id
+ if suffix:
+ url = "%s%s" % ( url, suffix )
+ return self.galaxy_interactor.get( url )
class WorkflowPopulator( object ):
@@ -154,7 +168,7 @@
tool_step[ "post_job_actions" ][ "RenameDatasetActionout_file1" ] = dict(
action_type="RenameDatasetAction",
output_name="out_file1",
- action_arguments=dict( newname="the_new_name" ),
+ action_arguments=dict( newname="foo ${replaceme}" ),
)
return workflow
diff -r bbe9be042b34268c649b42c8c85d238149e910f0 -r f68f8c8f147b863ec968475216cc9a72044a722b test/api/test_workflows.py
--- a/test/api/test_workflows.py
+++ b/test/api/test_workflows.py
@@ -467,6 +467,16 @@
assert n == expected_len, "Expected %d steps of type %s, found %d" % ( expected_len, type, n )
return sorted( steps, key=operator.itemgetter("id") )
+ @skip_without_tool( "cat1" )
+ def test_run_with_pja( self ):
+ workflow = self.workflow_populator.load_workflow( name="test_for_pja_run", add_pja=True )
+ workflow_request, history_id = self._setup_workflow_run( workflow, inputs_by='step_index' )
+ workflow_request[ "replacement_params" ] = dumps( dict( replaceme="was replaced" ) )
+ run_workflow_response = self._post( "workflows", data=workflow_request )
+ self._assert_status_code_is( run_workflow_response, 200 )
+ content = self.dataset_populator.get_history_dataset_details( history_id, wait=True, assert_ok=True )
+ assert content[ "name" ] == "foo was replaced"
+
@skip_without_tool( "random_lines1" )
def test_run_replace_params_by_tool( self ):
workflow_request, history_id = self._setup_random_x2_workflow( "test_for_replace_tool_params" )
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: davebgx: Fix data table xml definition for tool tarball download.
by commits-noreply@bitbucket.org 10 Sep '14
by commits-noreply@bitbucket.org 10 Sep '14
10 Sep '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/d85d039b8eeb/
Changeset: d85d039b8eeb
User: davebgx
Date: 2014-09-10 15:44:32
Summary: Fix data table xml definition for tool tarball download.
Affected #: 1 file
diff -r 308f95b0f2b01930fab8f43598b48ba9d680e568 -r d85d039b8eeb2781619683f62dddf0f4c20af773 lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -756,7 +756,6 @@
tarball_files.append( ( filesystem_path, tarball_path ) )
image_found = True
tool_xml = tool_xml.replace( '${static_path}/%s' % tarball_path, tarball_path )
- log.debug( tarball_files )
# If one or more tool help images were found, add the modified tool XML to the tarball instead of the original.
if image_found:
fd, new_tool_config = tempfile.mkstemp( suffix='.xml' )
@@ -817,8 +816,7 @@
if len( data_table_definitions ) > 0:
# Put the data table definition XML in a temporary file.
table_definition = '<?xml version="1.0" encoding="utf-8"?>\n<tables>\n %s</tables>'
- table_xml = [ data_table.xml_string for data_table in data_table_definitions ]
- table_definition = table_definition % '\n'.join( table_xml )
+ table_definition = table_definition % '\n'.join( data_table_definitions )
fd, table_conf = tempfile.mkstemp()
os.close( fd )
file( table_conf, 'w' ).write( table_definition )
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: dannon: Revert accidental replacement of symlinks w/ real file from ce088c6. Thanks @jmchilton.
by commits-noreply@bitbucket.org 10 Sep '14
by commits-noreply@bitbucket.org 10 Sep '14
10 Sep '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/308f95b0f2b0/
Changeset: 308f95b0f2b0
User: dannon
Date: 2014-09-10 02:47:48
Summary: Revert accidental replacement of symlinks w/ real file from ce088c6. Thanks @jmchilton.
Affected #: 17 files
diff -r 89ab3ca6171d10d37d26fb7c50242bd6dcde45d9 -r 308f95b0f2b01930fab8f43598b48ba9d680e568 lib/galaxy/model/tool_shed_install/migrate/versions/0001_add_tool_shed_repository_table.py
--- a/lib/galaxy/model/tool_shed_install/migrate/versions/0001_add_tool_shed_repository_table.py
+++ b/lib/galaxy/model/tool_shed_install/migrate/versions/0001_add_tool_shed_repository_table.py
@@ -1,51 +1,1 @@
-"""
-Migration script to add the tool_shed_repository table.
-"""
-from sqlalchemy import *
-from sqlalchemy.orm import *
-from migrate import *
-from migrate.changeset import *
-import sys, logging
-from galaxy.model.custom_types import *
-from sqlalchemy.exc import *
-import datetime
-now = datetime.datetime.utcnow
-
-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 )
-
-metadata = MetaData()
-
-# New table to store information about cloned tool shed repositories.
-ToolShedRepository_table = Table( "tool_shed_repository", metadata,
- Column( "id", Integer, primary_key=True ),
- Column( "create_time", DateTime, default=now ),
- Column( "update_time", DateTime, default=now, onupdate=now ),
- Column( "tool_shed", TrimmedString( 255 ), index=True ),
- Column( "name", TrimmedString( 255 ), index=True ),
- Column( "description" , TEXT ),
- Column( "owner", TrimmedString( 255 ), index=True ),
- Column( "changeset_revision", TrimmedString( 255 ), index=True ),
- Column( "deleted", Boolean, index=True, default=False ) )
-
-def upgrade(migrate_engine):
- metadata.bind = migrate_engine
- print __doc__
- metadata.reflect()
- try:
- ToolShedRepository_table.create()
- except Exception, e:
- log.debug( "Creating tool_shed_repository table failed: %s" % str( e ) )
-
-def downgrade(migrate_engine):
- metadata.bind = migrate_engine
- metadata.reflect()
- try:
- ToolShedRepository_table.drop()
- except Exception, e:
- log.debug( "Dropping tool_shed_repository table failed: %s" % str( e ) )
+../../../migrate/versions/0082_add_tool_shed_repository_table.py
\ No newline at end of file
diff -r 89ab3ca6171d10d37d26fb7c50242bd6dcde45d9 -r 308f95b0f2b01930fab8f43598b48ba9d680e568 lib/galaxy/model/tool_shed_install/migrate/versions/0002_add_tool_shed_repository_table_columns.py
--- a/lib/galaxy/model/tool_shed_install/migrate/versions/0002_add_tool_shed_repository_table_columns.py
+++ b/lib/galaxy/model/tool_shed_install/migrate/versions/0002_add_tool_shed_repository_table_columns.py
@@ -1,79 +1,1 @@
-"""
-Migration script to add the metadata, update_available and includes_datatypes columns to the tool_shed_repository table.
-"""
-
-from sqlalchemy import *
-from sqlalchemy.orm import *
-from migrate import *
-from migrate.changeset import *
-
-import datetime
-now = datetime.datetime.utcnow
-# Need our custom types, but don't import anything else from model
-from galaxy.model.custom_types import *
-
-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 )
-
-metadata = MetaData()
-
-def get_default_false(migrate_engine):
- if migrate_engine.name == 'mysql' or migrate_engine.name == 'sqlite':
- return "0"
- elif migrate_engine.name in ['postgresql', 'postgres']:
- return "false"
-
-def upgrade(migrate_engine):
- metadata.bind = migrate_engine
- print __doc__
- metadata.reflect()
- ToolShedRepository_table = Table( "tool_shed_repository", metadata, autoload=True )
- c = Column( "metadata", JSONType(), nullable=True )
- try:
- c.create( ToolShedRepository_table )
- assert c is ToolShedRepository_table.c.metadata
- except Exception, e:
- print "Adding metadata column to the tool_shed_repository table failed: %s" % str( e )
- log.debug( "Adding metadata column to the tool_shed_repository table failed: %s" % str( e ) )
- c = Column( "includes_datatypes", Boolean, index=True, default=False )
- try:
- c.create( ToolShedRepository_table, index_name="ix_tool_shed_repository_includes_datatypes")
- assert c is ToolShedRepository_table.c.includes_datatypes
- migrate_engine.execute( "UPDATE tool_shed_repository SET includes_datatypes=%s" % get_default_false(migrate_engine))
- except Exception, e:
- print "Adding includes_datatypes column to the tool_shed_repository table failed: %s" % str( e )
- log.debug( "Adding includes_datatypes column to the tool_shed_repository table failed: %s" % str( e ) )
- c = Column( "update_available", Boolean, default=False )
- try:
- c.create( ToolShedRepository_table )
- assert c is ToolShedRepository_table.c.update_available
- migrate_engine.execute( "UPDATE tool_shed_repository SET update_available=%s" % get_default_false(migrate_engine))
- except Exception, e:
- print "Adding update_available column to the tool_shed_repository table failed: %s" % str( e )
- log.debug( "Adding update_available column to the tool_shed_repository table failed: %s" % str( e ) )
-
-def downgrade(migrate_engine):
- metadata.bind = migrate_engine
- metadata.reflect()
- ToolShedRepository_table = Table( "tool_shed_repository", metadata, autoload=True )
- try:
- ToolShedRepository_table.c.metadata.drop()
- except Exception, e:
- print "Dropping column metadata from the tool_shed_repository table failed: %s" % str( e )
- log.debug( "Dropping column metadata from the tool_shed_repository table failed: %s" % str( e ) )
- try:
- ToolShedRepository_table.c.includes_datatypes.drop()
- except Exception, e:
- print "Dropping column includes_datatypes from the tool_shed_repository table failed: %s" % str( e )
- log.debug( "Dropping column includes_datatypes from the tool_shed_repository table failed: %s" % str( e ) )
- try:
- ToolShedRepository_table.c.update_available.drop()
- except Exception, e:
- print "Dropping column update_available from the tool_shed_repository table failed: %s" % str( e )
- log.debug( "Dropping column update_available from the tool_shed_repository table failed: %s" % str( e ) )
+../../../migrate/versions/0086_add_tool_shed_repository_table_columns.py
\ No newline at end of file
diff -r 89ab3ca6171d10d37d26fb7c50242bd6dcde45d9 -r 308f95b0f2b01930fab8f43598b48ba9d680e568 lib/galaxy/model/tool_shed_install/migrate/versions/0003_tool_id_guid_map_table.py
--- a/lib/galaxy/model/tool_shed_install/migrate/versions/0003_tool_id_guid_map_table.py
+++ b/lib/galaxy/model/tool_shed_install/migrate/versions/0003_tool_id_guid_map_table.py
@@ -1,52 +1,1 @@
-"""
-Migration script to create the tool_id_guid_map table.
-"""
-
-from sqlalchemy import *
-from sqlalchemy.orm import *
-from migrate import *
-from migrate.changeset import *
-
-import datetime
-now = datetime.datetime.utcnow
-# Need our custom types, but don't import anything else from model
-from galaxy.model.custom_types import *
-
-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 )
-
-metadata = MetaData()
-
-ToolIdGuidMap_table = Table( "tool_id_guid_map", metadata,
- Column( "id", Integer, primary_key=True ),
- Column( "create_time", DateTime, default=now ),
- Column( "update_time", DateTime, default=now, onupdate=now ),
- Column( "tool_id", String( 255 ) ),
- Column( "tool_version", TEXT ),
- Column( "tool_shed", TrimmedString( 255 ) ),
- Column( "repository_owner", TrimmedString( 255 ) ),
- Column( "repository_name", TrimmedString( 255 ) ),
- Column( "guid", TEXT, index=True, unique=True ) )
-
-def upgrade(migrate_engine):
- metadata.bind = migrate_engine
- print __doc__
- metadata.reflect()
- try:
- ToolIdGuidMap_table.create()
- except Exception, e:
- log.debug( "Creating tool_id_guid_map table failed: %s" % str( e ) )
-
-def downgrade(migrate_engine):
- metadata.bind = migrate_engine
- metadata.reflect()
- try:
- ToolIdGuidMap_table.drop()
- except Exception, e:
- log.debug( "Dropping tool_id_guid_map table failed: %s" % str( e ) )
+../../../migrate/versions/0087_tool_id_guid_map_table.py
\ No newline at end of file
diff -r 89ab3ca6171d10d37d26fb7c50242bd6dcde45d9 -r 308f95b0f2b01930fab8f43598b48ba9d680e568 lib/galaxy/model/tool_shed_install/migrate/versions/0004_add_installed_changeset_revison_column.py
--- a/lib/galaxy/model/tool_shed_install/migrate/versions/0004_add_installed_changeset_revison_column.py
+++ b/lib/galaxy/model/tool_shed_install/migrate/versions/0004_add_installed_changeset_revison_column.py
@@ -1,64 +1,1 @@
-"""
-Migration script to add the installed_changeset_revision column to the tool_shed_repository table.
-"""
-
-from sqlalchemy import *
-from sqlalchemy.orm import *
-from migrate import *
-from migrate.changeset import *
-
-import datetime
-now = datetime.datetime.utcnow
-# Need our custom types, but don't import anything else from model
-from galaxy.model.custom_types import *
-
-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 )
-
-metadata = MetaData()
-
-def upgrade(migrate_engine):
- metadata.bind = migrate_engine
- print __doc__
- metadata.reflect()
- ToolShedRepository_table = Table( "tool_shed_repository", metadata, autoload=True )
- col = Column( "installed_changeset_revision", TrimmedString( 255 ) )
- try:
- col.create( ToolShedRepository_table )
- assert col is ToolShedRepository_table.c.installed_changeset_revision
- except Exception, e:
- print "Adding installed_changeset_revision column to the tool_shed_repository table failed: %s" % str( e )
- log.debug( "Adding installed_changeset_revision column to the tool_shed_repository table failed: %s" % str( e ) )
- # Update each row by setting the value of installed_changeset_revison to be the value of changeset_revision.
- # This will be problematic if the value of changeset_revision was updated to something other than the value
- # that it was when the repository was installed (because the install path determined in real time will attempt to
- # find the repository using the updated changeset_revison instead of the required installed_changeset_revision),
- # but at the time this script was written, this scenario is extremely unlikely.
- cmd = "SELECT id AS id, " \
- + "installed_changeset_revision AS installed_changeset_revision, " \
- + "changeset_revision AS changeset_revision " \
- + "FROM tool_shed_repository;"
- tool_shed_repositories = migrate_engine.execute( cmd ).fetchall()
- update_count = 0
- for row in tool_shed_repositories:
- cmd = "UPDATE tool_shed_repository " \
- + "SET installed_changeset_revision = '%s' " % row.changeset_revision \
- + "WHERE changeset_revision = '%s';" % row.changeset_revision
- migrate_engine.execute( cmd )
- update_count += 1
- print "Updated the installed_changeset_revision column for ", update_count, " rows in the tool_shed_repository table. "
-def downgrade(migrate_engine):
- metadata.bind = migrate_engine
- metadata.reflect()
- ToolShedRepository_table = Table( "tool_shed_repository", metadata, autoload=True )
- try:
- ToolShedRepository_table.c.installed_changeset_revision.drop()
- except Exception, e:
- print "Dropping column installed_changeset_revision from the tool_shed_repository table failed: %s" % str( e )
- log.debug( "Dropping column installed_changeset_revision from the tool_shed_repository table failed: %s" % str( e ) )
+../../../migrate/versions/0088_add_installed_changeset_revison_column.py
\ No newline at end of file
diff -r 89ab3ca6171d10d37d26fb7c50242bd6dcde45d9 -r 308f95b0f2b01930fab8f43598b48ba9d680e568 lib/galaxy/model/tool_shed_install/migrate/versions/0005_add_tool_shed_repository_table_columns.py
--- a/lib/galaxy/model/tool_shed_install/migrate/versions/0005_add_tool_shed_repository_table_columns.py
+++ b/lib/galaxy/model/tool_shed_install/migrate/versions/0005_add_tool_shed_repository_table_columns.py
@@ -1,63 +1,1 @@
-"""
-Migration script to add the uninstalled and dist_to_shed columns to the tool_shed_repository table.
-"""
-
-from sqlalchemy import *
-from sqlalchemy.orm import *
-from migrate import *
-from migrate.changeset import *
-
-import datetime
-now = datetime.datetime.utcnow
-# Need our custom types, but don't import anything else from model
-from galaxy.model.custom_types import *
-
-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 )
-
-metadata = MetaData()
-
-def default_false(migrate_engine):
- if migrate_engine.name == 'mysql' or migrate_engine.name == 'sqlite':
- return "0"
- elif migrate_engine.name in ['postgresql', 'postgres']:
- return "false"
-
-def upgrade(migrate_engine):
- metadata.bind = migrate_engine
- print __doc__
- metadata.reflect()
- ToolShedRepository_table = Table( "tool_shed_repository", metadata, autoload=True )
- c = Column( "uninstalled", Boolean, default=False )
- try:
- c.create( ToolShedRepository_table )
- assert c is ToolShedRepository_table.c.uninstalled
- migrate_engine.execute( "UPDATE tool_shed_repository SET uninstalled=%s" % default_false(migrate_engine) )
- except Exception, e:
- print "Adding uninstalled column to the tool_shed_repository table failed: %s" % str( e )
- c = Column( "dist_to_shed", Boolean, default=False )
- try:
- c.create( ToolShedRepository_table )
- assert c is ToolShedRepository_table.c.dist_to_shed
- migrate_engine.execute( "UPDATE tool_shed_repository SET dist_to_shed=%s" % default_false(migrate_engine) )
- except Exception, e:
- print "Adding dist_to_shed column to the tool_shed_repository table failed: %s" % str( e )
-
-def downgrade(migrate_engine):
- metadata.bind = migrate_engine
- metadata.reflect()
- ToolShedRepository_table = Table( "tool_shed_repository", metadata, autoload=True )
- try:
- ToolShedRepository_table.c.uninstalled.drop()
- except Exception, e:
- print "Dropping column uninstalled from the tool_shed_repository table failed: %s" % str( e )
- try:
- ToolShedRepository_table.c.dist_to_shed.drop()
- except Exception, e:
- print "Dropping column dist_to_shed from the tool_shed_repository table failed: %s" % str( e )
+../../../migrate/versions/0090_add_tool_shed_repository_table_columns.py
\ No newline at end of file
diff -r 89ab3ca6171d10d37d26fb7c50242bd6dcde45d9 -r 308f95b0f2b01930fab8f43598b48ba9d680e568 lib/galaxy/model/tool_shed_install/migrate/versions/0006_add_tool_version_tables.py
--- a/lib/galaxy/model/tool_shed_install/migrate/versions/0006_add_tool_version_tables.py
+++ b/lib/galaxy/model/tool_shed_install/migrate/versions/0006_add_tool_version_tables.py
@@ -1,122 +1,1 @@
-"""
-Migration script to create the tool_version and tool_version_association tables and drop the tool_id_guid_map table.
-"""
-
-from sqlalchemy import *
-from sqlalchemy.orm import *
-from migrate import *
-from migrate.changeset import *
-
-import datetime
-now = datetime.datetime.utcnow
-# Need our custom types, but don't import anything else from model
-from galaxy.model.custom_types import *
-from galaxy.model.custom_types import _sniffnfix_pg9_hex
-from galaxy.util.json import loads, dumps
-
-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 )
-
-metadata = MetaData()
-#migrate_engine = scoped_session( sessionmaker( bind=migrate_engine, autoflush=False, autocommit=True ) )
-
-def nextval( table, col='id' ):
- if migrate_engine.name == 'postgres':
- return "nextval('%s_%s_seq')" % ( table, col )
- elif migrate_engine.name == 'mysql' or migrate_engine.name == 'sqlite':
- return "null"
- else:
- raise Exception( 'Unable to convert data for unknown database type: %s' % migrate_engine.name )
-
-def localtimestamp():
- if migrate_engine.name == 'postgres' or migrate_engine.name == 'mysql':
- return "LOCALTIMESTAMP"
- elif migrate_engine.name == 'sqlite':
- return "current_date || ' ' || current_time"
- else:
- raise Exception( 'Unable to convert data for unknown database type: %s' % db )
-
-ToolVersion_table = Table( "tool_version", metadata,
- Column( "id", Integer, primary_key=True ),
- Column( "create_time", DateTime, default=now ),
- Column( "update_time", DateTime, default=now, onupdate=now ),
- Column( "tool_id", String( 255 ) ),
- Column( "tool_shed_repository_id", Integer, ForeignKey( "tool_shed_repository.id" ), index=True, nullable=True ) )
-
-ToolVersionAssociation_table = Table( "tool_version_association", metadata,
- Column( "id", Integer, primary_key=True ),
- Column( "tool_id", Integer, ForeignKey( "tool_version.id" ), index=True, nullable=False ),
- Column( "parent_id", Integer, ForeignKey( "tool_version.id" ), index=True, nullable=False ) )
-
-def upgrade(migrate_engine):
- metadata.bind = migrate_engine
- print __doc__
-
- ToolIdGuidMap_table = Table( "tool_id_guid_map", metadata, autoload=True )
-
- metadata.reflect()
- # Create the tables.
- try:
- ToolVersion_table.create()
- except Exception, e:
- log.debug( "Creating tool_version table failed: %s" % str( e ) )
- try:
- ToolVersionAssociation_table.create()
- except Exception, e:
- log.debug( "Creating tool_version_association table failed: %s" % str( e ) )
- # Populate the tool table with tools included in installed tool shed repositories.
- cmd = "SELECT id, metadata FROM tool_shed_repository"
- result = migrate_engine.execute( cmd )
- count = 0
- for row in result:
- if row[1]:
- tool_shed_repository_id = row[0]
- repository_metadata = loads( _sniffnfix_pg9_hex( str( row[1] ) ) )
- # Create a new row in the tool table for each tool included in repository. We will NOT
- # handle tool_version_associaions because we do not have the information we need to do so.
- tools = repository_metadata.get( 'tools', [] )
- for tool_dict in tools:
- cmd = "INSERT INTO tool_version VALUES (%s, %s, %s, '%s', %s)" % \
- ( nextval( 'tool_version' ), localtimestamp(), localtimestamp(), tool_dict[ 'guid' ], tool_shed_repository_id )
- migrate_engine.execute( cmd )
- count += 1
- print "Added %d rows to the new tool_version table." % count
- # Drop the tool_id_guid_map table since the 2 new tables render it unnecessary.
- try:
- ToolIdGuidMap_table.drop()
- except Exception, e:
- log.debug( "Dropping tool_id_guid_map table failed: %s" % str( e ) )
-
-def downgrade(migrate_engine):
- metadata.bind = migrate_engine
-
- ToolIdGuidMap_table = Table( "tool_id_guid_map", metadata,
- Column( "id", Integer, primary_key=True ),
- Column( "create_time", DateTime, default=now ),
- Column( "update_time", DateTime, default=now, onupdate=now ),
- Column( "tool_id", String( 255 ) ),
- Column( "tool_version", TEXT ),
- Column( "tool_shed", TrimmedString( 255 ) ),
- Column( "repository_owner", TrimmedString( 255 ) ),
- Column( "repository_name", TrimmedString( 255 ) ),
- Column( "guid", TEXT, index=True, unique=True ) )
-
- metadata.reflect()
- try:
- ToolVersionAssociation_table.drop()
- except Exception, e:
- log.debug( "Dropping tool_version_association table failed: %s" % str( e ) )
- try:
- ToolVersion_table.drop()
- except Exception, e:
- log.debug( "Dropping tool_version table failed: %s" % str( e ) )
- try:
- ToolIdGuidMap_table.create()
- except Exception, e:
- log.debug( "Creating tool_id_guid_map table failed: %s" % str( e ) )
+../../../migrate/versions/0091_add_tool_version_tables.py
\ No newline at end of file
diff -r 89ab3ca6171d10d37d26fb7c50242bd6dcde45d9 -r 308f95b0f2b01930fab8f43598b48ba9d680e568 lib/galaxy/model/tool_shed_install/migrate/versions/0007_add_migrate_tools_table.py
--- a/lib/galaxy/model/tool_shed_install/migrate/versions/0007_add_migrate_tools_table.py
+++ b/lib/galaxy/model/tool_shed_install/migrate/versions/0007_add_migrate_tools_table.py
@@ -1,50 +1,1 @@
-"""
-Migration script to create the migrate_tools table.
-"""
-
-from sqlalchemy import *
-from sqlalchemy.orm import *
-from migrate import *
-from migrate.changeset import *
-
-import datetime
-now = datetime.datetime.utcnow
-# Need our custom types, but don't import anything else from model
-from galaxy.model.custom_types import *
-
-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 )
-
-metadata = MetaData()
-
-MigrateTools_table = Table( "migrate_tools", metadata,
- Column( "repository_id", TrimmedString( 255 ) ),
- Column( "repository_path", TEXT ),
- Column( "version", Integer ) )
-
-def upgrade(migrate_engine):
- metadata.bind = migrate_engine
- print __doc__
-
- metadata.reflect()
- # Create the table.
- try:
- MigrateTools_table.create()
- cmd = "INSERT INTO migrate_tools VALUES ('GalaxyTools', 'lib/galaxy/tool_shed/migrate', %d)" % 1
- migrate_engine.execute( cmd )
- except Exception, e:
- log.debug( "Creating migrate_tools table failed: %s" % str( e ) )
-
-def downgrade(migrate_engine):
- metadata.bind = migrate_engine
- metadata.reflect()
- try:
- MigrateTools_table.drop()
- except Exception, e:
- log.debug( "Dropping migrate_tools table failed: %s" % str( e ) )
+../../../migrate/versions/0092_add_migrate_tools_table.py
\ No newline at end of file
diff -r 89ab3ca6171d10d37d26fb7c50242bd6dcde45d9 -r 308f95b0f2b01930fab8f43598b48ba9d680e568 lib/galaxy/model/tool_shed_install/migrate/versions/0008_add_ctx_rev_column.py
--- a/lib/galaxy/model/tool_shed_install/migrate/versions/0008_add_ctx_rev_column.py
+++ b/lib/galaxy/model/tool_shed_install/migrate/versions/0008_add_ctx_rev_column.py
@@ -1,44 +1,1 @@
-"""
-Migration script to add the ctx_rev column to the tool_shed_repository table.
-"""
-
-from sqlalchemy import *
-from sqlalchemy.orm import *
-from migrate import *
-from migrate.changeset import *
-
-import datetime
-now = datetime.datetime.utcnow
-# Need our custom types, but don't import anything else from model
-from galaxy.model.custom_types import *
-
-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 )
-
-metadata = MetaData()
-
-def upgrade(migrate_engine):
- metadata.bind = migrate_engine
- print __doc__
- metadata.reflect()
- ToolShedRepository_table = Table( "tool_shed_repository", metadata, autoload=True )
- col = Column( "ctx_rev", TrimmedString( 10 ) )
- try:
- col.create( ToolShedRepository_table )
- assert col is ToolShedRepository_table.c.ctx_rev
- except Exception, e:
- print "Adding ctx_rev column to the tool_shed_repository table failed: %s" % str( e )
-def downgrade(migrate_engine):
- metadata.bind = migrate_engine
- metadata.reflect()
- ToolShedRepository_table = Table( "tool_shed_repository", metadata, autoload=True )
- try:
- ToolShedRepository_table.c.ctx_rev.drop()
- except Exception, e:
- print "Dropping column ctx_rev from the tool_shed_repository table failed: %s" % str( e )
+../../../migrate/versions/0097_add_ctx_rev_column.py
\ No newline at end of file
diff -r 89ab3ca6171d10d37d26fb7c50242bd6dcde45d9 -r 308f95b0f2b01930fab8f43598b48ba9d680e568 lib/galaxy/model/tool_shed_install/migrate/versions/0009_add_tool_dependency_table.py
--- a/lib/galaxy/model/tool_shed_install/migrate/versions/0009_add_tool_dependency_table.py
+++ b/lib/galaxy/model/tool_shed_install/migrate/versions/0009_add_tool_dependency_table.py
@@ -1,51 +1,1 @@
-"""
-Migration script to add the tool_dependency table.
-"""
-from sqlalchemy import *
-from sqlalchemy.orm import *
-from migrate import *
-from migrate.changeset import *
-import sys, logging
-from galaxy.model.custom_types import *
-from sqlalchemy.exc import *
-import datetime
-now = datetime.datetime.utcnow
-
-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 )
-
-metadata = MetaData()
-
-# New table to store information about cloned tool shed repositories.
-ToolDependency_table = Table( "tool_dependency", metadata,
- Column( "id", Integer, primary_key=True ),
- Column( "create_time", DateTime, default=now ),
- Column( "update_time", DateTime, default=now, onupdate=now ),
- Column( "tool_shed_repository_id", Integer, ForeignKey( "tool_shed_repository.id" ), index=True, nullable=False ),
- Column( "installed_changeset_revision", TrimmedString( 255 ) ),
- Column( "name", TrimmedString( 255 ) ),
- Column( "version", TrimmedString( 40 ) ),
- Column( "type", TrimmedString( 40 ) ),
- Column( "uninstalled", Boolean, default=False ) )
-
-def upgrade(migrate_engine):
- metadata.bind = migrate_engine
- print __doc__
- metadata.reflect()
- try:
- ToolDependency_table.create()
- except Exception, e:
- log.debug( "Creating tool_dependency table failed: %s" % str( e ) )
-
-def downgrade(migrate_engine):
- metadata.bind = migrate_engine
- metadata.reflect()
- try:
- ToolDependency_table.drop()
- except Exception, e:
- log.debug( "Dropping tool_dependency table failed: %s" % str( e ) )
+../../../migrate/versions/0099_add_tool_dependency_table.py
\ No newline at end of file
diff -r 89ab3ca6171d10d37d26fb7c50242bd6dcde45d9 -r 308f95b0f2b01930fab8f43598b48ba9d680e568 lib/galaxy/model/tool_shed_install/migrate/versions/0010_alter_tool_dependency_table_version_column.py
--- a/lib/galaxy/model/tool_shed_install/migrate/versions/0010_alter_tool_dependency_table_version_column.py
+++ b/lib/galaxy/model/tool_shed_install/migrate/versions/0010_alter_tool_dependency_table_version_column.py
@@ -1,54 +1,1 @@
-"""
-Migration script to alter the type of the tool_dependency.version column from TrimmedString(40) to Text.
-"""
-
-from sqlalchemy import *
-from sqlalchemy.orm import *
-from migrate import *
-from migrate.changeset import *
-
-import datetime
-now = datetime.datetime.utcnow
-# Need our custom types, but don't import anything else from model
-from galaxy.model.custom_types import *
-
-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 )
-
-metadata = MetaData()
-
-def upgrade(migrate_engine):
- metadata.bind = migrate_engine
- print __doc__
- metadata.reflect()
- ToolDependency_table = Table( "tool_dependency", metadata, autoload=True )
- # Change the tool_dependency table's version column from TrimmedString to Text.
- if migrate_engine.name in ['postgresql', 'postgres']:
- cmd = "ALTER TABLE tool_dependency ALTER COLUMN version TYPE Text;"
- elif migrate_engine.name == 'mysql':
- cmd = "ALTER TABLE tool_dependency MODIFY COLUMN version Text;"
- else:
- # We don't have to do anything for sqlite tables. From the sqlite documentation at http://sqlite.org/datatype3.html:
- # 1.0 Storage Classes and Datatypes
- # Each value stored in an SQLite database (or manipulated by the database engine) has one of the following storage classes:
- # NULL. The value is a NULL value.
- # INTEGER. The value is a signed integer, stored in 1, 2, 3, 4, 6, or 8 bytes depending on the magnitude of the value.
- # REAL. The value is a floating point value, stored as an 8-byte IEEE floating point number.
- # TEXT. The value is a text string, stored using the database encoding (UTF-8, UTF-16BE or UTF-16LE).
- # BLOB. The value is a blob of data, stored exactly as it was input.
- cmd = None
- if cmd:
- try:
- migrate_engine.execute( cmd )
- except Exception, e:
- log.debug( "Altering tool_dependency.version column from TrimmedString(40) to Text failed: %s" % str( e ) )
-def downgrade(migrate_engine):
- metadata.bind = migrate_engine
- # Not necessary to change column type Text to TrimmedString(40).
- pass
+../../../migrate/versions/0100_alter_tool_dependency_table_version_column.py
\ No newline at end of file
diff -r 89ab3ca6171d10d37d26fb7c50242bd6dcde45d9 -r 308f95b0f2b01930fab8f43598b48ba9d680e568 lib/galaxy/model/tool_shed_install/migrate/versions/0011_drop_installed_changeset_revision_column.py
--- a/lib/galaxy/model/tool_shed_install/migrate/versions/0011_drop_installed_changeset_revision_column.py
+++ b/lib/galaxy/model/tool_shed_install/migrate/versions/0011_drop_installed_changeset_revision_column.py
@@ -1,41 +1,1 @@
-"""
-Migration script to drop the installed_changeset_revision column from the tool_dependency table.
-"""
-from sqlalchemy import *
-from sqlalchemy.orm import *
-from migrate import *
-from migrate.changeset import *
-import sys, logging
-from galaxy.model.custom_types import *
-from sqlalchemy.exc import *
-import datetime
-now = datetime.datetime.utcnow
-
-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 )
-
-metadata = MetaData()
-
-def upgrade(migrate_engine):
- metadata.bind = migrate_engine
- print __doc__
- metadata.reflect()
- try:
- ToolDependency_table = Table( "tool_dependency", metadata, autoload=True )
- except NoSuchTableError:
- ToolDependency_table = None
- log.debug( "Failed loading table tool_dependency" )
- if ToolDependency_table is not None:
- try:
- col = ToolDependency_table.c.installed_changeset_revision
- col.drop()
- except Exception, e:
- log.debug( "Dropping column 'installed_changeset_revision' from tool_dependency table failed: %s" % ( str( e ) ) )
-def downgrade(migrate_engine):
- metadata.bind = migrate_engine
- pass
+../../../migrate/versions/0101_drop_installed_changeset_revision_column.py
\ No newline at end of file
diff -r 89ab3ca6171d10d37d26fb7c50242bd6dcde45d9 -r 308f95b0f2b01930fab8f43598b48ba9d680e568 lib/galaxy/model/tool_shed_install/migrate/versions/0012_add_tool_dependency_status_columns.py
--- a/lib/galaxy/model/tool_shed_install/migrate/versions/0012_add_tool_dependency_status_columns.py
+++ b/lib/galaxy/model/tool_shed_install/migrate/versions/0012_add_tool_dependency_status_columns.py
@@ -1,71 +1,1 @@
-"""
-Migration script to add status and error_message columns to the tool_dependency table and drop the uninstalled column from the tool_dependency table.
-"""
-
-from sqlalchemy import *
-from sqlalchemy.orm import *
-from migrate import *
-from migrate.changeset import *
-
-import datetime
-now = datetime.datetime.utcnow
-# Need our custom types, but don't import anything else from model
-from galaxy.model.custom_types import *
-
-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 )
-
-metadata = MetaData()
-
-def upgrade(migrate_engine):
- metadata.bind = migrate_engine
- print __doc__
- metadata.reflect()
- ToolDependency_table = Table( "tool_dependency", metadata, autoload=True )
- if migrate_engine.name == 'sqlite':
- col = Column( "status", TrimmedString( 255 ))
- else:
- col = Column( "status", TrimmedString( 255 ), nullable=False)
- try:
- col.create( ToolDependency_table )
- assert col is ToolDependency_table.c.status
- except Exception, e:
- print "Adding status column to the tool_dependency table failed: %s" % str( e )
- col = Column( "error_message", TEXT )
- try:
- col.create( ToolDependency_table )
- assert col is ToolDependency_table.c.error_message
- except Exception, e:
- print "Adding error_message column to the tool_dependency table failed: %s" % str( e )
-
- if migrate_engine.name != 'sqlite':
- #This breaks in sqlite due to failure to drop check constraint.
- # TODO move to alembic.
- try:
- ToolDependency_table.c.uninstalled.drop()
- except Exception, e:
- print "Dropping uninstalled column from the tool_dependency table failed: %s" % str( e )
-def downgrade(migrate_engine):
- metadata.bind = migrate_engine
- metadata.reflect()
- ToolDependency_table = Table( "tool_dependency", metadata, autoload=True )
- try:
- ToolDependency_table.c.status.drop()
- except Exception, e:
- print "Dropping column status from the tool_dependency table failed: %s" % str( e )
- try:
- ToolDependency_table.c.error_message.drop()
- except Exception, e:
- print "Dropping column error_message from the tool_dependency table failed: %s" % str( e )
- col = Column( "uninstalled", Boolean, default=False )
- try:
- col.create( ToolDependency_table )
- assert col is ToolDependency_table.c.uninstalled
- except Exception, e:
- print "Adding uninstalled column to the tool_dependency table failed: %s" % str( e )
+../../../migrate/versions/0102_add_tool_dependency_status_columns.py
\ No newline at end of file
diff -r 89ab3ca6171d10d37d26fb7c50242bd6dcde45d9 -r 308f95b0f2b01930fab8f43598b48ba9d680e568 lib/galaxy/model/tool_shed_install/migrate/versions/0013_add_tool_shed_repository_status_columns.py
--- a/lib/galaxy/model/tool_shed_install/migrate/versions/0013_add_tool_shed_repository_status_columns.py
+++ b/lib/galaxy/model/tool_shed_install/migrate/versions/0013_add_tool_shed_repository_status_columns.py
@@ -1,69 +1,1 @@
-"""Migration script to add status and error_message columns to the tool_shed_repository table."""
-
-from sqlalchemy import *
-from sqlalchemy.orm import *
-from migrate import *
-from migrate.changeset import *
-
-import datetime
-now = datetime.datetime.utcnow
-# Need our custom types, but don't import anything else from model
-from galaxy.model.custom_types import *
-
-metadata = MetaData()
-
-def upgrade(migrate_engine):
- metadata.bind = migrate_engine
- print __doc__
- metadata.reflect()
- ToolShedRepository_table = Table( "tool_shed_repository", metadata, autoload=True )
- # Add the status column to the tool_shed_repository table.
- col = Column( "status", TrimmedString( 255 ) )
- try:
- col.create( ToolShedRepository_table )
- assert col is ToolShedRepository_table.c.status
- except Exception, e:
- print "Adding status column to the tool_shed_repository table failed: %s" % str( e )
- # Add the error_message column to the tool_shed_repository table.
- col = Column( "error_message", TEXT )
- try:
- col.create( ToolShedRepository_table )
- assert col is ToolShedRepository_table.c.error_message
- except Exception, e:
- print "Adding error_message column to the tool_shed_repository table failed: %s" % str( e )
- # Update the status column value for tool_shed_repositories to the default value 'Installed'.
- cmd = "UPDATE tool_shed_repository SET status = 'Installed';"
- try:
- migrate_engine.execute( cmd )
- except Exception, e:
- print "Exception executing sql command: "
- print cmd
- print str( e )
- # Update the status column for tool_shed_repositories that have been uninstalled.
- cmd = "UPDATE tool_shed_repository SET status = 'Uninstalled' WHERE uninstalled;"
- try:
- migrate_engine.execute( cmd )
- except Exception, e:
- print "Exception executing sql command: "
- print cmd
- print str( e )
- # Update the status column for tool_shed_repositories that have been deactivated.
- cmd = "UPDATE tool_shed_repository SET status = 'Deactivated' where deleted and not uninstalled;"
- try:
- migrate_engine.execute( cmd )
- except Exception, e:
- print "Exception executing sql command: "
- print cmd
- print str( e )
-def downgrade(migrate_engine):
- metadata.bind = migrate_engine
- metadata.reflect()
- ToolShedRepository_table = Table( "tool_shed_repository", metadata, autoload=True )
- try:
- ToolShedRepository_table.c.status.drop()
- except Exception, e:
- print "Dropping column status from the tool_shed_repository table failed: %s" % str( e )
- try:
- ToolShedRepository_table.c.error_message.drop()
- except Exception, e:
- print "Dropping column error_message from the tool_shed_repository table failed: %s" % str( e )
+../../../migrate/versions/0103_add_tool_shed_repository_status_columns.py
\ No newline at end of file
diff -r 89ab3ca6171d10d37d26fb7c50242bd6dcde45d9 -r 308f95b0f2b01930fab8f43598b48ba9d680e568 lib/galaxy/model/tool_shed_install/migrate/versions/0014_add_repository_dependency_tables.py
--- a/lib/galaxy/model/tool_shed_install/migrate/versions/0014_add_repository_dependency_tables.py
+++ b/lib/galaxy/model/tool_shed_install/migrate/versions/0014_add_repository_dependency_tables.py
@@ -1,60 +1,1 @@
-"""
-Migration script to add the repository_dependency and repository_repository_dependency_association tables.
-"""
-from sqlalchemy import *
-from sqlalchemy.orm import *
-from migrate import *
-from migrate.changeset import *
-import sys, logging
-from galaxy.model.custom_types import *
-from sqlalchemy.exc import *
-import datetime
-now = datetime.datetime.utcnow
-
-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 )
-
-metadata = MetaData()
-
-RepositoryDependency_table = Table( "repository_dependency", metadata,
- Column( "id", Integer, primary_key=True ),
- Column( "create_time", DateTime, default=now ),
- Column( "update_time", DateTime, default=now, onupdate=now ),
- Column( "tool_shed_repository_id", Integer, ForeignKey( "tool_shed_repository.id" ), index=True, nullable=False ) )
-
-RepositoryRepositoryDependencyAssociation_table = Table( "repository_repository_dependency_association", metadata,
- Column( "id", Integer, primary_key=True ),
- Column( "create_time", DateTime, default=now ),
- Column( "update_time", DateTime, default=now, onupdate=now ),
- Column( "tool_shed_repository_id", Integer, ForeignKey( "tool_shed_repository.id" ), index=True ),
- Column( "repository_dependency_id", Integer, ForeignKey( "repository_dependency.id" ), index=True ) )
-
-def upgrade(migrate_engine):
- print __doc__
- metadata.bind = migrate_engine
- metadata.reflect()
- try:
- RepositoryDependency_table.create()
- except Exception, e:
- log.debug( "Creating repository_dependency table failed: %s" % str( e ) )
- try:
- RepositoryRepositoryDependencyAssociation_table.create()
- except Exception, e:
- log.debug( "Creating repository_repository_dependency_association table failed: %s" % str( e ) )
-
-def downgrade(migrate_engine):
- metadata.bind = migrate_engine
- metadata.reflect()
- try:
- RepositoryRepositoryDependencyAssociation_table.drop()
- except Exception, e:
- log.debug( "Dropping repository_repository_dependency_association table failed: %s" % str( e ) )
- try:
- RepositoryDependency_table.drop()
- except Exception, e:
- log.debug( "Dropping repository_dependency table failed: %s" % str( e ) )
+../../../migrate/versions/0109_add_repository_dependency_tables.py
\ No newline at end of file
diff -r 89ab3ca6171d10d37d26fb7c50242bd6dcde45d9 -r 308f95b0f2b01930fab8f43598b48ba9d680e568 lib/galaxy/model/tool_shed_install/migrate/versions/0015_update_migrate_tools_table.py
--- a/lib/galaxy/model/tool_shed_install/migrate/versions/0015_update_migrate_tools_table.py
+++ b/lib/galaxy/model/tool_shed_install/migrate/versions/0015_update_migrate_tools_table.py
@@ -1,38 +1,1 @@
-"""
-Migration script to update the migrate_tools.repository_path column to point to the new location lib/tool_shed/galaxy_install/migrate.
-"""
-
-from sqlalchemy import *
-from sqlalchemy.orm import *
-from migrate import *
-from migrate.changeset import *
-
-import datetime
-now = datetime.datetime.utcnow
-# Need our custom types, but don't import anything else from model
-from galaxy.model.custom_types import *
-
-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 )
-
-def upgrade(migrate_engine):
- print __doc__
- # Create the table.
- try:
- cmd = "UPDATE migrate_tools set repository_path='lib/galaxy/tool_shed/migrate';"
- migrate_engine.execute( cmd )
- except Exception, e:
- log.debug( "Updating migrate_tools.repository_path column to point to the new location lib/tool_shed/galaxy_install/migrate failed: %s" % str( e ) )
-
-def downgrade(migrate_engine):
- try:
- cmd = "UPDATE migrate_tools set repository_path='lib/galaxy/tool_shed/migrate';"
- migrate_engine.execute( cmd )
- except Exception, e:
- log.debug( "Updating migrate_tools.repository_path column to point to the old location lib/galaxy/tool_shed/migrate failed: %s" % str( e ) )
+../../../migrate/versions/0113_update_migrate_tools_table.py
\ No newline at end of file
diff -r 89ab3ca6171d10d37d26fb7c50242bd6dcde45d9 -r 308f95b0f2b01930fab8f43598b48ba9d680e568 lib/galaxy/model/tool_shed_install/migrate/versions/0016_update_migrate_tools_table_again.py
--- a/lib/galaxy/model/tool_shed_install/migrate/versions/0016_update_migrate_tools_table_again.py
+++ b/lib/galaxy/model/tool_shed_install/migrate/versions/0016_update_migrate_tools_table_again.py
@@ -1,40 +1,1 @@
-"""
-Migration script to update the migrate_tools.repository_path column to point to the new location lib/tool_shed/galaxy_install/migrate.
-"""
-
-from sqlalchemy import *
-from sqlalchemy.orm import *
-from migrate import *
-from migrate.changeset import *
-
-import datetime
-now = datetime.datetime.utcnow
-# Need our custom types, but don't import anything else from model
-from galaxy.model.custom_types import *
-
-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 )
-
-
-def upgrade(migrate_engine):
- print __doc__
- # Create the table.
- try:
- cmd = "UPDATE migrate_tools set repository_path='lib/tool_shed/galaxy_install/migrate';"
- migrate_engine.execute( cmd )
- except Exception, e:
- log.debug( "Updating migrate_tools.repository_path column to point to the new location lib/tool_shed/galaxy_install/migrate failed: %s" % str( e ) )
-
-def downgrade(migrate_engine):
- try:
- cmd = "UPDATE migrate_tools set repository_path='lib/galaxy/tool_shed/migrate';"
- migrate_engine.execute( cmd )
- except Exception, e:
- log.debug( "Updating migrate_tools.repository_path column to point to the old location lib/galaxy/tool_shed/migrate failed: %s" % str( e ) )
-
+../../../migrate/versions/0114_update_migrate_tools_table_again.py
\ No newline at end of file
diff -r 89ab3ca6171d10d37d26fb7c50242bd6dcde45d9 -r 308f95b0f2b01930fab8f43598b48ba9d680e568 lib/galaxy/model/tool_shed_install/migrate/versions/0017_drop_update_available_col_add_tool_shed_status_col.py
--- a/lib/galaxy/model/tool_shed_install/migrate/versions/0017_drop_update_available_col_add_tool_shed_status_col.py
+++ b/lib/galaxy/model/tool_shed_install/migrate/versions/0017_drop_update_available_col_add_tool_shed_status_col.py
@@ -1,77 +1,1 @@
-"""
-Migration script to drop the update_available Boolean column and replace it with the tool_shed_status JSONType column in the tool_shed_repository table.
-"""
-
-from sqlalchemy import *
-from sqlalchemy.orm import *
-from migrate import *
-from migrate.changeset import *
-import sys, logging
-from galaxy.model.custom_types import *
-from sqlalchemy.exc import *
-import datetime
-now = datetime.datetime.utcnow
-
-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 )
-
-metadata = MetaData()
-
-def default_false( migrate_engine ):
- if migrate_engine.name == 'mysql' or migrate_engine.name == 'sqlite':
- return "0"
- elif migrate_engine.name in [ 'postgresql', 'postgres' ]:
- return "false"
-
-def upgrade( migrate_engine ):
- metadata.bind = migrate_engine
- print __doc__
- metadata.reflect()
- try:
- ToolShedRepository_table = Table( "tool_shed_repository", metadata, autoload=True )
- except NoSuchTableError:
- ToolShedRepository_table = None
- log.debug( "Failed loading table tool_shed_repository" )
- if ToolShedRepository_table is not None:
- # For some unknown reason it is no longer possible to drop a column in a migration script if using the sqlite database.
- if migrate_engine.name != 'sqlite':
- try:
- col = ToolShedRepository_table.c.update_available
- col.drop()
- except Exception, e:
- print "Dropping column update_available from the tool_shed_repository table failed: %s" % str( e )
- c = Column( "tool_shed_status", JSONType, nullable=True )
- try:
- c.create( ToolShedRepository_table )
- assert c is ToolShedRepository_table.c.tool_shed_status
- except Exception, e:
- print "Adding tool_shed_status column to the tool_shed_repository table failed: %s" % str( e )
-
-def downgrade( migrate_engine ):
- metadata.bind = migrate_engine
- metadata.reflect()
- try:
- ToolShedRepository_table = Table( "tool_shed_repository", metadata, autoload=True )
- except NoSuchTableError:
- ToolShedRepository_table = None
- log.debug( "Failed loading table tool_shed_repository" )
- if ToolShedRepository_table is not None:
- # For some unknown reason it is no longer possible to drop a column in a migration script if using the sqlite database.
- if migrate_engine.name != 'sqlite':
- try:
- col = ToolShedRepository_table.c.tool_shed_status
- col.drop()
- except Exception, e:
- print "Dropping column tool_shed_status from the tool_shed_repository table failed: %s" % str( e )
- c = Column( "update_available", Boolean, default=False )
- try:
- c.create( ToolShedRepository_table )
- assert c is ToolShedRepository_table.c.update_available
- migrate_engine.execute( "UPDATE tool_shed_repository SET update_available=%s" % default_false( migrate_engine ) )
- except Exception, e:
- print "Adding column update_available to the tool_shed_repository table failed: %s" % str( e )
+../../../migrate/versions/0116_drop_update_available_col_add_tool_shed_status_col.py
\ No newline at end of file
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/bd450366fc9d/
Changeset: bd450366fc9d
User: jmchilton
Date: 2014-09-09 22:41:34
Summary: Pull separate missing tools template out of run.mako.
If you look at the conflicting sets of parameters these templates require I think it makes more sense to separate them this way - think result is simpler. Likewise, no need to for instance show collapse/expand all buttons on page with no actual rows for steps for instance. Most important thing here though is that now one can assume that step.module and step.state are available for all steps throughout run.mako (this will lead to further simplications).
Affected #: 3 files
diff -r 74b2495de918c95730f1f2fd2ac1bf502018a99f -r bd450366fc9da736c46358e6a827496c5c58d174 lib/galaxy/webapps/galaxy/controllers/workflow.py
--- a/lib/galaxy/webapps/galaxy/controllers/workflow.py
+++ b/lib/galaxy/webapps/galaxy/controllers/workflow.py
@@ -1351,10 +1351,8 @@
if missing_tools:
stored.annotation = self.get_item_annotation_str( trans.sa_session, trans.user, stored )
return trans.fill_template(
- "workflow/run.mako",
- steps=[],
+ "workflow/missing_tools.mako",
workflow=stored,
- hide_fixed_params=hide_fixed_params,
missing_tools=missing_tools
)
# Render the form
diff -r 74b2495de918c95730f1f2fd2ac1bf502018a99f -r bd450366fc9da736c46358e6a827496c5c58d174 templates/webapps/galaxy/workflow/missing_tools.mako
--- /dev/null
+++ b/templates/webapps/galaxy/workflow/missing_tools.mako
@@ -0,0 +1,17 @@
+<%inherit file="/base.mako"/>
+
+<h2>Cannot run workflow "${h.to_unicode( workflow.name )}"</h2>
+
+%if workflow.annotation:
+ <div class="workflow-annotation">${workflow.annotation}</div>
+ <hr/>
+%endif
+
+<div class='errormessage'>
+ <strong>This workflow utilizes tools which are unavailable, and cannot be run. Enable the tools listed below, or <a href="${h.url_for(controller='workflow', action='editor', id=trans.security.encode_id(workflow.id) )}" target="_parent">edit the workflow</a> to correct these errors.</strong><br/>
+ <ul>
+ %for i, tool in enumerate( missing_tools ):
+ <li>${tool}</li>
+ %endfor
+ </ul>
+</div>
\ No newline at end of file
diff -r 74b2495de918c95730f1f2fd2ac1bf502018a99f -r bd450366fc9da736c46358e6a827496c5c58d174 templates/webapps/galaxy/workflow/run.mako
--- a/templates/webapps/galaxy/workflow/run.mako
+++ b/templates/webapps/galaxy/workflow/run.mako
@@ -605,21 +605,11 @@
</div>
%endif
%endfor
-%if missing_tools:
- <div class='errormessage'>
- <strong>This workflow utilizes tools which are unavailable, and cannot be run. Enable the tools listed below, or <a href="${h.url_for(controller='workflow', action='editor', id=trans.security.encode_id(workflow.id) )}" target="_parent">edit the workflow</a> to correct these errors.</strong><br/>
- <ul>
- %for i, tool in enumerate( missing_tools ):
- <li>${tool}</li>
- %endfor
- </ul>
-%else:
- %if history_id is None:
-<p id='new_history_p'>
- <input type="checkbox" name='new_history' value="true" id='new_history_cbx'/><label for='new_history_cbx'>Send results to a new history </label>
- <span id="new_history_input">named: <input type='text' name='new_history_name' value='${ h.to_unicode( workflow.name ) | h }'/></span>
-</p>
- %endif
+%if history_id is None:
+ <p id='new_history_p'>
+ <input type="checkbox" name='new_history' value="true" id='new_history_cbx'/><label for='new_history_cbx'>Send results to a new history </label>
+ <span id="new_history_input">named: <input type='text' name='new_history_name' value='${ h.to_unicode( workflow.name ) | h }'/></span>
+ </p>
+%endif
<input type="submit" class="btn btn-primary" name="run_workflow" value="Run workflow" /></form>
-%endif
https://bitbucket.org/galaxy/galaxy-central/commits/89ab3ca6171d/
Changeset: 89ab3ca6171d
User: jmchilton
Date: 2014-09-09 22:41:34
Summary: Unify API for encoding runtime state across tool and input modules.
Add some documentation.
Affected #: 2 files
diff -r bd450366fc9da736c46358e6a827496c5c58d174 -r 89ab3ca6171d10d37d26fb7c50242bd6dcde45d9 lib/galaxy/workflow/modules.py
--- a/lib/galaxy/workflow/modules.py
+++ b/lib/galaxy/workflow/modules.py
@@ -114,6 +114,14 @@
raise TypeError( "Abstract method" )
def encode_runtime_state( self, trans, state ):
+ """ Encode the runtime state (loaded from the stored step and
+ populated via the WorkflowModuleInjector below) for use in a hidden
+ parameter on the webpage.
+
+ This will combined with runtime parameters supplied by user running
+ the workflow to create the final state to pass along to execute during
+ workflow invocation.
+ """
raise TypeError( "Abstract method" )
def decode_runtime_state( self, trans, string ):
@@ -460,6 +468,9 @@
return self.trans.fill_template( "workflow/editor_tool_form.mako",
tool=self.tool, values=self.state.inputs, errors=( self.errors or {} ) )
+ def encode_runtime_state( self, trans, state ):
+ return state.encode( self.tool, self.trans.app )
+
def update_state( self, incoming ):
# Build a callback that handles setting an input to be required at
# runtime. We still process all other parameters the user might have
diff -r bd450366fc9da736c46358e6a827496c5c58d174 -r 89ab3ca6171d10d37d26fb7c50242bd6dcde45d9 templates/webapps/galaxy/workflow/run.mako
--- a/templates/webapps/galaxy/workflow/run.mako
+++ b/templates/webapps/galaxy/workflow/run.mako
@@ -542,11 +542,15 @@
</script>
%endif
%for i, step in enumerate( steps ):
+ <!-- Only way module would be missing is if tool is missing, but
+ that would cause missing_tools.mako to render instead of this
+ template. -->
+ <% module = step.module %>
+ <input type="hidden" name="${step.id}|tool_state" value="${module.encode_runtime_state( t, step.state )}">
%if step.type == 'tool' or step.type is None:
<%
tool = trans.app.toolbox.get_tool( step.tool_id )
%>
- <input type="hidden" name="${step.id}|tool_state" value="${step.state.encode( tool, app )}"><div class="toolForm"><div class="toolFormTitle"><span class='title_ul_text'>Step ${int(step.order_index)+1}: ${tool.name}</span>
@@ -580,8 +584,6 @@
</div></div>
%else:
- <% module = step.module %>
- <input type="hidden" name="${step.id}|tool_state" value="${module.encode_runtime_state( t, step.state )}"><div class="toolForm"><div class="toolFormTitle"><span class='title_ul_text'>Step ${int(step.order_index)+1}: ${module.name}</span>
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
8 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/ce088c6f1fd4/
Changeset: ce088c6f1fd4
User: dannon
Date: 2014-09-08 22:41:53
Summary: First pass removing to_json_string/from_json_string.
Affected #: 107 files
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/datatypes/converters/bedgraph_to_array_tree_converter.py
--- a/lib/galaxy/datatypes/converters/bedgraph_to_array_tree_converter.py
+++ b/lib/galaxy/datatypes/converters/bedgraph_to_array_tree_converter.py
@@ -52,4 +52,4 @@
FileArrayTreeDict.dict_to_file( d, open( out_fname, "w" ) )
if __name__ == "__main__":
- main()
\ No newline at end of file
+ main()
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/datatypes/converters/fasta_to_len.py
--- a/lib/galaxy/datatypes/converters/fasta_to_len.py
+++ b/lib/galaxy/datatypes/converters/fasta_to_len.py
@@ -49,4 +49,4 @@
out.close()
if __name__ == "__main__" :
- compute_fasta_length( sys.argv[1], sys.argv[2], sys.argv[3], True )
\ No newline at end of file
+ compute_fasta_length( sys.argv[1], sys.argv[2], sys.argv[3], True )
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/datatypes/converters/fasta_to_tabular_converter.py
--- a/lib/galaxy/datatypes/converters/fasta_to_tabular_converter.py
+++ b/lib/galaxy/datatypes/converters/fasta_to_tabular_converter.py
@@ -40,4 +40,4 @@
print >> out, "%s\t%s" %( fasta_title, sequence )
out.close()
-if __name__ == "__main__" : __main__()
\ No newline at end of file
+if __name__ == "__main__" : __main__()
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/datatypes/converters/fastqsolexa_to_fasta_converter.py
--- a/lib/galaxy/datatypes/converters/fastqsolexa_to_fasta_converter.py
+++ b/lib/galaxy/datatypes/converters/fastqsolexa_to_fasta_converter.py
@@ -52,4 +52,4 @@
outfile.close()
-if __name__ == "__main__": __main__()
\ No newline at end of file
+if __name__ == "__main__": __main__()
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/datatypes/converters/interval_to_coverage.py
--- a/lib/galaxy/datatypes/converters/interval_to_coverage.py
+++ b/lib/galaxy/datatypes/converters/interval_to_coverage.py
@@ -149,4 +149,4 @@
fix_strand=True )
main( interval, coverage )
temp_file.close()
- coverage.close()
\ No newline at end of file
+ coverage.close()
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/datatypes/converters/wiggle_to_array_tree_converter.py
--- a/lib/galaxy/datatypes/converters/wiggle_to_array_tree_converter.py
+++ b/lib/galaxy/datatypes/converters/wiggle_to_array_tree_converter.py
@@ -26,4 +26,4 @@
FileArrayTreeDict.dict_to_file( d, open( out_fname, "w" ) )
if __name__ == "__main__":
- main()
\ No newline at end of file
+ main()
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/datatypes/tabular.py
--- a/lib/galaxy/datatypes/tabular.py
+++ b/lib/galaxy/datatypes/tabular.py
@@ -14,7 +14,7 @@
from galaxy.datatypes.checkers import is_gzip
from galaxy.datatypes.metadata import MetadataElement
from galaxy.datatypes.sniff import get_headers, get_test_fname
-from galaxy.util.json import to_json_string
+from galaxy.util.json import dumps
import dataproviders
log = logging.getLogger(__name__)
@@ -272,7 +272,7 @@
while cursor and ck_data[-1] != '\n':
ck_data += cursor
cursor = f.read(1)
- return to_json_string( { 'ck_data': util.unicodify( ck_data ), 'ck_index': ck_index + 1 } )
+ return dumps( { 'ck_data': util.unicodify( ck_data ), 'ck_index': ck_index + 1 } )
def display_data(self, trans, dataset, preview=False, filename=None, to_ext=None, chunk=None, **kwd):
preview = util.string_as_bool( preview )
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/datatypes/util/__init__.py
--- a/lib/galaxy/datatypes/util/__init__.py
+++ b/lib/galaxy/datatypes/util/__init__.py
@@ -1,3 +1,3 @@
"""
Utilities for Galaxy datatypes.
-"""
\ No newline at end of file
+"""
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/external_services/result_handlers/basic.py
--- a/lib/galaxy/external_services/result_handlers/basic.py
+++ b/lib/galaxy/external_services/result_handlers/basic.py
@@ -1,4 +1,4 @@
-from galaxy.util.json import to_json_string, from_json_string
+from galaxy.util.json import dumps, loads
from galaxy.util.template import fill_template
import logging
@@ -44,7 +44,7 @@
type = 'json_display'
def handle_result( self, result, param_dict, trans ):
- rval = from_json_string( result.content )
+ rval = loads( result.content )
return trans.fill_template( '/external_services/generic_json.mako', result = rval, param_dict = param_dict, action=self.parent )
class ExternalServiceActionJQueryGridResultHandler( ExternalServiceActionResultHandler ):
@@ -53,7 +53,7 @@
type = 'jquery_grid'
def handle_result( self, result, param_dict, trans ):
- rval = from_json_string( result.content )
+ rval = loads( result.content )
return trans.fill_template( '/external_services/generic_jquery_grid.mako', result = rval, param_dict = param_dict, action=self.parent )
result_type_to_class = {}
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/jobs/__init__.py
--- a/lib/galaxy/jobs/__init__.py
+++ b/lib/galaxy/jobs/__init__.py
@@ -25,7 +25,7 @@
from galaxy.jobs.runners import BaseJobRunner, JobState
from galaxy.util.bunch import Bunch
from galaxy.util.expressions import ExpressionContext
-from galaxy.util.json import from_json_string
+from galaxy.util.json import loads
from galaxy.util import unicodify
from .output_checker import check_output
@@ -723,7 +723,7 @@
self.job_runner_mapper = JobRunnerMapper( self, queue.dispatcher.url_to_destination, self.app.job_config )
self.params = None
if job.params:
- self.params = from_json_string( job.params )
+ self.params = loads( job.params )
if use_persisted_destination:
self.job_runner_mapper.cached_job_destination = JobDestination( from_job=job )
@@ -1390,7 +1390,7 @@
if os.path.exists( meta_file ):
for line in open( meta_file, 'r' ):
try:
- line = from_json_string( line )
+ line = loads( line )
assert 'type' in line
except:
log.exception( '(%s) Got JSON data from tool, but data is improperly formatted or no "type" key in data' % self.job_id )
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/jobs/actions/__init__.py
--- a/lib/galaxy/jobs/actions/__init__.py
+++ b/lib/galaxy/jobs/actions/__init__.py
@@ -1,4 +1,4 @@
"""
This package contains job action classes.
-"""
\ No newline at end of file
+"""
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/jobs/actions/post.py
--- a/lib/galaxy/jobs/actions/post.py
+++ b/lib/galaxy/jobs/actions/post.py
@@ -5,7 +5,7 @@
import datetime
import logging
from galaxy.util import send_mail
-from galaxy.util.json import to_json_string
+from galaxy.util.json import dumps
log = logging.getLogger( __name__ )
@@ -461,7 +461,7 @@
else:
# Not pja stuff.
pass
- return to_json_string(npd)
+ return dumps(npd)
@classmethod
def get_add_list(cls):
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/jobs/deferred/pacific_biosciences_smrt_portal.py
--- a/lib/galaxy/jobs/deferred/pacific_biosciences_smrt_portal.py
+++ b/lib/galaxy/jobs/deferred/pacific_biosciences_smrt_portal.py
@@ -83,7 +83,7 @@
return self.job_states.INVALID
url = 'http://' + job.params[ 'smrt_host' ] + self.api_path + '/Jobs/' + job.params[ 'smrt_job_id' ] + '/Status'
r = urllib2.urlopen( url )
- status = json.from_json_string( r.read() )
+ status = json.loads( r.read() )
# TODO: error handling: unexpected json or bad response, bad url, etc.
if status[ 'Code' ] == 'Completed':
log.debug( "SMRT Portal job '%s' is Completed. Initiating transfer." % job.params[ 'smrt_job_id' ] )
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/jobs/transfer_manager.py
--- a/lib/galaxy/jobs/transfer_manager.py
+++ b/lib/galaxy/jobs/transfer_manager.py
@@ -82,7 +82,7 @@
sock = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
sock.settimeout( 5 )
sock.connect( ( 'localhost', tj.socket ) )
- sock.send( json.to_json_string( request ) )
+ sock.send( json.dumps( request ) )
response = sock.recv( 8192 )
valid, response = json.validate_jsonrpc_response( response, id=request['id'] )
if not valid:
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/managers/context.py
--- a/lib/galaxy/managers/context.py
+++ b/lib/galaxy/managers/context.py
@@ -4,7 +4,7 @@
import os
-from galaxy.util.json import to_json_string
+from galaxy.util.json import dumps
from galaxy.util import bunch
class ProvidesAppContext( object ):
@@ -19,7 +19,7 @@
Application-level logging of user actions.
"""
if self.app.config.log_actions:
- action = self.app.model.UserAction(action=action, context=context, params=unicode( to_json_string( params ) ) )
+ action = self.app.model.UserAction(action=action, context=context, params=unicode( dumps( params ) ) )
try:
if user:
action.user = user
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/model/migrate/versions/0052_sample_dataset_table.py
--- a/lib/galaxy/model/migrate/versions/0052_sample_dataset_table.py
+++ b/lib/galaxy/model/migrate/versions/0052_sample_dataset_table.py
@@ -10,7 +10,7 @@
from sqlalchemy.exc import *
from galaxy.model.custom_types import *
-from galaxy.util.json import from_json_string, to_json_string
+from galaxy.util.json import loads, dumps
import datetime
now = datetime.datetime.utcnow
@@ -62,7 +62,7 @@
for r in result:
sample_id = r[0]
if r[1]:
- dataset_files = from_json_string(r[1])
+ dataset_files = loads(r[1])
for df in dataset_files:
if type(df) == type(dict()):
cmd = "INSERT INTO sample_dataset VALUES (%s, %s, %s, %s, '%s', '%s', '%s', '%s', '%s')"
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/model/migrate/versions/0054_visualization_dbkey.py
--- a/lib/galaxy/model/migrate/versions/0054_visualization_dbkey.py
+++ b/lib/galaxy/model/migrate/versions/0054_visualization_dbkey.py
@@ -6,7 +6,7 @@
from sqlalchemy.orm import *
from migrate import *
from migrate.changeset import *
-from galaxy.util.json import from_json_string
+from galaxy.util.json import loads
import logging
log = logging.getLogger( __name__ )
@@ -41,7 +41,7 @@
viz_id = viz['viz_id']
viz_rev_id = viz['viz_rev_id']
if viz[Visualization_revision_table.c.config]:
- dbkey = from_json_string(viz[Visualization_revision_table.c.config]).get('dbkey', "").replace("'", "\\'")
+ dbkey = loads(viz[Visualization_revision_table.c.config]).get('dbkey', "").replace("'", "\\'")
migrate_engine.execute("UPDATE visualization_revision SET dbkey='%s' WHERE id=%s" % (dbkey, viz_rev_id))
migrate_engine.execute("UPDATE visualization SET dbkey='%s' WHERE id=%s" % (dbkey, viz_id))
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/model/migrate/versions/0057_request_notify.py
--- a/lib/galaxy/model/migrate/versions/0057_request_notify.py
+++ b/lib/galaxy/model/migrate/versions/0057_request_notify.py
@@ -10,7 +10,7 @@
from sqlalchemy.exc import *
from galaxy.model.custom_types import *
-from galaxy.util.json import from_json_string, to_json_string
+from galaxy.util.json import loads, dumps
import datetime
now = datetime.datetime.utcnow
@@ -46,13 +46,13 @@
id = int(r[0])
notify_old = r[1]
notify_new = dict(email=[], sample_states=[], body='', subject='')
- cmd = "update request set notification='%s' where id=%i" % (to_json_string(notify_new), id)
+ cmd = "update request set notification='%s' where id=%i" % (dumps(notify_new), id)
migrate_engine.execute( cmd )
cmd = "SELECT id, notification FROM request"
result = migrate_engine.execute( cmd )
for r in result:
- rr = from_json_string(str(r[1]))
+ rr = loads(str(r[1]))
# remove the 'notify' column for non-sqlite databases.
if migrate_engine.name != 'sqlite':
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/model/migrate/versions/0059_sample_dataset_file_path.py
--- a/lib/galaxy/model/migrate/versions/0059_sample_dataset_file_path.py
+++ b/lib/galaxy/model/migrate/versions/0059_sample_dataset_file_path.py
@@ -10,7 +10,7 @@
from sqlalchemy.exc import *
from galaxy.model.custom_types import *
-from galaxy.util.json import from_json_string, to_json_string
+from galaxy.util.json import loads, dumps
import datetime
now = datetime.datetime.utcnow
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/model/migrate/versions/0065_add_name_to_form_fields_and_values.py
--- a/lib/galaxy/model/migrate/versions/0065_add_name_to_form_fields_and_values.py
+++ b/lib/galaxy/model/migrate/versions/0065_add_name_to_form_fields_and_values.py
@@ -9,7 +9,7 @@
from migrate import *
from migrate.changeset import *
from sqlalchemy.exc import *
-from galaxy.util.json import from_json_string, to_json_string
+from galaxy.util.json import loads, dumps
from galaxy.model.custom_types import _sniffnfix_pg9_hex
import datetime
@@ -53,13 +53,13 @@
fields = str( row[1] )
if not fields.strip():
continue
- fields_list = from_json_string( _sniffnfix_pg9_hex( fields ) )
+ fields_list = loads( _sniffnfix_pg9_hex( fields ) )
if len( fields_list ):
for index, field in enumerate( fields_list ):
field[ 'name' ] = 'field_%i' % index
field[ 'helptext' ] = field[ 'helptext' ].replace("'", "''").replace('"', "")
field[ 'label' ] = field[ 'label' ].replace("'", "''")
- fields_json = to_json_string( fields_list )
+ fields_json = dumps( fields_list )
if migrate_engine.name == 'mysql':
cmd = "UPDATE form_definition AS f SET f.fields='%s' WHERE f.id=%i" %( fields_json, form_definition_id )
else:
@@ -76,16 +76,16 @@
if not str( row[1] ).strip():
continue
row1 = str(row[1]).replace('\n', '').replace('\r', '')
- values_list = from_json_string( str( row1 ).strip() )
+ values_list = loads( str( row1 ).strip() )
if not str( row[2] ).strip():
continue
- fields_list = from_json_string( str( row[2] ).strip() )
+ fields_list = loads( str( row[2] ).strip() )
if fields_list and type(values_list) == type(list()):
values_dict = {}
for field_index, field in enumerate( fields_list ):
field_name = field[ 'name' ]
values_dict[ field_name ] = get_value(values_list, field_index )
- cmd = "UPDATE form_values SET content='%s' WHERE id=%i" %( to_json_string( values_dict ), form_values_id )
+ cmd = "UPDATE form_values SET content='%s' WHERE id=%i" %( dumps( values_dict ), form_values_id )
migrate_engine.execute( cmd )
def downgrade(migrate_engine):
@@ -110,17 +110,17 @@
form_values_id = int( row[0] )
if not str( row[1] ).strip():
continue
- values_dict = from_json_string( str( row[1] ) )
+ values_dict = loads( str( row[1] ) )
if not str( row[2] ).strip():
continue
- fields_list = from_json_string( str( row[2] ) )
+ fields_list = loads( str( row[2] ) )
if fields_list:
values_list = []
for field_index, field in enumerate( fields_list ):
field_name = field[ 'name' ]
field_value = values_dict[ field_name ]
values_list.append( field_value )
- cmd = "UPDATE form_values SET content='%s' WHERE id=%i" %( to_json_string( values_list ), form_values_id )
+ cmd = "UPDATE form_values SET content='%s' WHERE id=%i" %( dumps( values_list ), form_values_id )
migrate_engine.execute( cmd )
# remove name attribute from the field column of the form_definition table
cmd = "SELECT f.id, f.fields FROM form_definition AS f"
@@ -130,13 +130,13 @@
fields = str( row[1] )
if not fields.strip():
continue
- fields_list = from_json_string( _sniffnfix_pg9_hex( fields ) )
+ fields_list = loads( _sniffnfix_pg9_hex( fields ) )
if len( fields_list ):
for index, field in enumerate( fields_list ):
if field.has_key( 'name' ):
del field[ 'name' ]
if migrate_engine.name == 'mysql':
- cmd = "UPDATE form_definition AS f SET f.fields='%s' WHERE f.id=%i" %( to_json_string( fields_list ), form_definition_id )
+ cmd = "UPDATE form_definition AS f SET f.fields='%s' WHERE f.id=%i" %( dumps( fields_list ), form_definition_id )
else:
- cmd = "UPDATE form_definition SET fields='%s' WHERE id=%i" %( to_json_string( fields_list ), form_definition_id )
+ cmd = "UPDATE form_definition SET fields='%s' WHERE id=%i" %( dumps( fields_list ), form_definition_id )
migrate_engine.execute( cmd )
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/model/migrate/versions/0067_populate_sequencer_table.py
--- a/lib/galaxy/model/migrate/versions/0067_populate_sequencer_table.py
+++ b/lib/galaxy/model/migrate/versions/0067_populate_sequencer_table.py
@@ -13,7 +13,7 @@
from galaxy.model.custom_types import *
-from galaxy.util.json import from_json_string, to_json_string
+from galaxy.util.json import loads, dumps
import datetime
now = datetime.datetime.utcnow
@@ -104,7 +104,7 @@
'layout': 'none',
'default': '' } )
form_definition_type = 'Sequencer Information Form'
- form_definition_layout = to_json_string('[]')
+ form_definition_layout = dumps('[]')
cmd = "INSERT INTO form_definition VALUES ( %s, %s, %s, '%s', '%s', %s, '%s', '%s', '%s' )"
cmd = cmd % ( nextval( 'form_definition' ),
localtimestamp(),
@@ -112,7 +112,7 @@
form_definition_name,
form_definition_desc,
form_definition_current_id,
- to_json_string( form_definition_fields ),
+ dumps( form_definition_fields ),
form_definition_type,
form_definition_layout )
migrate_engine.execute( cmd )
@@ -134,7 +134,7 @@
values = str( row[1] )
if not values.strip():
continue
- values = from_json_string( values )
+ values = loads( values )
# proceed only if sequencer_info is a valid list
if values and type( values ) == type( dict() ):
if sequencer_info.get( 'host', '' ) == values.get( 'field_0', '' ) \
@@ -148,7 +148,7 @@
def add_sequencer( sequencer_index, sequencer_form_definition_id, sequencer_info ):
'''Adds a new sequencer to the sequencer table along with its form values.'''
# Create a new form values record with the supplied sequencer information
- values = to_json_string( { 'field_0': sequencer_info.get( 'host', '' ),
+ values = dumps( { 'field_0': sequencer_info.get( 'host', '' ),
'field_1': sequencer_info.get( 'username', '' ),
'field_2': sequencer_info.get( 'password', '' ),
'field_3': sequencer_info.get( 'data_dir', '' ),
@@ -233,7 +233,7 @@
# skip if sequencer_info is empty
if not sequencer_info.strip() or sequencer_info in ['None', 'null']:
continue
- sequencer_info = from_json_string( sequencer_info.strip() )
+ sequencer_info = loads( sequencer_info.strip() )
# proceed only if sequencer_info is a valid dict
if sequencer_info and type( sequencer_info ) == type( dict() ):
# check if this sequencer has already been added to the sequencer table
@@ -277,9 +277,9 @@
result = migrate_engine.execute( cmd )
for row in result:
request_type_id = row[0]
- seq_values = from_json_string( str( row[1] ) )
+ seq_values = loads( str( row[1] ) )
# create the datatx_info json dict
- datatx_info = to_json_string( dict( host = seq_values.get( 'field_0', '' ),
+ datatx_info = dumps( dict( host = seq_values.get( 'field_0', '' ),
username = seq_values.get( 'field_1', '' ),
password = seq_values.get( 'field_2', '' ),
data_dir = seq_values.get( 'field_3', '' ),
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/model/migrate/versions/0068_rename_sequencer_to_external_services.py
--- a/lib/galaxy/model/migrate/versions/0068_rename_sequencer_to_external_services.py
+++ b/lib/galaxy/model/migrate/versions/0068_rename_sequencer_to_external_services.py
@@ -15,7 +15,7 @@
from galaxy.model.custom_types import *
-from galaxy.util.json import from_json_string, to_json_string
+from galaxy.util.json import loads, dumps
import datetime
now = datetime.datetime.utcnow
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/model/migrate/versions/0076_fix_form_values_data_corruption.py
--- a/lib/galaxy/model/migrate/versions/0076_fix_form_values_data_corruption.py
+++ b/lib/galaxy/model/migrate/versions/0076_fix_form_values_data_corruption.py
@@ -9,7 +9,7 @@
from sqlalchemy.exc import *
import binascii
-from galaxy.util.json import from_json_string, to_json_string
+from galaxy.util.json import loads, dumps
import logging
log = logging.getLogger( __name__ )
@@ -42,11 +42,11 @@
# first check if loading the dict from the json succeeds
# if that fails, it means that the content field is corrupted.
try:
- field_values_dict = from_json_string( _sniffnfix_pg9_hex( str( row['field_values'] ) ) )
+ field_values_dict = loads( _sniffnfix_pg9_hex( str( row['field_values'] ) ) )
except Exception, e:
corrupted_rows = corrupted_rows + 1
# content field is corrupted
- fields_list = from_json_string( _sniffnfix_pg9_hex( str( row['fdfields'] ) ) )
+ fields_list = loads( _sniffnfix_pg9_hex( str( row['fdfields'] ) ) )
field_values_str = _sniffnfix_pg9_hex( str( row['field_values'] ) )
try:
#Encoding errors? Just to be safe.
@@ -85,7 +85,7 @@
# add to the new values dict
field_values_dict[ field['name'] ] = value
# update the db
- json_values = to_json_string(field_values_dict)
+ json_values = dumps(field_values_dict)
cmd = "UPDATE form_values SET content='%s' WHERE id=%i" %( json_values, int( row['id'] ) )
migrate_engine.execute( cmd )
try:
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/model/migrate/versions/0091_add_tool_version_tables.py
--- a/lib/galaxy/model/migrate/versions/0091_add_tool_version_tables.py
+++ b/lib/galaxy/model/migrate/versions/0091_add_tool_version_tables.py
@@ -12,7 +12,7 @@
# Need our custom types, but don't import anything else from model
from galaxy.model.custom_types import *
from galaxy.model.custom_types import _sniffnfix_pg9_hex
-from galaxy.util.json import from_json_string, to_json_string
+from galaxy.util.json import loads, dumps
import sys, logging
log = logging.getLogger( __name__ )
@@ -77,7 +77,7 @@
for row in result:
if row[1]:
tool_shed_repository_id = row[0]
- repository_metadata = from_json_string( _sniffnfix_pg9_hex( str( row[1] ) ) )
+ repository_metadata = loads( _sniffnfix_pg9_hex( str( row[1] ) ) )
# Create a new row in the tool table for each tool included in repository. We will NOT
# handle tool_version_associaions because we do not have the information we need to do so.
tools = repository_metadata.get( 'tools', [] )
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/model/migrate/versions/0115_longer_user_password_field.py
--- a/lib/galaxy/model/migrate/versions/0115_longer_user_password_field.py
+++ b/lib/galaxy/model/migrate/versions/0115_longer_user_password_field.py
@@ -22,4 +22,4 @@
try:
user.c.password.alter(type=String(40))
except:
- log.exception( "Altering password column failed" )
\ No newline at end of file
+ log.exception( "Altering password column failed" )
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/model/migrate/versions/0117_add_user_activation.py
--- a/lib/galaxy/model/migrate/versions/0117_add_user_activation.py
+++ b/lib/galaxy/model/migrate/versions/0117_add_user_activation.py
@@ -54,4 +54,4 @@
user_active.drop()
user_activation_token.drop()
except Exception, e:
- log.debug( "Dropping 'active' and 'activation_token' columns from galaxy_user table failed: %s" % ( str( e ) ) )
\ No newline at end of file
+ log.debug( "Dropping 'active' and 'activation_token' columns from galaxy_user table failed: %s" % ( str( e ) ) )
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/model/orm/logging_connection_proxy.py
--- a/lib/galaxy/model/orm/logging_connection_proxy.py
+++ b/lib/galaxy/model/orm/logging_connection_proxy.py
@@ -45,4 +45,4 @@
self.trace_logger.log( "sqlalchemy_query",
message="Query executed", statement=statement, parameters=parameters,
executemany=executemany, duration=duration )
- return rval
\ No newline at end of file
+ return rval
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/model/search.py
--- a/lib/galaxy/model/search.py
+++ b/lib/galaxy/model/search.py
@@ -39,7 +39,7 @@
Page, PageRevision)
from galaxy.model.tool_shed_install import ToolVersion
-from galaxy.util.json import to_json_string
+from galaxy.util.json import dumps
from sqlalchemy import and_
from sqlalchemy.orm import aliased
@@ -429,7 +429,7 @@
and_(
Job.id == alias.job_id,
alias.name == param_name,
- alias.value == to_json_string(right)
+ alias.value == dumps(right)
)
)
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/model/tool_shed_install/migrate/versions/0001_add_tool_shed_repository_table.py
--- a/lib/galaxy/model/tool_shed_install/migrate/versions/0001_add_tool_shed_repository_table.py
+++ b/lib/galaxy/model/tool_shed_install/migrate/versions/0001_add_tool_shed_repository_table.py
@@ -1,1 +1,51 @@
-../../../migrate/versions/0082_add_tool_shed_repository_table.py
\ No newline at end of file
+"""
+Migration script to add the tool_shed_repository table.
+"""
+from sqlalchemy import *
+from sqlalchemy.orm import *
+from migrate import *
+from migrate.changeset import *
+import sys, logging
+from galaxy.model.custom_types import *
+from sqlalchemy.exc import *
+import datetime
+now = datetime.datetime.utcnow
+
+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 )
+
+metadata = MetaData()
+
+# New table to store information about cloned tool shed repositories.
+ToolShedRepository_table = Table( "tool_shed_repository", metadata,
+ Column( "id", Integer, primary_key=True ),
+ Column( "create_time", DateTime, default=now ),
+ Column( "update_time", DateTime, default=now, onupdate=now ),
+ Column( "tool_shed", TrimmedString( 255 ), index=True ),
+ Column( "name", TrimmedString( 255 ), index=True ),
+ Column( "description" , TEXT ),
+ Column( "owner", TrimmedString( 255 ), index=True ),
+ Column( "changeset_revision", TrimmedString( 255 ), index=True ),
+ Column( "deleted", Boolean, index=True, default=False ) )
+
+def upgrade(migrate_engine):
+ metadata.bind = migrate_engine
+ print __doc__
+ metadata.reflect()
+ try:
+ ToolShedRepository_table.create()
+ except Exception, e:
+ log.debug( "Creating tool_shed_repository table failed: %s" % str( e ) )
+
+def downgrade(migrate_engine):
+ metadata.bind = migrate_engine
+ metadata.reflect()
+ try:
+ ToolShedRepository_table.drop()
+ except Exception, e:
+ log.debug( "Dropping tool_shed_repository table failed: %s" % str( e ) )
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/model/tool_shed_install/migrate/versions/0002_add_tool_shed_repository_table_columns.py
--- a/lib/galaxy/model/tool_shed_install/migrate/versions/0002_add_tool_shed_repository_table_columns.py
+++ b/lib/galaxy/model/tool_shed_install/migrate/versions/0002_add_tool_shed_repository_table_columns.py
@@ -1,1 +1,79 @@
-../../../migrate/versions/0086_add_tool_shed_repository_table_columns.py
\ No newline at end of file
+"""
+Migration script to add the metadata, update_available and includes_datatypes columns to the tool_shed_repository table.
+"""
+
+from sqlalchemy import *
+from sqlalchemy.orm import *
+from migrate import *
+from migrate.changeset import *
+
+import datetime
+now = datetime.datetime.utcnow
+# Need our custom types, but don't import anything else from model
+from galaxy.model.custom_types import *
+
+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 )
+
+metadata = MetaData()
+
+def get_default_false(migrate_engine):
+ if migrate_engine.name == 'mysql' or migrate_engine.name == 'sqlite':
+ return "0"
+ elif migrate_engine.name in ['postgresql', 'postgres']:
+ return "false"
+
+def upgrade(migrate_engine):
+ metadata.bind = migrate_engine
+ print __doc__
+ metadata.reflect()
+ ToolShedRepository_table = Table( "tool_shed_repository", metadata, autoload=True )
+ c = Column( "metadata", JSONType(), nullable=True )
+ try:
+ c.create( ToolShedRepository_table )
+ assert c is ToolShedRepository_table.c.metadata
+ except Exception, e:
+ print "Adding metadata column to the tool_shed_repository table failed: %s" % str( e )
+ log.debug( "Adding metadata column to the tool_shed_repository table failed: %s" % str( e ) )
+ c = Column( "includes_datatypes", Boolean, index=True, default=False )
+ try:
+ c.create( ToolShedRepository_table, index_name="ix_tool_shed_repository_includes_datatypes")
+ assert c is ToolShedRepository_table.c.includes_datatypes
+ migrate_engine.execute( "UPDATE tool_shed_repository SET includes_datatypes=%s" % get_default_false(migrate_engine))
+ except Exception, e:
+ print "Adding includes_datatypes column to the tool_shed_repository table failed: %s" % str( e )
+ log.debug( "Adding includes_datatypes column to the tool_shed_repository table failed: %s" % str( e ) )
+ c = Column( "update_available", Boolean, default=False )
+ try:
+ c.create( ToolShedRepository_table )
+ assert c is ToolShedRepository_table.c.update_available
+ migrate_engine.execute( "UPDATE tool_shed_repository SET update_available=%s" % get_default_false(migrate_engine))
+ except Exception, e:
+ print "Adding update_available column to the tool_shed_repository table failed: %s" % str( e )
+ log.debug( "Adding update_available column to the tool_shed_repository table failed: %s" % str( e ) )
+
+def downgrade(migrate_engine):
+ metadata.bind = migrate_engine
+ metadata.reflect()
+ ToolShedRepository_table = Table( "tool_shed_repository", metadata, autoload=True )
+ try:
+ ToolShedRepository_table.c.metadata.drop()
+ except Exception, e:
+ print "Dropping column metadata from the tool_shed_repository table failed: %s" % str( e )
+ log.debug( "Dropping column metadata from the tool_shed_repository table failed: %s" % str( e ) )
+ try:
+ ToolShedRepository_table.c.includes_datatypes.drop()
+ except Exception, e:
+ print "Dropping column includes_datatypes from the tool_shed_repository table failed: %s" % str( e )
+ log.debug( "Dropping column includes_datatypes from the tool_shed_repository table failed: %s" % str( e ) )
+ try:
+ ToolShedRepository_table.c.update_available.drop()
+ except Exception, e:
+ print "Dropping column update_available from the tool_shed_repository table failed: %s" % str( e )
+ log.debug( "Dropping column update_available from the tool_shed_repository table failed: %s" % str( e ) )
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/model/tool_shed_install/migrate/versions/0003_tool_id_guid_map_table.py
--- a/lib/galaxy/model/tool_shed_install/migrate/versions/0003_tool_id_guid_map_table.py
+++ b/lib/galaxy/model/tool_shed_install/migrate/versions/0003_tool_id_guid_map_table.py
@@ -1,1 +1,52 @@
-../../../migrate/versions/0087_tool_id_guid_map_table.py
\ No newline at end of file
+"""
+Migration script to create the tool_id_guid_map table.
+"""
+
+from sqlalchemy import *
+from sqlalchemy.orm import *
+from migrate import *
+from migrate.changeset import *
+
+import datetime
+now = datetime.datetime.utcnow
+# Need our custom types, but don't import anything else from model
+from galaxy.model.custom_types import *
+
+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 )
+
+metadata = MetaData()
+
+ToolIdGuidMap_table = Table( "tool_id_guid_map", metadata,
+ Column( "id", Integer, primary_key=True ),
+ Column( "create_time", DateTime, default=now ),
+ Column( "update_time", DateTime, default=now, onupdate=now ),
+ Column( "tool_id", String( 255 ) ),
+ Column( "tool_version", TEXT ),
+ Column( "tool_shed", TrimmedString( 255 ) ),
+ Column( "repository_owner", TrimmedString( 255 ) ),
+ Column( "repository_name", TrimmedString( 255 ) ),
+ Column( "guid", TEXT, index=True, unique=True ) )
+
+def upgrade(migrate_engine):
+ metadata.bind = migrate_engine
+ print __doc__
+ metadata.reflect()
+ try:
+ ToolIdGuidMap_table.create()
+ except Exception, e:
+ log.debug( "Creating tool_id_guid_map table failed: %s" % str( e ) )
+
+def downgrade(migrate_engine):
+ metadata.bind = migrate_engine
+ metadata.reflect()
+ try:
+ ToolIdGuidMap_table.drop()
+ except Exception, e:
+ log.debug( "Dropping tool_id_guid_map table failed: %s" % str( e ) )
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/model/tool_shed_install/migrate/versions/0004_add_installed_changeset_revison_column.py
--- a/lib/galaxy/model/tool_shed_install/migrate/versions/0004_add_installed_changeset_revison_column.py
+++ b/lib/galaxy/model/tool_shed_install/migrate/versions/0004_add_installed_changeset_revison_column.py
@@ -1,1 +1,64 @@
-../../../migrate/versions/0088_add_installed_changeset_revison_column.py
\ No newline at end of file
+"""
+Migration script to add the installed_changeset_revision column to the tool_shed_repository table.
+"""
+
+from sqlalchemy import *
+from sqlalchemy.orm import *
+from migrate import *
+from migrate.changeset import *
+
+import datetime
+now = datetime.datetime.utcnow
+# Need our custom types, but don't import anything else from model
+from galaxy.model.custom_types import *
+
+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 )
+
+metadata = MetaData()
+
+def upgrade(migrate_engine):
+ metadata.bind = migrate_engine
+ print __doc__
+ metadata.reflect()
+ ToolShedRepository_table = Table( "tool_shed_repository", metadata, autoload=True )
+ col = Column( "installed_changeset_revision", TrimmedString( 255 ) )
+ try:
+ col.create( ToolShedRepository_table )
+ assert col is ToolShedRepository_table.c.installed_changeset_revision
+ except Exception, e:
+ print "Adding installed_changeset_revision column to the tool_shed_repository table failed: %s" % str( e )
+ log.debug( "Adding installed_changeset_revision column to the tool_shed_repository table failed: %s" % str( e ) )
+ # Update each row by setting the value of installed_changeset_revison to be the value of changeset_revision.
+ # This will be problematic if the value of changeset_revision was updated to something other than the value
+ # that it was when the repository was installed (because the install path determined in real time will attempt to
+ # find the repository using the updated changeset_revison instead of the required installed_changeset_revision),
+ # but at the time this script was written, this scenario is extremely unlikely.
+ cmd = "SELECT id AS id, " \
+ + "installed_changeset_revision AS installed_changeset_revision, " \
+ + "changeset_revision AS changeset_revision " \
+ + "FROM tool_shed_repository;"
+ tool_shed_repositories = migrate_engine.execute( cmd ).fetchall()
+ update_count = 0
+ for row in tool_shed_repositories:
+ cmd = "UPDATE tool_shed_repository " \
+ + "SET installed_changeset_revision = '%s' " % row.changeset_revision \
+ + "WHERE changeset_revision = '%s';" % row.changeset_revision
+ migrate_engine.execute( cmd )
+ update_count += 1
+ print "Updated the installed_changeset_revision column for ", update_count, " rows in the tool_shed_repository table. "
+def downgrade(migrate_engine):
+ metadata.bind = migrate_engine
+ metadata.reflect()
+ ToolShedRepository_table = Table( "tool_shed_repository", metadata, autoload=True )
+ try:
+ ToolShedRepository_table.c.installed_changeset_revision.drop()
+ except Exception, e:
+ print "Dropping column installed_changeset_revision from the tool_shed_repository table failed: %s" % str( e )
+ log.debug( "Dropping column installed_changeset_revision from the tool_shed_repository table failed: %s" % str( e ) )
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/model/tool_shed_install/migrate/versions/0005_add_tool_shed_repository_table_columns.py
--- a/lib/galaxy/model/tool_shed_install/migrate/versions/0005_add_tool_shed_repository_table_columns.py
+++ b/lib/galaxy/model/tool_shed_install/migrate/versions/0005_add_tool_shed_repository_table_columns.py
@@ -1,1 +1,63 @@
-../../../migrate/versions/0090_add_tool_shed_repository_table_columns.py
\ No newline at end of file
+"""
+Migration script to add the uninstalled and dist_to_shed columns to the tool_shed_repository table.
+"""
+
+from sqlalchemy import *
+from sqlalchemy.orm import *
+from migrate import *
+from migrate.changeset import *
+
+import datetime
+now = datetime.datetime.utcnow
+# Need our custom types, but don't import anything else from model
+from galaxy.model.custom_types import *
+
+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 )
+
+metadata = MetaData()
+
+def default_false(migrate_engine):
+ if migrate_engine.name == 'mysql' or migrate_engine.name == 'sqlite':
+ return "0"
+ elif migrate_engine.name in ['postgresql', 'postgres']:
+ return "false"
+
+def upgrade(migrate_engine):
+ metadata.bind = migrate_engine
+ print __doc__
+ metadata.reflect()
+ ToolShedRepository_table = Table( "tool_shed_repository", metadata, autoload=True )
+ c = Column( "uninstalled", Boolean, default=False )
+ try:
+ c.create( ToolShedRepository_table )
+ assert c is ToolShedRepository_table.c.uninstalled
+ migrate_engine.execute( "UPDATE tool_shed_repository SET uninstalled=%s" % default_false(migrate_engine) )
+ except Exception, e:
+ print "Adding uninstalled column to the tool_shed_repository table failed: %s" % str( e )
+ c = Column( "dist_to_shed", Boolean, default=False )
+ try:
+ c.create( ToolShedRepository_table )
+ assert c is ToolShedRepository_table.c.dist_to_shed
+ migrate_engine.execute( "UPDATE tool_shed_repository SET dist_to_shed=%s" % default_false(migrate_engine) )
+ except Exception, e:
+ print "Adding dist_to_shed column to the tool_shed_repository table failed: %s" % str( e )
+
+def downgrade(migrate_engine):
+ metadata.bind = migrate_engine
+ metadata.reflect()
+ ToolShedRepository_table = Table( "tool_shed_repository", metadata, autoload=True )
+ try:
+ ToolShedRepository_table.c.uninstalled.drop()
+ except Exception, e:
+ print "Dropping column uninstalled from the tool_shed_repository table failed: %s" % str( e )
+ try:
+ ToolShedRepository_table.c.dist_to_shed.drop()
+ except Exception, e:
+ print "Dropping column dist_to_shed from the tool_shed_repository table failed: %s" % str( e )
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/model/tool_shed_install/migrate/versions/0006_add_tool_version_tables.py
--- a/lib/galaxy/model/tool_shed_install/migrate/versions/0006_add_tool_version_tables.py
+++ b/lib/galaxy/model/tool_shed_install/migrate/versions/0006_add_tool_version_tables.py
@@ -1,1 +1,122 @@
-../../../migrate/versions/0091_add_tool_version_tables.py
\ No newline at end of file
+"""
+Migration script to create the tool_version and tool_version_association tables and drop the tool_id_guid_map table.
+"""
+
+from sqlalchemy import *
+from sqlalchemy.orm import *
+from migrate import *
+from migrate.changeset import *
+
+import datetime
+now = datetime.datetime.utcnow
+# Need our custom types, but don't import anything else from model
+from galaxy.model.custom_types import *
+from galaxy.model.custom_types import _sniffnfix_pg9_hex
+from galaxy.util.json import loads, dumps
+
+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 )
+
+metadata = MetaData()
+#migrate_engine = scoped_session( sessionmaker( bind=migrate_engine, autoflush=False, autocommit=True ) )
+
+def nextval( table, col='id' ):
+ if migrate_engine.name == 'postgres':
+ return "nextval('%s_%s_seq')" % ( table, col )
+ elif migrate_engine.name == 'mysql' or migrate_engine.name == 'sqlite':
+ return "null"
+ else:
+ raise Exception( 'Unable to convert data for unknown database type: %s' % migrate_engine.name )
+
+def localtimestamp():
+ if migrate_engine.name == 'postgres' or migrate_engine.name == 'mysql':
+ return "LOCALTIMESTAMP"
+ elif migrate_engine.name == 'sqlite':
+ return "current_date || ' ' || current_time"
+ else:
+ raise Exception( 'Unable to convert data for unknown database type: %s' % db )
+
+ToolVersion_table = Table( "tool_version", metadata,
+ Column( "id", Integer, primary_key=True ),
+ Column( "create_time", DateTime, default=now ),
+ Column( "update_time", DateTime, default=now, onupdate=now ),
+ Column( "tool_id", String( 255 ) ),
+ Column( "tool_shed_repository_id", Integer, ForeignKey( "tool_shed_repository.id" ), index=True, nullable=True ) )
+
+ToolVersionAssociation_table = Table( "tool_version_association", metadata,
+ Column( "id", Integer, primary_key=True ),
+ Column( "tool_id", Integer, ForeignKey( "tool_version.id" ), index=True, nullable=False ),
+ Column( "parent_id", Integer, ForeignKey( "tool_version.id" ), index=True, nullable=False ) )
+
+def upgrade(migrate_engine):
+ metadata.bind = migrate_engine
+ print __doc__
+
+ ToolIdGuidMap_table = Table( "tool_id_guid_map", metadata, autoload=True )
+
+ metadata.reflect()
+ # Create the tables.
+ try:
+ ToolVersion_table.create()
+ except Exception, e:
+ log.debug( "Creating tool_version table failed: %s" % str( e ) )
+ try:
+ ToolVersionAssociation_table.create()
+ except Exception, e:
+ log.debug( "Creating tool_version_association table failed: %s" % str( e ) )
+ # Populate the tool table with tools included in installed tool shed repositories.
+ cmd = "SELECT id, metadata FROM tool_shed_repository"
+ result = migrate_engine.execute( cmd )
+ count = 0
+ for row in result:
+ if row[1]:
+ tool_shed_repository_id = row[0]
+ repository_metadata = loads( _sniffnfix_pg9_hex( str( row[1] ) ) )
+ # Create a new row in the tool table for each tool included in repository. We will NOT
+ # handle tool_version_associaions because we do not have the information we need to do so.
+ tools = repository_metadata.get( 'tools', [] )
+ for tool_dict in tools:
+ cmd = "INSERT INTO tool_version VALUES (%s, %s, %s, '%s', %s)" % \
+ ( nextval( 'tool_version' ), localtimestamp(), localtimestamp(), tool_dict[ 'guid' ], tool_shed_repository_id )
+ migrate_engine.execute( cmd )
+ count += 1
+ print "Added %d rows to the new tool_version table." % count
+ # Drop the tool_id_guid_map table since the 2 new tables render it unnecessary.
+ try:
+ ToolIdGuidMap_table.drop()
+ except Exception, e:
+ log.debug( "Dropping tool_id_guid_map table failed: %s" % str( e ) )
+
+def downgrade(migrate_engine):
+ metadata.bind = migrate_engine
+
+ ToolIdGuidMap_table = Table( "tool_id_guid_map", metadata,
+ Column( "id", Integer, primary_key=True ),
+ Column( "create_time", DateTime, default=now ),
+ Column( "update_time", DateTime, default=now, onupdate=now ),
+ Column( "tool_id", String( 255 ) ),
+ Column( "tool_version", TEXT ),
+ Column( "tool_shed", TrimmedString( 255 ) ),
+ Column( "repository_owner", TrimmedString( 255 ) ),
+ Column( "repository_name", TrimmedString( 255 ) ),
+ Column( "guid", TEXT, index=True, unique=True ) )
+
+ metadata.reflect()
+ try:
+ ToolVersionAssociation_table.drop()
+ except Exception, e:
+ log.debug( "Dropping tool_version_association table failed: %s" % str( e ) )
+ try:
+ ToolVersion_table.drop()
+ except Exception, e:
+ log.debug( "Dropping tool_version table failed: %s" % str( e ) )
+ try:
+ ToolIdGuidMap_table.create()
+ except Exception, e:
+ log.debug( "Creating tool_id_guid_map table failed: %s" % str( e ) )
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/model/tool_shed_install/migrate/versions/0007_add_migrate_tools_table.py
--- a/lib/galaxy/model/tool_shed_install/migrate/versions/0007_add_migrate_tools_table.py
+++ b/lib/galaxy/model/tool_shed_install/migrate/versions/0007_add_migrate_tools_table.py
@@ -1,1 +1,50 @@
-../../../migrate/versions/0092_add_migrate_tools_table.py
\ No newline at end of file
+"""
+Migration script to create the migrate_tools table.
+"""
+
+from sqlalchemy import *
+from sqlalchemy.orm import *
+from migrate import *
+from migrate.changeset import *
+
+import datetime
+now = datetime.datetime.utcnow
+# Need our custom types, but don't import anything else from model
+from galaxy.model.custom_types import *
+
+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 )
+
+metadata = MetaData()
+
+MigrateTools_table = Table( "migrate_tools", metadata,
+ Column( "repository_id", TrimmedString( 255 ) ),
+ Column( "repository_path", TEXT ),
+ Column( "version", Integer ) )
+
+def upgrade(migrate_engine):
+ metadata.bind = migrate_engine
+ print __doc__
+
+ metadata.reflect()
+ # Create the table.
+ try:
+ MigrateTools_table.create()
+ cmd = "INSERT INTO migrate_tools VALUES ('GalaxyTools', 'lib/galaxy/tool_shed/migrate', %d)" % 1
+ migrate_engine.execute( cmd )
+ except Exception, e:
+ log.debug( "Creating migrate_tools table failed: %s" % str( e ) )
+
+def downgrade(migrate_engine):
+ metadata.bind = migrate_engine
+ metadata.reflect()
+ try:
+ MigrateTools_table.drop()
+ except Exception, e:
+ log.debug( "Dropping migrate_tools table failed: %s" % str( e ) )
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/model/tool_shed_install/migrate/versions/0008_add_ctx_rev_column.py
--- a/lib/galaxy/model/tool_shed_install/migrate/versions/0008_add_ctx_rev_column.py
+++ b/lib/galaxy/model/tool_shed_install/migrate/versions/0008_add_ctx_rev_column.py
@@ -1,1 +1,44 @@
-../../../migrate/versions/0097_add_ctx_rev_column.py
\ No newline at end of file
+"""
+Migration script to add the ctx_rev column to the tool_shed_repository table.
+"""
+
+from sqlalchemy import *
+from sqlalchemy.orm import *
+from migrate import *
+from migrate.changeset import *
+
+import datetime
+now = datetime.datetime.utcnow
+# Need our custom types, but don't import anything else from model
+from galaxy.model.custom_types import *
+
+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 )
+
+metadata = MetaData()
+
+def upgrade(migrate_engine):
+ metadata.bind = migrate_engine
+ print __doc__
+ metadata.reflect()
+ ToolShedRepository_table = Table( "tool_shed_repository", metadata, autoload=True )
+ col = Column( "ctx_rev", TrimmedString( 10 ) )
+ try:
+ col.create( ToolShedRepository_table )
+ assert col is ToolShedRepository_table.c.ctx_rev
+ except Exception, e:
+ print "Adding ctx_rev column to the tool_shed_repository table failed: %s" % str( e )
+def downgrade(migrate_engine):
+ metadata.bind = migrate_engine
+ metadata.reflect()
+ ToolShedRepository_table = Table( "tool_shed_repository", metadata, autoload=True )
+ try:
+ ToolShedRepository_table.c.ctx_rev.drop()
+ except Exception, e:
+ print "Dropping column ctx_rev from the tool_shed_repository table failed: %s" % str( e )
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/model/tool_shed_install/migrate/versions/0009_add_tool_dependency_table.py
--- a/lib/galaxy/model/tool_shed_install/migrate/versions/0009_add_tool_dependency_table.py
+++ b/lib/galaxy/model/tool_shed_install/migrate/versions/0009_add_tool_dependency_table.py
@@ -1,1 +1,51 @@
-../../../migrate/versions/0099_add_tool_dependency_table.py
\ No newline at end of file
+"""
+Migration script to add the tool_dependency table.
+"""
+from sqlalchemy import *
+from sqlalchemy.orm import *
+from migrate import *
+from migrate.changeset import *
+import sys, logging
+from galaxy.model.custom_types import *
+from sqlalchemy.exc import *
+import datetime
+now = datetime.datetime.utcnow
+
+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 )
+
+metadata = MetaData()
+
+# New table to store information about cloned tool shed repositories.
+ToolDependency_table = Table( "tool_dependency", metadata,
+ Column( "id", Integer, primary_key=True ),
+ Column( "create_time", DateTime, default=now ),
+ Column( "update_time", DateTime, default=now, onupdate=now ),
+ Column( "tool_shed_repository_id", Integer, ForeignKey( "tool_shed_repository.id" ), index=True, nullable=False ),
+ Column( "installed_changeset_revision", TrimmedString( 255 ) ),
+ Column( "name", TrimmedString( 255 ) ),
+ Column( "version", TrimmedString( 40 ) ),
+ Column( "type", TrimmedString( 40 ) ),
+ Column( "uninstalled", Boolean, default=False ) )
+
+def upgrade(migrate_engine):
+ metadata.bind = migrate_engine
+ print __doc__
+ metadata.reflect()
+ try:
+ ToolDependency_table.create()
+ except Exception, e:
+ log.debug( "Creating tool_dependency table failed: %s" % str( e ) )
+
+def downgrade(migrate_engine):
+ metadata.bind = migrate_engine
+ metadata.reflect()
+ try:
+ ToolDependency_table.drop()
+ except Exception, e:
+ log.debug( "Dropping tool_dependency table failed: %s" % str( e ) )
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/model/tool_shed_install/migrate/versions/0010_alter_tool_dependency_table_version_column.py
--- a/lib/galaxy/model/tool_shed_install/migrate/versions/0010_alter_tool_dependency_table_version_column.py
+++ b/lib/galaxy/model/tool_shed_install/migrate/versions/0010_alter_tool_dependency_table_version_column.py
@@ -1,1 +1,54 @@
-../../../migrate/versions/0100_alter_tool_dependency_table_version_column.py
\ No newline at end of file
+"""
+Migration script to alter the type of the tool_dependency.version column from TrimmedString(40) to Text.
+"""
+
+from sqlalchemy import *
+from sqlalchemy.orm import *
+from migrate import *
+from migrate.changeset import *
+
+import datetime
+now = datetime.datetime.utcnow
+# Need our custom types, but don't import anything else from model
+from galaxy.model.custom_types import *
+
+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 )
+
+metadata = MetaData()
+
+def upgrade(migrate_engine):
+ metadata.bind = migrate_engine
+ print __doc__
+ metadata.reflect()
+ ToolDependency_table = Table( "tool_dependency", metadata, autoload=True )
+ # Change the tool_dependency table's version column from TrimmedString to Text.
+ if migrate_engine.name in ['postgresql', 'postgres']:
+ cmd = "ALTER TABLE tool_dependency ALTER COLUMN version TYPE Text;"
+ elif migrate_engine.name == 'mysql':
+ cmd = "ALTER TABLE tool_dependency MODIFY COLUMN version Text;"
+ else:
+ # We don't have to do anything for sqlite tables. From the sqlite documentation at http://sqlite.org/datatype3.html:
+ # 1.0 Storage Classes and Datatypes
+ # Each value stored in an SQLite database (or manipulated by the database engine) has one of the following storage classes:
+ # NULL. The value is a NULL value.
+ # INTEGER. The value is a signed integer, stored in 1, 2, 3, 4, 6, or 8 bytes depending on the magnitude of the value.
+ # REAL. The value is a floating point value, stored as an 8-byte IEEE floating point number.
+ # TEXT. The value is a text string, stored using the database encoding (UTF-8, UTF-16BE or UTF-16LE).
+ # BLOB. The value is a blob of data, stored exactly as it was input.
+ cmd = None
+ if cmd:
+ try:
+ migrate_engine.execute( cmd )
+ except Exception, e:
+ log.debug( "Altering tool_dependency.version column from TrimmedString(40) to Text failed: %s" % str( e ) )
+def downgrade(migrate_engine):
+ metadata.bind = migrate_engine
+ # Not necessary to change column type Text to TrimmedString(40).
+ pass
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/model/tool_shed_install/migrate/versions/0011_drop_installed_changeset_revision_column.py
--- a/lib/galaxy/model/tool_shed_install/migrate/versions/0011_drop_installed_changeset_revision_column.py
+++ b/lib/galaxy/model/tool_shed_install/migrate/versions/0011_drop_installed_changeset_revision_column.py
@@ -1,1 +1,41 @@
-../../../migrate/versions/0101_drop_installed_changeset_revision_column.py
\ No newline at end of file
+"""
+Migration script to drop the installed_changeset_revision column from the tool_dependency table.
+"""
+from sqlalchemy import *
+from sqlalchemy.orm import *
+from migrate import *
+from migrate.changeset import *
+import sys, logging
+from galaxy.model.custom_types import *
+from sqlalchemy.exc import *
+import datetime
+now = datetime.datetime.utcnow
+
+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 )
+
+metadata = MetaData()
+
+def upgrade(migrate_engine):
+ metadata.bind = migrate_engine
+ print __doc__
+ metadata.reflect()
+ try:
+ ToolDependency_table = Table( "tool_dependency", metadata, autoload=True )
+ except NoSuchTableError:
+ ToolDependency_table = None
+ log.debug( "Failed loading table tool_dependency" )
+ if ToolDependency_table is not None:
+ try:
+ col = ToolDependency_table.c.installed_changeset_revision
+ col.drop()
+ except Exception, e:
+ log.debug( "Dropping column 'installed_changeset_revision' from tool_dependency table failed: %s" % ( str( e ) ) )
+def downgrade(migrate_engine):
+ metadata.bind = migrate_engine
+ pass
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/model/tool_shed_install/migrate/versions/0012_add_tool_dependency_status_columns.py
--- a/lib/galaxy/model/tool_shed_install/migrate/versions/0012_add_tool_dependency_status_columns.py
+++ b/lib/galaxy/model/tool_shed_install/migrate/versions/0012_add_tool_dependency_status_columns.py
@@ -1,1 +1,71 @@
-../../../migrate/versions/0102_add_tool_dependency_status_columns.py
\ No newline at end of file
+"""
+Migration script to add status and error_message columns to the tool_dependency table and drop the uninstalled column from the tool_dependency table.
+"""
+
+from sqlalchemy import *
+from sqlalchemy.orm import *
+from migrate import *
+from migrate.changeset import *
+
+import datetime
+now = datetime.datetime.utcnow
+# Need our custom types, but don't import anything else from model
+from galaxy.model.custom_types import *
+
+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 )
+
+metadata = MetaData()
+
+def upgrade(migrate_engine):
+ metadata.bind = migrate_engine
+ print __doc__
+ metadata.reflect()
+ ToolDependency_table = Table( "tool_dependency", metadata, autoload=True )
+ if migrate_engine.name == 'sqlite':
+ col = Column( "status", TrimmedString( 255 ))
+ else:
+ col = Column( "status", TrimmedString( 255 ), nullable=False)
+ try:
+ col.create( ToolDependency_table )
+ assert col is ToolDependency_table.c.status
+ except Exception, e:
+ print "Adding status column to the tool_dependency table failed: %s" % str( e )
+ col = Column( "error_message", TEXT )
+ try:
+ col.create( ToolDependency_table )
+ assert col is ToolDependency_table.c.error_message
+ except Exception, e:
+ print "Adding error_message column to the tool_dependency table failed: %s" % str( e )
+
+ if migrate_engine.name != 'sqlite':
+ #This breaks in sqlite due to failure to drop check constraint.
+ # TODO move to alembic.
+ try:
+ ToolDependency_table.c.uninstalled.drop()
+ except Exception, e:
+ print "Dropping uninstalled column from the tool_dependency table failed: %s" % str( e )
+def downgrade(migrate_engine):
+ metadata.bind = migrate_engine
+ metadata.reflect()
+ ToolDependency_table = Table( "tool_dependency", metadata, autoload=True )
+ try:
+ ToolDependency_table.c.status.drop()
+ except Exception, e:
+ print "Dropping column status from the tool_dependency table failed: %s" % str( e )
+ try:
+ ToolDependency_table.c.error_message.drop()
+ except Exception, e:
+ print "Dropping column error_message from the tool_dependency table failed: %s" % str( e )
+ col = Column( "uninstalled", Boolean, default=False )
+ try:
+ col.create( ToolDependency_table )
+ assert col is ToolDependency_table.c.uninstalled
+ except Exception, e:
+ print "Adding uninstalled column to the tool_dependency table failed: %s" % str( e )
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/model/tool_shed_install/migrate/versions/0013_add_tool_shed_repository_status_columns.py
--- a/lib/galaxy/model/tool_shed_install/migrate/versions/0013_add_tool_shed_repository_status_columns.py
+++ b/lib/galaxy/model/tool_shed_install/migrate/versions/0013_add_tool_shed_repository_status_columns.py
@@ -1,1 +1,69 @@
-../../../migrate/versions/0103_add_tool_shed_repository_status_columns.py
\ No newline at end of file
+"""Migration script to add status and error_message columns to the tool_shed_repository table."""
+
+from sqlalchemy import *
+from sqlalchemy.orm import *
+from migrate import *
+from migrate.changeset import *
+
+import datetime
+now = datetime.datetime.utcnow
+# Need our custom types, but don't import anything else from model
+from galaxy.model.custom_types import *
+
+metadata = MetaData()
+
+def upgrade(migrate_engine):
+ metadata.bind = migrate_engine
+ print __doc__
+ metadata.reflect()
+ ToolShedRepository_table = Table( "tool_shed_repository", metadata, autoload=True )
+ # Add the status column to the tool_shed_repository table.
+ col = Column( "status", TrimmedString( 255 ) )
+ try:
+ col.create( ToolShedRepository_table )
+ assert col is ToolShedRepository_table.c.status
+ except Exception, e:
+ print "Adding status column to the tool_shed_repository table failed: %s" % str( e )
+ # Add the error_message column to the tool_shed_repository table.
+ col = Column( "error_message", TEXT )
+ try:
+ col.create( ToolShedRepository_table )
+ assert col is ToolShedRepository_table.c.error_message
+ except Exception, e:
+ print "Adding error_message column to the tool_shed_repository table failed: %s" % str( e )
+ # Update the status column value for tool_shed_repositories to the default value 'Installed'.
+ cmd = "UPDATE tool_shed_repository SET status = 'Installed';"
+ try:
+ migrate_engine.execute( cmd )
+ except Exception, e:
+ print "Exception executing sql command: "
+ print cmd
+ print str( e )
+ # Update the status column for tool_shed_repositories that have been uninstalled.
+ cmd = "UPDATE tool_shed_repository SET status = 'Uninstalled' WHERE uninstalled;"
+ try:
+ migrate_engine.execute( cmd )
+ except Exception, e:
+ print "Exception executing sql command: "
+ print cmd
+ print str( e )
+ # Update the status column for tool_shed_repositories that have been deactivated.
+ cmd = "UPDATE tool_shed_repository SET status = 'Deactivated' where deleted and not uninstalled;"
+ try:
+ migrate_engine.execute( cmd )
+ except Exception, e:
+ print "Exception executing sql command: "
+ print cmd
+ print str( e )
+def downgrade(migrate_engine):
+ metadata.bind = migrate_engine
+ metadata.reflect()
+ ToolShedRepository_table = Table( "tool_shed_repository", metadata, autoload=True )
+ try:
+ ToolShedRepository_table.c.status.drop()
+ except Exception, e:
+ print "Dropping column status from the tool_shed_repository table failed: %s" % str( e )
+ try:
+ ToolShedRepository_table.c.error_message.drop()
+ except Exception, e:
+ print "Dropping column error_message from the tool_shed_repository table failed: %s" % str( e )
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/model/tool_shed_install/migrate/versions/0014_add_repository_dependency_tables.py
--- a/lib/galaxy/model/tool_shed_install/migrate/versions/0014_add_repository_dependency_tables.py
+++ b/lib/galaxy/model/tool_shed_install/migrate/versions/0014_add_repository_dependency_tables.py
@@ -1,1 +1,60 @@
-../../../migrate/versions/0109_add_repository_dependency_tables.py
\ No newline at end of file
+"""
+Migration script to add the repository_dependency and repository_repository_dependency_association tables.
+"""
+from sqlalchemy import *
+from sqlalchemy.orm import *
+from migrate import *
+from migrate.changeset import *
+import sys, logging
+from galaxy.model.custom_types import *
+from sqlalchemy.exc import *
+import datetime
+now = datetime.datetime.utcnow
+
+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 )
+
+metadata = MetaData()
+
+RepositoryDependency_table = Table( "repository_dependency", metadata,
+ Column( "id", Integer, primary_key=True ),
+ Column( "create_time", DateTime, default=now ),
+ Column( "update_time", DateTime, default=now, onupdate=now ),
+ Column( "tool_shed_repository_id", Integer, ForeignKey( "tool_shed_repository.id" ), index=True, nullable=False ) )
+
+RepositoryRepositoryDependencyAssociation_table = Table( "repository_repository_dependency_association", metadata,
+ Column( "id", Integer, primary_key=True ),
+ Column( "create_time", DateTime, default=now ),
+ Column( "update_time", DateTime, default=now, onupdate=now ),
+ Column( "tool_shed_repository_id", Integer, ForeignKey( "tool_shed_repository.id" ), index=True ),
+ Column( "repository_dependency_id", Integer, ForeignKey( "repository_dependency.id" ), index=True ) )
+
+def upgrade(migrate_engine):
+ print __doc__
+ metadata.bind = migrate_engine
+ metadata.reflect()
+ try:
+ RepositoryDependency_table.create()
+ except Exception, e:
+ log.debug( "Creating repository_dependency table failed: %s" % str( e ) )
+ try:
+ RepositoryRepositoryDependencyAssociation_table.create()
+ except Exception, e:
+ log.debug( "Creating repository_repository_dependency_association table failed: %s" % str( e ) )
+
+def downgrade(migrate_engine):
+ metadata.bind = migrate_engine
+ metadata.reflect()
+ try:
+ RepositoryRepositoryDependencyAssociation_table.drop()
+ except Exception, e:
+ log.debug( "Dropping repository_repository_dependency_association table failed: %s" % str( e ) )
+ try:
+ RepositoryDependency_table.drop()
+ except Exception, e:
+ log.debug( "Dropping repository_dependency table failed: %s" % str( e ) )
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/model/tool_shed_install/migrate/versions/0015_update_migrate_tools_table.py
--- a/lib/galaxy/model/tool_shed_install/migrate/versions/0015_update_migrate_tools_table.py
+++ b/lib/galaxy/model/tool_shed_install/migrate/versions/0015_update_migrate_tools_table.py
@@ -1,1 +1,38 @@
-../../../migrate/versions/0113_update_migrate_tools_table.py
\ No newline at end of file
+"""
+Migration script to update the migrate_tools.repository_path column to point to the new location lib/tool_shed/galaxy_install/migrate.
+"""
+
+from sqlalchemy import *
+from sqlalchemy.orm import *
+from migrate import *
+from migrate.changeset import *
+
+import datetime
+now = datetime.datetime.utcnow
+# Need our custom types, but don't import anything else from model
+from galaxy.model.custom_types import *
+
+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 )
+
+def upgrade(migrate_engine):
+ print __doc__
+ # Create the table.
+ try:
+ cmd = "UPDATE migrate_tools set repository_path='lib/galaxy/tool_shed/migrate';"
+ migrate_engine.execute( cmd )
+ except Exception, e:
+ log.debug( "Updating migrate_tools.repository_path column to point to the new location lib/tool_shed/galaxy_install/migrate failed: %s" % str( e ) )
+
+def downgrade(migrate_engine):
+ try:
+ cmd = "UPDATE migrate_tools set repository_path='lib/galaxy/tool_shed/migrate';"
+ migrate_engine.execute( cmd )
+ except Exception, e:
+ log.debug( "Updating migrate_tools.repository_path column to point to the old location lib/galaxy/tool_shed/migrate failed: %s" % str( e ) )
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/model/tool_shed_install/migrate/versions/0016_update_migrate_tools_table_again.py
--- a/lib/galaxy/model/tool_shed_install/migrate/versions/0016_update_migrate_tools_table_again.py
+++ b/lib/galaxy/model/tool_shed_install/migrate/versions/0016_update_migrate_tools_table_again.py
@@ -1,1 +1,40 @@
-../../../migrate/versions/0114_update_migrate_tools_table_again.py
\ No newline at end of file
+"""
+Migration script to update the migrate_tools.repository_path column to point to the new location lib/tool_shed/galaxy_install/migrate.
+"""
+
+from sqlalchemy import *
+from sqlalchemy.orm import *
+from migrate import *
+from migrate.changeset import *
+
+import datetime
+now = datetime.datetime.utcnow
+# Need our custom types, but don't import anything else from model
+from galaxy.model.custom_types import *
+
+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 )
+
+
+def upgrade(migrate_engine):
+ print __doc__
+ # Create the table.
+ try:
+ cmd = "UPDATE migrate_tools set repository_path='lib/tool_shed/galaxy_install/migrate';"
+ migrate_engine.execute( cmd )
+ except Exception, e:
+ log.debug( "Updating migrate_tools.repository_path column to point to the new location lib/tool_shed/galaxy_install/migrate failed: %s" % str( e ) )
+
+def downgrade(migrate_engine):
+ try:
+ cmd = "UPDATE migrate_tools set repository_path='lib/galaxy/tool_shed/migrate';"
+ migrate_engine.execute( cmd )
+ except Exception, e:
+ log.debug( "Updating migrate_tools.repository_path column to point to the old location lib/galaxy/tool_shed/migrate failed: %s" % str( e ) )
+
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/model/tool_shed_install/migrate/versions/0017_drop_update_available_col_add_tool_shed_status_col.py
--- a/lib/galaxy/model/tool_shed_install/migrate/versions/0017_drop_update_available_col_add_tool_shed_status_col.py
+++ b/lib/galaxy/model/tool_shed_install/migrate/versions/0017_drop_update_available_col_add_tool_shed_status_col.py
@@ -1,1 +1,77 @@
-../../../migrate/versions/0116_drop_update_available_col_add_tool_shed_status_col.py
\ No newline at end of file
+"""
+Migration script to drop the update_available Boolean column and replace it with the tool_shed_status JSONType column in the tool_shed_repository table.
+"""
+
+from sqlalchemy import *
+from sqlalchemy.orm import *
+from migrate import *
+from migrate.changeset import *
+import sys, logging
+from galaxy.model.custom_types import *
+from sqlalchemy.exc import *
+import datetime
+now = datetime.datetime.utcnow
+
+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 )
+
+metadata = MetaData()
+
+def default_false( migrate_engine ):
+ if migrate_engine.name == 'mysql' or migrate_engine.name == 'sqlite':
+ return "0"
+ elif migrate_engine.name in [ 'postgresql', 'postgres' ]:
+ return "false"
+
+def upgrade( migrate_engine ):
+ metadata.bind = migrate_engine
+ print __doc__
+ metadata.reflect()
+ try:
+ ToolShedRepository_table = Table( "tool_shed_repository", metadata, autoload=True )
+ except NoSuchTableError:
+ ToolShedRepository_table = None
+ log.debug( "Failed loading table tool_shed_repository" )
+ if ToolShedRepository_table is not None:
+ # For some unknown reason it is no longer possible to drop a column in a migration script if using the sqlite database.
+ if migrate_engine.name != 'sqlite':
+ try:
+ col = ToolShedRepository_table.c.update_available
+ col.drop()
+ except Exception, e:
+ print "Dropping column update_available from the tool_shed_repository table failed: %s" % str( e )
+ c = Column( "tool_shed_status", JSONType, nullable=True )
+ try:
+ c.create( ToolShedRepository_table )
+ assert c is ToolShedRepository_table.c.tool_shed_status
+ except Exception, e:
+ print "Adding tool_shed_status column to the tool_shed_repository table failed: %s" % str( e )
+
+def downgrade( migrate_engine ):
+ metadata.bind = migrate_engine
+ metadata.reflect()
+ try:
+ ToolShedRepository_table = Table( "tool_shed_repository", metadata, autoload=True )
+ except NoSuchTableError:
+ ToolShedRepository_table = None
+ log.debug( "Failed loading table tool_shed_repository" )
+ if ToolShedRepository_table is not None:
+ # For some unknown reason it is no longer possible to drop a column in a migration script if using the sqlite database.
+ if migrate_engine.name != 'sqlite':
+ try:
+ col = ToolShedRepository_table.c.tool_shed_status
+ col.drop()
+ except Exception, e:
+ print "Dropping column tool_shed_status from the tool_shed_repository table failed: %s" % str( e )
+ c = Column( "update_available", Boolean, default=False )
+ try:
+ c.create( ToolShedRepository_table )
+ assert c is ToolShedRepository_table.c.update_available
+ migrate_engine.execute( "UPDATE tool_shed_repository SET update_available=%s" % default_false( migrate_engine ) )
+ except Exception, e:
+ print "Adding column update_available to the tool_shed_repository table failed: %s" % str( e )
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/openid/__init__.py
--- a/lib/galaxy/openid/__init__.py
+++ b/lib/galaxy/openid/__init__.py
@@ -1,3 +1,3 @@
"""
OpenID functionality
-"""
\ No newline at end of file
+"""
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/tools/actions/__init__.py
--- a/lib/galaxy/tools/actions/__init__.py
+++ b/lib/galaxy/tools/actions/__init__.py
@@ -4,7 +4,7 @@
from galaxy.tools.parameters import DataToolParameter
from galaxy.tools.parameters import DataCollectionToolParameter
from galaxy.tools.parameters.wrapped import WrappedParameters
-from galaxy.util.json import to_json_string
+from galaxy.util.json import dumps
from galaxy.util.none_like import NoneDataset
from galaxy.util.odict import odict
from galaxy.util.template import fill_template
@@ -324,7 +324,7 @@
job.add_output_dataset( name, dataset )
job.object_store_id = object_store_populator.object_store_id
if job_params:
- job.params = to_json_string( job_params )
+ job.params = dumps( job_params )
job.set_handler(tool.get_job_handler(job_params))
trans.sa_session.add( job )
# Now that we have a job id, we can remap any outputs if this is a rerun and the user chose to continue dependent jobs
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/tools/actions/metadata.py
--- a/lib/galaxy/tools/actions/metadata.py
+++ b/lib/galaxy/tools/actions/metadata.py
@@ -1,7 +1,7 @@
from __init__ import ToolAction
from galaxy.datatypes.metadata import JobExternalOutputMetadataWrapper
from galaxy.util.odict import odict
-from galaxy.util.json import to_json_string
+from galaxy.util.json import dumps
import logging
log = logging.getLogger( __name__ )
@@ -50,7 +50,7 @@
if user:
job.user_id = user.id
if job_params:
- job.params = to_json_string( job_params )
+ job.params = dumps( job_params )
start_job_state = job.state #should be job.states.NEW
try:
# For backward compatibility, some tools may not have versions yet.
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/tools/actions/upload_common.py
--- a/lib/galaxy/tools/actions/upload_common.py
+++ b/lib/galaxy/tools/actions/upload_common.py
@@ -7,7 +7,7 @@
from galaxy import datatypes, util
from galaxy.util.odict import odict
from galaxy.datatypes import sniff
-from galaxy.util.json import to_json_string
+from galaxy.util.json import dumps
from galaxy.model.orm import eagerload_all
from galaxy.exceptions import ObjectInvalid
@@ -342,7 +342,7 @@
# user cannot remove it unless the parent directory is writable.
if link_data_only == 'copy_files' and trans.app.config.external_chown_script:
_chown( uploaded_dataset.path )
- json_file.write( to_json_string( json ) + '\n' )
+ json_file.write( dumps( json ) + '\n' )
json_file.close()
if trans.app.config.external_chown_script:
_chown( json_file_path )
@@ -375,7 +375,7 @@
for name, value in tool.params_to_strings( params, trans.app ).iteritems():
job.add_parameter( name, value )
- job.add_parameter( 'paramfile', to_json_string( json_file_path ) )
+ job.add_parameter( 'paramfile', dumps( json_file_path ) )
object_store_id = None
for i, dataset in enumerate( data_list ):
if folder:
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/tools/imp_exp/__init__.py
--- a/lib/galaxy/tools/imp_exp/__init__.py
+++ b/lib/galaxy/tools/imp_exp/__init__.py
@@ -8,7 +8,7 @@
from galaxy.tools.parameters.basic import UnvalidatedValue
from galaxy.web.framework.helpers import to_unicode
from galaxy.model.item_attrs import UsesAnnotations
-from galaxy.util.json import from_json_string, to_json_string
+from galaxy.util.json import loads, dumps
from galaxy.web.base.controller import UsesHistoryMixin
log = logging.getLogger(__name__)
@@ -108,7 +108,7 @@
#
history_attr_file_name = os.path.join( archive_dir, 'history_attrs.txt')
history_attr_str = read_file_contents( history_attr_file_name )
- history_attrs = from_json_string( history_attr_str )
+ history_attrs = loads( history_attr_str )
# Create history.
new_history = model.History( name='imported from archive: %s' % history_attrs['name'].encode( 'utf-8' ), \
@@ -134,12 +134,12 @@
#
datasets_attrs_file_name = os.path.join( archive_dir, 'datasets_attrs.txt')
datasets_attr_str = read_file_contents( datasets_attrs_file_name )
- datasets_attrs = from_json_string( datasets_attr_str )
-
+ datasets_attrs = loads( datasets_attr_str )
+
if os.path.exists( datasets_attrs_file_name + ".provenance" ):
provenance_attr_str = read_file_contents( datasets_attrs_file_name + ".provenance" )
- provenance_attrs = from_json_string( provenance_attr_str )
- datasets_attrs += provenance_attrs
+ provenance_attrs = loads( provenance_attr_str )
+ datasets_attrs += provenance_attrs
# Get counts of how often each dataset file is used; a file can
# be linked to multiple dataset objects (HDAs).
@@ -230,7 +230,7 @@
return self.sa_session.query( model.HistoryDatasetAssociation ) \
.filter_by( history=new_history, hid=obj_dct['hid'] ).first()
return obj_dct
- jobs_attrs = from_json_string( jobs_attr_str, object_hook=as_hda )
+ jobs_attrs = loads( jobs_attr_str, object_hook=as_hda )
# Create each job.
for job_attrs in jobs_attrs:
@@ -279,7 +279,7 @@
.filter_by( history=new_history, hid=value.hid ).first()
value = input_hda.id
#print "added parameter %s-->%s to job %i" % ( name, value, imported_job.id )
- imported_job.add_parameter( name, to_json_string( value, cls=HistoryDatasetAssociationIDEncoder ) )
+ imported_job.add_parameter( name, dumps( value, cls=HistoryDatasetAssociationIDEncoder ) )
# TODO: Connect jobs to input datasets.
@@ -292,14 +292,14 @@
imported_job.add_output_dataset( output_hda.name, output_hda )
# Connect jobs to input datasets.
- if 'input_mapping' in job_attrs:
+ if 'input_mapping' in job_attrs:
for input_name, input_hid in job_attrs[ 'input_mapping' ].items():
#print "%s job has input dataset %i" % (imported_job.id, input_hid)
input_hda = self.sa_session.query( model.HistoryDatasetAssociation ) \
.filter_by( history=new_history, hid=input_hid ).first()
if input_hda:
imported_job.add_input_dataset( input_name, input_hda )
-
+
self.sa_session.flush()
@@ -409,7 +409,7 @@
}
history_attrs_filename = tempfile.NamedTemporaryFile( dir=temp_output_dir ).name
history_attrs_out = open( history_attrs_filename, 'w' )
- history_attrs_out.write( to_json_string( history_attrs ) )
+ history_attrs_out.write( dumps( history_attrs ) )
history_attrs_out.close()
jeha.history_attrs_filename = history_attrs_filename
@@ -427,12 +427,12 @@
included_datasets.append( dataset )
datasets_attrs_filename = tempfile.NamedTemporaryFile( dir=temp_output_dir ).name
datasets_attrs_out = open( datasets_attrs_filename, 'w' )
- datasets_attrs_out.write( to_json_string( datasets_attrs, cls=HistoryDatasetAssociationEncoder ) )
+ datasets_attrs_out.write( dumps( datasets_attrs, cls=HistoryDatasetAssociationEncoder ) )
datasets_attrs_out.close()
jeha.datasets_attrs_filename = datasets_attrs_filename
-
+
provenance_attrs_out = open( datasets_attrs_filename + ".provenance", 'w' )
- provenance_attrs_out.write( to_json_string( provenance_attrs, cls=HistoryDatasetAssociationEncoder ) )
+ provenance_attrs_out.write( dumps( provenance_attrs, cls=HistoryDatasetAssociationEncoder ) )
provenance_attrs_out.close()
#
@@ -477,7 +477,7 @@
job_attrs[ 'exit_code' ] = job.exit_code
job_attrs[ 'create_time' ] = job.create_time.isoformat()
job_attrs[ 'update_time' ] = job.update_time.isoformat()
-
+
# Get the job's parameters
try:
@@ -509,7 +509,7 @@
jobs_attrs_filename = tempfile.NamedTemporaryFile( dir=temp_output_dir ).name
jobs_attrs_out = open( jobs_attrs_filename, 'w' )
- jobs_attrs_out.write( to_json_string( jobs_attrs, cls=HistoryDatasetAssociationEncoder ) )
+ jobs_attrs_out.write( dumps( jobs_attrs, cls=HistoryDatasetAssociationEncoder ) )
jobs_attrs_out.close()
jeha.jobs_attrs_filename = jobs_attrs_filename
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/tools/imp_exp/export_history.py
--- a/lib/galaxy/tools/imp_exp/export_history.py
+++ b/lib/galaxy/tools/imp_exp/export_history.py
@@ -39,7 +39,7 @@
except OverflowError:
pass
datasets_attr_in.close()
- datasets_attrs = from_json_string( datasets_attr_str )
+ datasets_attrs = loads( datasets_attr_str )
# Add datasets to archive and update dataset attributes.
# TODO: security check to ensure that files added are in Galaxy dataset directory?
@@ -54,7 +54,7 @@
# Rewrite dataset attributes file.
datasets_attrs_out = open( datasets_attrs_file, 'w' )
- datasets_attrs_out.write( to_json_string( datasets_attrs ) )
+ datasets_attrs_out.write( dumps( datasets_attrs ) )
datasets_attrs_out.close()
# Finish archive.
@@ -80,4 +80,4 @@
# Create archive.
status = create_archive( history_attrs, dataset_attrs, job_attrs, out_file, gzip )
- print status
\ No newline at end of file
+ print status
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/tools/parameters/__init__.py
--- a/lib/galaxy/tools/parameters/__init__.py
+++ b/lib/galaxy/tools/parameters/__init__.py
@@ -85,7 +85,7 @@
for key, value in param_values.iteritems():
if key in params:
value = params[ key ].value_to_basic( value, app )
- rval[ key ] = str( to_json_string( value ) )
+ rval[ key ] = str( dumps( value ) )
return rval
@@ -98,7 +98,7 @@
"""
rval = dict()
for key, value in param_values.iteritems():
- value = json_fix( from_json_string( value ) )
+ value = json_fix( loads( value ) )
if key in params:
value = params[key].value_from_basic( value, app, ignore_errors )
rval[ key ] = value
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/tools/util/__init__.py
--- a/lib/galaxy/tools/util/__init__.py
+++ b/lib/galaxy/tools/util/__init__.py
@@ -3,4 +3,4 @@
FIXME: These are used by tool scripts, not the framework, and should not live
in this package.
-"""
\ No newline at end of file
+"""
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/util/__init__.py
--- a/lib/galaxy/util/__init__.py
+++ b/lib/galaxy/util/__init__.py
@@ -338,8 +338,8 @@
def pretty_print_json(json_data, is_json_string=False):
if is_json_string:
- json_data = json.from_json_string(json_data)
- return json.to_json_string(json_data, sort_keys=True, indent=4)
+ json_data = json.loads(json_data)
+ return json.dumps(json_data, sort_keys=True, indent=4)
# characters that are valid
valid_chars = set(string.letters + string.digits + " -=_.()/+*^,:?!")
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/util/backports/__init__.py
--- a/lib/galaxy/util/backports/__init__.py
+++ b/lib/galaxy/util/backports/__init__.py
@@ -1,3 +1,3 @@
"""
Modules for providing backward compatibility with future versions of Python
-"""
\ No newline at end of file
+"""
diff -r 9d15e899516411c9b491f66f001a55136b1173b9 -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 lib/galaxy/util/backports/importlib/__init__.py
--- a/lib/galaxy/util/backports/importlib/__init__.py
+++ b/lib/galaxy/util/backports/importlib/__init__.py
@@ -39,4 +39,4 @@
## Note: this was copied from
## http://svn.python.org/projects/python/trunk/Lib/importlib/__init__.py
- ## on 24 September 2012
\ No newline at end of file
+ ## on 24 September 2012
This diff is so big that we needed to truncate the remainder.
https://bitbucket.org/galaxy/galaxy-central/commits/983a1cc80be6/
Changeset: 983a1cc80be6
User: dannon
Date: 2014-09-08 23:03:22
Summary: Web helpers (${h.*}) in mako used to_json_string, now dumps.
Affected #: 45 files
diff -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 -r 983a1cc80be61c3ccdd3c10d06737381aacb9b05 templates/admin/external_service/reload_external_service_types.mako
--- a/templates/admin/external_service/reload_external_service_types.mako
+++ b/templates/admin/external_service/reload_external_service_types.mako
@@ -19,4 +19,4 @@
<input type="submit" name="reload_external_service_type_button" value="Reload"/></div></div>
-</form>
\ No newline at end of file
+</form>
diff -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 -r 983a1cc80be61c3ccdd3c10d06737381aacb9b05 templates/admin/requests/grid.mako
--- a/templates/admin/requests/grid.mako
+++ b/templates/admin/requests/grid.mako
@@ -1,1 +1,1 @@
-<%inherit file="/grid_base.mako"/>
\ No newline at end of file
+<%inherit file="/grid_base.mako"/>
diff -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 -r 983a1cc80be61c3ccdd3c10d06737381aacb9b05 templates/admin/requests/view_sample_dataset.mako
--- a/templates/admin/requests/view_sample_dataset.mako
+++ b/templates/admin/requests/view_sample_dataset.mako
@@ -76,4 +76,4 @@
<div style="clear: both"></div>
%endif
</div>
-</div>
\ No newline at end of file
+</div>
diff -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 -r 983a1cc80be61c3ccdd3c10d06737381aacb9b05 templates/galaxy_client_app.mako
--- a/templates/galaxy_client_app.mako
+++ b/templates/galaxy_client_app.mako
@@ -15,7 +15,7 @@
//TODO: global...
%for key in kwargs:
( window.bootstrapped = window.bootstrapped || {} )[ '${key}' ] = (
- ${ h.to_json_string( kwargs[ key ], indent=( 2 if trans.debug else 0 ) )} );
+ ${ h.dumps( kwargs[ key ], indent=( 2 if trans.debug else 0 ) )} );
%endfor
define( 'bootstrapped-data', function(){
return window.bootstrapped;
@@ -61,7 +61,7 @@
<%def name="get_config_json()">
## Conv. fn to write as JSON
-${ h.to_json_string( get_config_dict() )}
+${ h.dumps( get_config_dict() )}
</%def>
@@ -106,5 +106,5 @@
<%def name="get_user_json()">
## Conv. fn to write as JSON
-${ h.to_json_string( get_user_dict() )}
+${ h.dumps( get_user_dict() )}
</%def>
diff -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 -r 983a1cc80be61c3ccdd3c10d06737381aacb9b05 templates/grid_base.mako
--- a/templates/grid_base.mako
+++ b/templates/grid_base.mako
@@ -73,7 +73,7 @@
// load grid viewer
require(['mvc/grid/grid-view'], function(GridView) {
$(function() {
- gridView = new GridView( ${ h.to_json_string( self.get_grid_config( embedded=embedded, insert=insert ) ) } );
+ gridView = new GridView( ${ h.dumps( self.get_grid_config( embedded=embedded, insert=insert ) ) } );
});
});
</script>
diff -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 -r 983a1cc80be61c3ccdd3c10d06737381aacb9b05 templates/grid_base_async.mako
--- a/templates/grid_base_async.mako
+++ b/templates/grid_base_async.mako
@@ -1,4 +1,4 @@
<%namespace name="grid_base" file="./grid_base.mako" import="*" />
${init()}
-${h.to_json_string( grid_base.get_grid_config() )}
+${h.dumps( grid_base.get_grid_config() )}
diff -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 -r 983a1cc80be61c3ccdd3c10d06737381aacb9b05 templates/rss.mako
--- a/templates/rss.mako
+++ b/templates/rss.mako
@@ -20,4 +20,4 @@
</item>
%endfor
</channel>
-</rss>
\ No newline at end of file
+</rss>
diff -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 -r 983a1cc80be61c3ccdd3c10d06737381aacb9b05 templates/tagging_common.mako
--- a/templates/tagging_common.mako
+++ b/templates/tagging_common.mako
@@ -198,7 +198,7 @@
%>
var options =
{
- tags : ${h.to_json_string(tag_names_and_values)},
+ tags : ${h.dumps(tag_names_and_values)},
editable : ${iff( editable, 'true', 'false' )},
get_toggle_link_text_fn: ${get_toggle_link_text_fn},
tag_click_fn: ${tag_click_fn},
diff -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 -r 983a1cc80be61c3ccdd3c10d06737381aacb9b05 templates/user/dbkeys.mako
--- a/templates/user/dbkeys.mako
+++ b/templates/user/dbkeys.mako
@@ -246,4 +246,4 @@
(Len Entry option).</p></div></div>
-</%def>
\ No newline at end of file
+</%def>
diff -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 -r 983a1cc80be61c3ccdd3c10d06737381aacb9b05 templates/user/new_address.mako
--- a/templates/user/new_address.mako
+++ b/templates/user/new_address.mako
@@ -94,4 +94,4 @@
</div></form></div>
-</div>
\ No newline at end of file
+</div>
diff -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 -r 983a1cc80be61c3ccdd3c10d06737381aacb9b05 templates/webapps/demo_sequencer/empty.mako
--- a/templates/webapps/demo_sequencer/empty.mako
+++ b/templates/webapps/demo_sequencer/empty.mako
@@ -1,4 +1,4 @@
<html><body></body>
-</html>
\ No newline at end of file
+</html>
diff -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 -r 983a1cc80be61c3ccdd3c10d06737381aacb9b05 templates/webapps/galaxy/dataset/display.mako
--- a/templates/webapps/galaxy/dataset/display.mako
+++ b/templates/webapps/galaxy/dataset/display.mako
@@ -26,7 +26,7 @@
data.createTabularDatasetChunkedView({
// TODO: encode id.
dataset_config:
- _.extend( ${h.to_json_string( item.to_dict() )},
+ _.extend( ${h.dumps( item.to_dict() )},
{
chunk_url: "${h.url_for( controller='/dataset', action='display',
dataset_id=trans.security.encode_id( item.id ))}",
diff -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 -r 983a1cc80be61c3ccdd3c10d06737381aacb9b05 templates/webapps/galaxy/dataset/grid.mako
--- a/templates/webapps/galaxy/dataset/grid.mako
+++ b/templates/webapps/galaxy/dataset/grid.mako
@@ -1,1 +1,1 @@
-<%inherit file="/grid_base.mako"/>
\ No newline at end of file
+<%inherit file="/grid_base.mako"/>
diff -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 -r 983a1cc80be61c3ccdd3c10d06737381aacb9b05 templates/webapps/galaxy/dataset/item_content.mako
--- a/templates/webapps/galaxy/dataset/item_content.mako
+++ b/templates/webapps/galaxy/dataset/item_content.mako
@@ -1,3 +1,3 @@
<%namespace file="/dataset/display.mako" import="*" />
-${render_item( item, item_data )}
\ No newline at end of file
+${render_item( item, item_data )}
diff -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 -r 983a1cc80be61c3ccdd3c10d06737381aacb9b05 templates/webapps/galaxy/dataset/tabular_chunked.mako
--- a/templates/webapps/galaxy/dataset/tabular_chunked.mako
+++ b/templates/webapps/galaxy/dataset/tabular_chunked.mako
@@ -17,7 +17,7 @@
require(['mvc/data'], function(data) {
data.createTabularDatasetChunkedView({
- dataset_config: _.extend( ${h.to_json_string( trans.security.encode_dict_ids( dataset.to_dict() ) )},
+ dataset_config: _.extend( ${h.dumps( trans.security.encode_dict_ids( dataset.to_dict() ) )},
{
first_data_chunk: ${chunk}
}
diff -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 -r 983a1cc80be61c3ccdd3c10d06737381aacb9b05 templates/webapps/galaxy/galaxy.masthead.mako
--- a/templates/webapps/galaxy/galaxy.masthead.mako
+++ b/templates/webapps/galaxy/galaxy.masthead.mako
@@ -87,7 +87,7 @@
], function( mod_masthead, mod_menu, mod_modal, mod_frame, GalaxyUpload, user, quotameter ){
if( !Galaxy.currUser ){
// this doesn't need to wait for the page being readied
- Galaxy.currUser = new user.User(${ h.to_json_string( get_user_json(), indent=2 ) });
+ Galaxy.currUser = new user.User(${ h.dumps( get_user_json(), indent=2 ) });
}
$(function() {
@@ -97,7 +97,7 @@
}
// get configuration
- var masthead_config = ${ h.to_json_string( masthead_config ) };
+ var masthead_config = ${ h.dumps( masthead_config ) };
// load global galaxy objects
Galaxy.masthead = new mod_masthead.GalaxyMasthead(masthead_config);
diff -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 -r 983a1cc80be61c3ccdd3c10d06737381aacb9b05 templates/webapps/galaxy/galaxy.panels.mako
--- a/templates/webapps/galaxy/galaxy.panels.mako
+++ b/templates/webapps/galaxy/galaxy.panels.mako
@@ -100,7 +100,7 @@
"libs/backbone/backbone": { exports: "Backbone" },
}
});
- var galaxy_config = ${ h.to_json_string( self.galaxy_config ) };
+ var galaxy_config = ${ h.dumps( self.galaxy_config ) };
</script></%def>
diff -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 -r 983a1cc80be61c3ccdd3c10d06737381aacb9b05 templates/webapps/galaxy/history/citations.mako
--- a/templates/webapps/galaxy/history/citations.mako
+++ b/templates/webapps/galaxy/history/citations.mako
@@ -32,4 +32,4 @@
</script></%def><div id="citations">
-</div>
\ No newline at end of file
+</div>
diff -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 -r 983a1cc80be61c3ccdd3c10d06737381aacb9b05 templates/webapps/galaxy/history/display.mako
--- a/templates/webapps/galaxy/history/display.mako
+++ b/templates/webapps/galaxy/history/display.mako
@@ -46,8 +46,8 @@
</div><script type="text/javascript">
var debugging = JSON.parse( sessionStorage.getItem( 'debugging' ) ) || false,
- historyJSON = ${h.to_json_string( history_dict )},
- hdaJSON = ${h.to_json_string( hda_dicts )};
+ historyJSON = ${h.dumps( history_dict )},
+ hdaJSON = ${h.dumps( hda_dicts )};
//window.historyJSON = historyJSON;
//window.hdaJSON = hdaJSON;
diff -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 -r 983a1cc80be61c3ccdd3c10d06737381aacb9b05 templates/webapps/galaxy/history/display_structured.mako
--- a/templates/webapps/galaxy/history/display_structured.mako
+++ b/templates/webapps/galaxy/history/display_structured.mako
@@ -144,7 +144,7 @@
<script type="text/javascript">
define( 'display-structured', function(){
require([ 'mvc/history/hda-li-edit', 'mvc/history/hda-model' ], function( hdaEdit, hdaModel ){
- var hdaJSON = ${ h.to_json_string( hda_dicts, indent=( 2 if trans.debug else 0 ) ) };
+ var hdaJSON = ${ h.dumps( hda_dicts, indent=( 2 if trans.debug else 0 ) ) };
window.hdas = hdaJSON.map( function( hda ){
return new hdaEdit.HDAListItemEdit({
diff -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 -r 983a1cc80be61c3ccdd3c10d06737381aacb9b05 templates/webapps/galaxy/history/embed.mako
--- a/templates/webapps/galaxy/history/embed.mako
+++ b/templates/webapps/galaxy/history/embed.mako
@@ -67,8 +67,8 @@
panel = new panelMod.AnnotatedHistoryPanel({
el : $embeddedHistory.find( ".history-panel" ),
model : new historyModel.History(
- ${h.to_json_string( history_dict )},
- ${h.to_json_string( hda_dicts )},
+ ${h.dumps( history_dict )},
+ ${h.dumps( hda_dicts )},
{ logger: ( debugging )?( console ):( null ) }
)
}).render();
diff -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 -r 983a1cc80be61c3ccdd3c10d06737381aacb9b05 templates/webapps/galaxy/history/grid.mako
--- a/templates/webapps/galaxy/history/grid.mako
+++ b/templates/webapps/galaxy/history/grid.mako
@@ -1,1 +1,1 @@
-<%inherit file="../grid_base.mako"/>
\ No newline at end of file
+<%inherit file="../grid_base.mako"/>
diff -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 -r 983a1cc80be61c3ccdd3c10d06737381aacb9b05 templates/webapps/galaxy/history/item_content.mako
--- a/templates/webapps/galaxy/history/item_content.mako
+++ b/templates/webapps/galaxy/history/item_content.mako
@@ -1,3 +1,3 @@
<%namespace file="/history/display.mako" import="*" />
-${render_item( item, item_data )}
\ No newline at end of file
+${render_item( item, item_data )}
diff -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 -r 983a1cc80be61c3ccdd3c10d06737381aacb9b05 templates/webapps/galaxy/history/view.mako
--- a/templates/webapps/galaxy/history/view.mako
+++ b/templates/webapps/galaxy/history/view.mako
@@ -83,8 +83,8 @@
show_hidden = context.get( 'show_hidden', None )
user_is_owner_json = 'true' if user_is_owner else 'false'
- show_deleted_json = h.to_json_string( show_deleted )
- show_hidden_json = h.to_json_string( show_hidden )
+ show_deleted_json = h.dumps( show_deleted )
+ show_hidden_json = h.dumps( show_hidden )
%><div id="header" class="clear">
@@ -164,8 +164,8 @@
}
var userIsOwner = ${'true' if user_is_owner else 'false'},
- historyJSON = ${h.to_json_string( history )},
- hdaJSON = ${h.to_json_string( hdas )};
+ historyJSON = ${h.dumps( history )},
+ hdaJSON = ${h.dumps( hdas )};
panelToUse = ( userIsOwner )?
//TODO: change class names
({ location: 'mvc/history/history-panel-edit', className: 'HistoryPanel' }):
diff -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 -r 983a1cc80be61c3ccdd3c10d06737381aacb9b05 templates/webapps/galaxy/library/index.mako
--- a/templates/webapps/galaxy/library/index.mako
+++ b/templates/webapps/galaxy/library/index.mako
@@ -12,4 +12,4 @@
<iframe name="galaxy_main" id="galaxy_main" frameborder="0" style="position: absolute; width: 100%; height: 100%;" src="${h.url_for( controller="library", action="browse_libraries", default_action=default_action )}"></iframe>
-</%def>
\ No newline at end of file
+</%def>
diff -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 -r 983a1cc80be61c3ccdd3c10d06737381aacb9b05 templates/webapps/galaxy/page/create.mako
--- a/templates/webapps/galaxy/page/create.mako
+++ b/templates/webapps/galaxy/page/create.mako
@@ -11,4 +11,4 @@
});
})
</script>
-</%def>
\ No newline at end of file
+</%def>
diff -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 -r 983a1cc80be61c3ccdd3c10d06737381aacb9b05 templates/webapps/galaxy/page/select_items_grid.mako
--- a/templates/webapps/galaxy/page/select_items_grid.mako
+++ b/templates/webapps/galaxy/page/select_items_grid.mako
@@ -1,3 +1,3 @@
## Template generates a grid that enables user to select items.
<%namespace file="../grid_base.mako" import="*" />
-${load(True)}
\ No newline at end of file
+${load(True)}
diff -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 -r 983a1cc80be61c3ccdd3c10d06737381aacb9b05 templates/webapps/galaxy/requests/common/sample_dataset_transfer_status.mako
--- a/templates/webapps/galaxy/requests/common/sample_dataset_transfer_status.mako
+++ b/templates/webapps/galaxy/requests/common/sample_dataset_transfer_status.mako
@@ -2,4 +2,4 @@
${sample_dataset.status}
</%def>
-${render_sample_dataset_transfer_status( sample_dataset )}
\ No newline at end of file
+${render_sample_dataset_transfer_status( sample_dataset )}
diff -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 -r 983a1cc80be61c3ccdd3c10d06737381aacb9b05 templates/webapps/galaxy/requests/grid.mako
--- a/templates/webapps/galaxy/requests/grid.mako
+++ b/templates/webapps/galaxy/requests/grid.mako
@@ -1,1 +1,1 @@
-<%inherit file="/grid_base.mako"/>
\ No newline at end of file
+<%inherit file="/grid_base.mako"/>
diff -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 -r 983a1cc80be61c3ccdd3c10d06737381aacb9b05 templates/webapps/galaxy/root/redirect.mako
--- a/templates/webapps/galaxy/root/redirect.mako
+++ b/templates/webapps/galaxy/root/redirect.mako
@@ -2,4 +2,4 @@
<script type="text/javascript">
top.location.href = '${redirect_url}';
-</script>
\ No newline at end of file
+</script>
diff -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 -r 983a1cc80be61c3ccdd3c10d06737381aacb9b05 templates/webapps/galaxy/root/tool_menu.mako
--- a/templates/webapps/galaxy/root/tool_menu.mako
+++ b/templates/webapps/galaxy/root/tool_menu.mako
@@ -25,12 +25,12 @@
hidden: false
}),
tools = new tools_mod.ToolCollection(
- ${ h.to_json_string( trans.app.toolbox.to_dict( trans, in_panel=False ) ) }
+ ${ h.dumps( trans.app.toolbox.to_dict( trans, in_panel=False ) ) }
),
tool_panel = new tools_mod.ToolPanel({
tool_search: tool_search,
tools: tools,
- layout: ${h.to_json_string( trans.app.toolbox.to_dict( trans ) )}
+ layout: ${h.dumps( trans.app.toolbox.to_dict( trans ) )}
}),
tool_panel_view = new tools_mod.ToolPanelView({ model: tool_panel });
diff -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 -r 983a1cc80be61c3ccdd3c10d06737381aacb9b05 templates/webapps/galaxy/tool_form.api.mako
--- a/templates/webapps/galaxy/tool_form.api.mako
+++ b/templates/webapps/galaxy/tool_form.api.mako
@@ -36,7 +36,7 @@
<script>
require(['mvc/tools/tools-form'], function(ToolsForm){
$(function(){
- var form = new ToolsForm.View(${ h.to_json_string(self.form_config) });
+ var form = new ToolsForm.View(${ h.dumps(self.form_config) });
});
});
</script>
diff -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 -r 983a1cc80be61c3ccdd3c10d06737381aacb9b05 templates/webapps/galaxy/tracks/add_tracks.mako
--- a/templates/webapps/galaxy/tracks/add_tracks.mako
+++ b/templates/webapps/galaxy/tracks/add_tracks.mako
@@ -1,3 +1,3 @@
## Template generates a grid that enables user to add tracks
<%namespace file="../grid_base.mako" import="*" />
-${load(True)}
\ No newline at end of file
+${load(True)}
diff -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 -r 983a1cc80be61c3ccdd3c10d06737381aacb9b05 templates/webapps/galaxy/tracks/history_datasets_select_grid.mako
--- a/templates/webapps/galaxy/tracks/history_datasets_select_grid.mako
+++ b/templates/webapps/galaxy/tracks/history_datasets_select_grid.mako
@@ -2,4 +2,4 @@
<%def name="title()"><h2>History '${grid.get_current_item( trans, **kwargs ).name}'</h2>
-</%def>
\ No newline at end of file
+</%def>
diff -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 -r 983a1cc80be61c3ccdd3c10d06737381aacb9b05 templates/webapps/galaxy/tracks/library_datasets_select_grid.mako
--- a/templates/webapps/galaxy/tracks/library_datasets_select_grid.mako
+++ b/templates/webapps/galaxy/tracks/library_datasets_select_grid.mako
@@ -10,4 +10,4 @@
${render_content(simple=True)}
<script type="text/javascript">
make_popup_menus();
-</script>
\ No newline at end of file
+</script>
diff -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 -r 983a1cc80be61c3ccdd3c10d06737381aacb9b05 templates/webapps/galaxy/visualization/create.mako
--- a/templates/webapps/galaxy/visualization/create.mako
+++ b/templates/webapps/galaxy/visualization/create.mako
@@ -11,4 +11,4 @@
});
})
</script>
-</%def>
\ No newline at end of file
+</%def>
diff -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 -r 983a1cc80be61c3ccdd3c10d06737381aacb9b05 templates/webapps/galaxy/visualization/display.mako
--- a/templates/webapps/galaxy/visualization/display.mako
+++ b/templates/webapps/galaxy/visualization/display.mako
@@ -89,9 +89,9 @@
vis_id: "${config.get('vis_id')}",
dbkey: "${config.get('dbkey')}"
},
- ${ h.to_json_string( config.get( 'viewport', dict() ) ) },
- ${ h.to_json_string( config['tracks'] ) },
- ${ h.to_json_string( config.get('bookmarks') ) }
+ ${ h.dumps( config.get( 'viewport', dict() ) ) },
+ ${ h.dumps( config['tracks'] ) },
+ ${ h.dumps( config.get('bookmarks') ) }
);
// Set up keyboard navigation.
@@ -105,4 +105,4 @@
});
</script>
-</%def>
\ No newline at end of file
+</%def>
diff -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 -r 983a1cc80be61c3ccdd3c10d06737381aacb9b05 templates/webapps/galaxy/visualization/item_content.mako
--- a/templates/webapps/galaxy/visualization/item_content.mako
+++ b/templates/webapps/galaxy/visualization/item_content.mako
@@ -1,3 +1,3 @@
<%namespace file="/visualization/display.mako" import="*" />
-${render_item( item, item_data )}
\ No newline at end of file
+${render_item( item, item_data )}
diff -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 -r 983a1cc80be61c3ccdd3c10d06737381aacb9b05 templates/webapps/galaxy/visualization/phyloviz.mako
--- a/templates/webapps/galaxy/visualization/phyloviz.mako
+++ b/templates/webapps/galaxy/visualization/phyloviz.mako
@@ -168,8 +168,8 @@
};
$(function firstVizLoad(){ // calls when viz is loaded for the first time
- var config = ${ h.to_json_string( config )};
- var data = ${h.to_json_string(data['data'])};
+ var config = ${ h.dumps( config )};
+ var data = ${h.dumps(data['data'])};
initPhyloViz(data, config);
});
});
diff -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 -r 983a1cc80be61c3ccdd3c10d06737381aacb9b05 templates/webapps/galaxy/visualization/sweepster.mako
--- a/templates/webapps/galaxy/visualization/sweepster.mako
+++ b/templates/webapps/galaxy/visualization/sweepster.mako
@@ -125,7 +125,7 @@
$(function() {
// -- Viz set up. --
var viz = new sweepster.SweepsterVisualization(
- ${ h.to_json_string( config )}
+ ${ h.dumps( config )}
);
var viz_view = new sweepster.SweepsterVisualizationView({ model: viz });
viz_view.render();
@@ -145,4 +145,4 @@
<div class="unified-panel-header-inner"></div></div>
-</%def>
\ No newline at end of file
+</%def>
diff -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 -r 983a1cc80be61c3ccdd3c10d06737381aacb9b05 templates/webapps/galaxy/workflow/configure_menu.mako
--- a/templates/webapps/galaxy/workflow/configure_menu.mako
+++ b/templates/webapps/galaxy/workflow/configure_menu.mako
@@ -95,4 +95,4 @@
</form></div></div>
-</%def>
\ No newline at end of file
+</%def>
diff -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 -r 983a1cc80be61c3ccdd3c10d06737381aacb9b05 templates/webapps/galaxy/workflow/item_content.mako
--- a/templates/webapps/galaxy/workflow/item_content.mako
+++ b/templates/webapps/galaxy/workflow/item_content.mako
@@ -1,3 +1,3 @@
<%namespace file="/workflow/display.mako" import="*" />
-${render_item( item, item_data )}
\ No newline at end of file
+${render_item( item, item_data )}
diff -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 -r 983a1cc80be61c3ccdd3c10d06737381aacb9b05 templates/webapps/galaxy/workflow/myexp_export_content.mako
--- a/templates/webapps/galaxy/workflow/myexp_export_content.mako
+++ b/templates/webapps/galaxy/workflow/myexp_export_content.mako
@@ -45,4 +45,4 @@
</connection>
%endfor
%endfor
-</connections>
\ No newline at end of file
+</connections>
diff -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 -r 983a1cc80be61c3ccdd3c10d06737381aacb9b05 templates/webapps/tool_shed/category/valid_grid.mako
--- a/templates/webapps/tool_shed/category/valid_grid.mako
+++ b/templates/webapps/tool_shed/category/valid_grid.mako
@@ -10,4 +10,4 @@
%></%def>
-${grid_base.load(False, capture(self.insert))}
\ No newline at end of file
+${grid_base.load(False, capture(self.insert))}
diff -r ce088c6f1fd47ba4628cf6cbf0c84dd7ac010086 -r 983a1cc80be61c3ccdd3c10d06737381aacb9b05 templates/webapps/tool_shed/common/grid_common.mako
--- a/templates/webapps/tool_shed/common/grid_common.mako
+++ b/templates/webapps/tool_shed/common/grid_common.mako
@@ -24,7 +24,7 @@
%if value != "All":
<%
if isinstance( temp_column, TextColumn ):
- value = h.to_json_string( value )
+ value = h.dumps( value )
%><input type="hidden" id="${temp_column.key}" name="f-${temp_column.key}" value='${value}'/>
%endif
@@ -51,7 +51,7 @@
<%
new_filter = list( column_filter )
del new_filter[ i ]
- new_column_filter = GridColumnFilter( "", { column.key : h.to_json_string( new_filter ) } )
+ new_column_filter = GridColumnFilter( "", { column.key : h.dumps( new_filter ) } )
%><a href="${url(new_column_filter.get_url_args())}"><span class="delete-search-icon" /></a></span>
https://bitbucket.org/galaxy/galaxy-central/commits/25396cf39fef/
Changeset: 25396cf39fef
User: dannon
Date: 2014-09-08 23:11:18
Summary: Charts to_json_string/dumps swap.
Affected #: 3 files
diff -r 983a1cc80be61c3ccdd3c10d06737381aacb9b05 -r 25396cf39fef9f77fbb802ed8ad5b8c2affb6cd6 config/plugins/visualizations/charts/templates/charts.mako
--- a/config/plugins/visualizations/charts/templates/charts.mako
+++ b/config/plugins/visualizations/charts/templates/charts.mako
@@ -86,8 +86,8 @@
require(['plugin/app'], function(App) {
// load options
var options = {
- id : ${h.to_json_string( visualization_id )} || undefined,
- config : ${h.to_json_string( config )}
+ id : ${h.dumps( visualization_id )} || undefined,
+ config : ${h.dumps( config )}
}
// create application
diff -r 983a1cc80be61c3ccdd3c10d06737381aacb9b05 -r 25396cf39fef9f77fbb802ed8ad5b8c2affb6cd6 config/plugins/visualizations/common/templates/config_utils.mako
--- a/config/plugins/visualizations/common/templates/config_utils.mako
+++ b/config/plugins/visualizations/common/templates/config_utils.mako
@@ -36,7 +36,7 @@
'action' : 'saved',
'type' : visualization_name,
'title' : title,
- 'config' : h.to_json_string( config )
+ 'config' : h.dumps( config )
}
# save to existing visualization
if visualization_id:
diff -r 983a1cc80be61c3ccdd3c10d06737381aacb9b05 -r 25396cf39fef9f77fbb802ed8ad5b8c2affb6cd6 config/plugins/visualizations/scatterplot/templates/scatterplot.mako
--- a/config/plugins/visualizations/scatterplot/templates/scatterplot.mako
+++ b/config/plugins/visualizations/scatterplot/templates/scatterplot.mako
@@ -50,11 +50,11 @@
<script type="text/javascript">
$(function(){
var model = new ScatterplotModel({
- id : ${h.to_json_string( visualization_id )} || undefined,
+ id : ${h.dumps( visualization_id )} || undefined,
title : "${title}",
- config : ${h.to_json_string( config, indent=2 )}
+ config : ${h.dumps( config, indent=2 )}
});
- hdaJson = ${h.to_json_string( trans.security.encode_dict_ids( hda.to_dict() ), indent=2 )},
+ hdaJson = ${h.dumps( trans.security.encode_dict_ids( hda.to_dict() ), indent=2 )},
display = new ScatterplotDisplay({
el : $( '.scatterplot-display' ).attr( 'id', 'scatterplot-display-' + '${visualization_id}' ),
model : model,
@@ -78,11 +78,11 @@
<script type="text/javascript">
$(function(){
var model = new ScatterplotModel({
- id : ${h.to_json_string( visualization_id )} || undefined,
+ id : ${h.dumps( visualization_id )} || undefined,
title : "${title or default_title}",
- config : ${h.to_json_string( config, indent=2 )}
+ config : ${h.dumps( config, indent=2 )}
}),
- hdaJson = ${h.to_json_string( trans.security.encode_dict_ids( hda.to_dict() ), indent=2 )},
+ hdaJson = ${h.dumps( trans.security.encode_dict_ids( hda.to_dict() ), indent=2 )},
editor = new ScatterplotConfigEditor({
el : $( '.scatterplot-editor' ).attr( 'id', 'scatterplot-editor-hda-' + hdaJson.id ),
model : model,
https://bitbucket.org/galaxy/galaxy-central/commits/23f0f1e9477f/
Changeset: 23f0f1e9477f
User: dannon
Date: 2014-09-09 16:04:28
Summary: Switch to_json_string/from_json_string in galaxy/scripts.
Affected #: 11 files
diff -r 25396cf39fef9f77fbb802ed8ad5b8c2affb6cd6 -r 23f0f1e9477f6c14abbe9f08a4b9d12f5c122631 scripts/cleanup_datasets/populate_uuid.py
--- a/scripts/cleanup_datasets/populate_uuid.py
+++ b/scripts/cleanup_datasets/populate_uuid.py
@@ -42,4 +42,4 @@
if __name__ == "__main__":
- main()
\ No newline at end of file
+ main()
diff -r 25396cf39fef9f77fbb802ed8ad5b8c2affb6cd6 -r 23f0f1e9477f6c14abbe9f08a4b9d12f5c122631 scripts/cleanup_datasets/remove_renamed_datasets_from_disk.py
--- a/scripts/cleanup_datasets/remove_renamed_datasets_from_disk.py
+++ b/scripts/cleanup_datasets/remove_renamed_datasets_from_disk.py
@@ -28,4 +28,4 @@
print >> out, "# Removed " + str( removed_files ) + " files"
if __name__ == "__main__":
- main()
\ No newline at end of file
+ main()
diff -r 25396cf39fef9f77fbb802ed8ad5b8c2affb6cd6 -r 23f0f1e9477f6c14abbe9f08a4b9d12f5c122631 scripts/cleanup_datasets/rename_purged_datasets.py
--- a/scripts/cleanup_datasets/rename_purged_datasets.py
+++ b/scripts/cleanup_datasets/rename_purged_datasets.py
@@ -29,4 +29,4 @@
print >> out, "# Renamed " + str( renamed_files ) + " files"
if __name__ == "__main__":
- main()
\ No newline at end of file
+ main()
diff -r 25396cf39fef9f77fbb802ed8ad5b8c2affb6cd6 -r 23f0f1e9477f6c14abbe9f08a4b9d12f5c122631 scripts/cleanup_datasets/update_dataset_size.py
--- a/scripts/cleanup_datasets/update_dataset_size.py
+++ b/scripts/cleanup_datasets/update_dataset_size.py
@@ -31,4 +31,4 @@
sys.exit(0)
if __name__ == "__main__":
- main()
\ No newline at end of file
+ main()
diff -r 25396cf39fef9f77fbb802ed8ad5b8c2affb6cd6 -r 23f0f1e9477f6c14abbe9f08a4b9d12f5c122631 scripts/cleanup_datasets/update_metadata.py
--- a/scripts/cleanup_datasets/update_metadata.py
+++ b/scripts/cleanup_datasets/update_metadata.py
@@ -73,4 +73,4 @@
sys.exit(0)
if __name__ == "__main__":
- main()
\ No newline at end of file
+ main()
diff -r 25396cf39fef9f77fbb802ed8ad5b8c2affb6cd6 -r 23f0f1e9477f6c14abbe9f08a4b9d12f5c122631 scripts/functional_tests.py
--- a/scripts/functional_tests.py
+++ b/scripts/functional_tests.py
@@ -48,7 +48,7 @@
from galaxy import tools
from galaxy.util import bunch
from galaxy import util
-from galaxy.util.json import to_json_string
+from galaxy.util.json import dumps
from functional import database_contexts
from base.api_util import get_master_api_key
@@ -520,7 +520,7 @@
has_test_data, shed_tools_dict = parse_tool_panel_config( shed_tool_config, shed_tools_dict )
# Persist the shed_tools_dict to the galaxy_tool_shed_test_file.
shed_tools_file = open( galaxy_tool_shed_test_file, 'w' )
- shed_tools_file.write( to_json_string( shed_tools_dict ) )
+ shed_tools_file.write( dumps( shed_tools_dict ) )
shed_tools_file.close()
if not os.path.isabs( galaxy_tool_shed_test_file ):
galaxy_tool_shed_test_file = os.path.join( os.getcwd(), galaxy_tool_shed_test_file )
diff -r 25396cf39fef9f77fbb802ed8ad5b8c2affb6cd6 -r 23f0f1e9477f6c14abbe9f08a4b9d12f5c122631 scripts/galaxy_messaging/client/scanner_interface.py
--- a/scripts/galaxy_messaging/client/scanner_interface.py
+++ b/scripts/galaxy_messaging/client/scanner_interface.py
@@ -73,4 +73,4 @@
return
-
\ No newline at end of file
+
diff -r 25396cf39fef9f77fbb802ed8ad5b8c2affb6cd6 -r 23f0f1e9477f6c14abbe9f08a4b9d12f5c122631 scripts/galaxy_messaging/server/setup_rabbitmq.py
--- a/scripts/galaxy_messaging/server/setup_rabbitmq.py
+++ b/scripts/galaxy_messaging/server/setup_rabbitmq.py
@@ -35,4 +35,4 @@
sys.exit(1)
if __name__ == '__main__':
- main( sys.argv[1] )
\ No newline at end of file
+ main( sys.argv[1] )
diff -r 25396cf39fef9f77fbb802ed8ad5b8c2affb6cd6 -r 23f0f1e9477f6c14abbe9f08a4b9d12f5c122631 scripts/galaxy_messaging/server/xml_helper.py
--- a/scripts/galaxy_messaging/server/xml_helper.py
+++ b/scripts/galaxy_messaging/server/xml_helper.py
@@ -25,4 +25,4 @@
for node in nodelist:
if node.nodeType == node.TEXT_NODE:
rc = rc + node.data
- return rc
\ No newline at end of file
+ return rc
diff -r 25396cf39fef9f77fbb802ed8ad5b8c2affb6cd6 -r 23f0f1e9477f6c14abbe9f08a4b9d12f5c122631 scripts/metagenomics/convert_title.py
--- a/scripts/metagenomics/convert_title.py
+++ b/scripts/metagenomics/convert_title.py
@@ -36,4 +36,4 @@
print "\n".join(seq)
print >> sys.stderr, "Unable to find gi number for %d sequences, the title is replaced as giunknown" %(invalid_lines)
-
\ No newline at end of file
+
diff -r 25396cf39fef9f77fbb802ed8ad5b8c2affb6cd6 -r 23f0f1e9477f6c14abbe9f08a4b9d12f5c122631 scripts/transfer.py
--- a/scripts/transfer.py
+++ b/scripts/transfer.py
@@ -122,7 +122,7 @@
response = {}
valid, request, response = json.validate_jsonrpc_request( request, ( 'get_state', ), () )
if valid:
- self.request.send( json.to_json_string( json.jsonrpc_response( request=request, result=self.server.state_result.result ) ) )
+ self.request.send( json.dumps( json.jsonrpc_response( request=request, result=self.server.state_result.result ) ) )
else:
error_msg = 'Unable to serve request: %s' % response['error']['message']
if 'data' in response['error']:
https://bitbucket.org/galaxy/galaxy-central/commits/a3450635b1d6/
Changeset: a3450635b1d6
User: dannon
Date: 2014-09-09 16:06:35
Summary: Switch to_json_string/from_json_string in galaxy/tools.
Affected #: 3 files
diff -r 23f0f1e9477f6c14abbe9f08a4b9d12f5c122631 -r a3450635b1d6a4fd9a796adf72f63c4f12623ec5 tools/data_source/data_source.py
--- a/tools/data_source/data_source.py
+++ b/tools/data_source/data_source.py
@@ -3,7 +3,7 @@
# Data source application parameters are temporarily stored in the dataset file.
import socket, urllib, sys, os
from galaxy import eggs #eggs needs to be imported so that galaxy.util can find docutils egg...
-from galaxy.util.json import from_json_string, to_json_string
+from galaxy.util.json import loads, dumps
from galaxy.util import get_charset_from_http_headers
import galaxy.model # need to import model before sniff to resolve a circular import dependency
from galaxy.datatypes import sniff
@@ -23,7 +23,7 @@
def load_input_parameters( filename, erase_file = True ):
datasource_params = {}
try:
- json_params = from_json_string( open( filename, 'r' ).read() )
+ json_params = loads( open( filename, 'r' ).read() )
datasource_params = json_params.get( 'param_dict' )
except:
json_params = None
@@ -44,7 +44,7 @@
max_file_size = int( sys.argv[2] )
except:
max_file_size = 0
-
+
job_params, params = load_input_parameters( filename )
if job_params is None: #using an older tabular file
enhanced_handling = False
@@ -57,13 +57,13 @@
else:
enhanced_handling = True
json_file = open( job_params[ 'job_config' ][ 'TOOL_PROVIDED_JOB_METADATA_FILE' ], 'w' ) #specially named file for output junk to pass onto set metadata
-
+
datatypes_registry = Registry()
datatypes_registry.load_datatypes( root_dir = job_params[ 'job_config' ][ 'GALAXY_ROOT_DIR' ], config = job_params[ 'job_config' ][ 'GALAXY_DATATYPES_CONF_FILE' ] )
-
+
URL = params.get( 'URL', None ) #using exactly URL indicates that only one dataset is being downloaded
URL_method = params.get( 'URL_method', None )
-
+
# The Python support for fetching resources from the web is layered. urllib uses the httplib
# library, which in turn uses the socket library. As of Python 2.3 you can specify how long
# a socket should wait for a response before timing out. By default the socket module has no
@@ -71,14 +71,14 @@
# levels. However, you can set the default timeout ( in seconds ) globally for all sockets by
# doing the following.
socket.setdefaulttimeout( 600 )
-
+
for data_dict in job_params[ 'output_data' ]:
cur_filename = data_dict.get( 'file_name', filename )
cur_URL = params.get( '%s|%s|URL' % ( GALAXY_PARAM_PREFIX, data_dict[ 'out_data_name' ] ), URL )
if not cur_URL:
open( cur_filename, 'w' ).write( "" )
stop_err( 'The remote data source application has not sent back a URL parameter in the request.' )
-
+
# The following calls to urllib.urlopen() will use the above default timeout
try:
if not URL_method or URL_method == 'get':
@@ -96,7 +96,7 @@
cur_filename, is_multi_byte = sniff.stream_to_open_named_file( page, os.open( cur_filename, os.O_WRONLY | os.O_CREAT ), cur_filename, source_encoding=get_charset_from_http_headers( page.headers ) )
except Exception, e:
stop_err( 'Unable to fetch %s:\n%s' % ( cur_URL, e ) )
-
+
#here import checks that upload tool performs
if enhanced_handling:
try:
@@ -106,7 +106,7 @@
info = dict( type = 'dataset',
dataset_id = data_dict[ 'dataset_id' ],
ext = ext)
-
- json_file.write( "%s\n" % to_json_string( info ) )
-
+
+ json_file.write( "%s\n" % dumps( info ) )
+
if __name__ == "__main__": __main__()
diff -r 23f0f1e9477f6c14abbe9f08a4b9d12f5c122631 -r a3450635b1d6a4fd9a796adf72f63c4f12623ec5 tools/data_source/upload.py
--- a/tools/data_source/upload.py
+++ b/tools/data_source/upload.py
@@ -36,7 +36,7 @@
sys.stderr.write( msg )
sys.exit( ret )
def file_err( msg, dataset, json_file ):
- json_file.write( to_json_string( dict( type = 'dataset',
+ json_file.write( dumps( dict( type = 'dataset',
ext = 'data',
dataset_id = dataset.dataset_id,
stderr = msg ) ) + "\n" )
@@ -319,7 +319,7 @@
line_count = line_count )
if dataset.get('uuid', None) is not None:
info['uuid'] = dataset.get('uuid')
- json_file.write( to_json_string( info ) + "\n" )
+ json_file.write( dumps( info ) + "\n" )
if link_data_only == 'copy_files' and datatype.dataset_content_needs_grooming( output_path ):
# Groom the dataset content if necessary
@@ -358,7 +358,7 @@
info = dict( type = 'dataset',
dataset_id = dataset.dataset_id,
stdout = 'uploaded %s file' % dataset.file_type )
- json_file.write( to_json_string( info ) + "\n" )
+ json_file.write( dumps( info ) + "\n" )
def output_adjacent_tmpdir( output_path ):
@@ -382,7 +382,7 @@
registry.load_datatypes( root_dir=sys.argv[1], config=sys.argv[2] )
for line in open( sys.argv[3], 'r' ):
- dataset = from_json_string( line )
+ dataset = loads( line )
dataset = util.bunch.Bunch( **safe_dict( dataset ) )
try:
output_path = output_paths[int( dataset.dataset_id )][0]
diff -r 23f0f1e9477f6c14abbe9f08a4b9d12f5c122631 -r a3450635b1d6a4fd9a796adf72f63c4f12623ec5 tools/filters/gff/gff_filter_by_attribute.py
--- a/tools/filters/gff/gff_filter_by_attribute.py
+++ b/tools/filters/gff/gff_filter_by_attribute.py
@@ -1,13 +1,13 @@
#!/usr/bin/env python
# This tool takes a gff file as input and creates filters on attributes based on certain properties.
# The tool will skip over invalid lines within the file, informing the user about the number of lines skipped.
-# TODO: much of this code is copied from the Filter1 tool (filtering.py in tools/stats/). The commonalities should be
+# TODO: much of this code is copied from the Filter1 tool (filtering.py in tools/stats/). The commonalities should be
# abstracted and leveraged in each filtering tool.
from __future__ import division
import sys
from galaxy import eggs
-from galaxy.util.json import to_json_string, from_json_string
+from galaxy.util.json import dumps, loads
# Older py compatibility
try:
@@ -44,7 +44,7 @@
except:
if operand in secured:
stop_err( "Illegal value '%s' in %s '%s'" % ( operand, description, text ) )
-
+
#
# Process inputs.
#
@@ -52,13 +52,13 @@
in_fname = sys.argv[1]
out_fname = sys.argv[2]
cond_text = sys.argv[3]
-attribute_types = from_json_string( sys.argv[4] )
+attribute_types = loads( sys.argv[4] )
# Convert types from str to type objects.
for name, a_type in attribute_types.items():
check_for_executable(a_type)
attribute_types[ name ] = eval( a_type )
-
+
# Unescape if input has been escaped
mapped_str = {
'__lt__': '<',
@@ -72,23 +72,23 @@
}
for key, value in mapped_str.items():
cond_text = cond_text.replace( key, value )
-
+
# Attempt to determine if the condition includes executable stuff and, if so, exit.
check_for_executable( cond_text, 'condition')
-# Prepare the column variable names and wrappers for column data types. Only
+# Prepare the column variable names and wrappers for column data types. Only
# prepare columns up to largest column in condition.
attrs, type_casts = [], []
for name, attr_type in attribute_types.items():
attrs.append( name )
type_cast = "get_value('%(name)s', attribute_types['%(name)s'], attribute_values)" % ( {'name': name} )
type_casts.append( type_cast )
-
+
attr_str = ', '.join( attrs ) # 'c1, c2, c3, c4'
type_cast_str = ', '.join( type_casts ) # 'str(c1), int(c2), int(c3), str(c4)'
wrap = "%s = %s" % ( attr_str, type_cast_str )
-
-# Stats
+
+# Stats
skipped_lines = 0
first_invalid_line = 0
invalid_line = None
@@ -102,7 +102,7 @@
return (a_type)(values_dict[ name ])
else:
return None
-
+
# Read and filter input file, skipping invalid lines
code = '''
for i, line in enumerate( file( in_fname ) ):
https://bitbucket.org/galaxy/galaxy-central/commits/c2a961719f38/
Changeset: c2a961719f38
User: dannon
Date: 2014-09-09 16:12:40
Summary: Final to_json_string/from_json_string elimination in tests.
Affected #: 20 files
diff -r a3450635b1d6a4fd9a796adf72f63c4f12623ec5 -r c2a961719f380f5acf89fdc68964e40c225879bc test/base/twilltestcase.py
--- a/test/base/twilltestcase.py
+++ b/test/base/twilltestcase.py
@@ -16,7 +16,7 @@
from base.asserts import verify_assertions
from galaxy.util import asbool
-from galaxy.util.json import from_json_string
+from galaxy.util.json import loads
from galaxy.web import security
from galaxy.web.framework.helpers import iff
from urlparse import urlparse
@@ -56,7 +56,7 @@
f = open( self.tool_shed_test_file, 'r' )
text = f.read()
f.close()
- self.shed_tools_dict = from_json_string( text )
+ self.shed_tools_dict = loads( text )
else:
self.shed_tools_dict = {}
self.keepOutdir = os.environ.get( 'GALAXY_TEST_SAVE', '' )
@@ -1293,12 +1293,12 @@
def get_running_datasets( self ):
self.visit_url( '/api/histories' )
- history_id = from_json_string( self.last_page() )[0][ 'id' ]
+ history_id = loads( self.last_page() )[0][ 'id' ]
self.visit_url( '/api/histories/%s/contents' % history_id )
- jsondata = from_json_string( self.last_page() )
+ jsondata = loads( self.last_page() )
for history_item in jsondata:
self.visit_url( history_item[ 'url' ] )
- item_json = from_json_string( self.last_page() )
+ item_json = loads( self.last_page() )
if item_json[ 'state' ] in [ 'queued', 'running', 'paused' ]:
return True
return False
@@ -1394,7 +1394,7 @@
def json_from_url( self, url, params={} ):
self.visit_url( url, params )
- return from_json_string( self.last_page() )
+ return loads( self.last_page() )
def last_page( self ):
return tc.browser.get_html()
@@ -2510,4 +2510,4 @@
self.visit_url( page_url )
data = self.last_page()
return data
- return fetcher
\ No newline at end of file
+ return fetcher
diff -r a3450635b1d6a4fd9a796adf72f63c4f12623ec5 -r c2a961719f380f5acf89fdc68964e40c225879bc test/casperjs/server_env.py
--- a/test/casperjs/server_env.py
+++ b/test/casperjs/server_env.py
@@ -100,7 +100,7 @@
f = open( self.tool_shed_test_file, 'r' )
text = f.read()
f.close()
- shed_tools_dict = from_json_string( text )
+ shed_tools_dict = loads( text )
except Exception, exc:
log.error( 'Error reading tool shed test file "%s": %s', self.tool_shed_test_file, exc, exc_info=True )
diff -r a3450635b1d6a4fd9a796adf72f63c4f12623ec5 -r c2a961719f380f5acf89fdc68964e40c225879bc test/functional/test_ucsc_table_browser.py
--- a/test/functional/test_ucsc_table_browser.py
+++ b/test/functional/test_ucsc_table_browser.py
@@ -32,4 +32,4 @@
)
self.run_ucsc_main( track_params, output_params )
self.wait()
- self.verify_dataset_correctness( 'GRCm38mm10_chr5_34761740-34912521.fa' )
\ No newline at end of file
+ self.verify_dataset_correctness( 'GRCm38mm10_chr5_34761740-34912521.fa' )
diff -r a3450635b1d6a4fd9a796adf72f63c4f12623ec5 -r c2a961719f380f5acf89fdc68964e40c225879bc test/install_and_test_tool_shed_repositories/__init__.py
--- a/test/install_and_test_tool_shed_repositories/__init__.py
+++ b/test/install_and_test_tool_shed_repositories/__init__.py
@@ -1,1 +1,1 @@
-"""Install and test tool shed repositories."""
\ No newline at end of file
+"""Install and test tool shed repositories."""
diff -r a3450635b1d6a4fd9a796adf72f63c4f12623ec5 -r c2a961719f380f5acf89fdc68964e40c225879bc test/install_and_test_tool_shed_repositories/functional/__init__.py
--- a/test/install_and_test_tool_shed_repositories/functional/__init__.py
+++ b/test/install_and_test_tool_shed_repositories/functional/__init__.py
@@ -1,1 +1,1 @@
-'''Tests'''
\ No newline at end of file
+'''Tests'''
diff -r a3450635b1d6a4fd9a796adf72f63c4f12623ec5 -r c2a961719f380f5acf89fdc68964e40c225879bc test/install_and_test_tool_shed_repositories/repositories_with_tools/__init__.py
--- a/test/install_and_test_tool_shed_repositories/repositories_with_tools/__init__.py
+++ b/test/install_and_test_tool_shed_repositories/repositories_with_tools/__init__.py
@@ -1,1 +1,1 @@
-"""Install and test tool shed repositories that contain tools and tool test components."""
\ No newline at end of file
+"""Install and test tool shed repositories that contain tools and tool test components."""
diff -r a3450635b1d6a4fd9a796adf72f63c4f12623ec5 -r c2a961719f380f5acf89fdc68964e40c225879bc test/install_and_test_tool_shed_repositories/repositories_with_tools/functional_tests.py
--- a/test/install_and_test_tool_shed_repositories/repositories_with_tools/functional_tests.py
+++ b/test/install_and_test_tool_shed_repositories/repositories_with_tools/functional_tests.py
@@ -42,7 +42,7 @@
from base.tool_shed_util import parse_tool_panel_config
from galaxy.app import UniverseApplication
-from galaxy.util.json import from_json_string
+from galaxy.util.json import loads
from galaxy.util import asbool
from galaxy.util import unicodify
from galaxy.web import buildapp
@@ -312,7 +312,7 @@
# Find the path to the test-data directory within the installed repository.
has_test_data, shed_tools_dict = \
parse_tool_panel_config( galaxy_shed_tool_conf_file,
- from_json_string( file( galaxy_shed_tools_dict_file, 'r' ).read() ) )
+ loads( file( galaxy_shed_tools_dict_file, 'r' ).read() ) )
# If the repository has a test-data directory we write the generated shed_tools_dict to a temporary
# file so the functional test framework can find it.
install_and_test_base_util.populate_galaxy_shed_tools_dict_file( galaxy_shed_tools_dict_file,
diff -r a3450635b1d6a4fd9a796adf72f63c4f12623ec5 -r c2a961719f380f5acf89fdc68964e40c225879bc test/install_and_test_tool_shed_repositories/tool_dependency_definitions/__init__.py
--- a/test/install_and_test_tool_shed_repositories/tool_dependency_definitions/__init__.py
+++ b/test/install_and_test_tool_shed_repositories/tool_dependency_definitions/__init__.py
@@ -1,1 +1,1 @@
-"""Install and test tool shed repositories of type tool_dependency_definition."""
\ No newline at end of file
+"""Install and test tool shed repositories of type tool_dependency_definition."""
diff -r a3450635b1d6a4fd9a796adf72f63c4f12623ec5 -r c2a961719f380f5acf89fdc68964e40c225879bc test/tool_shed/__init__.py
--- a/test/tool_shed/__init__.py
+++ b/test/tool_shed/__init__.py
@@ -1,1 +1,1 @@
-"""Tool shed functional Tests"""
\ No newline at end of file
+"""Tool shed functional Tests"""
diff -r a3450635b1d6a4fd9a796adf72f63c4f12623ec5 -r c2a961719f380f5acf89fdc68964e40c225879bc test/tool_shed/base/twilltestcase.py
--- a/test/tool_shed/base/twilltestcase.py
+++ b/test/tool_shed/base/twilltestcase.py
@@ -15,7 +15,7 @@
from base.tool_shed_util import repository_installation_timeout
from base.twilltestcase import TwillTestCase
-from galaxy.util.json import from_json_string
+from galaxy.util.json import loads
from galaxy.web import security
from tool_shed.util.encoding_util import tool_shed_encode
from tool_shed.util import shed_util_common as suc
@@ -637,7 +637,7 @@
url = '/api/datatypes?upload_only=false'
self.visit_galaxy_url( url )
html = self.last_page()
- datatypes = from_json_string( html )
+ datatypes = loads( html )
return len( datatypes )
def get_env_sh_path( self, tool_dependency_name, tool_dependency_version, repository ):
@@ -714,7 +714,7 @@
# Get the current folder's contents.
url = '/repository/open_folder?folder_path=%s' % request_param_path
self.visit_url( url )
- file_list = from_json_string( self.last_page() )
+ file_list = loads( self.last_page() )
returned_file_list = []
if current_path is not None:
returned_file_list.append( current_path )
@@ -753,7 +753,7 @@
url = '/api/datatypes/sniffers'
self.visit_galaxy_url( url )
html = self.last_page()
- sniffers = from_json_string( html )
+ sniffers = loads( html )
return len( sniffers )
def get_tools_from_repository_metadata( self, repository, include_invalid=False ):
@@ -772,7 +772,7 @@
tool_guid = urllib.quote_plus( tool_metadata[ 0 ][ 'guid' ], safe='' )
api_url = '/%s' % '/'.join( [ 'api', 'tools', tool_guid ] )
self.visit_galaxy_url( api_url )
- tool_dict = from_json_string( self.last_page() )
+ tool_dict = loads( self.last_page() )
tool_panel_section = tool_dict[ 'panel_section_name' ]
return tool_panel_section
diff -r a3450635b1d6a4fd9a796adf72f63c4f12623ec5 -r c2a961719f380f5acf89fdc68964e40c225879bc test/tool_shed/functional/test_0170_complex_prior_installation_required.py
--- a/test/tool_shed/functional/test_0170_complex_prior_installation_required.py
+++ b/test/tool_shed/functional/test_0170_complex_prior_installation_required.py
@@ -131,4 +131,4 @@
self.check_repository_dependency( matplotlib_repository, depends_on_repository=numpy_repository )
self.display_manage_repository_page( matplotlib_repository, strings_displayed=[ 'numpy', '1.7', 'package', changeset_revision ] )
-
\ No newline at end of file
+
diff -r a3450635b1d6a4fd9a796adf72f63c4f12623ec5 -r c2a961719f380f5acf89fdc68964e40c225879bc test/tool_shed/functional/test_0310_hg_push_from_api.py
--- a/test/tool_shed/functional/test_0310_hg_push_from_api.py
+++ b/test/tool_shed/functional/test_0310_hg_push_from_api.py
@@ -166,4 +166,4 @@
'Added another line to filtering.py.' ]
strings_not_displayed = [ 'Added a line to filtering.py' ]
self.check_repository_changelog( repository, strings_displayed=strings_displayed, strings_not_displayed=[] )
-
\ No newline at end of file
+
diff -r a3450635b1d6a4fd9a796adf72f63c4f12623ec5 -r c2a961719f380f5acf89fdc68964e40c225879bc test/tool_shed/functional/test_0410_repository_component_review_access_control.py
--- a/test/tool_shed/functional/test_0410_repository_component_review_access_control.py
+++ b/test/tool_shed/functional/test_0410_repository_component_review_access_control.py
@@ -192,4 +192,4 @@
changeset_revision = self.get_repository_tip( repository )
review = self.test_db_util.get_repository_review_by_user_id_changeset_revision( user.id, repository.id, changeset_revision )
self.browse_component_review( review, strings_displayed=strings_displayed )
-
\ No newline at end of file
+
diff -r a3450635b1d6a4fd9a796adf72f63c4f12623ec5 -r c2a961719f380f5acf89fdc68964e40c225879bc test/tool_shed/functional/test_0420_citable_urls_for_repositories.py
--- a/test/tool_shed/functional/test_0420_citable_urls_for_repositories.py
+++ b/test/tool_shed/functional/test_0420_citable_urls_for_repositories.py
@@ -227,4 +227,4 @@
encoded_user_id=None,
encoded_repository_id=None,
strings_displayed=strings_displayed )
-
\ No newline at end of file
+
diff -r a3450635b1d6a4fd9a796adf72f63c4f12623ec5 -r c2a961719f380f5acf89fdc68964e40c225879bc test/tool_shed/functional/test_0460_upload_to_repository.py
--- a/test/tool_shed/functional/test_0460_upload_to_repository.py
+++ b/test/tool_shed/functional/test_0460_upload_to_repository.py
@@ -482,4 +482,4 @@
self.display_repository_file_contents( repository,
filename='repository_dependencies.xml',
filepath='subfolder',
- strings_displayed=[ changeset_revision ] )
\ No newline at end of file
+ strings_displayed=[ changeset_revision ] )
diff -r a3450635b1d6a4fd9a796adf72f63c4f12623ec5 -r c2a961719f380f5acf89fdc68964e40c225879bc test/tool_shed/functional/test_0480_tool_dependency_xml_verification.py
--- a/test/tool_shed/functional/test_0480_tool_dependency_xml_verification.py
+++ b/test/tool_shed/functional/test_0480_tool_dependency_xml_verification.py
@@ -72,4 +72,4 @@
repository = self.test_db_util.get_repository_by_name_and_owner( repository_name, common.test_user_1_name )
assert self.repository_is_new( repository ), 'Uploading an incorrectly defined tool_dependencies.xml resulted in a changeset being generated.'
-
\ No newline at end of file
+
diff -r a3450635b1d6a4fd9a796adf72f63c4f12623ec5 -r c2a961719f380f5acf89fdc68964e40c225879bc test/tool_shed/functional/test_1087_install_updated_repository_dependencies.py
--- a/test/tool_shed/functional/test_1087_install_updated_repository_dependencies.py
+++ b/test/tool_shed/functional/test_1087_install_updated_repository_dependencies.py
@@ -116,4 +116,4 @@
self.visit_galaxy_url( url, params )
self.check_for_strings( strings_displayed )
strings_not_displayed = [ 'column_maker_1087' ]
- self.display_galaxy_browse_repositories_page( strings_not_displayed=strings_not_displayed )
\ No newline at end of file
+ self.display_galaxy_browse_repositories_page( strings_not_displayed=strings_not_displayed )
diff -r a3450635b1d6a4fd9a796adf72f63c4f12623ec5 -r c2a961719f380f5acf89fdc68964e40c225879bc test/tool_shed/functional/test_1170_complex_prior_installation_required.py
--- a/test/tool_shed/functional/test_1170_complex_prior_installation_required.py
+++ b/test/tool_shed/functional/test_1170_complex_prior_installation_required.py
@@ -175,4 +175,4 @@
numpy_repository = self.test_db_util.get_installed_repository_by_name_owner( numpy_repository_name, common.test_user_1_name )
assert matplotlib_repository.update_time > numpy_repository.update_time, \
'Error: package_numpy_1_7_0170 shows a later update time than package_matplotlib_1_2_0170'
-
\ No newline at end of file
+
diff -r a3450635b1d6a4fd9a796adf72f63c4f12623ec5 -r c2a961719f380f5acf89fdc68964e40c225879bc test/tool_shed/functional/test_1300_reset_all_metadata.py
--- a/test/tool_shed/functional/test_1300_reset_all_metadata.py
+++ b/test/tool_shed/functional/test_1300_reset_all_metadata.py
@@ -463,4 +463,4 @@
del old_metadata[ 'tool_panel_section' ]
assert repository.metadata == old_metadata, 'Metadata for %s repository %s changed after reset. \nOld: %s\nNew: %s' % \
( repository.status, repository.name, old_metadata, repository.metadata )
-
\ No newline at end of file
+
diff -r a3450635b1d6a4fd9a796adf72f63c4f12623ec5 -r c2a961719f380f5acf89fdc68964e40c225879bc test/tool_shed/functional_tests.py
--- a/test/tool_shed/functional_tests.py
+++ b/test/tool_shed/functional_tests.py
@@ -57,7 +57,7 @@
from galaxy.app import UniverseApplication as GalaxyUniverseApplication
from galaxy.web import buildapp as galaxybuildapp
from galaxy.util import asbool
-from galaxy.util.json import to_json_string
+from galaxy.util.json import dumps
import nose.core
import nose.config
@@ -182,7 +182,7 @@
galaxy_test_proxy_port = None
if 'TOOL_SHED_TEST_DBPATH' in os.environ:
shed_db_path = os.environ[ 'TOOL_SHED_TEST_DBPATH' ]
- else:
+ else:
tempdir = tempfile.mkdtemp( dir=tool_shed_test_tmp_dir )
shed_db_path = os.path.join( tempdir, 'database' )
shed_tool_data_table_conf_file = os.environ.get( 'TOOL_SHED_TEST_TOOL_DATA_TABLE_CONF', os.path.join( tool_shed_test_tmp_dir, 'shed_tool_data_table_conf.xml' ) )
@@ -199,7 +199,7 @@
os.environ[ 'GALAXY_TEST_TOOL_DATA_PATH' ] = tool_data_path
if 'GALAXY_TEST_DBPATH' in os.environ:
galaxy_db_path = os.environ[ 'GALAXY_TEST_DBPATH' ]
- else:
+ else:
tempdir = tempfile.mkdtemp( dir=tool_shed_test_tmp_dir )
galaxy_db_path = os.path.join( tempdir, 'database' )
shed_file_path = os.path.join( shed_db_path, 'files' )
@@ -207,9 +207,9 @@
hgweb_config_file_path = tempfile.mkdtemp( dir=tool_shed_test_tmp_dir )
new_repos_path = tempfile.mkdtemp( dir=tool_shed_test_tmp_dir )
galaxy_tempfiles = tempfile.mkdtemp( dir=tool_shed_test_tmp_dir )
- galaxy_shed_tool_path = tempfile.mkdtemp( dir=tool_shed_test_tmp_dir )
- galaxy_migrated_tool_path = tempfile.mkdtemp( dir=tool_shed_test_tmp_dir )
- galaxy_tool_dependency_dir = tempfile.mkdtemp( dir=tool_shed_test_tmp_dir )
+ galaxy_shed_tool_path = tempfile.mkdtemp( dir=tool_shed_test_tmp_dir )
+ galaxy_migrated_tool_path = tempfile.mkdtemp( dir=tool_shed_test_tmp_dir )
+ galaxy_tool_dependency_dir = tempfile.mkdtemp( dir=tool_shed_test_tmp_dir )
os.environ[ 'GALAXY_TEST_TOOL_DEPENDENCY_DIR' ] = galaxy_tool_dependency_dir
hgweb_config_dir = hgweb_config_file_path
os.environ[ 'TEST_HG_WEB_CONFIG_DIR' ] = hgweb_config_dir
@@ -276,8 +276,8 @@
# Generate the shed_tool_data_table_conf.xml file.
file( shed_tool_data_table_conf_file, 'w' ).write( tool_data_table_conf_xml_template )
os.environ[ 'TOOL_SHED_TEST_TOOL_DATA_TABLE_CONF' ] = shed_tool_data_table_conf_file
- # ---- Build Tool Shed Application --------------------------------------------------
- toolshedapp = None
+ # ---- Build Tool Shed Application --------------------------------------------------
+ toolshedapp = None
# if not toolshed_database_connection.startswith( 'sqlite://' ):
# kwargs[ 'database_engine_option_max_overflow' ] = '20'
if tool_dependency_dir is not None:
@@ -335,7 +335,7 @@
else:
raise Exception( "Test HTTP server did not return '200 OK' after 10 tries" )
log.info( "Embedded web server started" )
-
+
# ---- Optionally start up a Galaxy instance ------------------------------------------------------
if 'TOOL_SHED_TEST_OMIT_GALAXY' not in os.environ:
# Generate the tool_conf.xml file.
@@ -357,7 +357,7 @@
open( galaxy_shed_data_manager_conf_file, 'wb' ).write( shed_data_manager_conf_xml_template )
galaxy_global_conf = get_webapp_global_conf()
galaxy_global_conf[ '__file__' ] = 'universe_wsgi.ini.sample'
-
+
kwargs = dict( allow_user_creation = True,
allow_user_deletion = True,
admin_users = 'test(a)bx.psu.edu',
@@ -389,15 +389,15 @@
tool_data_table_config_path = galaxy_tool_data_table_conf_file,
update_integrated_tool_panel = False,
use_heartbeat = False )
-
- # ---- Build Galaxy Application --------------------------------------------------
+
+ # ---- Build Galaxy Application --------------------------------------------------
if not galaxy_database_connection.startswith( 'sqlite://' ) and not install_galaxy_database_connection.startswith( 'sqlite://' ):
kwargs[ 'database_engine_option_pool_size' ] = '10'
kwargs[ 'database_engine_option_max_overflow' ] = '20'
galaxyapp = GalaxyUniverseApplication( **kwargs )
log.info( "Embedded Galaxy application started" )
-
+
# ---- Run galaxy webserver ------------------------------------------------------
galaxy_server = None
galaxy_global_conf[ 'database_file' ] = galaxy_database_connection
@@ -464,11 +464,11 @@
test_config = nose.config.Config( env=os.environ, ignoreFiles=ignore_files, plugins=nose.plugins.manager.DefaultPluginManager() )
test_config.configure( sys.argv )
# Run the tests.
- result = run_tests( test_config )
+ result = run_tests( test_config )
success = result.wasSuccessful()
except:
log.exception( "Failure running tests" )
-
+
log.info( "Shutting down" )
# ---- Tear down -----------------------------------------------------------
if tool_shed_server:
https://bitbucket.org/galaxy/galaxy-central/commits/6f06ff96d5ca/
Changeset: 6f06ff96d5ca
User: dannon
Date: 2014-09-09 16:17:56
Summary: Add deprecation notice for to_json_string/from_json_string. I left these references just in case I missed something that uses them.
Affected #: 1 file
diff -r c2a961719f380f5acf89fdc68964e40c225879bc -r 6f06ff96d5cacd8cd73b9a7e50d43aff5322dc17 lib/galaxy/util/json.py
--- a/lib/galaxy/util/json.py
+++ b/lib/galaxy/util/json.py
@@ -7,8 +7,8 @@
import random
import string
-to_json_string = json.dumps
-from_json_string = json.loads
+to_json_string = json.dumps # deprecated
+from_json_string = json.loads # deprecated
dumps = json.dumps
loads = json.loads
@@ -25,9 +25,9 @@
else:
return val
+
# Methods for handling JSON-RPC
-
def validate_jsonrpc_request( request, regular_methods, notification_methods ):
try:
request = loads( request )
https://bitbucket.org/galaxy/galaxy-central/commits/74b2495de918/
Changeset: 74b2495de918
User: dannon
Date: 2014-09-09 22:31:31
Summary: Merge json changes (and some cleanup) back with central.
Affected #: 62 files
diff -r 6f06ff96d5cacd8cd73b9a7e50d43aff5322dc17 -r 74b2495de918c95730f1f2fd2ac1bf502018a99f run_functional_tests.sh
--- /dev/null
+++ b/run_functional_tests.sh
@@ -0,0 +1,1 @@
+run_tests.sh
\ No newline at end of file
diff -r 6f06ff96d5cacd8cd73b9a7e50d43aff5322dc17 -r 74b2495de918c95730f1f2fd2ac1bf502018a99f static/scripts/mvc/base-mvc.js
--- a/static/scripts/mvc/base-mvc.js
+++ b/static/scripts/mvc/base-mvc.js
@@ -42,6 +42,7 @@
if( this.logger ){
var log = this.logger.log;
if( typeof this.logger.log === 'object' ){
+//TODO:! there has to be a way to get the lineno/file into this
log = Function.prototype.bind.call( this.logger.log, this.logger );
}
return log.apply( this.logger, arguments );
@@ -149,6 +150,23 @@
//==============================================================================
+/** Function that allows mixing of hashs into bbone MVC while showing the mixins first
+ * (before the more local class overrides/hash).
+ * Basically, a simple reversal of param order on _.defaults() - to show mixins in top of definition.
+ * @example:
+ * var NewModel = Something.extend( mixin( MyMixinA, MyMixinB, { ... myVars : ... }) );
+ *
+ * NOTE: this does not combine any hashes (like events, etc.) and you're expected to handle that
+ */
+function mixin( mixinHash1, /* mixinHash2, etc: ... variadic */ propsHash ){
+ var args = Array.prototype.slice.call( arguments, 0 ),
+ lastArg = args.pop();
+ args.unshift( lastArg );
+ return _.defaults.apply( _, args );
+}
+
+
+//==============================================================================
/** A mixin for models that allow T/F/Matching to their attributes - useful when
* searching or filtering collections of models.
* @example:
@@ -329,205 +347,6 @@
//==============================================================================
-/** Function that allows mixing of hashs into bbone MVC while showing the mixins first
- * (before the more local class overrides/hash).
- * Basically, a simple reversal of param order on _.defaults() - to show mixins in top of definition.
- * @example:
- * var NewModel = Something.extend( mixin( MyMixinA, MyMixinB, { ... myVars : ... }) );
- *
- * NOTE: this does not combine any hashes (like events, etc.) and you're expected to handle that
- */
-function mixin( mixinHash1, /* mixinHash2, etc: ... variadic */ propsHash ){
- var args = Array.prototype.slice.call( arguments, 0 ),
- lastArg = args.pop();
- args.unshift( lastArg );
- return _.defaults.apply( _, args );
-}
-
-//==============================================================================
-/** Return an underscore template fn from an array of strings.
- * @param {String[]} template the template strings to compile into the underscore template fn
- * @param {String} jsonNamespace an optional namespace for the json data passed in (defaults to 'model')
- * @returns {Function} the (wrapped) underscore template fn
- * The function accepts:
- *
- * The template strings can access:
- * the json/model hash using model ("<%- model.myAttr %>) using the jsonNamespace above
- * _l: the localizer function
- * view (if passed): ostensibly, the view using the template (handy for view instance vars)
- * Because they're namespaced, undefined attributes will not throw an error.
- *
- * @example:
- * templateBler : BASE_MVC.wrapTemplate([
- * '<div class="myclass <%- mynamespace.modelClass %>">',
- * '<span><% print( _l( mynamespace.message ) ); %>:<%= view.status %></span>'
- * '</div>'
- * ], 'mynamespace' )
- *
- * Meant to be called in a View's definition in order to compile only once.
- *
- */
-function wrapTemplate( template, jsonNamespace ){
- jsonNamespace = jsonNamespace || 'model';
- var templateFn = _.template( template.join( '' ) );
- return function( json, view ){
- var templateVars = { view : view || {}, _l : _l };
- templateVars[ jsonNamespace ] = json || {};
- return templateFn( templateVars );
- };
-}
-
-//==============================================================================
-/** A view which, when first rendered, shows only summary data/attributes, but
- * can be expanded to show further details (and optionally fetch those
- * details from the server).
- */
-var ExpandableView = Backbone.View.extend( LoggableMixin ).extend({
-//TODO: Although the reasoning behind them is different, this shares a lot with HiddenUntilActivated above: combine them
- //PRECONDITION: model must have method hasDetails
- //PRECONDITION: subclasses must have templates.el and templates.details
-
- initialize : function( attributes ){
- /** are the details of this view expanded/shown or not? */
- this.expanded = attributes.expanded || false;
- //this.log( '\t expanded:', this.expanded );
- this.fxSpeed = attributes.fxSpeed || this.fxSpeed;
- },
-
- // ........................................................................ render main
- /** jq fx speed */
- fxSpeed : 'fast',
-
- /** Render this content, set up ui.
- * @param {Number or String} speed the speed of the render
- */
- render : function( speed ){
- var $newRender = this._buildNewRender();
- this._setUpBehaviors( $newRender );
- this._queueNewRender( $newRender, speed );
- return this;
- },
-
- /** Build a temp div containing the new children for the view's $el.
- * If the view is already expanded, build the details as well.
- */
- _buildNewRender : function(){
- // create a new render using a skeleton template, render title buttons, render body, and set up events, etc.
- var $newRender = $( this.templates.el( this.model.toJSON(), this ) );
- if( this.expanded ){
- this.$details( $newRender ).replaceWith( this._renderDetails().show() );
- }
- return $newRender;
- },
-
- /** Fade out the old el, swap in the new contents, then fade in.
- * @param {Number or String} speed jq speed to use for rendering effects
- * @fires rendered when rendered
- */
- _queueNewRender : function( $newRender, speed ) {
- speed = ( speed === undefined )?( this.fxSpeed ):( speed );
- var view = this;
-
- $( view ).queue( 'fx', [
- function( next ){ this.$el.fadeOut( speed, next ); },
- function( next ){
- view._swapNewRender( $newRender );
- next();
- },
- function( next ){ this.$el.fadeIn( speed, next ); },
- function( next ){
- this.trigger( 'rendered', view );
- next();
- }
- ]);
- },
-
- /** empty out the current el, move the $newRender's children in */
- _swapNewRender : function( $newRender ){
- return this.$el.empty().attr( 'class', this.className ).append( $newRender.children() );
- },
-
- /** set up js behaviors, event handlers for elements within the given container
- * @param {jQuery} $container jq object that contains the elements to process (defaults to this.$el)
- */
- _setUpBehaviors : function( $where ){
- $where = $where || this.$el;
- // set up canned behavior on children (bootstrap, popupmenus, editable_text, etc.)
- //make_popup_menus( $where );
- $where.find( '[title]' ).tooltip({ placement : 'bottom' });
- },
-
- // ......................................................................... details
- /** shortcut to details DOM (as jQ) */
- $details : function( $where ){
- $where = $where || this.$el;
- return $where.find( '.details' );
- },
-
- /** build the DOM for the details and set up behaviors on it */
- _renderDetails : function(){
- var $newDetails = $( this.templates.details( this.model.toJSON(), this ) );
- this._setUpBehaviors( $newDetails );
- return $newDetails;
- },
-
- // ......................................................................... expansion/details
- /** Show or hide the details
- * @param {Boolean} expand if true, expand; if false, collapse
- */
- toggleExpanded : function( expand ){
- expand = ( expand === undefined )?( !this.expanded ):( expand );
- if( expand ){
- this.expand();
- } else {
- this.collapse();
- }
- return this;
- },
-
- /** Render and show the full, detailed body of this view including extra data and controls.
- * note: if the model does not have detailed data, fetch that data before showing the body
- * @fires expanded when a body has been expanded
- */
- expand : function(){
- var view = this;
- return view._fetchModelDetails()
- .always(function(){
- var $newDetails = view._renderDetails();
- view.$details().replaceWith( $newDetails );
- // needs to be set after the above or the slide will not show
- view.expanded = true;
- $newDetails.slideDown( view.fxSpeed, function(){
- view.trigger( 'expanded', view );
- });
- });
- },
-
- /** Check for model details and, if none, fetch them.
- * @returns {jQuery.promise} the model.fetch.xhr if details are being fetched, an empty promise if not
- */
- _fetchModelDetails : function(){
- if( !this.model.hasDetails() ){
- return this.model.fetch();
- }
- return jQuery.when();
- },
-
- /** Hide the body/details of an HDA.
- * @fires collapsed when a body has been collapsed
- */
- collapse : function(){
- var view = this;
- view.expanded = false;
- this.$details().slideUp( view.fxSpeed, function(){
- view.trigger( 'collapsed', view );
- });
- }
-
-});
-
-
-//==============================================================================
/** Mixin for views that can be dragged and dropped
* Allows for the drag behavior to be turned on/off, setting/removing jQuery event
* handlers each time.
@@ -711,186 +530,48 @@
//==============================================================================
-/** A view that is displayed in some larger list/grid/collection.
- * Inherits from Expandable, Selectable, Draggable.
- * The DOM contains warnings, a title bar, and a series of primary action controls.
- * Primary actions are meant to be easily accessible item functions (such as delete)
- * that are rendered in the title bar.
+/** Return an underscore template fn from an array of strings.
+ * @param {String[]} template the template strings to compile into the underscore template fn
+ * @param {String} jsonNamespace an optional namespace for the json data passed in (defaults to 'model')
+ * @returns {Function} the (wrapped) underscore template fn
+ * The function accepts:
*
- * Details are rendered when the user clicks the title bar or presses enter/space when
- * the title bar is in focus.
+ * The template strings can access:
+ * the json/model hash using model ("<%- model.myAttr %>) using the jsonNamespace above
+ * _l: the localizer function
+ * view (if passed): ostensibly, the view using the template (handy for view instance vars)
+ * Because they're namespaced, undefined attributes will not throw an error.
*
- * Designed as a base class for history panel contents - but usable elsewhere (I hope).
+ * @example:
+ * templateBler : BASE_MVC.wrapTemplate([
+ * '<div class="myclass <%- mynamespace.modelClass %>">',
+ * '<span><% print( _l( mynamespace.message ) ); %>:<%= view.status %></span>'
+ * '</div>'
+ * ], 'mynamespace' )
+ *
+ * Meant to be called in a View's definition in order to compile only once.
+ *
*/
-var ListItemView = ExpandableView.extend( mixin( SelectableViewMixin, DraggableViewMixin, {
-
-//TODO: that's a little contradictory
- tagName : 'div',
- className : 'list-item',
-
- /** Set up the base class and all mixins */
- initialize : function( attributes ){
- ExpandableView.prototype.initialize.call( this, attributes );
- SelectableViewMixin.initialize.call( this, attributes );
- DraggableViewMixin.initialize.call( this, attributes );
- },
-
- // ........................................................................ rendering
- /** In this override, call methods to build warnings, titlebar and primary actions */
- _buildNewRender : function(){
- var $newRender = ExpandableView.prototype._buildNewRender.call( this );
- $newRender.find( '.warnings' ).replaceWith( this._renderWarnings() );
- $newRender.find( '.title-bar' ).replaceWith( this._renderTitleBar() );
- $newRender.find( '.primary-actions' ).append( this._renderPrimaryActions() );
- $newRender.find( '.subtitle' ).replaceWith( this._renderSubtitle() );
- return $newRender;
- },
-
- /** In this override, render the selector controls and set up dragging before the swap */
- _swapNewRender : function( $newRender ){
- ExpandableView.prototype._swapNewRender.call( this, $newRender );
- if( this.selectable ){ this.showSelector( 0 ); }
- if( this.draggable ){ this.draggableOn(); }
- return this.$el;
- },
-
- /** Render any warnings the item may need to show (e.g. "I'm deleted") */
- _renderWarnings : function(){
- var view = this,
- $warnings = $( '<div class="warnings"></div>' ),
- json = view.model.toJSON();
-//TODO:! unordered (map)
- _.each( view.templates.warnings, function( templateFn ){
- $warnings.append( $( templateFn( json, view ) ) );
- });
- return $warnings;
- },
-
- /** Render the title bar (the main/exposed SUMMARY dom element) */
- _renderTitleBar : function(){
- return $( this.templates.titleBar( this.model.toJSON(), this ) );
- },
-
- /** Return an array of jQ objects containing common/easily-accessible item controls */
- _renderPrimaryActions : function(){
- // override this
- return [];
- },
-
- /** Render the title bar (the main/exposed SUMMARY dom element) */
- _renderSubtitle : function(){
- return $( this.templates.subtitle( this.model.toJSON(), this ) );
- },
-
- // ......................................................................... events
- /** event map */
- events : {
- // expand the body when the title is clicked or when in focus and space or enter is pressed
- 'click .title-bar' : '_clickTitleBar',
- 'keydown .title-bar' : '_keyDownTitleBar',
-
- // dragging - don't work, originalEvent === null
- //'dragstart .dataset-title-bar' : 'dragStartHandler',
- //'dragend .dataset-title-bar' : 'dragEndHandler'
-
- 'click .selector' : 'toggleSelect'
- },
-
- /** expand when the title bar is clicked */
- _clickTitleBar : function( event ){
- event.stopPropagation();
- this.toggleExpanded();
- },
-
- /** expand when the title bar is in focus and enter or space is pressed */
- _keyDownTitleBar : function( event ){
- // bail (with propagation) if keydown and not space or enter
- var KEYCODE_SPACE = 32, KEYCODE_RETURN = 13;
- if( event && ( event.type === 'keydown' )
- &&( event.keyCode === KEYCODE_SPACE || event.keyCode === KEYCODE_RETURN ) ){
- this.toggleExpanded();
- event.stopPropagation();
- return false;
- }
- return true;
- },
-
- // ......................................................................... misc
- /** String representation */
- toString : function(){
- var modelString = ( this.model )?( this.model + '' ):( '(no model)' );
- return 'ListItemView(' + modelString + ')';
- }
-}));
-
-// ............................................................................ TEMPLATES
-/** underscore templates */
-ListItemView.prototype.templates = (function(){
-//TODO: move to require text! plugin
-
- var elTemplato = wrapTemplate([
- '<div class="list-element">',
- // errors, messages, etc.
- '<div class="warnings"></div>',
-
- // multi-select checkbox
- '<div class="selector">',
- '<span class="fa fa-2x fa-square-o"></span>',
- '</div>',
- // space for title bar buttons - gen. floated to the right
- '<div class="primary-actions"></div>',
- '<div class="title-bar"></div>',
-
- // expandable area for more details
- '<div class="details"></div>',
- '</div>'
- ]);
-
- var warnings = {};
-
- var titleBarTemplate = wrapTemplate([
- // adding a tabindex here allows focusing the title bar and the use of keydown to expand the dataset display
- '<div class="title-bar clear" tabindex="0">',
-//TODO: prob. belongs in dataset-list-item
- '<span class="state-icon"></span>',
- '<div class="title">',
- '<span class="name"><%- element.name %></span>',
- '</div>',
- '<div class="subtitle"></div>',
- '</div>'
- ], 'element' );
-
- var subtitleTemplate = wrapTemplate([
- // override this
- '<div class="subtitle"></div>'
- ]);
-
- var detailsTemplate = wrapTemplate([
- // override this
- '<div class="details"></div>'
- ]);
-
- return {
- el : elTemplato,
- warnings : warnings,
- titleBar : titleBarTemplate,
- subtitle : subtitleTemplate,
- details : detailsTemplate
+function wrapTemplate( template, jsonNamespace ){
+ jsonNamespace = jsonNamespace || 'model';
+ var templateFn = _.template( template.join( '' ) );
+ return function( json, view ){
+ var templateVars = { view : view || {}, _l : _l };
+ templateVars[ jsonNamespace ] = json || {};
+ return templateFn( templateVars );
};
-}());
+}
//==============================================================================
return {
LoggableMixin : LoggableMixin,
SessionStorageModel : SessionStorageModel,
+ mixin : mixin,
SearchableModelMixin : SearchableModelMixin,
HiddenUntilActivatedViewMixin : HiddenUntilActivatedViewMixin,
- mixin : mixin,
- wrapTemplate : wrapTemplate,
- ExpandableView : ExpandableView,
DraggableViewMixin : DraggableViewMixin,
SelectableViewMixin : SelectableViewMixin,
- ListItemView : ListItemView
+ wrapTemplate : wrapTemplate
};
});
diff -r 6f06ff96d5cacd8cd73b9a7e50d43aff5322dc17 -r 74b2495de918c95730f1f2fd2ac1bf502018a99f static/scripts/mvc/collection/collection-li.js
--- a/static/scripts/mvc/collection/collection-li.js
+++ b/static/scripts/mvc/collection/collection-li.js
@@ -1,11 +1,12 @@
define([
+ "mvc/list/list-item",
"mvc/dataset/dataset-li",
"mvc/base-mvc",
"utils/localization"
-], function( DATASET_LI, BASE_MVC, _l ){
+], function( LIST_ITEM, DATASET_LI, BASE_MVC, _l ){
/* global Backbone, LoggableMixin */
//==============================================================================
-var ListItemView = BASE_MVC.ListItemView;
+var ListItemView = LIST_ITEM.ListItemView;
/** @class Read only view for DatasetCollection.
*/
var DCListItemView = ListItemView.extend(
@@ -97,8 +98,7 @@
//TODO: this might be expendable - compacted with HDAListItemView
/** logger used to record this.log messages, commonly set to console */
- // comment this out to suppress log output
- logger : console,
+ //logger : console,
/** add the DCE class to the list item */
className : ListItemView.prototype.className + " dataset-collection-element",
diff -r 6f06ff96d5cacd8cd73b9a7e50d43aff5322dc17 -r 74b2495de918c95730f1f2fd2ac1bf502018a99f static/scripts/mvc/collection/collection-model.js
--- a/static/scripts/mvc/collection/collection-model.js
+++ b/static/scripts/mvc/collection/collection-model.js
@@ -270,6 +270,11 @@
return this.save( { deleted: false }, options );
},
+ /** Is this collection deleted or purged? */
+ isDeletedOrPurged : function(){
+ return ( this.get( 'deleted' ) || this.get( 'purged' ) );
+ },
+
// ........................................................................ searchable
/** searchable attributes for collections */
searchAttributes : [
diff -r 6f06ff96d5cacd8cd73b9a7e50d43aff5322dc17 -r 74b2495de918c95730f1f2fd2ac1bf502018a99f static/scripts/mvc/collection/collection-panel.js
--- a/static/scripts/mvc/collection/collection-panel.js
+++ b/static/scripts/mvc/collection/collection-panel.js
@@ -1,9 +1,10 @@
define([
+ "mvc/list/list-panel",
"mvc/collection/collection-model",
"mvc/collection/collection-li",
"mvc/base-mvc",
"utils/localization"
-], function( DC_MODEL, DC_LI, BASE_MVC, _l ){
+], function( LIST_PANEL, DC_MODEL, DC_LI, BASE_MVC, _l ){
/* =============================================================================
TODO:
@@ -11,36 +12,29 @@
// =============================================================================
/** @class non-editable, read-only View/Controller for a dataset collection.
*/
-var CollectionPanel = Backbone.View.extend( BASE_MVC.LoggableMixin ).extend(
+var _super = LIST_PANEL.ModelListPanel;
+var CollectionPanel = _super.extend(
/** @lends CollectionPanel.prototype */{
//MODEL is either a DatasetCollection (or subclass) or a DatasetCollectionElement (list of pairs)
/** logger used to record this.log messages, commonly set to console */
//logger : console,
- tagName : 'div',
- className : 'dataset-collection-panel',
-
- /** (in ms) that jquery effects will use */
- fxSpeed : 'fast',
+ className : _super.prototype.className + ' dataset-collection-panel',
/** sub view class used for datasets */
DatasetDCEViewClass : DC_LI.DatasetDCEListItemView,
/** sub view class used for nested collections */
NestedDCDCEViewClass : DC_LI.NestedDCDCEListItemView,
+ /** key of attribute in model to assign to this.collection */
+ modelCollectionKey : 'elements',
// ......................................................................... SET UP
/** Set up the view, set up storage, bind listeners to HistoryContents events
* @param {Object} attributes optional settings for the panel
*/
initialize : function( attributes ){
- attributes = attributes || {};
- // set the logger if requested
- if( attributes.logger ){
- this.logger = attributes.logger;
- }
- this.log( this + '.initialize:', attributes );
-
+ _super.prototype.initialize.call( this, attributes );
this.linkTarget = attributes.linkTarget || '_blank';
this.hasUser = attributes.hasUser;
@@ -50,185 +44,49 @@
//window.collectionPanel = this;
},
- /** create any event listeners for the panel
- * @fires: rendered:initial on the first render
- * @fires: empty-history when switching to a history with no HDAs or creating a new history
- */
- _setUpListeners : function(){
- // debugging
- //if( this.logger ){
- this.on( 'all', function( event ){
- this.log( this + '', arguments );
- }, this );
- //}
- return this;
+ // ------------------------------------------------------------------------ sub-views
+ /** In this override, use model.getVisibleContents */
+ _filterCollection : function(){
+//TODO: should *not* be model.getVisibleContents
+ return this.model.getVisibleContents();
},
- // ------------------------------------------------------------------------ history/hda event listening
- /** listening for history and HDA events */
- _setUpModelEventHandlers : function(){
- return this;
- },
-
- // ------------------------------------------------------------------------ panel rendering
- /** Render panel
- * @fires: rendered when the panel is attached and fully visible
- * @see Backbone.View#render
- */
- render : function( speed, callback ){
- this.log( 'render:', speed, callback );
- // send a speed of 0 to have no fade in/out performed
- speed = ( speed === undefined )?( this.fxSpeed ):( speed );
- //this.debug( this + '.render, fxSpeed:', speed );
- var panel = this,
- $newRender;
-
- // handle the possibility of no model (can occur if fetching the model returns an error)
- if( !this.model ){
- return this;
- }
- $newRender = this.renderModel();
-
- // fade out existing, swap with the new, fade in, set up behaviours
- $( panel ).queue( 'fx', [
- function( next ){
- if( speed && panel.$el.is( ':visible' ) ){
- panel.$el.fadeOut( speed, next );
- } else {
- next();
- }
- },
- function( next ){
- // swap over from temp div newRender
- panel.$el.empty();
- if( $newRender ){
- panel.$el.append( $newRender.children() );
- }
- next();
- },
- function( next ){
- if( speed && !panel.$el.is( ':visible' ) ){
- panel.$el.fadeIn( speed, next );
- } else {
- next();
- }
- },
- function( next ){
- //TODO: ideally, these would be set up before the fade in (can't because of async save text)
- if( callback ){ callback.call( this ); }
- panel.trigger( 'rendered', this );
- next();
- }
- ]);
- return this;
- },
-
- /** render with collection data
- * @returns {jQuery} dom fragment as temporary container to be swapped out later
- */
- renderModel : function( ){
- // tmp div for final swap in render
-//TODO: ugh - reuse issue - refactor out
- var type = this.model.get( 'collection_type' ) || this.model.object.get( 'collection_type' ),
- json = _.extend( this.model.toJSON(), {
- parentName : this.parentName,
- type : type
- }),
- $newRender = $( '<div/>' ).append( this.templates.panel( json ) );
- this._setUpBehaviours( $newRender );
- this.renderContents( $newRender );
- return $newRender;
- },
-
- /** Set up js/widget behaviours */
- _setUpBehaviours : function( $where ){
- //TODO: these should be either sub-MVs, or handled by events
- $where = $where || this.$el;
- $where.find( '[title]' ).tooltip({ placement: 'bottom' });
- return this;
- },
-
- // ------------------------------------------------------------------------ sub-$element shortcuts
- /** the scroll container for this panel - can be $el, $el.parent(), or grandparent depending on context */
- $container : function(){
- return ( this.findContainerFn )?( this.findContainerFn.call( this ) ):( this.$el.parent() );
- },
- /** where list content views are attached */
- $datasetsList : function( $where ){
- return ( $where || this.$el ).find( '.datasets-list' );
- },
-
- // ------------------------------------------------------------------------ sub-views
- /** Set up/render a view for each DCE to be shown, init with model and listeners.
- * DCE views are cached to the map this.contentViews (using the model.id as key).
- * @param {jQuery} $whereTo what dom element to prepend the DCE views to
- * @returns the number of visible DCE views
- */
- renderContents : function( $whereTo ){
- //this.debug( 'renderContents, elements:', this.model.elements );
- $whereTo = $whereTo || this.$el;
-
- this.warn( this + '.renderContents:, model:', this.model );
- var panel = this,
- contentViews = {},
- //NOTE: no filtering here
- visibleContents = this.model.getVisibleContents();
- //this.debug( 'renderContents, visibleContents:', visibleContents, $whereTo );
-
- this.$datasetsList( $whereTo ).empty();
- if( visibleContents && visibleContents.length ){
- visibleContents.each( function( content ){
- var contentId = content.id,
- contentView = panel._createContentView( content );
- contentViews[ contentId ] = contentView;
- panel._attachContentView( contentView.render(), $whereTo );
- });
- }
- this.contentViews = contentViews;
- return this.contentViews;
- },
-
- /** */
- _createContentView : function( content ){
- //this.debug( 'content json:', JSON.stringify( content, null, ' ' ) );
- var contentView = null,
- ContentClass = this._getContentClass( content );
- //this.debug( 'content:', content );
- //this.debug( 'ContentClass:', ContentClass );
- contentView = new ContentClass({
- model : content,
- linkTarget : this.linkTarget,
- //draggable : true,
- hasUser : this.hasUser,
- logger : this.logger
- });
- //this.debug( 'contentView:', contentView );
- this._setUpContentListeners( contentView );
- return contentView;
- },
-
- /** */
- _getContentClass : function( content ){
- //this.debug( this + '._getContentClass:', content );
+ /** override to return proper view class based on element_type */
+ _getItemViewClass : function( model ){
+ //this.debug( this + '._getItemViewClass:', model );
//TODO: subclasses use DCEViewClass - but are currently unused - decide
- switch( content.get( 'element_type' ) ){
+ switch( model.get( 'element_type' ) ){
case 'hda':
return this.DatasetDCEViewClass;
case 'dataset_collection':
return this.NestedDCDCEViewClass;
}
- throw new TypeError( 'Unknown element type:', content.get( 'element_type' ) );
+ throw new TypeError( 'Unknown element type:', model.get( 'element_type' ) );
},
- /** Set up listeners for content view events. In this override, handle collection expansion. */
- _setUpContentListeners : function( contentView ){
+ /** override to add link target and anon */
+ _getItemViewOptions : function( model ){
+ var options = _super.prototype._getItemViewOptions.call( this, model );
+ return _.extend( options, {
+ linkTarget : this.linkTarget,
+ hasUser : this.hasUser
+ });
+ },
+
+ /** when a sub-view is clicked in the collection panel that is itself a collection,
+ * hide this panel's elements and show the sub-collection in its own panel.
+ */
+ _setUpItemViewListeners : function( view ){
var panel = this;
- if( contentView.model.get( 'element_type' ) === 'dataset_collection' ){
- contentView.on( 'expanded', function( collectionView ){
+ _super.prototype._setUpItemViewListeners.call( panel, view );
+ //TODO:?? doesn't seem to belong here
+ if( view.model.get( 'element_type' ) === 'dataset_collection' ){
+ view.on( 'expanded', function( collectionView ){
panel.info( 'expanded', collectionView );
panel._addCollectionPanel( collectionView );
});
}
+ return panel;
},
/** When a sub-collection is clicked, hide the current panel and render the sub-collection in its own panel */
@@ -246,7 +104,7 @@
});
currPanel.panelStack.push( panel );
- currPanel.$( '.controls' ).add( '.datasets-list' ).hide();
+ currPanel.$( '.controls' ).add( '.list-items' ).hide();
currPanel.$el.append( panel.$el );
panel.on( 'close', function(){
currPanel.render();
@@ -266,14 +124,6 @@
}
},
- /** attach an contentView to the panel */
- _attachContentView : function( contentView, $whereTo ){
- $whereTo = $whereTo || this.$el;
- var $datasetsList = this.$datasetsList( $whereTo );
- $datasetsList.append( contentView.$el );
- return this;
- },
-
// ------------------------------------------------------------------------ panel events
/** event map */
events : {
@@ -293,16 +143,16 @@
}
});
-//----------------------------------------------------------------------------- TEMPLATES
-/** underscore templates */
-CollectionPanel.templates = CollectionPanel.prototype.templates = (function(){
-// use closure to run underscore template fn only once at module load
- var _panelTemplate = _.template([
+
+//------------------------------------------------------------------------------ TEMPLATES
+CollectionPanel.prototype.templates = (function(){
+
+ var controlsTemplate = BASE_MVC.wrapTemplate([
'<div class="controls">',
'<div class="navigation">',
'<a class="back" href="javascript:void(0)">',
'<span class="fa fa-icon fa-angle-left"></span>',
- _l( 'Back to ' ), '<%- collection.parentName %>',
+ _l( 'Back to ' ), '<%- view.parentName %>',
'</a>',
'</div>',
@@ -310,29 +160,25 @@
'<div class="name"><%- collection.name || collection.element_identifier %></div>',
'<div class="subtitle">',
//TODO: remove logic from template
- '<% if( collection.type === "list" ){ %>',
+ '<% if( collection.collection_type === "list" ){ %>',
_l( 'a list of datasets' ),
- '<% } else if( collection.type === "paired" ){ %>',
+ '<% } else if( collection.collection_type === "paired" ){ %>',
_l( 'a pair of datasets' ),
- '<% } else if( collection.type === "list:paired" ){ %>',
+ '<% } else if( collection.collection_type === "list:paired" ){ %>',
_l( 'a list of paired datasets' ),
'<% } %>',
'</div>',
'</div>',
- '</div>',
- // where the datasets/hdas are added
- '<div class="datasets-list"></div>'
- ].join( '' ));
+ '</div>'
+ ], 'collection' );
- // we override here in order to pass the localizer (_L) into the template scope - since we use it as a fn within
- return {
- panel : function( json ){
- return _panelTemplate({ _l: _l, collection: json });
- }
- };
+ return _.extend( _.clone( _super.prototype.templates ), {
+ controls : controlsTemplate
+ });
}());
+
// =============================================================================
/** @class non-editable, read-only View/Controller for a dataset collection. */
var ListCollectionPanel = CollectionPanel.extend(
diff -r 6f06ff96d5cacd8cd73b9a7e50d43aff5322dc17 -r 74b2495de918c95730f1f2fd2ac1bf502018a99f static/scripts/mvc/dataset/dataset-li.js
--- a/static/scripts/mvc/dataset/dataset-li.js
+++ b/static/scripts/mvc/dataset/dataset-li.js
@@ -1,8 +1,9 @@
define([
+ "mvc/list/list-item",
"mvc/dataset/states",
"mvc/base-mvc",
"utils/localization"
-], function( STATES, BASE_MVC, _l ){
+], function( LIST_ITEM, STATES, BASE_MVC, _l ){
/* global Backbone */
/*==============================================================================
TODO:
@@ -11,7 +12,7 @@
simplify button rendering
==============================================================================*/
-var _super = BASE_MVC.ListItemView;
+var _super = LIST_ITEM.ListItemView;
/** @class Read only list view for either LDDAs, HDAs, or HDADCEs.
* Roughly, any DatasetInstance (and not a raw Dataset).
*/
diff -r 6f06ff96d5cacd8cd73b9a7e50d43aff5322dc17 -r 74b2495de918c95730f1f2fd2ac1bf502018a99f static/scripts/mvc/dataset/dataset-list.js
--- a/static/scripts/mvc/dataset/dataset-list.js
+++ b/static/scripts/mvc/dataset/dataset-list.js
@@ -1,5 +1,5 @@
define([
- "mvc/dataset/list-panel",
+ "mvc/list/list-panel",
"mvc/dataset/dataset-li",
"mvc/base-mvc",
"utils/localization"
diff -r 6f06ff96d5cacd8cd73b9a7e50d43aff5322dc17 -r 74b2495de918c95730f1f2fd2ac1bf502018a99f static/scripts/mvc/dataset/dataset-model.js
--- a/static/scripts/mvc/dataset/dataset-model.js
+++ b/static/scripts/mvc/dataset/dataset-model.js
@@ -94,6 +94,9 @@
this.trigger( 'state:ready', currModel, newState, this.previous( 'state' ) );
}
});
+ this.on( 'change:urls', function(){
+ console.warn( 'change:urls', arguments );
+ });
// the download url (currenlty) relies on having a correct file extension
this.on( 'change:id change:file_ext', function( currModel ){
this._generateUrls();
@@ -104,6 +107,8 @@
/** override to add urls */
toJSON : function(){
var json = Backbone.Model.prototype.toJSON.call( this );
+ //console.warn( 'returning json?' );
+ //return json;
return _.extend( json, {
urls : this.urls
});
diff -r 6f06ff96d5cacd8cd73b9a7e50d43aff5322dc17 -r 74b2495de918c95730f1f2fd2ac1bf502018a99f static/scripts/mvc/dataset/list-panel.js
--- a/static/scripts/mvc/dataset/list-panel.js
+++ /dev/null
@@ -1,687 +0,0 @@
-define([
- "mvc/base-mvc",
- "utils/localization"
-], function( BASE_MVC, _l ){
-/* =============================================================================
-TODO:
-
-============================================================================= */
-/** @class List that contains ListItemViews.
- */
-var ListPanel = Backbone.View.extend( BASE_MVC.LoggableMixin ).extend(
-/** @lends ReadOnlyHistoryPanel.prototype */{
-
- /** logger used to record this.log messages, commonly set to console */
- //logger : console,
-
- /** class to use for constructing the sub-views */
- viewClass : BASE_MVC.ListItemView,
-
- tagName : 'div',
- className : 'list-panel',
-
- /** (in ms) that jquery effects will use */
- fxSpeed : 'fast',
-
- /** string to display when the model has no hdas */
- emptyMsg : _l( 'This list is empty' ),
- /** string to no hdas match the search terms */
- noneFoundMsg : _l( 'No matching items found' ),
-
- // ......................................................................... SET UP
- /** Set up the view, set up storage, bind listeners to HistoryContents events
- * @param {Object} attributes optional settings for the list
- */
- initialize : function( attributes, options ){
- attributes = attributes || {};
- // set the logger if requested
- if( attributes.logger ){
- this.logger = attributes.logger;
- }
- this.log( this + '.initialize:', attributes );
-
- // ---- instance vars
- /** how quickly should jquery fx run? */
- this.fxSpeed = _.has( attributes, 'fxSpeed' )?( attributes.fxSpeed ):( this.fxSpeed );
-
- /** filters for displaying subviews */
- this.filters = [];
- /** current search terms */
- this.searchFor = attributes.searchFor || '';
-
- /** loading indicator */
- this.indicator = new LoadingIndicator( this.$el );
-
- /** currently showing selectors on items? */
- this.selecting = ( attributes.selecting !== undefined )? attributes.selecting : true;
- //this.selecting = false;
-
- /** cached selected item.model.ids to persist btwn renders */
- this.selected = attributes.selected || [];
- /** the last selected item.model.id */
- this.lastSelected = null;
-
- /** list item view class (when passed models) */
- this.viewClass = attributes.viewClass || this.viewClass;
-
- /** list item views */
- this.views = [];
- /** list item models */
- this.collection = attributes.collection || ( new Backbone.Collection([]) );
-
- /** filter fns run over collection items to see if they should show in the list */
- this.filters = attributes.filters || [];
-
-//TODO: remove
- this.title = attributes.title || '';
- this.subtitle = attributes.subtitle || '';
-
- this._setUpListeners();
- },
-
- /** create any event listeners for the list
- */
- _setUpListeners : function(){
- this.on( 'error', function( model, xhr, options, msg, details ){
- //this.errorHandler( model, xhr, options, msg, details );
- console.error( model, xhr, options, msg, details );
- }, this );
-
- // show hide the loading indicator
- this.on( 'loading', function(){
- this._showLoadingIndicator( 'loading...', 40 );
- }, this );
- this.on( 'loading-done', function(){
- this._hideLoadingIndicator( 40 );
- }, this );
-
- // throw the first render up as a diff namespace using once (for outside consumption)
- this.once( 'rendered', function(){
- this.trigger( 'rendered:initial', this );
- }, this );
-
- // debugging
- if( this.logger ){
- this.on( 'all', function( event ){
- this.log( this + '', arguments );
- }, this );
- }
-
- this._setUpCollectionListeners();
- this._setUpViewListeners();
- return this;
- },
-
- /** free any sub-views the list has */
- freeViews : function(){
-//TODO: stopListening? remove?
- this.views = [];
- return this;
- },
-
- // ------------------------------------------------------------------------ item listeners
- /** listening for history and HDA events */
- _setUpCollectionListeners : function(){
-
- this.collection.on( 'reset', function(){
- this.renderItems();
- }, this );
-
- this.collection.on( 'add', this.addItemView, this );
- this.collection.on( 'remove', this.removeItemView, this );
-
- // debugging
- if( this.logger ){
- this.collection.on( 'all', function( event ){
- this.info( this + '(collection)', arguments );
- }, this );
- }
- return this;
- },
-
- /** listening for history and HDA events */
- _setUpViewListeners : function(){
-
- // shift to select a range
- this.on( 'view:selected', function( view, ev ){
- if( ev && ev.shiftKey && this.lastSelected ){
- var lastSelectedView = _.find( this.views, function( view ){
- return view.model.id === this.lastSelected;
- });
- if( lastSelectedView ){
- this.selectRange( view, lastSelectedView );
- }
- }
- this.selected.push( view.model.id );
- this.lastSelected = view.model.id;
- }, this );
- },
-
- // ------------------------------------------------------------------------ rendering
- /** Render this content, set up ui.
- * @param {Number or String} speed the speed of the render
- */
- render : function( speed ){
- var $newRender = this._buildNewRender();
- this._setUpBehaviors( $newRender );
- this._queueNewRender( $newRender, speed );
- return this;
- },
-
- /** Build a temp div containing the new children for the view's $el.
- */
- _buildNewRender : function(){
- // create a new render using a skeleton template, render title buttons, render body, and set up events, etc.
- var json = this.model? this.model.toJSON() : {},
- $newRender = $( this.templates.el( json, this ) );
- this._renderTitle( $newRender );
- this._renderSubtitle( $newRender );
- this._renderSearch( $newRender );
- this.renderItems( $newRender );
- return $newRender;
- },
-
- /**
- */
- _renderTitle : function( $where ){
- //$where = $where || this.$el;
- //$where.find( '.title' ).replaceWith( ... )
- },
-
- /**
- */
- _renderSubtitle : function( $where ){
- //$where = $where || this.$el;
- //$where.find( '.title' ).replaceWith( ... )
- },
-
- /** Fade out the old el, swap in the new contents, then fade in.
- * @param {Number or String} speed jq speed to use for rendering effects
- * @fires rendered when rendered
- */
- _queueNewRender : function( $newRender, speed ) {
- speed = ( speed === undefined )?( this.fxSpeed ):( speed );
- var view = this;
-
- $( view ).queue( 'fx', [
- function( next ){ this.$el.fadeOut( speed, next ); },
- function( next ){
- view._swapNewRender( $newRender );
- next();
- },
- function( next ){ this.$el.fadeIn( speed, next ); },
- function( next ){
- view.trigger( 'rendered', view );
- next();
- }
- ]);
- },
-
- /** empty out the current el, move the $newRender's children in */
- _swapNewRender : function( $newRender ){
- this.$el.empty().attr( 'class', this.className ).append( $newRender.children() );
- if( this.selecting ){ this.showSelectors( 0 ); }
- return this;
- },
-
- /** */
- _setUpBehaviors : function( $where ){
- $where = $where || this.$el;
- $where.find( '.controls [title]' ).tooltip({ placement: 'bottom' });
- return this;
- },
-
- // ------------------------------------------------------------------------ sub-$element shortcuts
- /** the scroll container for this panel - can be $el, $el.parent(), or grandparent depending on context */
- $scrollContainer : function(){
- // override
- return this.$el.parent().parent();
- },
- /** */
- $list : function( $where ){
- return ( $where || this.$el ).find( '.list-items' );
- },
- /** container where list messages are attached */
- $messages : function( $where ){
- return ( $where || this.$el ).find( '.message-container' );
- },
- /** the message displayed when no views can be shown (no views, none matching search) */
- $emptyMessage : function( $where ){
- return ( $where || this.$el ).find( '.empty-message' );
- },
-
- // ------------------------------------------------------------------------ hda sub-views
- /**
- * @param {jQuery} $whereTo what dom element to prepend the HDA views to
- * @returns the visible item views
- */
- renderItems : function( $whereTo ){
- $whereTo = $whereTo || this.$el;
- var list = this,
- newViews = [];
-
- var $list = this.$list( $whereTo ),
- item$els = this._filterCollection().map( function( itemModel ){
-//TODO: creates views each time - not neccessarily good
- var view = list._createItemView( itemModel );
- newViews.push( view );
- return view.render( 0 ).$el;
- });
- this.debug( item$els );
- this.debug( newViews );
-
- $list.empty();
- if( item$els.length ){
- $list.append( item$els );
- this.$emptyMessage( $whereTo ).hide();
-
- } else {
- this._renderEmptyMessage( $whereTo ).show();
- }
-
- this.views = newViews;
- return newViews;
- },
-
- /**
- */
- _filterCollection : function(){
- // override this
- var list = this;
- return list.collection.filter( _.bind( list._filterItem, list ) );
- },
-
- /**
- */
- _filterItem : function( model ){
- // override this
- var list = this;
- return ( _.every( list.filters.map( function( fn ){ return fn.call( model ); }) ) )
- && ( !list.searchFor || model.matchesAll( list.searchFor ) );
- },
-
- /**
- */
- _createItemView : function( model ){
- var ViewClass = this._getItemViewClass( model ),
- options = _.extend( this._getItemViewOptions( model ), {
- model : model
- }),
- view = new ViewClass( options );
- this._setUpItemViewListeners( view );
- return view;
- },
-
- _getItemViewClass : function( model ){
- // override this
- return this.viewClass;
- },
-
- _getItemViewOptions : function( model ){
- // override this
- return {
- //logger : this.logger,
- fxSpeed : this.fxSpeed,
- expanded : false,
- selectable : this.selecting,
- selected : _.contains( this.selected, model.id ),
- draggable : this.dragging
- };
- },
-
- /**
- */
- _setUpItemViewListeners : function( view ){
- var list = this;
- view.on( 'all', function(){
- var args = Array.prototype.slice.call( arguments, 0 );
- args[0] = 'view:' + args[0];
- list.trigger.apply( list, args );
- });
-
- // debugging
- //if( this.logger ){
- // view.on( 'all', function( event ){
- // this.log( this + '(view)', arguments );
- // }, this );
- //}
- return this;
- },
-
- /** render the empty/none-found message */
- _renderEmptyMessage : function( $whereTo ){
- //this.debug( '_renderEmptyMessage', $whereTo, this.searchFor );
- var text = this.searchFor? this.noneFoundMsg : this.emptyMsg;
- return this.$emptyMessage( $whereTo ).text( text );
- },
-
- /** collapse all item views */
- expandAll : function(){
- _.each( this.views, function( view ){
- view.expand();
- });
- },
-
- /** collapse all item views */
- collapseAll : function(){
- _.each( this.views, function( view ){
- view.collapse();
- });
- },
-
- // ------------------------------------------------------------------------ collection/views syncing
- /**
- */
- addItemView : function( model, collection, options ){
- this.log( this + '.addItemView:', model );
- var list = this;
- if( !this._filterItem( model ) ){ return undefined; }
-
-//TODO: sorted? position?
- var view = list._createItemView( model );
- this.views.push( view );
-
- $( view ).queue( 'fx', [
- function( next ){ list.$emptyMessage().fadeOut( list.fxSpeed, next ); },
- function( next ){
-//TODO: auto render?
- list.$list().append( view.render().$el );
- next();
- }
- ]);
- return view;
- },
-
- /**
- */
- removeItemView : function( model, collection, options ){
- this.log( this + '.removeItemView:', model );
- var list = this,
- view = list.viewFromModel( model );
- if( !view ){ return undefined; }
-
- this.views = _.without( this.views, view );
- view.remove();
- if( !this.views.length ){
- list._renderEmptyMessage().fadeIn( list.fxSpeed );
- }
- return view;
- },
-
- /** get views based on model
- */
- viewFromModel : function( model ){
- for( var i=0; i<this.views.length; i++ ){
- var view = this.views[i];
- if( view.model === model ){
- return view;
- }
- }
- return undefined;
- },
-
- /** get views based on model properties
- */
- viewsWhereModel : function( properties ){
- return this.views.filter( function( view ){
- //return view.model.matches( properties );
-//TODO: replace with _.matches (underscore 1.6.0)
- var json = view.model.toJSON();
- //console.debug( '\t', json, properties );
- for( var key in properties ){
- if( properties.hasOwnPropery( key ) ){
- //console.debug( '\t\t', json[ key ], view.model.properties[ key ] );
- if( json[ key ] !== view.model.properties[ key ] ){
- return false;
- }
- }
- }
- return true;
- });
- },
-
- /**
- */
- viewRange : function( viewA, viewB ){
- if( viewA === viewB ){ return ( viewA )?( [ viewA ] ):( [] ); }
-
- var indexA = this.views.indexOf( viewA ),
- indexB = this.views.indexOf( viewB );
-
- // handle not found
- if( indexA === -1 || indexB === -1 ){
- if( indexA === indexB ){ return []; }
- return ( indexA === -1 )?( [ viewB ] ):( [ viewA ] );
- }
- // reverse if indeces are
- //note: end inclusive
- return ( indexA < indexB )?
- this.views.slice( indexA, indexB + 1 ) :
- this.views.slice( indexB, indexA + 1 );
- },
-
- // ------------------------------------------------------------------------ searching
- /** render a search input for filtering datasets shown
- * (see the search section in the HDA model for implementation of the actual searching)
- * return will start the search
- * esc will clear the search
- * clicking the clear button will clear the search
- * uses searchInput in ui.js
- */
- _renderSearch : function( $where ){
- $where.find( '.controls .search-input' ).searchInput({
- placeholder : 'search',
- initialVal : this.searchFor,
- onfirstsearch : _.bind( this._firstSearch, this ),
- onsearch : _.bind( this.searchItems, this ),
- onclear : _.bind( this.clearSearch, this )
- });
- return $where;
- },
-
- _firstSearch : function( searchFor ){
- this.log( 'onFirstSearch', searchFor );
- return this.searchItems( searchFor );
- },
-
- /** filter view list to those that contain the searchFor terms */
- searchItems : function( searchFor ){
- this.searchFor = searchFor;
- this.trigger( 'search:searching', searchFor, this );
- this.renderItems();
- return this;
- },
-
- /** clear the search filters and show all views that are normally shown */
- clearSearch : function( searchFor ){
- //this.log( 'onSearchClear', this );
- this.searchFor = '';
- this.trigger( 'search:clear', this );
- this.renderItems();
- return this;
- },
-
- // ------------------------------------------------------------------------ selection
- /** show selectors on all visible hdas and associated controls */
- showSelectors : function( speed ){
- speed = ( speed !== undefined )?( speed ):( this.fxSpeed );
- this.selecting = true;
- this.$( '.list-actions' ).slideDown( speed );
- _.each( this.views, function( view ){
- view.showSelector( speed );
- });
- this.selected = [];
- this.lastSelected = null;
- },
-
- /** hide selectors on all visible hdas and associated controls */
- hideSelectors : function( speed ){
- speed = ( speed !== undefined )?( speed ):( this.fxSpeed );
- this.selecting = false;
- this.$( '.list-actions' ).slideUp( speed );
- _.each( this.views, function( view ){
- view.hideSelector( speed );
- });
- this.selected = [];
- this.lastSelected = null;
- },
-
- /** show or hide selectors on all visible hdas and associated controls */
- toggleSelectors : function(){
- if( !this.selecting ){
- this.showSelectors();
- } else {
- this.hideSelectors();
- }
- },
-
- /** select all visible hdas */
- selectAll : function( event ){
- _.each( this.views, function( view ){
- view.select( event );
- });
- },
-
- /** deselect all visible hdas */
- deselectAll : function( event ){
- this.lastSelected = null;
- _.each( this.views, function( view ){
- view.deselect( event );
- });
- },
-
- /** select a range of datasets between A and B */
- selectRange : function( viewA, viewB ){
- var range = this.viewRange( viewA, viewB );
- _.each( range, function( view ){
- view.select();
- });
- return range;
- },
-
- /** return an array of all currently selected hdas */
- getSelectedViews : function(){
- return _.filter( this.views, function( v ){
- return v.selected;
- });
- },
-
- /** return an collection of the models of all currenly selected hdas */
- getSelectedModels : function(){
- return new this.collection.constructor( _.map( this.getSelectedViews(), function( view ){
- return view.model;
- }));
- },
-
- // ------------------------------------------------------------------------ loading indicator
-//TODO: questionable
- /** hide the $el and display a loading indicator (in the $el's parent) when loading new data */
- _showLoadingIndicator : function( msg, speed, callback ){
- speed = ( speed !== undefined )?( speed ):( this.fxSpeed );
- if( !this.indicator ){
- this.indicator = new LoadingIndicator( this.$el, this.$el.parent() );
- }
- if( !this.$el.is( ':visible' ) ){
- this.indicator.show( 0, callback );
- } else {
- this.$el.fadeOut( speed );
- this.indicator.show( msg, speed, callback );
- }
- },
-
- /** hide the loading indicator */
- _hideLoadingIndicator : function( speed, callback ){
- speed = ( speed !== undefined )?( speed ):( this.fxSpeed );
- if( this.indicator ){
- this.indicator.hide( speed, callback );
- }
- },
-
- // ------------------------------------------------------------------------ scrolling
- /** get the current scroll position of the panel in its parent */
- scrollPosition : function(){
- return this.$scrollContainer().scrollTop();
- },
-
- /** set the current scroll position of the panel in its parent */
- scrollTo : function( pos ){
- this.$scrollContainer().scrollTop( pos );
- return this;
- },
-
- /** Scrolls the panel to the top. */
- scrollToTop : function(){
- this.$scrollContainer().scrollTop( 0 );
- return this;
- },
-
- /** */
- scrollToItem : function( view ){
- if( !view ){ return; }
- var itemTop = view.$el.offset().top;
- this.$scrollContainer().scrollTop( itemTop );
- },
-
- // ------------------------------------------------------------------------ panel events
- /** event map */
- events : {
- 'click .select-all' : 'selectAll',
- 'click .deselect-all' : 'deselectAll'
- },
-
- // ------------------------------------------------------------------------ misc
- /** Return a string rep of the history */
- toString : function(){
- return 'ListPanel(' + this.collection + ')';
- }
-});
-
-// ............................................................................ TEMPLATES
-/** underscore templates */
-ListPanel.prototype.templates = (function(){
-//TODO: move to require text! plugin
-
- var elTemplate = BASE_MVC.wrapTemplate([
- // temp container
- '<div>',
- '<div class="controls">',
- '<div class="title">',
- '<div class="name"><%= model.name || view.title %></div>',
- '</div>',
- '<div class="subtitle"><%= view.subtitle %></div>',
- '<div class="actions"></div>',
- '<div class="messages"></div>',
-
- '<div class="search">',
- '<div class="search-input"></div>',
- '</div>',
-
- '<div class="list-actions">',
- '<div class="btn-group">',
- '<button class="select-all btn btn-default"',
- 'data-mode="select">', _l( 'All' ), '</button>',
- '<button class="deselect-all btn btn-default"',
- 'data-mode="select">', _l( 'None' ), '</button>',
- '</div>',
- //'<button class="action-popup-btn btn btn-default">',
- // _l( 'For all selected' ), '...',
- //'</button>',
- '</div>',
- '</div>',
- '<div class="list-items"></div>',
- '<div class="empty-message infomessagesmall"></div>',
- '</div>'
- ]);
-
- return {
- el : elTemplate
- };
-}());
-
-
-
-//==============================================================================
- return {
- ListPanel: ListPanel
- };
-});
diff -r 6f06ff96d5cacd8cd73b9a7e50d43aff5322dc17 -r 74b2495de918c95730f1f2fd2ac1bf502018a99f static/scripts/mvc/history/hda-li.js
--- a/static/scripts/mvc/history/hda-li.js
+++ b/static/scripts/mvc/history/hda-li.js
@@ -17,12 +17,12 @@
/** logger used to record this.log messages, commonly set to console */
//logger : console,
+ className : _super.prototype.className + " history-content",
+
initialize : function( attributes, options ){
_super.prototype.initialize.call( this, attributes, options );
},
- className : _super.prototype.className + " history-content",
-
// ......................................................................... misc
/** String representation */
toString : function(){
diff -r 6f06ff96d5cacd8cd73b9a7e50d43aff5322dc17 -r 74b2495de918c95730f1f2fd2ac1bf502018a99f static/scripts/mvc/history/history-contents.js
--- a/static/scripts/mvc/history/history-contents.js
+++ b/static/scripts/mvc/history/history-contents.js
@@ -53,6 +53,7 @@
*/
initialize : function( models, options ){
options = options || {};
+//TODO: could probably use the contents.history_id instead
this.historyId = options.historyId;
//this._setUpListeners();
@@ -226,7 +227,7 @@
if( !existing ){ return model; }
// merge the models _BEFORE_ calling the superclass version
- var merged = existing.toJSON();
+ var merged = _.clone( existing.attributes );
_.extend( merged, model );
return merged;
});
@@ -303,6 +304,13 @@
return xhr;
},
+ /** In this override, copy the historyId to the clone */
+ clone : function(){
+ var clone = Backbone.Collection.prototype.clone.call( this );
+ clone.historyId = this.historyId;
+ return clone;
+ },
+
/** debugging */
print : function(){
var contents = this;
diff -r 6f06ff96d5cacd8cd73b9a7e50d43aff5322dc17 -r 74b2495de918c95730f1f2fd2ac1bf502018a99f static/scripts/mvc/history/history-model.js
--- a/static/scripts/mvc/history/history-model.js
+++ b/static/scripts/mvc/history/history-model.js
@@ -232,7 +232,7 @@
/** Get data for a history then its hdas using a sequential ajax call, return a deferred to receive both */
History.getHistoryData = function getHistoryData( historyId, options ){
options = options || {};
- var hdaDetailIds = options.hdaDetailIds || [];
+ var detailIdsFn = options.detailIdsFn || [];
var hdcaDetailIds = options.hdcaDetailIds || [];
//console.debug( 'getHistoryData:', historyId, options );
@@ -250,20 +250,20 @@
// get the number of hdas accrd. to the history
return historyData && historyData.empty;
}
- function getHdas( historyData ){
+ function getContents( historyData ){
// get the hda data
// if no hdas accrd. to history: return empty immed.
if( isEmpty( historyData ) ){ return []; }
// if there are hdas accrd. to history: get those as well
- if( _.isFunction( hdaDetailIds ) ){
- hdaDetailIds = hdaDetailIds( historyData );
+ if( _.isFunction( detailIdsFn ) ){
+ detailIdsFn = detailIdsFn( historyData );
}
if( _.isFunction( hdcaDetailIds ) ){
hdcaDetailIds = hdcaDetailIds( historyData );
}
var data = {};
- if( hdaDetailIds.length ) {
- data.dataset_details = hdaDetailIds.join( ',' );
+ if( detailIdsFn.length ) {
+ data.dataset_details = detailIdsFn.join( ',' );
}
if( hdcaDetailIds.length ) {
// for symmetry, not actually used by backend of consumed
@@ -274,10 +274,10 @@
}
// getting these concurrently is 400% slower (sqlite, local, vanilla) - so:
- // chain the api calls - getting history first then hdas
+ // chain the api calls - getting history first then contents
var historyFn = options.historyFn || getHistory,
- hdaFn = options.hdaFn || getHdas;
+ contentsFn = options.contentsFn || getContents;
// chain ajax calls: get history first, then hdas
var historyXHR = historyFn( historyId );
@@ -291,15 +291,15 @@
df.reject( xhr, 'loading the history' );
});
- var hdaXHR = historyXHR.then( hdaFn );
- hdaXHR.then( function( hdaJSON ){
- df.notify({ status: 'dataset data retrieved', historyJSON: historyJSON, hdaJSON: hdaJSON });
+ var contentsXHR = historyXHR.then( contentsFn );
+ contentsXHR.then( function( contentsJSON ){
+ df.notify({ status: 'contents data retrieved', historyJSON: historyJSON, contentsJSON: contentsJSON });
// we've got both: resolve the outer scope deferred
- df.resolve( historyJSON, hdaJSON );
+ df.resolve( historyJSON, contentsJSON );
});
- hdaXHR.fail( function( xhr, status, message ){
+ contentsXHR.fail( function( xhr, status, message ){
// call reject on the outer deferred to allow its fail callback to run
- df.reject( xhr, 'loading the datasets', { history: historyJSON } );
+ df.reject( xhr, 'loading the contents', { history: historyJSON } );
});
return df;
diff -r 6f06ff96d5cacd8cd73b9a7e50d43aff5322dc17 -r 74b2495de918c95730f1f2fd2ac1bf502018a99f static/scripts/mvc/history/history-panel-annotated.js
--- a/static/scripts/mvc/history/history-panel-annotated.js
+++ b/static/scripts/mvc/history/history-panel-annotated.js
@@ -1,118 +1,97 @@
define([
"mvc/history/history-panel",
"mvc/history/hda-li",
+ "mvc/history/hdca-li",
+ "mvc/base-mvc",
"utils/localization"
-], function( HPANEL, HDA_LI, _l ){
+], function( HPANEL, HDA_LI, HDCA_LI, BASE_MVC, _l ){
/* =============================================================================
TODO:
============================================================================= */
-var _super = HPANEL.ReadOnlyHistoryPanel;
+var _super = HPANEL.HistoryPanel;
// used in history/display.mako and history/embed.mako
/** @class View/Controller for a tabular view of the history model.
- * @name AnnotatedHistoryPanel
*
* As ReadOnlyHistoryPanel, but with:
* history annotation always shown
* datasets displayed in a table:
* datasets in left cells, dataset annotations in the right
- *
- * @augments Backbone.View
- * @borrows LoggableMixin#logger as #logger
- * @borrows LoggableMixin#log as #log
- * @constructs
*/
var AnnotatedHistoryPanel = _super.extend(
/** @lends AnnotatedHistoryPanel.prototype */{
/** logger used to record this.log messages, commonly set to console */
- // comment this out to suppress log output
//logger : console,
- className : 'annotated-history-panel',
-
- //TODO:?? possibly into own annotated class
- /** class to use for constructing the HDA views */
- //HDAViewClass : HDA_LI.HDAListItemView,
+ className : _super.prototype.className + ' annotated-history-panel',
// ------------------------------------------------------------------------ panel rendering
- /** render with history data
- * In this override:
- * replace the datasets list with a table,
- * add the history annotation,
- * and move the search controls
- * @returns {jQuery} dom fragment as temporary container to be swapped out later
+ /** In this override, add the history annotation
*/
- renderModel : function( ){
- // why do we need this here? why isn't className being applied?
- this.$el.addClass( this.className );
- var $newRender = _super.prototype.renderModel.call( this ),
- // move datasets from div to table
- $datasetsList = this.$datasetsList( $newRender ),
- $datasetsTable = $( '<table/>' ).addClass( 'datasets-list datasets-table' );
- $datasetsTable.append( $datasetsList.children() );
- $datasetsList.replaceWith( $datasetsTable );
- //TODO: it's possible to do this with css only, right? display: table-cell, etc.?
-
- // add history annotation under subtitle
- $newRender.find( '.history-subtitle' ).after( this.renderHistoryAnnotation() );
-
- // hide search button, move search bar beneath controls (instead of above title), show, and set up
- $newRender.find( '.history-search-btn' ).hide();
- $newRender.find( '.history-controls' ).after( $newRender.find( '.history-search-controls' ).show() );
-
+ _buildNewRender : function(){
+ //TODO: shouldn't this display regardless (on all non-current panels)?
+ var $newRender = _super.prototype._buildNewRender.call( this );
+ this.renderHistoryAnnotation( $newRender );
return $newRender;
},
/** render the history's annotation as its own field */
- renderHistoryAnnotation : function(){
+ renderHistoryAnnotation : function( $newRender ){
var annotation = this.model.get( 'annotation' );
- if( !annotation ){ return null; }
- return $([
- '<div class="history-annotation">', annotation, '</div>'
- ].join( '' ));
+ if( !annotation ){ return; }
+ $newRender.find( '.controls .annotation-display' ).text( annotation );
},
- /** Set up/render a view for each HDA to be shown, init with model and listeners.
- * In this override, add table header cells to indicate the dataset, annotation columns
+ /** In this override, convert the list-items tag to a table
+ * and add table header cells to indicate the dataset, annotation columns
*/
- renderHdas : function( $whereTo ){
+ renderItems : function( $whereTo ){
$whereTo = $whereTo || this.$el;
- var hdaViews = _super.prototype.renderHdas.call( this, $whereTo );
- this.$datasetsList( $whereTo ).prepend( $( '<tr/>' ).addClass( 'headers' ).append([
- $( '<th/>' ).text( _l( 'Dataset' ) ),
- $( '<th/>' ).text( _l( 'Annotation' ) )
- ]));
- return hdaViews;
+
+ // convert to table
+ $whereTo.find( '.list-items' )
+ .replaceWith( $( '<table/>' ).addClass( 'list-items' ) );
+
+ // render rows/contents and prepend headers
+ var views = _super.prototype.renderItems.call( this, $whereTo );
+ this.$list( $whereTo )
+ .prepend( $( '<tr/>' ).addClass( 'headers' ).append([
+ $( '<th/>' ).text( _l( 'Dataset' ) ),
+ $( '<th/>' ).text( _l( 'Annotation' ) )
+ ]));
+ return views;
},
- // ------------------------------------------------------------------------ hda sub-views
- /** attach an hdaView to the panel
- * In this override, wrap the hdaView in a table row and cell, adding a 2nd cell for the hda annotation
+ // ------------------------------------------------------------------------ sub-views
+ /** In this override, wrap the content view in a table row
+ * with the content in the left td and annotation/extra-info in the right
*/
- attachContentView : function( hdaView, $whereTo ){
- $whereTo = $whereTo || this.$el;
- // build a row around the dataset with the std hdaView in the first cell and the annotation in the next
- var stateClass = _.find( hdaView.el.classList, function( c ){ return ( /^state\-/ ).test( c ); }),
- annotation = hdaView.model.get( 'annotation' ) || '',
- $tr = $( '<tr/>' ).addClass( 'dataset-row' ).append([
- $( '<td/>' ).addClass( 'dataset-container' ).append( hdaView.$el )
- // visually match the cell bg to the dataset at runtime (prevents the empty space)
- // (getting bg via jq on hidden elem doesn't work on chrome/webkit - so use states)
- //.css( 'background-color', hdaView.$el.css( 'background-color' ) ),
- .addClass( stateClass? stateClass.replace( '-', '-color-' ): '' ),
- $( '<td/>' ).addClass( 'additional-info' ).text( annotation )
- ]);
- this.$datasetsList( $whereTo ).append( $tr );
+ _attachItems : function( $whereTo ){
+ this.$list( $whereTo ).append( this.views.map( function( view ){
+ //TODO:?? possibly make this more flexible: instead of annotation use this._additionalInfo()
+ // build a row around the dataset with the std itemView in the first cell and the annotation in the next
+ var stateClass = _.find( view.el.classList, function( c ){ return ( /^state\-/ ).test( c ); }),
+ annotation = view.model.get( 'annotation' ) || '',
+ $tr = $( '<tr/>' ).append([
+ $( '<td/>' ).addClass( 'contents-container' ).append( view.$el )
+ // visually match the cell bg to the dataset at runtime (prevents the empty space)
+ // (getting bg via jq on hidden elem doesn't work on chrome/webkit - so use states)
+ //.css( 'background-color', view.$el.css( 'background-color' ) ),
+ .addClass( stateClass? stateClass.replace( '-', '-color-' ): '' ),
+ $( '<td/>' ).addClass( 'additional-info' ).text( annotation )
+ ]);
+ return $tr;
+ }));
+ return this;
},
// ------------------------------------------------------------------------ panel events
/** event map */
events : _.extend( _.clone( _super.prototype.events ), {
+ // clicking on any part of the row will expand the items
'click tr' : function( ev ){
- //if( !ev.target.hasAttribute( 'href' ) ){
- $( ev.currentTarget ).find( '.dataset-title-bar' ).click();
- //}
+ $( ev.currentTarget ).find( '.title-bar' ).click();
},
// prevent propagation on icon btns so they won't bubble up to tr and toggleBodyVisibility
'click .icon-btn' : function( ev ){
@@ -127,6 +106,7 @@
}
});
+
//==============================================================================
return {
AnnotatedHistoryPanel : AnnotatedHistoryPanel
This diff is so big that we needed to truncate the remainder.
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: carlfeberhard: Fix to b0c8da2: fix collapse call to curr panel in options; Browser tests: fix history selectors, misc. fixes
by commits-noreply@bitbucket.org 09 Sep '14
by commits-noreply@bitbucket.org 09 Sep '14
09 Sep '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/b4e8b3080281/
Changeset: b4e8b3080281
User: carlfeberhard
Date: 2014-09-09 16:09:06
Summary: Fix to b0c8da2: fix collapse call to curr panel in options; Browser tests: fix history selectors, misc. fixes
Affected #: 8 files
diff -r fbf45bfcdd19ce116a083a0742603234c91bc461 -r b4e8b308028162d72c4c393e1c876f1a17b2a614 templates/webapps/galaxy/root/index.mako
--- a/templates/webapps/galaxy/root/index.mako
+++ b/templates/webapps/galaxy/root/index.mako
@@ -66,7 +66,7 @@
},
"${_("Collapse Expanded Datasets")}": function() {
if( Galaxy && Galaxy.currHistoryPanel ){
- Galaxy.currHistoryPanel.collapseAllHdaBodies();
+ Galaxy.currHistoryPanel.collapseAll();
}
},
"${_("Include Deleted Datasets")}": function( clickEvent, thisMenuOption ) {
diff -r fbf45bfcdd19ce116a083a0742603234c91bc461 -r b4e8b308028162d72c4c393e1c876f1a17b2a614 test/casperjs/anon-history-tests.js
--- a/test/casperjs/anon-history-tests.js
+++ b/test/casperjs/anon-history-tests.js
@@ -23,7 +23,7 @@
unnamedName = spaceghost.historypanel.data.text.history.newName,
nameSelector = spaceghost.historypanel.data.selectors.history.name,
- subtitleSelector = spaceghost.historypanel.data.selectors.history.subtitle,
+ sizeSelector = spaceghost.historypanel.data.selectors.history.size,
initialSizeStr = spaceghost.historypanel.data.text.history.newSize,
tagIconSelector = spaceghost.historypanel.data.selectors.history.tagIcon,
annoIconSelector = spaceghost.historypanel.data.selectors.history.annoIcon,
@@ -47,11 +47,11 @@
this.test.assertVisible( nameSelector, 'History name is visible' );
this.test.assertSelectorHasText( nameSelector, unnamedName, 'History name is ' + unnamedName );
- this.test.comment( "history subtitle should display size and size should be 0 bytes" );
- this.test.assertExists( subtitleSelector, 'Found ' + subtitleSelector );
- this.test.assertVisible( subtitleSelector, 'History subtitle is visible' );
- this.test.assertSelectorHasText( subtitleSelector, initialSizeStr,
- 'History subtitle has "' + initialSizeStr + '"' );
+ this.test.comment( "history should display size and size should be 0 bytes" );
+ this.test.assertExists( sizeSelector, 'Found ' + sizeSelector );
+ this.test.assertVisible( sizeSelector, 'History size is visible' );
+ this.test.assertSelectorHasText( sizeSelector, initialSizeStr,
+ 'History size has "' + initialSizeStr + '"' );
this.test.comment( "NO tags or annotations icons should be available for an anonymous user" );
this.test.assertDoesntExist( tagIconSelector, 'Tag icon button not found' );
diff -r fbf45bfcdd19ce116a083a0742603234c91bc461 -r b4e8b308028162d72c4c393e1c876f1a17b2a614 test/casperjs/api-anon-history-tests.js
--- a/test/casperjs/api-anon-history-tests.js
+++ b/test/casperjs/api-anon-history-tests.js
@@ -8,7 +8,7 @@
spaceghost.start();
// =================================================================== TESTS
-spaceghost.thenOpen( spaceghost.baseUrl ).waitForSelector( '.history-name' );
+spaceghost.thenOpen( spaceghost.baseUrl ).waitForSelector( spaceghost.historypanel.data.selectors.history.name );
spaceghost.then( function(){
// ------------------------------------------------------------------------------------------- anon allowed
@@ -65,7 +65,7 @@
});
// ------------------------------------------------------------------------------------------- hdas
-spaceghost.thenOpen( spaceghost.baseUrl ).waitForSelector( '.history-name' );
+spaceghost.thenOpen( spaceghost.baseUrl ).waitForSelector( spaceghost.historypanel.data.selectors.history.name );
spaceghost.then( function(){
spaceghost.tools.uploadFile( '../../test-data/1.sam', function( uploadInfo ){
this.test.assert( uploadInfo.hdaElement !== null, "Convenience function produced hda" );
diff -r fbf45bfcdd19ce116a083a0742603234c91bc461 -r b4e8b308028162d72c4c393e1c876f1a17b2a614 test/casperjs/history-panel-tests.js
--- a/test/casperjs/history-panel-tests.js
+++ b/test/casperjs/history-panel-tests.js
@@ -27,6 +27,7 @@
nameSelector = spaceghost.historypanel.data.selectors.history.name,
subtitleSelector = spaceghost.historypanel.data.selectors.history.subtitle,
+ sizeSelector = spaceghost.historypanel.data.selectors.history.size,
unnamedName = spaceghost.historypanel.data.text.history.newName,
initialSizeStr = spaceghost.historypanel.data.text.history.newSize,
tagIconSelector = spaceghost.historypanel.data.selectors.history.tagIcon,
@@ -64,11 +65,11 @@
this.test.assertVisible( nameSelector, 'History name is visible' );
this.test.assertSelectorHasText( nameSelector, unnamedName, 'History name is ' + unnamedName );
- this.test.comment( "history subtitle should display size and size should be: " + initialSizeStr );
- this.test.assertExists( subtitleSelector, 'Found ' + subtitleSelector );
- this.test.assertVisible( subtitleSelector, 'History subtitle is visible' );
- this.test.assertSelectorHasText( subtitleSelector, initialSizeStr,
- 'History subtitle has "' + initialSizeStr + '"' );
+ this.test.comment( "history should display size and size should be: " + initialSizeStr );
+ this.test.assertExists( sizeSelector, 'Found ' + sizeSelector );
+ this.test.assertVisible( sizeSelector, 'History size is visible' );
+ this.test.assertSelectorHasText( sizeSelector, initialSizeStr,
+ 'History size has "' + initialSizeStr + '"' );
this.test.comment( "tags and annotation icons should be available" );
this.test.assertExists( tagIconSelector, 'Tag icon button found' );
@@ -157,12 +158,12 @@
this.test.assertSelectorHasText( nameSelector, newHistoryName, 'History name is ' + newHistoryName );
var onetxtFilesize = require( 'fs' ).size( filepathToUpload ),
- expectedSubtitle = onetxtFilesize + ' bytes';
- this.test.comment( "history subtitle should display size and size should be " + onetxtFilesize + " bytes" );
- this.test.assertExists( subtitleSelector, 'Found ' + subtitleSelector );
- this.test.assertVisible( subtitleSelector, 'History subtitle is visible' );
- this.test.assertSelectorHasText( subtitleSelector, expectedSubtitle,
- 'History subtitle has "' + expectedSubtitle + '": ' + this.fetchText( subtitleSelector ).trim() );
+ expectedSize = onetxtFilesize + ' bytes';
+ this.test.comment( "history should display size and size should be " + onetxtFilesize + " bytes" );
+ this.test.assertExists( sizeSelector, 'Found ' + sizeSelector );
+ this.test.assertVisible( sizeSelector, 'History size is visible' );
+ this.test.assertSelectorHasText( sizeSelector, expectedSize,
+ 'History size has "' + expectedSize + '": ' + this.fetchText( sizeSelector ).trim() );
this.test.comment( "tags and annotation icons should be available" );
this.test.assertExists( tagIconSelector, 'Tag icon button found' );
diff -r fbf45bfcdd19ce116a083a0742603234c91bc461 -r b4e8b308028162d72c4c393e1c876f1a17b2a614 test/casperjs/login-tests.js
--- a/test/casperjs/login-tests.js
+++ b/test/casperjs/login-tests.js
@@ -17,7 +17,8 @@
password = spaceghost.fixtureData.testUser.password;
}
-var userEmailSelector = '//a[contains(text(),"Logged in as")]';
+//var userEmailSelector = '//a[contains(text(),"Logged in as")]';
+var userEmailSelector = spaceghost.data.selectors.masthead.userMenu.userEmail_xpath;
// =================================================================== TESTS
// register a user (again...)
diff -r fbf45bfcdd19ce116a083a0742603234c91bc461 -r b4e8b308028162d72c4c393e1c876f1a17b2a614 test/casperjs/modules/historypanel.js
--- a/test/casperjs/modules/historypanel.js
+++ b/test/casperjs/modules/historypanel.js
@@ -356,15 +356,16 @@
},
selectors : {
history : {
- title : '.history-title',
- name : '.history-title .history-name',
- nameEditableTextInput : '.history-name input',
- subtitle : '.history-subtitle',
- tagIcon : '.history-secondary-actions .history-tag-btn',
- tagArea : '.history-controls .tags-display',
- annoIcon : '.history-secondary-actions .history-annotate-btn',
- annoArea : '.history-controls .annotation-display',
- emptyMsg : '.empty-history-message',
+ title : '.controls .title',
+ name : '.title .name',
+ nameEditableTextInput : '.name input',
+ subtitle : '.subtitle',
+ size : '.history-size',
+ tagIcon : '.actions .history-tag-btn',
+ tagArea : '.controls .tags-display',
+ annoIcon : '.actions .history-annotate-btn',
+ annoArea : '.controls .annotation-display',
+ emptyMsg : '.empty-message',
hdaContainer: '.datasets-list'
},
hda : {
diff -r fbf45bfcdd19ce116a083a0742603234c91bc461 -r b4e8b308028162d72c4c393e1c876f1a17b2a614 test/casperjs/modules/user.js
--- a/test/casperjs/modules/user.js
+++ b/test/casperjs/modules/user.js
@@ -56,14 +56,14 @@
// need manual submit (not a normal html form)
this.click( xpath( spaceghost.data.selectors.registrationPage.submit_xpath ) );
});
+ this.waitForNavigation( 'user/create', function afterRegister(){
+ // this.withMainPanel( function mainAfterRegister(){
+ // var messageInfo = spaceghost.getElementInfo( spaceghost.data.selectors.messages.all );
+ // spaceghost.debug( 'post registration message:\n' + spaceghost.jsonStr( messageInfo ) );
+ // });
+ });
});
- this.waitForNavigation( 'user/create', function afterRegister(){
- // this.withMainPanel( function mainAfterRegister(){
- // var messageInfo = spaceghost.getElementInfo( spaceghost.data.selectors.messages.all );
- // spaceghost.debug( 'post registration message:\n' + spaceghost.jsonStr( messageInfo ) );
- // });
- });
});
};
diff -r fbf45bfcdd19ce116a083a0742603234c91bc461 -r b4e8b308028162d72c4c393e1c876f1a17b2a614 test/casperjs/spaceghost.js
--- a/test/casperjs/spaceghost.js
+++ b/test/casperjs/spaceghost.js
@@ -638,7 +638,7 @@
}
function catchNavReq( url ){
- //this.debug( 'nav.req: ' + url );
+ this.debug( 'nav.req: ' + url );
for( var i=( urlsToWaitFor.length - 1 ); i>=0; i -= 1 ){
//this.debug( '\t checking: ' + urlsToWaitFor[i] );
if( urlMatches( urlsToWaitFor[i], url ) ){
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: jmchilton: Recreate run_functional_tests.sh as symbolic link to run_tests.sh.
by commits-noreply@bitbucket.org 09 Sep '14
by commits-noreply@bitbucket.org 09 Sep '14
09 Sep '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/fbf45bfcdd19/
Changeset: fbf45bfcdd19
User: jmchilton
Date: 2014-09-09 14:29:45
Summary: Recreate run_functional_tests.sh as symbolic link to run_tests.sh.
It is deprecated and will be removed someday - but we should mention in it more explicitly in a dev news brief and give it a few releases. See also Peter's comments on https://bitbucket.org/galaxy/galaxy-central/commits/6b26b7df6924de890ee547f….
Affected #: 1 file
diff -r 45a68696164451320e07537fa6fb8872686f710d -r fbf45bfcdd19ce116a083a0742603234c91bc461 run_functional_tests.sh
--- /dev/null
+++ b/run_functional_tests.sh
@@ -0,0 +1,1 @@
+run_tests.sh
\ No newline at end of file
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
08 Sep '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/45a686961644/
Changeset: 45a686961644
User: carlfeberhard
Date: 2014-09-08 22:56:07
Summary: Cleanup b0c8da2
Affected #: 10 files
diff -r 95b3be32cac3b11937fcc8813fb27a58ce0c18ca -r 45a68696164451320e07537fa6fb8872686f710d static/scripts/mvc/collection/collection-li.js
--- a/static/scripts/mvc/collection/collection-li.js
+++ b/static/scripts/mvc/collection/collection-li.js
@@ -98,8 +98,7 @@
//TODO: this might be expendable - compacted with HDAListItemView
/** logger used to record this.log messages, commonly set to console */
- // comment this out to suppress log output
- logger : console,
+ //logger : console,
/** add the DCE class to the list item */
className : ListItemView.prototype.className + " dataset-collection-element",
diff -r 95b3be32cac3b11937fcc8813fb27a58ce0c18ca -r 45a68696164451320e07537fa6fb8872686f710d static/scripts/mvc/collection/collection-panel.js
--- a/static/scripts/mvc/collection/collection-panel.js
+++ b/static/scripts/mvc/collection/collection-panel.js
@@ -18,7 +18,7 @@
//MODEL is either a DatasetCollection (or subclass) or a DatasetCollectionElement (list of pairs)
/** logger used to record this.log messages, commonly set to console */
- logger : console,
+ //logger : console,
className : _super.prototype.className + ' dataset-collection-panel',
@@ -41,7 +41,7 @@
this.panelStack = [];
this.parentName = attributes.parentName;
- window.collectionPanel = this;
+ //window.collectionPanel = this;
},
// ------------------------------------------------------------------------ sub-views
diff -r 95b3be32cac3b11937fcc8813fb27a58ce0c18ca -r 45a68696164451320e07537fa6fb8872686f710d static/scripts/mvc/history/history-panel-edit-current.js
--- a/static/scripts/mvc/history/history-panel-edit-current.js
+++ b/static/scripts/mvc/history/history-panel-edit-current.js
@@ -131,7 +131,6 @@
// if a hidden item is created (gen. by a workflow), moves thru the updater to the ready state,
// then: remove it from the collection if the panel is set to NOT show hidden datasets
this.collection.on( 'state:ready', function( model, newState, oldState ){
- console.debug( 'state:ready', model, newState, model.get( 'visible' ), this.storage.get( 'show_hidden' ) );
if( ( !model.get( 'visible' ) )
&& ( !this.storage.get( 'show_hidden' ) ) ){
this.removeItemView( this.viewFromModel( model ) );
@@ -274,7 +273,6 @@
});
panel.panelStack.push( overlaid );
- console.debug( panel.$( '.controls' ).add( panel.$list() ) );
panel.$( '.controls' ).add( panel.$list() ).hide();
panel.$el.append( overlaid.$el );
overlaid.on( 'close', function(){
diff -r 95b3be32cac3b11937fcc8813fb27a58ce0c18ca -r 45a68696164451320e07537fa6fb8872686f710d static/scripts/mvc/history/history-panel.js
--- a/static/scripts/mvc/history/history-panel.js
+++ b/static/scripts/mvc/history/history-panel.js
@@ -429,14 +429,11 @@
// if sentry is available, attempt to get the event id
var parsed = this._parseErrorMessage( model, xhr, options, msg, details );
// it's possible to have a triggered error before the message container is rendered - wait for it to show
- console.debug( this.$messages(), this.$messages().is( ':visible' ) );
if( !this.$messages().is( ':visible' ) ){
- console.debug( 'parsing error - waiting for render', model, xhr, options, msg, details );
this.once( 'rendered', function(){
this.displayMessage( 'error', parsed.message, parsed.details );
});
} else {
- console.debug( 'parsing error - showing', model, xhr, options, msg, details );
this.displayMessage( 'error', parsed.message, parsed.details );
}
}
@@ -543,7 +540,6 @@
/** Remove all messages from the panel. */
clearMessages : function( ev ){
- console.debug( ev.currentTarget );
$( ev.currentTarget ).fadeOut( this.fxSpeed, function(){
$( this ).remove();
});
diff -r 95b3be32cac3b11937fcc8813fb27a58ce0c18ca -r 45a68696164451320e07537fa6fb8872686f710d static/scripts/mvc/list/list-panel.js
--- a/static/scripts/mvc/list/list-panel.js
+++ b/static/scripts/mvc/list/list-panel.js
@@ -419,7 +419,6 @@
_renderEmptyMessage : function( $whereTo ){
this.debug( '_renderEmptyMessage', $whereTo, this.searchFor );
var text = this.searchFor? this.noneFoundMsg : this.emptyMsg;
- console.debug( this.$emptyMessage( $whereTo ) );
return this.$emptyMessage( $whereTo ).text( text );
},
diff -r 95b3be32cac3b11937fcc8813fb27a58ce0c18ca -r 45a68696164451320e07537fa6fb8872686f710d static/scripts/packed/mvc/collection/collection-li.js
--- a/static/scripts/packed/mvc/collection/collection-li.js
+++ b/static/scripts/packed/mvc/collection/collection-li.js
@@ -1,1 +1,1 @@
-define(["mvc/list/list-item","mvc/dataset/dataset-li","mvc/base-mvc","utils/localization"],function(a,h,i,d){var e=a.ListItemView;var c=e.extend({className:e.prototype.className+" dataset-collection",id:function(){return["dataset_collection",this.model.get("id")].join("-")},fxSpeed:"fast",initialize:function(j){if(j.logger){this.logger=this.model.logger=j.logger}this.log(this+"(DCListItemView).initialize:",j);e.prototype.initialize.call(this,j)},expand:function(){var j=this;return j._fetchModelDetails().always(function(){j.trigger("expanded",j)})},_renderSubtitle:function(){var j=$('<div class="subtitle"></div>');switch(this.model.get("collection_type")){case"list":return j.text(d("a list of datasets"));case"paired":return j.text(d("a pair of datasets"));case"list:paired":return j.text(d("a list of paired datasets"))}return j},toString:function(){var j=(this.model)?(this.model+""):("(no model)");return"DCListItemView("+j+")"}});c.prototype.templates=(function(){var j=i.wrapTemplate(['<div class="title-bar clear" tabindex="0">','<div class="title">','<span class="name"><%- collection.element_identifier || collection.name %></span>',"</div>",'<div class="subtitle"></div>',"</div>"],"collection");return _.extend({},e.prototype.templates,{titleBar:j})}());var f=e.extend({logger:console,className:e.prototype.className+" dataset-collection-element",fxSpeed:"fast",initialize:function(j){if(j.logger){this.logger=this.model.logger=j.logger}this.log("DCEListItemView.initialize:",j);e.prototype.initialize.call(this,j)},toString:function(){var j=(this.model)?(this.model+""):("(no model)");return"DCEListItemView("+j+")"}});f.prototype.templates=(function(){var j=i.wrapTemplate(['<div class="title-bar clear" tabindex="0">','<div class="title">','<span class="name"><%- element.element_identifier %></span>',"</div>",'<div class="subtitle"></div>',"</div>"],"element");return _.extend({},e.prototype.templates,{titleBar:j})}());var b=h.DatasetListItemView.extend({className:h.DatasetListItemView.prototype.className+" dataset-collection-element",initialize:function(j){if(j.logger){this.logger=this.model.logger=j.logger}this.log("DatasetDCEListItemView.initialize:",j);h.DatasetListItemView.prototype.initialize.call(this,j)},toString:function(){var j=(this.model)?(this.model+""):("(no model)");return"DatasetDCEListItemView("+j+")"}});b.prototype.templates=(function(){var j=i.wrapTemplate(['<div class="title-bar clear" tabindex="0">','<span class="state-icon"></span>','<div class="title">','<span class="name"><%- element.element_identifier %></span>',"</div>","</div>"],"element");return _.extend({},h.DatasetListItemView.prototype.templates,{titleBar:j})}());var g=c.extend({className:c.prototype.className+" dataset-collection-element",_swapNewRender:function(j){c.prototype._swapNewRender.call(this,j);var k=this.model.get("state")||"ok";this.$el.addClass("state-"+k);return this.$el},toString:function(){var j=(this.model)?(this.model+""):("(no model)");return"NestedDCDCEListItemView("+j+")"}});return{DCListItemView:c,DCEListItemView:f,DatasetDCEListItemView:b,NestedDCDCEListItemView:g}});
\ No newline at end of file
+define(["mvc/list/list-item","mvc/dataset/dataset-li","mvc/base-mvc","utils/localization"],function(a,h,i,d){var e=a.ListItemView;var c=e.extend({className:e.prototype.className+" dataset-collection",id:function(){return["dataset_collection",this.model.get("id")].join("-")},fxSpeed:"fast",initialize:function(j){if(j.logger){this.logger=this.model.logger=j.logger}this.log(this+"(DCListItemView).initialize:",j);e.prototype.initialize.call(this,j)},expand:function(){var j=this;return j._fetchModelDetails().always(function(){j.trigger("expanded",j)})},_renderSubtitle:function(){var j=$('<div class="subtitle"></div>');switch(this.model.get("collection_type")){case"list":return j.text(d("a list of datasets"));case"paired":return j.text(d("a pair of datasets"));case"list:paired":return j.text(d("a list of paired datasets"))}return j},toString:function(){var j=(this.model)?(this.model+""):("(no model)");return"DCListItemView("+j+")"}});c.prototype.templates=(function(){var j=i.wrapTemplate(['<div class="title-bar clear" tabindex="0">','<div class="title">','<span class="name"><%- collection.element_identifier || collection.name %></span>',"</div>",'<div class="subtitle"></div>',"</div>"],"collection");return _.extend({},e.prototype.templates,{titleBar:j})}());var f=e.extend({className:e.prototype.className+" dataset-collection-element",fxSpeed:"fast",initialize:function(j){if(j.logger){this.logger=this.model.logger=j.logger}this.log("DCEListItemView.initialize:",j);e.prototype.initialize.call(this,j)},toString:function(){var j=(this.model)?(this.model+""):("(no model)");return"DCEListItemView("+j+")"}});f.prototype.templates=(function(){var j=i.wrapTemplate(['<div class="title-bar clear" tabindex="0">','<div class="title">','<span class="name"><%- element.element_identifier %></span>',"</div>",'<div class="subtitle"></div>',"</div>"],"element");return _.extend({},e.prototype.templates,{titleBar:j})}());var b=h.DatasetListItemView.extend({className:h.DatasetListItemView.prototype.className+" dataset-collection-element",initialize:function(j){if(j.logger){this.logger=this.model.logger=j.logger}this.log("DatasetDCEListItemView.initialize:",j);h.DatasetListItemView.prototype.initialize.call(this,j)},toString:function(){var j=(this.model)?(this.model+""):("(no model)");return"DatasetDCEListItemView("+j+")"}});b.prototype.templates=(function(){var j=i.wrapTemplate(['<div class="title-bar clear" tabindex="0">','<span class="state-icon"></span>','<div class="title">','<span class="name"><%- element.element_identifier %></span>',"</div>","</div>"],"element");return _.extend({},h.DatasetListItemView.prototype.templates,{titleBar:j})}());var g=c.extend({className:c.prototype.className+" dataset-collection-element",_swapNewRender:function(j){c.prototype._swapNewRender.call(this,j);var k=this.model.get("state")||"ok";this.$el.addClass("state-"+k);return this.$el},toString:function(){var j=(this.model)?(this.model+""):("(no model)");return"NestedDCDCEListItemView("+j+")"}});return{DCListItemView:c,DCEListItemView:f,DatasetDCEListItemView:b,NestedDCDCEListItemView:g}});
\ No newline at end of file
diff -r 95b3be32cac3b11937fcc8813fb27a58ce0c18ca -r 45a68696164451320e07537fa6fb8872686f710d static/scripts/packed/mvc/collection/collection-panel.js
--- a/static/scripts/packed/mvc/collection/collection-panel.js
+++ b/static/scripts/packed/mvc/collection/collection-panel.js
@@ -1,1 +1,1 @@
-define(["mvc/list/list-panel","mvc/collection/collection-model","mvc/collection/collection-li","mvc/base-mvc","utils/localization"],function(a,d,f,j,b){var h=a.ModelListPanel;var g=h.extend({logger:console,className:h.prototype.className+" dataset-collection-panel",DatasetDCEViewClass:f.DatasetDCEListItemView,NestedDCDCEViewClass:f.NestedDCDCEListItemView,modelCollectionKey:"elements",initialize:function(k){h.prototype.initialize.call(this,k);this.linkTarget=k.linkTarget||"_blank";this.hasUser=k.hasUser;this.panelStack=[];this.parentName=k.parentName;window.collectionPanel=this},_filterCollection:function(){return this.model.getVisibleContents()},_getItemViewClass:function(k){switch(k.get("element_type")){case"hda":return this.DatasetDCEViewClass;case"dataset_collection":return this.NestedDCDCEViewClass}throw new TypeError("Unknown element type:",k.get("element_type"))},_getItemViewOptions:function(l){var k=h.prototype._getItemViewOptions.call(this,l);return _.extend(k,{linkTarget:this.linkTarget,hasUser:this.hasUser})},_setUpItemViewListeners:function(l){var k=this;h.prototype._setUpItemViewListeners.call(k,l);if(l.model.get("element_type")==="dataset_collection"){l.on("expanded",function(m){k.info("expanded",m);k._addCollectionPanel(m)})}return k},_addCollectionPanel:function(m){var n=this,k=m.model;var l=new i({model:k,parentName:this.model.get("name"),linkTarget:this.linkTarget});n.panelStack.push(l);n.$(".controls").add(".list-items").hide();n.$el.append(l.$el);l.on("close",function(){n.render();m.collapse();n.panelStack.pop()});if(!l.model.hasDetails()){var o=l.model.fetch();o.done(function(){l.render()})}else{l.render()}},events:{"click .navigation .back":"close"},close:function(k){this.$el.remove();this.trigger("close")},toString:function(){return"CollectionPanel("+((this.model)?(this.model.get("name")):(""))+")"}});g.prototype.templates=(function(){var k=j.wrapTemplate(['<div class="controls">','<div class="navigation">','<a class="back" href="javascript:void(0)">','<span class="fa fa-icon fa-angle-left"></span>',b("Back to "),"<%- view.parentName %>","</a>","</div>",'<div class="title">','<div class="name"><%- collection.name || collection.element_identifier %></div>','<div class="subtitle">','<% if( collection.collection_type === "list" ){ %>',b("a list of datasets"),'<% } else if( collection.collection_type === "paired" ){ %>',b("a pair of datasets"),'<% } else if( collection.collection_type === "list:paired" ){ %>',b("a list of paired datasets"),"<% } %>","</div>","</div>","</div>"],"collection");return _.extend(_.clone(h.prototype.templates),{controls:k})}());var e=g.extend({DatasetDCEViewClass:f.DatasetDCEListItemView,toString:function(){return"ListCollectionPanel("+((this.model)?(this.model.get("name")):(""))+")"}});var i=e.extend({toString:function(){return"PairCollectionPanel("+((this.model)?(this.model.get("name")):(""))+")"}});var c=g.extend({NestedDCDCEViewClass:f.NestedDCDCEListItemView,toString:function(){return"ListOfPairsCollectionPanel("+((this.model)?(this.model.get("name")):(""))+")"}});return{CollectionPanel:g,ListCollectionPanel:e,PairCollectionPanel:i,ListOfPairsCollectionPanel:c}});
\ No newline at end of file
+define(["mvc/list/list-panel","mvc/collection/collection-model","mvc/collection/collection-li","mvc/base-mvc","utils/localization"],function(a,d,f,j,b){var h=a.ModelListPanel;var g=h.extend({className:h.prototype.className+" dataset-collection-panel",DatasetDCEViewClass:f.DatasetDCEListItemView,NestedDCDCEViewClass:f.NestedDCDCEListItemView,modelCollectionKey:"elements",initialize:function(k){h.prototype.initialize.call(this,k);this.linkTarget=k.linkTarget||"_blank";this.hasUser=k.hasUser;this.panelStack=[];this.parentName=k.parentName},_filterCollection:function(){return this.model.getVisibleContents()},_getItemViewClass:function(k){switch(k.get("element_type")){case"hda":return this.DatasetDCEViewClass;case"dataset_collection":return this.NestedDCDCEViewClass}throw new TypeError("Unknown element type:",k.get("element_type"))},_getItemViewOptions:function(l){var k=h.prototype._getItemViewOptions.call(this,l);return _.extend(k,{linkTarget:this.linkTarget,hasUser:this.hasUser})},_setUpItemViewListeners:function(l){var k=this;h.prototype._setUpItemViewListeners.call(k,l);if(l.model.get("element_type")==="dataset_collection"){l.on("expanded",function(m){k.info("expanded",m);k._addCollectionPanel(m)})}return k},_addCollectionPanel:function(m){var n=this,k=m.model;var l=new i({model:k,parentName:this.model.get("name"),linkTarget:this.linkTarget});n.panelStack.push(l);n.$(".controls").add(".list-items").hide();n.$el.append(l.$el);l.on("close",function(){n.render();m.collapse();n.panelStack.pop()});if(!l.model.hasDetails()){var o=l.model.fetch();o.done(function(){l.render()})}else{l.render()}},events:{"click .navigation .back":"close"},close:function(k){this.$el.remove();this.trigger("close")},toString:function(){return"CollectionPanel("+((this.model)?(this.model.get("name")):(""))+")"}});g.prototype.templates=(function(){var k=j.wrapTemplate(['<div class="controls">','<div class="navigation">','<a class="back" href="javascript:void(0)">','<span class="fa fa-icon fa-angle-left"></span>',b("Back to "),"<%- view.parentName %>","</a>","</div>",'<div class="title">','<div class="name"><%- collection.name || collection.element_identifier %></div>','<div class="subtitle">','<% if( collection.collection_type === "list" ){ %>',b("a list of datasets"),'<% } else if( collection.collection_type === "paired" ){ %>',b("a pair of datasets"),'<% } else if( collection.collection_type === "list:paired" ){ %>',b("a list of paired datasets"),"<% } %>","</div>","</div>","</div>"],"collection");return _.extend(_.clone(h.prototype.templates),{controls:k})}());var e=g.extend({DatasetDCEViewClass:f.DatasetDCEListItemView,toString:function(){return"ListCollectionPanel("+((this.model)?(this.model.get("name")):(""))+")"}});var i=e.extend({toString:function(){return"PairCollectionPanel("+((this.model)?(this.model.get("name")):(""))+")"}});var c=g.extend({NestedDCDCEViewClass:f.NestedDCDCEListItemView,toString:function(){return"ListOfPairsCollectionPanel("+((this.model)?(this.model.get("name")):(""))+")"}});return{CollectionPanel:g,ListCollectionPanel:e,PairCollectionPanel:i,ListOfPairsCollectionPanel:c}});
\ No newline at end of file
diff -r 95b3be32cac3b11937fcc8813fb27a58ce0c18ca -r 45a68696164451320e07537fa6fb8872686f710d static/scripts/packed/mvc/history/history-panel-edit-current.js
--- a/static/scripts/packed/mvc/history/history-panel-edit-current.js
+++ b/static/scripts/packed/mvc/history/history-panel-edit-current.js
@@ -1,1 +1,1 @@
-define(["mvc/history/history-model","mvc/history/history-panel-edit","mvc/collection/collection-panel","mvc/base-mvc","utils/localization"],function(d,c,a,h,b){var e=h.SessionStorageModel.extend({defaults:{tagsEditorShown:false,annotationEditorShown:false},toString:function(){return"HistoryPanelPrefs("+JSON.stringify(this.toJSON())+")"}});e.storageKey=function f(){return("history-panel")};var g=c.HistoryPanelEdit;var i=g.extend({className:g.prototype.className+" current-history-panel",emptyMsg:b("This history is empty. Click 'Get Data' on the left tool menu to start"),noneFoundMsg:b("No matching datasets found"),initialize:function(j){j=j||{};this.preferences=new e(_.extend({id:e.storageKey()},_.pick(j,_.keys(e.prototype.defaults))));g.prototype.initialize.call(this,j);this.panelStack=[]},loadCurrentHistory:function(k){this.debug(this+".loadCurrentHistory");var j=this;return this.loadHistoryWithDetails("current",k).then(function(m,l){j.trigger("current-history",j)})},switchToHistory:function(m,l){var j=this,k=function(){return jQuery.getJSON(galaxy_config.root+"history/set_as_current?id="+m)};return this.loadHistoryWithDetails(m,l,k).then(function(o,n){j.trigger("switched-history",j)})},createNewHistory:function(l){if(!Galaxy||!Galaxy.currUser||Galaxy.currUser.isAnonymous()){this.displayMessage("error",b("You must be logged in to create histories"));return $.when()}var j=this,k=function(){return jQuery.getJSON(galaxy_config.root+"history/create_new_current")};return this.loadHistory(undefined,l,k).then(function(n,m){j.trigger("new-history",j)})},setModel:function(k,j,l){g.prototype.setModel.call(this,k,j,l);if(this.model){this.log("checking for updates");this.model.checkForUpdates()}return this},_setUpCollectionListeners:function(){g.prototype._setUpCollectionListeners.call(this);this.collection.on("state:ready",function(k,l,j){console.debug("state:ready",k,l,k.get("visible"),this.storage.get("show_hidden"));if((!k.get("visible"))&&(!this.storage.get("show_hidden"))){this.removeItemView(this.viewFromModel(k))}},this)},_setUpModelListeners:function(){g.prototype._setUpModelListeners.call(this);if(Galaxy&&Galaxy.quotaMeter){this.listenTo(this.model,"change:nice_size",function(){Galaxy.quotaMeter.update()})}},_buildNewRender:function(){if(!this.model){return $()}var j=g.prototype._buildNewRender.call(this);j.find(".search").prependTo(j.find(".controls"));this._renderQuotaMessage(j);return j},_renderQuotaMessage:function(j){j=j||this.$el;return $(this.templates.quotaMsg({},this)).prependTo(j.find(".messages"))},_renderEmptyMessage:function(l){var k=this,j=k.$emptyMessage(l),m=$(".toolMenuContainer");if((_.isEmpty(k.views)&&!k.searchFor)&&(Galaxy&&Galaxy.upload&&m.size())){j.empty();j.html([b("This history is empty"),". ",b("You can "),'<a class="uploader-link" href="javascript:void(0)">',b("load your own data"),"</a>",b(" or "),'<a class="get-data-link" href="javascript:void(0)">',b("get data from an external source"),"</a>"].join(""));j.find(".uploader-link").click(function(n){Galaxy.upload._eventShow(n)});j.find(".get-data-link").click(function(n){m.parent().scrollTop(0);m.find('span:contains("Get Data")').click()});return j.show()}return g.prototype._renderEmptyMessage.call(this,l)},_renderTags:function(j){var k=this;g.prototype._renderTags.call(this,j);if(this.preferences.get("tagsEditorShown")){this.tagsEditor.toggle(true)}this.tagsEditor.on("hiddenUntilActivated:shown hiddenUntilActivated:hidden",function(l){k.preferences.set("tagsEditorShown",l.hidden)})},_renderAnnotation:function(j){var k=this;g.prototype._renderAnnotation.call(this,j);if(this.preferences.get("annotationEditorShown")){this.annotationEditor.toggle(true)}this.annotationEditor.on("hiddenUntilActivated:shown hiddenUntilActivated:hidden",function(l){k.preferences.set("annotationEditorShown",l.hidden)})},_attachItems:function(j){this.$list(j).append(this.views.reverse().map(function(k){return k.$el}));return this},_setUpItemViewListeners:function(k){var j=this;g.prototype._setUpItemViewListeners.call(j,k);if(k instanceof j.HDCAViewClass){k.off("expanded");k.on("expanded",function(l){j.info("expanded",l);j._addCollectionPanel(l)});k.off("collapsed")}},_addCollectionPanel:function(l){var k=this,j=l.model;this.debug("history panel (stack), collectionModel:",j);var n=new (this._getCollectionPanelClass(j))({model:j,HDAViewClass:this.HDAViewClass,parentName:this.model.get("name"),linkTarget:this.linkTarget});k.panelStack.push(n);console.debug(k.$(".controls").add(k.$list()));k.$(".controls").add(k.$list()).hide();k.$el.append(n.$el);n.on("close",function(){k.render();l.collapse();k.panelStack.pop()});if(!n.model.hasDetails()){var m=n.model.fetch();m.done(function(){n.render()})}else{n.render()}},_getCollectionPanelClass:function(j){switch(j.get("collection_type")){case"list":return a.ListCollectionPanel;case"paired":return a.PairCollectionPanel;case"list:paired":return a.ListOfPairsCollectionPanel}throw new TypeError("Uknown collection_type: "+j.get("collection_type"))},addItemView:function(o,p,n){this.log(this+".addItemView:",o);if(!this._filterItem(o)){return undefined}var l=this;if(this.panelStack.length){return l}var k=l._createItemView(o);this.views.unshift(k);l.scrollToTop();$({}).queue([function m(r){var q=l.$emptyMessage();if(q.is(":visible")){q.fadeOut(l.fxSpeed,r)}else{r()}},function j(q){l.scrollToTop();l.$list().prepend(k.render(0).$el.hide());k.$el.slideDown(l.fxSpeed)}]);return k},connectToQuotaMeter:function(j){if(!j){return this}this.listenTo(j,"quota:over",this.showQuotaMessage);this.listenTo(j,"quota:under",this.hideQuotaMessage);this.on("rendered rendered:initial",function(){if(j&&j.isOverQuota()){this.showQuotaMessage()}});return this},showQuotaMessage:function(){var j=this.$el.find(".quota-message");if(j.is(":hidden")){j.slideDown(this.fxSpeed)}},hideQuotaMessage:function(){var j=this.$el.find(".quota-message");if(!j.is(":hidden")){j.slideUp(this.fxSpeed)}},connectToOptionsMenu:function(j){if(!j){return this}this.on("new-storage",function(l,k){if(j&&l){j.findItemByHtml(b("Include Deleted Datasets")).checked=l.get("show_deleted");j.findItemByHtml(b("Include Hidden Datasets")).checked=l.get("show_hidden")}});return this},toString:function(){return"CurrentHistoryPanel("+((this.model)?(this.model.get("name")):(""))+")"}});i.prototype.templates=(function(){var j=h.wrapTemplate(['<div class="quota-message errormessage">',b("You are over your disk quota"),". ",b("Tool execution is on hold until your disk usage drops below your allocated quota"),".","</div>"],"history");return _.extend(_.clone(g.prototype.templates),{quotaMsg:j})}());return{CurrentHistoryPanel:i}});
\ No newline at end of file
+define(["mvc/history/history-model","mvc/history/history-panel-edit","mvc/collection/collection-panel","mvc/base-mvc","utils/localization"],function(d,c,a,h,b){var e=h.SessionStorageModel.extend({defaults:{tagsEditorShown:false,annotationEditorShown:false},toString:function(){return"HistoryPanelPrefs("+JSON.stringify(this.toJSON())+")"}});e.storageKey=function f(){return("history-panel")};var g=c.HistoryPanelEdit;var i=g.extend({className:g.prototype.className+" current-history-panel",emptyMsg:b("This history is empty. Click 'Get Data' on the left tool menu to start"),noneFoundMsg:b("No matching datasets found"),initialize:function(j){j=j||{};this.preferences=new e(_.extend({id:e.storageKey()},_.pick(j,_.keys(e.prototype.defaults))));g.prototype.initialize.call(this,j);this.panelStack=[]},loadCurrentHistory:function(k){this.debug(this+".loadCurrentHistory");var j=this;return this.loadHistoryWithDetails("current",k).then(function(m,l){j.trigger("current-history",j)})},switchToHistory:function(m,l){var j=this,k=function(){return jQuery.getJSON(galaxy_config.root+"history/set_as_current?id="+m)};return this.loadHistoryWithDetails(m,l,k).then(function(o,n){j.trigger("switched-history",j)})},createNewHistory:function(l){if(!Galaxy||!Galaxy.currUser||Galaxy.currUser.isAnonymous()){this.displayMessage("error",b("You must be logged in to create histories"));return $.when()}var j=this,k=function(){return jQuery.getJSON(galaxy_config.root+"history/create_new_current")};return this.loadHistory(undefined,l,k).then(function(n,m){j.trigger("new-history",j)})},setModel:function(k,j,l){g.prototype.setModel.call(this,k,j,l);if(this.model){this.log("checking for updates");this.model.checkForUpdates()}return this},_setUpCollectionListeners:function(){g.prototype._setUpCollectionListeners.call(this);this.collection.on("state:ready",function(k,l,j){if((!k.get("visible"))&&(!this.storage.get("show_hidden"))){this.removeItemView(this.viewFromModel(k))}},this)},_setUpModelListeners:function(){g.prototype._setUpModelListeners.call(this);if(Galaxy&&Galaxy.quotaMeter){this.listenTo(this.model,"change:nice_size",function(){Galaxy.quotaMeter.update()})}},_buildNewRender:function(){if(!this.model){return $()}var j=g.prototype._buildNewRender.call(this);j.find(".search").prependTo(j.find(".controls"));this._renderQuotaMessage(j);return j},_renderQuotaMessage:function(j){j=j||this.$el;return $(this.templates.quotaMsg({},this)).prependTo(j.find(".messages"))},_renderEmptyMessage:function(l){var k=this,j=k.$emptyMessage(l),m=$(".toolMenuContainer");if((_.isEmpty(k.views)&&!k.searchFor)&&(Galaxy&&Galaxy.upload&&m.size())){j.empty();j.html([b("This history is empty"),". ",b("You can "),'<a class="uploader-link" href="javascript:void(0)">',b("load your own data"),"</a>",b(" or "),'<a class="get-data-link" href="javascript:void(0)">',b("get data from an external source"),"</a>"].join(""));j.find(".uploader-link").click(function(n){Galaxy.upload._eventShow(n)});j.find(".get-data-link").click(function(n){m.parent().scrollTop(0);m.find('span:contains("Get Data")').click()});return j.show()}return g.prototype._renderEmptyMessage.call(this,l)},_renderTags:function(j){var k=this;g.prototype._renderTags.call(this,j);if(this.preferences.get("tagsEditorShown")){this.tagsEditor.toggle(true)}this.tagsEditor.on("hiddenUntilActivated:shown hiddenUntilActivated:hidden",function(l){k.preferences.set("tagsEditorShown",l.hidden)})},_renderAnnotation:function(j){var k=this;g.prototype._renderAnnotation.call(this,j);if(this.preferences.get("annotationEditorShown")){this.annotationEditor.toggle(true)}this.annotationEditor.on("hiddenUntilActivated:shown hiddenUntilActivated:hidden",function(l){k.preferences.set("annotationEditorShown",l.hidden)})},_attachItems:function(j){this.$list(j).append(this.views.reverse().map(function(k){return k.$el}));return this},_setUpItemViewListeners:function(k){var j=this;g.prototype._setUpItemViewListeners.call(j,k);if(k instanceof j.HDCAViewClass){k.off("expanded");k.on("expanded",function(l){j.info("expanded",l);j._addCollectionPanel(l)});k.off("collapsed")}},_addCollectionPanel:function(l){var k=this,j=l.model;this.debug("history panel (stack), collectionModel:",j);var n=new (this._getCollectionPanelClass(j))({model:j,HDAViewClass:this.HDAViewClass,parentName:this.model.get("name"),linkTarget:this.linkTarget});k.panelStack.push(n);k.$(".controls").add(k.$list()).hide();k.$el.append(n.$el);n.on("close",function(){k.render();l.collapse();k.panelStack.pop()});if(!n.model.hasDetails()){var m=n.model.fetch();m.done(function(){n.render()})}else{n.render()}},_getCollectionPanelClass:function(j){switch(j.get("collection_type")){case"list":return a.ListCollectionPanel;case"paired":return a.PairCollectionPanel;case"list:paired":return a.ListOfPairsCollectionPanel}throw new TypeError("Uknown collection_type: "+j.get("collection_type"))},addItemView:function(o,p,n){this.log(this+".addItemView:",o);if(!this._filterItem(o)){return undefined}var l=this;if(this.panelStack.length){return l}var k=l._createItemView(o);this.views.unshift(k);l.scrollToTop();$({}).queue([function m(r){var q=l.$emptyMessage();if(q.is(":visible")){q.fadeOut(l.fxSpeed,r)}else{r()}},function j(q){l.scrollToTop();l.$list().prepend(k.render(0).$el.hide());k.$el.slideDown(l.fxSpeed)}]);return k},connectToQuotaMeter:function(j){if(!j){return this}this.listenTo(j,"quota:over",this.showQuotaMessage);this.listenTo(j,"quota:under",this.hideQuotaMessage);this.on("rendered rendered:initial",function(){if(j&&j.isOverQuota()){this.showQuotaMessage()}});return this},showQuotaMessage:function(){var j=this.$el.find(".quota-message");if(j.is(":hidden")){j.slideDown(this.fxSpeed)}},hideQuotaMessage:function(){var j=this.$el.find(".quota-message");if(!j.is(":hidden")){j.slideUp(this.fxSpeed)}},connectToOptionsMenu:function(j){if(!j){return this}this.on("new-storage",function(l,k){if(j&&l){j.findItemByHtml(b("Include Deleted Datasets")).checked=l.get("show_deleted");j.findItemByHtml(b("Include Hidden Datasets")).checked=l.get("show_hidden")}});return this},toString:function(){return"CurrentHistoryPanel("+((this.model)?(this.model.get("name")):(""))+")"}});i.prototype.templates=(function(){var j=h.wrapTemplate(['<div class="quota-message errormessage">',b("You are over your disk quota"),". ",b("Tool execution is on hold until your disk usage drops below your allocated quota"),".","</div>"],"history");return _.extend(_.clone(g.prototype.templates),{quotaMsg:j})}());return{CurrentHistoryPanel:i}});
\ No newline at end of file
diff -r 95b3be32cac3b11937fcc8813fb27a58ce0c18ca -r 45a68696164451320e07537fa6fb8872686f710d static/scripts/packed/mvc/history/history-panel.js
--- a/static/scripts/packed/mvc/history/history-panel.js
+++ b/static/scripts/packed/mvc/history/history-panel.js
@@ -1,1 +1,1 @@
-define(["mvc/list/list-panel","mvc/history/history-model","mvc/history/history-contents","mvc/history/hda-li","mvc/history/hdca-li","mvc/user/user-model","mvc/base-mvc","utils/localization"],function(d,f,l,b,a,g,n,e){var j=n.SessionStorageModel.extend({defaults:{expandedIds:{},show_deleted:false,show_hidden:false},addExpandedHda:function(o){var p="expandedIds";this.save(p,_.extend(this.get(p),_.object([o.id],[o.get("id")])))},removeExpandedHda:function(o){var p="expandedIds";this.save(p,_.omit(this.get(p),o.id))},toString:function(){return"HistoryPrefs("+this.id+")"}});j.storageKeyPrefix="history:";j.historyStorageKey=function h(o){if(!o){throw new Error("HistoryPrefs.historyStorageKey needs valid id: "+o)}return(j.storageKeyPrefix+o)};j.get=function c(o){return new j({id:j.historyStorageKey(o)})};j.clearAll=function i(p){for(var o in sessionStorage){if(o.indexOf(j.storageKeyPrefix)===0){sessionStorage.removeItem(o)}}};var m=d.ModelListPanel;var k=m.extend({HDAViewClass:b.HDAListItemView,HDCAViewClass:a.HDCAListItemView,collectionClass:l.HistoryContents,modelCollectionKey:"contents",tagName:"div",className:m.prototype.className+" history-panel",emptyMsg:e("This history is empty"),noneFoundMsg:e("No matching datasets found"),searchPlaceholder:e("search datasets"),initialize:function(o){m.prototype.initialize.call(this,o);this.linkTarget=o.linkTarget||"_blank"},freeModel:function(){m.prototype.freeModel.call(this);if(this.model){this.model.clearUpdateTimeout()}return this},_setUpListeners:function(){m.prototype._setUpListeners.call(this);this.on("error",function(p,s,o,r,q){this.errorHandler(p,s,o,r,q)});this.on("loading-done",function(){if(!this.views.length){this.trigger("empty-history",this)}})},loadHistoryWithDetails:function(r,q,p,s){this.info("loadHistoryWithDetails:",r,q,p,s);var o=function(t){return _.values(j.get(t.id).get("expandedIds"))};return this.loadHistory(r,q,p,s,o)},loadHistory:function(s,r,q,t,o){this.info("loadHistory:",s,r,q,t,o);var p=this;r=r||{};p.trigger("loading",p);var u=f.History.getHistoryData(s,{historyFn:q,contentsFn:t,detailIdsFn:r.initiallyExpanded||o});return p._loadHistoryFromXHR(u,r).fail(function(x,v,w){p.trigger("error",p,x,r,e("An error was encountered while "+v),{historyId:s,history:w||{}})}).always(function(){p.trigger("loading-done",p)})},_loadHistoryFromXHR:function(q,p){var o=this;q.then(function(r,s){o.JSONToModel(r,s,p);o.render()});q.fail(function(s,r){o.render()});return q},JSONToModel:function(r,o,p){this.log("JSONToModel:",r,o,p);p=p||{};var q=new f.History(r,o,p);this.setModel(q);return q},setModel:function(p,o){o=o||{};m.prototype.setModel.call(this,p,o);if(this.model){this._setUpWebStorage(o.initiallyExpanded,o.show_deleted,o.show_hidden)}},_setUpWebStorage:function(p,o,q){this.storage=new j({id:j.historyStorageKey(this.model.get("id"))});if(_.isObject(p)){this.storage.set("expandedIds",p)}if(_.isBoolean(o)){this.storage.set("show_deleted",o)}if(_.isBoolean(q)){this.storage.set("show_hidden",q)}this.trigger("new-storage",this.storage,this);this.log(this+" (init'd) storage:",this.storage.get());return this},_buildNewRender:function(){var o=m.prototype._buildNewRender.call(this);if(this.multiselectActions.length){o.find(".controls .actions").prepend(this._renderSelectButton())}return o},_renderSelectButton:function(o){return faIconButton({title:e("Operations on multiple datasets"),classes:"show-selectors-btn",faIcon:"fa-check-square-o"})},_getItemViewClass:function(o){var p=o.get("history_content_type");switch(p){case"dataset":return this.HDAViewClass;case"dataset_collection":return this.HDCAViewClass}throw new TypeError("Unknown history_content_type: "+p)},_filterItem:function(p){var o=this;return(m.prototype._filterItem.call(o,p)&&(!p.hidden()||o.storage.get("show_hidden"))&&(!p.isDeletedOrPurged()||o.storage.get("show_deleted")))},_getItemViewOptions:function(p){var o=m.prototype._getItemViewOptions.call(this,p);return _.extend(o,{linkTarget:this.linkTarget,expanded:!!this.storage.get("expandedIds")[p.id],hasUser:this.model.ownedByCurrUser()})},_setUpItemViewListeners:function(p){var o=this;m.prototype._setUpItemViewListeners.call(o,p);p.on("expanded",function(q){o.storage.addExpandedHda(q.model)});p.on("collapsed",function(q){o.storage.removeExpandedHda(q.model)});return this},refreshContents:function(p,o){if(this.model){return this.model.refresh(p,o)}return $.when()},getSelectedModels:function(){var o=m.prototype.getSelectedModels.call(this);o.historyId=this.collection.historyId;return o},events:_.extend(_.clone(m.prototype.events),{"click .show-selectors-btn":"toggleSelectors"}),toggleShowDeleted:function(o){o=(o!==undefined)?(o):(!this.storage.get("show_deleted"));this.storage.set("show_deleted",o);this.renderItems();return this.storage.get("show_deleted")},toggleShowHidden:function(o){o=(o!==undefined)?(o):(!this.storage.get("show_hidden"));this.storage.set("show_hidden",o);this.renderItems();return this.storage.get("show_hidden")},_firstSearch:function(o){var p=this,q=".history-search-input";this.log("onFirstSearch",o);if(p.model.contents.haveDetails()){p.searchItems(o);return}p.$el.find(q).searchInput("toggle-loading");p.model.contents.fetchAllDetails({silent:true}).always(function(){p.$el.find(q).searchInput("toggle-loading")}).done(function(){p.searchItems(o)})},errorHandler:function(q,t,p,s,r){this.error(q,t,p,s,r);if(t&&t.status===0&&t.readyState===0){}else{if(t&&t.status===502){}else{var o=this._parseErrorMessage(q,t,p,s,r);console.debug(this.$messages(),this.$messages().is(":visible"));if(!this.$messages().is(":visible")){console.debug("parsing error - waiting for render",q,t,p,s,r);this.once("rendered",function(){this.displayMessage("error",o.message,o.details)})}else{console.debug("parsing error - showing",q,t,p,s,r);this.displayMessage("error",o.message,o.details)}}}},_parseErrorMessage:function(s,v,w,q,o,t){var r=Galaxy.currUser,u={message:this._bePolite(q),details:{message:q,raven:(window.Raven&&_.isFunction(Raven.lastEventId))?(Raven.lastEventId()):(undefined),agent:navigator.userAgent,url:(window.Galaxy)?(Galaxy.lastAjax.url):(undefined),data:(window.Galaxy)?(Galaxy.lastAjax.data):(undefined),options:(v)?(_.omit(w,"xhr")):(w),xhr:v,source:(_.isFunction(s.toJSON))?(s.toJSON()):(s+""),user:(r instanceof g.User)?(r.toJSON()):(r+"")}};_.extend(u.details,o||{});if(v&&_.isFunction(v.getAllResponseHeaders)){var p=v.getAllResponseHeaders();p=_.compact(p.split("\n"));p=_.map(p,function(x){return x.split(": ")});u.details.xhr.responseHeaders=_.object(p)}return u},_bePolite:function(o){o=o||e("An error occurred while getting updates from the server");return o+". "+e("Please contact a Galaxy administrator if the problem persists")+"."},displayMessage:function(t,u,s){var q=this;this.scrollToTop();var r=this.$messages(),o=$("<div/>").addClass(t+"message").html(u);if(!_.isEmpty(s)){var p=$('<a href="javascript:void(0)">Details</a>').click(function(){Galaxy.modal.show(q._messageToModalOptions(t,u,s));return false});o.append(" ",p)}return r.html(o)},_messageToModalOptions:function(r,u,q){var o=this,p={title:"Details"};if(_.isObject(q)){q=_.omit(q,_.functions(q));var t=JSON.stringify(q,null," "),s=$("<pre/>").text(t);p.body=$("<div/>").append(s)}else{p.body=$("<div/>").html(q)}p.buttons={Ok:function(){Galaxy.modal.hide();o.clearMessages()}};return p},clearMessages:function(o){console.debug(o.currentTarget);$(o.currentTarget).fadeOut(this.fxSpeed,function(){$(this).remove()});return this},scrollToHid:function(o){return this.scrollToItem(_.first(this.viewsWhereModel({hid:o})))},toString:function(){return"HistoryPanel("+((this.model)?(this.model.get("name")):(""))+")"}});k.prototype.templates=(function(){var o=n.wrapTemplate(['<div class="controls">','<div class="title">','<div class="name"><%= history.name %></div>',"</div>",'<div class="subtitle">',"</div>",'<div class="history-size"><%= history.nice_size %></div>','<div class="actions"></div>','<div class="messages">',"<% if( history.deleted ){ %>",'<div class="deleted-msg warningmessagesmall">',e("This history has been deleted"),"</div>","<% } %>","<% if( history.message ){ %>",'<div class="<%= history.message.level || "info" %>messagesmall">',"<%= history.message.text %>","</div>","<% } %>","</div>",'<div class="tags-display"></div>','<div class="annotation-display"></div>','<div class="search">','<div class="search-input"></div>',"</div>",'<div class="list-actions">','<div class="btn-group">','<button class="select-all btn btn-default"','data-mode="select">',e("All"),"</button>",'<button class="deselect-all btn btn-default"','data-mode="select">',e("None"),"</button>","</div>",'<button class="list-action-popup-btn btn btn-default">',e("For all selected"),"...</button>","</div>","</div>"],"history");return _.extend(_.clone(m.prototype.templates),{controls:o})}());return{HistoryPanel:k}});
\ No newline at end of file
+define(["mvc/list/list-panel","mvc/history/history-model","mvc/history/history-contents","mvc/history/hda-li","mvc/history/hdca-li","mvc/user/user-model","mvc/base-mvc","utils/localization"],function(d,f,l,b,a,g,n,e){var j=n.SessionStorageModel.extend({defaults:{expandedIds:{},show_deleted:false,show_hidden:false},addExpandedHda:function(o){var p="expandedIds";this.save(p,_.extend(this.get(p),_.object([o.id],[o.get("id")])))},removeExpandedHda:function(o){var p="expandedIds";this.save(p,_.omit(this.get(p),o.id))},toString:function(){return"HistoryPrefs("+this.id+")"}});j.storageKeyPrefix="history:";j.historyStorageKey=function h(o){if(!o){throw new Error("HistoryPrefs.historyStorageKey needs valid id: "+o)}return(j.storageKeyPrefix+o)};j.get=function c(o){return new j({id:j.historyStorageKey(o)})};j.clearAll=function i(p){for(var o in sessionStorage){if(o.indexOf(j.storageKeyPrefix)===0){sessionStorage.removeItem(o)}}};var m=d.ModelListPanel;var k=m.extend({HDAViewClass:b.HDAListItemView,HDCAViewClass:a.HDCAListItemView,collectionClass:l.HistoryContents,modelCollectionKey:"contents",tagName:"div",className:m.prototype.className+" history-panel",emptyMsg:e("This history is empty"),noneFoundMsg:e("No matching datasets found"),searchPlaceholder:e("search datasets"),initialize:function(o){m.prototype.initialize.call(this,o);this.linkTarget=o.linkTarget||"_blank"},freeModel:function(){m.prototype.freeModel.call(this);if(this.model){this.model.clearUpdateTimeout()}return this},_setUpListeners:function(){m.prototype._setUpListeners.call(this);this.on("error",function(p,s,o,r,q){this.errorHandler(p,s,o,r,q)});this.on("loading-done",function(){if(!this.views.length){this.trigger("empty-history",this)}})},loadHistoryWithDetails:function(r,q,p,s){this.info("loadHistoryWithDetails:",r,q,p,s);var o=function(t){return _.values(j.get(t.id).get("expandedIds"))};return this.loadHistory(r,q,p,s,o)},loadHistory:function(s,r,q,t,o){this.info("loadHistory:",s,r,q,t,o);var p=this;r=r||{};p.trigger("loading",p);var u=f.History.getHistoryData(s,{historyFn:q,contentsFn:t,detailIdsFn:r.initiallyExpanded||o});return p._loadHistoryFromXHR(u,r).fail(function(x,v,w){p.trigger("error",p,x,r,e("An error was encountered while "+v),{historyId:s,history:w||{}})}).always(function(){p.trigger("loading-done",p)})},_loadHistoryFromXHR:function(q,p){var o=this;q.then(function(r,s){o.JSONToModel(r,s,p);o.render()});q.fail(function(s,r){o.render()});return q},JSONToModel:function(r,o,p){this.log("JSONToModel:",r,o,p);p=p||{};var q=new f.History(r,o,p);this.setModel(q);return q},setModel:function(p,o){o=o||{};m.prototype.setModel.call(this,p,o);if(this.model){this._setUpWebStorage(o.initiallyExpanded,o.show_deleted,o.show_hidden)}},_setUpWebStorage:function(p,o,q){this.storage=new j({id:j.historyStorageKey(this.model.get("id"))});if(_.isObject(p)){this.storage.set("expandedIds",p)}if(_.isBoolean(o)){this.storage.set("show_deleted",o)}if(_.isBoolean(q)){this.storage.set("show_hidden",q)}this.trigger("new-storage",this.storage,this);this.log(this+" (init'd) storage:",this.storage.get());return this},_buildNewRender:function(){var o=m.prototype._buildNewRender.call(this);if(this.multiselectActions.length){o.find(".controls .actions").prepend(this._renderSelectButton())}return o},_renderSelectButton:function(o){return faIconButton({title:e("Operations on multiple datasets"),classes:"show-selectors-btn",faIcon:"fa-check-square-o"})},_getItemViewClass:function(o){var p=o.get("history_content_type");switch(p){case"dataset":return this.HDAViewClass;case"dataset_collection":return this.HDCAViewClass}throw new TypeError("Unknown history_content_type: "+p)},_filterItem:function(p){var o=this;return(m.prototype._filterItem.call(o,p)&&(!p.hidden()||o.storage.get("show_hidden"))&&(!p.isDeletedOrPurged()||o.storage.get("show_deleted")))},_getItemViewOptions:function(p){var o=m.prototype._getItemViewOptions.call(this,p);return _.extend(o,{linkTarget:this.linkTarget,expanded:!!this.storage.get("expandedIds")[p.id],hasUser:this.model.ownedByCurrUser()})},_setUpItemViewListeners:function(p){var o=this;m.prototype._setUpItemViewListeners.call(o,p);p.on("expanded",function(q){o.storage.addExpandedHda(q.model)});p.on("collapsed",function(q){o.storage.removeExpandedHda(q.model)});return this},refreshContents:function(p,o){if(this.model){return this.model.refresh(p,o)}return $.when()},getSelectedModels:function(){var o=m.prototype.getSelectedModels.call(this);o.historyId=this.collection.historyId;return o},events:_.extend(_.clone(m.prototype.events),{"click .show-selectors-btn":"toggleSelectors"}),toggleShowDeleted:function(o){o=(o!==undefined)?(o):(!this.storage.get("show_deleted"));this.storage.set("show_deleted",o);this.renderItems();return this.storage.get("show_deleted")},toggleShowHidden:function(o){o=(o!==undefined)?(o):(!this.storage.get("show_hidden"));this.storage.set("show_hidden",o);this.renderItems();return this.storage.get("show_hidden")},_firstSearch:function(o){var p=this,q=".history-search-input";this.log("onFirstSearch",o);if(p.model.contents.haveDetails()){p.searchItems(o);return}p.$el.find(q).searchInput("toggle-loading");p.model.contents.fetchAllDetails({silent:true}).always(function(){p.$el.find(q).searchInput("toggle-loading")}).done(function(){p.searchItems(o)})},errorHandler:function(q,t,p,s,r){this.error(q,t,p,s,r);if(t&&t.status===0&&t.readyState===0){}else{if(t&&t.status===502){}else{var o=this._parseErrorMessage(q,t,p,s,r);if(!this.$messages().is(":visible")){this.once("rendered",function(){this.displayMessage("error",o.message,o.details)})}else{this.displayMessage("error",o.message,o.details)}}}},_parseErrorMessage:function(s,v,w,q,o,t){var r=Galaxy.currUser,u={message:this._bePolite(q),details:{message:q,raven:(window.Raven&&_.isFunction(Raven.lastEventId))?(Raven.lastEventId()):(undefined),agent:navigator.userAgent,url:(window.Galaxy)?(Galaxy.lastAjax.url):(undefined),data:(window.Galaxy)?(Galaxy.lastAjax.data):(undefined),options:(v)?(_.omit(w,"xhr")):(w),xhr:v,source:(_.isFunction(s.toJSON))?(s.toJSON()):(s+""),user:(r instanceof g.User)?(r.toJSON()):(r+"")}};_.extend(u.details,o||{});if(v&&_.isFunction(v.getAllResponseHeaders)){var p=v.getAllResponseHeaders();p=_.compact(p.split("\n"));p=_.map(p,function(x){return x.split(": ")});u.details.xhr.responseHeaders=_.object(p)}return u},_bePolite:function(o){o=o||e("An error occurred while getting updates from the server");return o+". "+e("Please contact a Galaxy administrator if the problem persists")+"."},displayMessage:function(t,u,s){var q=this;this.scrollToTop();var r=this.$messages(),o=$("<div/>").addClass(t+"message").html(u);if(!_.isEmpty(s)){var p=$('<a href="javascript:void(0)">Details</a>').click(function(){Galaxy.modal.show(q._messageToModalOptions(t,u,s));return false});o.append(" ",p)}return r.html(o)},_messageToModalOptions:function(r,u,q){var o=this,p={title:"Details"};if(_.isObject(q)){q=_.omit(q,_.functions(q));var t=JSON.stringify(q,null," "),s=$("<pre/>").text(t);p.body=$("<div/>").append(s)}else{p.body=$("<div/>").html(q)}p.buttons={Ok:function(){Galaxy.modal.hide();o.clearMessages()}};return p},clearMessages:function(o){$(o.currentTarget).fadeOut(this.fxSpeed,function(){$(this).remove()});return this},scrollToHid:function(o){return this.scrollToItem(_.first(this.viewsWhereModel({hid:o})))},toString:function(){return"HistoryPanel("+((this.model)?(this.model.get("name")):(""))+")"}});k.prototype.templates=(function(){var o=n.wrapTemplate(['<div class="controls">','<div class="title">','<div class="name"><%= history.name %></div>',"</div>",'<div class="subtitle">',"</div>",'<div class="history-size"><%= history.nice_size %></div>','<div class="actions"></div>','<div class="messages">',"<% if( history.deleted ){ %>",'<div class="deleted-msg warningmessagesmall">',e("This history has been deleted"),"</div>","<% } %>","<% if( history.message ){ %>",'<div class="<%= history.message.level || "info" %>messagesmall">',"<%= history.message.text %>","</div>","<% } %>","</div>",'<div class="tags-display"></div>','<div class="annotation-display"></div>','<div class="search">','<div class="search-input"></div>',"</div>",'<div class="list-actions">','<div class="btn-group">','<button class="select-all btn btn-default"','data-mode="select">',e("All"),"</button>",'<button class="deselect-all btn btn-default"','data-mode="select">',e("None"),"</button>","</div>",'<button class="list-action-popup-btn btn btn-default">',e("For all selected"),"...</button>","</div>","</div>"],"history");return _.extend(_.clone(m.prototype.templates),{controls:o})}());return{HistoryPanel:k}});
\ No newline at end of file
diff -r 95b3be32cac3b11937fcc8813fb27a58ce0c18ca -r 45a68696164451320e07537fa6fb8872686f710d static/scripts/packed/mvc/list/list-panel.js
--- a/static/scripts/packed/mvc/list/list-panel.js
+++ b/static/scripts/packed/mvc/list/list-panel.js
@@ -1,1 +1,1 @@
-define(["mvc/list/list-item","mvc/base-mvc","utils/localization"],function(d,b,c){var e=Backbone.View.extend(b.LoggableMixin).extend({viewClass:d.ListItemView,collectionClass:Backbone.Collection,tagName:"div",className:"list-panel",fxSpeed:"fast",emptyMsg:c("This list is empty"),noneFoundMsg:c("No matching items found"),searchPlaceholder:c("search"),multiselectActions:[],initialize:function(f,g){f=f||{};if(f.logger){this.logger=f.logger}this.log(this+".initialize:",f);this.fxSpeed=_.has(f,"fxSpeed")?(f.fxSpeed):(this.fxSpeed);this.filters=[];this.searchFor=f.searchFor||"";this.indicator=new LoadingIndicator(this.$el);this.selecting=(f.selecting!==undefined)?f.selecting:true;this.selected=f.selected||[];this.lastSelected=null;this.viewClass=f.viewClass||this.viewClass;this.views=[];this.collection=f.collection||(new this.collectionClass([]));this.filters=f.filters||[];this.$scrollContainer=f.$scrollContainer||this.$scrollContainer;this.title=f.title||"";this.subtitle=f.subtitle||"";this.multiselectActions=f.multiselectActions||this.multiselectActions;this.actionsPopup=null;this._setUpListeners()},freeViews:function(){_.each(this.views,function(f){f.off()});this.views=[];return this},_setUpListeners:function(){this.off();this.on("error",function(g,j,f,i,h){console.error(g,j,f,i,h)},this);this.on("loading",function(){this._showLoadingIndicator("loading...",40)},this);this.on("loading-done",function(){this._hideLoadingIndicator(40)},this);this.once("rendered",function(){this.trigger("rendered:initial",this)},this);if(this.logger){this.on("all",function(f){this.log(this+"",arguments)},this)}this._setUpCollectionListeners();this._setUpViewListeners();return this},_setUpCollectionListeners:function(){this.log(this+"._setUpCollectionListeners",this.collection);this.collection.off();this.collection.on("error",function(g,j,f,i,h){this.trigger("error",g,j,f,i,h)},this);this.collection.on("reset",function(){this.renderItems()},this);this.collection.on("add",this.addItemView,this);this.collection.on("remove",this.removeItemView,this);if(this.logger){this.collection.on("all",function(f){this.info(this+"(collection)",arguments)},this)}return this},_setUpViewListeners:function(){this.log(this+"._setUpViewListeners");this.on("view:selected",function(f,g){if(g&&g.shiftKey&&this.lastSelected){var h=_.find(this.views,function(i){return i.model.id===this.lastSelected});if(h){this.selectRange(f,h)}}this.selected.push(f.model.id);this.lastSelected=f.model.id},this);this.on("view:de-selected",function(f,g){this.selected=_.without(this.selected,f.model.id)},this)},render:function(g){this.log(this+".render",g);var f=this._buildNewRender();this._setUpBehaviors(f);this._queueNewRender(f,g);return this},_buildNewRender:function(){this.debug(this+"(ListPanel)._buildNewRender");var f=$(this.templates.el({},this));this._renderControls(f);this._renderTitle(f);this._renderSubtitle(f);this._renderSearch(f);this.renderItems(f);return f},_renderControls:function(g){this.debug(this+"(ListPanel)._renderControls");var f=$(this.templates.controls({},this));g.find(".controls").replaceWith(f);return f},_renderTitle:function(f){},_renderSubtitle:function(f){},_queueNewRender:function(g,h){h=(h===undefined)?(this.fxSpeed):(h);var f=this;f.log("_queueNewRender:",g,h);$(f).queue("fx",[function(i){this.$el.fadeOut(h,i)},function(i){f._swapNewRender(g);i()},function(i){this.$el.fadeIn(h,i)},function(i){f.trigger("rendered",f);i()}])},_swapNewRender:function(f){this.$el.empty().attr("class",this.className).append(f.children());if(this.selecting){this.showSelectors(0)}return this},_setUpBehaviors:function(f){f=f||this.$el;f.find(".controls [title]").tooltip({placement:"bottom"});return this},$scrollContainer:function(){return this.$el.parent().parent()},$list:function(f){return(f||this.$el).find(".list-items")},$messages:function(f){return(f||this.$el).find(".messages")},$emptyMessage:function(f){return(f||this.$el).find(".empty-message")},renderItems:function(h){h=h||this.$el;var f=this;f.log(this+".renderItems",h);var g=f.$list(h);f.views=f._filterCollection().map(function(i){return f._createItemView(i).render(0)});g.empty();if(f.views.length){f._attachItems(h);f.$emptyMessage(h).hide()}else{f._renderEmptyMessage(h).show()}return f.views},_filterCollection:function(){var f=this;return f.collection.filter(_.bind(f._filterItem,f))},_filterItem:function(g){var f=this;return(_.every(f.filters.map(function(h){return h.call(g)})))&&(!f.searchFor||g.matchesAll(f.searchFor))},_createItemView:function(h){var i=this._getItemViewClass(h),g=_.extend(this._getItemViewOptions(h),{model:h}),f=new i(g);this._setUpItemViewListeners(f);return f},_getItemViewClass:function(f){return this.viewClass},_getItemViewOptions:function(f){return{fxSpeed:this.fxSpeed,expanded:false,selectable:this.selecting,selected:_.contains(this.selected,f.id),draggable:this.dragging}},_setUpItemViewListeners:function(g){var f=this;g.on("all",function(){var h=Array.prototype.slice.call(arguments,0);h[0]="view:"+h[0];f.trigger.apply(f,h)});return f},_attachItems:function(f){this.$list(f).append(this.views.map(function(g){return g.$el}));return this},_renderEmptyMessage:function(f){this.debug("_renderEmptyMessage",f,this.searchFor);var g=this.searchFor?this.noneFoundMsg:this.emptyMsg;console.debug(this.$emptyMessage(f));return this.$emptyMessage(f).text(g)},expandAll:function(){_.each(this.views,function(f){f.expand()})},collapseAll:function(){_.each(this.views,function(f){f.collapse()})},addItemView:function(i,j,h){this.log(this+".addItemView:",i);var g=this;if(!g._filterItem(i)){return undefined}var f=g._createItemView(i);g.views.push(f);$(f).queue("fx",[function(k){g.$emptyMessage().fadeOut(g.fxSpeed,k)},function(k){g.$list().append(f.render().$el);k()}]);return f},removeItemView:function(i,j,h){this.log(this+".removeItemView:",i);var g=this,f=g.viewFromModel(i);if(!f){return undefined}$({}).queue("fx",[function(k){f.$el.fadeOut(g.fxSpeed,k)},function(k){g.views=_.without(g.views,f);f.remove();if(!g.views.length){g._renderEmptyMessage().fadeIn(g.fxSpeed,k)}else{k()}}]);return f},viewFromModel:function(g){for(var h=0;h<this.views.length;h++){var f=this.views[h];if(f.model===g){return f}}return undefined},viewFromModelId:function(g){for(var f=0;f<this.views.length;f++){if(this.views[f].model.id===g){return this.views[f]}}return undefined},viewsWhereModel:function(f){return this.views.filter(function(g){var i=g.model.toJSON();for(var h in f){if(f.hasOwnProperty(h)){if(i[h]!==g.model.get(h)){return false}}}return true})},viewRange:function(i,h){if(i===h){return(i)?([i]):([])}var g=this.views.indexOf(i),f=this.views.indexOf(h);if(g===-1||f===-1){if(g===f){return[]}return(g===-1)?([h]):([i])}return(g<f)?this.views.slice(g,f+1):this.views.slice(f,g+1)},_renderSearch:function(f){f.find(".controls .search-input").searchInput({placeholder:this.searchPlaceholder,initialVal:this.searchFor,onfirstsearch:_.bind(this._firstSearch,this),onsearch:_.bind(this.searchItems,this),onclear:_.bind(this.clearSearch,this)});return f},_firstSearch:function(f){this.log("onFirstSearch",f);return this.searchItems(f)},searchItems:function(f){this.searchFor=f;this.trigger("search:searching",f,this);this.renderItems();return this},clearSearch:function(f){this.searchFor="";this.trigger("search:clear",this);this.renderItems();return this},showSelectors:function(f){f=(f!==undefined)?(f):(this.fxSpeed);this.selecting=true;this.$(".list-actions").slideDown(f);_.each(this.views,function(g){g.showSelector(f)})},hideSelectors:function(f){f=(f!==undefined)?(f):(this.fxSpeed);this.selecting=false;this.$(".list-actions").slideUp(f);_.each(this.views,function(g){g.hideSelector(f)});this.selected=[];this.lastSelected=null},toggleSelectors:function(){if(!this.selecting){this.showSelectors()}else{this.hideSelectors()}},selectAll:function(f){_.each(this.views,function(g){g.select(f)})},deselectAll:function(f){this.lastSelected=null;_.each(this.views,function(g){g.deselect(f)})},selectRange:function(h,g){var f=this.viewRange(h,g);_.each(f,function(i){i.select()});return f},getSelectedViews:function(){return _.filter(this.views,function(f){return f.selected})},getSelectedModels:function(){return new this.collection.constructor(_.map(this.getSelectedViews(),function(f){return f.model}))},_showLoadingIndicator:function(g,f,h){this.debug("_showLoadingIndicator",this.indicator,g,f,h);f=(f!==undefined)?(f):(this.fxSpeed);if(!this.indicator){this.indicator=new LoadingIndicator(this.$el,this.$el.parent());this.debug("\t created",this.indicator)}if(!this.$el.is(":visible")){this.indicator.show(0,h)}else{this.$el.fadeOut(f);this.indicator.show(g,f,h)}},_hideLoadingIndicator:function(f,g){this.debug("_hideLoadingIndicator",this.indicator,f,g);f=(f!==undefined)?(f):(this.fxSpeed);if(this.indicator){this.indicator.hide(f,g)}},scrollPosition:function(){return this.$scrollContainer().scrollTop()},scrollTo:function(f){this.$scrollContainer().scrollTop(f);return this},scrollToTop:function(){this.$scrollContainer().scrollTop(0);return this},scrollToItem:function(f){if(!f){return this}var g=f.$el.offset().top;this.$scrollContainer().scrollTop(g);return this},scrollToId:function(f){return this.scrollToItem(this.viewFromModelId(f))},events:{"click .select-all":"selectAll","click .deselect-all":"deselectAll"},toString:function(){return"ListPanel("+this.collection+")"}});e.prototype.templates=(function(){var g=b.wrapTemplate(["<div>",'<div class="controls"></div>','<div class="list-items"></div>','<div class="empty-message infomessagesmall"></div>',"</div>"]);var f=b.wrapTemplate(['<div class="controls">','<div class="title">','<div class="name"><%= view.title %></div>',"</div>",'<div class="subtitle"><%= view.subtitle %></div>','<div class="actions"></div>','<div class="messages"></div>','<div class="search">','<div class="search-input"></div>',"</div>",'<div class="list-actions">','<div class="btn-group">','<button class="select-all btn btn-default"','data-mode="select">',c("All"),"</button>",'<button class="deselect-all btn btn-default"','data-mode="select">',c("None"),"</button>","</div>","</div>","</div>"]);return{el:g,controls:f}}());var a=e.extend({modelCollectionKey:"contents",initialize:function(f){e.prototype.initialize.call(this,f);this.selecting=(f.selecting!==undefined)?f.selecting:false;this.setModel(this.model,f)},setModel:function(g,f){f=f||{};this.debug(this+".setModel:",g,f);this.freeModel();this.freeViews();if(g){this.model=g;if(this.logger){this.model.logger=this.logger}this._setUpModelListeners();this.collection.off();this.collection=(this.model[this.modelCollectionKey])?this.model[this.modelCollectionKey]:(f.collection||(new this.collectionClass([])));this._setUpCollectionListeners();this.trigger("new-model",this)}return this},freeModel:function(){if(this.model){this.stopListening(this.model)}return this},_setUpModelListeners:function(){this.log(this+"._setUpModelListeners",this.model);this.model.on("error",function(){this.trigger.apply(panel,arguments)},this);return this},_renderControls:function(g){this.debug(this+"(ListPanel)._renderControls");var h=this.model?this.model.toJSON():{},f=$(this.templates.controls(h,this));g.find(".controls").replaceWith(f);this.debug("\t .controls:",this.$(".controls"));this.debug("\t $controls:",f);return f},toString:function(){return"ModelListPanel("+this.model+")"}});a.prototype.templates=(function(){var f=b.wrapTemplate(['<div class="controls">','<div class="title">','<div class="name"><%= model.name %></div>',"</div>",'<div class="subtitle"><%= view.subtitle %></div>','<div class="actions"></div>','<div class="messages"></div>','<div class="search">','<div class="search-input"></div>',"</div>",'<div class="list-actions">','<div class="btn-group">','<button class="select-all btn btn-default"','data-mode="select">',c("All"),"</button>",'<button class="deselect-all btn btn-default"','data-mode="select">',c("None"),"</button>","</div>","</div>","</div>"]);return _.extend(_.clone(e.prototype.templates),{controls:f})}());return{ListPanel:e,ModelListPanel:a}});
\ No newline at end of file
+define(["mvc/list/list-item","mvc/base-mvc","utils/localization"],function(d,b,c){var e=Backbone.View.extend(b.LoggableMixin).extend({viewClass:d.ListItemView,collectionClass:Backbone.Collection,tagName:"div",className:"list-panel",fxSpeed:"fast",emptyMsg:c("This list is empty"),noneFoundMsg:c("No matching items found"),searchPlaceholder:c("search"),multiselectActions:[],initialize:function(f,g){f=f||{};if(f.logger){this.logger=f.logger}this.log(this+".initialize:",f);this.fxSpeed=_.has(f,"fxSpeed")?(f.fxSpeed):(this.fxSpeed);this.filters=[];this.searchFor=f.searchFor||"";this.indicator=new LoadingIndicator(this.$el);this.selecting=(f.selecting!==undefined)?f.selecting:true;this.selected=f.selected||[];this.lastSelected=null;this.viewClass=f.viewClass||this.viewClass;this.views=[];this.collection=f.collection||(new this.collectionClass([]));this.filters=f.filters||[];this.$scrollContainer=f.$scrollContainer||this.$scrollContainer;this.title=f.title||"";this.subtitle=f.subtitle||"";this.multiselectActions=f.multiselectActions||this.multiselectActions;this.actionsPopup=null;this._setUpListeners()},freeViews:function(){_.each(this.views,function(f){f.off()});this.views=[];return this},_setUpListeners:function(){this.off();this.on("error",function(g,j,f,i,h){console.error(g,j,f,i,h)},this);this.on("loading",function(){this._showLoadingIndicator("loading...",40)},this);this.on("loading-done",function(){this._hideLoadingIndicator(40)},this);this.once("rendered",function(){this.trigger("rendered:initial",this)},this);if(this.logger){this.on("all",function(f){this.log(this+"",arguments)},this)}this._setUpCollectionListeners();this._setUpViewListeners();return this},_setUpCollectionListeners:function(){this.log(this+"._setUpCollectionListeners",this.collection);this.collection.off();this.collection.on("error",function(g,j,f,i,h){this.trigger("error",g,j,f,i,h)},this);this.collection.on("reset",function(){this.renderItems()},this);this.collection.on("add",this.addItemView,this);this.collection.on("remove",this.removeItemView,this);if(this.logger){this.collection.on("all",function(f){this.info(this+"(collection)",arguments)},this)}return this},_setUpViewListeners:function(){this.log(this+"._setUpViewListeners");this.on("view:selected",function(f,g){if(g&&g.shiftKey&&this.lastSelected){var h=_.find(this.views,function(i){return i.model.id===this.lastSelected});if(h){this.selectRange(f,h)}}this.selected.push(f.model.id);this.lastSelected=f.model.id},this);this.on("view:de-selected",function(f,g){this.selected=_.without(this.selected,f.model.id)},this)},render:function(g){this.log(this+".render",g);var f=this._buildNewRender();this._setUpBehaviors(f);this._queueNewRender(f,g);return this},_buildNewRender:function(){this.debug(this+"(ListPanel)._buildNewRender");var f=$(this.templates.el({},this));this._renderControls(f);this._renderTitle(f);this._renderSubtitle(f);this._renderSearch(f);this.renderItems(f);return f},_renderControls:function(g){this.debug(this+"(ListPanel)._renderControls");var f=$(this.templates.controls({},this));g.find(".controls").replaceWith(f);return f},_renderTitle:function(f){},_renderSubtitle:function(f){},_queueNewRender:function(g,h){h=(h===undefined)?(this.fxSpeed):(h);var f=this;f.log("_queueNewRender:",g,h);$(f).queue("fx",[function(i){this.$el.fadeOut(h,i)},function(i){f._swapNewRender(g);i()},function(i){this.$el.fadeIn(h,i)},function(i){f.trigger("rendered",f);i()}])},_swapNewRender:function(f){this.$el.empty().attr("class",this.className).append(f.children());if(this.selecting){this.showSelectors(0)}return this},_setUpBehaviors:function(f){f=f||this.$el;f.find(".controls [title]").tooltip({placement:"bottom"});return this},$scrollContainer:function(){return this.$el.parent().parent()},$list:function(f){return(f||this.$el).find(".list-items")},$messages:function(f){return(f||this.$el).find(".messages")},$emptyMessage:function(f){return(f||this.$el).find(".empty-message")},renderItems:function(h){h=h||this.$el;var f=this;f.log(this+".renderItems",h);var g=f.$list(h);f.views=f._filterCollection().map(function(i){return f._createItemView(i).render(0)});g.empty();if(f.views.length){f._attachItems(h);f.$emptyMessage(h).hide()}else{f._renderEmptyMessage(h).show()}return f.views},_filterCollection:function(){var f=this;return f.collection.filter(_.bind(f._filterItem,f))},_filterItem:function(g){var f=this;return(_.every(f.filters.map(function(h){return h.call(g)})))&&(!f.searchFor||g.matchesAll(f.searchFor))},_createItemView:function(h){var i=this._getItemViewClass(h),g=_.extend(this._getItemViewOptions(h),{model:h}),f=new i(g);this._setUpItemViewListeners(f);return f},_getItemViewClass:function(f){return this.viewClass},_getItemViewOptions:function(f){return{fxSpeed:this.fxSpeed,expanded:false,selectable:this.selecting,selected:_.contains(this.selected,f.id),draggable:this.dragging}},_setUpItemViewListeners:function(g){var f=this;g.on("all",function(){var h=Array.prototype.slice.call(arguments,0);h[0]="view:"+h[0];f.trigger.apply(f,h)});return f},_attachItems:function(f){this.$list(f).append(this.views.map(function(g){return g.$el}));return this},_renderEmptyMessage:function(f){this.debug("_renderEmptyMessage",f,this.searchFor);var g=this.searchFor?this.noneFoundMsg:this.emptyMsg;return this.$emptyMessage(f).text(g)},expandAll:function(){_.each(this.views,function(f){f.expand()})},collapseAll:function(){_.each(this.views,function(f){f.collapse()})},addItemView:function(i,j,h){this.log(this+".addItemView:",i);var g=this;if(!g._filterItem(i)){return undefined}var f=g._createItemView(i);g.views.push(f);$(f).queue("fx",[function(k){g.$emptyMessage().fadeOut(g.fxSpeed,k)},function(k){g.$list().append(f.render().$el);k()}]);return f},removeItemView:function(i,j,h){this.log(this+".removeItemView:",i);var g=this,f=g.viewFromModel(i);if(!f){return undefined}$({}).queue("fx",[function(k){f.$el.fadeOut(g.fxSpeed,k)},function(k){g.views=_.without(g.views,f);f.remove();if(!g.views.length){g._renderEmptyMessage().fadeIn(g.fxSpeed,k)}else{k()}}]);return f},viewFromModel:function(g){for(var h=0;h<this.views.length;h++){var f=this.views[h];if(f.model===g){return f}}return undefined},viewFromModelId:function(g){for(var f=0;f<this.views.length;f++){if(this.views[f].model.id===g){return this.views[f]}}return undefined},viewsWhereModel:function(f){return this.views.filter(function(g){var i=g.model.toJSON();for(var h in f){if(f.hasOwnProperty(h)){if(i[h]!==g.model.get(h)){return false}}}return true})},viewRange:function(i,h){if(i===h){return(i)?([i]):([])}var g=this.views.indexOf(i),f=this.views.indexOf(h);if(g===-1||f===-1){if(g===f){return[]}return(g===-1)?([h]):([i])}return(g<f)?this.views.slice(g,f+1):this.views.slice(f,g+1)},_renderSearch:function(f){f.find(".controls .search-input").searchInput({placeholder:this.searchPlaceholder,initialVal:this.searchFor,onfirstsearch:_.bind(this._firstSearch,this),onsearch:_.bind(this.searchItems,this),onclear:_.bind(this.clearSearch,this)});return f},_firstSearch:function(f){this.log("onFirstSearch",f);return this.searchItems(f)},searchItems:function(f){this.searchFor=f;this.trigger("search:searching",f,this);this.renderItems();return this},clearSearch:function(f){this.searchFor="";this.trigger("search:clear",this);this.renderItems();return this},showSelectors:function(f){f=(f!==undefined)?(f):(this.fxSpeed);this.selecting=true;this.$(".list-actions").slideDown(f);_.each(this.views,function(g){g.showSelector(f)})},hideSelectors:function(f){f=(f!==undefined)?(f):(this.fxSpeed);this.selecting=false;this.$(".list-actions").slideUp(f);_.each(this.views,function(g){g.hideSelector(f)});this.selected=[];this.lastSelected=null},toggleSelectors:function(){if(!this.selecting){this.showSelectors()}else{this.hideSelectors()}},selectAll:function(f){_.each(this.views,function(g){g.select(f)})},deselectAll:function(f){this.lastSelected=null;_.each(this.views,function(g){g.deselect(f)})},selectRange:function(h,g){var f=this.viewRange(h,g);_.each(f,function(i){i.select()});return f},getSelectedViews:function(){return _.filter(this.views,function(f){return f.selected})},getSelectedModels:function(){return new this.collection.constructor(_.map(this.getSelectedViews(),function(f){return f.model}))},_showLoadingIndicator:function(g,f,h){this.debug("_showLoadingIndicator",this.indicator,g,f,h);f=(f!==undefined)?(f):(this.fxSpeed);if(!this.indicator){this.indicator=new LoadingIndicator(this.$el,this.$el.parent());this.debug("\t created",this.indicator)}if(!this.$el.is(":visible")){this.indicator.show(0,h)}else{this.$el.fadeOut(f);this.indicator.show(g,f,h)}},_hideLoadingIndicator:function(f,g){this.debug("_hideLoadingIndicator",this.indicator,f,g);f=(f!==undefined)?(f):(this.fxSpeed);if(this.indicator){this.indicator.hide(f,g)}},scrollPosition:function(){return this.$scrollContainer().scrollTop()},scrollTo:function(f){this.$scrollContainer().scrollTop(f);return this},scrollToTop:function(){this.$scrollContainer().scrollTop(0);return this},scrollToItem:function(f){if(!f){return this}var g=f.$el.offset().top;this.$scrollContainer().scrollTop(g);return this},scrollToId:function(f){return this.scrollToItem(this.viewFromModelId(f))},events:{"click .select-all":"selectAll","click .deselect-all":"deselectAll"},toString:function(){return"ListPanel("+this.collection+")"}});e.prototype.templates=(function(){var g=b.wrapTemplate(["<div>",'<div class="controls"></div>','<div class="list-items"></div>','<div class="empty-message infomessagesmall"></div>',"</div>"]);var f=b.wrapTemplate(['<div class="controls">','<div class="title">','<div class="name"><%= view.title %></div>',"</div>",'<div class="subtitle"><%= view.subtitle %></div>','<div class="actions"></div>','<div class="messages"></div>','<div class="search">','<div class="search-input"></div>',"</div>",'<div class="list-actions">','<div class="btn-group">','<button class="select-all btn btn-default"','data-mode="select">',c("All"),"</button>",'<button class="deselect-all btn btn-default"','data-mode="select">',c("None"),"</button>","</div>","</div>","</div>"]);return{el:g,controls:f}}());var a=e.extend({modelCollectionKey:"contents",initialize:function(f){e.prototype.initialize.call(this,f);this.selecting=(f.selecting!==undefined)?f.selecting:false;this.setModel(this.model,f)},setModel:function(g,f){f=f||{};this.debug(this+".setModel:",g,f);this.freeModel();this.freeViews();if(g){this.model=g;if(this.logger){this.model.logger=this.logger}this._setUpModelListeners();this.collection.off();this.collection=(this.model[this.modelCollectionKey])?this.model[this.modelCollectionKey]:(f.collection||(new this.collectionClass([])));this._setUpCollectionListeners();this.trigger("new-model",this)}return this},freeModel:function(){if(this.model){this.stopListening(this.model)}return this},_setUpModelListeners:function(){this.log(this+"._setUpModelListeners",this.model);this.model.on("error",function(){this.trigger.apply(panel,arguments)},this);return this},_renderControls:function(g){this.debug(this+"(ListPanel)._renderControls");var h=this.model?this.model.toJSON():{},f=$(this.templates.controls(h,this));g.find(".controls").replaceWith(f);this.debug("\t .controls:",this.$(".controls"));this.debug("\t $controls:",f);return f},toString:function(){return"ModelListPanel("+this.model+")"}});a.prototype.templates=(function(){var f=b.wrapTemplate(['<div class="controls">','<div class="title">','<div class="name"><%= model.name %></div>',"</div>",'<div class="subtitle"><%= view.subtitle %></div>','<div class="actions"></div>','<div class="messages"></div>','<div class="search">','<div class="search-input"></div>',"</div>",'<div class="list-actions">','<div class="btn-group">','<button class="select-all btn btn-default"','data-mode="select">',c("All"),"</button>",'<button class="deselect-all btn btn-default"','data-mode="select">',c("None"),"</button>","</div>","</div>","</div>"]);return _.extend(_.clone(e.prototype.templates),{controls:f})}());return{ListPanel:e,ModelListPanel:a}});
\ No newline at end of file
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0