galaxy-commits
Threads by month
- ----- 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
August 2014
- 1 participants
- 159 discussions
commit/galaxy-central: nsoranzo: Fix SQlite datatype sniffing for old sqlite3. Remove unused imports.
by commits-noreply@bitbucket.org 28 Aug '14
by commits-noreply@bitbucket.org 28 Aug '14
28 Aug '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/03e9b373ec42/
Changeset: 03e9b373ec42
User: nsoranzo
Date: 2014-08-28 15:09:10
Summary: Fix SQlite datatype sniffing for old sqlite3. Remove unused imports.
Bug fixed: when uploading a gzipped FASTQ file through upload1 tool on a
machine with SQLite 3.3.6, it was detected as 'sqlite' datatype and not
decompressed.
In fact, the sqlite3 command 'pragma schema_version' on any file returns
without error on this SQLite version.
Affected #: 1 file
diff -r 59b6f95bfdd51bcf6c7da17fb9ad2fd4ad7f3133 -r 03e9b373ec42cf727a5d735876f55ab442f73310 lib/galaxy/datatypes/binary.py
--- a/lib/galaxy/datatypes/binary.py
+++ b/lib/galaxy/datatypes/binary.py
@@ -11,10 +11,7 @@
import struct
import subprocess
import tempfile
-import zipfile
-import sqlite3
-from urllib import urlencode, quote_plus
from galaxy import eggs
eggs.require( "bx-python" )
@@ -22,7 +19,6 @@
from galaxy.datatypes.metadata import MetadataElement,ListParameter,DictParameter
from galaxy.datatypes import metadata
-from galaxy.datatypes.sniff import *
import dataproviders
log = logging.getLogger(__name__)
@@ -580,14 +576,12 @@
except Exception, exc:
pass
- # Connects and runs a query that should work on any real database
- # If the file is not sqlite, an exception will be thrown and the sniffer will return false
def sniff( self, filename ):
+ # The first 16 bytes of any SQLite3 database file is 'SQLite format 3\0', and the file is binary. For details
+ # about the format, see http://www.sqlite.org/fileformat.html
try:
- conn = sqlite3.connect(filename)
- schema_version=conn.cursor().execute("pragma schema_version").fetchone()
- conn.close()
- if schema_version is not None:
+ header = open(filename).read(16)
+ if binascii.b2a_hex(header) == binascii.hexlify('SQLite format 3\0'):
return True
return False
except:
@@ -622,5 +616,5 @@
return dataproviders.dataset.SQliteDataProvider( dataset_source, **settings )
-Binary.register_sniffable_binary_format("sqlite","sqlite",SQlite)
+Binary.register_sniffable_binary_format("sqlite", "sqlite", SQlite)
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: nsoranzo: Fix SQlite datatype sniffing for old sqlite3. Remove unused imports.
by commits-noreply@bitbucket.org 28 Aug '14
by commits-noreply@bitbucket.org 28 Aug '14
28 Aug '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/a6cfe95047eb/
Changeset: a6cfe95047eb
Branch: stable
User: nsoranzo
Date: 2014-08-28 15:09:10
Summary: Fix SQlite datatype sniffing for old sqlite3. Remove unused imports.
Bug fixed: when uploading a gzipped FASTQ file through upload1 tool on a
machine with SQLite 3.3.6, it was detected as 'sqlite' datatype and not
decompressed.
In fact, the sqlite3 command 'pragma schema_version' on any file returns
without error on this SQLite version.
Affected #: 1 file
diff -r 57d1b775b0ca8515fd1fc71cee91e5db41cd9ec1 -r a6cfe95047eb7e85e3d0aa54e8bcce0ce449c880 lib/galaxy/datatypes/binary.py
--- a/lib/galaxy/datatypes/binary.py
+++ b/lib/galaxy/datatypes/binary.py
@@ -11,10 +11,7 @@
import struct
import subprocess
import tempfile
-import zipfile
-import sqlite3
-from urllib import urlencode, quote_plus
from galaxy import eggs
eggs.require( "bx-python" )
@@ -22,7 +19,6 @@
from galaxy.datatypes.metadata import MetadataElement
from galaxy.datatypes import metadata
-from galaxy.datatypes.sniff import *
import dataproviders
log = logging.getLogger(__name__)
@@ -552,14 +548,12 @@
class SQlite ( Binary ):
file_ext = "sqlite"
- # Connects and runs a query that should work on any real database
- # If the file is not sqlite, an exception will be thrown and the sniffer will return false
def sniff( self, filename ):
+ # The first 16 bytes of any SQLite3 database file is 'SQLite format 3\0', and the file is binary. For details
+ # about the format, see http://www.sqlite.org/fileformat.html
try:
- conn = sqlite3.connect(filename)
- schema_version=conn.cursor().execute("pragma schema_version").fetchone()
- conn.close()
- if schema_version is not None:
+ header = open(filename).read(16)
+ if binascii.b2a_hex(header) == binascii.hexlify('SQLite format 3\0'):
return True
return False
except:
@@ -586,5 +580,5 @@
return dataproviders.dataset.SQliteDataProvider( dataset_source, **settings )
-Binary.register_sniffable_binary_format("sqlite","sqlite",SQlite)
+Binary.register_sniffable_binary_format("sqlite", "sqlite", SQlite)
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 df2a994: remove debuggging statements
by commits-noreply@bitbucket.org 28 Aug '14
by commits-noreply@bitbucket.org 28 Aug '14
28 Aug '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/59b6f95bfdd5/
Changeset: 59b6f95bfdd5
User: carlfeberhard
Date: 2014-08-28 15:49:00
Summary: Fix to df2a994: remove debuggging statements
Affected #: 1 file
diff -r df2a99433e850b7ba594994fece91fdc87c24181 -r 59b6f95bfdd51bcf6c7da17fb9ad2fd4ad7f3133 lib/galaxy/visualization/registry.py
--- a/lib/galaxy/visualization/registry.py
+++ b/lib/galaxy/visualization/registry.py
@@ -229,14 +229,14 @@
Run a visualization's data_source tests to find out if
it can be applied to the target_object.
"""
- log.debug( 'is_object_applicable( self, trans, %s, %s )', target_object, data_source_tests )
+ #log.debug( 'is_object_applicable( self, trans, %s, %s )', target_object, data_source_tests )
for test in data_source_tests:
test_type = test[ 'type' ]
result_type = test[ 'result_type' ]
test_result = test[ 'result' ]
test_fn = test[ 'fn' ]
- log.debug( '%s %s: %s, %s, %s, %s', str( target_object ), 'is_object_applicable',
- test_type, result_type, test_result, test_fn )
+ #log.debug( '%s %s: %s, %s, %s, %s', str( target_object ), 'is_object_applicable',
+ # test_type, result_type, test_result, test_fn )
if test_type == 'isinstance':
# parse test_result based on result_type (curr: only datatype has to do this)
@@ -254,7 +254,7 @@
#NOTE: tests are OR'd, if any test passes - the visualization can be applied
if test_fn( target_object, test_result ):
- log.debug( '\t test passed' )
+ #log.debug( '\t test passed' )
return True
return 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
commit/galaxy-central: carlfeberhard: Vis registry: add two tests (has_attribute, not_eq); add see also for test types in visualization.dtd; correct applicability tests for trackster and circster using not_eq on datatype.track_type
by commits-noreply@bitbucket.org 28 Aug '14
by commits-noreply@bitbucket.org 28 Aug '14
28 Aug '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/df2a99433e85/
Changeset: df2a99433e85
User: carlfeberhard
Date: 2014-08-28 15:44:56
Summary: Vis registry: add two tests (has_attribute, not_eq); add see also for test types in visualization.dtd; correct applicability tests for trackster and circster using not_eq on datatype.track_type
Affected #: 4 files
diff -r f36c6fc80e8cd2bc6a5c6f77f0806aa7271e65f0 -r df2a99433e850b7ba594994fece91fdc87c24181 config/plugins/visualizations/circster/config/circster.xml
--- a/config/plugins/visualizations/circster/config/circster.xml
+++ b/config/plugins/visualizations/circster/config/circster.xml
@@ -4,13 +4,13 @@
<data_sources><data_source><model_class>HistoryDatasetAssociation</model_class>
- <test type="isinstance" test_attr="datatype" result_type="datatype">data.Data</test>
+ <test type="not_eq" test_attr="datatype.track_type">None</test><to_param param_attr="id">dataset_id</to_param><to_param assign="hda">hda_ldda</to_param></data_source><data_source><model_class>LibraryDatasetDatasetAssociation</model_class>
- <test type="isinstance" test_attr="datatype" result_type="datatype">data.Data</test>
+ <test type="not_eq" test_attr="datatype.track_type">None</test><to_param param_attr="id">dataset_id</to_param><to_param assign="ldda">hda_ldda</to_param></data_source>
diff -r f36c6fc80e8cd2bc6a5c6f77f0806aa7271e65f0 -r df2a99433e850b7ba594994fece91fdc87c24181 config/plugins/visualizations/trackster/config/trackster.xml
--- a/config/plugins/visualizations/trackster/config/trackster.xml
+++ b/config/plugins/visualizations/trackster/config/trackster.xml
@@ -5,14 +5,14 @@
<data_sources><data_source><model_class>HistoryDatasetAssociation</model_class>
- <test type="isinstance" test_attr="datatype" result_type="datatype">data.Data</test>
+ <test type="not_eq" test_attr="datatype.track_type">None</test><to_param param_attr="id">dataset_id</to_param><to_param assign="hda">hda_ldda</to_param><to_param param_attr="dbkey">dbkey</to_param></data_source><data_source><model_class>LibraryDatasetDatasetAssociation</model_class>
- <test type="isinstance" test_attr="datatype" result_type="datatype">data.Data</test>
+ <test type="not_eq" test_attr="datatype.track_type">None</test><to_param param_attr="id">dataset_id</to_param><to_param assign="ldda">hda_ldda</to_param></data_source>
diff -r f36c6fc80e8cd2bc6a5c6f77f0806aa7271e65f0 -r df2a99433e850b7ba594994fece91fdc87c24181 config/plugins/visualizations/visualization.dtd
--- a/config/plugins/visualizations/visualization.dtd
+++ b/config/plugins/visualizations/visualization.dtd
@@ -33,7 +33,8 @@
Currently, all tests are OR'd and there is no logical grouping. Tests are run in order.
(text): the text of this element is what the given target will be compared to (REQUIRED)
type: what type of test to run (e.g. when the target is an HDA the test will often be of type 'isinstance'
- and test whether the HDA's datatype isinstace of a class)
+ and test whether the HDA's datatype isinstace of a class).
+ See lib/galaxy/visualizations/registry.py, DataSourceParser.parse_tests for test type options.
DEFAULT: string comparison.
test_attr: what attribute of the target object should be used in the test. For instance, 'datatype'
will attempt to get the HDA.datatype from a target HDA. If the given object doesn't have
diff -r f36c6fc80e8cd2bc6a5c6f77f0806aa7271e65f0 -r df2a99433e850b7ba594994fece91fdc87c24181 lib/galaxy/visualization/registry.py
--- a/lib/galaxy/visualization/registry.py
+++ b/lib/galaxy/visualization/registry.py
@@ -203,6 +203,7 @@
#log.debug( '\t passed model_class' )
# tests are optional - default is the above class test
+#TODO: not true: must have test currently
tests = data_source[ 'tests' ]
if tests and not self.is_object_applicable( trans, target_object, tests ):
continue
@@ -228,14 +229,14 @@
Run a visualization's data_source tests to find out if
it can be applied to the target_object.
"""
- #log.debug( 'is_object_applicable( self, trans, %s, %s )', target_object, data_source_tests )
+ log.debug( 'is_object_applicable( self, trans, %s, %s )', target_object, data_source_tests )
for test in data_source_tests:
test_type = test[ 'type' ]
result_type = test[ 'result_type' ]
test_result = test[ 'result' ]
test_fn = test[ 'fn' ]
- #log.debug( '%s %s: %s, %s, %s, %s', str( target_object ), 'is_object_applicable',
- # test_type, result_type, test_result, test_fn )
+ log.debug( '%s %s: %s, %s, %s, %s', str( target_object ), 'is_object_applicable',
+ test_type, result_type, test_result, test_fn )
if test_type == 'isinstance':
# parse test_result based on result_type (curr: only datatype has to do this)
@@ -253,7 +254,7 @@
#NOTE: tests are OR'd, if any test passes - the visualization can be applied
if test_fn( target_object, test_result ):
- #log.debug( '\t test passed' )
+ log.debug( '\t test passed' )
return True
return False
@@ -407,6 +408,7 @@
# allow manually turning off a vis by checking for a disabled property
if 'disabled' in xml_tree.attrib:
+#TODO: differentiate between disabled and failed to parse, log.warn only on failure, log.info otherwise
return None
# a text display name for end user links
@@ -627,6 +629,13 @@
test_fn = lambda o, result: ( hasattr( getter( o ), 'has_dataprovider' )
and getter( o ).has_dataprovider( result ) )
+ elif test_type == 'has_attribute':
+ # does the object itself have attr in 'result' (no equivalence checking)
+ test_fn = lambda o, result: hasattr( getter( o ), result )
+
+ elif test_type == 'not_eq':
+ test_fn = lambda o, result: str( getter( o ) ) != result
+
else:
# default to simple (string) equilavance (coercing the test_attr to a string)
test_fn = lambda o, result: str( getter( o ) ) == result
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: natefoo: Update tag latest_2014.08.11 for changeset 109b170188e9
by commits-noreply@bitbucket.org 28 Aug '14
by commits-noreply@bitbucket.org 28 Aug '14
28 Aug '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/57d1b775b0ca/
Changeset: 57d1b775b0ca
Branch: stable
User: natefoo
Date: 2014-08-28 15:00:13
Summary: Update tag latest_2014.08.11 for changeset 109b170188e9
Affected #: 1 file
diff -r 109b170188e97fbfc2c998ec174aff9546dd1bd8 -r 57d1b775b0ca8515fd1fc71cee91e5db41cd9ec1 .hgtags
--- a/.hgtags
+++ b/.hgtags
@@ -18,4 +18,4 @@
81fbe25bd02edcd53065e8e4476dd1dfb5a72cf2 latest_2013.11.04
2a756ca2cb1826db7796018e77d12e2dd7b67603 latest_2014.02.10
ca45b78adb4152fc6e7395514d46eba6b7d0b838 release_2014.08.11
-9a4b43021fd1c5808c17329da7b6acbfd9ae27ed latest_2014.08.11
+109b170188e97fbfc2c998ec174aff9546dd1bd8 latest_2014.08.11
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: Fix using multiple list collections with different identifiers in workflows.
by commits-noreply@bitbucket.org 27 Aug '14
by commits-noreply@bitbucket.org 27 Aug '14
27 Aug '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/109b170188e9/
Changeset: 109b170188e9
Branch: stable
User: jmchilton
Date: 2014-08-27 20:39:43
Summary: Fix using multiple list collections with different identifiers in workflows.
Tools will pair off (or triplize, quadraplate, quintukify, etc...) based only on the index of the elements in the collection (so any N element list can be used in the same tool execution as any other N element list). Originally, I had decided to require the element identifiers to be the same in both collections (allows mixing a matching fewer collections in tools - but probably less likely to mismatch in a way the user did not intend). At any rate - I changed that decision and updated tool execution appropriately but not every aspect workflow collection 'pairing' - this fixes that and closes out this card https://trello.com/c/m5PiF1lR.
In very partical terms tools would ideally be consuming collection pairs - but for those that are still consuming two separate files (i.e. all of them) one can use two lists of datasets with pairs at matching indices and feed them into these tools - for workflows this doesn't work without this patch unless the identifiers and the indices match on these collections.
Thanks for Michael Crusoe and takadonet for the bug reports.
Affected #: 1 file
diff -r 51de5214e6f9e59b9bad5a05ae6a79d6e8944a9e -r 109b170188e97fbfc2c998ec174aff9546dd1bd8 lib/galaxy/dataset_collections/structure.py
--- a/lib/galaxy/dataset_collections/structure.py
+++ b/lib/galaxy/dataset_collections/structure.py
@@ -35,9 +35,9 @@
return self._walk_collections( dict_map( lambda hdca: hdca.collection, hdca_dict ) )
def _walk_collections( self, collection_dict ):
- for ( identifier, substructure ) in self.children:
+ for index, ( identifier, substructure ) in enumerate( self.children ):
def element( collection ):
- return collection[ identifier ]
+ return collection[ index ]
if substructure.is_leaf:
yield dict_map( element, collection_dict )
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
4 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/e032250c3f2e/
Changeset: e032250c3f2e
User: jmchilton
Date: 2014-08-27 22:32:26
Summary: Update readme for functional test tools directory.
Affected #: 1 file
diff -r a66a80701913bb99e8abd12235c1ca82dc508f57 -r e032250c3f2eef09002a00d6d1035de0928e58dd test/functional/tools/README.txt
--- a/test/functional/tools/README.txt
+++ b/test/functional/tools/README.txt
@@ -1,3 +1,15 @@
-This directory contains tools only useful for testing the tool test framework
-and demonstrating it features. Run the driver script 'run_functional_tests.sh'
-with '-framework' as first argument to run through these tests.
+This directory contains tools only useful for testing and
+demonstrating aspects of the tool syntax. Run the test driver script
+'run_tests.sh' with the '-framework' as first argument to run through
+these tests. Pass in an '-id' along with one of these tool ids to test
+a single tool.
+
+Some API tests use these tools to test various features of the API,
+tool, and workflow subsystems. Pass the arugment
+'-with_framework_test_tools' to 'run_tests.sh' in addition to '-api'
+to ensure these tools get loaded during the testing process.
+
+Finally, to play around witht these tools interactively - simply
+replace the 'universe_wsgi.ini' option 'tool_config_file' with:
+
+tool_config_file = test/functional/tools/samples_tool_conf.xml
https://bitbucket.org/galaxy/galaxy-central/commits/14230488f497/
Changeset: 14230488f497
User: jmchilton
Date: 2014-08-27 22:32:26
Summary: Add some more basic test tools for building simple workflows for testing.
Affected #: 4 files
diff -r e032250c3f2eef09002a00d6d1035de0928e58dd -r 14230488f49758d1abe748cd7500f9719a3390b6 test/functional/tools/for_workflows/cat.xml
--- /dev/null
+++ b/test/functional/tools/for_workflows/cat.xml
@@ -0,0 +1,19 @@
+<tool id="cat" name="Concatenate datasets (for test workflows)">
+ <description>tail-to-head</description>
+ <command>
+ cat $input1 #for $q in $queries# ${q.input2} #end for# > $out_file1
+ </command>
+ <inputs>
+ <param name="input1" type="data" label="Concatenate Dataset"/>
+ <repeat name="queries" title="Dataset">
+ <param name="input2" type="data" label="Select" />
+ </repeat>
+ </inputs>
+ <outputs>
+ <data name="out_file1" format="input" metadata_source="input1"/>
+ </outputs>
+ <tests>
+ </tests>
+ <help>
+ </help>
+</tool>
diff -r e032250c3f2eef09002a00d6d1035de0928e58dd -r 14230488f49758d1abe748cd7500f9719a3390b6 test/functional/tools/for_workflows/cat_list.xml
--- /dev/null
+++ b/test/functional/tools/for_workflows/cat_list.xml
@@ -0,0 +1,16 @@
+<tool id="cat_list" name="Concatenate dataset list (for test workflows)">
+ <description>tail-to-head</description>
+ <command>
+ cat #for $q in $input1# $q #end for# > $out_file1
+ </command>
+ <inputs>
+ <param name="input1" type="data" label="Concatenate Dataset" multiple="true" />
+ </inputs>
+ <outputs>
+ <data name="out_file1" format="input" metadata_source="input1"/>
+ </outputs>
+ <tests>
+ </tests>
+ <help>
+ </help>
+</tool>
diff -r e032250c3f2eef09002a00d6d1035de0928e58dd -r 14230488f49758d1abe748cd7500f9719a3390b6 test/functional/tools/for_workflows/head.xml
--- /dev/null
+++ b/test/functional/tools/for_workflows/head.xml
@@ -0,0 +1,13 @@
+<tool id="head" name="Select first">
+ <description>lines from a dataset</description>
+ <command>head $input $lineNum > $out_file1</command>
+ <inputs>
+ <param name="lineNum" size="5" type="integer" value="10" label="Select first" help="lines"/>
+ <param format="txt" name="input" type="data" label="from"/>
+ </inputs>
+ <outputs>
+ <data format="input" name="out_file1" metadata_source="input"/>
+ </outputs>
+ <help>
+ </help>
+</tool>
diff -r e032250c3f2eef09002a00d6d1035de0928e58dd -r 14230488f49758d1abe748cd7500f9719a3390b6 test/functional/tools/samples_tool_conf.xml
--- a/test/functional/tools/samples_tool_conf.xml
+++ b/test/functional/tools/samples_tool_conf.xml
@@ -23,4 +23,10 @@
<tool file="collection_mixed_param.xml" /><tool file="collection_two_paired.xml" /><tool file="collection_optional_param.xml" />
-</toolbox>
\ No newline at end of file
+
+ <!-- Tools interesting only for building up test workflows. -->
+ <tool file="for_workflows/cat.xml" />
+ <tool file="for_workflows/cat_list.xml" />
+ <tool file="for_workflows/head.xml" />
+
+</toolbox>
https://bitbucket.org/galaxy/galaxy-central/commits/c692332612dd/
Changeset: c692332612dd
User: jmchilton
Date: 2014-08-27 22:32:26
Summary: Remove workflow test that accidently depended on tool not in -central.
Opps.
Affected #: 3 files
diff -r 14230488f49758d1abe748cd7500f9719a3390b6 -r c692332612dd5c8d7eff798cdba4f2e91d4ff5a1 test/api/helpers.py
--- a/test/api/helpers.py
+++ b/test/api/helpers.py
@@ -11,7 +11,6 @@
# Simple workflow that takes an input and filters with random lines twice in a
# row - first grabbing 8 lines at random and then 6.
workflow_random_x2_str = resource_string( __name__, "test_workflow_2.ga" )
-workflow_two_paired_str = resource_string( __name__, "test_workflow_two_paired.ga" )
DEFAULT_HISTORY_TIMEOUT = 10 # Secs to wait on history to turn ok
@@ -161,9 +160,6 @@
def load_random_x2_workflow( self, name ):
return self.load_workflow( name, content=workflow_random_x2_str )
- def load_two_paired_workflow( self, name ):
- return self.load_workflow( name, content=workflow_two_paired_str )
-
def simple_workflow( self, name, **create_kwds ):
workflow = self.load_workflow( name )
return self.create_workflow( workflow, **create_kwds )
diff -r 14230488f49758d1abe748cd7500f9719a3390b6 -r c692332612dd5c8d7eff798cdba4f2e91d4ff5a1 test/api/test_workflow_two_paired.ga
--- a/test/api/test_workflow_two_paired.ga
+++ /dev/null
@@ -1,116 +0,0 @@
-{
- "a_galaxy_workflow": "true",
- "annotation": "",
- "format-version": "0.1",
- "name": "MultipairTest223",
- "steps": {
- "0": {
- "annotation": "",
- "id": 0,
- "input_connections": {},
- "inputs": [
- {
- "description": "",
- "name": "f1"
- }
- ],
- "name": "Input dataset collection",
- "outputs": [],
- "position": {
- "left": 302.3333435058594,
- "top": 330
- },
- "tool_errors": null,
- "tool_id": null,
- "tool_state": "{\"collection_type\": \"paired\", \"name\": \"f1\"}",
- "tool_version": null,
- "type": "data_collection_input",
- "user_outputs": []
- },
- "1": {
- "annotation": "",
- "id": 1,
- "input_connections": {},
- "inputs": [
- {
- "description": "",
- "name": "f2"
- }
- ],
- "name": "Input dataset collection",
- "outputs": [],
- "position": {
- "left": 288.3333435058594,
- "top": 446
- },
- "tool_errors": null,
- "tool_id": null,
- "tool_state": "{\"collection_type\": \"paired\", \"name\": \"f2\"}",
- "tool_version": null,
- "type": "data_collection_input",
- "user_outputs": []
- },
- "2": {
- "annotation": "",
- "id": 2,
- "input_connections": {
- "kind|f1": {
- "id": 0,
- "output_name": "output"
- },
- "kind|f2": {
- "id": 1,
- "output_name": "output"
- }
- },
- "inputs": [],
- "name": "collection_two_paired",
- "outputs": [
- {
- "name": "out1",
- "type": "txt"
- }
- ],
- "position": {
- "left": 782.3333740234375,
- "top": 200
- },
- "post_job_actions": {},
- "tool_errors": null,
- "tool_id": "collection_two_paired",
- "tool_state": "{\"__page__\": 0, \"kind\": \"{\\\"f1\\\": null, \\\"f2\\\": null, \\\"collection_type\\\": \\\"paired\\\", \\\"__current_case__\\\": 0}\", \"__rerun_remap_job_id__\": null}",
- "tool_version": "0.1.0",
- "type": "tool",
- "user_outputs": []
- },
- "3": {
- "annotation": "",
- "id": 3,
- "input_connections": {
- "cond1|input1": {
- "id": 2,
- "output_name": "out1"
- }
- },
- "inputs": [],
- "name": "Concatenate datasets",
- "outputs": [
- {
- "name": "out_file1",
- "type": "input"
- }
- ],
- "position": {
- "left": 1239.3333740234375,
- "top": 108.97916793823242
- },
- "post_job_actions": {},
- "tool_errors": null,
- "tool_id": "cat2",
- "tool_state": "{\"__page__\": 0, \"__rerun_remap_job_id__\": null, \"cond1\": \"{\\\"datatype\\\": \\\"txt\\\", \\\"input1\\\": null, \\\"__current_case__\\\": 0}\"}",
- "tool_version": "1.0.0",
- "type": "tool",
- "user_outputs": []
- }
- }
-}
\ No newline at end of file
diff -r 14230488f49758d1abe748cd7500f9719a3390b6 -r c692332612dd5c8d7eff798cdba4f2e91d4ff5a1 test/api/test_workflows.py
--- a/test/api/test_workflows.py
+++ b/test/api/test_workflows.py
@@ -149,26 +149,6 @@
run_workflow_response = self._post( "workflows", data=workflow_request )
self._assert_status_code_is( run_workflow_response, 403 )
- @skip_without_tool( "cat1" )
- @skip_without_tool( "collection_two_paired" )
- def test_run_workflow_collection_params( self ):
- workflow = self.workflow_populator.load_two_paired_workflow( name="test_for_run_two_paired" )
- workflow_id = self.workflow_populator.create_workflow( workflow )
- history_id = self.dataset_populator.new_history()
- hdca1 = self.dataset_collection_populator.create_pair_in_history( history_id, contents=["1 2 3", "4 5 6"] ).json()
- hdca2 = self.dataset_collection_populator.create_pair_in_history( history_id, contents=["7 8 9", "0 a b"] ).json()
- self.dataset_populator.wait_for_history( history_id, assert_ok=True )
- label_map = { "f1": self._ds_entry( hdca1 ), "f2": self._ds_entry( hdca2 ) }
- workflow_request = dict(
- history="hist_id=%s" % history_id,
- workflow_id=workflow_id,
- ds_map=self._build_ds_map( workflow_id, label_map ),
- )
- 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("1 2 3\n4 5 6\n7 8 9\n0 a b\n", self.dataset_populator.get_history_dataset_content( history_id ) )
-
def test_workflow_stability( self ):
# Run this index stability test with following command:
# ./run_tests.sh test/api/test_workflows.py:WorkflowsApiTestCase.test_workflow_stability
https://bitbucket.org/galaxy/galaxy-central/commits/f36c6fc80e8c/
Changeset: f36c6fc80e8c
User: jmchilton
Date: 2014-08-27 22:32:26
Summary: Add workflow test demonstrating failure when multiple lists with different identifiers are using in workflows.
Affected #: 3 files
diff -r c692332612dd5c8d7eff798cdba4f2e91d4ff5a1 -r f36c6fc80e8cd2bc6a5c6f77f0806aa7271e65f0 test/api/helpers.py
--- a/test/api/helpers.py
+++ b/test/api/helpers.py
@@ -160,6 +160,12 @@
def load_random_x2_workflow( self, name ):
return self.load_workflow( name, content=workflow_random_x2_str )
+ def load_workflow_from_resource( self, name, filename=None ):
+ if filename is None:
+ filename = "%s.ga" % name
+ content = resource_string( __name__, filename )
+ return self.load_workflow( name, content=content )
+
def simple_workflow( self, name, **create_kwds ):
workflow = self.load_workflow( name )
return self.create_workflow( workflow, **create_kwds )
@@ -319,8 +325,14 @@
def list_identifiers( self, history_id, contents=None ):
count = 3 if not contents else len( contents )
- hdas = self.__datasets( history_id, count=count, contents=contents )
- hda_to_identifier = lambda ( i, hda ): dict( name="data%d" % ( i + 1 ), src="hda", id=hda[ "id" ] )
+ # Contents can be a list of strings (with name auto-assigned here) or a list of
+ # 2-tuples of form (name, dataset_content).
+ if contents and isinstance(contents[0], tuple):
+ hdas = self.__datasets( history_id, count=count, contents=[c[1] for c in contents] )
+ hda_to_identifier = lambda ( i, hda ): dict( name=contents[i][0], src="hda", id=hda[ "id" ] )
+ else:
+ hdas = self.__datasets( history_id, count=count, contents=contents )
+ hda_to_identifier = lambda ( i, hda ): dict( name="data%d" % ( i + 1 ), src="hda", id=hda[ "id" ] )
element_identifiers = map( hda_to_identifier, enumerate( hdas ) )
return element_identifiers
diff -r c692332612dd5c8d7eff798cdba4f2e91d4ff5a1 -r f36c6fc80e8cd2bc6a5c6f77f0806aa7271e65f0 test/api/test_workflow_matching_lists.ga
--- /dev/null
+++ b/test/api/test_workflow_matching_lists.ga
@@ -0,0 +1,117 @@
+{
+ "a_galaxy_workflow": "true",
+ "annotation": "",
+ "format-version": "0.1",
+ "name": "test_workflow_matching_lists",
+ "steps": {
+ "0": {
+ "annotation": "",
+ "id": 0,
+ "input_connections": {},
+ "inputs": [
+ {
+ "description": "",
+ "name": "list1"
+ }
+ ],
+ "name": "Input dataset collection",
+ "outputs": [],
+ "position": {
+ "left": 139.833336353302,
+ "top": 162.33334398269653
+ },
+ "tool_errors": null,
+ "tool_id": null,
+ "tool_state": "{\"collection_type\": \"list\", \"name\": \"list1\"}",
+ "tool_version": null,
+ "type": "data_collection_input",
+ "user_outputs": []
+ },
+ "1": {
+ "annotation": "",
+ "id": 1,
+ "input_connections": {},
+ "inputs": [
+ {
+ "description": "",
+ "name": "list2"
+ }
+ ],
+ "name": "Input dataset collection",
+ "outputs": [],
+ "position": {
+ "left": 141.864586353302,
+ "top": 272.3680577278137
+ },
+ "tool_errors": null,
+ "tool_id": null,
+ "tool_state": "{\"collection_type\": \"list\", \"name\": \"list2\"}",
+ "tool_version": null,
+ "type": "data_collection_input",
+ "user_outputs": []
+ },
+ "2": {
+ "annotation": "",
+ "id": 2,
+ "input_connections": {
+ "input1": {
+ "id": 0,
+ "output_name": "output"
+ },
+ "queries_0|input2": {
+ "id": 1,
+ "output_name": "output"
+ }
+ },
+ "inputs": [],
+ "name": "Concatenate datasets (for test workflows)",
+ "outputs": [
+ {
+ "name": "out_file1",
+ "type": "input"
+ }
+ ],
+ "position": {
+ "left": 453.40974473953247,
+ "top": 203.4097294807434
+ },
+ "post_job_actions": {},
+ "tool_errors": null,
+ "tool_id": "cat",
+ "tool_state": "{\"__page__\": 0, \"__rerun_remap_job_id__\": null, \"input1\": \"null\", \"queries\": \"[{\\\"input2\\\": null, \\\"__index__\\\": 0}]\"}",
+ "tool_version": "1.0.0",
+ "type": "tool",
+ "user_outputs": []
+ },
+ "3": {
+ "annotation": "",
+ "id": 3,
+ "input_connections": {
+ "input1": {
+ "id": 2,
+ "output_name": "out_file1"
+ }
+ },
+ "inputs": [],
+ "name": "Concatenate dataset list (for test workflows)",
+ "outputs": [
+ {
+ "name": "out_file1",
+ "type": "input"
+ }
+ ],
+ "position": {
+ "left": 828.93061876297,
+ "top": 217.4201512336731
+ },
+ "post_job_actions": {},
+ "tool_errors": null,
+ "tool_id": "cat_list",
+ "tool_state": "{\"__page__\": 0, \"__rerun_remap_job_id__\": null, \"input1\": \"null\"}",
+ "tool_version": "1.0.0",
+ "type": "tool",
+ "user_outputs": []
+ }
+ },
+ "uuid": "54aadd3b-9d2b-436a-acfa-246a8c251651"
+}
\ No newline at end of file
diff -r c692332612dd5c8d7eff798cdba4f2e91d4ff5a1 -r f36c6fc80e8cd2bc6a5c6f77f0806aa7271e65f0 test/api/test_workflows.py
--- a/test/api/test_workflows.py
+++ b/test/api/test_workflows.py
@@ -149,6 +149,26 @@
run_workflow_response = self._post( "workflows", data=workflow_request )
self._assert_status_code_is( run_workflow_response, 403 )
+ @skip_without_tool( "cat" )
+ @skip_without_tool( "cat_list" )
+ def test_workflow_run_with_matching_lists( self ):
+ workflow = self.workflow_populator.load_workflow_from_resource( "test_workflow_matching_lists" )
+ workflow_id = self.workflow_populator.create_workflow( workflow )
+ history_id = self.dataset_populator.new_history()
+ hdca1 = self.dataset_collection_populator.create_list_in_history( history_id, contents=[("sample1-1", "1 2 3"), ("sample2-1", "7 8 9")] ).json()
+ hdca2 = self.dataset_collection_populator.create_list_in_history( history_id, contents=[("sample1-2", "4 5 6"), ("sample2-2", "0 a b")] ).json()
+ self.dataset_populator.wait_for_history( history_id, assert_ok=True )
+ label_map = { "list1": self._ds_entry( hdca1 ), "list2": self._ds_entry( hdca2 ) }
+ workflow_request = dict(
+ history="hist_id=%s" % history_id,
+ workflow_id=workflow_id,
+ ds_map=self._build_ds_map( workflow_id, label_map ),
+ )
+ 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("1 2 3\n4 5 6\n7 8 9\n0 a b\n", self.dataset_populator.get_history_dataset_content( history_id ) )
+
def test_workflow_stability( self ):
# Run this index stability test with following command:
# ./run_tests.sh test/api/test_workflows.py:WorkflowsApiTestCase.test_workflow_stability
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: UI, Paired collection creator: fixes and refactoring, allow pairs to be selected
by commits-noreply@bitbucket.org 27 Aug '14
by commits-noreply@bitbucket.org 27 Aug '14
27 Aug '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/a66a80701913/
Changeset: a66a80701913
User: carlfeberhard
Date: 2014-08-27 20:47:54
Summary: UI, Paired collection creator: fixes and refactoring, allow pairs to be selected
Affected #: 4 files
diff -r 5a7a7003fbc3bc8f9d56f18a8d4b8f2d5b28fe42 -r a66a80701913bb99e8abd12235c1ca82dc508f57 static/scripts/mvc/collection/paired-collection-creator.js
--- a/static/scripts/mvc/collection/paired-collection-creator.js
+++ b/static/scripts/mvc/collection/paired-collection-creator.js
@@ -5,10 +5,18 @@
], function( levelshteinDistance, baseMVC, _l ){
/* ============================================================================
TODO:
+ _adjPairedOnScrollBar
+ parition drag now doesn't stop when dragging down
+ can push footer out of modal
+ only *after* partition is all the way down once?
PROGRAMMATICALLY:
-h = Galaxy.currHistoryPanel; h.showSelectors(); h.selectAllDatasets(); _.last( h.actionsPopup.options ).func()
+currPanel.once( 'rendered', function(){
+ currPanel.showSelectors();
+ currPanel.selectAllDatasets();
+ _.last( currPanel.actionsPopup.options ).func();
+});
============================================================================ */
/** A view for paired datasets in the collections creator.
@@ -26,7 +34,9 @@
this.$el.attr( 'draggable', true )
.html( _.template([
'<span class="forward-dataset-name flex-column"><%= pair.forward.name %></span>',
- '<span class="pair-name flex-column"><%= pair.name %></span>',
+ '<span class="pair-name-column flex-column">',
+ '<span class="pair-name"><%= pair.name %></span>',
+ '</span>',
'<span class="reverse-dataset-name flex-column"><%= pair.reverse.name %></span>'
].join(''), { pair: this.pair }))
.addClass( 'flex-column-container' );
@@ -661,8 +671,6 @@
return;
}
- //this.$( '.unpaired-columns .forward-column' ).lassoable({});
-
// create the dataset dom arrays
$rev = split[1].map( function( dataset, i ){
// if there'll be a fwd dataset across the way, add a button to pair the row
@@ -685,6 +693,7 @@
this.$( '.unpaired-columns .forward-column .column-datasets' ).append( $fwd )
.add( this.$( '.unpaired-columns .paired-column .column-datasets' ).append( $prd ) )
.add( this.$( '.unpaired-columns .reverse-column .column-datasets' ).append( $rev ) );
+ this._adjUnpairedOnScrollbar();
},
/** return a string to display the count of filtered out datasets */
_renderUnpairedDisplayStr : function( numFiltered ){
@@ -724,6 +733,18 @@
this.$( '.unpaired-columns .paired-column .column-datasets' ).empty().prepend( $msg );
return $msg;
},
+ /** try to detect if the unpaired section has a scrollbar and adjust left column for better centering of all */
+ _adjUnpairedOnScrollbar : function(){
+ var $unpairedColumns = this.$( '.unpaired-columns' ).last(),
+ $firstDataset = this.$( '.unpaired-columns .reverse-column .dataset' ).first();
+ if( !$firstDataset.size() ){ return; }
+ var ucRight = $unpairedColumns.offset().left + $unpairedColumns.outerWidth(),
+ dsRight = $firstDataset.offset().left + $firstDataset.outerWidth(),
+ rightDiff = Math.floor( ucRight ) - Math.floor( dsRight );
+ //this.debug( 'rightDiff:', ucRight, '-', dsRight, '=', rightDiff );
+ this.$( '.unpaired-columns .forward-column' )
+ .css( 'margin-left', ( rightDiff > 0 )? rightDiff: 0 );
+ },
/** render the paired section and update counts of paired datasets */
_renderPaired : function( speed, callback ){
@@ -907,6 +928,7 @@
'click .paired-column-title' : '_clickShowOnlyPaired',
'mousedown .flexible-partition-drag' : '_startPartitionDrag',
// paired
+ 'click .paired-columns .dataset.paired' : 'selectPair',
'click .paired-columns .pair-name' : '_clickPairName',
'click .unpair-btn' : '_clickUnpair',
@@ -965,28 +987,23 @@
this.splitView();
}
},
+
/** hide unpaired, show paired */
hideUnpaired : function( speed, callback ){
- speed = speed || 0;
- this.$( '.unpaired-columns' ).hide( speed, callback );
- //this.$( '.unpaired-filter' ).hide( speed );
- this.$( '.paired-columns' ).show( speed ).css( 'flex', '1 0 auto' );
this.unpairedPanelHidden = true;
+ this.pairedPanelHidden = false;
+ this._renderMiddle( speed, callback );
},
/** hide paired, show unpaired */
hidePaired : function( speed, callback ){
- speed = speed || 0;
- this.$( '.unpaired-columns' ).show( speed ).css( 'flex', '1 0 auto' );
- //this.$( '.unpaired-filter' ).show( speed );
- this.$( '.paired-columns' ).hide( speed, callback );
+ this.unpairedPanelHidden = false;
this.pairedPanelHidden = true;
+ this._renderMiddle( speed, callback );
},
/** show both paired and unpaired (splitting evenly) */
splitView : function( speed, callback ){
- speed = speed || 0;
this.unpairedPanelHidden = this.pairedPanelHidden = false;
- //this.$( '.unpaired-filter' ).show( speed );
- this._renderMiddle( speed );
+ this._renderMiddle( speed, callback );
return this;
},
@@ -1148,6 +1165,7 @@
//creator.debug( 'mouseup triggered' );
$( 'body' ).trigger( 'mouseup' );
}
+ creator._adjUnpairedOnScrollbar();
startingY += offset;
}
$( 'body' ).mousemove( trackMouse );
@@ -1165,29 +1183,37 @@
unpairedHi = Math.max( 10, unpairedHi + adj );
pairedHi = pairedHi - adj;
- //TODO: seems like shouldn't need this (it should be part of the hide/show/splitView)
- if( unpairedHi <= 10 ){
- if( !this.unpairedPanelHidden ){
+//TODO: seems like shouldn't need this (it should be part of the hide/show/splitView)
+ var movingUpwards = adj < 0;
+ // when the divider gets close to the top - lock into hiding the unpaired section
+ if( movingUpwards ){
+ if( this.unpairedPanelHidden ){
+ return false;
+ } else if( unpairedHi <= 10 ){
this.hideUnpaired();
return false;
}
-
- } else if( this.unpairedPanelHidden ){
- $unpaired.show();
- this.unpairedPanelHidden = false;
+ } else {
+ if( this.unpairedPanelHidden ){
+ $unpaired.show();
+ this.unpairedPanelHidden = false;
+ }
}
// when the divider gets close to the bottom - lock into hiding the paired section
- if( pairedHi <= 15 ){
- if( !this.pairedPanelHidden ){
+ if( !movingUpwards ){
+ if( this.pairedPanelHidden ){
+ return false;
+ } else if( pairedHi <= 15 ){
this.hidePaired();
- if( pairedHi < 5 ){ return false; }
+ return false;
}
- // when the divider gets close to the bottom and the paired section is hidden
- } else if( this.pairedPanelHidden ){
- $paired.show();
- this.pairedPanelHidden = false;
+ } else {
+ if( this.pairedPanelHidden ){
+ $paired.show();
+ this.pairedPanelHidden = false;
+ }
}
$unpaired.css({
@@ -1198,8 +1224,14 @@
},
// ........................................................................ paired
+ /** select a pair when clicked */
+ selectPair : function( ev ){
+ $( ev.currentTarget ).toggleClass( 'selected' );
+ },
+
/** rename a pair when the pair name is clicked */
_clickPairName : function( ev ){
+ ev.stopPropagation();
var $control = $( ev.currentTarget ),
pair = this.paired[ $control.parent().index() ],
response = prompt( 'Enter a new name for the pair:', pair.name );
diff -r 5a7a7003fbc3bc8f9d56f18a8d4b8f2d5b28fe42 -r a66a80701913bb99e8abd12235c1ca82dc508f57 static/scripts/packed/mvc/collection/paired-collection-creator.js
--- a/static/scripts/packed/mvc/collection/paired-collection-creator.js
+++ b/static/scripts/packed/mvc/collection/paired-collection-creator.js
@@ -1,1 +1,1 @@
-define(["utils/levenshtein","mvc/base-mvc","utils/localization"],function(g,a,d){var f=Backbone.View.extend(a.LoggableMixin).extend({tagName:"li",className:"dataset paired",initialize:function(h){this.pair=h.pair||{}},render:function(){this.$el.attr("draggable",true).html(_.template(['<span class="forward-dataset-name flex-column"><%= pair.forward.name %></span>','<span class="pair-name flex-column"><%= pair.name %></span>','<span class="reverse-dataset-name flex-column"><%= pair.reverse.name %></span>'].join(""),{pair:this.pair})).addClass("flex-column-container");return this}});var e=Backbone.View.extend(a.LoggableMixin).extend({className:"collection-creator flex-row-container",initialize:function(h){h=_.defaults(h,{datasets:[],filters:this.DEFAULT_FILTERS,automaticallyPair:true,matchPercentage:1,strategy:"lcs"});this.initialList=h.datasets;this.historyId=h.historyId;this.filters=this.commonFilters[h.filters]||this.commonFilters[this.DEFAULT_FILTERS];if(_.isArray(h.filters)){this.filters=h.filters}this.automaticallyPair=h.automaticallyPair;this.matchPercentage=h.matchPercentage;this.strategy=this.strategies[h.strategy]||this.strategies[this.DEFAULT_STRATEGY];if(_.isFunction(h.strategy)){this.strategy=h.strategy}this.removeExtensions=true;this.oncancel=h.oncancel;this.oncreate=h.oncreate;this.unpairedPanelHidden=false;this.pairedPanelHidden=false;this._dataSetUp();this._setUpBehaviors()},commonFilters:{none:["",""],illumina:["_1","_2"]},DEFAULT_FILTERS:"illumina",strategies:{lcs:"autoPairLCSs",levenshtein:"autoPairLevenshtein"},DEFAULT_STRATEGY:"lcs",_dataSetUp:function(){this.paired=[];this.unpaired=[];this.selectedIds=[];this._sortInitialList();this._ensureIds();this.unpaired=this.initialList.slice(0);if(this.automaticallyPair){this.autoPair()}},_sortInitialList:function(){this._sortDatasetList(this.initialList)},_sortDatasetList:function(h){h.sort(function(j,i){return naturalSort(j.name,i.name)});return h},_ensureIds:function(){this.initialList.forEach(function(h){if(!h.hasOwnProperty("id")){h.id=_.uniqueId()}});return this.initialList},_splitByFilters:function(j){var i=[],h=[];this.unpaired.forEach(function(k){if(this._filterFwdFn(k)){i.push(k)}if(this._filterRevFn(k)){h.push(k)}}.bind(this));return[i,h]},_filterFwdFn:function(i){var h=new RegExp(this.filters[0]);return h.test(i.name)},_filterRevFn:function(i){var h=new RegExp(this.filters[1]);return h.test(i.name)},_addToUnpaired:function(i){var h=function(j,l){if(j===l){return j}var k=Math.floor((l-j)/2)+j,m=naturalSort(i.name,this.unpaired[k].name);if(m<0){return h(j,k)}else{if(m>0){return h(k+1,l)}}while(this.unpaired[k]&&this.unpaired[k].name===i.name){k++}return k}.bind(this);this.unpaired.splice(h(0,this.unpaired.length),0,i)},autoPair:function(h){h=h||this.strategy;this.simpleAutoPair();return this[h].call(this)},simpleAutoPair:function(){var n=0,l,r=this._splitByFilters(),h=r[0],q=r[1],p,s,k=false;while(n<h.length){var m=h[n];p=m.name.replace(this.filters[0],"");k=false;for(l=0;l<q.length;l++){var o=q[l];s=o.name.replace(this.filters[1],"");if(m!==o&&p===s){k=true;this._pair(h.splice(n,1)[0],q.splice(l,1)[0],{silent:true});break}}if(!k){n+=1}}},autoPairLevenshtein:function(){var o=0,m,t=this._splitByFilters(),h=t[0],r=t[1],q,v,k,s,l;while(o<h.length){var n=h[o];q=n.name.replace(this.filters[0],"");l=Number.MAX_VALUE;for(m=0;m<r.length;m++){var p=r[m];v=p.name.replace(this.filters[1],"");if(n!==p){if(q===v){s=m;l=0;break}k=levenshteinDistance(q,v);if(k<l){s=m;l=k}}}var u=1-(l/(Math.max(q.length,v.length)));if(u>=this.matchPercentage){this._pair(h.splice(o,1)[0],r.splice(s,1)[0],{silent:true});if(h.length<=0||r.length<=0){return}}else{o+=1}}},autoPairLCSs:function(){var m=0,k,t=this._splitByFilters(),h=t[0],r=t[1],q,w,v,s,o;if(!h.length||!r.length){return}while(m<h.length){var l=h[m];q=l.name.replace(this.filters[0],"");o=0;for(k=0;k<r.length;k++){var p=r[k];w=p.name.replace(this.filters[1],"");if(l!==p){if(q===w){s=k;o=q.length;break}var n=this._naiveStartingAndEndingLCS(q,w);v=n.length;if(v>o){s=k;o=v}}}var u=o/(Math.min(q.length,w.length));if(u>=this.matchPercentage){this._pair(h.splice(m,1)[0],r.splice(s,1)[0],{silent:true});if(h.length<=0||r.length<=0){return}}else{m+=1}}},_naiveStartingAndEndingLCS:function(m,k){var n="",o="",l=0,h=0;while(l<m.length&&l<k.length){if(m[l]!==k[l]){break}n+=m[l];l+=1}if(l===m.length){return m}if(l===k.length){return k}l=(m.length-1);h=(k.length-1);while(l>=0&&h>=0){if(m[l]!==k[h]){break}o=[m[l],o].join("");l-=1;h-=1}return n+o},_pair:function(j,h,i){i=i||{};var k=this._createPair(j,h,i.name);this.paired.push(k);this.unpaired=_.without(this.unpaired,j,h);if(!i.silent){this.trigger("pair:new",k)}return k},_createPair:function(j,h,i){if(!(j&&h)||(j===h)){throw new Error("Bad pairing: "+[JSON.stringify(j),JSON.stringify(h)])}i=i||this._guessNameForPair(j,h);return{forward:j,name:i,reverse:h}},_guessNameForPair:function(j,h,k){k=(k!==undefined)?(k):(this.removeExtensions);var i=this._naiveStartingAndEndingLCS(j.name.replace(this.filters[0],""),h.name.replace(this.filters[1],""));if(k){var l=i.lastIndexOf(".");if(l>0){i=i.slice(0,l)}}return i||(j.name+" & "+h.name)},_unpair:function(i,h){h=h||{};if(!i){throw new Error("Bad pair: "+JSON.stringify(i))}this.paired=_.without(this.paired,i);this._addToUnpaired(i.forward);this._addToUnpaired(i.reverse);if(!h.silent){this.trigger("pair:unpair",[i])}return i},unpairAll:function(){var h=[];while(this.paired.length){h.push(this._unpair(this.paired[0],{silent:true}))}this.trigger("pair:unpair",h)},_pairToJSON:function(h){return{collection_type:"paired",src:"new_collection",name:h.name,element_identifiers:[{name:"forward",id:h.forward.id,src:"hda"},{name:"reverse",id:h.reverse.id,src:"hda"}]}},createList:function(){var j=this,i;if(j.historyId){i="/api/histories/"+this.historyId+"/contents/dataset_collections"}var h={type:"dataset_collection",collection_type:"list:paired",name:_.escape(j.$(".collection-name").val()),element_identifiers:j.paired.map(function(k){return j._pairToJSON(k)})};return jQuery.ajax(i,{type:"POST",contentType:"application/json",dataType:"json",data:JSON.stringify(h)}).fail(function(m,k,l){j._ajaxErrHandler(m,k,l)}).done(function(k,l,m){j.trigger("collection:created",k,l,m);if(typeof j.oncreate==="function"){j.oncreate.call(this,k,l,m)}})},_ajaxErrHandler:function(k,h,j){this.error(k,h,j);var i=d("An error occurred while creating this collection");if(k){if(k.readyState===0&&k.status===0){i+=": "+d("Galaxy could not be reached and may be updating.")+d(" Try again in a few minutes.")}else{if(k.responseJSON){i+="<br /><pre>"+JSON.stringify(k.responseJSON)+"</pre>"}else{i+=": "+j}}}creator._showAlert(i,"alert-danger")},render:function(h,i){this.$el.empty().html(e.templates.main());this._renderHeader(h);this._renderMiddle(h);this._renderFooter(h);this._addPluginComponents();return this},_renderHeader:function(i,j){var h=this.$(".header").empty().html(e.templates.header()).find(".help-content").prepend($(e.templates.helpContent()));this._renderFilters();return h},_renderFilters:function(){return this.$(".forward-column .column-header input").val(this.filters[0]).add(this.$(".reverse-column .column-header input").val(this.filters[1]))},_renderMiddle:function(i,j){var h=this.$(".middle").empty().html(e.templates.middle());if(this.unpairedPanelHidden){this.$(".unpaired-columns").hide()}else{if(this.pairedPanelHidden){this.$(".paired-columns").hide()}}this._renderUnpaired();this._renderPaired();return h},_renderUnpaired:function(m,n){var k=this,l,i,h=[],j=this._splitByFilters();this.$(".forward-column .title").text([j[0].length,d("unpaired forward")].join(" "));this.$(".forward-column .unpaired-info").text(this._renderUnpairedDisplayStr(this.unpaired.length-j[0].length));this.$(".reverse-column .title").text([j[1].length,d("unpaired reverse")].join(" "));this.$(".reverse-column .unpaired-info").text(this._renderUnpairedDisplayStr(this.unpaired.length-j[1].length));this.$(".unpaired-columns .column-datasets").empty();this.$(".autopair-link").toggle(this.unpaired.length!==0);if(this.unpaired.length===0){this._renderUnpairedEmpty();return}i=j[1].map(function(p,o){if((j[0][o]!==undefined)&&(j[0][o]!==p)){h.push(k._renderPairButton())}return k._renderUnpairedDataset(p)});l=j[0].map(function(o){return k._renderUnpairedDataset(o)});if(!l.length&&!i.length){this._renderUnpairedNotShown();return}this.$(".unpaired-columns .forward-column .column-datasets").append(l).add(this.$(".unpaired-columns .paired-column .column-datasets").append(h)).add(this.$(".unpaired-columns .reverse-column .column-datasets").append(i))},_renderUnpairedDisplayStr:function(h){return["(",h," ",d("filtered out"),")"].join("")},_renderUnpairedDataset:function(h){return $("<li/>").attr("id","dataset-"+h.id).addClass("dataset unpaired").attr("draggable",true).addClass(h.selected?"selected":"").append($("<span/>").addClass("dataset-name").text(h.name)).data("dataset",h)},_renderPairButton:function(){return $("<li/>").addClass("dataset unpaired").append($("<span/>").addClass("dataset-name").text(d("Pair these datasets")))},_renderUnpairedEmpty:function(){var h=$('<div class="empty-message"></div>').text("("+d("no remaining unpaired datasets")+")");this.$(".unpaired-columns .paired-column .column-datasets").empty().prepend(h);return h},_renderUnpairedNotShown:function(){var h=$('<div class="empty-message"></div>').text("("+d("no datasets were found matching the current filters")+")");this.$(".unpaired-columns .paired-column .column-datasets").empty().prepend(h);return h},_renderPaired:function(i,j){this.$(".paired-column-title .title").text([this.paired.length,d("paired")].join(" "));this.$(".unpair-all-link").toggle(this.paired.length!==0);if(this.paired.length===0){this._renderPairedEmpty();return}else{this.$(".remove-extensions-link").show()}this.$(".paired-columns .column-datasets").empty();var h=this;this.paired.forEach(function(m,k){var l=new f({pair:m});h.$(".paired-columns .column-datasets").append(l.render().$el).append(['<button class="unpair-btn">','<span class="fa fa-unlink" title="',d("Unpair"),'"></span>',"</button>"].join(""))})},_renderPairedEmpty:function(){var h=$('<div class="empty-message"></div>').text("("+d("no paired datasets yet")+")");this.$(".paired-columns .column-datasets").empty().prepend(h);return h},_renderFooter:function(i,j){var h=this.$(".footer").empty().html(e.templates.footer());this.$(".remove-extensions").prop("checked",this.removeExtensions);if(typeof this.oncancel==="function"){this.$(".cancel-create.btn").show()}return h},_addPluginComponents:function(){this._chooseFiltersPopover(".choose-filters-link");this.$(".help-content i").hoverhighlight(".collection-creator","rgba( 64, 255, 255, 1.0 )")},_chooseFiltersPopover:function(h){function i(l,k){return['<button class="filter-choice btn" ','data-forward="',l,'" data-reverse="',k,'">',d("Forward"),": ",l,", ",d("Reverse"),": ",k,"</button>"].join("")}var j=$(_.template(['<div class="choose-filters">','<div class="help">',d("Choose from the following filters to change which unpaired reads are shown in the display"),":</div>",i("_1","_2"),i("_R1","_R2"),"</div>"].join(""),{}));return this.$(h).popover({container:".collection-creator",placement:"bottom",html:true,content:j})},_validationWarning:function(i,h){var j="validation-warning";if(i==="name"){i=this.$(".collection-name").add(this.$(".collection-name-prompt"));this.$(".collection-name").focus().select()}if(h){i=i||this.$("."+j);i.removeClass(j)}else{i.addClass(j)}},_setUpBehaviors:function(){this.on("pair:new",function(){this._renderUnpaired();this._renderPaired();this.$(".paired-columns").scrollTop(8000000)});this.on("pair:unpair",function(h){this._renderUnpaired();this._renderPaired();this.splitView()});this.on("filter-change",function(){this.filters=[this.$(".forward-unpaired-filter input").val(),this.$(".reverse-unpaired-filter input").val()];this._renderFilters();this._renderUnpaired()});this.on("autopair",function(){this._renderUnpaired();this._renderPaired();var h,i=null;if(this.paired.length){i="alert-success";h=this.paired.length+" "+d("pairs created");if(!this.unpaired.length){h+=": "+d("all datasets have been successfully paired");this.hideUnpaired()}}else{h=d("Could not automatically create any pairs from the given dataset names")}this._showAlert(h,i)});return this},events:{"click .more-help":"_clickMoreHelp","click .less-help":"_clickLessHelp","click .header .alert button":"_hideAlert","click .forward-column .column-title":"_clickShowOnlyUnpaired","click .reverse-column .column-title":"_clickShowOnlyUnpaired","click .unpair-all-link":"_clickUnpairAll","change .forward-unpaired-filter input":function(h){this.trigger("filter-change")},"focus .forward-unpaired-filter input":function(h){$(h.currentTarget).select()},"click .autopair-link":"_clickAutopair","click .choose-filters .filter-choice":"_clickFilterChoice","click .clear-filters-link":"_clearFilters","change .reverse-unpaired-filter input":function(h){this.trigger("filter-change")},"focus .reverse-unpaired-filter input":function(h){$(h.currentTarget).select()},"click .forward-column .dataset.unpaired":"_clickUnpairedDataset","click .reverse-column .dataset.unpaired":"_clickUnpairedDataset","click .paired-column .dataset.unpaired":"_clickPairRow","click .unpaired-columns":"clearSelectedUnpaired","mousedown .unpaired-columns .dataset":"_mousedownUnpaired","click .paired-column-title":"_clickShowOnlyPaired","mousedown .flexible-partition-drag":"_startPartitionDrag","click .paired-columns .pair-name":"_clickPairName","click .unpair-btn":"_clickUnpair","change .remove-extensions":function(h){this.toggleExtensions()},"change .collection-name":"_changeName","click .cancel-create":function(h){if(typeof this.oncancel==="function"){this.oncancel.call(this)}},"click .create-collection":"_clickCreate"},_clickMoreHelp:function(h){this.$(".main-help").addClass("expanded");this.$(".more-help").hide()},_clickLessHelp:function(h){this.$(".main-help").removeClass("expanded");this.$(".more-help").show()},_showAlert:function(i,h){h=h||"alert-danger";this.$(".main-help").hide();this.$(".header .alert").attr("class","alert alert-dismissable").addClass(h).show().find(".alert-message").html(i)},_hideAlert:function(h){this.$(".main-help").show();this.$(".header .alert").hide()},_clickShowOnlyUnpaired:function(h){if(this.$(".paired-columns").is(":visible")){this.hidePaired()}else{this.splitView()}},_clickShowOnlyPaired:function(h){if(this.$(".unpaired-columns").is(":visible")){this.hideUnpaired()}else{this.splitView()}},hideUnpaired:function(h,i){h=h||0;this.$(".unpaired-columns").hide(h,i);this.$(".paired-columns").show(h).css("flex","1 0 auto");this.unpairedPanelHidden=true},hidePaired:function(h,i){h=h||0;this.$(".unpaired-columns").show(h).css("flex","1 0 auto");this.$(".paired-columns").hide(h,i);this.pairedPanelHidden=true},splitView:function(h,i){h=h||0;this.unpairedPanelHidden=this.pairedPanelHidden=false;this._renderMiddle(h);return this},_clickUnpairAll:function(h){this.unpairAll()},_clickAutopair:function(i){var h=this.autoPair();this.trigger("autopair",h)},_clickFilterChoice:function(i){var h=$(i.currentTarget);this.$(".forward-unpaired-filter input").val(h.data("forward"));this.$(".reverse-unpaired-filter input").val(h.data("reverse"));this._hideChooseFilters();this.trigger("filter-change")},_hideChooseFilters:function(){this.$(".choose-filters-link").popover("hide");this.$(".popover").css("display","none")},_clearFilters:function(h){this.$(".forward-unpaired-filter input").val("");this.$(".reverse-unpaired-filter input").val("");this.trigger("filter-change")},_clickUnpairedDataset:function(h){h.stopPropagation();return this.toggleSelectUnpaired($(h.currentTarget))},toggleSelectUnpaired:function(j,i){i=i||{};var k=j.data("dataset"),h=i.force!==undefined?i.force:!j.hasClass("selected");if(!j.size()||k===undefined){return j}if(h){j.addClass("selected");if(!i.waitToPair){this.pairAllSelected()}}else{j.removeClass("selected")}return j},pairAllSelected:function(i){i=i||{};var j=this,k=[],h=[],l=[];j.$(".unpaired-columns .forward-column .dataset.selected").each(function(){k.push($(this).data("dataset"))});j.$(".unpaired-columns .reverse-column .dataset.selected").each(function(){h.push($(this).data("dataset"))});k.length=h.length=Math.min(k.length,h.length);k.forEach(function(n,m){try{l.push(j._pair(n,h[m],{silent:true}))}catch(o){j.error(o)}});if(l.length&&!i.silent){this.trigger("pair:new",l)}return l},clearSelectedUnpaired:function(){this.$(".unpaired-columns .dataset.selected").removeClass("selected")},_mousedownUnpaired:function(j){if(j.shiftKey){var i=this,h=$(j.target).addClass("selected"),k=function(l){i.$(l.target).filter(".dataset").addClass("selected")};h.parent().on("mousemove",k);$(document).one("mouseup",function(l){h.parent().off("mousemove",k);i.pairAllSelected()})}},_clickPairRow:function(j){var k=$(j.currentTarget).index(),i=$(".unpaired-columns .forward-column .dataset").eq(k).data("dataset"),h=$(".unpaired-columns .reverse-column .dataset").eq(k).data("dataset");this._pair(i,h)},_startPartitionDrag:function(i){var h=this,l=i.pageY;$("body").css("cursor","ns-resize");h.$(".flexible-partition-drag").css("color","black");function k(m){h.$(".flexible-partition-drag").css("color","");$("body").css("cursor","").unbind("mousemove",j)}function j(m){var n=m.pageY-l;if(!h.adjPartition(n)){$("body").trigger("mouseup")}l+=n}$("body").mousemove(j);$("body").one("mouseup",k)},adjPartition:function(i){var h=this.$(".unpaired-columns"),j=this.$(".paired-columns"),k=parseInt(h.css("height"),10),l=parseInt(j.css("height"),10);k=Math.max(10,k+i);l=l-i;if(k<=10){if(!this.unpairedPanelHidden){this.hideUnpaired();return false}}else{if(this.unpairedPanelHidden){h.show();this.unpairedPanelHidden=false}}if(l<=15){if(!this.pairedPanelHidden){this.hidePaired();if(l<5){return false}}}else{if(this.pairedPanelHidden){j.show();this.pairedPanelHidden=false}}h.css({height:k+"px",flex:"0 0 auto"});return true},_clickPairName:function(j){var i=$(j.currentTarget),k=this.paired[i.parent().index()],h=prompt("Enter a new name for the pair:",k.name);if(h){k.name=h;k.customizedName=true;i.text(k.name)}},_clickUnpair:function(i){var h=Math.floor($(i.currentTarget).index()/2);this._unpair(this.paired[h])},toggleExtensions:function(i){var h=this;h.removeExtensions=(i!==undefined)?(i):(!h.removeExtensions);_.each(h.paired,function(j){if(j.customizedName){return}j.name=h._guessNameForPair(j.forward,j.reverse)});h._renderPaired();h._renderFooter()},_changeName:function(h){this._validationWarning("name",!!this._getName())},_getName:function(){return _.escape(this.$(".collection-name").val())},_clickCreate:function(i){var h=this._getName();if(!h){this._validationWarning("name")}else{this.createList()}},_printList:function(i){var h=this;_.each(i,function(j){if(i===h.paired){h._printPair(j)}else{}})},_printPair:function(h){this.debug(h.forward.name,h.reverse.name,": ->",h.name)},toString:function(){return"PairedCollectionCreator"}});e.templates=e.templates||{main:_.template(['<div class="header flex-row no-flex"></div>','<div class="middle flex-row flex-row-container"></div>','<div class="footer flex-row no-flex">'].join("")),header:_.template(['<div class="main-help well clear">','<a class="more-help" href="javascript:void(0);">',d("More help"),"</a>",'<div class="help-content">','<a class="less-help" href="javascript:void(0);">',d("Less"),"</a>","</div>","</div>",'<div class="alert alert-dismissable">','<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>','<span class="alert-message"></span>',"</div>",'<div class="column-headers vertically-spaced flex-column-container">','<div class="forward-column flex-column column">','<div class="column-header">','<div class="column-title">','<span class="title">',d("Unpaired forward"),"</span>",'<span class="title-info unpaired-info"></span>',"</div>",'<div class="unpaired-filter forward-unpaired-filter pull-left">','<input class="search-query" placeholder="',d("Filter this list"),'" />',"</div>","</div>","</div>",'<div class="paired-column flex-column no-flex column">','<div class="column-header">','<a class="choose-filters-link" href="javascript:void(0)">',d("Choose filters"),"</a>",'<a class="clear-filters-link" href="javascript:void(0);">',d("Clear filters"),"</a><br />",'<a class="autopair-link" href="javascript:void(0);">',d("Auto-pair"),"</a>","</div>","</div>",'<div class="reverse-column flex-column column">','<div class="column-header">','<div class="column-title">','<span class="title">',d("Unpaired reverse"),"</span>",'<span class="title-info unpaired-info"></span>',"</div>",'<div class="unpaired-filter reverse-unpaired-filter pull-left">','<input class="search-query" placeholder="',d("Filter this list"),'" />',"</div>","</div>","</div>","</div>"].join("")),middle:_.template(['<div class="unpaired-columns flex-column-container scroll-container flex-row">','<div class="forward-column flex-column column">','<ol class="column-datasets"></ol>',"</div>",'<div class="paired-column flex-column no-flex column">','<ol class="column-datasets"></ol>',"</div>",'<div class="reverse-column flex-column column">','<ol class="column-datasets"></ol>',"</div>","</div>",'<div class="flexible-partition">','<div class="flexible-partition-drag" title="',d("Drag to change"),'"></div>','<div class="column-header">','<div class="column-title paired-column-title">','<span class="title"></span>',"</div>",'<a class="unpair-all-link" href="javascript:void(0);">',d("Unpair all"),"</a>","</div>","</div>",'<div class="paired-columns flex-column-container scroll-container flex-row">','<ol class="column-datasets"></ol>',"</div>"].join("")),footer:_.template(['<div class="attributes clear">','<div class="clear">','<label class="remove-extensions-prompt pull-right">',d("Remove file extensions from pair names"),"?",'<input class="remove-extensions pull-right" type="checkbox" />',"</label>","</div>",'<div class="clear">','<input class="collection-name form-control pull-right" ','placeholder="',d("Enter a name for your new list"),'" />','<div class="collection-name-prompt pull-right">',d("Name"),":</div>","</div>","</div>",'<div class="actions clear vertically-spaced">','<div class="other-options pull-left">','<button class="cancel-create btn" tabindex="-1">',d("Cancel"),"</button>",'<div class="create-other btn-group dropup">','<button class="btn btn-default dropdown-toggle" data-toggle="dropdown">',d("Create a different kind of collection"),' <span class="caret"></span>',"</button>",'<ul class="dropdown-menu" role="menu">','<li><a href="#">',d("Create a <i>single</i> pair"),"</a></li>",'<li><a href="#">',d("Create a list of <i>unpaired</i> datasets"),"</a></li>","</ul>","</div>","</div>",'<div class="main-options pull-right">','<button class="create-collection btn btn-primary">',d("Create list"),"</button>","</div>","</div>"].join("")),helpContent:_.template(["<p>",d(["Collections of paired datasets are ordered lists of dataset pairs (often forward and reverse reads). ","These collections can be passed to tools and workflows in order to have analyses done on each member of ","the entire group. This interface allows you to create a collection, choose which datasets are paired, ","and re-order the final collection."].join("")),"</p>","<p>",d(['Unpaired datasets are shown in the <i data-target=".unpaired-columns">unpaired section</i> ',"(hover over the underlined words to highlight below). ",'Paired datasets are shown in the <i data-target=".paired-columns">paired section</i>.',"<ul>To pair datasets, you can:","<li>Click a dataset in the ",'<i data-target=".unpaired-columns .forward-column .column-datasets,','.unpaired-columns .forward-column">forward column</i> ',"to select it then click a dataset in the ",'<i data-target=".unpaired-columns .reverse-column .column-datasets,','.unpaired-columns .reverse-column">reverse column</i>.',"</li>",'<li>Click one of the "Pair these datasets" buttons in the ','<i data-target=".unpaired-columns .paired-column .column-datasets,','.unpaired-columns .paired-column">middle column</i> ',"to pair the datasets in a particular row.","</li>",'<li>Click <i data-target=".autopair-link">"Auto-pair"</i> ',"to have your datasets automatically paired based on name.","</li>","</ul>"].join("")),"</p>","<p>",d(["<ul>You can filter what is shown in the unpaired sections by:","<li>Entering partial dataset names in either the ",'<i data-target=".forward-unpaired-filter input">forward filter</i> or ','<i data-target=".reverse-unpaired-filter input">reverse filter</i>.',"</li>","<li>Choosing from a list of preset filters by clicking the ",'<i data-target=".choose-filters-link">"Choose filters" link</i>.',"</li>","<li>Entering regular expressions to match dataset names. See: ",'<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expre…"',' target="_blank">MDN\'s JavaScript Regular Expression Tutorial</a>. ',"Note: forward slashes (\\) are not needed.","</li>","<li>Clearing the filters by clicking the ",'<i data-target=".clear-filters-link">"Clear filters" link</i>.',"</li>","</ul>"].join("")),"</p>","<p>",d(["To unpair individual dataset pairs, click the ",'<i data-target=".unpair-btn">unpair buttons ( <span class="fa fa-unlink"></span> )</i>. ','Click the <i data-target=".unpair-all-link">"Unpair all" link</i> to unpair all pairs.'].join("")),"</p>","<p>",d(['You can include or remove the file extensions (e.g. ".fastq") from your pair names by toggling the ','<i data-target=".remove-extensions-prompt">"Remove file extensions from pair names?"</i> control.'].join("")),"</p>","<p>",d(['Once your collection is complete, enter a <i data-target=".collection-name">name</i> and ','click <i data-target=".create-collection">"Create list"</i>. ',"(Note: you do not have to pair all unpaired datasets to finish.)"].join("")),"</p>"].join(""))};(function(){jQuery.fn.extend({hoverhighlight:function h(j,i){j=j||"body";if(!this.size()){return this}$(this).each(function(){var l=$(this),k=l.data("target");if(k){l.mouseover(function(m){$(k,j).css({background:i})}).mouseout(function(m){$(k).css({background:""})})}});return this}})}());var b=function c(j,h){h=_.defaults(h||{},{datasets:j,oncancel:function(){Galaxy.modal.hide()},oncreate:function(){Galaxy.modal.hide();Galaxy.currHistoryPanel.refreshContents()}});if(!window.Galaxy||!Galaxy.modal){throw new Error("Galaxy or Galaxy.modal not found")}var i=new e(h).render();Galaxy.modal.show({title:"Create a collection of paired datasets",body:i.$el,width:"80%",height:"800px",closing_events:true});window.PCC=i;return i};return{PairedCollectionCreator:e,pairedCollectionCreatorModal:b}});
\ No newline at end of file
+define(["utils/levenshtein","mvc/base-mvc","utils/localization"],function(g,a,d){var f=Backbone.View.extend(a.LoggableMixin).extend({tagName:"li",className:"dataset paired",initialize:function(h){this.pair=h.pair||{}},render:function(){this.$el.attr("draggable",true).html(_.template(['<span class="forward-dataset-name flex-column"><%= pair.forward.name %></span>','<span class="pair-name-column flex-column">','<span class="pair-name"><%= pair.name %></span>',"</span>",'<span class="reverse-dataset-name flex-column"><%= pair.reverse.name %></span>'].join(""),{pair:this.pair})).addClass("flex-column-container");return this}});var e=Backbone.View.extend(a.LoggableMixin).extend({className:"collection-creator flex-row-container",initialize:function(h){h=_.defaults(h,{datasets:[],filters:this.DEFAULT_FILTERS,automaticallyPair:true,matchPercentage:1,strategy:"lcs"});this.initialList=h.datasets;this.historyId=h.historyId;this.filters=this.commonFilters[h.filters]||this.commonFilters[this.DEFAULT_FILTERS];if(_.isArray(h.filters)){this.filters=h.filters}this.automaticallyPair=h.automaticallyPair;this.matchPercentage=h.matchPercentage;this.strategy=this.strategies[h.strategy]||this.strategies[this.DEFAULT_STRATEGY];if(_.isFunction(h.strategy)){this.strategy=h.strategy}this.removeExtensions=true;this.oncancel=h.oncancel;this.oncreate=h.oncreate;this.unpairedPanelHidden=false;this.pairedPanelHidden=false;this._dataSetUp();this._setUpBehaviors()},commonFilters:{none:["",""],illumina:["_1","_2"]},DEFAULT_FILTERS:"illumina",strategies:{lcs:"autoPairLCSs",levenshtein:"autoPairLevenshtein"},DEFAULT_STRATEGY:"lcs",_dataSetUp:function(){this.paired=[];this.unpaired=[];this.selectedIds=[];this._sortInitialList();this._ensureIds();this.unpaired=this.initialList.slice(0);if(this.automaticallyPair){this.autoPair()}},_sortInitialList:function(){this._sortDatasetList(this.initialList)},_sortDatasetList:function(h){h.sort(function(j,i){return naturalSort(j.name,i.name)});return h},_ensureIds:function(){this.initialList.forEach(function(h){if(!h.hasOwnProperty("id")){h.id=_.uniqueId()}});return this.initialList},_splitByFilters:function(j){var i=[],h=[];this.unpaired.forEach(function(k){if(this._filterFwdFn(k)){i.push(k)}if(this._filterRevFn(k)){h.push(k)}}.bind(this));return[i,h]},_filterFwdFn:function(i){var h=new RegExp(this.filters[0]);return h.test(i.name)},_filterRevFn:function(i){var h=new RegExp(this.filters[1]);return h.test(i.name)},_addToUnpaired:function(i){var h=function(j,l){if(j===l){return j}var k=Math.floor((l-j)/2)+j,m=naturalSort(i.name,this.unpaired[k].name);if(m<0){return h(j,k)}else{if(m>0){return h(k+1,l)}}while(this.unpaired[k]&&this.unpaired[k].name===i.name){k++}return k}.bind(this);this.unpaired.splice(h(0,this.unpaired.length),0,i)},autoPair:function(h){h=h||this.strategy;this.simpleAutoPair();return this[h].call(this)},simpleAutoPair:function(){var n=0,l,r=this._splitByFilters(),h=r[0],q=r[1],p,s,k=false;while(n<h.length){var m=h[n];p=m.name.replace(this.filters[0],"");k=false;for(l=0;l<q.length;l++){var o=q[l];s=o.name.replace(this.filters[1],"");if(m!==o&&p===s){k=true;this._pair(h.splice(n,1)[0],q.splice(l,1)[0],{silent:true});break}}if(!k){n+=1}}},autoPairLevenshtein:function(){var o=0,m,t=this._splitByFilters(),h=t[0],r=t[1],q,v,k,s,l;while(o<h.length){var n=h[o];q=n.name.replace(this.filters[0],"");l=Number.MAX_VALUE;for(m=0;m<r.length;m++){var p=r[m];v=p.name.replace(this.filters[1],"");if(n!==p){if(q===v){s=m;l=0;break}k=levenshteinDistance(q,v);if(k<l){s=m;l=k}}}var u=1-(l/(Math.max(q.length,v.length)));if(u>=this.matchPercentage){this._pair(h.splice(o,1)[0],r.splice(s,1)[0],{silent:true});if(h.length<=0||r.length<=0){return}}else{o+=1}}},autoPairLCSs:function(){var m=0,k,t=this._splitByFilters(),h=t[0],r=t[1],q,w,v,s,o;if(!h.length||!r.length){return}while(m<h.length){var l=h[m];q=l.name.replace(this.filters[0],"");o=0;for(k=0;k<r.length;k++){var p=r[k];w=p.name.replace(this.filters[1],"");if(l!==p){if(q===w){s=k;o=q.length;break}var n=this._naiveStartingAndEndingLCS(q,w);v=n.length;if(v>o){s=k;o=v}}}var u=o/(Math.min(q.length,w.length));if(u>=this.matchPercentage){this._pair(h.splice(m,1)[0],r.splice(s,1)[0],{silent:true});if(h.length<=0||r.length<=0){return}}else{m+=1}}},_naiveStartingAndEndingLCS:function(m,k){var n="",o="",l=0,h=0;while(l<m.length&&l<k.length){if(m[l]!==k[l]){break}n+=m[l];l+=1}if(l===m.length){return m}if(l===k.length){return k}l=(m.length-1);h=(k.length-1);while(l>=0&&h>=0){if(m[l]!==k[h]){break}o=[m[l],o].join("");l-=1;h-=1}return n+o},_pair:function(j,h,i){i=i||{};var k=this._createPair(j,h,i.name);this.paired.push(k);this.unpaired=_.without(this.unpaired,j,h);if(!i.silent){this.trigger("pair:new",k)}return k},_createPair:function(j,h,i){if(!(j&&h)||(j===h)){throw new Error("Bad pairing: "+[JSON.stringify(j),JSON.stringify(h)])}i=i||this._guessNameForPair(j,h);return{forward:j,name:i,reverse:h}},_guessNameForPair:function(j,h,k){k=(k!==undefined)?(k):(this.removeExtensions);var i=this._naiveStartingAndEndingLCS(j.name.replace(this.filters[0],""),h.name.replace(this.filters[1],""));if(k){var l=i.lastIndexOf(".");if(l>0){i=i.slice(0,l)}}return i||(j.name+" & "+h.name)},_unpair:function(i,h){h=h||{};if(!i){throw new Error("Bad pair: "+JSON.stringify(i))}this.paired=_.without(this.paired,i);this._addToUnpaired(i.forward);this._addToUnpaired(i.reverse);if(!h.silent){this.trigger("pair:unpair",[i])}return i},unpairAll:function(){var h=[];while(this.paired.length){h.push(this._unpair(this.paired[0],{silent:true}))}this.trigger("pair:unpair",h)},_pairToJSON:function(h){return{collection_type:"paired",src:"new_collection",name:h.name,element_identifiers:[{name:"forward",id:h.forward.id,src:"hda"},{name:"reverse",id:h.reverse.id,src:"hda"}]}},createList:function(){var j=this,i;if(j.historyId){i="/api/histories/"+this.historyId+"/contents/dataset_collections"}var h={type:"dataset_collection",collection_type:"list:paired",name:_.escape(j.$(".collection-name").val()),element_identifiers:j.paired.map(function(k){return j._pairToJSON(k)})};return jQuery.ajax(i,{type:"POST",contentType:"application/json",dataType:"json",data:JSON.stringify(h)}).fail(function(m,k,l){j._ajaxErrHandler(m,k,l)}).done(function(k,l,m){j.trigger("collection:created",k,l,m);if(typeof j.oncreate==="function"){j.oncreate.call(this,k,l,m)}})},_ajaxErrHandler:function(k,h,j){this.error(k,h,j);var i=d("An error occurred while creating this collection");if(k){if(k.readyState===0&&k.status===0){i+=": "+d("Galaxy could not be reached and may be updating.")+d(" Try again in a few minutes.")}else{if(k.responseJSON){i+="<br /><pre>"+JSON.stringify(k.responseJSON)+"</pre>"}else{i+=": "+j}}}creator._showAlert(i,"alert-danger")},render:function(h,i){this.$el.empty().html(e.templates.main());this._renderHeader(h);this._renderMiddle(h);this._renderFooter(h);this._addPluginComponents();return this},_renderHeader:function(i,j){var h=this.$(".header").empty().html(e.templates.header()).find(".help-content").prepend($(e.templates.helpContent()));this._renderFilters();return h},_renderFilters:function(){return this.$(".forward-column .column-header input").val(this.filters[0]).add(this.$(".reverse-column .column-header input").val(this.filters[1]))},_renderMiddle:function(i,j){var h=this.$(".middle").empty().html(e.templates.middle());if(this.unpairedPanelHidden){this.$(".unpaired-columns").hide()}else{if(this.pairedPanelHidden){this.$(".paired-columns").hide()}}this._renderUnpaired();this._renderPaired();return h},_renderUnpaired:function(m,n){var k=this,l,i,h=[],j=this._splitByFilters();this.$(".forward-column .title").text([j[0].length,d("unpaired forward")].join(" "));this.$(".forward-column .unpaired-info").text(this._renderUnpairedDisplayStr(this.unpaired.length-j[0].length));this.$(".reverse-column .title").text([j[1].length,d("unpaired reverse")].join(" "));this.$(".reverse-column .unpaired-info").text(this._renderUnpairedDisplayStr(this.unpaired.length-j[1].length));this.$(".unpaired-columns .column-datasets").empty();this.$(".autopair-link").toggle(this.unpaired.length!==0);if(this.unpaired.length===0){this._renderUnpairedEmpty();return}i=j[1].map(function(p,o){if((j[0][o]!==undefined)&&(j[0][o]!==p)){h.push(k._renderPairButton())}return k._renderUnpairedDataset(p)});l=j[0].map(function(o){return k._renderUnpairedDataset(o)});if(!l.length&&!i.length){this._renderUnpairedNotShown();return}this.$(".unpaired-columns .forward-column .column-datasets").append(l).add(this.$(".unpaired-columns .paired-column .column-datasets").append(h)).add(this.$(".unpaired-columns .reverse-column .column-datasets").append(i));this._adjUnpairedOnScrollbar()},_renderUnpairedDisplayStr:function(h){return["(",h," ",d("filtered out"),")"].join("")},_renderUnpairedDataset:function(h){return $("<li/>").attr("id","dataset-"+h.id).addClass("dataset unpaired").attr("draggable",true).addClass(h.selected?"selected":"").append($("<span/>").addClass("dataset-name").text(h.name)).data("dataset",h)},_renderPairButton:function(){return $("<li/>").addClass("dataset unpaired").append($("<span/>").addClass("dataset-name").text(d("Pair these datasets")))},_renderUnpairedEmpty:function(){var h=$('<div class="empty-message"></div>').text("("+d("no remaining unpaired datasets")+")");this.$(".unpaired-columns .paired-column .column-datasets").empty().prepend(h);return h},_renderUnpairedNotShown:function(){var h=$('<div class="empty-message"></div>').text("("+d("no datasets were found matching the current filters")+")");this.$(".unpaired-columns .paired-column .column-datasets").empty().prepend(h);return h},_adjUnpairedOnScrollbar:function(){var k=this.$(".unpaired-columns").last(),l=this.$(".unpaired-columns .reverse-column .dataset").first();if(!l.size()){return}var h=k.offset().left+k.outerWidth(),j=l.offset().left+l.outerWidth(),i=Math.floor(h)-Math.floor(j);this.$(".unpaired-columns .forward-column").css("margin-left",(i>0)?i:0)},_renderPaired:function(i,j){this.$(".paired-column-title .title").text([this.paired.length,d("paired")].join(" "));this.$(".unpair-all-link").toggle(this.paired.length!==0);if(this.paired.length===0){this._renderPairedEmpty();return}else{this.$(".remove-extensions-link").show()}this.$(".paired-columns .column-datasets").empty();var h=this;this.paired.forEach(function(m,k){var l=new f({pair:m});h.$(".paired-columns .column-datasets").append(l.render().$el).append(['<button class="unpair-btn">','<span class="fa fa-unlink" title="',d("Unpair"),'"></span>',"</button>"].join(""))})},_renderPairedEmpty:function(){var h=$('<div class="empty-message"></div>').text("("+d("no paired datasets yet")+")");this.$(".paired-columns .column-datasets").empty().prepend(h);return h},_renderFooter:function(i,j){var h=this.$(".footer").empty().html(e.templates.footer());this.$(".remove-extensions").prop("checked",this.removeExtensions);if(typeof this.oncancel==="function"){this.$(".cancel-create.btn").show()}return h},_addPluginComponents:function(){this._chooseFiltersPopover(".choose-filters-link");this.$(".help-content i").hoverhighlight(".collection-creator","rgba( 64, 255, 255, 1.0 )")},_chooseFiltersPopover:function(h){function i(l,k){return['<button class="filter-choice btn" ','data-forward="',l,'" data-reverse="',k,'">',d("Forward"),": ",l,", ",d("Reverse"),": ",k,"</button>"].join("")}var j=$(_.template(['<div class="choose-filters">','<div class="help">',d("Choose from the following filters to change which unpaired reads are shown in the display"),":</div>",i("_1","_2"),i("_R1","_R2"),"</div>"].join(""),{}));return this.$(h).popover({container:".collection-creator",placement:"bottom",html:true,content:j})},_validationWarning:function(i,h){var j="validation-warning";if(i==="name"){i=this.$(".collection-name").add(this.$(".collection-name-prompt"));this.$(".collection-name").focus().select()}if(h){i=i||this.$("."+j);i.removeClass(j)}else{i.addClass(j)}},_setUpBehaviors:function(){this.on("pair:new",function(){this._renderUnpaired();this._renderPaired();this.$(".paired-columns").scrollTop(8000000)});this.on("pair:unpair",function(h){this._renderUnpaired();this._renderPaired();this.splitView()});this.on("filter-change",function(){this.filters=[this.$(".forward-unpaired-filter input").val(),this.$(".reverse-unpaired-filter input").val()];this._renderFilters();this._renderUnpaired()});this.on("autopair",function(){this._renderUnpaired();this._renderPaired();var h,i=null;if(this.paired.length){i="alert-success";h=this.paired.length+" "+d("pairs created");if(!this.unpaired.length){h+=": "+d("all datasets have been successfully paired");this.hideUnpaired()}}else{h=d("Could not automatically create any pairs from the given dataset names")}this._showAlert(h,i)});return this},events:{"click .more-help":"_clickMoreHelp","click .less-help":"_clickLessHelp","click .header .alert button":"_hideAlert","click .forward-column .column-title":"_clickShowOnlyUnpaired","click .reverse-column .column-title":"_clickShowOnlyUnpaired","click .unpair-all-link":"_clickUnpairAll","change .forward-unpaired-filter input":function(h){this.trigger("filter-change")},"focus .forward-unpaired-filter input":function(h){$(h.currentTarget).select()},"click .autopair-link":"_clickAutopair","click .choose-filters .filter-choice":"_clickFilterChoice","click .clear-filters-link":"_clearFilters","change .reverse-unpaired-filter input":function(h){this.trigger("filter-change")},"focus .reverse-unpaired-filter input":function(h){$(h.currentTarget).select()},"click .forward-column .dataset.unpaired":"_clickUnpairedDataset","click .reverse-column .dataset.unpaired":"_clickUnpairedDataset","click .paired-column .dataset.unpaired":"_clickPairRow","click .unpaired-columns":"clearSelectedUnpaired","mousedown .unpaired-columns .dataset":"_mousedownUnpaired","click .paired-column-title":"_clickShowOnlyPaired","mousedown .flexible-partition-drag":"_startPartitionDrag","click .paired-columns .dataset.paired":"selectPair","click .paired-columns .pair-name":"_clickPairName","click .unpair-btn":"_clickUnpair","change .remove-extensions":function(h){this.toggleExtensions()},"change .collection-name":"_changeName","click .cancel-create":function(h){if(typeof this.oncancel==="function"){this.oncancel.call(this)}},"click .create-collection":"_clickCreate"},_clickMoreHelp:function(h){this.$(".main-help").addClass("expanded");this.$(".more-help").hide()},_clickLessHelp:function(h){this.$(".main-help").removeClass("expanded");this.$(".more-help").show()},_showAlert:function(i,h){h=h||"alert-danger";this.$(".main-help").hide();this.$(".header .alert").attr("class","alert alert-dismissable").addClass(h).show().find(".alert-message").html(i)},_hideAlert:function(h){this.$(".main-help").show();this.$(".header .alert").hide()},_clickShowOnlyUnpaired:function(h){if(this.$(".paired-columns").is(":visible")){this.hidePaired()}else{this.splitView()}},_clickShowOnlyPaired:function(h){if(this.$(".unpaired-columns").is(":visible")){this.hideUnpaired()}else{this.splitView()}},hideUnpaired:function(h,i){this.unpairedPanelHidden=true;this.pairedPanelHidden=false;this._renderMiddle(h,i)},hidePaired:function(h,i){this.unpairedPanelHidden=false;this.pairedPanelHidden=true;this._renderMiddle(h,i)},splitView:function(h,i){this.unpairedPanelHidden=this.pairedPanelHidden=false;this._renderMiddle(h,i);return this},_clickUnpairAll:function(h){this.unpairAll()},_clickAutopair:function(i){var h=this.autoPair();this.trigger("autopair",h)},_clickFilterChoice:function(i){var h=$(i.currentTarget);this.$(".forward-unpaired-filter input").val(h.data("forward"));this.$(".reverse-unpaired-filter input").val(h.data("reverse"));this._hideChooseFilters();this.trigger("filter-change")},_hideChooseFilters:function(){this.$(".choose-filters-link").popover("hide");this.$(".popover").css("display","none")},_clearFilters:function(h){this.$(".forward-unpaired-filter input").val("");this.$(".reverse-unpaired-filter input").val("");this.trigger("filter-change")},_clickUnpairedDataset:function(h){h.stopPropagation();return this.toggleSelectUnpaired($(h.currentTarget))},toggleSelectUnpaired:function(j,i){i=i||{};var k=j.data("dataset"),h=i.force!==undefined?i.force:!j.hasClass("selected");if(!j.size()||k===undefined){return j}if(h){j.addClass("selected");if(!i.waitToPair){this.pairAllSelected()}}else{j.removeClass("selected")}return j},pairAllSelected:function(i){i=i||{};var j=this,k=[],h=[],l=[];j.$(".unpaired-columns .forward-column .dataset.selected").each(function(){k.push($(this).data("dataset"))});j.$(".unpaired-columns .reverse-column .dataset.selected").each(function(){h.push($(this).data("dataset"))});k.length=h.length=Math.min(k.length,h.length);k.forEach(function(n,m){try{l.push(j._pair(n,h[m],{silent:true}))}catch(o){j.error(o)}});if(l.length&&!i.silent){this.trigger("pair:new",l)}return l},clearSelectedUnpaired:function(){this.$(".unpaired-columns .dataset.selected").removeClass("selected")},_mousedownUnpaired:function(j){if(j.shiftKey){var i=this,h=$(j.target).addClass("selected"),k=function(l){i.$(l.target).filter(".dataset").addClass("selected")};h.parent().on("mousemove",k);$(document).one("mouseup",function(l){h.parent().off("mousemove",k);i.pairAllSelected()})}},_clickPairRow:function(j){var k=$(j.currentTarget).index(),i=$(".unpaired-columns .forward-column .dataset").eq(k).data("dataset"),h=$(".unpaired-columns .reverse-column .dataset").eq(k).data("dataset");this._pair(i,h)},_startPartitionDrag:function(i){var h=this,l=i.pageY;$("body").css("cursor","ns-resize");h.$(".flexible-partition-drag").css("color","black");function k(m){h.$(".flexible-partition-drag").css("color","");$("body").css("cursor","").unbind("mousemove",j)}function j(m){var n=m.pageY-l;if(!h.adjPartition(n)){$("body").trigger("mouseup")}h._adjUnpairedOnScrollbar();l+=n}$("body").mousemove(j);$("body").one("mouseup",k)},adjPartition:function(i){var h=this.$(".unpaired-columns"),j=this.$(".paired-columns"),k=parseInt(h.css("height"),10),l=parseInt(j.css("height"),10);k=Math.max(10,k+i);l=l-i;var m=i<0;if(m){if(this.unpairedPanelHidden){return false}else{if(k<=10){this.hideUnpaired();return false}}}else{if(this.unpairedPanelHidden){h.show();this.unpairedPanelHidden=false}}if(!m){if(this.pairedPanelHidden){return false}else{if(l<=15){this.hidePaired();return false}}}else{if(this.pairedPanelHidden){j.show();this.pairedPanelHidden=false}}h.css({height:k+"px",flex:"0 0 auto"});return true},selectPair:function(h){$(h.currentTarget).toggleClass("selected")},_clickPairName:function(j){j.stopPropagation();var i=$(j.currentTarget),k=this.paired[i.parent().index()],h=prompt("Enter a new name for the pair:",k.name);if(h){k.name=h;k.customizedName=true;i.text(k.name)}},_clickUnpair:function(i){var h=Math.floor($(i.currentTarget).index()/2);this._unpair(this.paired[h])},toggleExtensions:function(i){var h=this;h.removeExtensions=(i!==undefined)?(i):(!h.removeExtensions);_.each(h.paired,function(j){if(j.customizedName){return}j.name=h._guessNameForPair(j.forward,j.reverse)});h._renderPaired();h._renderFooter()},_changeName:function(h){this._validationWarning("name",!!this._getName())},_getName:function(){return _.escape(this.$(".collection-name").val())},_clickCreate:function(i){var h=this._getName();if(!h){this._validationWarning("name")}else{this.createList()}},_printList:function(i){var h=this;_.each(i,function(j){if(i===h.paired){h._printPair(j)}else{}})},_printPair:function(h){this.debug(h.forward.name,h.reverse.name,": ->",h.name)},toString:function(){return"PairedCollectionCreator"}});e.templates=e.templates||{main:_.template(['<div class="header flex-row no-flex"></div>','<div class="middle flex-row flex-row-container"></div>','<div class="footer flex-row no-flex">'].join("")),header:_.template(['<div class="main-help well clear">','<a class="more-help" href="javascript:void(0);">',d("More help"),"</a>",'<div class="help-content">','<a class="less-help" href="javascript:void(0);">',d("Less"),"</a>","</div>","</div>",'<div class="alert alert-dismissable">','<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>','<span class="alert-message"></span>',"</div>",'<div class="column-headers vertically-spaced flex-column-container">','<div class="forward-column flex-column column">','<div class="column-header">','<div class="column-title">','<span class="title">',d("Unpaired forward"),"</span>",'<span class="title-info unpaired-info"></span>',"</div>",'<div class="unpaired-filter forward-unpaired-filter pull-left">','<input class="search-query" placeholder="',d("Filter this list"),'" />',"</div>","</div>","</div>",'<div class="paired-column flex-column no-flex column">','<div class="column-header">','<a class="choose-filters-link" href="javascript:void(0)">',d("Choose filters"),"</a>",'<a class="clear-filters-link" href="javascript:void(0);">',d("Clear filters"),"</a><br />",'<a class="autopair-link" href="javascript:void(0);">',d("Auto-pair"),"</a>","</div>","</div>",'<div class="reverse-column flex-column column">','<div class="column-header">','<div class="column-title">','<span class="title">',d("Unpaired reverse"),"</span>",'<span class="title-info unpaired-info"></span>',"</div>",'<div class="unpaired-filter reverse-unpaired-filter pull-left">','<input class="search-query" placeholder="',d("Filter this list"),'" />',"</div>","</div>","</div>","</div>"].join("")),middle:_.template(['<div class="unpaired-columns flex-column-container scroll-container flex-row">','<div class="forward-column flex-column column">','<ol class="column-datasets"></ol>',"</div>",'<div class="paired-column flex-column no-flex column">','<ol class="column-datasets"></ol>',"</div>",'<div class="reverse-column flex-column column">','<ol class="column-datasets"></ol>',"</div>","</div>",'<div class="flexible-partition">','<div class="flexible-partition-drag" title="',d("Drag to change"),'"></div>','<div class="column-header">','<div class="column-title paired-column-title">','<span class="title"></span>',"</div>",'<a class="unpair-all-link" href="javascript:void(0);">',d("Unpair all"),"</a>","</div>","</div>",'<div class="paired-columns flex-column-container scroll-container flex-row">','<ol class="column-datasets"></ol>',"</div>"].join("")),footer:_.template(['<div class="attributes clear">','<div class="clear">','<label class="remove-extensions-prompt pull-right">',d("Remove file extensions from pair names"),"?",'<input class="remove-extensions pull-right" type="checkbox" />',"</label>","</div>",'<div class="clear">','<input class="collection-name form-control pull-right" ','placeholder="',d("Enter a name for your new list"),'" />','<div class="collection-name-prompt pull-right">',d("Name"),":</div>","</div>","</div>",'<div class="actions clear vertically-spaced">','<div class="other-options pull-left">','<button class="cancel-create btn" tabindex="-1">',d("Cancel"),"</button>",'<div class="create-other btn-group dropup">','<button class="btn btn-default dropdown-toggle" data-toggle="dropdown">',d("Create a different kind of collection"),' <span class="caret"></span>',"</button>",'<ul class="dropdown-menu" role="menu">','<li><a href="#">',d("Create a <i>single</i> pair"),"</a></li>",'<li><a href="#">',d("Create a list of <i>unpaired</i> datasets"),"</a></li>","</ul>","</div>","</div>",'<div class="main-options pull-right">','<button class="create-collection btn btn-primary">',d("Create list"),"</button>","</div>","</div>"].join("")),helpContent:_.template(["<p>",d(["Collections of paired datasets are ordered lists of dataset pairs (often forward and reverse reads). ","These collections can be passed to tools and workflows in order to have analyses done on each member of ","the entire group. This interface allows you to create a collection, choose which datasets are paired, ","and re-order the final collection."].join("")),"</p>","<p>",d(['Unpaired datasets are shown in the <i data-target=".unpaired-columns">unpaired section</i> ',"(hover over the underlined words to highlight below). ",'Paired datasets are shown in the <i data-target=".paired-columns">paired section</i>.',"<ul>To pair datasets, you can:","<li>Click a dataset in the ",'<i data-target=".unpaired-columns .forward-column .column-datasets,','.unpaired-columns .forward-column">forward column</i> ',"to select it then click a dataset in the ",'<i data-target=".unpaired-columns .reverse-column .column-datasets,','.unpaired-columns .reverse-column">reverse column</i>.',"</li>",'<li>Click one of the "Pair these datasets" buttons in the ','<i data-target=".unpaired-columns .paired-column .column-datasets,','.unpaired-columns .paired-column">middle column</i> ',"to pair the datasets in a particular row.","</li>",'<li>Click <i data-target=".autopair-link">"Auto-pair"</i> ',"to have your datasets automatically paired based on name.","</li>","</ul>"].join("")),"</p>","<p>",d(["<ul>You can filter what is shown in the unpaired sections by:","<li>Entering partial dataset names in either the ",'<i data-target=".forward-unpaired-filter input">forward filter</i> or ','<i data-target=".reverse-unpaired-filter input">reverse filter</i>.',"</li>","<li>Choosing from a list of preset filters by clicking the ",'<i data-target=".choose-filters-link">"Choose filters" link</i>.',"</li>","<li>Entering regular expressions to match dataset names. See: ",'<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expre…"',' target="_blank">MDN\'s JavaScript Regular Expression Tutorial</a>. ',"Note: forward slashes (\\) are not needed.","</li>","<li>Clearing the filters by clicking the ",'<i data-target=".clear-filters-link">"Clear filters" link</i>.',"</li>","</ul>"].join("")),"</p>","<p>",d(["To unpair individual dataset pairs, click the ",'<i data-target=".unpair-btn">unpair buttons ( <span class="fa fa-unlink"></span> )</i>. ','Click the <i data-target=".unpair-all-link">"Unpair all" link</i> to unpair all pairs.'].join("")),"</p>","<p>",d(['You can include or remove the file extensions (e.g. ".fastq") from your pair names by toggling the ','<i data-target=".remove-extensions-prompt">"Remove file extensions from pair names?"</i> control.'].join("")),"</p>","<p>",d(['Once your collection is complete, enter a <i data-target=".collection-name">name</i> and ','click <i data-target=".create-collection">"Create list"</i>. ',"(Note: you do not have to pair all unpaired datasets to finish.)"].join("")),"</p>"].join(""))};(function(){jQuery.fn.extend({hoverhighlight:function h(j,i){j=j||"body";if(!this.size()){return this}$(this).each(function(){var l=$(this),k=l.data("target");if(k){l.mouseover(function(m){$(k,j).css({background:i})}).mouseout(function(m){$(k).css({background:""})})}});return this}})}());var b=function c(j,h){h=_.defaults(h||{},{datasets:j,oncancel:function(){Galaxy.modal.hide()},oncreate:function(){Galaxy.modal.hide();Galaxy.currHistoryPanel.refreshContents()}});if(!window.Galaxy||!Galaxy.modal){throw new Error("Galaxy or Galaxy.modal not found")}var i=new e(h).render();Galaxy.modal.show({title:"Create a collection of paired datasets",body:i.$el,width:"80%",height:"800px",closing_events:true});window.PCC=i;return i};return{PairedCollectionCreator:e,pairedCollectionCreatorModal:b}});
\ No newline at end of file
diff -r 5a7a7003fbc3bc8f9d56f18a8d4b8f2d5b28fe42 -r a66a80701913bb99e8abd12235c1ca82dc508f57 static/style/blue/base.css
--- a/static/style/blue/base.css
+++ b/static/style/blue/base.css
@@ -1851,12 +1851,16 @@
.collection-creator .header .column-headers .column-header .unpaired-filter{width:100%}.collection-creator .header .column-headers .column-header .unpaired-filter .search-query{width:100%;height:22px}
.collection-creator .header .paired-column a:not(:last-child){margin-right:8px}
.collection-creator .header .reverse-column .column-title{text-align:right}
-.collection-creator .unpaired-columns,.collection-creator .paired-columns{height:0;border:1px solid lightgrey;border-width:1px 0 1px 0}
-.collection-creator .paired-columns{margin-bottom:8px}
-.collection-creator .column-datasets{list-style:none;overflow:hidden}.collection-creator .column-datasets .dataset{height:32px;margin-bottom:2px;border:1px solid lightgrey;border-radius:3px;padding:0 8px 0 8px;line-height:28px;cursor:pointer}.collection-creator .column-datasets .dataset:last-child{margin-bottom:4px}
-.collection-creator .unpaired-columns .dataset.unpaired{margin-top:2px;border-color:grey}.collection-creator .unpaired-columns .dataset.unpaired:hover{border-color:black}
-.collection-creator .unpaired-columns .dataset.unpaired.selected{border-color:black;background:black;color:white}
-.collection-creator .unpaired-columns .forward-column .dataset.unpaired{margin-right:32px}
+.collection-creator .flex-bordered-vertically{height:0;border:1px solid lightgrey;border-width:1px 0 1px 0}
+.collection-creator .column-datasets{list-style:none;overflow:hidden}.collection-creator .column-datasets .dataset{height:32px;margin-top:2px;border:1px solid lightgrey;border-radius:3px;padding:0 8px 0 8px;line-height:28px;cursor:pointer}.collection-creator .column-datasets .dataset:last-of-type{margin-bottom:2px}
+.collection-creator .column-datasets .dataset.unpaired{border-color:grey}
+.collection-creator .column-datasets .dataset.paired{margin-left:34px;margin-right:34px;border:2px solid grey;background:#AFF1AF}.collection-creator .column-datasets .dataset.paired span{display:inline-block;overflow:hidden}
+.collection-creator .column-datasets .dataset.paired .forward-dataset-name{text-align:right;border-right:1px solid grey;padding-right:8px}.collection-creator .column-datasets .dataset.paired .forward-dataset-name:after{margin-left:8px;font-family:FontAwesome;content:'\f061'}
+.collection-creator .column-datasets .dataset.paired .pair-name-column{text-align:center}.collection-creator .column-datasets .dataset.paired .pair-name-column .pair-name:hover{text-decoration:underline}
+.collection-creator .column-datasets .dataset.paired .reverse-dataset-name{border-left:1px solid grey;padding-left:8px}.collection-creator .column-datasets .dataset.paired .reverse-dataset-name:before{margin-right:8px;font-family:FontAwesome;content:'\f060'}
+.collection-creator .column-datasets .dataset:hover{border-color:black}
+.collection-creator .column-datasets .dataset.selected{border-color:black;background:black;color:white}
+.collection-creator .unpaired-columns{height:0;border:1px solid lightgrey;border-width:1px 0 1px 0}.collection-creator .unpaired-columns .forward-column .dataset.unpaired{margin-right:32px}
.collection-creator .unpaired-columns .paired-column .dataset.unpaired{border-color:lightgrey;color:lightgrey}.collection-creator .unpaired-columns .paired-column .dataset.unpaired:hover{border-color:black;color:black}
.collection-creator .unpaired-columns .reverse-column .dataset.unpaired{text-align:right;margin-left:32px}
.collection-creator .flexible-partition .flexible-partition-drag{width:100%;height:8px;cursor:ns-resize;line-height:2px;text-align:center;color:lightgrey}.collection-creator .flexible-partition .flexible-partition-drag:before{content:'...'}
@@ -1864,13 +1868,8 @@
.collection-creator .flexible-partition .column-header{width:100%;text-align:center}.collection-creator .flexible-partition .column-header .column-title{display:inline}
.collection-creator .flexible-partition .column-header>*:not(:last-child){margin-right:8px}
.collection-creator .flexible-partition .column-header .remove-extensions-link{display:none}
-.collection-creator .paired-columns .column-datasets{width:100%;overflow:auto}.collection-creator .paired-columns .column-datasets .dataset.paired{margin:0px 34px 2px 34px;border-radius:3px;border:2px solid grey;background:#AFF1AF}.collection-creator .paired-columns .column-datasets .dataset.paired:first-child{margin-top:2px}
-.collection-creator .paired-columns .column-datasets .dataset.paired:hover,.collection-creator .paired-columns .column-datasets .dataset.paired.emphasized{border-color:black}
-.collection-creator .paired-columns .column-datasets .dataset.paired span{display:inline-block;overflow:hidden}
-.collection-creator .paired-columns .column-datasets .dataset.paired .forward-dataset-name{text-align:right;border-right:1px solid grey;padding-right:8px}.collection-creator .paired-columns .column-datasets .dataset.paired .forward-dataset-name:after{margin-left:8px;font-family:FontAwesome;content:'\f061'}
-.collection-creator .paired-columns .column-datasets .dataset.paired .pair-name{display:inline-block;text-align:center}.collection-creator .paired-columns .column-datasets .dataset.paired .pair-name:hover{text-decoration:underline}
-.collection-creator .paired-columns .column-datasets .dataset.paired .reverse-dataset-name{display:inline-block;border-left:1px solid grey;padding-left:8px}.collection-creator .paired-columns .column-datasets .dataset.paired .reverse-dataset-name:before{margin-right:8px;font-family:FontAwesome;content:'\f060'}
-.collection-creator .paired-columns .unpair-btn{float:right;margin-top:-34px;width:31px;height:32px;border-color:transparent;background:transparent;font-size:120%}.collection-creator .paired-columns .unpair-btn:hover{border-color:#BFBFBF;background:#DEDEDE}
+.collection-creator .paired-columns{height:0;border:1px solid lightgrey;border-width:1px 0 1px 0;margin-bottom:8px}.collection-creator .paired-columns .column-datasets{width:100%;overflow:auto}
+.collection-creator .paired-columns .unpair-btn{float:right;margin-top:-32px;width:31px;height:32px;border-color:transparent;background:transparent;font-size:120%}.collection-creator .paired-columns .unpair-btn:hover{border-color:#BFBFBF;background:#DEDEDE}
.collection-creator .paired-columns .empty-message{text-align:center}
.collection-creator .footer{padding-bottom:8px}.collection-creator .footer .attributes .remove-extensions-prompt{line-height:32px}.collection-creator .footer .attributes .remove-extensions-prompt .remove-extensions{display:inline-block;width:24px;height:24px}
.collection-creator .footer .attributes .collection-name-prompt{margin:5px 4px 0 0}
diff -r 5a7a7003fbc3bc8f9d56f18a8d4b8f2d5b28fe42 -r a66a80701913bb99e8abd12235c1ca82dc508f57 static/style/src/less/ui/paired-collection-creator.less
--- a/static/style/src/less/ui/paired-collection-creator.less
+++ b/static/style/src/less/ui/paired-collection-creator.less
@@ -211,10 +211,9 @@
}
// ------------------------------------------------------------------------ middle
- .middle {
- }
- .unpaired-columns,
- .paired-columns {
+ // ---- all
+ // macro
+ .flex-bordered-vertically {
// huh! - giving these any static height will pull them in
height: 0;
// NOT setting the above will give a full-height page
@@ -222,46 +221,80 @@
border: 1px solid lightgrey;
border-width: 1px 0 1px 0;
}
- // ------------------------------------------------------------------------ unpaired
- .paired-columns {
- margin-bottom: 8px;
- }
- // ------------------------------------------------------------------------ middle
- // ---- all
.column-datasets {
list-style: none;
overflow: hidden;
.dataset {
height: 32px;
- margin-bottom: 2px;
+ margin-top: 2px;
+ &:last-of-type {
+ margin-bottom: 2px;
+ }
border: 1px solid lightgrey;
border-radius: 3px;
padding: 0 8px 0 8px;
line-height: 28px;
cursor: pointer;
- //overflow: hidden;
- &:last-child {
- margin-bottom: 4px;
+
+ &.unpaired {
+ border-color: grey;
+ }
+
+ &.paired {
+ margin-left: 34px;
+ margin-right: 34px;
+ border: 2px solid grey;
+ background: #AFF1AF;
+
+ span {
+ display: inline-block;
+ overflow: hidden;
+ }
+ .forward-dataset-name {
+ text-align: right;
+ border-right: 1px solid grey;
+ padding-right: 8px;
+ &:after {
+ margin-left: 8px;
+ font-family: FontAwesome;
+ content: '\f061';
+ }
+ }
+ .pair-name-column {
+ text-align: center;
+ .pair-name:hover {
+ text-decoration: underline;
+ }
+ }
+ .reverse-dataset-name {
+ border-left: 1px solid grey;
+ padding-left: 8px;
+ &:before {
+ margin-right: 8px;
+ font-family: FontAwesome;
+ content: '\f060';
+ }
+ }
+ }
+
+ &:hover {
+ border-color: black;
+ }
+
+ &.selected {
+ border-color: black;
+ background: black;
+ color: white;
}
}
}
// ---- unpaired
.unpaired-columns {
- .dataset.unpaired {
- margin-top: 2px;
- border-color: grey;
- &:hover {
- border-color: black;
- }
- &.selected {
- border-color: black;
- background: black;
- color: white;
- }
- }
+ .flex-bordered-vertically;
+
.forward-column {
.dataset.unpaired {
margin-right: 32px;
@@ -319,62 +352,16 @@
// ---- paired datasets
.paired-columns {
+ .flex-bordered-vertically;
+ margin-bottom: 8px;
+
.column-datasets {
width: 100%;
overflow: auto;
-
- .dataset.paired {
- &:first-child {
- margin-top: 2px;
- }
- margin: 0px 34px 2px 34px;
-
- border-radius: 3px;
- border: 2px solid grey;
-
- background: #AFF1AF;
-
- &:hover,
- &.emphasized {
- border-color: black;
- }
-
- span {
- display: inline-block;
- overflow: hidden;
- }
- .forward-dataset-name {
- text-align: right;
- border-right: 1px solid grey;
- padding-right: 8px;
- &:after {
- margin-left: 8px;
- font-family: FontAwesome;
- content: '\f061';
- }
- }
- .pair-name {
- display: inline-block;
- text-align: center;
- &:hover {
- text-decoration: underline;
- }
- }
- .reverse-dataset-name {
- display: inline-block;
- border-left: 1px solid grey;
- padding-left: 8px;
- &:before {
- margin-right: 8px;
- font-family: FontAwesome;
- content: '\f060';
- }
- }
- }
}
.unpair-btn {
float: right;
- margin-top: -34px;
+ margin-top: -32px;
width: 31px;
height: 32px;
//z-index: 1;
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: martenson: initial implementation of library folder manager
by commits-noreply@bitbucket.org 27 Aug '14
by commits-noreply@bitbucket.org 27 Aug '14
27 Aug '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/5a7a7003fbc3/
Changeset: 5a7a7003fbc3
User: martenson
Date: 2014-08-27 19:26:36
Summary: initial implementation of library folder manager
Affected #: 2 files
diff -r 8c0b86881425de9ba43c6aa604e868236cb7a9c9 -r 5a7a7003fbc3bc8f9d56f18a8d4b8f2d5b28fe42 lib/galaxy/managers/folders.py
--- /dev/null
+++ b/lib/galaxy/managers/folders.py
@@ -0,0 +1,160 @@
+"""
+Manager and Serializer for Library Folders.
+"""
+
+import galaxy.web
+from galaxy import exceptions
+from galaxy.model import orm
+
+import logging
+log = logging.getLogger( __name__ )
+
+
+# =============================================================================
+class FolderManager( object ):
+ """
+ Interface/service object for interacting with folders.
+ """
+
+ def get( self, trans, decoded_folder_id, check_ownership=False, check_accessible=True):
+ """
+ Get the folder from the DB.
+
+ :param decoded_folder_id: decoded folder id
+ :type decoded_folder_id: int
+ :param check_ownership: flag whether the check that user is owner
+ :type check_ownership: bool
+ :param check_accessible: flag whether to check that user can access item
+ :type check_accessible: bool
+
+ :returns: the requested folder
+ :rtype: LibraryFolder
+ """
+ try:
+ folder = trans.sa_session.query( trans.app.model.LibraryFolder ).filter( trans.app.model.LibraryFolder.table.c.id == decoded_folder_id ).one()
+ except MultipleResultsFound:
+ raise exceptions.InconsistentDatabase( 'Multiple folders found with the same id.' )
+ except NoResultFound:
+ raise exceptions.RequestParameterInvalidException( 'No folder found with the id provided.' )
+ except Exception, e:
+ raise exceptions.InternalServerError( 'Error loading from the database.' + str( e ) )
+
+ folder = self.secure( trans, folder, check_ownership, check_accessible )
+
+ return folder
+
+ def secure( self, trans, folder, check_ownership=True, check_accessible=True ):
+ """
+ Check if (a) user owns folder or (b) folder is accessible to user.
+
+ :param folder: folder item
+ :type folder: LibraryFolder
+ :param check_ownership: flag whether the check that user is owner
+ :type check_ownership: bool
+ :param check_accessible: flag whether to check that user can access item
+ :type check_accessible: bool
+
+ :returns: the original folder
+ :rtype: LibraryFolder
+ """
+ # all folders are accessible to an admin
+ if trans.user_is_admin():
+ return folder
+ if check_ownership:
+ folder = self.check_ownership( trans, folder )
+ if check_accessible:
+ folder = self.check_accessible( trans, folder )
+ return folder
+
+ def check_ownership( self, trans, folder ):
+ """
+ Check whether the user is owner of the folder.
+
+ :returns: the original folder
+ :rtype: LibraryFolder
+ """
+ if not trans.user:
+ raise exceptions.AuthenticationRequired( "Must be logged in to manage Galaxy items", type='error' )
+ if folder.user != trans.user:
+ raise exceptions.ItemOwnershipException( "Folder is not owned by the current user", type='error' )
+ else:
+ return folder
+
+ def check_accessible( self, trans, folder ):
+ """
+ Check whether the folder is accessible to current user.
+ By default every folder is accessible (contents have their own permissions).
+ """
+ return True
+
+ def get_folder_dict( self, trans, folder ):
+ """
+ Return folder data in the form of a dictionary.
+
+ :param folder: folder item
+ :type folder: LibraryFolder
+
+ :returns: dict with data about the new folder
+ :rtype: dictionary
+
+ """
+ folder_dict = folder.to_dict( view='element' )
+ folder_dict = trans.security.encode_all_ids( folder_dict, True )
+ folder_dict[ 'id' ] = 'F' + folder_dict[ 'id' ]
+ if folder_dict[ 'parent_id' ] is not None:
+ folder_dict[ 'parent_id' ] = 'F' + folder_dict[ 'parent_id' ]
+ return folder_dict
+
+ def create( self, trans, parent_folder_id, new_folder_name, new_folder_description='' ):
+ """
+ Create a new folder under the given folder.
+
+ :param parent_folder_id: decoded id
+ :type parent_folder_id: int
+ :param new_folder_name: name of the new folder
+ :type new_folder_name: str
+ :param new_folder_description: description of the folder (optional, defaults to empty string)
+ :type new_folder_description: str
+
+ :returns: the new folder
+ :rtype: LibraryFolder
+
+ :raises: InsufficientPermissionsException
+ """
+ parent_folder = self.get( trans, parent_folder_id )
+ current_user_roles = trans.get_current_user_roles()
+ if not ( trans.user_is_admin or trans.app.security_agent.can_add_library_item( current_user_roles, parent_folder ) ):
+ raise exceptions.InsufficientPermissionsException( 'You do not have proper permission to create folders under given folder.' )
+ new_folder = trans.app.model.LibraryFolder( name=new_folder_name, description=new_folder_description )
+ # We are associating the last used genome build with folders, so we will always
+ # initialize a new folder with the first dbkey in genome builds list which is currently
+ # ? unspecified (?)
+ new_folder.genome_build = trans.app.genome_builds.default_value
+ parent_folder.add_folder( new_folder )
+ trans.sa_session.add( new_folder )
+ trans.sa_session.flush()
+ # New folders default to having the same permissions as their parent folder
+ trans.app.security_agent.copy_library_permissions( trans, parent_folder, new_folder )
+ return new_folder
+
+ def get_current_roles( self, trans, folder ):
+ """
+ Find all roles currently connected to relevant permissions
+ on the folder.
+
+ :param folder: the model object
+ :type folder: LibraryFolder
+
+ :returns: dict of current roles for all available permission types
+ :rtype: dictionary
+ """
+ # Omit duplicated roles by converting to set
+ modify_roles = set( trans.app.security_agent.get_roles_for_action( folder, trans.app.security_agent.permitted_actions.LIBRARY_MODIFY ) )
+ manage_roles = set( trans.app.security_agent.get_roles_for_action( folder, trans.app.security_agent.permitted_actions.LIBRARY_MANAGE ) )
+ add_roles = set( trans.app.security_agent.get_roles_for_action( folder, trans.app.security_agent.permitted_actions.LIBRARY_ADD ) )
+
+ modify_folder_role_list = [ modify_role.name for modify_role in modify_roles ]
+ manage_folder_role_list = [ manage_role.name for manage_role in manage_roles ]
+ add_library_item_role_list = [ add_role.name for add_role in add_roles ]
+
+ return dict( modify_folder_role_list=modify_folder_role_list, manage_folder_role_list=manage_folder_role_list, add_library_item_role_list=add_library_item_role_list )
diff -r 8c0b86881425de9ba43c6aa604e868236cb7a9c9 -r 5a7a7003fbc3bc8f9d56f18a8d4b8f2d5b28fe42 lib/galaxy/webapps/galaxy/api/folders.py
--- a/lib/galaxy/webapps/galaxy/api/folders.py
+++ b/lib/galaxy/webapps/galaxy/api/folders.py
@@ -1,16 +1,10 @@
"""
API operations on library folders
"""
-# import os
-# import shutil
-# import urllib
-# import re
-# import socket
-# import traceback
-# import string
from galaxy import util
from galaxy import web
from galaxy import exceptions
+from galaxy.managers import folders
from galaxy.web import _future_expose_api as expose_api
from galaxy.web.base.controller import BaseAPIController, UsesLibraryMixin, UsesLibraryMixinItems
from sqlalchemy.orm.exc import MultipleResultsFound
@@ -22,10 +16,14 @@
class FoldersController( BaseAPIController, UsesLibraryMixin, UsesLibraryMixinItems ):
+ def __init__( self, app ):
+ super( FoldersController, self ).__init__( app )
+ self.folder_manager = folders.FolderManager()
+
@web.expose_api
def index( self, trans, **kwd ):
"""
- GET /api/folders/
+ *GET /api/folders/
This would normally display a list of folders. However, that would
be across multiple libraries, so it's not implemented.
"""
@@ -45,12 +43,8 @@
:returns: dictionary including details of the folder
:rtype: dict
"""
- folder_id_without_prefix = self.__cut_the_prefix( id )
- content = self.get_library_folder( trans, folder_id_without_prefix, check_ownership=False, check_accessible=True )
- return_dict = self.encode_all_ids( trans, content.to_dict( view='element' ) )
- return_dict[ 'id' ] = 'F' + return_dict[ 'id' ]
- if return_dict[ 'parent_id' ] is not None:
- return_dict[ 'parent_id' ] = 'F' + return_dict[ 'parent_id' ]
+ folder = self.folder_manager.get( trans, self.__cut_and_decode( trans, id ), check_ownership=False, check_accessible=True )
+ return_dict = self.folder_manager.get_folder_dict( trans, folder )
return return_dict
@expose_api
@@ -74,47 +68,20 @@
:returns: information about newly created folder, notably including ID
:rtype: dictionary
- :raises: RequestParameterMissingException, MalformedId, InternalServerError
+ :raises: RequestParameterMissingException
"""
-
payload = kwd.get( 'payload', None )
if payload is None:
- raise exceptions.RequestParameterMissingException( "Missing required parameters 'encoded_parent_folder_id' and 'name'." )
+ raise exceptions.RequestParameterMissingException( "Missing required parameter 'name'." )
name = payload.get( 'name', None )
+ if name is None:
+ raise exceptions.RequestParameterMissingException( "Missing required parameter 'name'." )
description = payload.get( 'description', '' )
- if encoded_parent_folder_id is None:
- raise exceptions.RequestParameterMissingException( "Missing required parameter 'encoded_parent_folder_id'." )
- elif name is None:
- raise exceptions.RequestParameterMissingException( "Missing required parameter 'name'." )
-
- encoded_parent_folder_id = self.__cut_the_prefix( encoded_parent_folder_id )
- decoded_parent_folder_id = self.__decode_folder_id( trans, encoded_parent_folder_id )
- parent_folder = self.__load_folder( trans, decoded_parent_folder_id )
+ decoded_parent_folder_id = self.__cut_and_decode( trans, encoded_parent_folder_id )
+ parent_folder = self.folder_manager.get( trans, decoded_parent_folder_id )
+ new_folder = self.folder_manager.create( trans, parent_folder.id, name, description )
+ return self.folder_manager.get_folder_dict( trans, new_folder )
- library = parent_folder.parent_library
- if library.deleted:
- raise exceptions.ObjectAttributeInvalidException( 'You cannot create folder within a deleted library. Undelete it first.' )
-
- # TODO: refactor the functionality for use in manager instead of calling another controller
- params = dict( [ ( "name", name ), ( "description", description ) ] )
- status, output = trans.webapp.controllers['library_common'].create_folder( trans, 'api', encoded_parent_folder_id, '', **params )
-
- if 200 == status and len( output.items() ) == 1:
- for k, v in output.items():
- try:
- folder = trans.sa_session.query( trans.app.model.LibraryFolder ).get( v.id )
- except Exception, e:
- raise exceptions.InternalServerError( 'Error loading from the database.' + str( e ))
- if folder:
- update_time = folder.update_time.strftime( "%Y-%m-%d %I:%M %p" )
- return_dict = self.encode_all_ids( trans, folder.to_dict( view='element' ) )
- return_dict[ 'update_time' ] = update_time
- return_dict[ 'parent_id' ] = 'F' + return_dict[ 'parent_id' ]
- return_dict[ 'id' ] = 'F' + return_dict[ 'id' ]
- return return_dict
- else:
- raise exceptions.InternalServerError( 'Error while creating a folder.' + str( e ) )
-
@expose_api
def get_permissions( self, trans, encoded_folder_id, **kwd ):
"""
@@ -135,19 +102,16 @@
"""
current_user_roles = trans.get_current_user_roles()
is_admin = trans.user_is_admin()
-
encoded_folder_id = self.__cut_the_prefix( encoded_folder_id )
decoded_folder_id = self.__decode_folder_id( trans, encoded_folder_id )
- folder = self.__load_folder( trans, decoded_folder_id )
+ folder = self.folder_manager.get( trans, decoded_folder_id )
- if not ( is_admin or trans.app.security_agent.can_manage_library_item( current_user_roles, library ) ):
+ if not ( is_admin or trans.app.security_agent.can_manage_library_item( current_user_roles, folder ) ):
raise exceptions.InsufficientPermissionsException( 'You do not have proper permission to access permissions of this folder.' )
scope = kwd.get( 'scope', None )
-
if scope == 'current' or scope is None:
- return self._get_current_roles( trans, folder )
-
+ return self.folder_manager.get_current_roles( trans, folder )
# Return roles that are available to select.
elif scope == 'available':
page = kwd.get( 'page', None )
@@ -155,17 +119,13 @@
page = int( page )
else:
page = 1
-
page_limit = kwd.get( 'page_limit', None )
if page_limit is not None:
page_limit = int( page_limit )
else:
page_limit = 10
-
query = kwd.get( 'q', None )
-
roles, total_roles = trans.app.security_agent.get_valid_roles( trans, folder, query, page, page_limit )
-
return_roles = []
for role in roles:
return_roles.append( dict( id=role.name, name=role.name, type=role.type ) )
@@ -203,7 +163,7 @@
current_user_roles = trans.get_current_user_roles()
decoded_folder_id = self.__decode_folder_id( trans, self.__cut_the_prefix( encoded_folder_id ) )
- folder = self.__load_folder( trans, decoded_folder_id )
+ folder = self.folder_manager.get( trans, decoded_folder_id )
if not ( is_admin or trans.app.security_agent.can_manage_library_item( current_user_roles, folder ) ):
raise exceptions.InsufficientPermissionsException( 'You do not have proper permission to modify permissions of this folder.' )
@@ -266,8 +226,7 @@
else:
raise exceptions.RequestParameterInvalidException( 'The mandatory parameter "action" has an invalid value.'
'Allowed values are: "set_permissions"' )
-
- return self._get_current_roles( trans, folder )
+ return self.folder_manager.get_current_roles( trans, folder )
@web.expose_api
def update( self, trans, id, library_id, payload, **kwd ):
@@ -297,42 +256,11 @@
raise exceptions.MalformedId( "Malformed folder id ( %s ) specified, unable to decode" % ( str( encoded_id ) ) )
return decoded_id
- def __load_folder( self, trans, folder_id ):
+ def __cut_and_decode( self, trans, encoded_folder_id ):
"""
- Load the folder from the DB.
+ Cuts the prefix (the prepended 'F') and returns the decoded id.
"""
- try:
- folder = trans.sa_session.query( trans.app.model.LibraryFolder ).filter( trans.app.model.LibraryFolder.table.c.id == folder_id ).one()
- except MultipleResultsFound:
- raise exceptions.InconsistentDatabase( 'Multiple folders found with the same id.' )
- except NoResultFound:
- raise exceptions.RequestParameterInvalidException( 'No folder found with the id provided.' )
- except Exception, e:
- raise exceptions.InternalServerError( 'Error loading from the database.' + str( e ) )
- return folder
-
-
- def _get_current_roles( self, trans, folder ):
- """
- Find all roles currently connected to relevant permissions
- on the folder.
-
- :param folder: the model object
- :type folder: LibraryFolder
-
- :rtype: dictionary
- :returns: dict of current roles for all available permission types
- """
- # Omit duplicated roles by converting to set
- modify_roles = set( trans.app.security_agent.get_roles_for_action( folder, trans.app.security_agent.permitted_actions.LIBRARY_MODIFY ) )
- manage_roles = set( trans.app.security_agent.get_roles_for_action( folder, trans.app.security_agent.permitted_actions.LIBRARY_MANAGE ) )
- add_roles = set( trans.app.security_agent.get_roles_for_action( folder, trans.app.security_agent.permitted_actions.LIBRARY_ADD ) )
-
- modify_folder_role_list = [ modify_role.name for modify_role in modify_roles ]
- manage_folder_role_list = [ manage_role.name for manage_role in manage_roles ]
- add_library_item_role_list = [ add_role.name for add_role in add_roles ]
-
- return dict( modify_folder_role_list=modify_folder_role_list, manage_folder_role_list=manage_folder_role_list, add_library_item_role_list=add_library_item_role_list )
+ return self.__decode_folder_id( trans, self.__cut_the_prefix( encoded_folder_id ) )
def _load_role( self, trans, role_name ):
"""
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: Fix upload tool for 6cb895d.
by commits-noreply@bitbucket.org 27 Aug '14
by commits-noreply@bitbucket.org 27 Aug '14
27 Aug '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/8c0b86881425/
Changeset: 8c0b86881425
User: jmchilton
Date: 2014-08-27 19:06:26
Summary: Fix upload tool for 6cb895d.
Web form (at least for older style upload tool) was passing in '' and the UUID custom datatype treats this as an invalid UUID (probably correct) instead of a None. This changeset fixes that by ensuring these values coming in through the controllers are transformed into None-s.
Affected #: 1 file
diff -r 3e00d002e7ba1fdd9d914bcd68589aad5c1e21ff -r 8c0b86881425de9ba43c6aa604e868236cb7a9c9 lib/galaxy/tools/parameters/grouping.py
--- a/lib/galaxy/tools/parameters/grouping.py
+++ b/lib/galaxy/tools/parameters/grouping.py
@@ -278,7 +278,7 @@
ftp_files = context['ftp_files']
name = context.get( 'NAME', None )
info = context.get( 'INFO', None )
- uuid = context.get( 'uuid', None )
+ uuid = context.get( 'uuid', None ) or None # Turn '' to None
warnings = []
to_posix_lines = False
if context.get( 'to_posix_lines', None ) not in [ "None", None, False ]:
@@ -324,7 +324,7 @@
data_file = context['file_data']
url_paste = context['url_paste']
ftp_files = context['ftp_files']
- uuid = context.get( 'uuid', None )
+ uuid = context.get( 'uuid', None ) or None # Turn '' to None
name = context.get( 'NAME', None )
info = context.get( 'INFO', None )
to_posix_lines = 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