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
July 2014
- 1 participants
- 146 discussions
commit/galaxy-central: dan: Fix for parsing tool <input> attributes when it contains no parameters.
by commits-noreply@bitbucket.org 24 Jul '14
by commits-noreply@bitbucket.org 24 Jul '14
24 Jul '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/832bbb3fa9fb/
Changeset: 832bbb3fa9fb
User: dan
Date: 2014-07-24 22:46:24
Summary: Fix for parsing tool <input> attributes when it contains no parameters.
Affected #: 1 file
diff -r 6f7d70f72da237e0d8d37a20b14a4eab1828803d -r 832bbb3fa9fb62d53f2be23cf880755fa2001f46 lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -1391,7 +1391,7 @@
# Load parameters (optional)
input_elem = root.find("inputs")
enctypes = set()
- if input_elem:
+ if input_elem is not None:
# Handle properties of the input form
self.check_values = string_as_bool( input_elem.get("check_values", self.check_values ) )
self.nginx_upload = string_as_bool( input_elem.get( "nginx_upload", self.nginx_upload ) )
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: Bugfix in test tool demoing two collection params.
by commits-noreply@bitbucket.org 24 Jul '14
by commits-noreply@bitbucket.org 24 Jul '14
24 Jul '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/6f7d70f72da2/
Changeset: 6f7d70f72da2
User: jmchilton
Date: 2014-07-24 22:30:51
Summary: Bugfix in test tool demoing two collection params.
Bit problematic functional tests passed despite this bug.
Affected #: 1 file
diff -r b2700f28372549a17f5ca03af60e86964665c3ff -r 6f7d70f72da237e0d8d37a20b14a4eab1828803d test/functional/tools/collection_two_paired.xml
--- a/test/functional/tools/collection_two_paired.xml
+++ b/test/functional/tools/collection_two_paired.xml
@@ -20,8 +20,8 @@
<param name="f2" type="data_collection" collection_type="paired" /></when><when value="list">
- <param name="f1" type="data_collection" collection_type="paired" />
- <param name="f2" type="data_collection" collection_type="paired" />
+ <param name="f1" type="data_collection" collection_type="list" />
+ <param name="f2" type="data_collection" collection_type="list" /></when></conditional></inputs>
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: Add functional tool tests exercising multiple collection parameters at once.
by commits-noreply@bitbucket.org 24 Jul '14
by commits-noreply@bitbucket.org 24 Jul '14
24 Jul '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/b2700f283725/
Changeset: b2700f283725
User: jmchilton
Date: 2014-07-24 22:06:04
Summary: Add functional tool tests exercising multiple collection parameters at once.
Affected #: 2 files
diff -r 2be89285509068e862d27d41c3ba02c5a59e5b00 -r b2700f28372549a17f5ca03af60e86964665c3ff test/functional/tools/collection_two_paired.xml
--- /dev/null
+++ b/test/functional/tools/collection_two_paired.xml
@@ -0,0 +1,69 @@
+<tool id="collection_two_paired" name="collection_two_paired" version="0.1.0">
+ <command>
+ #if $kind.collection_type == "paired"
+ cat $kind.f1.forward $kind.f1['reverse'] >> $out1;
+ cat $kind.f2.forward $kind.f2['reverse'] >> $out1;
+ #else
+ #for $i, $_ in enumerate($kind.f1):
+ cat $kind.f1[$i] $kind.f2[$i] >> $out1;
+ #end for
+ #end if
+ </command>
+ <inputs>
+ <conditional name="kind">
+ <param type="select" name="collection_type">
+ <option value="paired">Paired Datasets</option>
+ <option value="list">List of Datasets</option>
+ </param>
+ <when value="paired">
+ <param name="f1" type="data_collection" collection_type="paired" />
+ <param name="f2" type="data_collection" collection_type="paired" />
+ </when>
+ <when value="list">
+ <param name="f1" type="data_collection" collection_type="paired" />
+ <param name="f2" type="data_collection" collection_type="paired" />
+ </when>
+ </conditional>
+ </inputs>
+ <outputs>
+ <data format="txt" name="out1" />
+ </outputs>
+ <tests>
+ <test>
+ <conditional name="kind">
+ <param name="collection_type" value="paired" />
+ <param name="f1">
+ <collection type="paired">
+ <element name="forward" value="simple_line.txt" />
+ <element name="reverse" value="simple_line_alternative.txt" />
+ </collection>
+ </param>
+ <param name="f2">
+ <collection type="paired">
+ <element name="forward" value="simple_line.txt" />
+ <element name="reverse" value="simple_line_alternative.txt" />
+ </collection>
+ </param>
+ </conditional>
+ <output name="out1" file="simple_lines_interleaved.txt"/>
+ </test>
+ <test>
+ <conditional name="kind">
+ <param name="collection_type" value="list" />
+ <param name="f1">
+ <collection type="list">
+ <element name="l11" value="simple_line.txt" />
+ <element name="l12" value="simple_line.txt" />
+ </collection>
+ </param>
+ <param name="f2">
+ <collection type="list">
+ <element name="l21" value="simple_line_alternative.txt" />
+ <element name="l22" value="simple_line_alternative.txt" />
+ </collection>
+ </param>
+ </conditional>
+ <output name="out1" file="simple_lines_interleaved.txt"/>
+ </test>
+ </tests>
+</tool>
diff -r 2be89285509068e862d27d41c3ba02c5a59e5b00 -r b2700f28372549a17f5ca03af60e86964665c3ff test/functional/tools/samples_tool_conf.xml
--- a/test/functional/tools/samples_tool_conf.xml
+++ b/test/functional/tools/samples_tool_conf.xml
@@ -21,4 +21,5 @@
<tool file="collection_paired_test.xml" /><tool file="collection_nested_test.xml" /><tool file="collection_mixed_param.xml" />
+ <tool file="collection_two_paired.xml" /></toolbox>
\ No newline at end of file
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
3 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/20dcff34ee3b/
Changeset: 20dcff34ee3b
User: jmchilton
Date: 2014-07-24 21:30:11
Summary: More collection-y state update tests.
Affected #: 1 file
diff -r 9d8967752787556b3d814e086fe2bd9eb1992170 -r 20dcff34ee3bb598969c51a7c5b53e9dd679c111 test/unit/tools/test_execution.py
--- a/test/unit/tools/test_execution.py
+++ b/test/unit/tools/test_execution.py
@@ -16,13 +16,12 @@
eggs.require( "Paste" )
from paste import httpexceptions
-# Tool with a repeat parameter, to test state update.
-REPEAT_TOOL_CONTENTS = '''<tool id="test_tool" name="Test Tool">
+BASE_REPEAT_TOOL_CONTENTS = '''<tool id="test_tool" name="Test Tool"><command>echo "$param1" #for $r in $repeat# "$r.param2" #end for# < $out1</command><inputs><param type="text" name="param1" value="" /><repeat name="repeat1" label="Repeat 1">
- <param type="text" name="param2" value="" />
+ %s
</repeat></inputs><outputs>
@@ -31,6 +30,10 @@
</tool>
'''
+# Tool with a repeat parameter, to test state update.
+REPEAT_TOOL_CONTENTS = BASE_REPEAT_TOOL_CONTENTS % '''<param type="text" name="param2" value="" />'''
+REPEAT_COLLECTION_PARAM_CONTENTS = BASE_REPEAT_TOOL_CONTENTS % '''<param type="data_collection" name="param2" collection_type="paired" />'''
+
class ToolExecutionTestCase( TestCase, tools_support.UsesApp, tools_support.UsesTools ):
@@ -287,13 +290,48 @@
} )
self.__assert_exeuted( template, template_vars )
- def __history_dataset_collection_for( self, hdas, id=1234 ):
- collection = galaxy.model.DatasetCollection()
+ def test_subcollection_multirun_with_state_updates( self ):
+ self._init_tool( REPEAT_COLLECTION_PARAM_CONTENTS )
+ hda1, hda2 = self.__add_dataset( 1 ), self.__add_dataset( 2 )
+ collection = self.__history_dataset_collection_for( [ hda1, hda2 ], collection_type="list:paired" )
+ collection_id = self.app.security.encode_id( collection.id )
+ self.app.dataset_collections_service = Bunch(
+ match_collections=lambda collections: None
+ )
+ template, template_vars = self.__handle_with_incoming(
+ repeat1_add="dummy",
+ )
+ state = self.__assert_rerenders_tool_without_errors( template, template_vars )
+ assert len( state.inputs[ "repeat1" ] ) == 1
+ template, template_vars = self.__handle_with_incoming( state, **{
+ "repeat1_0|param2|__collection_multirun__": "%s|paired" % collection_id,
+ "repeat1_add": "dummy",
+ } )
+ state = self.__assert_rerenders_tool_without_errors( template, template_vars )
+ assert state.inputs[ "repeat1" ][ 0 ][ "param2|__collection_multirun__" ] == "%s|paired" % collection_id
+
+ def __history_dataset_collection_for( self, hdas, collection_type="list", id=1234 ):
+ collection = galaxy.model.DatasetCollection(
+ collection_type=collection_type,
+ )
to_element = lambda hda: galaxy.model.DatasetCollectionElement(
collection=collection,
element=hda,
)
- collection.datasets = map(to_element, hdas)
+ elements = map(to_element, hdas)
+ if collection_type == "list:paired":
+ paired_collection = galaxy.model.DatasetCollection(
+ collection_type="paired",
+ )
+ paired_collection.elements = elements
+ list_dce = galaxy.model.DatasetCollectionElement(
+ collection=collection,
+ element=paired_collection,
+ )
+ elements = [ list_dce ]
+
+ collection.elements = elements
+
history_dataset_collection_association = galaxy.model.HistoryDatasetCollectionAssociation(
id=id,
collection=collection,
@@ -349,13 +387,13 @@
self.history.datasets.append( hda )
return hda
- def __add_collection_dataset( self, id, *hdas ):
+ def __add_collection_dataset( self, id, collection_type="paired", *hdas ):
hdca = galaxy.model.HistoryDatasetCollectionAssociation()
hdca.id = id
collection = galaxy.model.DatasetCollection()
hdca.collection = collection
collection.elements = [ galaxy.model.DatasetCollectionElement(element=self.__add_dataset( 1 )) ]
-
+ collection.type = collection_type
self.trans.sa_session.model_objects[ galaxy.model.HistoryDatasetCollectionAssociation ][ id ] = hdca
self.history.dataset_collections.append( hdca )
return hdca
https://bitbucket.org/galaxy/galaxy-central/commits/9c2cbf6c7f3d/
Changeset: 9c2cbf6c7f3d
User: jmchilton
Date: 2014-07-24 21:30:11
Summary: Fix multirun and collection multirun state updates in tool param GUI.
4139740 fixed backend and had tests so I guess I didn't even manually test, turns out tool parameter GUI generation needed to fixed for these changes though.
Affected #: 1 file
diff -r 20dcff34ee3bb598969c51a7c5b53e9dd679c111 -r 9c2cbf6c7f3db7cb59ebd53b9c2829404077993a lib/galaxy/tools/parameters/basic.py
--- a/lib/galaxy/tools/parameters/basic.py
+++ b/lib/galaxy/tools/parameters/basic.py
@@ -1712,10 +1712,15 @@
if self.__display_multirun_option():
# Select multiple datasets, run multiple jobs.
multirun_key = "%s|__multirun__" % self.name
+ collection_multirun_key = "%s|__collection_multirun__" % self.name
if multirun_key in (other_values or {}):
multirun_value = listify( other_values[ multirun_key ] )
if multirun_value and len( multirun_value ) > 1:
default_field = "select_multiple"
+ elif collection_multirun_key in (other_values or {}):
+ multirun_value = listify( other_values[ collection_multirun_key ] )
+ if multirun_value:
+ default_field = "select_collection"
else:
multirun_value = value
multi_dataset_matcher = DatasetMatcher( trans, self, multirun_value, other_values )
@@ -2014,9 +2019,17 @@
default_field = "select_single_collection"
fields = odict()
+ collection_multirun_key = "%s|__collection_multirun__" % self.name
+ if collection_multirun_key in (other_values or {}):
+ multirun_value = other_values[ collection_multirun_key ]
+ if multirun_value:
+ default_field = "select_map_over_collections"
+ else:
+ multirun_value = value
+
history = self._get_history( trans )
fields[ "select_single_collection" ] = self._get_single_collection_field( trans=trans, history=history, value=value, other_values=other_values )
- fields[ "select_map_over_collections" ] = self._get_select_dataset_collection_field( trans=trans, history=history, value=value, other_values=other_values )
+ fields[ "select_map_over_collections" ] = self._get_select_dataset_collection_field( trans=trans, history=history, value=multirun_value, other_values=other_values )
return self._switch_fields( fields, default_field=default_field )
https://bitbucket.org/galaxy/galaxy-central/commits/2be892855090/
Changeset: 2be892855090
User: jmchilton
Date: 2014-07-24 21:30:11
Summary: Small UI fix for data param multirun options.
Index-based logic wasn't updated after made it so certain options wouldn't be visible if they were not valid for a given history.
Affected #: 1 file
diff -r 9c2cbf6c7f3db7cb59ebd53b9c2829404077993a -r 2be89285509068e862d27d41c3ba02c5a59e5b00 static/scripts/galaxy.tools.js
--- a/static/scripts/galaxy.tools.js
+++ b/static/scripts/galaxy.tools.js
@@ -86,7 +86,7 @@
}).attr(
'title',
selectionType['select_by']
- );
+ ).data( "index", iIndex );
view.formRow().find( "label" ).append( button );
}
});
@@ -114,11 +114,13 @@
} else {
$("div#remap-row").css("display", "none");
}
- this.formRow().find( "i" ).each(function(index, iElement) {
+ this.formRow().find( "i" ).each(function(_, iElement) {
+ var $iElement = $(iElement);
+ var index = $iElement.data("index");
if(index == enableIndex) {
- $(iElement).css('color', 'black');
+ $iElement.css('color', 'black');
} else {
- $(iElement).css('color', 'Gray');
+ $iElement.css('color', 'Gray');
}
});
var $select = this.$( "select" );
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: jgoecks: Trackster: resolve name collision due to refactoring.
by commits-noreply@bitbucket.org 24 Jul '14
by commits-noreply@bitbucket.org 24 Jul '14
24 Jul '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/9d8967752787/
Changeset: 9d8967752787
User: jgoecks
Date: 2014-07-24 15:26:39
Summary: Trackster: resolve name collision due to refactoring.
Affected #: 1 file
diff -r 6fbe4d95a8dc64bd222dbf1170bdadcc5321e855 -r 9d8967752787556b3d814e086fe2bd9eb1992170 static/scripts/viz/trackster.js
--- a/static/scripts/viz/trackster.js
+++ b/static/scripts/viz/trackster.js
@@ -103,8 +103,9 @@
var self = this,
menu = create_icon_buttons_menu([
{ icon_class: 'plus-button', title: 'Add tracks', on_click: function() {
- visualization.select_datasets(galaxy_config.root + "visualization/list_current_history_datasets", galaxy_config.root + "api/datasets", { 'f-dbkey': view.dbkey }, function(tracks) {
- _.each(tracks, function(track) {
+ visualization.select_datasets(galaxy_config.root + "visualization/list_current_history_datasets", galaxy_config.root + "api/datasets", { 'f-dbkey': view.dbkey },
+ function(new_tracks) {
+ _.each(new_tracks, function(track) {
view.add_drawable( tracks.object_from_template(track, view, view) );
});
});
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: greg: Fix missing import in the Tool Shed's ToolValidator.
by commits-noreply@bitbucket.org 23 Jul '14
by commits-noreply@bitbucket.org 23 Jul '14
23 Jul '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/6fbe4d95a8dc/
Changeset: 6fbe4d95a8dc
User: greg
Date: 2014-07-23 22:31:59
Summary: Fix missing import in the Tool Shed's ToolValidator.
Affected #: 1 file
diff -r 7aade8875ea4dde276b33922bbc7fdbc0630a9f5 -r 6fbe4d95a8dc64bd222dbf1170bdadcc5321e855 lib/tool_shed/tools/tool_validator.py
--- a/lib/tool_shed/tools/tool_validator.py
+++ b/lib/tool_shed/tools/tool_validator.py
@@ -12,6 +12,7 @@
from tool_shed.util import hg_util
from tool_shed.util import shed_util_common as suc
from tool_shed.util import tool_util
+from tool_shed.util import xml_util
log = logging.getLogger( __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
3 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/2ae881148949/
Changeset: 2ae881148949
User: dannon
Date: 2014-07-23 21:41:14
Summary: Fix 'decod_id' invocation to use the correct function when deleting user addresses.
Affected #: 1 file
diff -r 053943b668af334c480b464fe7351b50284b7099 -r 2ae881148949596af9c30f2c559dc8f627dda402 lib/galaxy/webapps/galaxy/controllers/user.py
--- a/lib/galaxy/webapps/galaxy/controllers/user.py
+++ b/lib/galaxy/webapps/galaxy/controllers/user.py
@@ -1514,7 +1514,7 @@
@web.expose
def delete_address( self, trans, cntrller, address_id=None, user_id=None ):
try:
- user_address = trans.sa_session.query( trans.app.model.UserAddress ).get( trans.security.decod_id( address_id ) )
+ user_address = trans.sa_session.query( trans.app.model.UserAddress ).get( trans.security.decode_id( address_id ) )
except:
message = 'Invalid address is (%s)' % address_id
status = 'error'
https://bitbucket.org/galaxy/galaxy-central/commits/4974ffd8b2cb/
Changeset: 4974ffd8b2cb
User: dannon
Date: 2014-07-23 21:42:23
Summary: Fix another variable definition issue in user address deletion.
Affected #: 1 file
diff -r 2ae881148949596af9c30f2c559dc8f627dda402 -r 4974ffd8b2cb5ee994a0d517c2332261898d4d46 lib/galaxy/webapps/galaxy/controllers/user.py
--- a/lib/galaxy/webapps/galaxy/controllers/user.py
+++ b/lib/galaxy/webapps/galaxy/controllers/user.py
@@ -1522,7 +1522,7 @@
user_address.deleted = True
trans.sa_session.add( user_address )
trans.sa_session.flush()
- 'Address (%s) deleted' % user_address.desc
+ message = 'Address (%s) deleted' % user_address.desc
status = 'done'
return trans.response.send_redirect( web.url_for( controller='user',
action='manage_user_info',
https://bitbucket.org/galaxy/galaxy-central/commits/7aade8875ea4/
Changeset: 7aade8875ea4
User: dannon
Date: 2014-07-23 22:27:42
Summary: Merge.
Affected #: 60 files
diff -r 4974ffd8b2cb5ee994a0d517c2332261898d4d46 -r 7aade8875ea4dde276b33922bbc7fdbc0630a9f5 lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py
--- a/lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py
+++ b/lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py
@@ -12,7 +12,6 @@
import tool_shed.repository_types.util as rt_util
from tool_shed.util import common_util
-from tool_shed.util import datatype_util
from tool_shed.util import encoding_util
from tool_shed.util import hg_util
from tool_shed.util import readme_util
@@ -25,6 +24,7 @@
from tool_shed.galaxy_install import dependency_display
from tool_shed.galaxy_install import install_manager
+from tool_shed.galaxy_install.datatypes import custom_datatype_manager
from tool_shed.galaxy_install.grids import admin_toolshed_grids
from tool_shed.galaxy_install.metadata.installed_repository_metadata_manager import InstalledRepositoryMetadataManager
from tool_shed.galaxy_install.repair_repository_manager import RepairRepositoryManager
@@ -256,17 +256,17 @@
dmh.remove_from_data_manager( tool_shed_repository )
if tool_shed_repository.includes_datatypes:
# Deactivate proprietary datatypes.
- installed_repository_dict = datatype_util.load_installed_datatypes( trans.app,
- tool_shed_repository,
- repository_install_dir,
- deactivate=True )
+ cdl = custom_datatype_manager.CustomDatatypeLoader( trans.app )
+ installed_repository_dict = cdl.load_installed_datatypes( tool_shed_repository,
+ repository_install_dir,
+ deactivate=True )
if installed_repository_dict:
converter_path = installed_repository_dict.get( 'converter_path' )
if converter_path is not None:
- datatype_util.load_installed_datatype_converters( trans.app, installed_repository_dict, deactivate=True )
+ cdl.load_installed_datatype_converters( installed_repository_dict, deactivate=True )
display_path = installed_repository_dict.get( 'display_path' )
if display_path is not None:
- datatype_util.load_installed_display_applications( trans.app, installed_repository_dict, deactivate=True )
+ cdl.load_installed_display_applications( installed_repository_dict, deactivate=True )
if remove_from_disk_checked:
try:
# Remove the repository from disk.
diff -r 4974ffd8b2cb5ee994a0d517c2332261898d4d46 -r 7aade8875ea4dde276b33922bbc7fdbc0630a9f5 lib/galaxy/webapps/galaxy/controllers/history.py
--- a/lib/galaxy/webapps/galaxy/controllers/history.py
+++ b/lib/galaxy/webapps/galaxy/controllers/history.py
@@ -195,6 +195,7 @@
class HistoryController( BaseUIController, SharableMixin, UsesAnnotations, UsesItemRatings,
UsesHistoryMixin, UsesHistoryDatasetAssociationMixin, ExportsHistoryMixin,
ImportsHistoryMixin ):
+
def __init__( self, app ):
super( HistoryController, self ).__init__( app )
self.mgrs = util.bunch.Bunch(
diff -r 4974ffd8b2cb5ee994a0d517c2332261898d4d46 -r 7aade8875ea4dde276b33922bbc7fdbc0630a9f5 lib/galaxy/webapps/galaxy/controllers/page.py
--- a/lib/galaxy/webapps/galaxy/controllers/page.py
+++ b/lib/galaxy/webapps/galaxy/controllers/page.py
@@ -1,5 +1,6 @@
from sqlalchemy import desc, and_
from galaxy import model, web
+from galaxy import managers
from galaxy.web import error, url_for
from galaxy.model.item_attrs import UsesItemRatings
from galaxy.web.base.controller import BaseUIController, SharableMixin, UsesHistoryMixin, UsesStoredWorkflowMixin, UsesVisualizationMixin
@@ -285,6 +286,12 @@
_page_selection_grid = PageSelectionGrid()
_visualization_selection_grid = VisualizationSelectionGrid()
+ def __init__( self, app ):
+ super( PageController, self ).__init__( app )
+ self.mgrs = util.bunch.Bunch(
+ histories=managers.histories.HistoryManager()
+ )
+
@web.expose
@web.require_login()
def list( self, trans, *args, **kwargs ):
@@ -718,6 +725,7 @@
"""
Returns html suitable for embedding in another page.
"""
+ #TODO: should be moved to history controller and/or called via ajax from the template
history = self.get_history( trans, id, False, True )
if not history:
return None
@@ -729,15 +737,22 @@
hda_dicts = []
datasets = self.get_history_datasets( trans, history )
- for hda in datasets:
- hda_dict = self.get_hda_dict( trans, hda )
- hda_dict[ 'annotation' ] = self.get_item_annotation_str( trans.sa_session, history.user, hda )
- hda_dicts.append( hda_dict )
- history_dict = self.get_history_dict( trans, history, hda_dictionaries=hda_dicts )
- history_dict[ 'annotation' ] = history.annotation
+ #for hda in datasets:
+ # hda_dict = self.get_hda_dict( trans, hda )
+ # hda_dict[ 'annotation' ] = self.get_item_annotation_str( trans.sa_session, history.user, hda )
+ # hda_dicts.append( hda_dict )
+ #history_dict = self.get_history_dict( trans, history, hda_dictionaries=hda_dicts )
+ #history_dict[ 'annotation' ] = history.annotation
+
+ # include all datasets: hidden, deleted, and purged
+ #TODO!: doubled query (hda_dictionaries + datasets)
+ history_data = self.mgrs.histories._get_history_data( trans, history )
+ history_dictionary = history_data[ 'history' ]
+ hda_dictionaries = history_data[ 'contents' ]
+ history_dictionary[ 'annotation' ] = history.annotation
filled = trans.fill_template( "history/embed.mako", item=history, item_data=datasets,
- user_is_owner=user_is_owner, history_dict=history_dict, hda_dicts=hda_dicts )
+ user_is_owner=user_is_owner, history_dict=history_dictionary, hda_dicts=hda_dictionaries )
return filled
def _get_embed_html( self, trans, item_class, item_id ):
diff -r 4974ffd8b2cb5ee994a0d517c2332261898d4d46 -r 7aade8875ea4dde276b33922bbc7fdbc0630a9f5 lib/galaxy/webapps/tool_shed/controllers/repository.py
--- a/lib/galaxy/webapps/tool_shed/controllers/repository.py
+++ b/lib/galaxy/webapps/tool_shed/controllers/repository.py
@@ -1062,7 +1062,7 @@
action='browse_repositories',
message=message,
status=status ) )
- name = kwd.get( 'name', '' )
+ name = kwd.get( 'name', '' ).strip()
description = kwd.get( 'description', '' )
long_description = kwd.get( 'long_description', '' )
category_ids = util.listify( kwd.get( 'category_id', '' ) )
@@ -1262,7 +1262,11 @@
repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans.app, repository_id, changeset_revision )
metadata = repository_metadata.metadata
toolshed_base_url = str( web.url_for( '/', qualified=True ) ).rstrip( '/' )
+ # Initialize the repository dependency RelationBuilder.
rb = relation_builder.RelationBuilder( trans.app, repository, repository_metadata, toolshed_base_url )
+ # Work-around to ensure repositories that contain packages needed only for compiling
+ # a dependent package are included in the capsule.
+ rb.set_filter_dependencies_needed_for_compiling( False )
# Get a dictionary of all repositories upon which the contents of the current repository_metadata record depend.
repository_dependencies = rb.get_repository_dependencies_for_changeset_revision()
if repository_dependencies:
diff -r 4974ffd8b2cb5ee994a0d517c2332261898d4d46 -r 7aade8875ea4dde276b33922bbc7fdbc0630a9f5 lib/tool_shed/capsule/capsule_manager.py
--- a/lib/tool_shed/capsule/capsule_manager.py
+++ b/lib/tool_shed/capsule/capsule_manager.py
@@ -245,9 +245,13 @@
repository_metadata = suc.get_repository_metadata_by_changeset_revision( self.app,
self.repository_id,
self.changeset_revision )
- # Get a dictionary of all repositories upon which the contents of the current repository_metadata record depend.
+ # Get a dictionary of all repositories upon which the contents of the current
+ # repository_metadata record depend.
toolshed_base_url = str( web.url_for( '/', qualified=True ) ).rstrip( '/' )
rb = RelationBuilder( self.app, repository, repository_metadata, toolshed_base_url )
+ # Work-around to ensure repositories that contain packages needed only for compiling
+ # a dependent package are included in the capsule.
+ rb.set_filter_dependencies_needed_for_compiling( False )
repository_dependencies = rb.get_repository_dependencies_for_changeset_revision()
repo = hg_util.get_repo_for_repository( self.app,
repository=self.repository,
diff -r 4974ffd8b2cb5ee994a0d517c2332261898d4d46 -r 7aade8875ea4dde276b33922bbc7fdbc0630a9f5 lib/tool_shed/dependencies/repository/relation_builder.py
--- a/lib/tool_shed/dependencies/repository/relation_builder.py
+++ b/lib/tool_shed/dependencies/repository/relation_builder.py
@@ -23,6 +23,11 @@
self.handled_key_rd_dicts = []
self.key_rd_dicts_to_be_processed = []
self.tool_shed_url = tool_shed_url
+ # This is a temporary work-around for handling repository dependencies that are needed
+ # only if compiling a dependent package. This value should be True unless exporting
+ # a repository capsule, in which case the set_filter_dependencies_needed_for_compiling()
+ # function is called.
+ self.filter_dependencies_needed_for_compiling = True
def can_add_to_key_rd_dicts( self, key_rd_dict, key_rd_dicts ):
"""Handle the case where an update to the changeset revision was done."""
@@ -389,9 +394,12 @@
current_repository_key_rd_dicts = \
self.get_updated_changeset_revisions_for_repository_dependencies( current_repository_key_rd_dicts )
for key_rd_dict in current_repository_key_rd_dicts:
- # Filter out repository dependencies that are required only if compiling the dependent
- # repository's tool dependency.
- key_rd_dict = self.filter_only_if_compiling_contained_td( key_rd_dict )
+ if self.filter_dependencies_needed_for_compiling:
+ # Filter out repository dependencies that are required only if compiling the dependent
+ # repository's tool dependency.
+ # TODO: this temporary work-around should be removed when the underlying framework
+ # support for handling only_if_compiling_contained_td-flagged repositories is completed.
+ key_rd_dict = self.filter_only_if_compiling_contained_td( key_rd_dict )
if key_rd_dict:
is_circular = False
in_handled_key_rd_dicts = self.in_key_rd_dicts( key_rd_dict, self.handled_key_rd_dicts )
@@ -483,6 +491,9 @@
clean_key_rd_dicts.append( new_key_rd_dict )
return clean_key_rd_dicts
+ def set_filter_dependencies_needed_for_compiling( self, value ):
+ self.filter_dependencies_needed_for_compiling = asbool( value )
+
def update_circular_repository_dependencies( self, repository_key, repository_dependency, repository_dependencies ):
repository_dependency_as_key = self.get_repository_dependency_as_key( repository_dependency )
repository_key_as_repository_dependency = repository_key.split( container_util.STRSEP )
diff -r 4974ffd8b2cb5ee994a0d517c2332261898d4d46 -r 7aade8875ea4dde276b33922bbc7fdbc0630a9f5 lib/tool_shed/galaxy_install/datatypes/custom_datatype_manager.py
--- /dev/null
+++ b/lib/tool_shed/galaxy_install/datatypes/custom_datatype_manager.py
@@ -0,0 +1,218 @@
+import logging
+import os
+import tempfile
+
+from galaxy.util import asbool
+
+from tool_shed.util import basic_util
+from tool_shed.util import hg_util
+from tool_shed.util import tool_util
+from tool_shed.util import shed_util_common as suc
+from tool_shed.util import xml_util
+
+log = logging.getLogger( __name__ )
+
+
+class CustomDatatypeLoader( object ):
+
+ def __init__( self, app ):
+ self.app = app
+
+ def alter_config_and_load_prorietary_datatypes( self, datatypes_config, relative_install_dir,
+ deactivate=False, override=True ):
+ """
+ Parse a custom datatypes config (a datatypes_conf.xml file included in an installed
+ tool shed repository) and add information to appropriate element attributes that will
+ enable custom datatype class modules, datatypes converters and display applications
+ to be discovered and properly imported by the datatypes registry. The value of override
+ will be False when a tool shed repository is being installed. Since installation is
+ occurring after the datatypes registry has been initialized, the registry's contents
+ cannot be overridden by conflicting data types.
+ """
+ tree, error_message = xml_util.parse_xml( datatypes_config )
+ if tree is None:
+ return None, None
+ datatypes_config_root = tree.getroot()
+ registration = datatypes_config_root.find( 'registration' )
+ if registration is None:
+ # We have valid XML, but not a valid custom datatypes definition.
+ return None, None
+ sniffers = datatypes_config_root.find( 'sniffers' )
+ converter_path, display_path = self.get_converter_and_display_paths( registration,
+ relative_install_dir )
+ if converter_path:
+ # Path to datatype converters
+ registration.attrib[ 'proprietary_converter_path' ] = converter_path
+ if display_path:
+ # Path to datatype display applications
+ registration.attrib[ 'proprietary_display_path' ] = display_path
+ relative_path_to_datatype_file_name = None
+ datatype_files = datatypes_config_root.find( 'datatype_files' )
+ datatype_class_modules = []
+ if datatype_files is not None:
+ # The <datatype_files> tag set contains any number of <datatype_file> tags.
+ # <datatype_files>
+ # <datatype_file name="gmap.py"/>
+ # <datatype_file name="metagenomics.py"/>
+ # </datatype_files>
+ # We'll add attributes to the datatype tag sets so that the modules can be properly imported
+ # by the datatypes registry.
+ for elem in datatype_files.findall( 'datatype_file' ):
+ datatype_file_name = elem.get( 'name', None )
+ if datatype_file_name:
+ # Find the file in the installed repository.
+ for root, dirs, files in os.walk( relative_install_dir ):
+ if root.find( '.hg' ) < 0:
+ for name in files:
+ if name == datatype_file_name:
+ datatype_class_modules.append( os.path.join( root, name ) )
+ break
+ break
+ if datatype_class_modules:
+ for relative_path_to_datatype_file_name in datatype_class_modules:
+ datatype_file_name_path, datatype_file_name = os.path.split( relative_path_to_datatype_file_name )
+ for elem in registration.findall( 'datatype' ):
+ # Handle 'type' attribute which should be something like one of the following:
+ # type="gmap:GmapDB"
+ # type="galaxy.datatypes.gmap:GmapDB"
+ dtype = elem.get( 'type', None )
+ if dtype:
+ fields = dtype.split( ':' )
+ proprietary_datatype_module = fields[ 0 ]
+ if proprietary_datatype_module.find( '.' ) >= 0:
+ # Handle the case where datatype_module is "galaxy.datatypes.gmap".
+ proprietary_datatype_module = proprietary_datatype_module.split( '.' )[ -1 ]
+ # The value of proprietary_path must be an absolute path due to job_working_directory.
+ elem.attrib[ 'proprietary_path' ] = os.path.abspath( datatype_file_name_path )
+ elem.attrib[ 'proprietary_datatype_module' ] = proprietary_datatype_module
+ # Temporarily persist the custom datatypes configuration file so it can be loaded into the
+ # datatypes registry.
+ fd, proprietary_datatypes_config = tempfile.mkstemp( prefix="tmp-toolshed-acalpd" )
+ os.write( fd, '<?xml version="1.0"?>\n' )
+ os.write( fd, '<datatypes>\n' )
+ os.write( fd, '%s' % xml_util.xml_to_string( registration ) )
+ if sniffers is not None:
+ os.write( fd, '%s' % xml_util.xml_to_string( sniffers ) )
+ os.write( fd, '</datatypes>\n' )
+ os.close( fd )
+ os.chmod( proprietary_datatypes_config, 0644 )
+ # Load custom datatypes
+ self.app.datatypes_registry.load_datatypes( root_dir=self.app.config.root,
+ config=proprietary_datatypes_config,
+ deactivate=deactivate,
+ override=override )
+ if deactivate:
+ # Reload the upload tool to eliminate deactivated datatype extensions from the file_type
+ # select list.
+ tool_util.reload_upload_tools( self.app )
+ else:
+ self.append_to_datatypes_registry_upload_file_formats( registration )
+ tool_util.reload_upload_tools( self.app )
+ if datatype_files is not None:
+ try:
+ os.unlink( proprietary_datatypes_config )
+ except:
+ pass
+ return converter_path, display_path
+
+ def append_to_datatypes_registry_upload_file_formats( self, elem ):
+ # See if we have any datatypes that should be displayed in the upload tool's file_type select list.
+ for datatype_elem in elem.findall( 'datatype' ):
+ extension = datatype_elem.get( 'extension', None )
+ display_in_upload = datatype_elem.get( 'display_in_upload', None )
+ if extension is not None and display_in_upload is not None:
+ display_in_upload = asbool( str( display_in_upload ) )
+ if display_in_upload and extension not in self.app.datatypes_registry.upload_file_formats:
+ self.app.datatypes_registry.upload_file_formats.append( extension )
+
+ def create_repository_dict_for_proprietary_datatypes( self, tool_shed, name, owner, installed_changeset_revision,
+ tool_dicts, converter_path=None, display_path=None ):
+ return dict( tool_shed=tool_shed,
+ repository_name=name,
+ repository_owner=owner,
+ installed_changeset_revision=installed_changeset_revision,
+ tool_dicts=tool_dicts,
+ converter_path=converter_path,
+ display_path=display_path )
+
+ def get_converter_and_display_paths( self, registration_elem, relative_install_dir ):
+ """
+ Find the relative path to data type converters and display applications included
+ in installed tool shed repositories.
+ """
+ converter_path = None
+ display_path = None
+ for elem in registration_elem.findall( 'datatype' ):
+ if not converter_path:
+ # If any of the <datatype> tag sets contain <converter> tags, set the converter_path
+ # if it is not already set. This requires developers to place all converters in the
+ # same subdirectory within the repository hierarchy.
+ for converter in elem.findall( 'converter' ):
+ converter_config = converter.get( 'file', None )
+ if converter_config:
+ converter_config_file_name = basic_util.strip_path( converter_config )
+ for root, dirs, files in os.walk( relative_install_dir ):
+ if root.find( '.hg' ) < 0:
+ for name in files:
+ if name == converter_config_file_name:
+ # The value of converter_path must be absolute due to job_working_directory.
+ converter_path = os.path.abspath( root )
+ break
+ if converter_path:
+ break
+ if not display_path:
+ # If any of the <datatype> tag sets contain <display> tags, set the display_path
+ # if it is not already set. This requires developers to place all display acpplications
+ # in the same subdirectory within the repository hierarchy.
+ for display_app in elem.findall( 'display' ):
+ display_config = display_app.get( 'file', None )
+ if display_config:
+ display_config_file_name = basic_util.strip_path( display_config )
+ for root, dirs, files in os.walk( relative_install_dir ):
+ if root.find( '.hg' ) < 0:
+ for name in files:
+ if name == display_config_file_name:
+ # The value of display_path must be absolute due to job_working_directory.
+ display_path = os.path.abspath( root )
+ break
+ if display_path:
+ break
+ if converter_path and display_path:
+ break
+ return converter_path, display_path
+
+ def load_installed_datatype_converters( self, installed_repository_dict, deactivate=False ):
+ """Load or deactivate proprietary datatype converters."""
+ self.app.datatypes_registry.load_datatype_converters( self.app.toolbox,
+ installed_repository_dict=installed_repository_dict,
+ deactivate=deactivate )
+
+ def load_installed_datatypes( self, repository, relative_install_dir, deactivate=False ):
+ """
+ Load proprietary datatypes and return information needed for loading custom
+ datatypes converters and display applications later.
+ """
+ metadata = repository.metadata
+ repository_dict = None
+ datatypes_config = hg_util.get_config_from_disk( suc.DATATYPES_CONFIG_FILENAME, relative_install_dir )
+ if datatypes_config:
+ converter_path, display_path = \
+ self.alter_config_and_load_prorietary_datatypes( datatypes_config,
+ relative_install_dir,
+ deactivate=deactivate )
+ if converter_path or display_path:
+ # Create a dictionary of tool shed repository related information.
+ repository_dict = \
+ self.create_repository_dict_for_proprietary_datatypes( tool_shed=repository.tool_shed,
+ name=repository.name,
+ owner=repository.owner,
+ installed_changeset_revision=repository.installed_changeset_revision,
+ tool_dicts=metadata.get( 'tools', [] ),
+ converter_path=converter_path,
+ display_path=display_path )
+ return repository_dict
+
+ def load_installed_display_applications( self, installed_repository_dict, deactivate=False ):
+ """Load or deactivate custom datatype display applications."""
+ self.app.datatypes_registry.load_display_applications( installed_repository_dict=installed_repository_dict,
+ deactivate=deactivate )
diff -r 4974ffd8b2cb5ee994a0d517c2332261898d4d46 -r 7aade8875ea4dde276b33922bbc7fdbc0630a9f5 lib/tool_shed/galaxy_install/install_manager.py
--- a/lib/tool_shed/galaxy_install/install_manager.py
+++ b/lib/tool_shed/galaxy_install/install_manager.py
@@ -18,7 +18,6 @@
from tool_shed.util import basic_util
from tool_shed.util import common_util
-from tool_shed.util import datatype_util
from tool_shed.util import encoding_util
from tool_shed.util import hg_util
from tool_shed.util import shed_util_common as suc
@@ -26,6 +25,7 @@
from tool_shed.util import tool_util
from tool_shed.util import xml_util
+from tool_shed.galaxy_install.datatypes import custom_datatype_manager
from tool_shed.galaxy_install.metadata.installed_repository_metadata_manager import InstalledRepositoryMetadataManager
from tool_shed.galaxy_install.repository_dependencies import repository_dependency_manager
from tool_shed.galaxy_install.tool_dependencies.recipe.env_file_builder import EnvFileBuilder
@@ -594,18 +594,19 @@
files_dir = os.path.join( shed_config_dict[ 'tool_path' ], files_dir )
datatypes_config = hg_util.get_config_from_disk( suc.DATATYPES_CONFIG_FILENAME, files_dir )
# Load data types required by tools.
+ cdl = custom_datatype_manager.CustomDatatypeLoader( self.app )
converter_path, display_path = \
- datatype_util.alter_config_and_load_prorietary_datatypes( self.app, datatypes_config, files_dir, override=False )
+ cdl.alter_config_and_load_prorietary_datatypes( datatypes_config, files_dir, override=False )
if converter_path or display_path:
# Create a dictionary of tool shed repository related information.
repository_dict = \
- datatype_util.create_repository_dict_for_proprietary_datatypes( tool_shed=tool_shed,
- name=tool_shed_repository.name,
- owner=tool_shed_repository.owner,
- installed_changeset_revision=tool_shed_repository.installed_changeset_revision,
- tool_dicts=metadata_dict.get( 'tools', [] ),
- converter_path=converter_path,
- display_path=display_path )
+ cdl.create_repository_dict_for_proprietary_datatypes( tool_shed=tool_shed,
+ name=tool_shed_repository.name,
+ owner=tool_shed_repository.owner,
+ installed_changeset_revision=tool_shed_repository.installed_changeset_revision,
+ tool_dicts=metadata_dict.get( 'tools', [] ),
+ converter_path=converter_path,
+ display_path=display_path )
if converter_path:
# Load proprietary datatype converters
self.app.datatypes_registry.load_datatype_converters( self.app.toolbox, installed_repository_dict=repository_dict )
diff -r 4974ffd8b2cb5ee994a0d517c2332261898d4d46 -r 7aade8875ea4dde276b33922bbc7fdbc0630a9f5 lib/tool_shed/galaxy_install/installed_repository_manager.py
--- a/lib/tool_shed/galaxy_install/installed_repository_manager.py
+++ b/lib/tool_shed/galaxy_install/installed_repository_manager.py
@@ -7,12 +7,12 @@
from galaxy import util
from tool_shed.util import common_util
from tool_shed.util import container_util
-from tool_shed.util import datatype_util
from tool_shed.util import shed_util_common as suc
from tool_shed.util import tool_dependency_util
from tool_shed.util import xml_util
from galaxy.model.orm import and_
+from tool_shed.galaxy_install.datatypes import custom_datatype_manager
from tool_shed.galaxy_install.metadata.installed_repository_metadata_manager import InstalledRepositoryMetadataManager
from tool_shed.galaxy_install.repository_dependencies import repository_dependency_manager
from tool_shed.galaxy_install.tools import data_manager
@@ -114,17 +114,17 @@
else:
repository_install_dir = os.path.abspath( relative_install_dir )
# Activate proprietary datatypes.
- installed_repository_dict = datatype_util.load_installed_datatypes( self.app,
- repository,
- repository_install_dir,
- deactivate=False )
+ cdl = custom_datatype_manager.CustomDatatypeLoader( self.app )
+ installed_repository_dict = cdl.load_installed_datatypes( repository,
+ repository_install_dir,
+ deactivate=False )
if installed_repository_dict:
converter_path = installed_repository_dict.get( 'converter_path' )
if converter_path is not None:
- datatype_util.load_installed_datatype_converters( self.app, installed_repository_dict, deactivate=False )
+ cdl.load_installed_datatype_converters( installed_repository_dict, deactivate=False )
display_path = installed_repository_dict.get( 'display_path' )
if display_path is not None:
- datatype_util.load_installed_display_applications( self.app, installed_repository_dict, deactivate=False )
+ cdl.load_installed_display_applications( installed_repository_dict, deactivate=False )
def add_entry_to_installed_repository_dependencies_of_installed_repositories( self, repository ):
"""
@@ -732,22 +732,24 @@
self.add_entry_to_installed_runtime_dependent_tool_dependencies_of_installed_tool_dependencies( tool_dependency )
def load_proprietary_datatypes( self ):
+ cdl = custom_datatype_manager.CustomDatatypeLoader( self.app )
for tool_shed_repository in self.context.query( self.install_model.ToolShedRepository ) \
- .filter( and_( self.install_model.ToolShedRepository.table.c.includes_datatypes==True,
- self.install_model.ToolShedRepository.table.c.deleted==False ) ) \
- .order_by( self.install_model.ToolShedRepository.table.c.id ):
+ .filter( and_( self.install_model.ToolShedRepository.table.c.includes_datatypes==True,
+ self.install_model.ToolShedRepository.table.c.deleted==False ) ) \
+ .order_by( self.install_model.ToolShedRepository.table.c.id ):
relative_install_dir = self.get_repository_install_dir( tool_shed_repository )
if relative_install_dir:
- installed_repository_dict = datatype_util.load_installed_datatypes( self.app, tool_shed_repository, relative_install_dir )
+ installed_repository_dict = cdl.load_installed_datatypes( tool_shed_repository, relative_install_dir )
if installed_repository_dict:
self.installed_repository_dicts.append( installed_repository_dict )
def load_proprietary_converters_and_display_applications( self, deactivate=False ):
+ cdl = custom_datatype_manager.CustomDatatypeLoader( self.app )
for installed_repository_dict in self.installed_repository_dicts:
if installed_repository_dict[ 'converter_path' ]:
- datatype_util.load_installed_datatype_converters( self.app, installed_repository_dict, deactivate=deactivate )
+ cdl.load_installed_datatype_converters( installed_repository_dict, deactivate=deactivate )
if installed_repository_dict[ 'display_path' ]:
- datatype_util.load_installed_display_applications( self.app, installed_repository_dict, deactivate=deactivate )
+ cdl.load_installed_display_applications( installed_repository_dict, deactivate=deactivate )
def purge_repository( self, repository ):
"""Purge a repository with status New (a white ghost) from the database."""
diff -r 4974ffd8b2cb5ee994a0d517c2332261898d4d46 -r 7aade8875ea4dde276b33922bbc7fdbc0630a9f5 lib/tool_shed/galaxy_install/tool_migration_manager.py
--- a/lib/tool_shed/galaxy_install/tool_migration_manager.py
+++ b/lib/tool_shed/galaxy_install/tool_migration_manager.py
@@ -14,6 +14,7 @@
from galaxy.util.odict import odict
from tool_shed.galaxy_install import install_manager
+from tool_shed.galaxy_install.datatypes import custom_datatype_manager
from tool_shed.galaxy_install.metadata.installed_repository_metadata_manager import InstalledRepositoryMetadataManager
from tool_shed.galaxy_install.tools import tool_panel_manager
@@ -22,7 +23,6 @@
from tool_shed.util import basic_util
from tool_shed.util import common_util
-from tool_shed.util import datatype_util
from tool_shed.util import hg_util
from tool_shed.util import shed_util_common as suc
from tool_shed.util import tool_dependency_util
@@ -492,6 +492,7 @@
print '\nThe ToolMigrationManager returned the following error while installing tool dependency ', installed_tool_dependency.name, ':'
print installed_tool_dependency.error_message, '\n\n'
if 'datatypes' in metadata_dict:
+ cdl = custom_datatype_manager.CustomDatatypeLoader( self.app )
tool_shed_repository.status = self.app.install_model.ToolShedRepository.installation_status.LOADING_PROPRIETARY_DATATYPES
if not tool_shed_repository.includes_datatypes:
tool_shed_repository.includes_datatypes = True
@@ -499,21 +500,27 @@
self.app.install_model.context.flush()
work_dir = tempfile.mkdtemp( prefix="tmp-toolshed-hrc" )
datatypes_config = hg_util.get_config_from_disk( suc.DATATYPES_CONFIG_FILENAME, repo_install_dir )
- # Load proprietary data types required by tools. The value of override is not important here since the Galaxy server will be started
- # after this installation completes.
- converter_path, display_path = datatype_util.alter_config_and_load_prorietary_datatypes( self.app, datatypes_config, repo_install_dir, override=False ) #repo_install_dir was relative_install_dir
+ # Load proprietary data types required by tools. The value of override is not
+ # important here since the Galaxy server will be started after this installation
+ #completes.
+ converter_path, display_path = \
+ cdl.alter_config_and_load_prorietary_datatypes( datatypes_config,
+ repo_install_dir,
+ override=False )
if converter_path or display_path:
# Create a dictionary of tool shed repository related information.
- repository_dict = datatype_util.create_repository_dict_for_proprietary_datatypes( tool_shed=self.tool_shed_url,
- name=tool_shed_repository.name,
- owner=self.repository_owner,
- installed_changeset_revision=tool_shed_repository.installed_changeset_revision,
- tool_dicts=metadata_dict.get( 'tools', [] ),
- converter_path=converter_path,
- display_path=display_path )
+ repository_dict = \
+ cdl.create_repository_dict_for_proprietary_datatypes( tool_shed=self.tool_shed_url,
+ name=tool_shed_repository.name,
+ owner=self.repository_owner,
+ installed_changeset_revision=tool_shed_repository.installed_changeset_revision,
+ tool_dicts=metadata_dict.get( 'tools', [] ),
+ converter_path=converter_path,
+ display_path=display_path )
if converter_path:
# Load proprietary datatype converters
- self.app.datatypes_registry.load_datatype_converters( self.toolbox, installed_repository_dict=repository_dict )
+ self.app.datatypes_registry.load_datatype_converters( self.toolbox,
+ installed_repository_dict=repository_dict )
if display_path:
# Load proprietary datatype display applications
self.app.datatypes_registry.load_display_applications( installed_repository_dict=repository_dict )
diff -r 4974ffd8b2cb5ee994a0d517c2332261898d4d46 -r 7aade8875ea4dde276b33922bbc7fdbc0630a9f5 lib/tool_shed/util/datatype_util.py
--- a/lib/tool_shed/util/datatype_util.py
+++ /dev/null
@@ -1,187 +0,0 @@
-import logging
-import os
-import tempfile
-from galaxy import eggs
-from galaxy.util import asbool
-from tool_shed.util import basic_util
-from tool_shed.util import hg_util
-from tool_shed.util import tool_util
-from tool_shed.util import xml_util
-import tool_shed.util.shed_util_common as suc
-
-log = logging.getLogger( __name__ )
-
-def alter_config_and_load_prorietary_datatypes( app, datatypes_config, relative_install_dir, deactivate=False, override=True ):
- """
- Parse a proprietary datatypes config (a datatypes_conf.xml file included in an installed tool shed repository) and
- add information to appropriate element attributes that will enable proprietary datatype class modules, datatypes converters
- and display applications to be discovered and properly imported by the datatypes registry. The value of override will
- be False when a tool shed repository is being installed. Since installation is occurring after the datatypes registry
- has been initialized, the registry's contents cannot be overridden by conflicting data types.
- """
- tree, error_message = xml_util.parse_xml( datatypes_config )
- if tree is None:
- return None, None
- datatypes_config_root = tree.getroot()
- registration = datatypes_config_root.find( 'registration' )
- if registration is None:
- # We have valid XML, but not a valid proprietary datatypes definition.
- return None, None
- sniffers = datatypes_config_root.find( 'sniffers' )
- converter_path, display_path = get_converter_and_display_paths( registration, relative_install_dir )
- if converter_path:
- # Path to datatype converters
- registration.attrib[ 'proprietary_converter_path' ] = converter_path
- if display_path:
- # Path to datatype display applications
- registration.attrib[ 'proprietary_display_path' ] = display_path
- relative_path_to_datatype_file_name = None
- datatype_files = datatypes_config_root.find( 'datatype_files' )
- datatype_class_modules = []
- if datatype_files is not None:
- # The <datatype_files> tag set contains any number of <datatype_file> tags.
- # <datatype_files>
- # <datatype_file name="gmap.py"/>
- # <datatype_file name="metagenomics.py"/>
- # </datatype_files>
- # We'll add attributes to the datatype tag sets so that the modules can be properly imported by the datatypes registry.
- for elem in datatype_files.findall( 'datatype_file' ):
- datatype_file_name = elem.get( 'name', None )
- if datatype_file_name:
- # Find the file in the installed repository.
- for root, dirs, files in os.walk( relative_install_dir ):
- if root.find( '.hg' ) < 0:
- for name in files:
- if name == datatype_file_name:
- datatype_class_modules.append( os.path.join( root, name ) )
- break
- break
- if datatype_class_modules:
- for relative_path_to_datatype_file_name in datatype_class_modules:
- datatype_file_name_path, datatype_file_name = os.path.split( relative_path_to_datatype_file_name )
- for elem in registration.findall( 'datatype' ):
- # Handle 'type' attribute which should be something like one of the following:
- # type="gmap:GmapDB"
- # type="galaxy.datatypes.gmap:GmapDB"
- dtype = elem.get( 'type', None )
- if dtype:
- fields = dtype.split( ':' )
- proprietary_datatype_module = fields[ 0 ]
- if proprietary_datatype_module.find( '.' ) >= 0:
- # Handle the case where datatype_module is "galaxy.datatypes.gmap".
- proprietary_datatype_module = proprietary_datatype_module.split( '.' )[ -1 ]
- # The value of proprietary_path must be an absolute path due to job_working_directory.
- elem.attrib[ 'proprietary_path' ] = os.path.abspath( datatype_file_name_path )
- elem.attrib[ 'proprietary_datatype_module' ] = proprietary_datatype_module
- # Temporarily persist the proprietary datatypes configuration file so it can be loaded into the datatypes registry.
- fd, proprietary_datatypes_config = tempfile.mkstemp( prefix="tmp-toolshed-acalpd" )
- os.write( fd, '<?xml version="1.0"?>\n' )
- os.write( fd, '<datatypes>\n' )
- os.write( fd, '%s' % xml_util.xml_to_string( registration ) )
- if sniffers is not None:
- os.write( fd, '%s' % xml_util.xml_to_string( sniffers ) )
- os.write( fd, '</datatypes>\n' )
- os.close( fd )
- os.chmod( proprietary_datatypes_config, 0644 )
- # Load proprietary datatypes
- app.datatypes_registry.load_datatypes( root_dir=app.config.root, config=proprietary_datatypes_config, deactivate=deactivate, override=override )
- if deactivate:
- # Reload the upload tool to eliminate deactivated datatype extensions from the file_type select list.
- tool_util.reload_upload_tools( app )
- else:
- append_to_datatypes_registry_upload_file_formats( app, registration )
- tool_util.reload_upload_tools( app )
- if datatype_files is not None:
- try:
- os.unlink( proprietary_datatypes_config )
- except:
- pass
- return converter_path, display_path
-
-def append_to_datatypes_registry_upload_file_formats( app, elem ):
- # See if we have any datatypes that should be displayed in the upload tool's file_type select list.
- for datatype_elem in elem.findall( 'datatype' ):
- extension = datatype_elem.get( 'extension', None )
- display_in_upload = datatype_elem.get( 'display_in_upload', None )
- if extension is not None and display_in_upload is not None:
- display_in_upload = asbool( str( display_in_upload ) )
- if display_in_upload and extension not in app.datatypes_registry.upload_file_formats:
- app.datatypes_registry.upload_file_formats.append( extension )
-
-def create_repository_dict_for_proprietary_datatypes( tool_shed, name, owner, installed_changeset_revision, tool_dicts, converter_path=None, display_path=None ):
- return dict( tool_shed=tool_shed,
- repository_name=name,
- repository_owner=owner,
- installed_changeset_revision=installed_changeset_revision,
- tool_dicts=tool_dicts,
- converter_path=converter_path,
- display_path=display_path )
-
-def get_converter_and_display_paths( registration_elem, relative_install_dir ):
- """Find the relative path to data type converters and display applications included in installed tool shed repositories."""
- converter_path = None
- display_path = None
- for elem in registration_elem.findall( 'datatype' ):
- if not converter_path:
- # If any of the <datatype> tag sets contain <converter> tags, set the converter_path
- # if it is not already set. This requires developers to place all converters in the
- # same subdirectory within the repository hierarchy.
- for converter in elem.findall( 'converter' ):
- converter_config = converter.get( 'file', None )
- if converter_config:
- converter_config_file_name = basic_util.strip_path( converter_config )
- for root, dirs, files in os.walk( relative_install_dir ):
- if root.find( '.hg' ) < 0:
- for name in files:
- if name == converter_config_file_name:
- # The value of converter_path must be absolute due to job_working_directory.
- converter_path = os.path.abspath( root )
- break
- if converter_path:
- break
- if not display_path:
- # If any of the <datatype> tag sets contain <display> tags, set the display_path
- # if it is not already set. This requires developers to place all display acpplications
- # in the same subdirectory within the repository hierarchy.
- for display_app in elem.findall( 'display' ):
- display_config = display_app.get( 'file', None )
- if display_config:
- display_config_file_name = basic_util.strip_path( display_config )
- for root, dirs, files in os.walk( relative_install_dir ):
- if root.find( '.hg' ) < 0:
- for name in files:
- if name == display_config_file_name:
- # The value of display_path must be absolute due to job_working_directory.
- display_path = os.path.abspath( root )
- break
- if display_path:
- break
- if converter_path and display_path:
- break
- return converter_path, display_path
-
-def load_installed_datatype_converters( app, installed_repository_dict, deactivate=False ):
- # Load or deactivate proprietary datatype converters
- app.datatypes_registry.load_datatype_converters( app.toolbox, installed_repository_dict=installed_repository_dict, deactivate=deactivate )
-
-def load_installed_datatypes( app, repository, relative_install_dir, deactivate=False ):
- # Load proprietary datatypes and return information needed for loading proprietary datatypes converters and display applications later.
- metadata = repository.metadata
- repository_dict = None
- datatypes_config = hg_util.get_config_from_disk( suc.DATATYPES_CONFIG_FILENAME, relative_install_dir )
- if datatypes_config:
- converter_path, display_path = alter_config_and_load_prorietary_datatypes( app, datatypes_config, relative_install_dir, deactivate=deactivate )
- if converter_path or display_path:
- # Create a dictionary of tool shed repository related information.
- repository_dict = create_repository_dict_for_proprietary_datatypes( tool_shed=repository.tool_shed,
- name=repository.name,
- owner=repository.owner,
- installed_changeset_revision=repository.installed_changeset_revision,
- tool_dicts=metadata.get( 'tools', [] ),
- converter_path=converter_path,
- display_path=display_path )
- return repository_dict
-
-def load_installed_display_applications( app, installed_repository_dict, deactivate=False ):
- # Load or deactivate proprietary datatype display applications
- app.datatypes_registry.load_display_applications( installed_repository_dict=installed_repository_dict, deactivate=deactivate )
diff -r 4974ffd8b2cb5ee994a0d517c2332261898d4d46 -r 7aade8875ea4dde276b33922bbc7fdbc0630a9f5 static/scripts/mvc/base-mvc.js
--- a/static/scripts/mvc/base-mvc.js
+++ b/static/scripts/mvc/base-mvc.js
@@ -14,7 +14,7 @@
* @example
* // Add to your models/views at the definition using chaining:
* var MyModel = Backbone.Model.extend( LoggableMixin ).extend({ // ... });
- *
+ *
* // or - more explicitly AFTER the definition:
* var MyModel = Backbone.Model.extend({
* logger : console
@@ -208,8 +208,23 @@
};
//==============================================================================
-return {
- LoggableMixin : LoggableMixin,
- SessionStorageModel : SessionStorageModel,
- HiddenUntilActivatedViewMixin : HiddenUntilActivatedViewMixin
-};});
+function mixin( mixinHash1, /* mixinHash2, etc: ... variadic */ propsHash ){
+ // usage: var NewModel = Something.extend( mixin( MyMixinA, MyMixinB, { ... }) );
+ //NOTE: this does not combine any hashes (like events, etc.) and you're expected to handle that
+
+ // simple reversal of param order on _.defaults() - to show mixins in top of definition
+ var args = Array.prototype.slice.call( arguments, 0 ),
+ lastArg = args.pop();
+ args.unshift( lastArg );
+ return _.defaults.apply( _, args );
+}
+
+
+//==============================================================================
+ return {
+ LoggableMixin : LoggableMixin,
+ SessionStorageModel : SessionStorageModel,
+ HiddenUntilActivatedViewMixin : HiddenUntilActivatedViewMixin,
+ mixin : mixin
+ };
+});
diff -r 4974ffd8b2cb5ee994a0d517c2332261898d4d46 -r 7aade8875ea4dde276b33922bbc7fdbc0630a9f5 static/scripts/mvc/collection/collection-model.js
--- /dev/null
+++ b/static/scripts/mvc/collection/collection-model.js
@@ -0,0 +1,250 @@
+define([
+ "mvc/dataset/hda-model",
+ "mvc/base-mvc",
+ "utils/localization"
+], function( HDA_MODEL, BASE_MVC, _l ){
+//==============================================================================
+/** @class Backbone model for Dataset collection elements.
+ * DC Elements contain a sub-model named 'object'. This class moves that
+ * 'object' from the JSON in the attributes list to a full, instantiated
+ * sub-model found in this.object. This is done on intialization and
+ * everytime the 'change:object' event is fired.
+ *
+ * @borrows LoggableMixin#logger as #logger
+ * @borrows LoggableMixin#log as #log
+ * @constructs
+ */
+var DatasetCollectionElement = Backbone.Model.extend( BASE_MVC.LoggableMixin ).extend(
+/** @lends DatasetCollectionElement.prototype */{
+ //TODO:?? this model may be unneccessary - it reflects the api structure, but...
+ // if we munge the element with the element.object at parse, we can flatten the entire hierarchy
+
+ /** logger used to record this.log messages, commonly set to console */
+ // comment this out to suppress log output
+ //logger : console,
+
+ defaults : {
+ id : null,
+ model_class : 'DatasetCollectionElement',
+ element_identifier : null,
+ element_index : null,
+ element_type : null
+ },
+
+ /** Set up.
+ * @see Backbone.Collection#initialize
+ */
+ initialize : function( model, options ){
+ this.info( this + '.initialize:', model, options );
+ options = options || {};
+ //this._setUpListeners();
+
+ this.object = this._createObjectModel();
+ this.on( 'change:object', function(){
+ //console.log( 'change:object' );
+//TODO: prob. better to update the sub-model instead of re-creating it
+ this.object = this._createObjectModel();
+ });
+ },
+
+ _createObjectModel : function(){
+ //console.log( '_createObjectModel', this.get( 'object' ), this.object );
+ //TODO: same patterns as HDCA _createElementsModel - refactor to BASE_MVC.hasSubModel?
+ if( _.isUndefined( this.object ) ){ this.object = null; }
+ if( !this.get( 'object' ) ){ return this.object; }
+
+ var object = this.get( 'object' );
+ this.unset( 'object', { silent: true });
+
+ this.debug( 'DCE, element_type:', this.get( 'element_type' ) );
+ switch( this.get( 'element_type' ) ){
+ case 'dataset_collection':
+ this.object = new DatasetCollection( object );
+ break;
+ case 'hda':
+ this.object = new HDA_MODEL.HistoryDatasetAssociation( object );
+ break;
+ default:
+ throw new TypeError( 'Unknown element_type: ' + this.get( 'element_type' ) );
+ }
+ return this.object;
+ },
+
+ /** String representation. */
+ toString : function(){
+ var objStr = ( this.object )?( '' + this.object ):( this.get( 'element_identifier' ) );
+ return ([ 'DatasetCollectionElement(', objStr, ')' ].join( '' ));
+ }
+});
+
+
+//==============================================================================
+/** @class Backbone collection for DCEs.
+ * NOTE: used *only* in second level of list:paired collections (a
+ * collection that contains collections)
+ *
+ * @borrows LoggableMixin#logger as #logger
+ * @borrows LoggableMixin#log as #log
+ * @constructs
+ */
+var DatasetCollectionElementCollection = Backbone.Collection.extend( BASE_MVC.LoggableMixin ).extend(
+/** @lends DatasetCollectionElementCollection.prototype */{
+ model: DatasetCollectionElement,
+
+ // comment this out to suppress log output
+ /** logger used to record this.log messages, commonly set to console */
+ //logger : console,
+
+ /** Set up.
+ * @see Backbone.Collection#initialize
+ */
+ initialize : function( models, options ){
+ options = options || {};
+ this.info( this + '.initialize:', models, options );
+ //this._setUpListeners();
+ },
+
+ /** String representation. */
+ toString : function(){
+ return ([ 'DatasetCollectionElementCollection(', this.length, ')' ].join( '' ));
+ }
+});
+
+
+//==============================================================================
+/** @class Backbone model for Dataset Collections.
+ * DCs contain a bbone collection named 'elements' using the class found in
+ * this.collectionClass (gen. DatasetCollectionElementCollection). DCs move
+ * that 'object' from the JSON in the attributes list to a full, instantiated
+ * collection found in this.elements. This is done on intialization and
+ * everytime the 'change:elements' event is fired.
+ *
+ * @borrows LoggableMixin#logger as #logger
+ * @borrows LoggableMixin#log as #log
+ * @constructs
+ */
+var DatasetCollection = Backbone.Model.extend( BASE_MVC.LoggableMixin ).extend(
+/** @lends ListDatasetCollection.prototype */{
+
+ //logger : console,
+
+ /** default attributes for a model */
+ defaults : {
+ collection_type : 'list'
+ },
+
+ collectionClass : DatasetCollectionElementCollection,
+
+ /** */
+ initialize : function( model, options ){
+ this.info( 'DatasetCollection.initialize:', model, options );
+ //historyContent.HistoryContent.prototype.initialize.call( this, attrs, options );
+ this.elements = this._createElementsModel();
+//TODO:?? no way to use parse here?
+ this.on( 'change:elements', function(){
+ this.log( 'change:elements' );
+//TODO: prob. better to update the collection instead of re-creating it
+ this.elements = this._createElementsModel();
+ });
+ },
+
+ /** move elements model attribute to full collection */
+ _createElementsModel : function(){
+ this.log( '_createElementsModel', this.get( 'elements' ), this.elements );
+//TODO: same patterns as DatasetCollectionElement _createObjectModel - refactor to BASE_MVC.hasSubModel?
+ var elements = this.get( 'elements' ) || [];
+ this.info( 'elements:', elements );
+ this.unset( 'elements', { silent: true });
+ this.elements = new this.collectionClass( elements );
+ return this.elements;
+ },
+
+ hasDetails : function(){
+//TODO: this is incorrect for (accidentally) empty collections
+ return this.elements.length !== 0;
+ },
+
+ // ........................................................................ misc
+ /** String representation */
+ toString : function(){
+ var idAndName = [ this.get( 'id' ), this.get( 'name' ) || this.get( 'element_identifier' ) ];
+ return 'DatasetCollection(' + ( idAndName.join(',') ) + ')';
+ }
+});
+
+
+//==============================================================================
+/** @class Backbone collection for a collection of collection collections collecting correctly. */
+var DatasetCollectionCollection = Backbone.Collection.extend( BASE_MVC.LoggableMixin ).extend({
+
+ model: DatasetCollection,
+
+ ///** logger used to record this.log messages, commonly set to console */
+ //// comment this out to suppress log output
+ //logger : console,
+
+ /** Set up.
+ * @see Backbone.Collection#initialize
+ */
+ initialize : function( models, options ){
+ options = options || {};
+ this.info( 'DatasetCollectionCollection.initialize:', models, options );
+ //this._setUpListeners();
+ },
+
+ /** String representation. */
+ toString : function(){
+ return ([ 'DatasetCollectionCollection(', this.get( 'name' ), ')' ].join( '' ));
+ }
+});
+
+
+//NOTE: the following prototypes may not be necessary - but I wanted to specifiy
+// them (for now) and allow for the possibility of unique functionality
+//==============================================================================
+var ListDatasetCollection = DatasetCollection.extend(
+/** @lends ListDatasetCollection.prototype */{
+
+ /** String representation. */
+ toString : function(){
+ return ([ 'ListDatasetCollection(', this.get( 'name' ), ')' ].join( '' ));
+ }
+});
+
+
+//==============================================================================
+var PairDatasetCollection = DatasetCollection.extend(
+/** @lends ListDatasetCollection.prototype */{
+
+ /** String representation. */
+ toString : function(){
+ return ([ 'PairDatasetCollection(', this.get( 'name' ), ')' ].join( '' ));
+ }
+});
+
+
+//==============================================================================
+var ListPairedDatasetCollection = DatasetCollection.extend(
+/** @lends ListDatasetCollection.prototype */{
+
+ // list:paired is the only collection that itself contains collections
+ //collectionClass : DatasetCollectionCollection,
+
+ /** String representation. */
+ toString : function(){
+ return ([ 'ListPairedDatasetCollection(', this.get( 'name' ), ')' ].join( '' ));
+ }
+});
+
+
+//==============================================================================
+ return {
+ DatasetCollectionElement : DatasetCollectionElement,
+ DatasetCollectionElementCollection : DatasetCollectionElementCollection,
+ DatasetCollection : DatasetCollection,
+ DatasetCollectionCollection : DatasetCollectionCollection,
+ ListDatasetCollection : ListDatasetCollection,
+ PairDatasetCollection : PairDatasetCollection,
+ ListPairedDatasetCollection : ListPairedDatasetCollection
+ };
+});
diff -r 4974ffd8b2cb5ee994a0d517c2332261898d4d46 -r 7aade8875ea4dde276b33922bbc7fdbc0630a9f5 static/scripts/mvc/collection/collection-panel.js
--- /dev/null
+++ b/static/scripts/mvc/collection/collection-panel.js
@@ -0,0 +1,326 @@
+define([
+ "mvc/collection/dataset-collection-base",
+ "mvc/dataset/hda-base",
+ "mvc/base-mvc",
+ "utils/localization"
+], function( DC_BASE, HDA_BASE, BASE_MVC, _l ){
+/* =============================================================================
+TODO:
+
+============================================================================= */
+/** @class non-editable, read-only View/Controller for a dataset collection.
+ * @name CollectionPanel
+ *
+ * @augments Backbone.View
+ * @borrows LoggableMixin#logger as #logger
+ * @borrows LoggableMixin#log as #log
+ * @constructs
+ */
+var CollectionPanel = Backbone.View.extend( BASE_MVC.LoggableMixin ).extend(
+/** @lends CollectionPanel.prototype */{
+
+ /** logger used to record this.log messages, commonly set to console */
+ // comment this out to suppress log output
+ //logger : console,
+
+ tagName : 'div',
+ className : 'history-panel',
+
+ /** (in ms) that jquery effects will use */
+ fxSpeed : 'fast',
+
+ // ......................................................................... SET UP
+ /** Set up the view, set up storage, bind listeners to HistoryContents events
+ * @param {Object} attributes optional settings for the panel
+ */
+ initialize : function( attributes ){
+ attributes = attributes || {};
+ // set the logger if requested
+ if( attributes.logger ){
+ this.logger = attributes.logger;
+ }
+ this.log( this + '.initialize:', attributes );
+
+ this.hasUser = attributes.hasUser;
+ this.HDAViewClass = attributes.HDAViewClass || HDA_BASE.HDABaseView;
+ },
+
+ /** create any event listeners for the panel
+ * @fires: rendered:initial on the first render
+ * @fires: empty-history when switching to a history with no HDAs or creating a new history
+ */
+ _setUpListeners : function(){
+ // debugging
+ //if( this.logger ){
+ this.on( 'all', function( event ){
+ this.log( this + '', arguments );
+ }, this );
+ //}
+ return this;
+ },
+
+ // ------------------------------------------------------------------------ history/hda event listening
+ /** listening for history and HDA events */
+ _setUpModelEventHandlers : function(){
+ return this;
+ },
+
+ // ------------------------------------------------------------------------ panel rendering
+ /** Render urls, historyPanel body, and hdas (if any are shown)
+ * @fires: rendered when the panel is attached and fully visible
+ * @see Backbone.View#render
+ */
+ render : function( speed, callback ){
+ this.log( 'render:', speed, callback );
+ // send a speed of 0 to have no fade in/out performed
+ speed = ( speed === undefined )?( this.fxSpeed ):( speed );
+ //console.debug( this + '.render, fxSpeed:', speed );
+ var panel = this,
+ $newRender;
+
+ // handle the possibility of no model (can occur if fetching the model returns an error)
+ if( !this.model ){
+ return this;
+ }
+ $newRender = this.renderModel();
+
+ // fade out existing, swap with the new, fade in, set up behaviours
+ $( panel ).queue( 'fx', [
+ function( next ){
+ if( speed && panel.$el.is( ':visible' ) ){
+ panel.$el.fadeOut( speed, next );
+ } else {
+ next();
+ }
+ },
+ function( next ){
+ // swap over from temp div newRender
+ panel.$el.empty();
+ if( $newRender ){
+ panel.$el.append( $newRender.children() );
+ }
+ next();
+ },
+ function( next ){
+ if( speed && !panel.$el.is( ':visible' ) ){
+ panel.$el.fadeIn( speed, next );
+ } else {
+ next();
+ }
+ },
+ function( next ){
+ //TODO: ideally, these would be set up before the fade in (can't because of async save text)
+ if( callback ){ callback.call( this ); }
+ panel.trigger( 'rendered', this );
+ next();
+ }
+ ]);
+ return this;
+ },
+
+ /** render with history data
+ * @returns {jQuery} dom fragment as temporary container to be swapped out later
+ */
+ renderModel : function( ){
+ // tmp div for final swap in render
+ var $newRender = $( '<div/>' ).append( CollectionPanel.templates.panel( this.model.toJSON() ) );
+ this._setUpBehaviours( $newRender );
+ this.renderContents( $newRender );
+ return $newRender;
+ },
+
+ /** Set up HistoryPanel js/widget behaviours */
+ _setUpBehaviours : function( $where ){
+ //TODO: these should be either sub-MVs, or handled by events
+ $where = $where || this.$el;
+ $where.find( '[title]' ).tooltip({ placement: 'bottom' });
+ return this;
+ },
+
+ // ------------------------------------------------------------------------ sub-$element shortcuts
+ /** the scroll container for this panel - can be $el, $el.parent(), or grandparent depending on context */
+ $container : function(){
+ return ( this.findContainerFn )?( this.findContainerFn.call( this ) ):( this.$el.parent() );
+ },
+ /** where hdaViews are attached */
+ $datasetsList : function( $where ){
+ return ( $where || this.$el ).find( '.datasets-list' );
+ },
+
+ // ------------------------------------------------------------------------ sub-views
+ /** Set up/render a view for each HDA to be shown, init with model and listeners.
+ * HDA views are cached to the map this.hdaViews (using the model.id as key).
+ * @param {jQuery} $whereTo what dom element to prepend the HDA views to
+ * @returns the number of visible hda views
+ */
+ renderContents : function( $whereTo ){
+ //console.debug( 'renderContents, elements:', this.model.elements );
+ $whereTo = $whereTo || this.$el;
+
+ var panel = this,
+ contentViews = {},
+ visibleContents = this.model.elements || [];
+ //this.log( 'renderContents, visibleContents:', visibleContents, $whereTo );
+
+ this.$datasetsList( $whereTo ).empty();
+ if( visibleContents && visibleContents.length ){
+ visibleContents.each( function( content ){
+ var contentId = content.id,
+ contentView = panel._createContentView( content );
+ contentViews[ contentId ] = contentView;
+ panel.attachContentView( contentView.render(), $whereTo );
+ });
+ }
+ this.contentViews = contentViews;
+ return this.contentViews;
+ },
+
+ /**
+ * @param {HistoryDatasetAssociation} content
+ */
+ _createContentView : function( content ){
+ //console.debug( 'content json:', JSON.stringify( content, null, ' ' ) );
+ var contentView = null,
+ ContentClass = this._getContentClass( content );
+ //console.debug( 'content.object json:', JSON.stringify( content.object, null, ' ' ) );
+ //console.debug( 'ContentClass:', ContentClass );
+ //console.debug( 'content:', content );
+ //console.debug( 'content.object:', content.object );
+ contentView = new ContentClass({
+ model : content.object,
+ linkTarget : this.linkTarget,
+ //draggable : true,
+ hasUser : this.hasUser,
+ logger : this.logger
+ });
+ //this._setUpHdaListeners( contentView );
+ return contentView;
+ },
+
+ _getContentClass : function( content ){
+ switch( content.get( 'element_type' ) ){
+ case 'hda':
+ return this.HDAViewClass;
+ case 'dataset_collection':
+ return DC_BASE.NestedDCEBaseView;
+ }
+ throw new TypeError( 'Unknown element type:', content.get( 'element_type' ) );
+ },
+
+// /** Set up HistoryPanel listeners for HDAView events. Currently binds:
+// * HDAView#body-visible, HDAView#body-hidden to store expanded states
+// * @param {HDAView} hdaView HDAView (base or edit) to listen to
+// */
+// _setUpHdaListeners : function( hdaView ){
+// var panel = this;
+// hdaView.on( 'error', function( model, xhr, options, msg ){
+// panel.errorHandler( model, xhr, options, msg );
+// });
+// // maintain a list of hdas whose bodies are expanded
+// hdaView.on( 'body-expanded', function( model ){
+// panel.storage.addExpandedHda( model );
+// });
+// hdaView.on( 'body-collapsed', function( id ){
+// panel.storage.removeExpandedHda( id );
+// });
+// return this;
+// },
+
+ /** attach an contentView to the panel */
+ attachContentView : function( contentView, $whereTo ){
+ $whereTo = $whereTo || this.$el;
+ var $datasetsList = this.$datasetsList( $whereTo );
+ $datasetsList.append( contentView.$el );
+ return this;
+ },
+
+ // ------------------------------------------------------------------------ panel events
+ /** event map */
+ events : {
+ 'click .panel-navigation-back' : 'close'
+ },
+
+ /** */
+ close : function( event ){
+ this.$el.remove();
+ this.trigger( 'collection-close' );
+ },
+
+ // ........................................................................ misc
+ /** Return a string rep of the history */
+ toString : function(){
+ return 'CollectionPanel(' + (( this.model )?( this.model.get( 'name' )):( '' )) + ')';
+ }
+});
+
+
+//------------------------------------------------------------------------------ TEMPLATES
+var _panelTemplate = [
+ '<div class="history-controls">',
+ '<div class="panel-navigation">',
+ '<a class="panel-navigation-back" href="javascript:void(0)">', _l( 'Back' ), '</a>',
+ '</div>',
+
+ '<div class="history-title">',
+ '<% if( collection.name ){ %>',
+ '<div class="history-name"><%= collection.hid %> : <%= collection.name %></div>',
+ '<% } %>',
+ '</div>',
+
+ //'<div class="history-subtitle clear">',
+ // '<% if( history.nice_size ){ %>',
+ // '<div class="history-size"><%= history.nice_size %></div>',
+ // '<% } %>',
+ // '<div class="history-secondary-actions"></div>',
+ //'</div>',
+ //
+ //'<% if( history.deleted ){ %>',
+ // '<div class="warningmessagesmall"><strong>',
+ // _l( 'You are currently viewing a deleted history!' ),
+ // '</strong></div>',
+ //'<% } %>',
+ //
+ //'<div class="message-container">',
+ // '<% if( history.message ){ %>',
+ // // should already be localized
+ // '<div class="<%= history.status %>message"><%= history.message %></div>',
+ // '<% } %>',
+ //'</div>',
+ //
+ //'<div class="quota-message errormessage">',
+ // _l( 'You are over your disk quota' ), '. ',
+ // _l( 'Tool execution is on hold until your disk usage drops below your allocated quota' ), '.',
+ //'</div>',
+ //
+ //'<div class="tags-display"></div>',
+ //'<div class="annotation-display"></div>',
+ //'<div class="history-dataset-actions">',
+ // '<div class="btn-group">',
+ // '<button class="history-select-all-datasets-btn btn btn-default"',
+ // 'data-mode="select">', _l( 'All' ), '</button>',
+ // '<button class="history-deselect-all-datasets-btn btn btn-default"',
+ // 'data-mode="select">', _l( 'None' ), '</button>',
+ // '</div>',
+ // '<button class="history-dataset-action-popup-btn btn btn-default">',
+ // _l( 'For all selected' ), '...</button>',
+ //'</div>',
+ '</div>',
+ // end history controls
+
+ // where the datasets/hdas are added
+ '<div class="datasets-list"></div>'
+
+].join( '' );
+
+CollectionPanel.templates = {
+ panel : function( JSON ){
+ return _.template( _panelTemplate, JSON, { variable: 'collection' });
+ }
+};
+
+
+//==============================================================================
+ return {
+ CollectionPanel: CollectionPanel
+ };
+});
diff -r 4974ffd8b2cb5ee994a0d517c2332261898d4d46 -r 7aade8875ea4dde276b33922bbc7fdbc0630a9f5 static/scripts/mvc/collection/dataset-collection-base.js
--- a/static/scripts/mvc/collection/dataset-collection-base.js
+++ b/static/scripts/mvc/collection/dataset-collection-base.js
@@ -1,328 +1,151 @@
define([
- "mvc/history/history-content-base-view",
+ "mvc/base-mvc",
"utils/localization"
-], function( historyContentBaseView, _l ){
+], function( BASE_MVC, _l ){
/* global Backbone, LoggableMixin */
//==============================================================================
-/** @class Read only view for HistoryDatasetCollectionAssociation.
- * @name HDABaseView
+/** @class Read only view for DatasetCollection.
+ * @name DCBaseView
*
* @augments Backbone.View
* @borrows LoggableMixin#logger as #logger
* @borrows LoggableMixin#log as #log
* @constructs
*/
-var DatasetCollectionBaseView = historyContentBaseView.HistoryContentBaseView.extend({
- className : "dataset hda history-panel-hda",
- id : function(){ return 'hdca-' + this.model.get( 'id' ); },
+var DCBaseView = Backbone.View.extend( BASE_MVC.LoggableMixin ).extend({
+
+ /** logger used to record this.log messages, commonly set to console */
+ // comment this out to suppress log output
+ //logger : console,
+
+ /** */
+ className : "dataset-collection",
+ /** */
+ fxSpeed : 'fast',
/** */
initialize : function( attributes ){
if( attributes.logger ){ this.logger = this.model.logger = attributes.logger; }
- this.log( this + '.initialize:', attributes );
- /** is the view currently in selection mode? */
- this.selectable = attributes.selectable || false;
- //this.log( '\t selectable:', this.selectable );
- /** is the view currently selected? */
- this.selected = attributes.selected || false;
- /** is the body of this collection view expanded/not? */
- this.expanded = attributes.expanded || false;
+ this.log( 'DCBaseView.initialize:', attributes );
},
- /** */
- render : function( fade ){
- var $newRender = this._buildNewRender();
-
- this._queueNewRender( $newRender, fade );
- return this;
- },
-
- /** */
- _buildNewRender : function(){
- var $newRender = $( DatasetCollectionBaseView.templates.skeleton( this.model.toJSON() ) );
- $newRender.find( '.dataset-primary-actions' ).append( this._render_titleButtons() );
- $newRender.children( '.dataset-body' ).replaceWith( this._render_body() );
- this._setUpBehaviors( $newRender );
- return $newRender;
- },
-
- /** */
- _queueNewRender : function( $newRender, fade ) {
- fade = ( fade === undefined )?( true ):( fade );
- var view = this;
-
- // fade the old render out (if desired)
- if( fade ){
- $( view ).queue( function( next ){ this.$el.fadeOut( view.fxSpeed, next ); });
- }
- // empty the old render, update to any new HDA state, swap in the new render contents, handle multi-select
- $( view ).queue( function( next ){
- this.$el.empty()
- .attr( 'class', view.className ).addClass( 'state-' + view.model.get( 'state' ) )
- .append( $newRender.children() );
- if( this.selectable ){ this.showSelector( 0 ); }
- next();
- });
- // fade the new in
- if( fade ){
- $( view ).queue( function( next ){ this.$el.fadeIn( view.fxSpeed, next ); });
- }
- // trigger an event to know we're ready
- $( view ).queue( function( next ){
- this.trigger( 'rendered', view );
- if( this.model.inReadyState() ){
- this.trigger( 'rendered:ready', view );
- }
- if( this.draggable ){ this.draggableOn(); }
- next();
- });
- },
-
- // ................................................................................ titlebar buttons
- /** Render icon-button group for the common, most easily accessed actions.
- * @returns {jQuery} rendered DOM
- */
- _render_titleButtons : function(){
- // render just the display for read-only
- return [ ];
- },
-
- // ......................................................................... state body renderers
- /** Render the enclosing div of the collection body and, if expanded, the html in the body
- * @returns {jQuery} rendered DOM
- */
- _render_body : function(){
- var $body = $( '<div>Error: unknown state "' + this.model.get( 'state' ) + '".</div>' ),
- // cheesy: get function by assumed matching name
- renderFn = this[ '_render_body_' + this.model.get( 'state' ) ];
- if( _.isFunction( renderFn ) ){
- $body = renderFn.call( this );
- }
- this._setUpBehaviors( $body );
-
- // only render the body html if it's being shown
- if( this.expanded ){
- $body.show();
- }
- return $body;
- },
-
- /** set up js behaviors, event handlers for elements within the given container
- * @param {jQuery} $container jq object that contains the elements to process (defaults to this.$el)
- */
- _setUpBehaviors : function( $container ){
- $container = $container || this.$el;
- // set up canned behavior on children (bootstrap, popupmenus, editable_text, etc.)
- make_popup_menus( $container );
- $container.find( '[title]' ).tooltip({ placement : 'bottom' });
- },
-
- // TODO: Eliminate duplication between following event map and one for HDAs.
-
- // ......................................................................... events
- /** event map */
- events : {
- // expand the body when the title is clicked or when in focus and space or enter is pressed
- 'click .dataset-title-bar' : 'toggleBodyVisibility',
- 'keydown .dataset-title-bar' : 'toggleBodyVisibility',
-
- // toggle selected state
- 'click .dataset-selector' : 'toggleSelect'
- },
-
- /** Show or hide the body/details of history content.
- * note: if the model does not have detailed data, fetch that data before showing the body
- * @param {Event} event the event that triggered this (@link HDABaseView#events)
- * @param {Boolean} expanded if true, expand; if false, collapse
- * @fires body-expanded when a body has been expanded
- * @fires body-collapsed when a body has been collapsed
- */
- toggleBodyVisibility : function( event, expand ){
- // bail (with propagation) if keydown and not space or enter
- var KEYCODE_SPACE = 32, KEYCODE_RETURN = 13;
- if( event && ( event.type === 'keydown' )
- && !( event.keyCode === KEYCODE_SPACE || event.keyCode === KEYCODE_RETURN ) ){
- return true;
- }
-
- var $body = this.$el.find( '.dataset-body' );
- expand = ( expand === undefined )?( !$body.is( ':visible' ) ):( expand );
- if( expand ){
- this.expandBody();
- } else {
- this.collapseBody();
- }
- return false;
- },
-
- /** Render and show the full, detailed body of this view including extra data and controls.
- * @fires body-expanded when a body has been expanded
- */
- expandBody : function(){
- var contentView = this;
-
- function _renderBodyAndExpand(){
- contentView.$el.children( '.dataset-body' ).replaceWith( contentView._render_body() );
- contentView.$el.children( '.dataset-body' ).slideDown( contentView.fxSpeed, function(){
- contentView.expanded = true;
- contentView.trigger( 'body-expanded', contentView.model );
- });
- }
- // TODO: Fetch more details like HDA view...
- _renderBodyAndExpand();
- },
-
- /** Hide the body/details of an HDA.
- * @fires body-collapsed when a body has been collapsed
- */
- collapseBody : function(){
- var hdaView = this;
- this.$el.children( '.dataset-body' ).slideUp( hdaView.fxSpeed, function(){
- hdaView.expanded = false;
- hdaView.trigger( 'body-collapsed', hdaView.model.id );
- });
- },
-
- /** Render an 'ok' collection.
- * @param {jQuery} parent DOM to which to append this body
- */
- _render_body_ok : function(){
- // most common state renderer and the most complicated
- var $body = $( DatasetCollectionBaseView.templates.body( this.model.toJSON() ) );
-
- // return shortened form if del'd (no display apps or peek?)
- if( this.model.get( 'deleted' ) ){
- return $body;
- }
-
- return $body;
- },
-
- // ......................................................................... selection
- /** display a (fa-icon) checkbox on the left of the hda that fires events when checked
- * Note: this also hides the primary actions
- */
- showSelector : function(){
- // make sure selected state is represented properly
- if( this.selected ){
- this.select( null, true );
- }
-
- this.selectable = true;
- this.trigger( 'selectable', true, this );
-
- this.$( '.dataset-primary-actions' ).hide();
- this.$( '.dataset-selector' ).show();
- },
-
- /** remove the selection checkbox */
- hideSelector : function(){
- // reverse the process from showSelect
- this.selectable = false;
- this.trigger( 'selectable', false, this );
-
- this.$( '.dataset-selector' ).hide();
- this.$( '.dataset-primary-actions' ).show();
- },
-
- toggleSelector : function(){
- if( !this.$el.find( '.dataset-selector' ).is( ':visible' ) ){
- this.showSelector();
- } else {
- this.hideSelector();
- }
- },
-
- /** event handler for selection (also programmatic selection)
- */
- select : function( event ){
- // switch icon, set selected, and trigger event
- this.$el.find( '.dataset-selector span' )
- .removeClass( 'fa-square-o' ).addClass( 'fa-check-square-o' );
- if( !this.selected ){
- this.trigger( 'selected', this, event );
- this.selected = true;
- }
- return false;
- },
-
- /** event handler for clearing selection (also programmatic deselection)
- */
- deselect : function( event ){
- // switch icon, set selected, and trigger event
- this.$el.find( '.dataset-selector span' )
- .removeClass( 'fa-check-square-o' ).addClass( 'fa-square-o' );
- if( this.selected ){
- this.trigger( 'de-selected', this, event );
- this.selected = false;
- }
- return false;
- },
-
- toggleSelect : function( event ){
- if( this.selected ){
- this.deselect( event );
- } else {
- this.select( event );
- }
- },
+//TODO: render has been removed from the inheritance chain here, so this won't work when called as is
// ......................................................................... misc
/** String representation */
toString : function(){
var modelString = ( this.model )?( this.model + '' ):( '(no model)' );
- return 'HDCABaseView(' + modelString + ')';
+ return 'DCBaseView(' + modelString + ')';
}
});
-//------------------------------------------------------------------------------ TEMPLATES
-//TODO: possibly break these out into a sep. module
-var skeletonTemplate = _.template([
- '<div class="dataset hda">',
- '<div class="dataset-warnings">',
- '<% if ( collection.deleted ) { %>',
- '<div class="dataset-deleted-msg warningmessagesmall"><strong>',
- _l( 'This collection has been deleted.' ),
+/** templates for DCBaseViews (skeleton and body) */
+DCBaseView.templates = (function(){
+// use closure to run underscore template fn only once at module load
+ var skeletonTemplate = _.template([
+ '<div class="dataset hda">',
+ '<div class="dataset-warnings">',
+ '<% if ( collection.deleted ) { %>',
+ '<div class="dataset-deleted-msg warningmessagesmall"><strong>',
+ _l( 'This collection has been deleted.' ),
+ '</div>',
+ '<% } %>',
+ '<% if ( !collection.visible ) { %>',
+ '<div class="dataset-hidden-msg warningmessagesmall"><strong>',
+ _l( 'This collection has been hidden.' ),
+ '</div>',
+ '<% } %>',
+ '</div>',
+ '<div class="dataset-primary-actions"></div>',
+ '<div class="dataset-title-bar clear" tabindex="0">',
+ '<span class="dataset-state-icon state-icon"></span>',
+ '<div class="dataset-title">',
+ '<span class="dataset-name"><%- collection.name %></span>',
'</div>',
- '<% } %>',
- '<% if ( !collection.visible ) { %>',
- '<div class="dataset-hidden-msg warningmessagesmall"><strong>',
- _l( 'This collection has been hidden.' ),
- '</div>',
- '<% } %>',
- '</div>',
- '<div class="dataset-selector"><span class="fa fa-2x fa-square-o"></span></div>',
- '<div class="dataset-primary-actions"></div>',
- '<div class="dataset-title-bar clear" tabindex="0">',
- '<span class="dataset-state-icon state-icon"></span>',
- '<div class="dataset-title">',
- '<span class="hda-hid"><%= collection.hid %></span> ',
- '<span class="dataset-name"><%= collection.name %></span>',
'</div>',
- '</div>',
- '<div class="dataset-body"></div>',
- '</div>'
-].join( '' ));
+ '<div class="dataset-body"></div>',
+ '</div>'
+ ].join( '' ));
-var bodyTemplate = _.template([
- '<div class="dataset-body">',
- '<div class="dataset-summary">',
- _l( 'A dataset collection.' ),
- '</div>'
-].join( '' ));
+ var bodyTemplate = _.template([
+ '<div class="dataset-body">',
+ '<div class="dataset-summary">',
+ _l( 'A dataset collection.' ),
+ '</div>'
+ ].join( '' ));
-DatasetCollectionBaseView.templates = {
// we override here in order to pass the localizer (_L) into the template scope - since we use it as a fn within
- skeleton : function( collectionJSON ){
- return skeletonTemplate({ _l: _l, collection: collectionJSON });
- },
- body : function( collectionJSON ){
- return bodyTemplate({ _l: _l, collection: collectionJSON });
- }
-};
+ return {
+ skeleton : function( collectionJSON ){
+ return skeletonTemplate({ _l: _l, collection: collectionJSON });
+ },
+ body : function( collectionJSON ){
+ return bodyTemplate({ _l: _l, collection: collectionJSON });
+ }
+ };
+}());
+
+
+//TODO: unused
+////==============================================================================
+///** @class Read only view for DatasetCollectionElement.
+// * @name DCEBaseView
+// *
+// * @augments Backbone.View
+// * @borrows LoggableMixin#logger as #logger
+// * @borrows LoggableMixin#log as #log
+// * @constructs
+// */
+//var NestedDCBaseView = DCBaseView.extend({
+//
+// logger : console,
+//
+// /** */
+// initialize : function( attributes ){
+// if( attributes.logger ){ this.logger = this.model.logger = attributes.logger; }
+// this.warn( this + '.initialize:', attributes );
+// DCBaseView.prototype.initialize.call( this, attributes );
+// },
+//
+// _template : function(){
+// this.debug( this.model );
+// this.debug( this.model.toJSON() );
+// return NestedDCBaseView.templates.skeleton( this.model.toJSON() );
+// },
+//
+// // ......................................................................... misc
+// /** String representation */
+// toString : function(){
+// var modelString = ( this.model )?( this.model + '' ):( '(no model)' );
+// return 'NestedDCBaseView(' + modelString + ')';
+// }
+//});
+//
+////------------------------------------------------------------------------------ TEMPLATES
+////TODO: possibly break these out into a sep. module
+//NestedDCBaseView.templates = (function(){
+// var skeleton = _.template([
+// '<div class="dataset hda history-panel-hda state-ok">',
+// '<div class="dataset-primary-actions"></div>',
+// '<div class="dataset-title-bar clear" tabindex="0">',
+// '<div class="dataset-title">',
+// '<span class="dataset-name"><%= collection.name %></span>',
+// '</div>',
+// '</div>',
+// '</div>'
+// ].join( '' ));
+// // we override here in order to pass the localizer (_L) into the template scope - since we use it as a fn within
+// return {
+// skeleton : function( json ){
+// return skeleton({ _l: _l, collection: json });
+// }
+// };
+//}());
+
//==============================================================================
return {
- DatasetCollectionBaseView : DatasetCollectionBaseView
+ DCBaseView : DCBaseView,
+ //NestedDCBaseView : NestedDCBaseView,
};
});
diff -r 4974ffd8b2cb5ee994a0d517c2332261898d4d46 -r 7aade8875ea4dde276b33922bbc7fdbc0630a9f5 static/scripts/mvc/collection/dataset-collection-edit.js
--- a/static/scripts/mvc/collection/dataset-collection-edit.js
+++ b/static/scripts/mvc/collection/dataset-collection-edit.js
@@ -1,75 +1,36 @@
define([
- "mvc/dataset/hda-model",
+ "mvc/dataset/states",
"mvc/collection/dataset-collection-base",
"utils/localization"
-], function( hdaModel, datasetCollectionBase, _l ){
+], function( STATES, DC_BASE_VIEW, _l ){
//==============================================================================
-/** @class Editing view for HistoryDatasetCollectionAssociation.
+var _super = DC_BASE_VIEW.DCBaseView;
+/** @class Editing view for DatasetCollection.
* @name DatasetCollectionEditView
*
- * @augments DatasetCollectionBaseView
+ * @augments DCBaseView
* @constructs
*/
-var DatasetCollectionEditView = datasetCollectionBase.DatasetCollectionBaseView.extend( {
+var DCEditView = _super.extend({
+
+ /** logger used to record this.log messages, commonly set to console */
+ // comment this out to suppress log output
+ //logger : console,
initialize : function( attributes ){
- datasetCollectionBase.DatasetCollectionBaseView.prototype.initialize.call( this, attributes );
- },
-
- // ......................................................................... edit attr, delete
- /** Render icon-button group for the common, most easily accessed actions.
- * Overrides _render_titleButtons to include editing related buttons.
- * @see DatasetCollectionBaseView#_render_titleButtons
- * @returns {jQuery} rendered DOM
- */
- _render_titleButtons : function(){
- // render the display, edit attr and delete icon-buttons
- return datasetCollectionBase.DatasetCollectionBaseView.prototype._render_titleButtons.call( this ).concat([
- this._render_deleteButton()
- ]);
- },
-
- /** Render icon-button to delete this hda.
- * @returns {jQuery} rendered DOM
- */
- _render_deleteButton : function(){
- // don't show delete if...
- if( ( this.model.get( 'state' ) === hdaModel.HistoryDatasetAssociation.STATES.NEW )
- || ( this.model.get( 'state' ) === hdaModel.HistoryDatasetAssociation.STATES.NOT_VIEWABLE )
- || ( !this.model.get( 'accessible' ) ) ){
- return null;
- }
-
- var self = this,
- deleteBtnData = {
- title : _l( 'Delete' ),
- classes : 'dataset-delete',
- onclick : function() {
- // ...bler... tooltips being left behind in DOM (hover out never called on deletion)
- self.$el.find( '.icon-btn.dataset-delete' ).trigger( 'mouseout' );
- self.model[ 'delete' ]();
- }
- };
- if( this.model.get( 'deleted' ) ){
- deleteBtnData = {
- title : _l( 'Dataset collection is already deleted' ),
- disabled : true
- };
- }
- deleteBtnData.faIcon = 'fa-times';
- return faIconButton( deleteBtnData );
+ _super.prototype.initialize.call( this, attributes );
},
// ......................................................................... misc
/** string rep */
toString : function(){
var modelString = ( this.model )?( this.model + '' ):( '(no model)' );
- return 'HDCAEditView(' + modelString + ')';
+ return 'DCEditView(' + modelString + ')';
}
});
//==============================================================================
return {
- DatasetCollectionEditView : DatasetCollectionEditView
+ DCEditView : DCEditView
};
});
This diff is so big that we needed to truncate the remainder.
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: greg: Fix for exporting repositories that contain package recipes that define additional packages needed only for compiling the dependent package.
by commits-noreply@bitbucket.org 23 Jul '14
by commits-noreply@bitbucket.org 23 Jul '14
23 Jul '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/e45ed2368920/
Changeset: e45ed2368920
User: greg
Date: 2014-07-23 22:19:39
Summary: Fix for exporting repositories that contain package recipes that define additional packages needed only for compiling the dependent package.
Affected #: 3 files
diff -r b08a47eb8c3c15022b9e3f7d9990d40fd0fa70c0 -r e45ed2368920315ab1f9cfe28d81e07cefc5c955 lib/galaxy/webapps/tool_shed/controllers/repository.py
--- a/lib/galaxy/webapps/tool_shed/controllers/repository.py
+++ b/lib/galaxy/webapps/tool_shed/controllers/repository.py
@@ -1262,7 +1262,11 @@
repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans.app, repository_id, changeset_revision )
metadata = repository_metadata.metadata
toolshed_base_url = str( web.url_for( '/', qualified=True ) ).rstrip( '/' )
+ # Initialize the repository dependency RelationBuilder.
rb = relation_builder.RelationBuilder( trans.app, repository, repository_metadata, toolshed_base_url )
+ # Work-around to ensure repositories that contain packages needed only for compiling
+ # a dependent package are included in the capsule.
+ rb.set_filter_dependencies_needed_for_compiling( False )
# Get a dictionary of all repositories upon which the contents of the current repository_metadata record depend.
repository_dependencies = rb.get_repository_dependencies_for_changeset_revision()
if repository_dependencies:
diff -r b08a47eb8c3c15022b9e3f7d9990d40fd0fa70c0 -r e45ed2368920315ab1f9cfe28d81e07cefc5c955 lib/tool_shed/capsule/capsule_manager.py
--- a/lib/tool_shed/capsule/capsule_manager.py
+++ b/lib/tool_shed/capsule/capsule_manager.py
@@ -245,9 +245,13 @@
repository_metadata = suc.get_repository_metadata_by_changeset_revision( self.app,
self.repository_id,
self.changeset_revision )
- # Get a dictionary of all repositories upon which the contents of the current repository_metadata record depend.
+ # Get a dictionary of all repositories upon which the contents of the current
+ # repository_metadata record depend.
toolshed_base_url = str( web.url_for( '/', qualified=True ) ).rstrip( '/' )
rb = RelationBuilder( self.app, repository, repository_metadata, toolshed_base_url )
+ # Work-around to ensure repositories that contain packages needed only for compiling
+ # a dependent package are included in the capsule.
+ rb.set_filter_dependencies_needed_for_compiling( False )
repository_dependencies = rb.get_repository_dependencies_for_changeset_revision()
repo = hg_util.get_repo_for_repository( self.app,
repository=self.repository,
diff -r b08a47eb8c3c15022b9e3f7d9990d40fd0fa70c0 -r e45ed2368920315ab1f9cfe28d81e07cefc5c955 lib/tool_shed/dependencies/repository/relation_builder.py
--- a/lib/tool_shed/dependencies/repository/relation_builder.py
+++ b/lib/tool_shed/dependencies/repository/relation_builder.py
@@ -23,6 +23,11 @@
self.handled_key_rd_dicts = []
self.key_rd_dicts_to_be_processed = []
self.tool_shed_url = tool_shed_url
+ # This is a temporary work-around for handling repository dependencies that are needed
+ # only if compiling a dependent package. This value should be True unless exporting
+ # a repository capsule, in which case the set_filter_dependencies_needed_for_compiling()
+ # function is called.
+ self.filter_dependencies_needed_for_compiling = True
def can_add_to_key_rd_dicts( self, key_rd_dict, key_rd_dicts ):
"""Handle the case where an update to the changeset revision was done."""
@@ -389,9 +394,12 @@
current_repository_key_rd_dicts = \
self.get_updated_changeset_revisions_for_repository_dependencies( current_repository_key_rd_dicts )
for key_rd_dict in current_repository_key_rd_dicts:
- # Filter out repository dependencies that are required only if compiling the dependent
- # repository's tool dependency.
- key_rd_dict = self.filter_only_if_compiling_contained_td( key_rd_dict )
+ if self.filter_dependencies_needed_for_compiling:
+ # Filter out repository dependencies that are required only if compiling the dependent
+ # repository's tool dependency.
+ # TODO: this temporary work-around should be removed when the underlying framework
+ # support for handling only_if_compiling_contained_td-flagged repositories is completed.
+ key_rd_dict = self.filter_only_if_compiling_contained_td( key_rd_dict )
if key_rd_dict:
is_circular = False
in_handled_key_rd_dicts = self.in_key_rd_dicts( key_rd_dict, self.handled_key_rd_dicts )
@@ -483,6 +491,9 @@
clean_key_rd_dicts.append( new_key_rd_dict )
return clean_key_rd_dicts
+ def set_filter_dependencies_needed_for_compiling( self, value ):
+ self.filter_dependencies_needed_for_compiling = asbool( value )
+
def update_circular_repository_dependencies( self, repository_key, repository_dependency, repository_dependencies ):
repository_dependency_as_key = self.get_repository_dependency_as_key( repository_dependency )
repository_key_as_repository_dependency = repository_key.split( container_util.STRSEP )
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: greg: Strip repository names when creating in the Tool Shed.
by commits-noreply@bitbucket.org 23 Jul '14
by commits-noreply@bitbucket.org 23 Jul '14
23 Jul '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/b08a47eb8c3c/
Changeset: b08a47eb8c3c
User: greg
Date: 2014-07-23 19:40:23
Summary: Strip repository names when creating in the Tool Shed.
Affected #: 1 file
diff -r 598a4ec015f66237d41ed2176c673fd52b744f15 -r b08a47eb8c3c15022b9e3f7d9990d40fd0fa70c0 lib/galaxy/webapps/tool_shed/controllers/repository.py
--- a/lib/galaxy/webapps/tool_shed/controllers/repository.py
+++ b/lib/galaxy/webapps/tool_shed/controllers/repository.py
@@ -1062,7 +1062,7 @@
action='browse_repositories',
message=message,
status=status ) )
- name = kwd.get( 'name', '' )
+ name = kwd.get( 'name', '' ).strip()
description = kwd.get( 'description', '' )
long_description = kwd.get( 'long_description', '' )
category_ids = util.listify( kwd.get( 'category_id', '' ) )
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: carlfeberhard: History/Collection/HDA MVC: refactoring; Base MVC: create mixin shortcut to extend, use with HistoryContentMixin; Pages: allow display of collections; HDAs: fix annotation default overwriting existing when only partial model is saved; Style: begin separation of collections styles and prep for DOM class renaming; pack scripts
by commits-noreply@bitbucket.org 23 Jul '14
by commits-noreply@bitbucket.org 23 Jul '14
23 Jul '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/598a4ec015f6/
Changeset: 598a4ec015f6
User: carlfeberhard
Date: 2014-07-23 18:59:04
Summary: History/Collection/HDA MVC: refactoring; Base MVC: create mixin shortcut to extend, use with HistoryContentMixin; Pages: allow display of collections; HDAs: fix annotation default overwriting existing when only partial model is saved; Style: begin separation of collections styles and prep for DOM class renaming; pack scripts
Affected #: 50 files
diff -r 74d7ff952ec902e68cc99745fdcd3c14e86208b2 -r 598a4ec015f66237d41ed2176c673fd52b744f15 lib/galaxy/webapps/galaxy/controllers/history.py
--- a/lib/galaxy/webapps/galaxy/controllers/history.py
+++ b/lib/galaxy/webapps/galaxy/controllers/history.py
@@ -195,6 +195,7 @@
class HistoryController( BaseUIController, SharableMixin, UsesAnnotations, UsesItemRatings,
UsesHistoryMixin, UsesHistoryDatasetAssociationMixin, ExportsHistoryMixin,
ImportsHistoryMixin ):
+
def __init__( self, app ):
super( HistoryController, self ).__init__( app )
self.mgrs = util.bunch.Bunch(
diff -r 74d7ff952ec902e68cc99745fdcd3c14e86208b2 -r 598a4ec015f66237d41ed2176c673fd52b744f15 lib/galaxy/webapps/galaxy/controllers/page.py
--- a/lib/galaxy/webapps/galaxy/controllers/page.py
+++ b/lib/galaxy/webapps/galaxy/controllers/page.py
@@ -1,5 +1,6 @@
from sqlalchemy import desc, and_
from galaxy import model, web
+from galaxy import managers
from galaxy.web import error, url_for
from galaxy.model.item_attrs import UsesItemRatings
from galaxy.web.base.controller import BaseUIController, SharableMixin, UsesHistoryMixin, UsesStoredWorkflowMixin, UsesVisualizationMixin
@@ -285,6 +286,12 @@
_page_selection_grid = PageSelectionGrid()
_visualization_selection_grid = VisualizationSelectionGrid()
+ def __init__( self, app ):
+ super( PageController, self ).__init__( app )
+ self.mgrs = util.bunch.Bunch(
+ histories=managers.histories.HistoryManager()
+ )
+
@web.expose
@web.require_login()
def list( self, trans, *args, **kwargs ):
@@ -718,6 +725,7 @@
"""
Returns html suitable for embedding in another page.
"""
+ #TODO: should be moved to history controller and/or called via ajax from the template
history = self.get_history( trans, id, False, True )
if not history:
return None
@@ -729,15 +737,22 @@
hda_dicts = []
datasets = self.get_history_datasets( trans, history )
- for hda in datasets:
- hda_dict = self.get_hda_dict( trans, hda )
- hda_dict[ 'annotation' ] = self.get_item_annotation_str( trans.sa_session, history.user, hda )
- hda_dicts.append( hda_dict )
- history_dict = self.get_history_dict( trans, history, hda_dictionaries=hda_dicts )
- history_dict[ 'annotation' ] = history.annotation
+ #for hda in datasets:
+ # hda_dict = self.get_hda_dict( trans, hda )
+ # hda_dict[ 'annotation' ] = self.get_item_annotation_str( trans.sa_session, history.user, hda )
+ # hda_dicts.append( hda_dict )
+ #history_dict = self.get_history_dict( trans, history, hda_dictionaries=hda_dicts )
+ #history_dict[ 'annotation' ] = history.annotation
+
+ # include all datasets: hidden, deleted, and purged
+ #TODO!: doubled query (hda_dictionaries + datasets)
+ history_data = self.mgrs.histories._get_history_data( trans, history )
+ history_dictionary = history_data[ 'history' ]
+ hda_dictionaries = history_data[ 'contents' ]
+ history_dictionary[ 'annotation' ] = history.annotation
filled = trans.fill_template( "history/embed.mako", item=history, item_data=datasets,
- user_is_owner=user_is_owner, history_dict=history_dict, hda_dicts=hda_dicts )
+ user_is_owner=user_is_owner, history_dict=history_dictionary, hda_dicts=hda_dictionaries )
return filled
def _get_embed_html( self, trans, item_class, item_id ):
diff -r 74d7ff952ec902e68cc99745fdcd3c14e86208b2 -r 598a4ec015f66237d41ed2176c673fd52b744f15 static/scripts/mvc/base-mvc.js
--- a/static/scripts/mvc/base-mvc.js
+++ b/static/scripts/mvc/base-mvc.js
@@ -14,7 +14,7 @@
* @example
* // Add to your models/views at the definition using chaining:
* var MyModel = Backbone.Model.extend( LoggableMixin ).extend({ // ... });
- *
+ *
* // or - more explicitly AFTER the definition:
* var MyModel = Backbone.Model.extend({
* logger : console
@@ -208,8 +208,23 @@
};
//==============================================================================
-return {
- LoggableMixin : LoggableMixin,
- SessionStorageModel : SessionStorageModel,
- HiddenUntilActivatedViewMixin : HiddenUntilActivatedViewMixin
-};});
+function mixin( mixinHash1, /* mixinHash2, etc: ... variadic */ propsHash ){
+ // usage: var NewModel = Something.extend( mixin( MyMixinA, MyMixinB, { ... }) );
+ //NOTE: this does not combine any hashes (like events, etc.) and you're expected to handle that
+
+ // simple reversal of param order on _.defaults() - to show mixins in top of definition
+ var args = Array.prototype.slice.call( arguments, 0 ),
+ lastArg = args.pop();
+ args.unshift( lastArg );
+ return _.defaults.apply( _, args );
+}
+
+
+//==============================================================================
+ return {
+ LoggableMixin : LoggableMixin,
+ SessionStorageModel : SessionStorageModel,
+ HiddenUntilActivatedViewMixin : HiddenUntilActivatedViewMixin,
+ mixin : mixin
+ };
+});
diff -r 74d7ff952ec902e68cc99745fdcd3c14e86208b2 -r 598a4ec015f66237d41ed2176c673fd52b744f15 static/scripts/mvc/collection/collection-model.js
--- /dev/null
+++ b/static/scripts/mvc/collection/collection-model.js
@@ -0,0 +1,250 @@
+define([
+ "mvc/dataset/hda-model",
+ "mvc/base-mvc",
+ "utils/localization"
+], function( HDA_MODEL, BASE_MVC, _l ){
+//==============================================================================
+/** @class Backbone model for Dataset collection elements.
+ * DC Elements contain a sub-model named 'object'. This class moves that
+ * 'object' from the JSON in the attributes list to a full, instantiated
+ * sub-model found in this.object. This is done on intialization and
+ * everytime the 'change:object' event is fired.
+ *
+ * @borrows LoggableMixin#logger as #logger
+ * @borrows LoggableMixin#log as #log
+ * @constructs
+ */
+var DatasetCollectionElement = Backbone.Model.extend( BASE_MVC.LoggableMixin ).extend(
+/** @lends DatasetCollectionElement.prototype */{
+ //TODO:?? this model may be unneccessary - it reflects the api structure, but...
+ // if we munge the element with the element.object at parse, we can flatten the entire hierarchy
+
+ /** logger used to record this.log messages, commonly set to console */
+ // comment this out to suppress log output
+ //logger : console,
+
+ defaults : {
+ id : null,
+ model_class : 'DatasetCollectionElement',
+ element_identifier : null,
+ element_index : null,
+ element_type : null
+ },
+
+ /** Set up.
+ * @see Backbone.Collection#initialize
+ */
+ initialize : function( model, options ){
+ this.info( this + '.initialize:', model, options );
+ options = options || {};
+ //this._setUpListeners();
+
+ this.object = this._createObjectModel();
+ this.on( 'change:object', function(){
+ //console.log( 'change:object' );
+//TODO: prob. better to update the sub-model instead of re-creating it
+ this.object = this._createObjectModel();
+ });
+ },
+
+ _createObjectModel : function(){
+ //console.log( '_createObjectModel', this.get( 'object' ), this.object );
+ //TODO: same patterns as HDCA _createElementsModel - refactor to BASE_MVC.hasSubModel?
+ if( _.isUndefined( this.object ) ){ this.object = null; }
+ if( !this.get( 'object' ) ){ return this.object; }
+
+ var object = this.get( 'object' );
+ this.unset( 'object', { silent: true });
+
+ this.debug( 'DCE, element_type:', this.get( 'element_type' ) );
+ switch( this.get( 'element_type' ) ){
+ case 'dataset_collection':
+ this.object = new DatasetCollection( object );
+ break;
+ case 'hda':
+ this.object = new HDA_MODEL.HistoryDatasetAssociation( object );
+ break;
+ default:
+ throw new TypeError( 'Unknown element_type: ' + this.get( 'element_type' ) );
+ }
+ return this.object;
+ },
+
+ /** String representation. */
+ toString : function(){
+ var objStr = ( this.object )?( '' + this.object ):( this.get( 'element_identifier' ) );
+ return ([ 'DatasetCollectionElement(', objStr, ')' ].join( '' ));
+ }
+});
+
+
+//==============================================================================
+/** @class Backbone collection for DCEs.
+ * NOTE: used *only* in second level of list:paired collections (a
+ * collection that contains collections)
+ *
+ * @borrows LoggableMixin#logger as #logger
+ * @borrows LoggableMixin#log as #log
+ * @constructs
+ */
+var DatasetCollectionElementCollection = Backbone.Collection.extend( BASE_MVC.LoggableMixin ).extend(
+/** @lends DatasetCollectionElementCollection.prototype */{
+ model: DatasetCollectionElement,
+
+ // comment this out to suppress log output
+ /** logger used to record this.log messages, commonly set to console */
+ //logger : console,
+
+ /** Set up.
+ * @see Backbone.Collection#initialize
+ */
+ initialize : function( models, options ){
+ options = options || {};
+ this.info( this + '.initialize:', models, options );
+ //this._setUpListeners();
+ },
+
+ /** String representation. */
+ toString : function(){
+ return ([ 'DatasetCollectionElementCollection(', this.length, ')' ].join( '' ));
+ }
+});
+
+
+//==============================================================================
+/** @class Backbone model for Dataset Collections.
+ * DCs contain a bbone collection named 'elements' using the class found in
+ * this.collectionClass (gen. DatasetCollectionElementCollection). DCs move
+ * that 'object' from the JSON in the attributes list to a full, instantiated
+ * collection found in this.elements. This is done on intialization and
+ * everytime the 'change:elements' event is fired.
+ *
+ * @borrows LoggableMixin#logger as #logger
+ * @borrows LoggableMixin#log as #log
+ * @constructs
+ */
+var DatasetCollection = Backbone.Model.extend( BASE_MVC.LoggableMixin ).extend(
+/** @lends ListDatasetCollection.prototype */{
+
+ //logger : console,
+
+ /** default attributes for a model */
+ defaults : {
+ collection_type : 'list'
+ },
+
+ collectionClass : DatasetCollectionElementCollection,
+
+ /** */
+ initialize : function( model, options ){
+ this.info( 'DatasetCollection.initialize:', model, options );
+ //historyContent.HistoryContent.prototype.initialize.call( this, attrs, options );
+ this.elements = this._createElementsModel();
+//TODO:?? no way to use parse here?
+ this.on( 'change:elements', function(){
+ this.log( 'change:elements' );
+//TODO: prob. better to update the collection instead of re-creating it
+ this.elements = this._createElementsModel();
+ });
+ },
+
+ /** move elements model attribute to full collection */
+ _createElementsModel : function(){
+ this.log( '_createElementsModel', this.get( 'elements' ), this.elements );
+//TODO: same patterns as DatasetCollectionElement _createObjectModel - refactor to BASE_MVC.hasSubModel?
+ var elements = this.get( 'elements' ) || [];
+ this.info( 'elements:', elements );
+ this.unset( 'elements', { silent: true });
+ this.elements = new this.collectionClass( elements );
+ return this.elements;
+ },
+
+ hasDetails : function(){
+//TODO: this is incorrect for (accidentally) empty collections
+ return this.elements.length !== 0;
+ },
+
+ // ........................................................................ misc
+ /** String representation */
+ toString : function(){
+ var idAndName = [ this.get( 'id' ), this.get( 'name' ) || this.get( 'element_identifier' ) ];
+ return 'DatasetCollection(' + ( idAndName.join(',') ) + ')';
+ }
+});
+
+
+//==============================================================================
+/** @class Backbone collection for a collection of collection collections collecting correctly. */
+var DatasetCollectionCollection = Backbone.Collection.extend( BASE_MVC.LoggableMixin ).extend({
+
+ model: DatasetCollection,
+
+ ///** logger used to record this.log messages, commonly set to console */
+ //// comment this out to suppress log output
+ //logger : console,
+
+ /** Set up.
+ * @see Backbone.Collection#initialize
+ */
+ initialize : function( models, options ){
+ options = options || {};
+ this.info( 'DatasetCollectionCollection.initialize:', models, options );
+ //this._setUpListeners();
+ },
+
+ /** String representation. */
+ toString : function(){
+ return ([ 'DatasetCollectionCollection(', this.get( 'name' ), ')' ].join( '' ));
+ }
+});
+
+
+//NOTE: the following prototypes may not be necessary - but I wanted to specifiy
+// them (for now) and allow for the possibility of unique functionality
+//==============================================================================
+var ListDatasetCollection = DatasetCollection.extend(
+/** @lends ListDatasetCollection.prototype */{
+
+ /** String representation. */
+ toString : function(){
+ return ([ 'ListDatasetCollection(', this.get( 'name' ), ')' ].join( '' ));
+ }
+});
+
+
+//==============================================================================
+var PairDatasetCollection = DatasetCollection.extend(
+/** @lends ListDatasetCollection.prototype */{
+
+ /** String representation. */
+ toString : function(){
+ return ([ 'PairDatasetCollection(', this.get( 'name' ), ')' ].join( '' ));
+ }
+});
+
+
+//==============================================================================
+var ListPairedDatasetCollection = DatasetCollection.extend(
+/** @lends ListDatasetCollection.prototype */{
+
+ // list:paired is the only collection that itself contains collections
+ //collectionClass : DatasetCollectionCollection,
+
+ /** String representation. */
+ toString : function(){
+ return ([ 'ListPairedDatasetCollection(', this.get( 'name' ), ')' ].join( '' ));
+ }
+});
+
+
+//==============================================================================
+ return {
+ DatasetCollectionElement : DatasetCollectionElement,
+ DatasetCollectionElementCollection : DatasetCollectionElementCollection,
+ DatasetCollection : DatasetCollection,
+ DatasetCollectionCollection : DatasetCollectionCollection,
+ ListDatasetCollection : ListDatasetCollection,
+ PairDatasetCollection : PairDatasetCollection,
+ ListPairedDatasetCollection : ListPairedDatasetCollection
+ };
+});
diff -r 74d7ff952ec902e68cc99745fdcd3c14e86208b2 -r 598a4ec015f66237d41ed2176c673fd52b744f15 static/scripts/mvc/collection/collection-panel.js
--- /dev/null
+++ b/static/scripts/mvc/collection/collection-panel.js
@@ -0,0 +1,326 @@
+define([
+ "mvc/collection/dataset-collection-base",
+ "mvc/dataset/hda-base",
+ "mvc/base-mvc",
+ "utils/localization"
+], function( DC_BASE, HDA_BASE, BASE_MVC, _l ){
+/* =============================================================================
+TODO:
+
+============================================================================= */
+/** @class non-editable, read-only View/Controller for a dataset collection.
+ * @name CollectionPanel
+ *
+ * @augments Backbone.View
+ * @borrows LoggableMixin#logger as #logger
+ * @borrows LoggableMixin#log as #log
+ * @constructs
+ */
+var CollectionPanel = Backbone.View.extend( BASE_MVC.LoggableMixin ).extend(
+/** @lends CollectionPanel.prototype */{
+
+ /** logger used to record this.log messages, commonly set to console */
+ // comment this out to suppress log output
+ //logger : console,
+
+ tagName : 'div',
+ className : 'history-panel',
+
+ /** (in ms) that jquery effects will use */
+ fxSpeed : 'fast',
+
+ // ......................................................................... SET UP
+ /** Set up the view, set up storage, bind listeners to HistoryContents events
+ * @param {Object} attributes optional settings for the panel
+ */
+ initialize : function( attributes ){
+ attributes = attributes || {};
+ // set the logger if requested
+ if( attributes.logger ){
+ this.logger = attributes.logger;
+ }
+ this.log( this + '.initialize:', attributes );
+
+ this.hasUser = attributes.hasUser;
+ this.HDAViewClass = attributes.HDAViewClass || HDA_BASE.HDABaseView;
+ },
+
+ /** create any event listeners for the panel
+ * @fires: rendered:initial on the first render
+ * @fires: empty-history when switching to a history with no HDAs or creating a new history
+ */
+ _setUpListeners : function(){
+ // debugging
+ //if( this.logger ){
+ this.on( 'all', function( event ){
+ this.log( this + '', arguments );
+ }, this );
+ //}
+ return this;
+ },
+
+ // ------------------------------------------------------------------------ history/hda event listening
+ /** listening for history and HDA events */
+ _setUpModelEventHandlers : function(){
+ return this;
+ },
+
+ // ------------------------------------------------------------------------ panel rendering
+ /** Render urls, historyPanel body, and hdas (if any are shown)
+ * @fires: rendered when the panel is attached and fully visible
+ * @see Backbone.View#render
+ */
+ render : function( speed, callback ){
+ this.log( 'render:', speed, callback );
+ // send a speed of 0 to have no fade in/out performed
+ speed = ( speed === undefined )?( this.fxSpeed ):( speed );
+ //console.debug( this + '.render, fxSpeed:', speed );
+ var panel = this,
+ $newRender;
+
+ // handle the possibility of no model (can occur if fetching the model returns an error)
+ if( !this.model ){
+ return this;
+ }
+ $newRender = this.renderModel();
+
+ // fade out existing, swap with the new, fade in, set up behaviours
+ $( panel ).queue( 'fx', [
+ function( next ){
+ if( speed && panel.$el.is( ':visible' ) ){
+ panel.$el.fadeOut( speed, next );
+ } else {
+ next();
+ }
+ },
+ function( next ){
+ // swap over from temp div newRender
+ panel.$el.empty();
+ if( $newRender ){
+ panel.$el.append( $newRender.children() );
+ }
+ next();
+ },
+ function( next ){
+ if( speed && !panel.$el.is( ':visible' ) ){
+ panel.$el.fadeIn( speed, next );
+ } else {
+ next();
+ }
+ },
+ function( next ){
+ //TODO: ideally, these would be set up before the fade in (can't because of async save text)
+ if( callback ){ callback.call( this ); }
+ panel.trigger( 'rendered', this );
+ next();
+ }
+ ]);
+ return this;
+ },
+
+ /** render with history data
+ * @returns {jQuery} dom fragment as temporary container to be swapped out later
+ */
+ renderModel : function( ){
+ // tmp div for final swap in render
+ var $newRender = $( '<div/>' ).append( CollectionPanel.templates.panel( this.model.toJSON() ) );
+ this._setUpBehaviours( $newRender );
+ this.renderContents( $newRender );
+ return $newRender;
+ },
+
+ /** Set up HistoryPanel js/widget behaviours */
+ _setUpBehaviours : function( $where ){
+ //TODO: these should be either sub-MVs, or handled by events
+ $where = $where || this.$el;
+ $where.find( '[title]' ).tooltip({ placement: 'bottom' });
+ return this;
+ },
+
+ // ------------------------------------------------------------------------ sub-$element shortcuts
+ /** the scroll container for this panel - can be $el, $el.parent(), or grandparent depending on context */
+ $container : function(){
+ return ( this.findContainerFn )?( this.findContainerFn.call( this ) ):( this.$el.parent() );
+ },
+ /** where hdaViews are attached */
+ $datasetsList : function( $where ){
+ return ( $where || this.$el ).find( '.datasets-list' );
+ },
+
+ // ------------------------------------------------------------------------ sub-views
+ /** Set up/render a view for each HDA to be shown, init with model and listeners.
+ * HDA views are cached to the map this.hdaViews (using the model.id as key).
+ * @param {jQuery} $whereTo what dom element to prepend the HDA views to
+ * @returns the number of visible hda views
+ */
+ renderContents : function( $whereTo ){
+ //console.debug( 'renderContents, elements:', this.model.elements );
+ $whereTo = $whereTo || this.$el;
+
+ var panel = this,
+ contentViews = {},
+ visibleContents = this.model.elements || [];
+ //this.log( 'renderContents, visibleContents:', visibleContents, $whereTo );
+
+ this.$datasetsList( $whereTo ).empty();
+ if( visibleContents && visibleContents.length ){
+ visibleContents.each( function( content ){
+ var contentId = content.id,
+ contentView = panel._createContentView( content );
+ contentViews[ contentId ] = contentView;
+ panel.attachContentView( contentView.render(), $whereTo );
+ });
+ }
+ this.contentViews = contentViews;
+ return this.contentViews;
+ },
+
+ /**
+ * @param {HistoryDatasetAssociation} content
+ */
+ _createContentView : function( content ){
+ //console.debug( 'content json:', JSON.stringify( content, null, ' ' ) );
+ var contentView = null,
+ ContentClass = this._getContentClass( content );
+ //console.debug( 'content.object json:', JSON.stringify( content.object, null, ' ' ) );
+ //console.debug( 'ContentClass:', ContentClass );
+ //console.debug( 'content:', content );
+ //console.debug( 'content.object:', content.object );
+ contentView = new ContentClass({
+ model : content.object,
+ linkTarget : this.linkTarget,
+ //draggable : true,
+ hasUser : this.hasUser,
+ logger : this.logger
+ });
+ //this._setUpHdaListeners( contentView );
+ return contentView;
+ },
+
+ _getContentClass : function( content ){
+ switch( content.get( 'element_type' ) ){
+ case 'hda':
+ return this.HDAViewClass;
+ case 'dataset_collection':
+ return DC_BASE.NestedDCEBaseView;
+ }
+ throw new TypeError( 'Unknown element type:', content.get( 'element_type' ) );
+ },
+
+// /** Set up HistoryPanel listeners for HDAView events. Currently binds:
+// * HDAView#body-visible, HDAView#body-hidden to store expanded states
+// * @param {HDAView} hdaView HDAView (base or edit) to listen to
+// */
+// _setUpHdaListeners : function( hdaView ){
+// var panel = this;
+// hdaView.on( 'error', function( model, xhr, options, msg ){
+// panel.errorHandler( model, xhr, options, msg );
+// });
+// // maintain a list of hdas whose bodies are expanded
+// hdaView.on( 'body-expanded', function( model ){
+// panel.storage.addExpandedHda( model );
+// });
+// hdaView.on( 'body-collapsed', function( id ){
+// panel.storage.removeExpandedHda( id );
+// });
+// return this;
+// },
+
+ /** attach an contentView to the panel */
+ attachContentView : function( contentView, $whereTo ){
+ $whereTo = $whereTo || this.$el;
+ var $datasetsList = this.$datasetsList( $whereTo );
+ $datasetsList.append( contentView.$el );
+ return this;
+ },
+
+ // ------------------------------------------------------------------------ panel events
+ /** event map */
+ events : {
+ 'click .panel-navigation-back' : 'close'
+ },
+
+ /** */
+ close : function( event ){
+ this.$el.remove();
+ this.trigger( 'collection-close' );
+ },
+
+ // ........................................................................ misc
+ /** Return a string rep of the history */
+ toString : function(){
+ return 'CollectionPanel(' + (( this.model )?( this.model.get( 'name' )):( '' )) + ')';
+ }
+});
+
+
+//------------------------------------------------------------------------------ TEMPLATES
+var _panelTemplate = [
+ '<div class="history-controls">',
+ '<div class="panel-navigation">',
+ '<a class="panel-navigation-back" href="javascript:void(0)">', _l( 'Back' ), '</a>',
+ '</div>',
+
+ '<div class="history-title">',
+ '<% if( collection.name ){ %>',
+ '<div class="history-name"><%= collection.hid %> : <%= collection.name %></div>',
+ '<% } %>',
+ '</div>',
+
+ //'<div class="history-subtitle clear">',
+ // '<% if( history.nice_size ){ %>',
+ // '<div class="history-size"><%= history.nice_size %></div>',
+ // '<% } %>',
+ // '<div class="history-secondary-actions"></div>',
+ //'</div>',
+ //
+ //'<% if( history.deleted ){ %>',
+ // '<div class="warningmessagesmall"><strong>',
+ // _l( 'You are currently viewing a deleted history!' ),
+ // '</strong></div>',
+ //'<% } %>',
+ //
+ //'<div class="message-container">',
+ // '<% if( history.message ){ %>',
+ // // should already be localized
+ // '<div class="<%= history.status %>message"><%= history.message %></div>',
+ // '<% } %>',
+ //'</div>',
+ //
+ //'<div class="quota-message errormessage">',
+ // _l( 'You are over your disk quota' ), '. ',
+ // _l( 'Tool execution is on hold until your disk usage drops below your allocated quota' ), '.',
+ //'</div>',
+ //
+ //'<div class="tags-display"></div>',
+ //'<div class="annotation-display"></div>',
+ //'<div class="history-dataset-actions">',
+ // '<div class="btn-group">',
+ // '<button class="history-select-all-datasets-btn btn btn-default"',
+ // 'data-mode="select">', _l( 'All' ), '</button>',
+ // '<button class="history-deselect-all-datasets-btn btn btn-default"',
+ // 'data-mode="select">', _l( 'None' ), '</button>',
+ // '</div>',
+ // '<button class="history-dataset-action-popup-btn btn btn-default">',
+ // _l( 'For all selected' ), '...</button>',
+ //'</div>',
+ '</div>',
+ // end history controls
+
+ // where the datasets/hdas are added
+ '<div class="datasets-list"></div>'
+
+].join( '' );
+
+CollectionPanel.templates = {
+ panel : function( JSON ){
+ return _.template( _panelTemplate, JSON, { variable: 'collection' });
+ }
+};
+
+
+//==============================================================================
+ return {
+ CollectionPanel: CollectionPanel
+ };
+});
diff -r 74d7ff952ec902e68cc99745fdcd3c14e86208b2 -r 598a4ec015f66237d41ed2176c673fd52b744f15 static/scripts/mvc/collection/dataset-collection-base.js
--- a/static/scripts/mvc/collection/dataset-collection-base.js
+++ b/static/scripts/mvc/collection/dataset-collection-base.js
@@ -1,328 +1,151 @@
define([
- "mvc/history/history-content-base-view",
+ "mvc/base-mvc",
"utils/localization"
-], function( historyContentBaseView, _l ){
+], function( BASE_MVC, _l ){
/* global Backbone, LoggableMixin */
//==============================================================================
-/** @class Read only view for HistoryDatasetCollectionAssociation.
- * @name HDABaseView
+/** @class Read only view for DatasetCollection.
+ * @name DCBaseView
*
* @augments Backbone.View
* @borrows LoggableMixin#logger as #logger
* @borrows LoggableMixin#log as #log
* @constructs
*/
-var DatasetCollectionBaseView = historyContentBaseView.HistoryContentBaseView.extend({
- className : "dataset hda history-panel-hda",
- id : function(){ return 'hdca-' + this.model.get( 'id' ); },
+var DCBaseView = Backbone.View.extend( BASE_MVC.LoggableMixin ).extend({
+
+ /** logger used to record this.log messages, commonly set to console */
+ // comment this out to suppress log output
+ //logger : console,
+
+ /** */
+ className : "dataset-collection",
+ /** */
+ fxSpeed : 'fast',
/** */
initialize : function( attributes ){
if( attributes.logger ){ this.logger = this.model.logger = attributes.logger; }
- this.log( this + '.initialize:', attributes );
- /** is the view currently in selection mode? */
- this.selectable = attributes.selectable || false;
- //this.log( '\t selectable:', this.selectable );
- /** is the view currently selected? */
- this.selected = attributes.selected || false;
- /** is the body of this collection view expanded/not? */
- this.expanded = attributes.expanded || false;
+ this.log( 'DCBaseView.initialize:', attributes );
},
- /** */
- render : function( fade ){
- var $newRender = this._buildNewRender();
-
- this._queueNewRender( $newRender, fade );
- return this;
- },
-
- /** */
- _buildNewRender : function(){
- var $newRender = $( DatasetCollectionBaseView.templates.skeleton( this.model.toJSON() ) );
- $newRender.find( '.dataset-primary-actions' ).append( this._render_titleButtons() );
- $newRender.children( '.dataset-body' ).replaceWith( this._render_body() );
- this._setUpBehaviors( $newRender );
- return $newRender;
- },
-
- /** */
- _queueNewRender : function( $newRender, fade ) {
- fade = ( fade === undefined )?( true ):( fade );
- var view = this;
-
- // fade the old render out (if desired)
- if( fade ){
- $( view ).queue( function( next ){ this.$el.fadeOut( view.fxSpeed, next ); });
- }
- // empty the old render, update to any new HDA state, swap in the new render contents, handle multi-select
- $( view ).queue( function( next ){
- this.$el.empty()
- .attr( 'class', view.className ).addClass( 'state-' + view.model.get( 'state' ) )
- .append( $newRender.children() );
- if( this.selectable ){ this.showSelector( 0 ); }
- next();
- });
- // fade the new in
- if( fade ){
- $( view ).queue( function( next ){ this.$el.fadeIn( view.fxSpeed, next ); });
- }
- // trigger an event to know we're ready
- $( view ).queue( function( next ){
- this.trigger( 'rendered', view );
- if( this.model.inReadyState() ){
- this.trigger( 'rendered:ready', view );
- }
- if( this.draggable ){ this.draggableOn(); }
- next();
- });
- },
-
- // ................................................................................ titlebar buttons
- /** Render icon-button group for the common, most easily accessed actions.
- * @returns {jQuery} rendered DOM
- */
- _render_titleButtons : function(){
- // render just the display for read-only
- return [ ];
- },
-
- // ......................................................................... state body renderers
- /** Render the enclosing div of the collection body and, if expanded, the html in the body
- * @returns {jQuery} rendered DOM
- */
- _render_body : function(){
- var $body = $( '<div>Error: unknown state "' + this.model.get( 'state' ) + '".</div>' ),
- // cheesy: get function by assumed matching name
- renderFn = this[ '_render_body_' + this.model.get( 'state' ) ];
- if( _.isFunction( renderFn ) ){
- $body = renderFn.call( this );
- }
- this._setUpBehaviors( $body );
-
- // only render the body html if it's being shown
- if( this.expanded ){
- $body.show();
- }
- return $body;
- },
-
- /** set up js behaviors, event handlers for elements within the given container
- * @param {jQuery} $container jq object that contains the elements to process (defaults to this.$el)
- */
- _setUpBehaviors : function( $container ){
- $container = $container || this.$el;
- // set up canned behavior on children (bootstrap, popupmenus, editable_text, etc.)
- make_popup_menus( $container );
- $container.find( '[title]' ).tooltip({ placement : 'bottom' });
- },
-
- // TODO: Eliminate duplication between following event map and one for HDAs.
-
- // ......................................................................... events
- /** event map */
- events : {
- // expand the body when the title is clicked or when in focus and space or enter is pressed
- 'click .dataset-title-bar' : 'toggleBodyVisibility',
- 'keydown .dataset-title-bar' : 'toggleBodyVisibility',
-
- // toggle selected state
- 'click .dataset-selector' : 'toggleSelect'
- },
-
- /** Show or hide the body/details of history content.
- * note: if the model does not have detailed data, fetch that data before showing the body
- * @param {Event} event the event that triggered this (@link HDABaseView#events)
- * @param {Boolean} expanded if true, expand; if false, collapse
- * @fires body-expanded when a body has been expanded
- * @fires body-collapsed when a body has been collapsed
- */
- toggleBodyVisibility : function( event, expand ){
- // bail (with propagation) if keydown and not space or enter
- var KEYCODE_SPACE = 32, KEYCODE_RETURN = 13;
- if( event && ( event.type === 'keydown' )
- && !( event.keyCode === KEYCODE_SPACE || event.keyCode === KEYCODE_RETURN ) ){
- return true;
- }
-
- var $body = this.$el.find( '.dataset-body' );
- expand = ( expand === undefined )?( !$body.is( ':visible' ) ):( expand );
- if( expand ){
- this.expandBody();
- } else {
- this.collapseBody();
- }
- return false;
- },
-
- /** Render and show the full, detailed body of this view including extra data and controls.
- * @fires body-expanded when a body has been expanded
- */
- expandBody : function(){
- var contentView = this;
-
- function _renderBodyAndExpand(){
- contentView.$el.children( '.dataset-body' ).replaceWith( contentView._render_body() );
- contentView.$el.children( '.dataset-body' ).slideDown( contentView.fxSpeed, function(){
- contentView.expanded = true;
- contentView.trigger( 'body-expanded', contentView.model );
- });
- }
- // TODO: Fetch more details like HDA view...
- _renderBodyAndExpand();
- },
-
- /** Hide the body/details of an HDA.
- * @fires body-collapsed when a body has been collapsed
- */
- collapseBody : function(){
- var hdaView = this;
- this.$el.children( '.dataset-body' ).slideUp( hdaView.fxSpeed, function(){
- hdaView.expanded = false;
- hdaView.trigger( 'body-collapsed', hdaView.model.id );
- });
- },
-
- /** Render an 'ok' collection.
- * @param {jQuery} parent DOM to which to append this body
- */
- _render_body_ok : function(){
- // most common state renderer and the most complicated
- var $body = $( DatasetCollectionBaseView.templates.body( this.model.toJSON() ) );
-
- // return shortened form if del'd (no display apps or peek?)
- if( this.model.get( 'deleted' ) ){
- return $body;
- }
-
- return $body;
- },
-
- // ......................................................................... selection
- /** display a (fa-icon) checkbox on the left of the hda that fires events when checked
- * Note: this also hides the primary actions
- */
- showSelector : function(){
- // make sure selected state is represented properly
- if( this.selected ){
- this.select( null, true );
- }
-
- this.selectable = true;
- this.trigger( 'selectable', true, this );
-
- this.$( '.dataset-primary-actions' ).hide();
- this.$( '.dataset-selector' ).show();
- },
-
- /** remove the selection checkbox */
- hideSelector : function(){
- // reverse the process from showSelect
- this.selectable = false;
- this.trigger( 'selectable', false, this );
-
- this.$( '.dataset-selector' ).hide();
- this.$( '.dataset-primary-actions' ).show();
- },
-
- toggleSelector : function(){
- if( !this.$el.find( '.dataset-selector' ).is( ':visible' ) ){
- this.showSelector();
- } else {
- this.hideSelector();
- }
- },
-
- /** event handler for selection (also programmatic selection)
- */
- select : function( event ){
- // switch icon, set selected, and trigger event
- this.$el.find( '.dataset-selector span' )
- .removeClass( 'fa-square-o' ).addClass( 'fa-check-square-o' );
- if( !this.selected ){
- this.trigger( 'selected', this, event );
- this.selected = true;
- }
- return false;
- },
-
- /** event handler for clearing selection (also programmatic deselection)
- */
- deselect : function( event ){
- // switch icon, set selected, and trigger event
- this.$el.find( '.dataset-selector span' )
- .removeClass( 'fa-check-square-o' ).addClass( 'fa-square-o' );
- if( this.selected ){
- this.trigger( 'de-selected', this, event );
- this.selected = false;
- }
- return false;
- },
-
- toggleSelect : function( event ){
- if( this.selected ){
- this.deselect( event );
- } else {
- this.select( event );
- }
- },
+//TODO: render has been removed from the inheritance chain here, so this won't work when called as is
// ......................................................................... misc
/** String representation */
toString : function(){
var modelString = ( this.model )?( this.model + '' ):( '(no model)' );
- return 'HDCABaseView(' + modelString + ')';
+ return 'DCBaseView(' + modelString + ')';
}
});
-//------------------------------------------------------------------------------ TEMPLATES
-//TODO: possibly break these out into a sep. module
-var skeletonTemplate = _.template([
- '<div class="dataset hda">',
- '<div class="dataset-warnings">',
- '<% if ( collection.deleted ) { %>',
- '<div class="dataset-deleted-msg warningmessagesmall"><strong>',
- _l( 'This collection has been deleted.' ),
+/** templates for DCBaseViews (skeleton and body) */
+DCBaseView.templates = (function(){
+// use closure to run underscore template fn only once at module load
+ var skeletonTemplate = _.template([
+ '<div class="dataset hda">',
+ '<div class="dataset-warnings">',
+ '<% if ( collection.deleted ) { %>',
+ '<div class="dataset-deleted-msg warningmessagesmall"><strong>',
+ _l( 'This collection has been deleted.' ),
+ '</div>',
+ '<% } %>',
+ '<% if ( !collection.visible ) { %>',
+ '<div class="dataset-hidden-msg warningmessagesmall"><strong>',
+ _l( 'This collection has been hidden.' ),
+ '</div>',
+ '<% } %>',
+ '</div>',
+ '<div class="dataset-primary-actions"></div>',
+ '<div class="dataset-title-bar clear" tabindex="0">',
+ '<span class="dataset-state-icon state-icon"></span>',
+ '<div class="dataset-title">',
+ '<span class="dataset-name"><%- collection.name %></span>',
'</div>',
- '<% } %>',
- '<% if ( !collection.visible ) { %>',
- '<div class="dataset-hidden-msg warningmessagesmall"><strong>',
- _l( 'This collection has been hidden.' ),
- '</div>',
- '<% } %>',
- '</div>',
- '<div class="dataset-selector"><span class="fa fa-2x fa-square-o"></span></div>',
- '<div class="dataset-primary-actions"></div>',
- '<div class="dataset-title-bar clear" tabindex="0">',
- '<span class="dataset-state-icon state-icon"></span>',
- '<div class="dataset-title">',
- '<span class="hda-hid"><%= collection.hid %></span> ',
- '<span class="dataset-name"><%= collection.name %></span>',
'</div>',
- '</div>',
- '<div class="dataset-body"></div>',
- '</div>'
-].join( '' ));
+ '<div class="dataset-body"></div>',
+ '</div>'
+ ].join( '' ));
-var bodyTemplate = _.template([
- '<div class="dataset-body">',
- '<div class="dataset-summary">',
- _l( 'A dataset collection.' ),
- '</div>'
-].join( '' ));
+ var bodyTemplate = _.template([
+ '<div class="dataset-body">',
+ '<div class="dataset-summary">',
+ _l( 'A dataset collection.' ),
+ '</div>'
+ ].join( '' ));
-DatasetCollectionBaseView.templates = {
// we override here in order to pass the localizer (_L) into the template scope - since we use it as a fn within
- skeleton : function( collectionJSON ){
- return skeletonTemplate({ _l: _l, collection: collectionJSON });
- },
- body : function( collectionJSON ){
- return bodyTemplate({ _l: _l, collection: collectionJSON });
- }
-};
+ return {
+ skeleton : function( collectionJSON ){
+ return skeletonTemplate({ _l: _l, collection: collectionJSON });
+ },
+ body : function( collectionJSON ){
+ return bodyTemplate({ _l: _l, collection: collectionJSON });
+ }
+ };
+}());
+
+
+//TODO: unused
+////==============================================================================
+///** @class Read only view for DatasetCollectionElement.
+// * @name DCEBaseView
+// *
+// * @augments Backbone.View
+// * @borrows LoggableMixin#logger as #logger
+// * @borrows LoggableMixin#log as #log
+// * @constructs
+// */
+//var NestedDCBaseView = DCBaseView.extend({
+//
+// logger : console,
+//
+// /** */
+// initialize : function( attributes ){
+// if( attributes.logger ){ this.logger = this.model.logger = attributes.logger; }
+// this.warn( this + '.initialize:', attributes );
+// DCBaseView.prototype.initialize.call( this, attributes );
+// },
+//
+// _template : function(){
+// this.debug( this.model );
+// this.debug( this.model.toJSON() );
+// return NestedDCBaseView.templates.skeleton( this.model.toJSON() );
+// },
+//
+// // ......................................................................... misc
+// /** String representation */
+// toString : function(){
+// var modelString = ( this.model )?( this.model + '' ):( '(no model)' );
+// return 'NestedDCBaseView(' + modelString + ')';
+// }
+//});
+//
+////------------------------------------------------------------------------------ TEMPLATES
+////TODO: possibly break these out into a sep. module
+//NestedDCBaseView.templates = (function(){
+// var skeleton = _.template([
+// '<div class="dataset hda history-panel-hda state-ok">',
+// '<div class="dataset-primary-actions"></div>',
+// '<div class="dataset-title-bar clear" tabindex="0">',
+// '<div class="dataset-title">',
+// '<span class="dataset-name"><%= collection.name %></span>',
+// '</div>',
+// '</div>',
+// '</div>'
+// ].join( '' ));
+// // we override here in order to pass the localizer (_L) into the template scope - since we use it as a fn within
+// return {
+// skeleton : function( json ){
+// return skeleton({ _l: _l, collection: json });
+// }
+// };
+//}());
+
//==============================================================================
return {
- DatasetCollectionBaseView : DatasetCollectionBaseView
+ DCBaseView : DCBaseView,
+ //NestedDCBaseView : NestedDCBaseView,
};
});
diff -r 74d7ff952ec902e68cc99745fdcd3c14e86208b2 -r 598a4ec015f66237d41ed2176c673fd52b744f15 static/scripts/mvc/collection/dataset-collection-edit.js
--- a/static/scripts/mvc/collection/dataset-collection-edit.js
+++ b/static/scripts/mvc/collection/dataset-collection-edit.js
@@ -1,75 +1,36 @@
define([
- "mvc/dataset/hda-model",
+ "mvc/dataset/states",
"mvc/collection/dataset-collection-base",
"utils/localization"
-], function( hdaModel, datasetCollectionBase, _l ){
+], function( STATES, DC_BASE_VIEW, _l ){
//==============================================================================
-/** @class Editing view for HistoryDatasetCollectionAssociation.
+var _super = DC_BASE_VIEW.DCBaseView;
+/** @class Editing view for DatasetCollection.
* @name DatasetCollectionEditView
*
- * @augments DatasetCollectionBaseView
+ * @augments DCBaseView
* @constructs
*/
-var DatasetCollectionEditView = datasetCollectionBase.DatasetCollectionBaseView.extend( {
+var DCEditView = _super.extend({
+
+ /** logger used to record this.log messages, commonly set to console */
+ // comment this out to suppress log output
+ //logger : console,
initialize : function( attributes ){
- datasetCollectionBase.DatasetCollectionBaseView.prototype.initialize.call( this, attributes );
- },
-
- // ......................................................................... edit attr, delete
- /** Render icon-button group for the common, most easily accessed actions.
- * Overrides _render_titleButtons to include editing related buttons.
- * @see DatasetCollectionBaseView#_render_titleButtons
- * @returns {jQuery} rendered DOM
- */
- _render_titleButtons : function(){
- // render the display, edit attr and delete icon-buttons
- return datasetCollectionBase.DatasetCollectionBaseView.prototype._render_titleButtons.call( this ).concat([
- this._render_deleteButton()
- ]);
- },
-
- /** Render icon-button to delete this hda.
- * @returns {jQuery} rendered DOM
- */
- _render_deleteButton : function(){
- // don't show delete if...
- if( ( this.model.get( 'state' ) === hdaModel.HistoryDatasetAssociation.STATES.NEW )
- || ( this.model.get( 'state' ) === hdaModel.HistoryDatasetAssociation.STATES.NOT_VIEWABLE )
- || ( !this.model.get( 'accessible' ) ) ){
- return null;
- }
-
- var self = this,
- deleteBtnData = {
- title : _l( 'Delete' ),
- classes : 'dataset-delete',
- onclick : function() {
- // ...bler... tooltips being left behind in DOM (hover out never called on deletion)
- self.$el.find( '.icon-btn.dataset-delete' ).trigger( 'mouseout' );
- self.model[ 'delete' ]();
- }
- };
- if( this.model.get( 'deleted' ) ){
- deleteBtnData = {
- title : _l( 'Dataset collection is already deleted' ),
- disabled : true
- };
- }
- deleteBtnData.faIcon = 'fa-times';
- return faIconButton( deleteBtnData );
+ _super.prototype.initialize.call( this, attributes );
},
// ......................................................................... misc
/** string rep */
toString : function(){
var modelString = ( this.model )?( this.model + '' ):( '(no model)' );
- return 'HDCAEditView(' + modelString + ')';
+ return 'DCEditView(' + modelString + ')';
}
});
//==============================================================================
return {
- DatasetCollectionEditView : DatasetCollectionEditView
+ DCEditView : DCEditView
};
});
diff -r 74d7ff952ec902e68cc99745fdcd3c14e86208b2 -r 598a4ec015f66237d41ed2176c673fd52b744f15 static/scripts/mvc/collection/hdca-base.js
--- /dev/null
+++ b/static/scripts/mvc/collection/hdca-base.js
@@ -0,0 +1,116 @@
+define([
+ "mvc/base-mvc",
+ "mvc/collection/dataset-collection-base",
+ "mvc/history/history-content-base-view",
+ "utils/localization"
+], function( BASE_MVC, DC_BASE, HISTORY_CONTENT_BASE_VIEW, _l ){
+/* global Backbone, LoggableMixin */
+//==============================================================================
+var HCVMixin = HISTORY_CONTENT_BASE_VIEW.HistoryContentViewMixin,
+ _super = DC_BASE.DCBaseView;
+/** @class Read only view for HistoryDatasetCollectionAssociation.
+ * @name
+ *
+ * @augments Backbone.View
+ * @borrows LoggableMixin#logger as #logger
+ * @borrows LoggableMixin#log as #log
+ * @constructs
+ */
+var HDCABaseView = _super.extend( BASE_MVC.mixin( HCVMixin, {
+
+ /** logger used to record this.log messages, commonly set to console */
+ // comment this out to suppress log output
+ //logger : console,
+
+ /** */
+ className : "dataset hda history-panel-hda",
+
+ /** */
+ initialize : function( attributes ){
+ if( attributes.logger ){ this.logger = this.model.logger = attributes.logger; }
+ this.log( this + '.initialize:', attributes );
+ _super.prototype.initialize.call( this, attributes );
+ HCVMixin.initialize.call( this, attributes );
+ },
+
+ /** */
+ _template : function(){
+ return HDCABaseView.templates.skeleton( this.model.toJSON() );
+ },
+
+ /** */
+ events : _.extend( _.clone( HCVMixin.events ), {
+ }),
+
+ /** */
+ _renderBody : function(){
+ // override this
+ var $body = $( _super.templates.body( this.model.toJSON() ) );
+ if( this.expanded ){
+ $body.show();
+ }
+ return $body;
+ },
+
+ // ......................................................................... misc
+ /** String representation */
+ toString : function(){
+ var modelString = ( this.model )?( this.model + '' ):( '(no model)' );
+ return 'HDCABaseView(' + modelString + ')';
+ }
+}));
+
+/** templates for HDCAs (skeleton and body) */
+HDCABaseView.templates = HDCABaseView.prototype.templates = (function(){
+// use closure to run underscore template fn only once at module load
+ var skeletonTemplate = _.template([
+ '<div class="dataset hda">',
+ '<div class="dataset-warnings">',
+ '<% if ( collection.deleted ) { %>',
+ '<div class="dataset-deleted-msg warningmessagesmall"><strong>',
+ _l( 'This collection has been deleted.' ),
+ '</div>',
+ '<% } %>',
+ '<% if ( !collection.visible ) { %>',
+ '<div class="dataset-hidden-msg warningmessagesmall"><strong>',
+ _l( 'This collection has been hidden.' ),
+ '</div>',
+ '<% } %>',
+ '</div>',
+ '<div class="dataset-selector"><span class="fa fa-2x fa-square-o"></span></div>',
+ '<div class="dataset-primary-actions"></div>',
+ '<div class="dataset-title-bar clear" tabindex="0">',
+ '<span class="dataset-state-icon state-icon"></span>',
+ '<div class="dataset-title">',
+ '<span class="hda-hid"><%- collection.hid %></span> ',
+ '<span class="dataset-name"><%- collection.name %></span>',
+ '</div>',
+ '</div>',
+ '<div class="dataset-body"></div>',
+ '</div>'
+ ].join( '' ));
+
+ var bodyTemplate = _.template([
+ '<div class="dataset-body">',
+ '<div class="dataset-summary">',
+ _l( 'A dataset collection.' ),
+ '</div>'
+ ].join( '' ));
+
+ // we override here in order to pass the localizer (_L) into the template scope - since we use it as a fn within
+ return {
+ skeleton : function( collectionJSON ){
+ return skeletonTemplate({ _l: _l, collection: collectionJSON });
+ },
+ body : function( collectionJSON ){
+ return bodyTemplate({ _l: _l, collection: collectionJSON });
+ }
+ };
+}());
+
+
+//==============================================================================
+ return {
+ HDCABaseView : HDCABaseView
+ };
+});
diff -r 74d7ff952ec902e68cc99745fdcd3c14e86208b2 -r 598a4ec015f66237d41ed2176c673fd52b744f15 static/scripts/mvc/collection/hdca-edit.js
--- /dev/null
+++ b/static/scripts/mvc/collection/hdca-edit.js
@@ -0,0 +1,74 @@
+define([
+ "mvc/dataset/states",
+ "mvc/collection/hdca-base",
+ "utils/localization"
+], function( STATES, HDCA_BASE, _l ){
+//==============================================================================
+var _super = HDCA_BASE.HDCABaseView;
+/** @class Editing view for HistoryDatasetCollectionAssociation.
+ * @name DatasetCollectionEditView
+ *
+ * @augments HDCABaseView
+ * @constructs
+ */
+var HDCAEditView = _super.extend({
+
+ /** logger used to record this.log messages, commonly set to console */
+ // comment this out to suppress log output
+ //logger : console,
+
+ initialize : function( attributes ){
+ _super.prototype.initialize.call( this, attributes );
+ },
+
+ // ......................................................................... edit attr, delete
+ /** Render icon-button group for the common, most easily accessed actions.
+ * Overrides _render_titleButtons to include editing related buttons.
+ * @returns {jQuery} rendered DOM
+ */
+ _render_titleButtons : function(){
+ this.log( this + '._render_titleButtons' );
+ // render the display, edit attr and delete icon-buttons
+ return _super.prototype._render_titleButtons.call( this )
+ .concat([
+ this._render_deleteButton()
+ ]);
+ },
+
+ /** Render icon-button to delete this hda.
+ * @returns {jQuery} rendered DOM
+ */
+ _render_deleteButton : function(){
+ var self = this,
+ deleteBtnData = {
+ title : _l( 'Delete' ),
+ classes : 'dataset-delete',
+ onclick : function() {
+ // ...bler... tooltips being left behind in DOM (hover out never called on deletion)
+ self.$el.find( '.icon-btn.dataset-delete' ).trigger( 'mouseout' );
+ self.model[ 'delete' ]();
+ }
+ };
+ if( self.model.get( 'deleted' ) ){
+ deleteBtnData = {
+ title : _l( 'Dataset collection is already deleted' ),
+ disabled : true
+ };
+ }
+ deleteBtnData.faIcon = 'fa-times';
+ return faIconButton( deleteBtnData );
+ },
+
+ // ......................................................................... misc
+ /** string rep */
+ toString : function(){
+ var modelString = ( this.model )?( this.model + '' ):( '(no model)' );
+ return 'HDCAEditView(' + modelString + ')';
+ }
+});
+
+//==============================================================================
+ return {
+ HDCAEditView : HDCAEditView
+ };
+});
diff -r 74d7ff952ec902e68cc99745fdcd3c14e86208b2 -r 598a4ec015f66237d41ed2176c673fd52b744f15 static/scripts/mvc/collection/hdca-model.js
--- a/static/scripts/mvc/collection/hdca-model.js
+++ b/static/scripts/mvc/collection/hdca-model.js
@@ -1,69 +1,89 @@
define([
"mvc/history/history-content-base",
+ "mvc/collection/collection-model",
"utils/localization"
-], function( historyContent, _l ){
+], function( HISTORY_CONTENT, DC_MODEL, _l ){
//==============================================================================
-var HistoryDatasetCollectionAssociation = historyContent.HistoryContent.extend(
-/** @lends HistoryDatasetCollectionAssociation.prototype */{
- /** default attributes for a model */
- defaults : {
- // parent (containing) history
- history_id : null,
- // often used with tagging
- model_class : 'HistoryDatasetCollectionAssociation',
- history_content_type : 'dataset_collection',
- hid : 0,
+var hcontentMixin = HISTORY_CONTENT.HistoryContentMixin,
+/** @class Backbone model for (generic) Dataset Collection within a History.
+ * @constructs
+ */
+ HistoryDatasetCollection = DC_MODEL.DatasetCollection.extend( hcontentMixin );
- id : null,
- name : '(unnamed dataset collection)',
- // one of HistoryDatasetAssociation.STATES, calling them all 'ok' for now.
- state : 'ok',
- accessible : true,
- deleted : false,
- visible : true,
+//NOTE: the following prototypes may not be necessary - but I wanted to specifiy
+// them (for now) and allow for the possibility of unique functionality
+//==============================================================================
+var ListDC = DC_MODEL.ListDatasetCollection,
+/** @class Backbone model for List Dataset Collection within a History.
+ * @constructs
+ */
+ HistoryListDatasetCollection = ListDC.extend( hcontentMixin ).extend(
+/** @lends HistoryListDatasetCollection.prototype */{
- purged : false, // Purged doesn't make sense for collections - at least right now.
-
- tags : [],
- annotation : ''
- },
- urls : function(){
+ initialize : function( model, options ){
+ ListDC.prototype.initialize.call( this, model, options );
+ hcontentMixin.initialize.call( this, model, options );
+ //TODO: in lieu of any state info for collections, show as 'ok'
+ this.set( 'state', 'ok', { silent: true });
},
- inReadyState : function(){
- return true; // TODO
- },
-
- // ........................................................................ search
- /** what attributes of an collection will be used in a text search */
- searchAttributes : [
- 'name'
- ],
-
- /** our attr keys don't often match the labels we display to the user - so, when using
- * attribute specifiers ('name="bler"') in a term, allow passing in aliases for the
- * following attr keys.
- */
- searchAliases : {
- title : 'name'
- // TODO: Add tag...
- },
-
- // ........................................................................ misc
- /** String representation */
+ /** String representation. */
toString : function(){
- var nameAndId = this.get( 'id' ) || '';
- if( this.get( 'name' ) ){
- nameAndId = this.get( 'hid' ) + ' :"' + this.get( 'name' ) + '",' + nameAndId;
- }
- return 'HDCA-' + this.get( 'collection_type' ) + '(' + nameAndId + ')';
+ return ([ 'HistoryListDatasetCollection(', this.get( 'name' ), ')' ].join( '' ));
}
});
//==============================================================================
+var PairDC = DC_MODEL.PairDatasetCollection,
+/** @class Backbone model for Pair Dataset Collection within a History.
+ * @constructs
+ */
+ HistoryPairDatasetCollection = PairDC.extend( hcontentMixin ).extend(
+/** @lends HistoryPairDatasetCollection.prototype */{
+
+ initialize : function( model, options ){
+ PairDC.prototype.initialize.call( this, model, options );
+ hcontentMixin.initialize.call( this, model, options );
+ //TODO: in lieu of any state info for collections, show as 'ok'
+ this.set( 'state', 'ok', { silent: true });
+ },
+
+ /** String representation. */
+ toString : function(){
+ return ([ 'HistoryPairDatasetCollection(', this.get( 'name' ), ')' ].join( '' ));
+ }
+});
+
+
+//==============================================================================
+var ListPairedDC = DC_MODEL.ListPairedDatasetCollection,
+/** @class Backbone model for List of Pairs Dataset Collection within a History.
+ * @constructs
+ */
+ HistoryListPairedDatasetCollection = ListPairedDC.extend( hcontentMixin ).extend(
+/** @lends HistoryListPairedDatasetCollection.prototype */{
+
+ initialize : function( model, options ){
+ ListPairedDC.prototype.initialize.call( this, model, options );
+ hcontentMixin.initialize.call( this, model, options );
+ //TODO: in lieu of any state info for collections, show as 'ok'
+ this.set( 'state', 'ok', { silent: true });
+ },
+
+ /** String representation. */
+ toString : function(){
+ return ([ 'HistoryListPairedDatasetCollection(', this.get( 'name' ), ')' ].join( '' ));
+ }
+});
+
+
+//==============================================================================
return {
- HistoryDatasetCollectionAssociation : HistoryDatasetCollectionAssociation
+ HistoryDatasetCollection : HistoryDatasetCollection,
+ HistoryListDatasetCollection : HistoryListDatasetCollection,
+ HistoryPairDatasetCollection : HistoryPairDatasetCollection,
+ HistoryListPairedDatasetCollection : HistoryListPairedDatasetCollection
};
});
diff -r 74d7ff952ec902e68cc99745fdcd3c14e86208b2 -r 598a4ec015f66237d41ed2176c673fd52b744f15 static/scripts/mvc/dataset/hda-base.js
--- a/static/scripts/mvc/dataset/hda-base.js
+++ b/static/scripts/mvc/dataset/hda-base.js
@@ -1,11 +1,12 @@
define([
- "mvc/dataset/hda-model",
+ "mvc/dataset/states",
"mvc/history/history-content-base-view",
"mvc/data",
"utils/localization"
-], function( hdaModel, historyContentBaseView, dataset, _l ){
+], function( STATES, HCONTENT_BASE_VIEW, DATA, _l ){
/* global Backbone */
//==============================================================================
+var _super = HCONTENT_BASE_VIEW.HistoryContentBaseView;
/** @class Read only view for HistoryDatasetAssociation.
* @name HDABaseView
*
@@ -14,11 +15,11 @@
* @borrows LoggableMixin#log as #log
* @constructs
*/
-var HDABaseView = historyContentBaseView.HistoryContentBaseView.extend(
+var HDABaseView = _super.extend(
/** @lends HDABaseView.prototype */{
- ///** logger used to record this.log messages, commonly set to console */
- //// comment this out to suppress log output
+ /** logger used to record this.log messages, commonly set to console */
+ // comment this out to suppress log output
//logger : console,
tagName : "div",
@@ -38,6 +39,8 @@
if( attributes.logger ){ this.logger = this.model.logger = attributes.logger; }
this.log( this + '.initialize:', attributes );
+ _super.prototype.initialize.call( this, attributes );
+
/** list of rendering functions for the default, primary icon-buttons. */
this.defaultPrimaryActionButtonRenderers = [
this._render_showParamsButton
@@ -46,15 +49,6 @@
/** where should pages from links be displayed? (default to new tab/window) */
this.linkTarget = attributes.linkTarget || '_blank';
- /** is the view currently in selection mode? */
- this.selectable = attributes.selectable || false;
- //this.log( '\t selectable:', this.selectable );
- /** is the view currently selected? */
- this.selected = attributes.selected || false;
- //this.log( '\t selected:', this.selected );
- /** is the body of this hda view expanded/not? */
- this.expanded = attributes.expanded || false;
- //this.log( '\t expanded:', this.expanded );
/** is the body of this hda view expanded/not? */
this.draggable = attributes.draggable || false;
//this.log( '\t draggable:', this.draggable );
@@ -86,77 +80,20 @@
// ......................................................................... render main
/** Render this HDA, set up ui.
* @param {Boolean} fade whether or not to fade out/in when re-rendering
- * @fires rendered when rendered
- * @fires rendered:ready when first rendered and NO running HDAs
* @returns {Object} this HDABaseView
*/
render : function( fade ){
//HACK: hover exit doesn't seem to be called on prev. tooltips when RE-rendering - so: no tooltip hide
// handle that here by removing previous view's tooltips
this.$el.find("[title]").tooltip( "destroy" );
-
// re-get web controller urls for functions relating to this hda. (new model data may have changed this)
this.urls = this.model.urls();
- var $newRender = this._buildNewRender();
- this._queueNewRender( $newRender, fade );
- return this;
-
+ return _super.prototype.render.call( this, fade );
},
- _buildNewRender : function(){
- // create a new render using a skeleton template, render title buttons, render body, and set up events, etc.
- var $newRender = $( HDABaseView.templates.skeleton( this.model.toJSON() ) );
- $newRender.find( '.dataset-primary-actions' ).append( this._render_titleButtons() );
- $newRender.children( '.dataset-body' ).replaceWith( this._render_body() );
- this._setUpBehaviors( $newRender );
- //this._renderSelectable( $newRender );
- return $newRender;
- },
-
- _queueNewRender : function( $newRender, fade ) {
- fade = ( fade === undefined )?( true ):( fade );
- var view = this;
-
- // fade the old render out (if desired)
- if( fade ){
- $( view ).queue( function( next ){ this.$el.fadeOut( view.fxSpeed, next ); });
- }
- // empty the old render, update to any new HDA state, swap in the new render contents, handle multi-select
- $( view ).queue( function( next ){
- this.$el.empty()
- .attr( 'class', view.className ).addClass( 'state-' + view.model.get( 'state' ) )
- .append( $newRender.children() );
- if( this.selectable ){ this.showSelector( 0 ); }
- next();
- });
- // fade the new in
- if( fade ){
- $( view ).queue( function( next ){ this.$el.fadeIn( view.fxSpeed, next ); });
- }
- // trigger an event to know we're ready
- $( view ).queue( function( next ){
- this.trigger( 'rendered', view );
- if( this.model.inReadyState() ){
- this.trigger( 'rendered:ready', view );
- }
- if( this.draggable ){ this.draggableOn(); }
- next();
- });
- },
-
- /** set up js behaviors, event handlers for elements within the given container
- * @param {jQuery} $container jq object that contains the elements to process (defaults to this.$el)
- */
- _setUpBehaviors : function( $container ){
- $container = $container || this.$el;
- // set up canned behavior on children (bootstrap, popupmenus, editable_text, etc.)
- make_popup_menus( $container );
- $container.find( '[title]' ).tooltip({ placement : 'bottom' });
- },
-
// ................................................................................ titlebar buttons
- /** Render icon-button group for the common, most easily accessed actions.
+ /** In this override, render the dataset display button
* @returns {jQuery} rendered DOM
*/
_render_titleButtons : function(){
@@ -170,8 +107,8 @@
_render_displayButton : function(){
// don't show display if not viewable or not accessible
// (do show if in error, running)
- if( ( this.model.get( 'state' ) === hdaModel.HistoryDatasetAssociation.STATES.NOT_VIEWABLE )
- || ( this.model.get( 'state' ) === hdaModel.HistoryDatasetAssociation.STATES.DISCARDED )
+ if( ( this.model.get( 'state' ) === STATES.NOT_VIEWABLE )
+ || ( this.model.get( 'state' ) === STATES.DISCARDED )
|| ( !this.model.get( 'accessible' ) ) ){
return null;
}
@@ -187,12 +124,12 @@
displayBtnData.title = _l( 'Cannot display datasets removed from disk' );
// disable if still uploading
- } else if( this.model.get( 'state' ) === hdaModel.HistoryDatasetAssociation.STATES.UPLOAD ){
+ } else if( this.model.get( 'state' ) === STATES.UPLOAD ){
displayBtnData.disabled = true;
displayBtnData.title = _l( 'This dataset must finish uploading before it can be viewed' );
// disable if still new
- } else if( this.model.get( 'state' ) === hdaModel.HistoryDatasetAssociation.STATES.NEW ){
+ } else if( this.model.get( 'state' ) === STATES.NEW ){
displayBtnData.disabled = true;
displayBtnData.title = _l( 'This dataset is not yet viewable' );
@@ -211,9 +148,9 @@
title : "Data Viewer: " + self.model.get( 'name' ),
type : "other",
content : function( parent_elt ){
- var new_dataset = new dataset.TabularDataset({ id: self.model.get( 'id' ) });
+ var new_dataset = new DATA.TabularDataset({ id: self.model.get( 'id' ) });
$.when( new_dataset.fetch() ).then( function(){
- dataset.createTabularDatasetChunkedView({
+ DATA.createTabularDatasetChunkedView({
model: new_dataset,
parent_elt: parent_elt,
embedded: true,
@@ -298,7 +235,7 @@
/** Render the enclosing div of the hda body and, if expanded, the html in the body
* @returns {jQuery} rendered DOM
*/
- _render_body : function(){
+ _renderBody : function(){
var $body = $( '<div>Error: unknown dataset state "' + this.model.get( 'state' ) + '".</div>' ),
// cheesy: get function by assumed matching name
renderFn = this[ '_render_body_' + this.model.get( 'state' ) ];
@@ -437,61 +374,23 @@
// ......................................................................... events
/** event map */
- events : {
- // expand the body when the title is clicked or when in focus and space or enter is pressed
- 'click .dataset-title-bar' : 'toggleBodyVisibility',
- 'keydown .dataset-title-bar' : 'toggleBodyVisibility',
+ events : _.extend( _.clone( _super.prototype.events ), {
+ }),
- // dragging - don't work, originalEvent === null
- //'dragstart .dataset-title-bar' : 'dragStartHandler',
- //'dragend .dataset-title-bar' : 'dragEndHandler'
-
- // toggle selected state
- 'click .dataset-selector' : 'toggleSelect'
- },
-
- /** Show or hide the body/details of history content.
- * note: if the model does not have detailed data, fetch that data before showing the body
- * @param {Event} event the event that triggered this (@link HDABaseView#events)
- * @param {Boolean} expanded if true, expand; if false, collapse
- * @fires body-expanded when a body has been expanded
- * @fires body-collapsed when a body has been collapsed
+ /** Override for expanding hda details (within the panel)
+ * note: in this override, the fetch for details does *not* fire a change event (silent == true)
+ * @fires expanded when a body has been expanded
*/
- toggleBodyVisibility : function( event, expand ){
- // bail (with propagation) if keydown and not space or enter
- var KEYCODE_SPACE = 32, KEYCODE_RETURN = 13;
- if( event && ( event.type === 'keydown' )
- && !( event.keyCode === KEYCODE_SPACE || event.keyCode === KEYCODE_RETURN ) ){
- return true;
- }
-
- var $body = this.$el.find( '.dataset-body' );
- expand = ( expand === undefined )?( !$body.is( ':visible' ) ):( expand );
- if( expand ){
- this.expandBody();
- } else {
- this.collapseBody();
- }
- return false;
- },
-
- /** Render and show the full, detailed body of this view including extra data and controls.
- * @fires body-expanded when a body has been expanded
- */
- expandBody : function(){
+ expand : function(){
var hdaView = this;
function _renderBodyAndExpand(){
- hdaView.$el.children( '.dataset-body' ).replaceWith( hdaView._render_body() );
+ hdaView.$el.children( '.dataset-body' ).replaceWith( hdaView._renderBody() );
+ //NOTE: needs to be set after the above or the slide will not show
+ hdaView.expanded = true;
hdaView.$el.children( '.dataset-body' ).slideDown( hdaView.fxSpeed, function(){
- hdaView.expanded = true;
- hdaView.trigger( 'body-expanded', hdaView.model );
+ hdaView.trigger( 'expanded', hdaView.model );
});
-
- //hdaView.render( false ).$el.children( '.dataset-body' ).slideDown( hdaView.fxSpeed, function(){
- // hdaView.expanded = true;
- // hdaView.trigger( 'body-expanded', hdaView.model.get( 'id' ) );
- //});
}
// fetch first if no details in the model
if( this.model.inReadyState() && !this.model.hasDetails() ){
@@ -505,128 +404,6 @@
}
},
- /** Hide the body/details of an HDA.
- * @fires body-collapsed when a body has been collapsed
- */
- collapseBody : function(){
- var hdaView = this;
- this.$el.children( '.dataset-body' ).slideUp( hdaView.fxSpeed, function(){
- hdaView.expanded = false;
- hdaView.trigger( 'body-collapsed', hdaView.model.id );
- });
- },
-
- // ......................................................................... selection
- /** display a (fa-icon) checkbox on the left of the hda that fires events when checked
- * Note: this also hides the primary actions
- */
- showSelector : function(){
- // make sure selected state is represented properly
- if( this.selected ){
- this.select( null, true );
- }
-
- this.selectable = true;
- this.trigger( 'selectable', true, this );
-
- this.$( '.dataset-primary-actions' ).hide();
- this.$( '.dataset-selector' ).show();
- },
-
- /** remove the selection checkbox */
- hideSelector : function(){
- // reverse the process from showSelect
- this.selectable = false;
- this.trigger( 'selectable', false, this );
-
- this.$( '.dataset-selector' ).hide();
- this.$( '.dataset-primary-actions' ).show();
- },
-
- toggleSelector : function(){
- if( !this.$el.find( '.dataset-selector' ).is( ':visible' ) ){
- this.showSelector();
- } else {
- this.hideSelector();
- }
- },
-
- /** event handler for selection (also programmatic selection)
- */
- select : function( event ){
- // switch icon, set selected, and trigger event
- this.$el.find( '.dataset-selector span' )
- .removeClass( 'fa-square-o' ).addClass( 'fa-check-square-o' );
- if( !this.selected ){
- this.trigger( 'selected', this, event );
- this.selected = true;
- }
- return false;
- },
-
- /** event handler for clearing selection (also programmatic deselection)
- */
- deselect : function( event ){
- // switch icon, set selected, and trigger event
- this.$el.find( '.dataset-selector span' )
- .removeClass( 'fa-check-square-o' ).addClass( 'fa-square-o' );
- if( this.selected ){
- this.trigger( 'de-selected', this, event );
- this.selected = false;
- }
- return false;
- },
-
- toggleSelect : function( event ){
- if( this.selected ){
- this.deselect( event );
- } else {
- this.select( event );
- }
- },
-
- // ......................................................................... drag/drop
- draggableOn : function(){
- this.draggable = true;
- //TODO: I have no idea why this doesn't work with the events hash or jq.on()...
- //this.$el.find( '.dataset-title-bar' )
- // .attr( 'draggable', true )
- // .bind( 'dragstart', this.dragStartHandler, false )
- // .bind( 'dragend', this.dragEndHandler, false );
- this.dragStartHandler = _.bind( this._dragStartHandler, this );
- this.dragEndHandler = _.bind( this._dragEndHandler, this );
-
- var titleBar = this.$el.find( '.dataset-title-bar' ).attr( 'draggable', true ).get(0);
- titleBar.addEventListener( 'dragstart', this.dragStartHandler, false );
- titleBar.addEventListener( 'dragend', this.dragEndHandler, false );
- },
- draggableOff : function(){
- this.draggable = false;
- var titleBar = this.$el.find( '.dataset-title-bar' ).attr( 'draggable', false ).get(0);
- titleBar.removeEventListener( 'dragstart', this.dragStartHandler, false );
- titleBar.removeEventListener( 'dragend', this.dragEndHandler, false );
- },
- toggleDraggable : function(){
- if( this.draggable ){
- this.draggableOff();
- } else {
- this.draggableOn();
- }
- },
- _dragStartHandler : function( event ){
- //console.debug( 'dragStartHandler:', this, event, arguments )
- this.trigger( 'dragstart', this );
- event.dataTransfer.effectAllowed = 'move';
- //TODO: all except IE: should be 'application/json', IE: must be 'text'
- event.dataTransfer.setData( 'text', JSON.stringify( this.model.toJSON() ) );
- return false;
- },
- _dragEndHandler : function( event ){
- this.trigger( 'dragend', this );
- //console.debug( 'dragEndHandler:', event )
- return false;
- },
-
// ......................................................................... removal
/** Remove this view's html from the DOM and remove all event listeners.
* @param {Function} callback an optional function called when removal is done
@@ -799,7 +576,7 @@
'</div>'
].join( '' ));
-HDABaseView.templates = {
+HDABaseView.templates = HDABaseView.prototype.templates = {
// we override here in order to pass the localizer (_L) into the template scope - since we use it as a fn within
skeleton : function( hdaJSON ){
return skeletonTemplate({ _l: _l, hda: hdaJSON });
This diff is so big that we needed to truncate the remainder.
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0