galaxy-dev
Threads by month
- ----- 2025 -----
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- 10007 discussions
29 Aug '09
details: http://www.bx.psu.edu/hg/galaxy/rev/3ef81a4d574e
changeset: 2649:3ef81a4d574e
user: jeremy goecks <jeremy.goecks(a)emory.edu>
date: Fri Aug 28 15:42:37 2009 -0400
description:
tags module for handling and processing tags
2 file(s) affected in this change:
lib/galaxy/tags/__init__.py
lib/galaxy/tags/tag_handler.py
diffs (238 lines):
diff -r 7aa2475b7fa9 -r 3ef81a4d574e lib/galaxy/tags/__init__.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/galaxy/tags/__init__.py Fri Aug 28 15:42:37 2009 -0400
@@ -0,0 +1,3 @@
+"""
+Galaxy tagging classes and methods.
+"""
diff -r 7aa2475b7fa9 -r 3ef81a4d574e lib/galaxy/tags/tag_handler.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/galaxy/tags/tag_handler.py Fri Aug 28 15:42:37 2009 -0400
@@ -0,0 +1,226 @@
+from galaxy.model import Tag, History, HistoryTagAssociation, Dataset, DatasetTagAssociation, HistoryDatasetAssociation, HistoryDatasetAssociationTagAssociation
+import re
+
+class TagHandler( object ):
+
+ # Tag separator.
+ tag_separators = ',;'
+
+ # Hierarchy separator.
+ hierarchy_separator = '.'
+
+ # Key-value separator.
+ key_value_separators = "=:"
+
+ def __init__(self):
+ self.tag_assoc_classes = dict()
+
+ def add_tag_assoc_class(self, entity_class, tag_assoc_class):
+ self.tag_assoc_classes[entity_class] = tag_assoc_class
+
+ def get_tag_assoc_class(self, entity_class):
+ return self.tag_assoc_classes[entity_class]
+
+ # Remove a tag from an item.
+ def remove_item_tag(self, item, tag_name):
+ # Get item tag association.
+ item_tag_assoc = self._get_item_tag_assoc(item, tag_name)
+
+ # Remove association.
+ if item_tag_assoc:
+ # Delete association.
+ item_tag_assoc.delete()
+ item.tags.remove(item_tag_assoc)
+ return True
+
+ return False
+
+ # Delete tags from an item.
+ def delete_item_tags(self, item):
+ # Delete item-tag associations.
+ for tag in item.tags:
+ tag.delete()
+
+ # Delete tags from item.
+ del item.tags[:]
+
+ # Returns true if item is has a given tag.
+ def item_has_tag(self, item, tag_name):
+ # Check for an item-tag association to see if item has a given tag.
+ item_tag_assoc = self._get_item_tag_assoc(item, tag_name)
+ if item_tag_assoc:
+ return True
+ return False
+
+
+ # Apply tags to an item.
+ def apply_item_tags(self, db_session, item, tags_str):
+ # Parse tags.
+ parsed_tags = self._parse_tags(tags_str)
+
+ # Apply each tag.
+ for name, value in parsed_tags.items():
+ # Get or create item-tag association.
+ item_tag_assoc = self._get_item_tag_assoc(item, name)
+ if not item_tag_assoc:
+ #
+ # Create item-tag association.
+ #
+
+ # Create tag; if None, skip the tag (and log error).
+ tag = self._get_or_create_tag(db_session, name)
+ if not tag:
+ # Log error?
+ continue
+
+ # Create tag association based on item class.
+ item_tag_assoc_class = self.tag_assoc_classes[item.__class__]
+ item_tag_assoc = item_tag_assoc_class()
+
+ # Add tag to association.
+ item.tags.append(item_tag_assoc)
+ item_tag_assoc.tag = tag
+
+ # Apply attributes to item-tag association. Strip whitespace from user name and tag.
+ if value:
+ trimmed_value = value.strip()
+ else:
+ trimmed_value = value
+ item_tag_assoc.user_tname = name.strip()
+ item_tag_assoc.user_value = trimmed_value
+ item_tag_assoc.value = self._scrub_tag_value(value)
+
+ # Build a string from an item's tags.
+ def get_tags_str(self, tags):
+ # Return empty string if there are no tags.
+ if not tags:
+ return ""
+
+ # Create string of tags.
+ tags_str_list = list()
+ for tag in tags:
+ tag_str = tag.user_tname
+ if tag.value is not None:
+ tag_str += ":" + tag.user_value
+ tags_str_list.append(tag_str)
+ return ", ".join(tags_str_list)
+
+ # Get a Tag object from a tag string.
+ def _get_tag(self, db_session, tag_str):
+ return db_session.query(Tag).filter(Tag.name==tag_str).first()
+
+ # Create a Tag object from a tag string.
+ def _create_tag(self, db_session, tag_str):
+ tag_hierarchy = tag_str.split(self.__class__.hierarchy_separator)
+ tag_prefix = ""
+ parent_tag = None
+ for sub_tag in tag_hierarchy:
+ # Get or create subtag.
+ tag_name = tag_prefix + self._scrub_tag_name(sub_tag)
+ tag = db_session.query(Tag).filter(Tag.name==tag_name).first()
+ if not tag:
+ tag = Tag(type="generic", name=tag_name)
+
+ # Set tag parent.
+ tag.parent = parent_tag
+
+ # Update parent and tag prefix.
+ parent_tag = tag
+ tag_prefix = tag.name + self.__class__.hierarchy_separator
+ return tag
+
+ # Get or create a Tag object from a tag string.
+ def _get_or_create_tag(self, db_session, tag_str):
+ # Scrub tag; if tag is None after being scrubbed, return None.
+ scrubbed_tag_str = self._scrub_tag_name(tag_str)
+ if not scrubbed_tag_str:
+ return None
+
+ # Get item tag.
+ tag = self._get_tag(db_session, scrubbed_tag_str)
+
+ # Create tag if necessary.
+ if tag is None:
+ tag = self._create_tag(db_session, scrubbed_tag_str)
+
+ return tag
+
+ # Return ItemTagAssociation object for an item and a tag string; returns None if there is
+ # no such tag.
+ def _get_item_tag_assoc(self, item, tag_name):
+ scrubbed_tag_name = self._scrub_tag_name(tag_name)
+ for item_tag_assoc in item.tags:
+ if item_tag_assoc.tag.name == scrubbed_tag_name:
+ return item_tag_assoc
+ return None
+
+ # Returns a list of raw (tag-name, value) pairs derived from a string; method does not scrub tags.
+ # Return value is a dictionary where tag-names are keys.
+ def _parse_tags(self, tag_str):
+ # Gracefully handle None.
+ if not tag_str:
+ return dict()
+
+ # Split tags based on separators.
+ reg_exp = re.compile('[' + self.__class__.tag_separators + ']')
+ raw_tags = reg_exp.split(tag_str)
+
+ # Extract name-value pairs.
+ name_value_pairs = dict()
+ for raw_tag in raw_tags:
+ nv_pair = self._get_name_value_pair(raw_tag)
+ name_value_pairs[nv_pair[0]] = nv_pair[1]
+ return name_value_pairs
+
+ # Scrub a tag value.
+ def _scrub_tag_value(self, value):
+ # Gracefully handle None:
+ if not value:
+ return None
+
+ # Remove whitespace from value.
+ reg_exp = re.compile('\s')
+ scrubbed_value = re.sub(reg_exp, "", value)
+
+ # Lowercase and return.
+ return scrubbed_value.lower()
+
+ # Scrub a tag name.
+ def _scrub_tag_name(self, name):
+ # Gracefully handle None:
+ if not name:
+ return None
+
+ # Remove whitespace from name.
+ reg_exp = re.compile('\s')
+ scrubbed_name = re.sub(reg_exp, "", name)
+
+ # Ignore starting ':' char.
+ if scrubbed_name.startswith(self.__class__.hierarchy_separator):
+ scrubbed_name = scrubbed_name[1:]
+
+ # If name is too short or too long, return None.
+ if len(scrubbed_name) < 3 or len(scrubbed_name) > 255:
+ return None
+
+ # Lowercase and return.
+ return scrubbed_name.lower()
+
+ # Scrub a tag name list.
+ def _scrub_tag_name_list(self, tag_name_list):
+ scrubbed_tag_list = list()
+ for tag in tag_name_list:
+ scrubbed_tag_list.append(self._scrub_tag_name(tag))
+ return scrubbed_tag_list
+
+ # Get name, value pair from a tag string.
+ def _get_name_value_pair(self, tag_str):
+ # Use regular expression to parse name, value.
+ reg_exp = re.compile("[" + self.__class__.key_value_separators + "]")
+ name_value_pair = reg_exp.split(tag_str)
+
+ # Add empty slot if tag does not have value.
+ if len(name_value_pair) < 2:
+ name_value_pair.append(None)
+
+ return name_value_pair
\ No newline at end of file
1
0
details: http://www.bx.psu.edu/hg/galaxy/rev/7aa2475b7fa9
changeset: 2648:7aa2475b7fa9
user: jeremy goecks <jeremy.goecks(a)emory.edu>
date: Fri Aug 28 15:40:58 2009 -0400
description:
add tagging to HDAs
1 file(s) affected in this change:
templates/dataset/edit_attributes.mako
diffs (74 lines):
diff -r 77dfb7834a94 -r 7aa2475b7fa9 templates/dataset/edit_attributes.mako
--- a/templates/dataset/edit_attributes.mako Fri Aug 28 15:40:32 2009 -0400
+++ b/templates/dataset/edit_attributes.mako Fri Aug 28 15:40:58 2009 -0400
@@ -3,6 +3,50 @@
<%def name="title()">${_('Edit Dataset Attributes')}</%def>
+<%def name="stylesheets()">
+ ${h.css( "base", "history", "autocomplete_tagging" )}
+</%def>
+
+<%def name="javascripts()">
+ ## <!--[if lt IE 7]>
+ ## <script type='text/javascript' src="/static/scripts/IE7.js"> </script>
+ ## <![endif]-->
+ ${h.js( "jquery", "galaxy.base", "jquery.autocomplete", "autocomplete_tagging" )}
+ <script type="text/javascript">
+ $( document ).ready( function() {
+ // Set up autocomplete tagger.
+<%
+ ## Build string of tag name, values.
+ tag_names_and_values = list()
+ for tag in data.tags:
+ tag_name = tag.user_tname
+ tag_value = ""
+ if tag.value is not None:
+ tag_value = tag.user_value
+ tag_names_and_values.append("\"" + tag_name + "\" : \"" + tag_value + "\"")
+%>
+ var options =
+ {
+ tags : {${", ".join(tag_names_and_values)}},
+ tag_click_fn: function(tag) { /* Do nothing. */ },
+ use_toggle_link: false,
+ input_size: 30,
+ in_form: true,
+ <% encoded_data_id = trans.security.encode_id(data.id) %>
+ ajax_autocomplete_tag_url: "${h.url_for( controller='tag', action='tag_autocomplete_data', id=encoded_data_id, item_type="hda" )}",
+ ajax_add_tag_url: "${h.url_for( controller='tag', action='add_tag_async', id=encoded_data_id, item_type="hda" )}",
+ ajax_delete_tag_url: "${h.url_for( controller='tag', action='remove_tag_async', id=encoded_data_id, item_type="hda" )}",
+ delete_tag_img: "${h.url_for('/static/images/delete_tag_icon_gray.png')}",
+ delete_tag_img_rollover: "${h.url_for('/static/images/delete_tag_icon_white.png')}",
+ add_tag_img: "${h.url_for('/static/images/add_icon.png')}",
+ add_tag_img_rollover: "${h.url_for('/static/images/add_icon_dark.png')}",
+ };
+% if trans.get_user() is not None:
+ $("#dataset-tag-area").autocomplete_tagging(options);
+ });
+% endif
+ </script>
+</%def>
<%def name="datatype( dataset, datatypes )">
<select name="datatype">
@@ -38,7 +82,18 @@
<input type="text" name="info" value="${data.info}" size="40"/>
</div>
<div style="clear: both"></div>
- </div>
+ </div>
+ %if trans.get_user() is not None:
+ <div class="form-row">
+ <label>
+ Tags:
+ </label>
+ <div id="dataset-tag-area"
+ style="float: left; margin-left: 1px; width: 295px; margin-right: 10px; border-style: inset; border-color: #ddd; border-width: 1px">
+ </div>
+ <div style="clear: both"></div>
+ </div>
+ %endif
%for name, spec in data.metadata.spec.items():
%if spec.visible:
<div class="form-row">
1
0
29 Aug '09
details: http://www.bx.psu.edu/hg/galaxy/rev/817c183aa633
changeset: 2646:817c183aa633
user: jeremy goecks <jeremy.goecks(a)emory.edu>
date: Fri Aug 28 15:38:46 2009 -0400
description:
add autocomplete_tagging.css.tmpl to templates list
1 file(s) affected in this change:
static/june_2007_style/make_style.py
diffs (13 lines):
diff -r 6f43113ab087 -r 817c183aa633 static/june_2007_style/make_style.py
--- a/static/june_2007_style/make_style.py Fri Aug 28 15:36:41 2009 -0400
+++ b/static/june_2007_style/make_style.py Fri Aug 28 15:38:46 2009 -0400
@@ -27,7 +27,8 @@
( "history.css.tmpl", "history.css" ),
( "tool_menu.css.tmpl", "tool_menu.css" ),
( "iphone.css.tmpl", "iphone.css" ),
- ( "reset.css.tmpl", "reset.css" ) ]
+ ( "reset.css.tmpl", "reset.css" ),
+ ( "autocomplete_tagging.css.tmpl", "autocomplete_tagging.css") ]
images = [
( "./gradient.py 9 30 $panel_header_bg_top - $panel_header_bg_bottom 0 0 $panel_header_bg_bottom 1 1", "panel_header_bg.png" ),
1
0
details: http://www.bx.psu.edu/hg/galaxy/rev/6f43113ab087
changeset: 2645:6f43113ab087
user: jeremy goecks <jeremy.goecks(a)emory.edu>
date: Fri Aug 28 15:36:41 2009 -0400
description:
changes to the model to support tags
1 file(s) affected in this change:
lib/galaxy/model/mapping.py
diffs (94 lines):
diff -r b6b4d07ad087 -r 6f43113ab087 lib/galaxy/model/mapping.py
--- a/lib/galaxy/model/mapping.py Fri Aug 28 15:35:27 2009 -0400
+++ b/lib/galaxy/model/mapping.py Fri Aug 28 15:36:41 2009 -0400
@@ -544,6 +544,34 @@
Column( "content", TEXT )
)
+Tag.table = Table( "tag", metadata,
+ Column( "id", Integer, primary_key=True ),
+ Column( "type", Integer ),
+ Column( "parent_id", Integer, ForeignKey( "tag.id" ) ),
+ Column( "name", TrimmedString(255) ),
+ UniqueConstraint( "name" ) )
+
+HistoryTagAssociation.table = Table( "history_tag_association", metadata,
+ Column( "history_id", Integer, ForeignKey( "history.id" ), index=True ),
+ Column( "tag_id", Integer, ForeignKey( "tag.id" ), index=True ),
+ Column( "user_tname", TrimmedString(255), index=True),
+ Column( "value", TrimmedString(255), index=True),
+ Column( "user_value", TrimmedString(255), index=True) )
+
+DatasetTagAssociation.table = Table( "dataset_tag_association", metadata,
+ Column( "dataset_id", Integer, ForeignKey( "dataset.id" ), index=True ),
+ Column( "tag_id", Integer, ForeignKey( "tag.id" ), index=True ),
+ Column( "user_tname", TrimmedString(255), index=True),
+ Column( "value", TrimmedString(255), index=True),
+ Column( "user_value", TrimmedString(255), index=True) )
+
+HistoryDatasetAssociationTagAssociation.table = Table( "history_dataset_association_tag_association", metadata,
+ Column( "history_dataset_association_id", Integer, ForeignKey( "history_dataset_association.id" ), index=True ),
+ Column( "tag_id", Integer, ForeignKey( "tag.id" ), index=True ),
+ Column( "user_tname", TrimmedString(255), index=True),
+ Column( "value", TrimmedString(255), index=True),
+ Column( "user_value", TrimmedString(255), index=True) )
+
# With the tables defined we can define the mappers and setup the
# relationships between the model objects.
@@ -643,7 +671,8 @@
backref=backref( "parent", primaryjoin=( HistoryDatasetAssociation.table.c.parent_id == HistoryDatasetAssociation.table.c.id ), remote_side=[HistoryDatasetAssociation.table.c.id], uselist=False ) ),
visible_children=relation(
HistoryDatasetAssociation,
- primaryjoin=( ( HistoryDatasetAssociation.table.c.parent_id == HistoryDatasetAssociation.table.c.id ) & ( HistoryDatasetAssociation.table.c.visible == True ) ) )
+ primaryjoin=( ( HistoryDatasetAssociation.table.c.parent_id == HistoryDatasetAssociation.table.c.id ) & ( HistoryDatasetAssociation.table.c.visible == True ) ) ),
+ tags=relation(HistoryDatasetAssociationTagAssociation, backref='history_tag_associations')
) )
assign_mapper( context, Dataset, Dataset.table,
@@ -659,7 +688,8 @@
primaryjoin=( Dataset.table.c.id == LibraryDatasetDatasetAssociation.table.c.dataset_id ) ),
active_library_associations=relation(
LibraryDatasetDatasetAssociation,
- primaryjoin=( ( Dataset.table.c.id == LibraryDatasetDatasetAssociation.table.c.dataset_id ) & ( LibraryDatasetDatasetAssociation.table.c.deleted == False ) ) )
+ primaryjoin=( ( Dataset.table.c.id == LibraryDatasetDatasetAssociation.table.c.dataset_id ) & ( LibraryDatasetDatasetAssociation.table.c.deleted == False ) ) ),
+ tags=relation(DatasetTagAssociation, backref='datasets')
) )
assign_mapper( context, HistoryDatasetAssociationDisplayAtAuthorization, HistoryDatasetAssociationDisplayAtAuthorization.table,
@@ -678,7 +708,8 @@
assign_mapper( context, History, History.table,
properties=dict( galaxy_sessions=relation( GalaxySessionToHistoryAssociation ),
datasets=relation( HistoryDatasetAssociation, backref="history", order_by=asc(HistoryDatasetAssociation.table.c.hid) ),
- active_datasets=relation( HistoryDatasetAssociation, primaryjoin=( ( HistoryDatasetAssociation.table.c.history_id == History.table.c.id ) & ( not_( HistoryDatasetAssociation.table.c.deleted ) ) ), order_by=asc( HistoryDatasetAssociation.table.c.hid ), viewonly=True )
+ active_datasets=relation( HistoryDatasetAssociation, primaryjoin=( ( HistoryDatasetAssociation.table.c.history_id == History.table.c.id ) & ( not_( HistoryDatasetAssociation.table.c.deleted ) ) ), order_by=asc( HistoryDatasetAssociation.table.c.hid ), viewonly=True ),
+ tags=relation(HistoryTagAssociation, backref="histories")
) )
assign_mapper( context, HistoryUserShareAssociation, HistoryUserShareAssociation.table,
@@ -938,6 +969,25 @@
lazy=False )
) )
+assign_mapper( context, Tag, Tag.table,
+ properties=dict( children=relation(Tag, backref=backref( 'parent', remote_side=[Tag.table.c.id] ) )
+ ) )
+
+assign_mapper( context, HistoryTagAssociation, HistoryTagAssociation.table,
+ properties=dict( tag=relation(Tag, backref="tagged_histories") ),
+ primary_key=[HistoryTagAssociation.table.c.history_id, HistoryTagAssociation.table.c.tag_id]
+ )
+
+assign_mapper( context, DatasetTagAssociation, DatasetTagAssociation.table,
+ properties=dict( tag=relation(Tag, backref="tagged_datasets") ),
+ primary_key=[DatasetTagAssociation.table.c.dataset_id, DatasetTagAssociation.table.c.tag_id]
+ )
+
+assign_mapper( context, HistoryDatasetAssociationTagAssociation, HistoryDatasetAssociationTagAssociation.table,
+ properties=dict( tag=relation(Tag, backref="tagged_history_dataset_associations") ),
+ primary_key=[HistoryDatasetAssociationTagAssociation.table.c.history_dataset_association_id, HistoryDatasetAssociationTagAssociation.table.c.tag_id]
+ )
+
def db_next_hid( self ):
"""
Override __next_hid to generate from the database in a concurrency
1
0
details: http://www.bx.psu.edu/hg/galaxy/rev/77dfb7834a94
changeset: 2647:77dfb7834a94
user: jeremy goecks <jeremy.goecks(a)emory.edu>
date: Fri Aug 28 15:40:32 2009 -0400
description:
add tagging to histories
1 file(s) affected in this change:
templates/root/history.mako
diffs (118 lines):
diff -r 817c183aa633 -r 77dfb7834a94 templates/root/history.mako
--- a/templates/root/history.mako Fri Aug 28 15:38:46 2009 -0400
+++ b/templates/root/history.mako Fri Aug 28 15:40:32 2009 -0400
@@ -14,8 +14,8 @@
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Pragma" content="no-cache">
-${h.css( "base", "history" )}
-${h.js( "jquery", "json2", "jquery.jstore-all" )}
+${h.css( "base", "history", "autocomplete_tagging" )}
+${h.js( "jquery", "json2", "jquery.jstore-all", "jquery.autocomplete", "autocomplete_tagging" )}
<script type="text/javascript">
$(function() {
@@ -83,6 +83,93 @@
%endif
%endfor
});
+
+ //
+ // Set up autocomplete tagger.
+ //
+<%
+ ## Build string of tag name, values.
+ tag_names_and_values = list()
+ for tag in history.tags:
+ tag_name = tag.user_tname
+ tag_value = ""
+ if tag.value is not None:
+ tag_value = tag.user_value
+ tag_names_and_values.append("\"" + tag_name + "\" : \"" + tag_value + "\"")
+%>
+ //
+ // Returns the number of keys (elements) in an array/dictionary.
+ //
+ var array_length = function(an_array)
+ {
+ if (an_array.length)
+ return an_array.length;
+
+ var count = 0;
+ for (element in an_array)
+ count++;
+ return count;
+ };
+
+ //
+ // Function get text to display on the toggle link.
+ //
+ var get_toggle_link_text = function(tags)
+ {
+ var text = "";
+ var num_tags = array_length(tags);
+ if (num_tags != 0)
+ {
+ text = num_tags + (num_tags != 1 ? " Tags" : " Tag");
+ /*
+ // Show first N tags; hide the rest.
+ var max_to_show = 1;
+
+ // Build tag string.
+ var tag_strs = new Array();
+ var count = 0;
+ for (tag_name in tags)
+ {
+ tag_value = tags[tag_name];
+ tag_strs[tag_strs.length] = build_tag_str(tag_name, tag_value);
+ if (++count == max_to_show)
+ break;
+ }
+ tag_str = tag_strs.join(", ");
+
+ // Finalize text.
+ var num_tags_hiding = num_tags - max_to_show;
+ text = "Tags: " + tag_str +
+ (num_tags_hiding != 0 ? " and " + num_tags_hiding + " more" : "");
+ */
+ }
+ else
+ {
+ // No tags.
+ text = "Add tags to this history";
+ }
+ return text;
+ };
+
+ var options =
+ {
+ tags : {${", ".join(tag_names_and_values)}},
+ get_toggle_link_text_fn: get_toggle_link_text,
+ input_size: 15,
+ tag_click_fn: function(tag) { /* Do nothing. */ },
+ <% encoded_history_id = trans.security.encode_id(history.id) %>
+ ajax_autocomplete_tag_url: "${h.url_for( controller='tag', action='tag_autocomplete_data', id=encoded_history_id, item_type="history" )}",
+ ajax_add_tag_url: "${h.url_for( controller='tag', action='add_tag_async', id=encoded_history_id, item_type="history" )}",
+ ajax_delete_tag_url: "${h.url_for( controller='tag', action='remove_tag_async', id=encoded_history_id, item_type="history" )}",
+ delete_tag_img: "${h.url_for('/static/images/delete_tag_icon_gray.png')}",
+ delete_tag_img_rollover: "${h.url_for('/static/images/delete_tag_icon_white.png')}",
+ add_tag_img: "${h.url_for('/static/images/add_icon.png')}",
+ add_tag_img_rollover: "${h.url_for('/static/images/add_icon_dark.png')}",
+ };
+% if trans.get_user() is not None:
+ $("#history-tag-area").autocomplete_tagging(options);
+% endif
+
});
// Functionized so AJAX'd datasets can call them
// Get shown/hidden state from cookie
@@ -290,6 +377,9 @@
<p></p>
%endif
+<div id="history-tag-area" style="margin-bottom: 1em">
+</div>
+
<%namespace file="history_common.mako" import="render_dataset" />
%if not datasets:
1
0
29 Aug '09
details: http://www.bx.psu.edu/hg/galaxy/rev/36f438ce1f82
changeset: 2639:36f438ce1f82
user: Kelly Vincent <kpvincent(a)bx.psu.edu>
date: Fri Aug 28 15:59:16 2009 -0400
description:
Added samtools-based tools (sam_to_bam, sam_merge, sam_pileup) with their supporting files and modified Bam datatype so temp files are properly cleaned up
15 file(s) affected in this change:
lib/galaxy/datatypes/images.py
test-data/chrM.fa
test-data/sam_to_bam_in1.sam
test-data/sam_to_bam_in2.sam
test-data/sam_to_bam_out1.bam
test-data/sam_to_bam_out2.bam
tool-data/sam_fa_indices.loc.sample
tool_conf.xml.sample
tools/samtools/sam_merge.py
tools/samtools/sam_merge.xml
tools/samtools/sam_merge_code.py
tools/samtools/sam_pileup.py
tools/samtools/sam_pileup.xml
tools/samtools/sam_to_bam.py
tools/samtools/sam_to_bam.xml
diffs (843 lines):
diff -r d261f41a2a03 -r 36f438ce1f82 lib/galaxy/datatypes/images.py
--- a/lib/galaxy/datatypes/images.py Fri Aug 28 15:29:53 2009 -0400
+++ b/lib/galaxy/datatypes/images.py Fri Aug 28 15:59:16 2009 -0400
@@ -252,14 +252,17 @@
index_file = dataset.metadata.spec['bam_index'].param.new_file( dataset = dataset )
tmp_dir = tempfile.gettempdir()
tmpf1 = tempfile.NamedTemporaryFile(dir=tmp_dir)
+ tmpf1bai = '%s.bai' % tmpf1.name
try:
subprocess.check_call(['cd', tmp_dir], shell=True)
subprocess.check_call('cp %s %s' % (dataset.file_name, tmpf1.name), shell=True)
subprocess.check_call('samtools index %s' % tmpf1.name, shell=True)
- subprocess.check_call('cp %s.bai %s' % (tmpf1.name, index_file.file_name), shell=True)
+ subprocess.check_call('cp %s %s' % (tmpf1bai, index_file.file_name), shell=True)
except subprocess.CalledProcessError:
sys.stderr.write('There was a problem creating the index for the BAM file\n')
tmpf1.close()
+ if os.path.exists(tmpf1bai):
+ os.remove(tmpf1bai)
dataset.metadata.bam_index = index_file
def set_peek( self, dataset ):
if not dataset.dataset.purged:
diff -r d261f41a2a03 -r 36f438ce1f82 test-data/chrM.fa
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/chrM.fa Fri Aug 28 15:59:16 2009 -0400
@@ -0,0 +1,335 @@
+>chrM
+GTTAATGTAGCTTAATAATATAAAGCAAGGCACTGAAAATGCCTAGATGA
+GTATTCTTACTCCATAAACACATAGGCTTGGTCCTAGCCTTTTTATTAGT
+TATTAATAGAATTACACATGCAAGTATCCGCACCCCAGTGAGAATGCCCT
+CTAAATCACGTCTCTACGATTAAAAGGAGCAGGTATCAAGCACACTAGAA
+AGTAGCTCATAACACCTTGCTCAGCCACACCCCCACGGGACACAGCAGTG
+ATAAAAATTAAGCTATGAACGAAAGTTCGACTAAGTCATATTAAATAAGG
+GTTGGTAAATTTCGTGCCAGCCACCGCGGTCATACGATTAACCCAAATTA
+ATAAATCTCCGGCGTAAAGCGTGTCAAAGACTAATACCAAAATAAAGTTA
+AAACCCAGTTAAGCCGTAAAAAGCTACAACCAAAGTAAAATAGACTACGA
+AAGTGACTTTAATACCTCTGACTACACGATAGCTAAGACCCAAACTGGGA
+TTAGATACCCCACTATGCTTAGCCCTAAACTAAAATAGCTTACCACAACA
+AAGCTATTCGCCAGAGTACTACTAGCAACAGCCTAAAACTCAAAGGACTT
+GGCGGTGCTTTACATCCCTCTAGAGGAGCCTGTTCCATAATCGATAAACC
+CCGATAAACCCCACCATCCCTTGCTAATTCAGCCTATATACCGCCATCTT
+CAGCAAACCCTAAACAAGGTACCGAAGTAAGCACAAATATCCAACATAAA
+AACGTTAGGTCAAGGTGTAGCCCATGGGATGGAGAGAAATGGGCTACATT
+TTCTACCCTAAGAACAAGAACTTTAACCCGGACGAAAGTCTCCATGAAAC
+TGGAGACTAAAGGAGGATTTAGCAGTAAATTAAGAATAGAGAGCTTAATT
+GAATCAGGCCATGAAGCGCGCACACACCGCCCGTCACCCTCCTTAAATAT
+CACAAATCATAACATAACATAAAACCGTGACCCAAACATATGAAAGGAGA
+CAAGTCGTAACAAGGTAAGTATACCGGAAGGTGTACTTGGATAACCAAAG
+TGTAGCTTAAACAAAGCATCCAGCTTACACCTAGAAGATTTCACTCAAAA
+TGAACACTTTGAACTAAAGCTAGCCCAAACAATACCTAATTCAATTACCC
+TTAGTCACTTAACTAAAACATTCACCAAACCATTAAAGTATAGGAGATAG
+AAATTTTAACTTGGCGCTATAGAGAAAGTACCGTAAGGGAACGATGAAAG
+ATGCATTAAAAGTACTAAACAGCAAAGCTTACCCCTTTTACCTTTTGCAT
+AATGATTTAACTAGAATAAACTTAGCAAAGAGAACTTAAGCTAAGCACCC
+CGAAACCAGACGAGCTACCTATGAACAGTTACAAATGAACCAACTCATCT
+ATGTCGCAAAATAGTGAGAAGATTCGTAGGTAGAGGTGAAAAGCCCAACG
+AGCCTGGTGATAGCTGGTTGTCCAGAAACAGAATTTCAGTTCAAATTTAA
+ATTTACCTAAAAACTACTCAATTCTAATGTAAATTTAAATTATAGTCTAA
+AAAGGTACAGCTTTTTAGATACAGGTTACAACCTTCATTAGAGAGTAAGA
+ACAAGATAAACCCATAGTTGGCTTAAAAGCAGCCATCAATTAAGAAAGCG
+TTCAAGCTCAACGACACATCTATCTTAATCCCAACAATCAACCCAAACTA
+ACTCCTAATCTCATACTGGACTATTCTATCAACACATAGAAGCAATAATG
+TTAATATGAGTAACAAGAATTATTTCTCCTTGCATAAGCTTATATCAGAA
+CGAATACTCACTGATAGTTAACAACAAGATAGGGATAATCCAAAAACTAA
+TCATCTATTTAAACCATTGTTAACCCAACACAGGCATGCATCTATAAGGA
+AAGATTAAAAGAAGTAAAAGGAACTCGGCAAACACAAACCCCGCCTGTTT
+ACCAAAAACATCACCTCTAGCATTTCCAGTATTAGAGGCACTGCCTGCCC
+AGTGACATCTGTTtaaacggccgcggtatcctaaccgtgcaaaggtagca
+taatcacttgttccctaaatagggacttgtatgaatggccacacgagggt
+tttactgtctcttacttccaatcagtgaaattgaccttcccgtgaagagg
+cgggaatgactaaataagacgagaagaccctatggagcttTAATTAACTG
+ATTCACAAAAAACAACACACAAACCTTAACCTTCAGGGACAACAAAACTT
+TTGATTGAATCAGCAATTTCGGTTGGGGTGACCTCGGAGAACAAAACAAC
+CTCCGAGTGATTTAAATCCAGACTAACCAGTCAAAATATATAATCACTTA
+TTGATCCAAACCATTGATCAACGGAACAAGTTACCCTAGGGATAACAGCG
+CAATCCTATTCCAGAGTCCATATCGACAATTAGGGTTTACGACCTCGATG
+TTGGATCAAGACATCCTAATGGTGCAACCGCTATTAAGGGTTCGTTTGTT
+CAACGATTAAAGTCTTACGTGATCTGAGTTCAGACCGGAGTAATCCAGGT
+CGGTTTCTATCTATTCTATACTTTTCCCAGTACGAAAGGACAAGAAAAGT
+AGGGCCCACTTTACAAGAAGCGCCCTCAAACTAATAGATGACATAATCTA
+AATCTAACTAATTTATAACTTCTACCGCCCTAGAACAGGGCTCgttaggg
+tggcagagcccggaaattgcataaaacttaaacctttacactcagaggtt
+caactcctctccctaacaacaTGTTCATAATTAACGTCCTCCTCCTAATT
+GTCCCAATCTTGCTCGCCGTAGCATTCCTCACACTAGTTGAACGAAAAGT
+CTTAGGCTATATGCAACTTCGCAAAGGACCCAACATCGTAGGCCCCTATG
+GCCTACTACAACCTATTGCCGATGCCCTCAAACTATTTATCAAAGAGCCA
+CTACAACCACTAACATCATCGACATCCATATTCATCATCGCACCAATCCT
+AGCCCTAACCCTGGCCTTAACCATATGAATCCCTCTGCCCATACCATACC
+CACTAATCAACATAAACCTAGGAATTCTATTCATACTAGCCATGTCCAGC
+CTAGCTGTCTACTCAATCCTTTGATCAGGATGGGCCTCAAACTCAAAATA
+CGCCCTAATTGGAGCTCTACGAGCAGTAGCACAAACCATCTCATACGAAG
+TAACTCTAGCAATCATCCTACTCTCAGTCCTCCTAATAAGCGGATCATTC
+ACATTATCAACACTTATTATTACCCAAGAATACCTCTGATTAATCTTCCC
+ATCATGACCCTTAGCCATAATGTGATTCATCTCAACATTAGCCGAAACCA
+ACCGAGCTCCATTTGACCTAACAGAAGGAGAATCAGAACTCGTCTCTGGA
+TTCAACGTTGAATACGCAGCCGGCCCATTTGCTCTATTCTTCCTAGCAGA
+ATACGCAAACATCATCATGATAAACATCTTCACAACAACCCTATTTCTAG
+GAGCATTTCACAACCCCTACCTGCCAGAACTCTACTCAATTAATTTCACC
+ATTAAAGCTCTCCTTCTAACATGTTCCTTCCTATGAATCCGAGCATCCTA
+CCCACGATTCCGATATGACCAACTTATACACCTCCTATGAAAGAACTTCC
+TACCACTCACACTAGCCCTCTGCATATGACACGTCTCACTTCCAATCATA
+CTATCCAGCATCCCACCACAAACATAGGAAATATGTCTGACAAAAGAGTT
+ACTTTGATAGAGTAAAACATAGAGGCTCAAACCCTCTTATTTctagaact
+acaggaattgaacctgctcctgagaattcaaaatcctccgtgctaccgaa
+ttacaccatgtcctaCAAGTAAGGTCAGCTAAATAAGCTATCGGGCCCAT
+ACCCCGAAAATGTTGGATTACACCCTTCCCGTACTAATAAATCCCCTTAT
+CTTCACAACTATTCTAATAACAGTTCTTCTAGGAACTATAATCGTTATAA
+TAAGCTCACACTGACTAATAATCTGAATCGGATTTGAAATAAATCTACTA
+GCCATTATCCCTATCCTAATAAAAAAGTACAATCCCCGAACCATAGAAGC
+CTCCACCAAATATTTTCTAACCCAAGCCACCGCATCAATACTCCTCATAA
+TAGCGATCATCATTAACCTCATACACTCAGGCCAATGAACAATCACAAAA
+GTCTTCAACCCCACAGCGTCCATCATTATAACTTCAGCTCTCGCCATAAA
+ACTTGGACTCACACCATTCCACTTCTGAGTACCCGAAGTCACACAGGGCA
+TCTCATTAACATCAGGTCTCATCCTACTTACATGACAAAAACTAGCCCCA
+ATATCAATCCTATATCAAATCTCACCCTCAATTAACCTAAATATCTTATT
+AACTATAGCCGTACTGTCAATCCTAGTAGGAGGCTGAGGCGGTCTCAACC
+AAACCCAACTACGAAAAATCATAGCATACTCGTCAATCGCGCATATAGGA
+TGAATAACAGCTGTCCTAGTATATAACCCAACACTAACAATACTAAACAT
+ATTAATTTACATTATAATAACACTCACAATATTCATACTATTTATCCACA
+GCTCCTCTACTACAACACTATCACTCTCCCACACATGAAACAAAATACCT
+CTAACCACTACACTAATCTTAATTACCTTACTATCCATAGGAGGCCTCCC
+CCCACTATCAGGATTCATACCCAAATGAATAATCATTCAAGAGCTCACCA
+AAAATAGCAGCATCATCCTCCCCACACTAATAGCCATTATAGCACTACTC
+AACCTCTACTTCTACATACGACTAACCTATTCCACCTCACTGACCATATT
+CCCATCCACAAACAACATAAAAATAAAATGACAATTCGAAACCAAACGAA
+TTACTCTCTTACCCCCGTTAATTGTTATATCCTCCCTACTCCTCCCCCTA
+ACCCCCATACTATCAATTTTGGACTAGGAATTTAGGTTAACATCCCAGAC
+CAAGAGCCTTCAAAGCTCTAAGCAAGTGAATCCACTTAATTCCTGCATAC
+TAAGGACTGCGAGACTCTATCTCACATCAATTGAACGCAAATCAAACTCT
+TTTATTAAGCTAAGCCCTTACTAGATTGGTGGGCTACCATCCCACGAAAT
+TTTAGTTAACAGCTAAATACCCTAATCAACTGGCTTCAATCTACTTCTCC
+CGCCGCCTAGAAAAAAAGGCGGGAGAAGCCCCGGCAGAAATTGAAGCTGC
+TCCTTTGAATTTGCAATTCAATGTGAAAATTCACCACGGGACTTGATAAG
+AAGAGGATTCCAACCCCTGTCTTTAGATTTACAGTCTAATGCTTACTCAG
+CCATCTTACCTATGTTCATCAACCGCTGACTATTTTCAACTAACCACAAA
+GACATCGGCACTCTGTACCTCCTATTCGGCGCTTGAGCTGGAATAGTAGG
+AACTGCCCTAAGCCTCCTAATCCGTGCTGAATTAGGCCAACCTGGGACCC
+TACTAGGAGATGATCAGATCTACAATGTCATTGTAACCGCCCATGCATTC
+GTAATAATTTTCTTTATGGTCATACCCATTATAATCGGAGGATTCGGAAA
+CTGATTAGTCCCCCTGATAATTGGAGCACCTGATATAGCTTTCCCCCGAA
+TAAACAACATAAGCTTCTGATTACTTCCCCCATCATTCCTACTTCTTCTC
+GCTTCCTCAATAATTGAAGCAGGTGCCGGAACAGGCTGAACCGTATATCC
+TCCTCTAGCTGGAAATCTGGCGCATGCAGGAGCCTCTGTTGACTTAACCA
+TTTTCTCTCTCCACCTAGCTGGGGTGTCCTCGATTTTAGGTGCCATCAAC
+TTTATTACCACAATCATTAACATAAAACCACCAGCCCTATCCCAATATCA
+AACCCCCCTATTCGTTTGATCTGTCCTTATTACGGCAGTACTCCTTCTCC
+TAGCCCTCCCGGTCCTAGCAGCAGGCATTACCATGCTTCTCACAGACCGT
+AACCTGAACACTACTTTCTTCGACCCCGCAGGAGGAGGGGATCCAATCCT
+TTATCAACACCTATTCTGATTCTTCGGACACCCCGAAGTCTATATTCTTA
+TCCTACCAGGCTTCGGTATAATCTCACACATCGTCACATACTACTCAGGT
+AAAAAGGAACCTTTTGGCTACATGGGTATAGTGTGAGCTATAATATCCAT
+TGGCTTTCTAGGCTTCATCGTATGGGCTCACCACATGTTTACAGTAGGGA
+TAGACGTTGACACACGAGCATACTTCACATCAGCTACCATAATCATCGCT
+ATCCCTACTGGTGTAAAAGTATTCAGCTGACTAGCCACCCTGCACGGAGG
+AAATATCAAATGATCTCCAGCTATACTCTGAGCTCTAGGCTTCATCTTCT
+TATTCACAGTAGGAGGTCTAACAGGAATCGTCCTAGCTAACTCATCCCTA
+GATATTGTTCTCCACGATACTTATTATGTAGTAGCACATTTCCATTATGT
+CCTGTCTATAGGAGCAGTCTTCGCCATTATGGGGGGATTTGTACACTGAT
+TCCCTCTATTCTCAGGATACACACTCAACCAAACCTGAGCAAAAATCCAC
+TTTACAATTATATTCGTAGGGGTAAATATAACCTTCTTCCCACAACATTT
+CCTTGGCCTCTCAGGAATGCCACGACGCTATTCTGATTATCCAGACGCAT
+ATACAACATGAAATACCATCTCATCCATAGGATCTTTTATCTCACTTACA
+GCAGTGATACTAATAATTTTCATAATTTGAGAAGCGTTCGCATCCAAACG
+AGAAGTGTCTACAGTAGAATTAACCTCAACTAATCTGGAATGACTACACG
+GATGCCCCCCACCATACCACACATTTGAAGAACCCACCTACGTAAACCTA
+AAAtaagaaaggaaggaatcgaaccccctctaactggtttcaagccaata
+tcataaccactatgtctttctcCATCAATTGAGGTATTAGTAAAAATTAC
+ATGACTTTGTCAAAGTTAAATTATAGGTTAAACCCCTATATACCTCTATG
+GCCTACCCCTTCCAACTAGGATTCCAAGACGCAACATCCCCTATTATAGA
+AGAACTCCTACACTTCCACGACCACACACTAATAATCGTATTCCTAATTA
+GCTCTCTAGTATTATATATTATCTCATCAATACTAACAACTAAATTAACC
+CATACCAGCACCATAGATGCTCAAGAAGTAGAGACAATTTGAACGATTTT
+ACCAGCCATCATCCTTATTCTAATCGCCCTCCCATCCCTACGAATTCTAT
+ATATAATAGATGAAATCAATAATCCGTCCCTCACAGTCAAAACAATAGGC
+CACCAATGATACTGAAGCTACGAGTATACCGATTACGAAGACTTGACCTT
+TGACTCCTACATGATCCCCACATCAGACCTAAAACCAGGAGAATTACGTC
+TTCTAGAAGTCGACAATCGAGTGGTTCTCCCCATAGAAATAACCATCCGA
+ATGCTAATTTCATCCGAAGACGTCCTACACTCATGAGCTGTGCCCTCCCT
+AGGCCTAAAAACAGACGCTATCCCTGGGCGCCTAAATCAGACAACTCTCG
+TGGCCTCTCGACCAGGACTTTACTACGGTCAATGCTCAGAGATCTGCGGA
+TCAAACCACAGCTTTATACCAATTGTCCTTGAACTAGTTCCACTGAAACA
+CTTCGAAGAATGATCTGCATCAATATTATAAAGTCACTAAGAAGCTATTA
+TAGCATTAACCTTTTAAGTTAAAGATTGAGGGTTCAACCCCCTCCCTAGT
+GATATGCCACAGTTGGATACATCAACATGATTTATTAATATCGTCTCAAT
+AATCCTAACTCTATTTATTGTATTTCAACTAAAAATCTCAAAGCACTCCT
+ATCCGACACACCCAGAAGTAAAGACAACCAAAATAACAAAACACTCTGCC
+CCTTGAGAATCAAAATGAACGAAAATCTATTCGCCTCTTTCGCTACCCCA
+ACAATAGTAGGCCTCCCTATTGTAATTCTGATCATCATATTTCCCAGCAT
+CCTATTCCCCTCACCCAACCGACTAATCAACAATCGCCTAATCTCAATTC
+AACAATGGCTAGTCCAACTTACATCAAAACAAATAATAGCTATCCATAAC
+AGCAAAGGACAAACCTGAACTCTTATACTCATATCACTGATCCTATTCAT
+TGGCTCAACAAACTTATTAGGCCTACTACCTCACTCATTTACACCAACAA
+CACAACTATCAATAAACCTAGGCATAGCTATTCCCCTATGGGCAGGGACA
+GTATTCATAGGCTTTCGTCACAAAACAAAAGCAGCCCTAGCCCACTTTCT
+ACCTCAAGGGACGCCCATTTTCCTCATCCCCATACTAGTAATTATCGAGA
+CTATCAGCCTATTTATTCAACCTGTAGCCCTAGCCGTGCGGCTAACCGCT
+AACATTACCGCCGGACACCTCCTAATACACCTCATCGGAGGGGCAACACT
+AGCCCTCATAAGCATCAGCCCCTCAACAGCCCTTATTACGTTTATCATCC
+TAATTCTACTAACTATCCTCGAATTCGCAGTAGCTATAATCCAAGCCTAC
+GTATTCACTCTCCTGGTAAGCCTTTACTTACACGACAACACCTAATGACC
+CACCAAACCCACGCTTACCACATAGTAAACCCCAGCCCATGACCACTTAC
+AGGAGCCCTATCAGCCCTCCTGATAACATCAGGACTAGCCATGTGATTTC
+ACTTTAACTCAACCTTACTTCTAGCTATAGGGCTATTAACTAACATCCTT
+ACCATATATCAATGATGACGAGACATCATCCGAGAAAGCACATTCCAAGG
+CCATCACACATCAATCGTTCAAAAGGGACTCCGATATGGCATAATCCTTT
+TTATTATCTCAGAAGTCTTCTTCTTCTCTGGCTTCTTCTGAGCCTTTTAC
+CACTCAAGCCTAGCCCCCACACCCGAACTAGGCGGCTGCTGACCACCCAC
+AGGTATCCACCCCTTAAACCCCCTAGAAGTCCCCTTACTCAACACCTCAG
+TGCTCCTAGCATCTGGAGTCTCTATCACCTGAGCCCACCATAGCCTAATA
+GAAGGAAACCGTAAAAATATGCTCCAAGGCCTATTCATCACAATTTCACT
+AGGCGTATACTTCACCCTTCTCCAAGCCTCAGAATACTATGAAGCCTCAT
+TTACTATTTCAGATGGAGTATACGGATCAACATTTTTCGTAGCAACAGGG
+TTCCACGGACTACACGTAATTATCGGATCTACCTTCCTCATTGTATGTTT
+CCTACGCCAACTAAAATTCCACTTTACATCCAGCCACCACTTCGGATTCG
+AAGCAGCCGCTTGATACTGACACTTCGTCGACGTAGTCTGACTATTCTTG
+TACGTCTCTATTTATTGATGAGGATCCTATTCTTTTAGTATTGACCAGTA
+CAATTGACTTCCAATCAATCAGCTTCGGTATAACCCGAAAAAGAATAATA
+AACCTCATACTGACACTCCTCACTAACACATTACTAGCCTCGCTACTCGT
+ACTCATCGCATTCTGACTACCACAACTAAACATCTATGCAGAAAAAACCA
+GCCCATATGAATGCGGATTTGACCCTATAGGGTCAGCACGCCTCCCCTTC
+TCAATAAAATTTTTCTTAGTGGCCATTACATTTCTGCTATTCGACTTAGA
+AATTGCCCTCCTATTACCCCTTCCATGAGCATCCCAAACAACTAACCTAA
+ACACTATACTTATCATAGCACTAGTCCTAATCTCTCTTCTAGCCATCAGC
+CTAGCCTACGAATGAACCCAAAAAGGACTAGAATGAACTGAGTATGGTAA
+TTAGTTTAAACCAAAACAAATGATTTCGACTCATTAAACTATGATTAACT
+TCATAATTACCAACATGTCACTAGTCCATATTAATATCTTCCTAGCATTC
+ACAGTATCCCTCGTAGGCCTACTAATGTACCGATCCCACCTAATATCCTC
+ACTCCTATGCCTAGAAGGAATAATACTATCACTATTCGTCATAGCAACCA
+TAATAGTCCTAAACACCCACTTCACACTAGCTAGTATAATACCTATCATC
+TTACTAGTATTTGCTGCCTGCGAACGAGCTCTAGGATTATCCCTACTAGT
+CATAGTCTCCAATACTTATGGAGTAGACCACGTACAAAACCTTAACCTCC
+TCCAATGCTAAAAATTATCATTCCCACAATCATACTTATGCCCCTTACAT
+GACTATCAAAAAAGAATATAATCTGAATCAACACTACAACCTATAGTCTA
+TTAATCAGCCTTATCAGCCTATCCCTCCTAAACCAACCTAGCAACAATAG
+CCTAAACTTCTCACTAATATTCTTCTCCGATCCCCTATCAGCCCCACTTC
+TGGTGTTGACAACATGACTACTGCCACTAATACTCATAGCCAGCCAACAC
+CATCTATCTAAGGAACCACTAATCCGAAAAAAACTCTACATCACCATGCT
+AACCATACTTCAAACTTTCCTAATCATGACTTTTACCGCCACAGAACTAA
+TCTCCTTCTACATCCTATTTGAAGCCACATTAGTTCCAACACTAATTATC
+ATCACCCGCTGAGGCAACCAAACAGAACGCCTGAACGCAGGCCTCTACTT
+CCTATTCTACACACTAATAGGTTCCCTCCCACTCTTAGTTGCACTAATCT
+CTATCCAAAACCTAACAGGCTCACTAAACTTCCTATTAATTCAATACTGA
+AACCAAGCACTACCCGACTCTTGATCCAATATTTTCCTATGACTAGCATG
+TATAATAGCATTCATAGTCAAAATACCGGTATATGGTCTTCACCTCTGAC
+TCCCAAAAGCCCATGTAGAAGCCCCAATTGCCGGATCCATAGTGCTAGCA
+GCCATTCTACTAAAACTAGGAGGCTACGGAATACTACGAATTACAACAAT
+ACTAAACCCCCAAACTAGCTTTATAGCCTACCCCTTCCTCATACTATCCC
+TGTGAGGAATAATCATAACTAGTTCCATCTGCTTGCGACAAACCGATCTA
+AAATCACTTATTGCATACTCCTCTGTCAGCCACATAGCCCTAGTAATCGT
+AGCCGTCCTCATCCAAACACCATGAAGTTATATAGGAGCTACAGCCCTAA
+TAATCGCTCACGGCCTTACATCATCAATACTATTCTGCCTGGCAAACTCA
+AATTACGAACGTACCCATAGCCGAACTATAATCCTAGCCCGCGGGCTTCA
+AACACTTCTTCCCCTTATAGCAGCCTGATGACTATTAGCCAGCCTAACCA
+ACCTGGCCCTCCCTCCCAGCATTAACCTAATTGGAGAGCTATTCGTAGTA
+ATATCATCATTCTCATGATCAAATATTACCATTATCCTAATAGGAGCCAA
+TATCACCATCACCGCCCTCTACTCCCTATACATACTAATCACAACACAAC
+GAGGGAAATACACACACCATATCAACAGCATTAAACCTTCATTTACACGA
+GAAAACGCACTCATGGCCCTCCACATGACTCCCCTACTACTCCTATCACT
+TAACCCTAAAATTATCCTAGGCTTTACGTACTGTAAATATAGTTTAACAA
+AAACACTAGATTGTGGATCTAGAAACAGAAACTTAATATTTCTTATTTAC
+CGAGAAAGTATGCAAGAACTGCTAATTCATGCCCCCATGTCCAACAAACA
+TGGCTCTCTCAAACTTTTAAAGGATAGGAGCTATCCGTTGGTCTTAGGAA
+CCAAAAAATTGGTGCAACTCCAAATAAAAGTAATCAACATGTTCTCCTCC
+CTCATACTAGTTTCACTATTAGTACTAACCCTCCCAATCATATTATCAAT
+CTTCAATACCTACAAAAACAGCACGTTCCCGCATCATGTAAAAAACACTA
+TCTCATATGCCTTCATTACTAGCCTAATTCCCACTATAATATTTATTCAC
+TCTGGACAAGAAACAATTATCTCAAACTGACACTGAATAACCATACAAAC
+CCTCAAACTATCCCTAAGCTTCAAACTAGATTACTTCTCAATAATTTTCG
+TACCAGTAGCCCTATTCGTAACATGATCTATTATGGAATTCTCCCTATGA
+TACATGCACTCAGATCCTTACATTACTCGATTTTTTAAATACTTACTTAC
+ATTCCTCATCACTATAATAATTCTAGTCACAGCTAACAACCTTTTCCAAC
+TGTTCATCGGATGGGAGGGAGTAGGCATCATGTCATTCTTACTAATCGGA
+TGATGATACGGCCGAACAGATGCCAACACCGCGGCCCTTCAAGCAATCCT
+TTATAACCGCATCGGGGATATCGGCTTCATCATGGCCATAGCCTGATTCC
+TATTCAACACCAACACATGAGACCTCCAACAAATCTTCATACTCGACCCC
+AACCTTACCAACCTCCCGCTCCTAGGCCTCCTCCTAGCCGCAACTGGCAA
+ATCCGCTCAATTTGGACTCCACCCATGACTTCCTTCAGCCATAGAGGGCC
+CTACACCAGTCTCAGCCCTACTCCACTCCAGCACAATAGTTGTAGCAGGC
+GTCTTCCTGCTAATCCGCTTCCATCCACTAATAGAAAACAACAAAACAAT
+CCAGTCACTTACCCTATGCCTAGGAGCCATCACCACACTATTCACAGCAA
+TCTGCGCACTCACTCAAAACGATATCAAAAAAATCATTGCTTTCTCCACC
+TCCAGCCAACTAGGCCTGATAATCGTAACCATCGGTATCAATCAACCCTA
+CCTAGCATTCCTCCACATTTGCACTCACGCATTCTTCAAAGCTATACTAT
+TTATATGTTCCGGATCCATTATCCACAGCCTAAATGACGAGCAAGATATC
+CGAAAAATAGGCGGACTATTTAATGCAATACCCTTCACCACCACATCTCT
+AATTATTGGCAGCCTTGCACTCACCGGAATTCCTTTCCTCACAGGCTTCT
+ACTCCAAAGACCTCATCATCGAAACCGCCAACACATCGTACACCAACGCC
+TGAGCCCTACTAATAACTCTCATTGCCACATCCCTCACAGCTGTCTACAG
+TACCCGAATCATCTTCTTTGCACTCCTAGGGCAACCCCGCTTCCTCCCTC
+TGACCTCAATCAACGAAAATAACCCCTTTCTAATTAACTCCATCAAACGC
+CTCTTAATTGGCAGCATTTTTGCCGGATTCTTCATCTCCAACAATATCTA
+CCCCACAACCGTCCCAGAAATAACCATACCTACTTACATAAAACTCACCG
+CCCTCGCAGTAACCATCCTAGGATTTACACTAGCCCTAGAACTAAGCTTG
+ATAACCCATAACTTAAAACTAGAACACTCCACCAACGTATTCAAATTCTC
+CAACCTCCTAGGATACTACCCAACAATTATACACCGACTCCCACCGCTCG
+CTAACCTATCAATAAGCCAAAAATCAGCATCACTTCTACTAGACTCAATC
+TGACTAGAAAACATCCTGCCAAAATCTATCTCCCAGTTCCAAATAAAAAC
+CTCGATCCTAATTTCCACCCAAAAAGGACAAATCAAATTATATTTCCTCT
+CATTCCTCATCACCCTTACCCTAAGCATACTACTTTTTAATCTCCACGAG
+TAACCTCTAAAATTACCAAGACCCCAACAAGCAACGATCAACCAGTCACA
+ATCACAACCCAAGCCCCATAACTATACAATGCAGCAGCCCCTATAATTTC
+CTCACTAAACGCCCCAGAATCTCCAGTATCATAAATAGCTCAAGCCCCCA
+CACCACTAAACTTAAACACTACCCCCACTTCCTCACTCTTCAGAACATAT
+AAAACCAACATAACCTCCATCAACAACCCTAAAAGAAATACCCCCATAAC
+AGTCGTATTAGACACCCATACCTCAGGATACTGCTCAGTAGCCATAGCCG
+TTGTATAACCAAAAACAACCAACATTCCTCCCAAATAAATCAAAAACACC
+ATCAACCCCAAAAAGGACCCTCCAAAATTCATAATAATACCACAACCTAC
+CCCTCCACTTACAATCAGCACTAAACCCCCATAAATAGGTGAAGGTTTTG
+AAGAAAACCCCACAAAACTAACAACAAAAATAACACTCAAAATAAACACA
+ATATATGTCATCATTATTCCCACGTGGAATCTAACCACGACCAATGACAT
+GAAAAATCATCGTTGTATTTCAACTATAAGAACACCAATGACAAACATCC
+GGAAATCTCACCCACTAATTAAAATCATCAATCACTCTTTTATTGACCTA
+CCAGCCCCCTCAAACATTTCATCATGATGAAACTTCGGCTCCCTCCTAGG
+AATCTGCCTAATCCTCCAAATCTTAACAGGCCTATTCCTAGCCATACACT
+ACACATCAGACACGACAACTGCCTTCTCATCCGTCACTCACATCTGCCGA
+GACGTTAACTACGGATGAATTATTCGCTACCTCCATGCCAACGGAGCATC
+AATATTTTTTATCTGCCTCTTCATTCACGTAGGACGCGGCCTCTACTACG
+GCTCTTACACATTCCTAGAGACATGAAACATTGGAATCATCCTACTTTTC
+ACAGTTATAGCTACAGCATTCATGGGCTATGTCCTACCATGAGGCCAAAT
+ATCCTTTTGAGGAGCAACAGTCATCACGAACCTCCTATCAGCAATTCCCT
+ACATCGGTACTACCCTCGTCGAGTGAATCTGAGGTGGATTCTCAGTAGAC
+AAAGCCACCCTTACCCGATTTTTTGCTTTCCACTTCATCCTACCCTTCAT
+CATCACAGCCCTGGTAGTCGTACATTTACTATTTCTTCACGAAACAGGAT
+CTAATAACCCCTCAGGAATCCCATCCGATATGGACAAAATCCCATTCCAC
+CCATATTATACAATTAAAGACATCCTAGGACTCCTCCTCCTGATCTTGCT
+CCTACTAACTCTAGTATTATTCTCCCCCGACCTCCTAGGAGACCCAGACA
+ACTACACCCCAGCTAACCCTCTCAGCACTCCCCCTCATATTAAACCAGAA
+TGGTACTTCCTGTTTGCCTACGCCATCCTACGCTCCATTCCCAACAAACT
+AGGCGGCGTATTAGCCCTAATCCTCTCCATCCTGATCCTAGCACTCATCC
+CCACCCTCCACATATCAAAACAACGAAGCATAATATTCCGGCCTCTCAGC
+CAATGCGTATTCTGACTCTTAGTGGCAGACTTACTGACACTAACATGAAT
+CGGCGGACAGCCAGTGGAACACCCATACGTAATTATCGGCCAACTGGCCT
+CAATCCTCTACTTCTCCCTAATTCTCATTTTTATACCACTCGCAAGCACC
+ATCGAAAACAATCTTCTAAAATGAAGAGTCCCTGTAGTATATCGCACATT
+ACCCTGGTCTTGTAAACCAGAAAAGGGGGAAAACGTTTCCTCCCAAGGAC
+TATCAAGGAAGAAGCTCTAGCTCCACCATCAACACCCAAAGCTGAAATTC
+TACTTAAACTATTCCTTGATTTCTTCCCCTAAACGACAACAATTTACCCT
+CATGTGCTATGTCAGTATCAGATTATACCCCCACATAACACCATACCCAC
+CTGACATGCAATATCTTATGAATGGCCTATGTACGTCGTGCATTAAATTG
+TCTGCCCCATGAATAATAAGCATGTACATAATATCATTTATCTTACATAA
+GTACATTATATTATTGATCGTGCATACCCCATCCAAGTCAAATCATTTCC
+AGTCAACACGCATATCACAGCCCATGTTCCACGAGCTTAATCACCAAGCC
+GCGGGAAATCAGCAACCCTCCCAACTACGTGTCCCAATCCTCGCTCCGGG
+CCCATCCAAACGTGGGGGTTTCTACAATGAAACTATACCTGGCATCTGGT
+TCTTTCTTCAGGGCCATTCCCACCCAACCTCGCCCATTCTTTCCCCTTAA
+ATAAGACATCTCGATGGACTAATGACTAATCAGCCCATGCTCACACATAA
+CTGTGATTTCATGCATTTGGTATCTTTTTATATTTGGGGATGCTATGACT
+CAGCTATGGCCGTCAAAGGCCTCGACGCAGTCAATTAAATTGAAGCTGGA
+CTTAAATTGAACGTTATTCCTCCGCATCAGCAACCATAAGGTGTTATTCA
+GTCCATGGTAGCGGGACATAGGAAACAAgtgcacctgtgcacctgtgcac
+ctgtgcacctgtgcacctgtgcacctgtgcacctgtgcacctgtgcacct
+gtgcacctgtgcacctgtgcacctgtgcacctgtgcacctgtgcacctgt
+gcacctgtgcacctgtgcacctgtgcacctgtgcacctgtgcacctgtgc
+acctgtgcacctgtgcacctgtgcacctgtgcacctgtgcacctgtgcac
+ctgtgcacctACCCGCGCAGTAAGCAAGTAATATAGCTTTCTTAATCAAA
+CCCCCCCTACCCCCCATTAAACTCCACATATGTACATTCAACACAATCTT
+GCCAAACCCCAAAAACAAGACTAAACAATGCACAATACTTCATGAAGCTT
+AACCCTCGCATGCCAACCATAATAACTCAACACACCTAACAATCTTAACA
+GAACTTTCCCCCCGCCATTAATACCAACATGCTACTTTAATCAATAAAAT
+TTCCATAGACAGGCATCCCCCTAGATCTAATTTTCTAAATCTGTCAACCC
+TTCTTCCCCC
diff -r d261f41a2a03 -r 36f438ce1f82 test-data/sam_to_bam_in1.sam
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/sam_to_bam_in1.sam Fri Aug 28 15:59:16 2009 -0400
@@ -0,0 +1,10 @@
+HWI-EAS91_1_30788AAXX:1:1:1513:715 16 chrM 9563 25 36M * 0 0 CTGACTACCACAACTAAACATCTATGCNNAAAAAAC I+-II?IDIIIIIIIIIIIIIIIIIII""IIIIIII NM:i:1 X1:i:1 MD:Z:7N0N27
+HWI-EAS91_1_30788AAXX:1:1:1698:516 16 chrM 2735 25 36M * 0 0 TTTACACTCAGAGGTTCAACTCCTCTCNNTAACAAC I9IIIII5IIIIIIIIIIIIIIIIIII""IIIIIII NM:i:1 X1:i:1 MD:Z:7N0N27
+HWI-EAS91_1_30788AAXX:1:1:1491:637 16 chrM 10864 25 36M * 0 0 TGTAGAAGCCCCAATTGCCGGATCCATNNTGCTAGC DBAIIIIIIIIIIIFIIIIIIIIIIII""IIIIIII NM:i:1 X1:i:1 MD:Z:7N0N27
+HWI-EAS91_1_30788AAXX:1:1:1711:249 16 chrM 10617 25 36M * 0 0 ACCAAACAGAACGCCTGAACGCAGGCCNNTACTTCC IIIIIIIIIIIIIIIIIIIIIIIIIII""IIIIIII NM:i:1 X1:i:1 MD:Z:7N0N27
+HWI-EAS91_1_30788AAXX:1:1:1634:211 0 chrM 9350 25 36M * 0 0 GAAGCAGNNGCTTGATACTGACACTTCGTCGACGTA IIIIIII""IIIIIIIIIIIIIIIIIIIIII9IIDF NM:i:1 X1:i:1 MD:Z:7N0N27
+HWI-EAS91_1_30788AAXX:1:1:1218:141 16 chrM 14062 25 36M * 0 0 ACAAAACTAACAACAAAAATAACACTCNNAATAAAC I+IIII1IIIIIIIIIIIIIIIIIIII""IIIIIII NM:i:1 X1:i:1 MD:Z:7N0N27
+HWI-EAS91_1_30788AAXX:1:1:1398:854 16 chrM 3921 25 36M * 0 0 CACCCTTCCCGTACTAATAAATCCCCTNNTCTTCAC IIIII=AIIIIIIIIIIIIIIBIIIII""IIIIIII NM:i:1 X1:i:1 MD:Z:7N0N27
+HWI-EAS91_1_30788AAXX:1:1:1310:991 16 chrM 10002 25 36M * 0 0 CTCCTATGCCTAGAAGGAATAATACTANNACTATTC I:2IEI:IIDIIIIII4IIIIIIIIII""IIIIIII NM:i:1 X1:i:1 MD:Z:7N0N27
+HWI-EAS91_1_30788AAXX:1:1:1716:413 0 chrM 6040 25 36M * 0 0 GATCCAANNCTTTATCAACACCTATTCTGATTCTTC IIIIIII""IIIIIIIIIIIIIIIIIIIIIIIIIII NM:i:1 X1:i:1 MD:Z:7N0N27
+HWI-EAS91_1_30788AAXX:1:1:1630:59 16 chrM 12387 25 36M * 0 0 TCATACTCGACCCCAACCTTACCAACCNNCCGCTCC FIIHII;IIIIIIIIIIIIIIIIIIII""IIIIIII NM:i:1 X1:i:1 MD:Z:7N0N27
diff -r d261f41a2a03 -r 36f438ce1f82 test-data/sam_to_bam_in2.sam
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test-data/sam_to_bam_in2.sam Fri Aug 28 15:59:16 2009 -0400
@@ -0,0 +1,10 @@
+HWI-EAS91_1_30788AAXX:1:1:1095:605 0 chrM 23 25 36M * 0 0 AAGCAAGNNACTGAAAATGCCTAGATGAGTATTCTT IIIIIII""IIIIIIIIIIIIIIIEIIIIIIIIIII NM:i:1 X1:i:1 MD:Z:7N0N27
+HWI-EAS91_1_30788AAXX:1:1:1650:1185 0 chrM 14956 25 36M * 0 0 ACCCCAGNNAACCCTCTCAGCACTCCCCCTCATATT IIIIIII""IIIIIIIIIIII6IIIIIIIII5I-II NM:i:1 X1:i:1 MD:Z:7N0N27
+HWI-EAS91_1_30788AAXX:1:1:799:192 16 chrM 8421 25 36M * 0 0 CCTGTAGCCCTAGCCGTGCGGCTAACCNNTAACATT II%::I<IIIIIEIII8IIIIIIIIII""IIIIIII NM:i:1 X1:i:1 MD:Z:7N0N27
+HWI-EAS91_1_30788AAXX:1:1:1082:719 16 chrM 7191 25 36M * 0 0 TAAATTAACCCATACCAGCACCATAGANNCTCAAGA <III0EII3+3I29I>III8AIIIIII""IIIIIII NM:i:1 X1:i:1 MD:Z:7N0N27
+HWI-EAS91_1_30788AAXX:1:1:1746:1180 16 chrM 12013 25 36M * 0 0 CCTAAGCTTCAAACTAGATTACTTCTCNNTAATTTT IIIIIIIIFIIIIIIIIIIIIIIIIII""IIIIIII NM:i:1 X1:i:1 MD:Z:7N0N27
+HWI-EAS91_1_30788AAXX:1:1:606:460 0 chrM 4552 25 36M * 0 0 TTAATTTNNATTATAATAACACTCACAATATTCATA IIIIIII""IIIIIIIIIIIIIIIIII?I6IIIII6 NM:i:1 X1:i:1 MD:Z:7N0N27
+HWI-EAS91_1_30788AAXX:1:1:1059:362 16 chrM 7348 25 36M * 0 0 GGCCACCAATGATACTGAAGCTACGAGNNTACCGAT II/<)2IIIIIIIIIIIIIIIIIIIII""IIIIIII NM:i:1 X1:i:1 MD:Z:7N0N27
+HWI-EAS91_1_30788AAXX:1:1:1483:1161 16 chrM 15080 25 36M * 0 0 TCCTGATCCTAGCACTCATCCCCACCCNNCACATAT HIIIIIFIIAIHIIIIIIIIIIIIIII""IIIIIII NM:i:1 X1:i:1 MD:Z:7N0N27
+HWI-EAS91_1_30788AAXX:1:1:1273:600 16 chrM 13855 25 36M * 0 0 GTATTAGACACCCATACCTCAGGATACNNCTCAGTA IIIIIIIIIIIIIIIIIIIIIIIIIII""IIIIIII NM:i:1 X1:i:1 MD:Z:7N0N27
+HWI-EAS91_1_30788AAXX:1:1:1190:1283 16 chrM 15338 25 36M * 0 0 TATATCGCACATTACCCTGGTCTTGTANNCCAGAAA EIII?-IIIIIAIIIIIIIIIIIIIII""IIIIIII NM:i:1 X1:i:1 MD:Z:7N0N27
diff -r d261f41a2a03 -r 36f438ce1f82 test-data/sam_to_bam_out1.bam
Binary file test-data/sam_to_bam_out1.bam has changed
diff -r d261f41a2a03 -r 36f438ce1f82 test-data/sam_to_bam_out2.bam
Binary file test-data/sam_to_bam_out2.bam has changed
diff -r d261f41a2a03 -r 36f438ce1f82 tool-data/sam_fa_indices.loc.sample
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tool-data/sam_fa_indices.loc.sample Fri Aug 28 15:59:16 2009 -0400
@@ -0,0 +1,27 @@
+#This is a sample file distributed with Galaxy that enables tools
+#to use a directory of Samtools indexed sequences data files. You will need
+#to create these data files and then create a sam_fa_indices.loc file
+#similar to this one (store it in this directory ) that points to
+#the directories in which those files are stored. The sam_fa_indices.loc
+#file has this format (white space characters are TAB characters):
+#
+#<index> <seq> <location>
+#
+#So, for example, if you had hg18 indexed stored in
+#/depot/data2/galaxy/sam/,
+#then the sam_fa_indices.loc entry would look like this:
+#
+#hg18 /depot/data2/galaxy/sam/hg18.fa
+#
+#and your /depot/data2/galaxy/sam/ directory
+#would contain hg18.fa and hg18.fa.fai files:
+#
+#-rw-r--r-- 1 james universe 830134 2005-09-13 10:12 hg18.fa
+#-rw-r--r-- 1 james universe 527388 2005-09-13 10:12 hg18.fa.fai
+#
+#Your sam_fa_indices.loc file should include an entry per line for
+#each index set you have stored. The file in the path does actually
+#exist, but it should never be directly used. Instead, the name serves
+#as a prefix for the index file. For example:
+#
+#hg18 /depot/data2/galaxy/sam/hg18.fa
diff -r d261f41a2a03 -r 36f438ce1f82 tool_conf.xml.sample
--- a/tool_conf.xml.sample Fri Aug 28 15:29:53 2009 -0400
+++ b/tool_conf.xml.sample Fri Aug 28 15:59:16 2009 -0400
@@ -331,9 +331,13 @@
<tool file="metag_tools/megablast_xml_parser.xml" />
<tool file="metag_tools/blat_wrapper.xml" />
<tool file="metag_tools/mapping_to_ucsc.xml" />
- <tool file="sr_mapping/bwa_wrapper.xml" />
</section>
<section name="Tracks" id="tracks">
<tool file="visualization/genetrack.xml" />
</section>
+ <section name="SAM Tools" id="samtools">
+ <tool file="samtools/sam_to_bam.xml" />
+ <tool file="samtools/sam_merge.xml" />
+ <tool file="samtools/sam_pileup.xml" />
+ </section>
</toolbox>
diff -r d261f41a2a03 -r 36f438ce1f82 tools/samtools/sam_merge.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/samtools/sam_merge.py Fri Aug 28 15:59:16 2009 -0400
@@ -0,0 +1,21 @@
+#! /usr/bin/python
+
+import os, sys
+
+def stop_err( msg ):
+ sys.stderr.write( msg )
+ sys.exit()
+
+def __main__():
+ infile = sys.argv[1]
+ outfile = sys.argv[2]
+ if len( sys.argv ) < 3:
+ stop_err( 'No files to merge' )
+ filenames = sys.argv[3:]
+ cmd1 = 'samtools merge %s %s %s' % (outfile, infile, ' '.join(filenames))
+ try:
+ os.system(cmd1)
+ except Exception, eq:
+ stop_err('Error running SAMtools merge tool\n' + str(eq))
+
+if __name__ == "__main__" : __main__()
\ No newline at end of file
diff -r d261f41a2a03 -r 36f438ce1f82 tools/samtools/sam_merge.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/samtools/sam_merge.xml Fri Aug 28 15:59:16 2009 -0400
@@ -0,0 +1,32 @@
+<tool id="sam_merge" name="Merge BAM Files" version="1.0.0">
+ <description>merges BAM files together</description>
+ <command interpreter="python">
+ sam_merge.py
+ $input1
+ $output1
+ $input2
+ #for $i in $inputs
+ ${i.input}
+ #end for
+ </command>
+ <inputs>
+ <param name="input1" label="First file" type="data" format="bam" />
+ <param name="input2" label="with file" type="data" format="bam" help="Need to add more files? Use controls below." />
+ <repeat name="inputs" title="Input Files">
+ <param name="input" label="Add file" type="data" format="bam" />
+ </repeat>
+ </inputs>
+ <outputs>
+ <data name="output1" format="bam" />
+ </outputs>
+ <!-- bam files are binary and not sniffable so can't be uploaded without being corrupted, so no tests -->
+ <help>
+
+**What it does**
+
+This tool uses SAMTools_' merge command to merge any number of BAM files together into one BAM file.
+
+.. _SAMTools: http://samtools.sourceforge.net/samtools.shtml
+
+ </help>
+</tool>
diff -r d261f41a2a03 -r 36f438ce1f82 tools/samtools/sam_merge_code.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/samtools/sam_merge_code.py Fri Aug 28 15:59:16 2009 -0400
@@ -0,0 +1,35 @@
+import sets
+from galaxy.tools.parameters import DataToolParameter
+
+def validate_input( trans, error_map, param_values, page_param_map ):
+ dbkeys = sets.Set()
+ data_param_names = sets.Set()
+ data_params = 0
+ for name, param in page_param_map.iteritems():
+ if isinstance( param, DataToolParameter ):
+ # for each dataset parameter
+ if param_values.get(name, None) != None:
+ dbkeys.add( param_values[name].dbkey )
+ data_params += 1
+ # check meta data
+# try:
+# param = param_values[name]
+# startCol = int( param.metadata.startCol )
+# endCol = int( param.metadata.endCol )
+# chromCol = int( param.metadata.chromCol )
+# if param.metadata.strandCol is not None:
+# strandCol = int ( param.metadata.strandCol )
+# else:
+# strandCol = 0
+# except:
+# error_msg = "The attributes of this dataset are not properly set. " + \
+# "Click the pencil icon in the history item to set the chrom, start, end and strand columns."
+# error_map[name] = error_msg
+ data_param_names.add( name )
+ if len( dbkeys ) > 1:
+ for name in data_param_names:
+ error_map[name] = "All datasets must belong to same genomic build, " \
+ "this dataset is linked to build '%s'" % param_values[name].dbkey
+ if data_params != len(data_param_names):
+ for name in data_param_names:
+ error_map[name] = "A dataset of the appropriate type is required"
\ No newline at end of file
diff -r d261f41a2a03 -r 36f438ce1f82 tools/samtools/sam_pileup.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/samtools/sam_pileup.py Fri Aug 28 15:59:16 2009 -0400
@@ -0,0 +1,89 @@
+#! /usr/bin/python
+
+"""
+Creates a pileup file from a bam file and a reference.
+
+usage: %prog [options]
+ -i, --input1=i: bam file
+ -o, --output1=o: Output pileup
+ -r, --ref=r: Reference file type
+ -n, --ownFile=n: User-supplied fasta reference file
+ -d, --dbkey=d: dbkey of user-supplied file
+ -x, --indexDir=x: Index directory
+ -b, --bamIndex=b: BAM index file
+
+usage: %prog input1 output1 ref_type refFile ownFile dbkey index_dir bam_index
+"""
+
+import os, sys, tempfile
+from galaxy import eggs
+import pkg_resources; pkg_resources.require( "bx-python" )
+from bx.cookbook import doc_optparse
+
+def stop_err( msg ):
+ sys.stderr.write( msg )
+ sys.exit()
+
+def check_seq_file( dbkey, GALAXY_DATA_INDEX_DIR ):
+ seq_file = "%s/sam_fa_indices.loc" % GALAXY_DATA_INDEX_DIR
+ seq_path = ''
+ for line in open( seq_file ):
+ line = line.rstrip( '\r\n' )
+ if line and not line.startswith( "#" ) and line.startswith( 'index' ):
+ fields = line.split( '\t' )
+ if len( fields ) < 3:
+ continue
+ if fields[1] == dbkey:
+ seq_path = fields[2].strip()
+ break
+ return seq_path
+
+def __main__():
+ #Parse Command Line
+ options, args = doc_optparse.parse( __doc__ )
+ seq_path = check_seq_file( options.dbkey, options.indexDir )
+ tmp_dir = tempfile.gettempdir()
+ os.chdir(tmp_dir)
+ tmpf0 = tempfile.NamedTemporaryFile(dir=tmp_dir)
+ tmpf0bam = '%s.bam' % tmpf0.name
+ tmpf0bambai = '%s.bam.bai' % tmpf0.name
+ tmpf1 = tempfile.NamedTemporaryFile(dir=tmp_dir)
+ tmpf1fai = '%s.fai' % tmpf1.name
+ cmd1 = None
+ cmd2 = 'cp %s %s; cp %s %s' % (options.input1, tmpf0bam, options.bamIndex, tmpf0bambai)
+ cmd3 = 'samtools pileup -f %s %s > %s 2> /dev/null'
+ if options.ref =='indexed':
+ full_path = "%s.fai" % seq_path
+ if not os.path.exists( full_path ):
+ stop_err( "No sequences are available for '%s', request them by reporting this error." % options.dbkey )
+ cmd3 = cmd3 % (seq_path, tmpf0bam, options.output1)
+ elif options.ref == 'history':
+ cmd1 = 'cp %s %s; cp %s.fai %s' % (options.ownFile, tmpf1.name, options.ownFile, tmpf1fai)
+ cmd3 = cmd3 % (tmpf1.name, tmpf0bam, options.output1)
+ # index reference if necessary
+ if cmd1:
+ try:
+ os.system(cmd1)
+ except Exception, eq:
+ stop_err('Error moving reference sequence\n' + str(eq))
+ # copy bam index to working directory
+ try:
+ os.system(cmd2)
+ except Exception, eq:
+ stop_err('Error moving files to temp directory\n' + str(eq))
+ # perform pileup command
+ try:
+ os.system(cmd3)
+ except Exception, eq:
+ stop_err('Error running SAMtools merge tool\n' + str(eq))
+ # clean up temp files
+ tmpf1.close()
+ tmpf0.close()
+ if os.path.exists(tmpf0bam):
+ os.remove(tmpf0bam)
+ if os.path.exists(tmpf0bambai):
+ os.remove(tmpf0bambai)
+ if os.path.exists(tmpf1fai):
+ os.remove(tmpf0bambai)
+
+if __name__ == "__main__" : __main__()
diff -r d261f41a2a03 -r 36f438ce1f82 tools/samtools/sam_pileup.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/samtools/sam_pileup.xml Fri Aug 28 15:59:16 2009 -0400
@@ -0,0 +1,50 @@
+<tool id="sam_pileup" name="SAM Pileup Format" version="1.0.0">
+ <description>generates the pileup format for a provided BAM file</description>
+ <command interpreter="python">
+ sam_pileup.py
+ --input1=$input1
+ --output=$output1
+ --ref=$refOrHistory.reference
+ #if $refOrHistory.reference == "history":
+ --ownFile=$refOrHistory.ownFile
+ #else:
+ --ownFile="None"
+ #end if
+ --dbkey=${input1.metadata.dbkey}
+ --indexDir=${GALAXY_DATA_INDEX_DIR}
+ --bamIndex=${input1.metadata.bam_index}
+ </command>
+ <inputs>
+ <conditional name="refOrHistory">
+ <param name="reference" type="select" label="Will you select a reference genome from your history or use a built-in index?">
+ <option value="indexed">Use a built-in index</option>
+ <option value="history">Use one from the history</option>
+ </param>
+ <when value="indexed">
+ <param name="input1" type="data" format="bam" label="Select the BAM file to generate the pileup file for">
+ <validator type="unspecified_build" />
+ <validator type="dataset_metadata_in_file" filename="sam_fa_indices.loc" metadata_name="dbkey" metadata_column="1" message="Sequences are not currently available for the specified build." line_startswith="index" />
+ </param>
+ </when>
+ <when value="history">
+ <param name="input1" type="data" format="sam, bam" label="Select the BAM file to generate the pileup file for" />
+ <param name="ownFile" type="data" format="fasta" metadata_name="dbkey" label="Select a reference genome" />
+ </when>
+ </conditional>
+ </inputs>
+ <outputs>
+ <data format="tabular" name="output1" />
+ </outputs>
+ <!-- tests are not possible because bam is a non-sniffable binary format and cannot be uploaded without being corrupted -->
+ <help>
+
+**What it does**
+
+Uses SAMTools_' pileup command to produce a file in the pileup format based on the provided BAM file.
+
+.. _SAMTools: http://samtools.sourceforge.net/samtools.shtml
+
+ </help>
+</tool>
+
+
diff -r d261f41a2a03 -r 36f438ce1f82 tools/samtools/sam_to_bam.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/samtools/sam_to_bam.py Fri Aug 28 15:59:16 2009 -0400
@@ -0,0 +1,85 @@
+#! /usr/bin/python
+
+"""
+Converts SAM data to BAM format.
+
+usage: %prog [options]
+ -i, --input1=i: SAM file to be converted
+ -d, --dbkey=d: dbkey value
+ -r, --ref_file=r: Reference file if choosing from history
+ -o, --output1=o: BAM output
+ -x, --index_dir=x: Index directory
+
+usage: %prog input_file dbkey ref_list output_file
+"""
+
+import os, sys, tempfile
+from galaxy import eggs
+import pkg_resources; pkg_resources.require( "bx-python" )
+from bx.cookbook import doc_optparse
+
+def stop_err( msg ):
+ sys.stderr.write( "%s\n" % msg )
+ sys.exit()
+
+def check_seq_file( dbkey, GALAXY_DATA_INDEX_DIR ):
+ seq_file = "%s/sam_fa_indices.loc" % GALAXY_DATA_INDEX_DIR
+ seq_path = ''
+ for line in open( seq_file ):
+ line = line.rstrip( '\r\n' )
+ if line and not line.startswith( "#" ) and line.startswith( 'index' ):
+ fields = line.split( '\t' )
+ if len( fields ) < 3:
+ continue
+ if fields[1] == dbkey:
+ seq_path = fields[2].strip()
+ break
+ return seq_path
+
+def __main__():
+ #Parse Command Line
+ options, args = doc_optparse.parse( __doc__ )
+ seq_path = check_seq_file( options.dbkey, options.index_dir )
+ tmp_dir = tempfile.gettempdir()
+ os.chdir(tmp_dir)
+ tmpf1 = tempfile.NamedTemporaryFile(dir=tmp_dir)
+ tmpf1fai = '%s.fai' % tmpf1.name
+ tmpf2 = tempfile.NamedTemporaryFile(dir=tmp_dir)
+ tmpf3 = tempfile.NamedTemporaryFile(dir=tmp_dir)
+ tmpf3bam = '%s.bam' % tmpf3.name
+ if options.ref_file == "None":
+ full_path = "%s.fai" % seq_path
+ if not os.path.exists( full_path ):
+ stop_err( "No sequences are available for '%s', request them by reporting this error." % options.dbkey )
+ cmd1 = "cp %s %s; cp %s %s" % (seq_path, tmpf1.name, full_path, tmpf1fai)
+ else:
+ cmd1 = "cp %s %s; samtools faidx %s 2>/dev/null" % (options.ref_file, tmpf1.name, tmpf1.name)
+ cmd2 = "samtools view -bt %s -o %s %s 2>/dev/null" % (tmpf1fai, tmpf2.name, options.input1)
+ cmd3 = "samtools sort %s %s 2>/dev/null" % (tmpf2.name, tmpf3.name)
+ cmd4 = "cp %s %s" % (tmpf3bam, options.output1)
+ # either create index based on fa file or copy provided index to temp directory
+ try:
+ os.system(cmd1)
+ except Exception, eq:
+ stop_err("Error creating the reference list index.\n" + str(eq))
+ # create original bam file
+ try:
+ os.system(cmd2)
+ except Exception, eq:
+ stop_err("Error running view command.\n" + str(eq))
+ # sort original bam file to produce sorted output bam file
+ try:
+ os.system(cmd3)
+ os.system(cmd4)
+ except Exception, eq:
+ stop_err("Error sorting data and creating output file.\n" + str(eq))
+ # cleanup temp files
+ tmpf1.close()
+ tmpf2.close()
+ tmpf3.close()
+ if os.path.exists(tmpf1fai):
+ os.remove(tmpf1fai)
+ if os.path.exists(tmpf3bam):
+ os.remove(tmpf3bam)
+
+if __name__=="__main__": __main__()
diff -r d261f41a2a03 -r 36f438ce1f82 tools/samtools/sam_to_bam.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/samtools/sam_to_bam.xml Fri Aug 28 15:59:16 2009 -0400
@@ -0,0 +1,59 @@
+<tool id="sam_to_bam" name="SAM-to-BAM" version="1.0.0">
+ <description>converts SAM format to BAM format</description>
+ <command interpreter="python">
+ sam_to_bam.py
+ --input1=$source.input1
+ --dbkey=${input1.metadata.dbkey}
+ #if $source.indexSource == "history":
+ --ref_file=$ref_file
+ #else
+ --ref_file="None"
+ #end if
+ --output1=$output1
+ --index_dir=${GALAXY_DATA_INDEX_DIR}
+ </command>
+ <inputs>
+ <conditional name="source">
+ <param name="indexSource" type="select" label="Choose the source for the reference list">
+ <option value="built_in">Built-in</option>
+ <option value="history">History</option>
+ </param>
+ <when value="built_in">
+ <param name="input1" type="data" format="sam" label="SAM File to Convert">
+ <validator type="unspecified_build" />
+ <validator type="dataset_metadata_in_file" filename="sam_fa_indices.loc" metadata_name="dbkey" metadata_column="1" message="Sequences are not currently available for the specified build." line_startswith="index" />
+ </param>
+ </when>
+ <when value="history">
+ <param name="input1" type="data" format="sam" label="SAM File to Convert" />
+ <param name="ref_file" type="data" format="fasta" label="Choose the reference file" />
+ </when>
+ </conditional>
+ </inputs>
+ <outputs>
+ <data name="output1" format="bam"/>
+ </outputs>
+ <tests>
+ <test>
+ <param name="indexSource" value="history" />
+ <param name="input1" value="sam_to_bam_in1.sam" ftype="sam" />
+ <param name="ref_file" value="chrM.fa" ftype="fasta" />
+ <output name="output1" file="sam_to_bam_out1.bam" />
+ </test>
+ <test>
+ <param name="indexSource" value="built_in" />
+ <param name="input1" value="sam_to_bam_in2.sam" ftype="sam" dbkey="chrM" />
+ <param name="ref_file" value="chrM.fa" ftype="fasta" />
+ <output name="output1" file="sam_to_bam_out2.bam" />
+ </test>
+ </tests>
+ <help>
+
+**What it does**
+
+This tool uses the SAMTools_ toolkit to produce a BAM file based on a sorted input SAM file.
+
+.. _SAMTools: http://samtools.sourceforge.net/samtools.shtml
+
+ </help>
+</tool>
1
0
details: http://www.bx.psu.edu/hg/galaxy/rev/b6b4d07ad087
changeset: 2644:b6b4d07ad087
user: jeremy goecks <jeremy.goecks(a)emory.edu>
date: Fri Aug 28 15:35:27 2009 -0400
description:
changes to the model to support tags
1 file(s) affected in this change:
lib/galaxy/model/__init__.py
diffs (41 lines):
diff -r 1835c027763a -r b6b4d07ad087 lib/galaxy/model/__init__.py
--- a/lib/galaxy/model/__init__.py Fri Aug 28 15:31:06 2009 -0400
+++ b/lib/galaxy/model/__init__.py Fri Aug 28 15:35:27 2009 -0400
@@ -1142,6 +1142,37 @@
self.user = None
self.title = None
self.content = None
+
+class Tag ( object ):
+ def __init__( self, id=None, type=None, parent_id=None, name=None ):
+ self.id = id
+ self.type = type
+ self.parent_id = parent_id
+ self.name = name
+
+ def __str__ ( self ):
+ return "Tag(id=%s, type=%s, parent_id=%s, name=%s)" % ( self.id, self.type, self.parent_id, self.name )
+
+class ItemTagAssociation ( object ):
+ def __init__( self, item_id=None, tag_id=None, user_tname=None, value=None ):
+ self.item_id = item_id
+ self.tag_id = tag_id
+ self.user_tname = user_tname
+ self.value = None
+ self.user_value = None
+
+ def __str__ ( self ):
+ return "%s(item_id=%s, item_tag=%s, user_tname=%s, value=%s, user_value=%s)" % (self.__class__.__name__, self.item_id, self.tag_id, self.user_tname, self.value. self.user_value )
+
+
+class HistoryTagAssociation ( ItemTagAssociation ):
+ pass
+
+class DatasetTagAssociation ( ItemTagAssociation ):
+ pass
+
+class HistoryDatasetAssociationTagAssociation ( ItemTagAssociation ):
+ pass
1
0
details: http://www.bx.psu.edu/hg/galaxy/rev/1835c027763a
changeset: 2643:1835c027763a
user: jeremy goecks <jeremy.goecks(a)emory.edu>
date: Fri Aug 28 15:31:06 2009 -0400
description:
JS files for tagging
2 file(s) affected in this change:
static/scripts/autocomplete_tagging.js
static/scripts/jquery.autocomplete.js
diffs (1285 lines):
diff -r 116e79410240 -r 1835c027763a static/scripts/autocomplete_tagging.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/static/scripts/autocomplete_tagging.js Fri Aug 28 15:31:06 2009 -0400
@@ -0,0 +1,453 @@
+/**
+ * JQuery extension for tagging with autocomplete.
+ * @author: Jeremy Goecks
+ * @require: jquery.autocomplete plugin
+ */
+var ac_tag_area_id_gen = 1;
+
+jQuery.fn.autocomplete_tagging = function(options) {
+
+ //
+ // Set up function defaults.
+ //
+ var defaults =
+ {
+ get_toggle_link_text_fn: function(tags)
+ {
+ var text = "";
+ var num_tags = array_length(tags);
+ if (num_tags != 0)
+ text = num_tags + (num_tags != 0 ? " Tags" : " Tag");
+ else
+ // No tags.
+ text = "Add tags";
+ return text;
+ },
+ tag_click_fn : function (tag) { },
+ input_size: 20,
+ in_form: false,
+ tags : {},
+ use_toggle_link: true,
+ item_id: "",
+ add_tag_img: "",
+ add_tag_img_rollover: "",
+ delete_tag_img: "",
+ ajax_autocomplete_tag_url: "",
+ ajax_retag_url: "",
+ ajax_delete_tag_url: "",
+ ajax_add_tag_url: ""
+ };
+
+ //
+ // Extend object.
+ //
+ var settings = jQuery.extend(defaults, options);
+
+ //
+ // Create core elements: tag area and TODO.
+ //
+
+ // Tag area.
+ var area_id = "tag-area-" + (ac_tag_area_id_gen)++;
+ var tag_area = $("<div></div>").attr("id", area_id).addClass("tag-area");
+ this.append(tag_area);
+
+ //
+ // Returns the number of keys (elements) in an array/dictionary.
+ //
+ var array_length = function(an_array)
+ {
+ if (an_array.length)
+ return an_array.length;
+
+ var count = 0;
+ for (element in an_array)
+ count++;
+ return count;
+ };
+
+ //
+ // Function to build toggle link.
+ //
+ var build_toggle_link = function()
+ {
+ var link_text = settings.get_toggle_link_text_fn(settings.tags);
+ var toggle_link = $("<a href='/history/tags'>" + link_text + "</a>").addClass("toggle-link");
+ // Link toggles the display state of the tag area.
+ toggle_link.click( function()
+ {
+ // Take special actions depending on whether toggle is showing or hiding link.
+ var showing_tag_area = (tag_area.css("display") == "none");
+ var after_toggle_fn;
+ if (showing_tag_area)
+ {
+ after_toggle_fn = function()
+ {
+ // If there are no tags, go right to editing mode by generating a
+ // click on the area.
+ var num_tags = array_length(settings.tags);
+ if (num_tags == 0)
+ tag_area.click();
+ };
+ }
+ else // Hiding area.
+ {
+ after_toggle_fn = function()
+ {
+ tag_area.blur();
+ };
+ }
+ tag_area.slideToggle("fast", after_toggle_fn);
+
+ return false;
+ });
+
+ return toggle_link;
+ };
+
+ // Add toggle link.
+ var toggle_link = build_toggle_link();
+ if (settings.use_toggle_link)
+ {
+ this.prepend(toggle_link);
+ }
+
+ //
+ // Function to build other elements.
+ //
+
+ //
+ // Return a string that contains the contents of an associative array. This is
+ // a debugging method.
+ //
+ var assoc_array_to_str = function(an_array)
+ {
+ // Convert associative array to simple array and then join array elements.
+ var array_str_list = new Array();
+ for (key in an_array)
+ array_str_list[array_str_list.length] = key + "-->" + an_array[key];
+
+ return "{" + array_str_list.join(",") + "}"
+ };
+
+ //
+ // Collapse tag name + value into a single string.
+ //
+ var build_tag_str = function(tag_name, tag_value)
+ {
+ return tag_name + ( (tag_value != "" && tag_value) ? ":" + tag_value : "");
+ };
+
+ //
+ // Get tag name and value from a string.
+ //
+ var get_tag_name_and_value = function(tag_str)
+ {
+ return tag_str.split(":");
+ };
+
+ //
+ // Add "add tag" button.
+ //
+ var build_add_tag_button = function(tag_input_field)
+ {
+ var add_tag_button = $("<img src='" + settings.add_tag_img + "' rollover='" + settings.add_tag_img_rollover + "'/>").addClass("add-tag-button");
+
+ add_tag_button.click( function()
+ {
+ // Hide button.
+ $(this).hide();
+
+ // Clicking on button is the same as clicking on the tag area.
+ tag_area.click();
+
+ return false;
+ });
+
+ return add_tag_button;
+ };
+
+ //
+ // Function that builds a tag button.
+ //
+ var build_tag_button = function(tag_str)
+ {
+ // Build "delete tag" image and handler.
+ var delete_img = $("<img src='" + settings.delete_tag_img + "'/>").addClass("delete-tag-img");
+ delete_img.mouseenter( function ()
+ {
+ $(this).attr("src", settings.delete_tag_img_rollover);
+ });
+ delete_img.mouseleave( function ()
+ {
+ $(this).attr("src", settings.delete_tag_img);
+ });
+ delete_img.click( function ()
+ {
+ // Tag button is image's parent.
+ var tag_button = $(this).parent();
+
+ // Get tag name.
+ var tag_name_elt = tag_button.find(".tag-name").eq(0);
+ var tag_str = tag_name_elt.text();
+ var tag_name = get_tag_name_and_value(tag_str)[0];
+
+ // TODO: should remove succeed if tag is not already applied to
+ // history?
+ tag_button.remove();
+
+ // Remove tag from local list for consistency.
+ delete settings.tags[tag_name];
+
+ // Update toggle link text.
+ var new_text = settings.get_toggle_link_text_fn(settings.tags);
+ toggle_link.text(new_text);
+
+ // Delete tag.
+ $.ajax({
+ url: settings.ajax_delete_tag_url,
+ data: { tag_name: tag_name },
+ error: function()
+ {
+ // Failed.
+ alert( "Remove tag failed" );
+ },
+ success: function()
+ {
+ }
+ });
+
+ return true;
+ });
+
+ // Build tag button.
+ var tag_name_elt = $("<span>" + tag_str + "</span>").addClass("tag-name");
+ tag_name_elt.click( function()
+ {
+ settings.tag_click_fn(tag_str);
+ return true;
+ });
+
+ var tag_button = $("<span></span>").addClass("tag-button");
+ tag_button.append(tag_name_elt);
+ tag_button.append(delete_img);
+
+ return tag_button;
+ };
+
+ //
+ // Build input + autocompete for tag.
+ //
+ var build_tag_input = function(tag_text)
+ {
+ // If element is in form, tag input is a textarea; otherwise element is a input type=text.
+ var t;
+ if (settings.in_form)
+ t = $( "<textarea id='history-tag-input' rows='1' cols='" +
+ settings.input_size + "' value='" + tag_text + "'></textarea>" );
+ else // element not in form.
+ t = $( "<input id='history-tag-input' type='text' size='" +
+ settings.input_size + "' value='" + tag_text + "'></input>" );
+ t.keyup( function( e )
+ {
+ if ( e.keyCode == 27 )
+ {
+ // Escape key
+ $(this).trigger( "blur" );
+ } else if (
+ ( e.keyCode == 13 ) || // Return Key
+ ( e.keyCode == 188 ) || // Comma
+ ( e.keyCode == 32 ) // Space
+ )
+ {
+ //
+ // Check input.
+ //
+
+ new_value = this.value;
+
+ // Do nothing if return key was used to autocomplete.
+ if (return_key_pressed_for_autocomplete == true)
+ {
+ return_key_pressed_for_autocomplete = false;
+ return false;
+ }
+
+ // Suppress space after a ":"
+ if ( new_value.indexOf(": ", new_value.length - 2) != -1)
+ {
+ this.value = new_value.substring(0, new_value.length-1);
+ return false;
+ }
+
+ // Remove trigger keys from input.
+ if ( (e.keyCode == 188) || (e.keyCode == 32) )
+ new_value = new_value.substring( 0 , new_value.length - 1 );
+
+ // Trim whitespace.
+ new_value = new_value.replace(/^\s+|\s+$/g,"");
+
+ // Too short?
+ if (new_value.length < 3)
+ return false;
+
+ //
+ // New tag OK - apply it.
+ //
+
+ this.value = "";
+
+ // Add button for tag after all other tag buttons.
+ var new_tag_button = build_tag_button(new_value);
+ var tag_buttons = tag_area.children(".tag-button");
+ if (tag_buttons.length != 0)
+ {
+ var last_tag_button = tag_buttons.slice(tag_buttons.length-1);
+ last_tag_button.after(new_tag_button);
+ }
+ else
+ tag_area.prepend(new_tag_button);
+
+ // Add tag to internal list.
+ var tag_name_and_value = new_value.split(":");
+ settings.tags[tag_name_and_value[0]] = tag_name_and_value[1];
+
+ // Update toggle link text.
+ var new_text = settings.get_toggle_link_text_fn(settings.tags);
+ toggle_link.text(new_text);
+
+ // Commit tag to server.
+ var $this = $(this);
+ $.ajax({
+ url: settings.ajax_add_tag_url,
+ data: { new_tag: new_value },
+ error: function()
+ {
+ // Remove tag and show alert.
+ new_tag_button.remove();
+ var new_text = settings.get_toggle_link_text_fn(settings.tags);
+ toggle_link.text(new_text);
+ alert( "Add tag failed" );
+ },
+ success: function()
+ {
+ // Flush autocomplete cache because it's not out of date.
+ // TODO: in the future, we could remove the particular item
+ // that was chosen from the cache rather than flush it.
+ $this.flushCache();
+ }
+ });
+
+ return false;
+ }
+ });
+
+ // Add autocomplete to input.
+ var format_item_func = function(key, row_position, num_rows, value, search_term) {
+ tag_name_and_value = value.split(":");
+ return (tag_name_and_value.length == 1 ? tag_name_and_value[0] :tag_name_and_value[1]);
+ //var array = new Array(key, value, row_position, num_rows,
+ //search_term ); return "\"" + array.join("*") + "\"";
+ }
+ var autocomplete_options =
+ { selectFirst: false, formatItem : format_item_func, autoFill: false, highlight: false };
+
+ t.autocomplete(settings.ajax_autocomplete_tag_url, autocomplete_options);
+
+ t.addClass("tag-input");
+
+ return t;
+ };
+
+ //
+ // Build tag area.
+ //
+
+ // Add tag buttons for each current tag to the tag area.
+ for (tag_name in settings.tags)
+ {
+ var tag_value = settings.tags[tag_name];
+ var tag_str = build_tag_str(tag_name, tag_value);
+ var tag_button = build_tag_button(tag_str, toggle_link, settings.tags);
+ tag_area.append(tag_button);
+ }
+
+ // Add tag input field and "add tag" button.
+ var tag_input_field = build_tag_input("");
+ var add_tag_button = build_add_tag_button(tag_input_field);
+
+ // When the tag area blurs, go to "view tag" mode.
+ tag_area.blur( function(e)
+ {
+ add_tag_button.show();
+ tag_input_field.hide();
+ tag_area.removeClass("active-tag-area");
+ });
+
+ tag_area.append(add_tag_button);
+ tag_area.append(tag_input_field);
+ tag_input_field.hide();
+
+ // On click, enable user to add tags.
+ tag_area.click( function(e)
+ {
+ var is_active = $(this).hasClass("active-tag-area");
+
+ // If a "delete image" object was pressed and area is inactive, do nothing.
+ if ($(e.target).hasClass("delete-tag-img") && !is_active)
+ return false;
+
+ // If a "tag name" object was pressed and area is inactive, do nothing.
+ if ($(e.target).hasClass("tag-name") && !is_active)
+ return false;
+
+ // Hide add tag button, show tag_input field. Change background to show
+ // area is active.
+ $(this).addClass("active-tag-area");
+ add_tag_button.hide();
+ tag_input_field.show();
+ tag_input_field.focus();
+
+ // Add handler to document that will call blur when the tag area is blurred;
+ // a tag area is blurred when a user clicks on an element outside the area.
+ var handle_document_click = function(e)
+ {
+ var tag_area_id = tag_area.attr("id");
+ // Blur the tag area if the element clicked on is not in the tag area.
+ if (
+ ($(e.target).attr("id") != tag_area_id) &&
+ ($(e.target).parents().filter(tag_area_id).length == 0)
+ )
+ {
+ tag_area.blur();
+ $(document).unbind("click", handle_document_click);
+ }
+ };
+ // TODO: we should attach the click handler to all frames in order to capture
+ // clicks outside the frame that this element is in.
+ //window.parent.document.onclick = handle_document_click;
+ //var temp = $(window.parent.document.body).contents().find("iframe").html();
+ //alert(temp);
+ //$(document).parent().click(handle_document_click);
+ $(window).click(handle_document_click);
+
+ return false;
+ });
+
+ // If using toggle link, hide the tag area. Otherwise, if there are no tags,
+ // hide the "add tags" button and show the input field.
+ if (settings.use_toggle_link)
+ tag_area.hide();
+ else
+ {
+ var num_tags = array_length(settings.tags);
+ if (num_tags == 0)
+ {
+ add_tag_button.hide();
+ tag_input_field.show();
+ }
+ }
+
+
+ return this.addClass("tag-element");
+}
diff -r 116e79410240 -r 1835c027763a static/scripts/jquery.autocomplete.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/static/scripts/jquery.autocomplete.js Fri Aug 28 15:31:06 2009 -0400
@@ -0,0 +1,824 @@
+/*
+ * Autocomplete - jQuery plugin 1.0.2
+ *
+ * Copyright (c) 2007 Dylan Verheul, Dan G. Switzer, Anjesh Tuladhar, Jörn Zaefferer
+ *
+ * Dual licensed under the MIT and GPL licenses:
+ * http://www.opensource.org/licenses/mit-license.php
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * Revision: $Id: jquery.autocomplete.js 5747 2008-06-25 18:30:55Z joern.zaefferer $
+ *
+ */
+
+String.prototype.endsWith = function(str) {return (this.match(str+"$")==str)}
+
+
+var return_key_pressed_for_autocomplete = false;
+
+;(function($) {
+
+$.fn.extend({
+ autocomplete: function(urlOrData, options) {
+ var isUrl = typeof urlOrData == "string";
+ options = $.extend({}, $.Autocompleter.defaults, {
+ url: isUrl ? urlOrData : null,
+ data: isUrl ? null : urlOrData,
+ delay: isUrl ? $.Autocompleter.defaults.delay : 10,
+ max: options && !options.scroll ? 10 : 150
+ }, options);
+
+ // if highlight is set to false, replace it with a do-nothing function
+ options.highlight = options.highlight || function(value) { return value; };
+
+ // if the formatMatch option is not specified, then use formatItem for backwards compatibility
+ options.formatMatch = options.formatMatch || options.formatItem;
+
+ return this.each(function() {
+ new $.Autocompleter(this, options);
+ });
+ },
+ result: function(handler) {
+ return this.bind("result", handler);
+ },
+ search: function(handler) {
+ return this.trigger("search", [handler]);
+ },
+ flushCache: function() {
+ return this.trigger("flushCache");
+ },
+ setOptions: function(options){
+ return this.trigger("setOptions", [options]);
+ },
+ unautocomplete: function() {
+ return this.trigger("unautocomplete");
+ }
+});
+
+$.Autocompleter = function(input, options) {
+
+ var KEY = {
+ UP: 38,
+ DOWN: 40,
+ DEL: 46,
+ TAB: 9,
+ RETURN: 13,
+ ESC: 27,
+ COMMA: 188,
+ PAGEUP: 33,
+ PAGEDOWN: 34,
+ BACKSPACE: 8,
+ COLON: 16
+ };
+
+ // Create $ object for input element
+ var $input = $(input).attr("autocomplete", "off").addClass(options.inputClass);
+
+ var timeout;
+ var previousValue = "";
+ var cache = $.Autocompleter.Cache(options);
+ var hasFocus = 0;
+ var lastKeyPressCode;
+ var config = {
+ mouseDownOnSelect: false
+ };
+ var select = $.Autocompleter.Select(options, input, selectCurrent, config);
+
+ var blockSubmit;
+
+ // prevent form submit in opera when selecting with return key
+ $.browser.opera && $(input.form).bind("submit.autocomplete", function() {
+ if (blockSubmit) {
+ blockSubmit = false;
+ return false;
+ }
+ });
+
+ // only opera doesn't trigger keydown multiple times while pressed, others don't work with keypress at all
+ $input.bind(($.browser.opera ? "keypress" : "keydown") + ".autocomplete", function(event) {
+ // track last key pressed
+ lastKeyPressCode = event.keyCode;
+ switch(event.keyCode) {
+
+ case KEY.UP:
+ event.preventDefault();
+ if ( select.visible() ) {
+ select.prev();
+ } else {
+ onChange(0, true);
+ }
+ break;
+
+ case KEY.DOWN:
+ event.preventDefault();
+ if ( select.visible() ) {
+ select.next();
+ } else {
+ onChange(0, true);
+ }
+ break;
+
+ case KEY.PAGEUP:
+ event.preventDefault();
+ if ( select.visible() ) {
+ select.pageUp();
+ } else {
+ onChange(0, true);
+ }
+ break;
+
+ case KEY.PAGEDOWN:
+ event.preventDefault();
+ if ( select.visible() ) {
+ select.pageDown();
+ } else {
+ onChange(0, true);
+ }
+ break;
+
+ // matches also semicolon
+ case options.multiple && $.trim(options.multipleSeparator) == "," && KEY.COMMA:
+ case KEY.TAB:
+ case KEY.RETURN:
+ if (event.keyCode == KEY.RETURN)
+ return_key_pressed_for_autocomplete = false;
+ if( selectCurrent() ) {
+ // stop default to prevent a form submit, Opera needs special handling
+ event.preventDefault();
+ blockSubmit = true;
+
+ // JG: set flag to indicate that a selection just occurred using the return key. FYI:
+ // event.stopPropagation() does not work.
+ if (event.keyCode == KEY.RETURN)
+ return_key_pressed_for_autocomplete = true;
+
+ return false;
+ }
+
+ case KEY.ESC:
+ select.hide();
+ break;
+ case KEY.COLON:
+ break;
+
+ default:
+ clearTimeout(timeout);
+ timeout = setTimeout(onChange, options.delay);
+ break;
+ }
+ }).focus(function(){
+ // track whether the field has focus, we shouldn't process any
+ // results if the field no longer has focus
+ hasFocus++;
+ }).blur(function() {
+ hasFocus = 0;
+ if (!config.mouseDownOnSelect) {
+ // JG: if blur and user is not selecting with mouse, hide
+ // object.
+ select.hide();
+ }
+ return this;
+ }).click(function() {
+ // show select when clicking in a focused field
+ if ( hasFocus++ > 1 && !select.visible() ) {
+ onChange(0, true);
+ }
+ return this;
+ }).bind("search", function() {
+ // TODO why not just specifying both arguments?
+ var fn = (arguments.length > 1) ? arguments[1] : null;
+ function findValueCallback(q, data) {
+ var result;
+ if( data && data.length ) {
+ for (var i=0; i < data.length; i++) {
+ if( data[i].result.toLowerCase() == q.toLowerCase() ) {
+ result = data[i];
+ break;
+ }
+ }
+ }
+ if( typeof fn == "function" ) fn(result);
+ else $input.trigger("result", result && [result.data, result.value]);
+ }
+ $.each(trimWords($input.val()), function(i, value) {
+ request(value, findValueCallback, findValueCallback);
+ });
+
+ return this;
+ }).bind("flushCache", function() {
+ cache.flush();
+ }).bind("setOptions", function() {
+ $.extend(options, arguments[1]);
+ // if we've updated the data, repopulate
+ if ( "data" in arguments[1] )
+ cache.populate();
+ }).bind("unautocomplete", function() {
+ select.unbind();
+ $input.unbind();
+ $(input.form).unbind(".autocomplete");
+ });
+
+
+ function selectCurrent() {
+ var selected = select.selected();
+ if( !selected )
+ return false;
+
+ var v = selected.result;
+ previousValue = v;
+
+ if ( options.multiple ) {
+ var words = trimWords($input.val());
+ if ( words.length > 1 ) {
+ v = words.slice(0, words.length - 1).join( options.multipleSeparator ) + options.multipleSeparator + v;
+ }
+ v += options.multipleSeparator;
+ }
+
+ $input.val(v);
+ hideResultsNow();
+ $input.trigger("result", [selected.data, selected.value]);
+ return true;
+ }
+
+ function onChange(crap, skipPrevCheck) {
+ if( lastKeyPressCode == KEY.DEL ) {
+ select.hide();
+ return;
+ }
+
+ var currentValue = $input.val();
+
+ if ( !skipPrevCheck && currentValue == previousValue )
+ return;
+
+ previousValue = currentValue;
+
+ currentValue = lastWord(currentValue);
+ if ( currentValue.length >= options.minChars) {
+ $input.addClass(options.loadingClass);
+ if (!options.matchCase)
+ currentValue = currentValue.toLowerCase();
+ request(currentValue, receiveData, hideResultsNow);
+ } else {
+ stopLoading();
+ select.hide();
+ }
+ };
+
+ function trimWords(value) {
+ if ( !value ) {
+ return [""];
+ }
+ var words = value.split( options.multipleSeparator );
+ var result = [];
+ $.each(words, function(i, value) {
+ if ( $.trim(value) )
+ result[i] = $.trim(value);
+ });
+ return result;
+ }
+
+ function lastWord(value) {
+ if ( !options.multiple )
+ return value;
+ var words = trimWords(value);
+ return words[words.length - 1];
+ }
+
+ // fills in the input box w/the first match (assumed to be the best match)
+ // q: the term entered
+ // sValue: the first matching result
+ function autoFill(q, sValue){
+ // autofill in the complete box w/the first match as long as the user hasn't entered in more data
+ // if the last user key pressed was backspace, don't autofill
+ if( options.autoFill && (lastWord($input.val()).toLowerCase() == q.toLowerCase()) && lastKeyPressCode != KEY.BACKSPACE ) {
+ // fill in the value (keep the case the user has typed)
+ $input.val($input.val() + sValue.substring(lastWord(previousValue).length));
+ // select the portion of the value not typed by the user (so the next character will erase)
+ $.Autocompleter.Selection(input, previousValue.length, previousValue.length + sValue.length);
+ }
+ };
+
+ function hideResults() {
+ clearTimeout(timeout);
+ timeout = setTimeout(hideResultsNow, 200);
+ };
+
+ function hideResultsNow() {
+ var wasVisible = select.visible();
+ select.hide();
+ clearTimeout(timeout);
+ stopLoading();
+ if (options.mustMatch) {
+ // call search and run callback
+ $input.search(
+ function (result){
+ // if no value found, clear the input box
+ if( !result ) {
+ if (options.multiple) {
+ var words = trimWords($input.val()).slice(0, -1);
+ $input.val( words.join(options.multipleSeparator) + (words.length ? options.multipleSeparator : "") );
+ }
+ else
+ $input.val( "" );
+ }
+ }
+ );
+ }
+ if (wasVisible)
+ // position cursor at end of input field
+ $.Autocompleter.Selection(input, input.value.length, input.value.length);
+ };
+
+ function receiveData(q, data) {
+ if ( data && data.length && hasFocus ) {
+ stopLoading();
+ select.display(data, q);
+ autoFill(q, data[0].value);
+ select.show();
+ } else {
+ hideResultsNow();
+ }
+ };
+
+ function request(term, success, failure) {
+ if (!options.matchCase)
+ term = term.toLowerCase();
+ var data = cache.load(term);
+
+ // JG: hack: if term ends with ':', kill data to force an ajax request.
+ if (term.endsWith(":"))
+ data = null;
+
+ // recieve the cached data
+ if (data && data.length) {
+ success(term, data);
+ // if an AJAX url has been supplied, try loading the data now
+ } else if( (typeof options.url == "string") && (options.url.length > 0) ){
+ var extraParams = {
+ timestamp: +new Date()
+ };
+ $.each(options.extraParams, function(key, param) {
+ extraParams[key] = typeof param == "function" ? param() : param;
+ });
+
+ $.ajax({
+ // try to leverage ajaxQueue plugin to abort previous requests
+ mode: "abort",
+ // limit abortion to this input
+ port: "autocomplete" + input.name,
+ dataType: options.dataType,
+ url: options.url,
+ data: $.extend({
+ q: lastWord(term),
+ limit: options.max
+ }, extraParams),
+ success: function(data) {
+ var parsed = options.parse && options.parse(data) || parse(data);
+ cache.add(term, parsed);
+ success(term, parsed);
+ }
+ });
+ } else {
+ // if we have a failure, we need to empty the list -- this prevents the the [TAB] key from selecting the last successful match
+ select.emptyList();
+ failure(term);
+ }
+ };
+
+ function parse(data) {
+ var parsed = [];
+ var rows = data.split("\n");
+ for (var i=0; i < rows.length; i++) {
+ var row = $.trim(rows[i]);
+ if (row) {
+ row = row.split("|");
+ parsed[parsed.length] = {
+ data: row,
+ value: row[0],
+ result: options.formatResult && options.formatResult(row, row[0]) || row[0]
+ };
+ }
+ }
+ return parsed;
+ };
+
+ function stopLoading() {
+ $input.removeClass(options.loadingClass);
+ };
+
+};
+
+$.Autocompleter.defaults = {
+ inputClass: "ac_input",
+ resultsClass: "ac_results",
+ loadingClass: "ac_loading",
+ minChars: 1,
+ delay: 400,
+ matchCase: false,
+ matchSubset: true,
+ matchContains: false,
+ cacheLength: 10,
+ max: 100,
+ mustMatch: false,
+ extraParams: {},
+ selectFirst: true,
+ formatItem: function(row) { return row[0]; },
+ formatMatch: null,
+ autoFill: false,
+ width: 0,
+ multiple: false,
+ multipleSeparator: ", ",
+ highlight: function(value, term) {
+ return value.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + term.replace(/([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi, "\\$1") + ")(?![^<>]*>)(?![^&;]+;)", "gi"), "<strong>$1</strong>");
+ },
+ scroll: true,
+ scrollHeight: 180
+};
+
+$.Autocompleter.Cache = function(options) {
+
+ var data = {};
+ var length = 0;
+
+ function matchSubset(s, sub) {
+ if (!options.matchCase)
+ s = s.toLowerCase();
+ var i = s.indexOf(sub);
+ if (i == -1) return false;
+ return i == 0 || options.matchContains;
+ };
+
+ function add(q, value) {
+ if (length > options.cacheLength){
+ flush();
+ }
+ if (!data[q]){
+ length++;
+ }
+ data[q] = value;
+ }
+
+ function populate(){
+ if( !options.data ) return false;
+ // track the matches
+ var stMatchSets = {},
+ nullData = 0;
+
+ // no url was specified, we need to adjust the cache length to make sure it fits the local data store
+ if( !options.url ) options.cacheLength = 1;
+
+ // track all options for minChars = 0
+ stMatchSets[""] = [];
+
+ // loop through the array and create a lookup structure
+ for ( var i = 0, ol = options.data.length; i < ol; i++ ) {
+ var rawValue = options.data[i];
+ // if rawValue is a string, make an array otherwise just reference the array
+ rawValue = (typeof rawValue == "string") ? [rawValue] : rawValue;
+
+ var value = options.formatMatch(rawValue, i+1, options.data.length);
+ if ( value === false )
+ continue;
+
+ var firstChar = value.charAt(0).toLowerCase();
+ // if no lookup array for this character exists, look it up now
+ if( !stMatchSets[firstChar] )
+ stMatchSets[firstChar] = [];
+
+ // if the match is a string
+ var row = {
+ value: value,
+ data: rawValue,
+ result: options.formatResult && options.formatResult(rawValue) || value
+ };
+
+ // push the current match into the set list
+ stMatchSets[firstChar].push(row);
+
+ // keep track of minChars zero items
+ if ( nullData++ < options.max ) {
+ stMatchSets[""].push(row);
+ }
+ };
+
+ // add the data items to the cache
+ $.each(stMatchSets, function(i, value) {
+ // increase the cache size
+ options.cacheLength++;
+ // add to the cache
+ add(i, value);
+ });
+ }
+
+ // populate any existing data
+ setTimeout(populate, 25);
+
+ function flush(){
+ data = {};
+ length = 0;
+ }
+
+ return {
+ flush: flush,
+ add: add,
+ populate: populate,
+ load: function(q) {
+ if (!options.cacheLength || !length)
+ return null;
+
+ /*
+ * if dealing w/local data and matchContains than we must make sure
+ * to loop through all the data collections looking for matches
+ */
+ if( !options.url && options.matchContains ){
+ // track all matches
+ var csub = [];
+ // loop through all the data grids for matches
+ for( var k in data ){
+ // don't search through the stMatchSets[""] (minChars: 0) cache
+ // this prevents duplicates
+ if( k.length > 0 ){
+ var c = data[k];
+ $.each(c, function(i, x) {
+ // if we've got a match, add it to the array
+ if (matchSubset(x.value, q)) {
+ csub.push(x);
+ }
+ });
+ }
+ }
+ return csub;
+ } else
+ // if the exact item exists, use it
+ if (data[q]){
+ return data[q];
+ } else
+ if (options.matchSubset) {
+ for (var i = q.length - 1; i >= options.minChars; i--) {
+ var c = data[q.substr(0, i)];
+ if (c) {
+ var csub = [];
+ $.each(c, function(i, x) {
+ if ( (x.data.indexOf("#Header") == 0) ||
+ (matchSubset(x.value, q)) ) {
+ csub[csub.length] = x;
+ }
+ });
+ return csub;
+ }
+ }
+
+ }
+ return null;
+ }
+ };
+};
+
+$.Autocompleter.Select = function (options, input, select, config) {
+ var CLASSES = {
+ ACTIVE: "ac_over"
+ };
+
+ var listItems,
+ active = -1,
+ data,
+ term = "",
+ needsInit = true,
+ element,
+ list;
+
+ // Create results
+ function init() {
+ if (!needsInit)
+ return;
+ element = $("<div/>")
+ .hide()
+ .addClass(options.resultsClass)
+ .css("position", "absolute")
+ .appendTo(document.body);
+
+ list = $("<ul/>").appendTo(element).mouseover( function(event) {
+ if(target(event).nodeName && target(event).nodeName.toUpperCase() == 'LI') {
+ active = $("li", list).removeClass(CLASSES.ACTIVE).index(target(event));
+ // JG: Only add active class if target is not a header.
+ if (!headerAtPosition(active))
+ $(target(event)).addClass(CLASSES.ACTIVE);
+ }
+ }).click(function(event) {
+ // JG: Ignore click on header.
+ active = $("li", list).index(target(event));
+ if (headerAtPosition(active))
+ return;
+
+ // Handle click on autocomplete options.
+ $(target(event)).addClass(CLASSES.ACTIVE);
+ select();
+ // TODO provide option to avoid setting focus again after selection? useful for cleanup-on-focus
+ input.focus();
+ return false;
+ }).mousedown(function() {
+ config.mouseDownOnSelect = true;
+ }).mouseup(function() {
+ config.mouseDownOnSelect = false;
+ });
+
+ if( options.width > 0 )
+ element.css("width", options.width);
+
+ needsInit = false;
+ }
+
+ function target(event) {
+ var element = event.target;
+ while(element && element.tagName != "LI")
+ element = element.parentNode;
+ // more fun with IE, sometimes event.target is empty, just ignore it then
+ if(!element)
+ return [];
+ return element;
+ }
+
+ // JG: Returns true iff there is a header element at the given position.
+ function headerAtPosition(position)
+ {
+ dataAtPosition = data[position].data;
+ return (dataAtPosition.indexOf("#Header") == 0);
+ }
+
+ function moveSelect(step) {
+ listItems.slice(active, active + 1).removeClass(CLASSES.ACTIVE);
+ // JG: while active item is a header, continue stepping.
+ var isHeader = false;
+ do
+ {
+ movePosition(step);
+ isHeader = headerAtPosition(active);
+ }
+ while (isHeader);
+ var activeItem = listItems.slice(active, active + 1).addClass(CLASSES.ACTIVE);
+
+
+ if(options.scroll) {
+ var offset = 0;
+ listItems.slice(0, active).each(function() {
+ offset += this.offsetHeight;
+ });
+ if((offset + activeItem[0].offsetHeight - list.scrollTop()) > list[0].clientHeight) {
+ list.scrollTop(offset + activeItem[0].offsetHeight - list.innerHeight());
+ } else if(offset < list.scrollTop()) {
+ list.scrollTop(offset);
+ }
+ }
+ };
+
+ function movePosition(step) {
+ active += step;
+ if (active < 0) {
+ active = listItems.size() - 1;
+ } else if (active >= listItems.size()) {
+ active = 0;
+ }
+ }
+
+ function limitNumberOfItems(available) {
+ return options.max && options.max < available
+ ? options.max
+ : available;
+ }
+
+ function fillList() {
+ list.empty();
+ var max = limitNumberOfItems(data.length);
+ for (var i=0; i < max; i++) {
+ if (!data[i])
+ continue;
+ var formatted = options.formatItem(data[i].data, i+1, max, data[i].value, term);
+ if ( formatted === false )
+ continue;
+
+ // JG: Build list item by formatting the item and choosing a CSS class.
+ if (headerAtPosition(i))
+ {
+ // Found header element; only add header if there are subsequent elements.
+ if (i != max-1)
+ var li = $("<li/>").html(data[i].data[1]).addClass("ac_header").appendTo(list)[0];
+ }
+ else
+ {
+ // Found completion element.
+ var li = $("<li/>").html(options.highlight(formatted, term)).addClass(i%2 == 0 ? "ac_even" : "ac_odd").appendTo(list)[0];
+ }
+
+ $.data(li, "ac_data", data[i]);
+ }
+ listItems = list.find("li");
+ if ( options.selectFirst ) {
+ listItems.slice(0, 1).addClass(CLASSES.ACTIVE);
+ active = 0;
+ }
+ // apply bgiframe if available
+ if ( $.fn.bgiframe )
+ list.bgiframe();
+ }
+
+ return {
+ display: function(d, q) {
+ init();
+ data = d;
+ term = q;
+ fillList();
+ },
+ next: function() {
+ moveSelect(1);
+ },
+ prev: function() {
+ moveSelect(-1);
+ },
+ pageUp: function() {
+ if (active != 0 && active - 8 < 0) {
+ moveSelect( -active );
+ } else {
+ moveSelect(-8);
+ }
+ },
+ pageDown: function() {
+ if (active != listItems.size() - 1 && active + 8 > listItems.size()) {
+ moveSelect( listItems.size() - 1 - active );
+ } else {
+ moveSelect(8);
+ }
+ },
+ hide: function() {
+ element && element.hide();
+ listItems && listItems.removeClass(CLASSES.ACTIVE);
+ active = -1;
+ },
+ visible : function() {
+ return element && element.is(":visible");
+ },
+ current: function() {
+ return this.visible() && (listItems.filter("." + CLASSES.ACTIVE)[0] || options.selectFirst && listItems[0]);
+ },
+ show: function() {
+ var offset = $(input).offset();
+ element.css({
+ width: typeof options.width == "string" || options.width > 0 ? options.width : $(input).width(),
+ top: offset.top + input.offsetHeight,
+ left: offset.left
+ }).show();
+ if(options.scroll) {
+ list.scrollTop(0);
+ list.css({
+ maxHeight: options.scrollHeight,
+ overflow: 'auto'
+ });
+
+ if($.browser.msie && typeof document.body.style.maxHeight === "undefined") {
+ var listHeight = 0;
+ listItems.each(function() {
+ listHeight += this.offsetHeight;
+ });
+ var scrollbarsVisible = listHeight > options.scrollHeight;
+ list.css('height', scrollbarsVisible ? options.scrollHeight : listHeight );
+ if (!scrollbarsVisible) {
+ // IE doesn't recalculate width when scrollbar disappears
+ listItems.width( list.width() - parseInt(listItems.css("padding-left")) - parseInt(listItems.css("padding-right")) );
+ }
+ }
+
+ }
+ },
+ selected: function() {
+ var selected = listItems && listItems.filter("." + CLASSES.ACTIVE).removeClass(CLASSES.ACTIVE);
+ return selected && selected.length && $.data(selected[0], "ac_data");
+ },
+ emptyList: function (){
+ list && list.empty();
+ },
+ unbind: function() {
+ element && element.remove();
+ }
+ };
+};
+
+$.Autocompleter.Selection = function(field, start, end) {
+ if( field.createTextRange ){
+ var selRange = field.createTextRange();
+ selRange.collapse(true);
+ selRange.moveStart("character", start);
+ selRange.moveEnd("character", end);
+ selRange.select();
+ } else if( field.setSelectionRange ){
+ field.setSelectionRange(start, end);
+ } else {
+ if( field.selectionStart ){
+ field.selectionStart = start;
+ field.selectionEnd = end;
+ }
+ }
+ field.focus();
+};
+
+})(jQuery);
1
0
details: http://www.bx.psu.edu/hg/galaxy/rev/116e79410240
changeset: 2642:116e79410240
user: jeremy goecks <jeremy.goecks(a)emory.edu>
date: Fri Aug 28 15:29:47 2009 -0400
description:
CSS code for tagging
2 file(s) affected in this change:
static/june_2007_style/autocomplete_tagging.css.tmpl
static/june_2007_style/blue/autocomplete_tagging.css
diffs (276 lines):
diff -r 6b66a5e142ab -r 116e79410240 static/june_2007_style/autocomplete_tagging.css.tmpl
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/static/june_2007_style/autocomplete_tagging.css.tmpl Fri Aug 28 15:29:47 2009 -0400
@@ -0,0 +1,133 @@
+/****************************************************************************/
+/* JQuery autocomplete code */
+/****************************************************************************/
+
+.ac_results {
+ padding: 0px;
+ border: 1px solid black;
+ background-color: white;
+ overflow: hidden;
+ z-index: 99999;
+}
+
+.ac_results ul {
+ width: 100%;
+ list-style-position: outside;
+ list-style: none;
+ padding: 0;
+ margin: 0;
+}
+
+.ac_results li {
+ padding: 2px 5px;
+ cursor: default;
+ display: block;
+ /*
+ if width will be 100% horizontal scrollbar will apear
+ when scroll mode will be used
+ */
+ /*width: 100%;*/
+ /* font: menu; */
+ font-size: 12px;
+ /*
+ it is very important, if line-height not setted or setted
+ in relative units scroll will be broken in firefox
+ */
+ line-height: 16px;
+ overflow: hidden;
+}
+
+.ac_loading {
+ background: white url('indicator.gif') right center no-repeat;
+}
+
+.ac_odd {
+ background-color: #fff; /* #eee */
+ margin-left: 0.3em;
+}
+
+.ac_even {
+ margin-left: 0.3em;
+}
+
+.ac_over {
+ background-color: #0A246A;
+ color: white;
+}
+
+.ac_header {
+ font-style: normal;
+ color: gray;
+ border-bottom: 0.1em solid gray;
+}
+
+/****************************************************************************/
+/* Custom code for supporting tags */
+/****************************************************************************/
+.tag-area {
+ width: 100%;
+ cursor: pointer;
+ border: solid 1px #eee;
+}
+
+.active-tag-area {
+ background-color: white;
+}
+
+.toggle-link
+{
+ font-weight: bold;
+ padding: 0.3em;
+ margin-bottom: 1em;
+ width: 100%;
+ padding: 0.2em 0em 0.2em 0em;
+}
+
+.tag-button {
+ width: auto;
+ color: #444;
+ text-decoration: none;
+ display: inline-block;
+ cursor: pointer;
+ margin: 0.2em;
+ border: 0;
+ padding: 0.1em 0.5em 0.1em 0.5em;
+ -moz-border-radius: .5em;
+ -webkit-border-radius: .5em;
+ border-radius: .5em;
+ background:#bbb;
+}
+
+.tag-button img
+{
+ padding-left: 0.4em;
+}
+
+.tag-button .tag-name:hover
+{
+ color: white;
+}
+
+.add-tag-button
+{
+ margin-bottom: 0.3em;
+ vertical-align: middle;
+ padding: 0.3em;
+}
+
+.add-tag-button:hover
+{
+ cursor: pointer;
+}
+
+.tag-input {
+ vertical-align: bottom;
+ border: none;
+ outline: none;
+}
+
+.delete-tag-img
+{
+
+ margin-left: 0.3em
+}
\ No newline at end of file
diff -r 6b66a5e142ab -r 116e79410240 static/june_2007_style/blue/autocomplete_tagging.css
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/static/june_2007_style/blue/autocomplete_tagging.css Fri Aug 28 15:29:47 2009 -0400
@@ -0,0 +1,133 @@
+/****************************************************************************/
+/* JQuery autocomplete code */
+/****************************************************************************/
+
+.ac_results {
+ padding: 0px;
+ border: 1px solid black;
+ background-color: white;
+ overflow: hidden;
+ z-index: 99999;
+}
+
+.ac_results ul {
+ width: 100%;
+ list-style-position: outside;
+ list-style: none;
+ padding: 0;
+ margin: 0;
+}
+
+.ac_results li {
+ padding: 2px 5px;
+ cursor: default;
+ display: block;
+ /*
+ if width will be 100% horizontal scrollbar will apear
+ when scroll mode will be used
+ */
+ /*width: 100%;*/
+ /* font: menu; */
+ font-size: 12px;
+ /*
+ it is very important, if line-height not setted or setted
+ in relative units scroll will be broken in firefox
+ */
+ line-height: 16px;
+ overflow: hidden;
+}
+
+.ac_loading {
+ background: white url('indicator.gif') right center no-repeat;
+}
+
+.ac_odd {
+ background-color: #fff; /* #eee */
+ margin-left: 0.3em;
+}
+
+.ac_even {
+ margin-left: 0.3em;
+}
+
+.ac_over {
+ background-color: #0A246A;
+ color: white;
+}
+
+.ac_header {
+ font-style: normal;
+ color: gray;
+ border-bottom: 0.1em solid gray;
+}
+
+/****************************************************************************/
+/* Custom code for supporting tags */
+/****************************************************************************/
+.tag-area {
+ width: 100%;
+ cursor: pointer;
+ border: solid 1px #eee;
+}
+
+.active-tag-area {
+ background-color: white;
+}
+
+.toggle-link
+{
+ font-weight: bold;
+ padding: 0.3em;
+ margin-bottom: 1em;
+ width: 100%;
+ padding: 0.2em 0em 0.2em 0em;
+}
+
+.tag-button {
+ width: auto;
+ color: #444;
+ text-decoration: none;
+ display: inline-block;
+ cursor: pointer;
+ margin: 0.2em;
+ border: 0;
+ padding: 0.1em 0.5em 0.1em 0.5em;
+ -moz-border-radius: .5em;
+ -webkit-border-radius: .5em;
+ border-radius: .5em;
+ background:#bbb;
+}
+
+.tag-button img
+{
+ padding-left: 0.4em;
+}
+
+.tag-button .tag-name:hover
+{
+ color: white;
+}
+
+.add-tag-button
+{
+ margin-bottom: 0.3em;
+ vertical-align: middle;
+ padding: 0.3em;
+}
+
+.add-tag-button:hover
+{
+ cursor: pointer;
+}
+
+.tag-input {
+ vertical-align: bottom;
+ border: none;
+ outline: none;
+}
+
+.delete-tag-img
+{
+
+ margin-left: 0.3em
+}
\ No newline at end of file
1
0
29 Aug '09
details: http://www.bx.psu.edu/hg/galaxy/rev/cc4944a62b66
changeset: 2640:cc4944a62b66
user: Greg Von Kuster <greg(a)bx.psu.edu>
date: Fri Aug 28 16:52:58 2009 -0400
description:
Performance improvements in the GalaxyRBACAgent for checking access permissions on libraries. Also added information to main config regarding mysql timeouts ( resolves ticket # 132 ).
27 file(s) affected in this change:
lib/galaxy/model/__init__.py
lib/galaxy/model/mapping.py
lib/galaxy/security/__init__.py
lib/galaxy/tools/actions/__init__.py
lib/galaxy/tools/parameters/basic.py
lib/galaxy/web/controllers/admin.py
lib/galaxy/web/controllers/dataset.py
lib/galaxy/web/controllers/history.py
lib/galaxy/web/controllers/library.py
lib/galaxy/web/controllers/root.py
templates/admin/library/browse_library.mako
templates/dataset/edit_attributes.mako
templates/library/browse_library.mako
templates/library/common.mako
templates/library/folder_info.mako
templates/library/folder_permissions.mako
templates/library/ldda_edit_info.mako
templates/library/ldda_info.mako
templates/library/library_dataset_info.mako
templates/library/library_dataset_permissions.mako
templates/library/library_info.mako
templates/library/library_permissions.mako
templates/mobile/history/detail.mako
templates/mobile/manage_library.mako
templates/root/history_common.mako
test/base/twilltestcase.py
universe_wsgi.ini.sample
diffs (1463 lines):
diff -r 36f438ce1f82 -r cc4944a62b66 lib/galaxy/model/__init__.py
--- a/lib/galaxy/model/__init__.py Fri Aug 28 15:59:16 2009 -0400
+++ b/lib/galaxy/model/__init__.py Fri Aug 28 16:52:58 2009 -0400
@@ -723,15 +723,19 @@
return None
@property
def active_components( self ):
- return list( self.active_folders ) + list( self.active_datasets )
+ return list( self.active_folders ) + list( self.active_library_datasets )
+ @property
+ def active_library_datasets( self ):
+ # This needs to be a list
+ return [ ld for ld in self.datasets if not ld.library_dataset_dataset_association.deleted ]
+ @property
+ def activatable_library_datasets( self ):
+ # This needs to be a list
+ return [ ld for ld in self.datasets if not ld.library_dataset_dataset_association.dataset.deleted ]
@property
def active_datasets( self ):
# This needs to be a list
- return [ ld for ld in self.datasets if not ld.library_dataset_dataset_association.deleted ]
- @property
- def activatable_datasets( self ):
- # This needs to be a list
- return [ ld for ld in self.datasets if not ld.library_dataset_dataset_association.dataset.deleted ]
+ return [ ld.library_dataset_dataset_association.dataset for ld in self.datasets if not ld.library_dataset_dataset_association.deleted ]
@property #make this a relation
def activatable_folders( self ):
# This needs to be a list
diff -r 36f438ce1f82 -r cc4944a62b66 lib/galaxy/model/mapping.py
--- a/lib/galaxy/model/mapping.py Fri Aug 28 15:59:16 2009 -0400
+++ b/lib/galaxy/model/mapping.py Fri Aug 28 16:52:58 2009 -0400
@@ -740,7 +740,7 @@
assign_mapper( context, DatasetPermissions, DatasetPermissions.table,
properties=dict(
dataset=relation( Dataset, backref="actions" ),
- role=relation( Role, backref="actions" )
+ role=relation( Role, backref="dataset_actions" )
)
)
diff -r 36f438ce1f82 -r cc4944a62b66 lib/galaxy/security/__init__.py
--- a/lib/galaxy/security/__init__.py Fri Aug 28 15:59:16 2009 -0400
+++ b/lib/galaxy/security/__init__.py Fri Aug 28 16:52:58 2009 -0400
@@ -33,8 +33,10 @@
def get_actions( self ):
"""Get all permitted actions as a list of Action objects"""
return self.permitted_actions.__dict__.values()
- def allow_action( self, user, action, **kwd ):
+ def allow_action( self, user, roles, action, **kwd ):
raise 'No valid method of checking action (%s) on %s for user %s.' % ( action, kwd, user )
+ def get_item_action( self, action, item ):
+ raise 'No valid method of retrieving action (%s) for item %s.' % ( action, item )
def guess_derived_permissions_for_datasets( self, datasets = [] ):
raise "Unimplemented Method"
def associate_components( self, **kwd ):
@@ -79,40 +81,48 @@
( self.model.LibraryFolder, self.model.LibraryFolderPermissions ),
( self.model.LibraryDataset, self.model.LibraryDatasetPermissions ),
( self.model.LibraryDatasetDatasetAssociation, self.model.LibraryDatasetDatasetAssociationPermissions ) )
- def allow_action( self, user, action, **kwd ):
+ @property
+ def sa_session( self ):
+ """
+ Returns a SQLAlchemy session -- currently just gets the current
+ session from the threadlocal session context, but this is provided
+ to allow migration toward a more SQLAlchemy 0.4 style of use.
+ """
+ return self.model.context.current
+ def allow_action( self, user, roles, action, **kwd ):
if 'dataset' in kwd:
- return self.allow_dataset_action( user, action, kwd[ 'dataset' ] )
+ return self.allow_dataset_action( user, roles, action, kwd[ 'dataset' ] )
elif 'library_item' in kwd:
- return self.allow_library_item_action( user, action, kwd[ 'library_item' ] )
+ return self.allow_library_item_action( user, roles, action, kwd[ 'library_item' ] )
raise 'No valid method of checking action (%s) for user %s using kwd %s' % ( action, str( user ), str( kwd ) )
- def allow_dataset_action( self, user, action, dataset ):
+ def allow_dataset_action( self, user, roles, action, dataset ):
"""Returns true when user has permission to perform an action"""
- if not isinstance( dataset, self.model.Dataset ):
- dataset = dataset.dataset
if not user:
if action == self.permitted_actions.DATASET_ACCESS and action.action not in [ dp.action for dp in dataset.actions ]:
- return True # anons only get access, and only if there are no roles required for the access action
- # other actions (or if the dataset has roles defined for the access action) fall through to the false below
+ # anons only get access, and only if there are no roles required for the access action
+ # Other actions (or if the dataset has roles defined for the access action) fall through
+ # to the false below
+ return True
elif action.action not in [ dp.action for dp in dataset.actions ]:
if action.model == 'restrict':
- return True # implicit access to restrict-style actions if the dataset does not have the action
- # grant-style actions fall through to the false below
+ # Implicit access to restrict-style actions if the dataset does not have the action
+ # Grant style actions fall through to the false below
+ return True
else:
- user_role_ids = sorted( [ r.id for r in user.all_roles() ] )
perms = self.get_dataset_permissions( dataset )
if action in perms.keys():
# The filter() returns a list of the dataset's role ids of which the user is not a member,
# so an empty list means the user has all of the required roles.
- if not filter( lambda x: x not in user_role_ids, [ r.id for r in perms[ action ] ] ):
- return True # user has all of the roles required to perform the action
- # Fall through to the false because the user is missing at least one required role
- return False # default is to reject
- def allow_library_item_action( self, user, action, library_item ):
+ if not filter( lambda x: x not in roles, [ r for r in perms[ action ] ] ):
+ # User has all of the roles required to perform the action
+ return True
+ # The user is missing at least one required role
+ return False
+ def allow_library_item_action( self, user, roles, action, library_item ):
if user is None:
# All permissions are granted, so non-users cannot have permissions
return False
if action.model == 'grant':
- user_role_ids = [ r.id for r in user.all_roles() ]
# Check to see if user has access to any of the roles
allowed_role_assocs = []
for item_class, permission_class in self.library_item_assocs:
@@ -126,11 +136,17 @@
elif permission_class == self.model.LibraryDatasetDatasetAssociationPermissions:
allowed_role_assocs = permission_class.filter_by( action=action.action, library_dataset_dataset_association_id=library_item.id ).all()
for allowed_role_assoc in allowed_role_assocs:
- if allowed_role_assoc.role_id in user_role_ids:
+ if allowed_role_assoc.role in roles:
return True
return False
else:
raise 'Unimplemented model (%s) specified for action (%s)' % ( action.model, action.action )
+ def get_item_action( self, action, item ):
+ # item must be one of: Dataset, Library, LibraryFolder, LibraryDataset, LibraryDatasetDatasetAssociation
+ for permission in item.actions:
+ if permission.action == action:
+ return permission
+ return None
def guess_derived_permissions_for_datasets( self, datasets=[] ):
"""Returns a dict of { action : [ role, role, ... ] } for the output dataset based upon provided datasets"""
perms = {}
@@ -260,7 +276,10 @@
if [ assoc for assoc in dataset.history_associations if assoc.history not in user.histories ]:
# Don't change permissions on a dataset associated with a history not owned by the user
continue
- if bypass_manage_permission or self.allow_action( user, self.permitted_actions.DATASET_MANAGE_PERMISSIONS, dataset=dataset ):
+ if bypass_manage_permission or self.allow_action( user,
+ user.all_roles(),
+ self.permitted_actions.DATASET_MANAGE_PERMISSIONS,
+ dataset=dataset ):
self.set_all_dataset_permissions( dataset, permissions )
def history_get_default_permissions( self, history ):
permissions = {}
@@ -402,17 +421,18 @@
lp = permission_class( action.action, target_library_item, private_role )
lp.flush()
else:
- raise 'Invalid class (%s) specified for target_library_item (%s)' % ( target_library_item.__class__, target_library_item.__class__.__name__ )
- def show_library_item( self, user, library_item ):
- if self.allow_action( user, self.permitted_actions.LIBRARY_MODIFY, library_item=library_item ) or \
- self.allow_action( user, self.permitted_actions.LIBRARY_MANAGE, library_item=library_item ) or \
- self.allow_action( user, self.permitted_actions.LIBRARY_ADD, library_item=library_item ):
+ raise 'Invalid class (%s) specified for target_library_item (%s)' % \
+ ( target_library_item.__class__, target_library_item.__class__.__name__ )
+ def show_library_item( self, user, roles, library_item ):
+ if self.allow_action( user, roles, self.permitted_actions.LIBRARY_MODIFY, library_item=library_item ) or \
+ self.allow_action( user, roles, self.permitted_actions.LIBRARY_MANAGE, library_item=library_item ) or \
+ self.allow_action( user, roles, self.permitted_actions.LIBRARY_ADD, library_item=library_item ):
return True
if isinstance( library_item, self.model.Library ):
- return self.show_library_item( user, library_item.root_folder )
+ return self.show_library_item( user, roles, library_item.root_folder )
elif isinstance( library_item, self.model.LibraryFolder ):
for folder in library_item.folders:
- if self.show_library_item( user, folder ):
+ if self.show_library_item( user, roles, folder ):
return True
return False
def set_entity_user_associations( self, users=[], roles=[], groups=[], delete_existing_assocs=True ):
@@ -462,26 +482,30 @@
if 'role' in kwd:
return self.model.GroupRoleAssociation.filter_by( role_id = kwd['role'].id, group_id = kwd['group'].id ).first()
raise 'No valid method of associating provided components: %s' % kwd
- def check_folder_contents( self, user, entry ):
+ def check_folder_contents( self, user, roles, folder ):
"""
- Return true if there are any datasets under 'folder' that the
- user has access permission on. We do this a lot and it's a
- pretty inefficient method, optimizations are welcomed.
+ Return true if there are any datasets under 'folder' that are public or that the
+ user has access permission on.
"""
- if isinstance( entry, self.model.Library ):
- return self.check_folder_contents( user, entry.root_folder )
- elif isinstance( entry, self.model.LibraryFolder ):
- for library_dataset in entry.active_datasets:
- if self.allow_action( user, self.permitted_actions.DATASET_ACCESS, dataset=library_dataset.library_dataset_dataset_association.dataset ):
- return True
- for folder in entry.active_folders:
- if self.check_folder_contents( user, folder ):
- return True
- return False
- elif isinstance( entry, self.model.LibraryDatasetDatasetAssociation ):
- return self.allow_action( user, self.permitted_actions.DATASET_ACCESS, dataset=entry.dataset )
- else:
- raise 'Passed an illegal object to check_folder_contents: %s' % type( entry )
+ action = self.permitted_actions.DATASET_ACCESS.action
+ lddas = self.sa_session.query( self.model.LibraryDatasetDatasetAssociation ) \
+ .join( "library_dataset" ) \
+ .filter( self.model.LibraryDataset.folder == folder ) \
+ .join( "dataset" ) \
+ .options( eagerload_all( "dataset.actions" ) ) \
+ .all()
+ for ldda in lddas:
+ ldda_access = self.get_item_action( action, ldda.dataset )
+ if ldda_access is None:
+ # Dataset is public
+ return True
+ if ldda_access.role in roles:
+ # The current user has access permission on the dataset
+ return True
+ for sub_folder in folder.active_folders:
+ if self.check_folder_contents( user, roles, sub_folder ):
+ return True
+ return False
class HostAgent( RBACAgent ):
"""
diff -r 36f438ce1f82 -r cc4944a62b66 lib/galaxy/tools/actions/__init__.py
--- a/lib/galaxy/tools/actions/__init__.py Fri Aug 28 15:59:16 2009 -0400
+++ b/lib/galaxy/tools/actions/__init__.py Fri Aug 28 16:52:58 2009 -0400
@@ -47,8 +47,15 @@
assoc.dataset = new_data
assoc.flush()
data = new_data
- # TODO, Nate: Make sure the permitted actions here are appropriate.
- if data and not trans.app.security_agent.allow_action( trans.user, data.permitted_actions.DATASET_ACCESS, dataset=data ):
+ user = trans.user
+ if user:
+ roles = user.all_roles()
+ else:
+ roles = None
+ if data and not trans.app.security_agent.allow_action( user,
+ roles,
+ data.permitted_actions.DATASET_ACCESS,
+ dataset=data.dataset ):
raise "User does not have permission to use a dataset (%s) provided for input." % data.id
return data
if isinstance( input, DataToolParameter ):
@@ -261,10 +268,17 @@
# parameters to the command as a special case.
for name, value in tool.params_to_strings( incoming, trans.app ).iteritems():
job.add_parameter( name, value )
+ user = trans.user
+ if user:
+ roles = user.all_roles()
+ else:
+ roles = None
for name, dataset in inp_data.iteritems():
if dataset:
- # TODO, Nate: Make sure the permitted actions here are appropriate.
- if not trans.app.security_agent.allow_action( trans.user, dataset.permitted_actions.DATASET_ACCESS, dataset=dataset ):
+ if not trans.app.security_agent.allow_action( user,
+ roles,
+ dataset.permitted_actions.DATASET_ACCESS,
+ dataset=dataset.dataset ):
raise "User does not have permission to use a dataset (%s) provided for input." % data.id
job.add_input_dataset( name, dataset )
else:
diff -r 36f438ce1f82 -r cc4944a62b66 lib/galaxy/tools/parameters/basic.py
--- a/lib/galaxy/tools/parameters/basic.py Fri Aug 28 15:59:16 2009 -0400
+++ b/lib/galaxy/tools/parameters/basic.py Fri Aug 28 16:52:58 2009 -0400
@@ -1137,6 +1137,11 @@
field = form_builder.SelectField( self.name, self.multiple, None, self.refresh_on_change, refresh_on_change_values = self.refresh_on_change_values )
# CRUCIAL: the dataset_collector function needs to be local to DataToolParameter.get_html_field()
def dataset_collector( hdas, parent_hid ):
+ user = trans.user
+ if user:
+ roles = user.all_roles()
+ else:
+ roles = None
for i, hda in enumerate( hdas ):
if len( hda.name ) > 30:
hda_name = '%s..%s' % ( hda.name[:17], hda.name[-11:] )
@@ -1148,12 +1153,18 @@
hid = str( hda.hid )
if not hda.dataset.state in [galaxy.model.Dataset.states.ERROR, galaxy.model.Dataset.states.DISCARDED] and \
hda.visible and \
- trans.app.security_agent.allow_action( trans.user, hda.permitted_actions.DATASET_ACCESS, dataset=hda ):
+ trans.app.security_agent.allow_action( user,
+ roles,
+ hda.permitted_actions.DATASET_ACCESS,
+ dataset=hda.dataset ):
# If we are sending data to an external application, then we need to make sure there are no roles
# associated with the dataset that restrict it's access from "public". We determine this by sending
# None as the user to the allow_action method.
if self.tool and self.tool.tool_type == 'data_destination':
- if not trans.app.security_agent.allow_action( None, hda.permitted_actions.DATASET_ACCESS, dataset=hda ):
+ if not trans.app.security_agent.allow_action( None,
+ None,
+ hda.permitted_actions.DATASET_ACCESS,
+ dataset=hda.dataset ):
continue
if self.options and hda.get_dbkey() != filter_value:
continue
@@ -1165,7 +1176,10 @@
if target_ext:
if converted_dataset:
hda = converted_dataset
- if not trans.app.security_agent.allow_action( trans.user, trans.app.security_agent.permitted_actions.DATASET_ACCESS, dataset=hda.dataset ):
+ if not trans.app.security_agent.allow_action( user,
+ roles,
+ trans.app.security_agent.permitted_actions.DATASET_ACCESS,
+ dataset=hda.dataset ):
continue
selected = ( value and ( hda in value ) )
field.add_option( "%s: (as %s) %s" % ( hid, target_ext, hda_name ), hda.id, selected )
diff -r 36f438ce1f82 -r cc4944a62b66 lib/galaxy/web/controllers/admin.py
--- a/lib/galaxy/web/controllers/admin.py Fri Aug 28 15:59:16 2009 -0400
+++ b/lib/galaxy/web/controllers/admin.py Fri Aug 28 16:52:58 2009 -0400
@@ -269,7 +269,7 @@
gra.delete()
gra.flush()
# Delete DatasetPermissionss
- for dp in role.actions:
+ for dp in role.dataset_actions:
dp.delete()
dp.flush()
msg = "The following have been purged from the database for role '%s': " % role.name
@@ -997,16 +997,8 @@
msg=msg,
messagetype=messagetype )
elif action == 'delete':
- def delete_folder( folder ):
- folder.refresh()
- for subfolder in folder.active_folders:
- delete_folder( subfolder )
- for ldda in folder.active_datasets:
- ldda.deleted = True
- ldda.flush()
- folder.deleted = True
- folder.flush()
- delete_folder( folder )
+ folder.deleted = True
+ folder.flush()
msg = "Folder '%s' and all of its contents have been marked deleted" % folder.name
return trans.response.send_redirect( web.url_for( action='browse_library',
id=library_id,
diff -r 36f438ce1f82 -r cc4944a62b66 lib/galaxy/web/controllers/dataset.py
--- a/lib/galaxy/web/controllers/dataset.py Fri Aug 28 15:59:16 2009 -0400
+++ b/lib/galaxy/web/controllers/dataset.py Fri Aug 28 16:52:58 2009 -0400
@@ -108,7 +108,15 @@
data = trans.app.model.HistoryDatasetAssociation.get( dataset_id )
if not data:
raise paste.httpexceptions.HTTPRequestRangeNotSatisfiable( "Invalid reference dataset id: %s." % str( dataset_id ) )
- if trans.app.security_agent.allow_action( trans.user, data.permitted_actions.DATASET_ACCESS, dataset = data ):
+ user = trans.user
+ if user:
+ roles = user.all_roles()
+ else:
+ roles = None
+ if trans.app.security_agent.allow_action( user,
+ roles,
+ data.permitted_actions.DATASET_ACCESS,
+ dataset=data.dataset ):
if data.state == trans.model.Dataset.states.UPLOAD:
return trans.show_error_message( "Please wait until this dataset finishes uploading before attempting to view it." )
if filename is None or filename.lower() == "index":
@@ -142,9 +150,17 @@
if 'display_url' not in kwd or 'redirect_url' not in kwd:
return trans.show_error_message( 'Invalid parameters specified for "display at" link, please contact a Galaxy administrator' )
redirect_url = kwd['redirect_url'] % urllib.quote_plus( kwd['display_url'] )
- if trans.app.security_agent.allow_action( None, data.permitted_actions.DATASET_ACCESS, dataset = data ):
+ user = trans.user
+ if user:
+ roles = user.all_roles()
+ else:
+ roles = None
+ if trans.app.security_agent.allow_action( None, None, data.permitted_actions.DATASET_ACCESS, dataset=data.dataset ):
return trans.response.send_redirect( redirect_url ) # anon access already permitted by rbac
- if trans.app.security_agent.allow_action( trans.user, data.permitted_actions.DATASET_ACCESS, dataset = data ):
+ if trans.app.security_agent.allow_action( user,
+ roles,
+ data.permitted_actions.DATASET_ACCESS,
+ dataset=data.dataset ):
trans.app.host_security_agent.set_dataset_permissions( data, trans.user, site )
return trans.response.send_redirect( redirect_url )
else:
diff -r 36f438ce1f82 -r cc4944a62b66 lib/galaxy/web/controllers/history.py
--- a/lib/galaxy/web/controllers/history.py Fri Aug 28 15:59:16 2009 -0400
+++ b/lib/galaxy/web/controllers/history.py Fri Aug 28 16:52:58 2009 -0400
@@ -411,6 +411,7 @@
err_msg=err_msg,
share_button=True ) )
user = trans.get_user()
+ user_roles = user.all_roles()
histories, send_to_users, send_to_err = self._get_histories_and_users( trans, user, id, email )
send_to_err = ''
# The user has made a choice, so dictionaries will be built for sharing
@@ -442,13 +443,15 @@
for hda in history.activatable_datasets:
# If the current dataset is not public, we may need to perform an action on it to
# make it accessible by the other user.
- if not trans.app.security_agent.allow_action( send_to_user,
+ if not trans.app.security_agent.allow_action( send_to_user,
+ send_to_user.all_roles(),
trans.app.security_agent.permitted_actions.DATASET_ACCESS,
- dataset=hda ):
+ dataset=hda.dataset ):
# The user with which we are sharing the history does not have access permission on the current dataset
- if trans.app.security_agent.allow_action( user,
+ if trans.app.security_agent.allow_action( user,
+ user_roles,
trans.app.security_agent.permitted_actions.DATASET_MANAGE_PERMISSIONS,
- dataset=hda ) and not hda.dataset.library_associations:
+ dataset=hda.dataset ) and not hda.dataset.library_associations:
# The current user has authority to change permissions on the current dataset because
# they have permission to manage permissions on the dataset and the dataset is not associated
# with a library.
@@ -525,6 +528,7 @@
cannot_change = {}
no_change_needed = {}
unique_no_change_needed = {}
+ user_roles = user.all_roles()
for history in histories:
for send_to_user in send_to_users:
# Make sure the current history has not already been shared with the current send_to_user
@@ -552,13 +556,15 @@
no_change_needed[ send_to_user ][ history ] = [ hda ]
else:
no_change_needed[ send_to_user ][ history ].append( hda )
- elif not trans.app.security_agent.allow_action( send_to_user,
+ elif not trans.app.security_agent.allow_action( send_to_user,
+ send_to_user.all_roles(),
trans.app.security_agent.permitted_actions.DATASET_ACCESS,
- dataset=hda ):
+ dataset=hda.dataset ):
# The user with which we are sharing the history does not have access permission on the current dataset
- if trans.app.security_agent.allow_action( user,
+ if trans.app.security_agent.allow_action( user,
+ user_roles,
trans.app.security_agent.permitted_actions.DATASET_MANAGE_PERMISSIONS,
- dataset=hda ) and not hda.dataset.library_associations:
+ dataset=hda.dataset ) and not hda.dataset.library_associations:
# The current user has authority to change permissions on the current dataset because
# they have permission to manage permissions on the dataset and the dataset is not associated
# with a library.
diff -r 36f438ce1f82 -r cc4944a62b66 lib/galaxy/web/controllers/library.py
--- a/lib/galaxy/web/controllers/library.py Fri Aug 28 15:59:16 2009 -0400
+++ b/lib/galaxy/web/controllers/library.py Fri Aug 28 16:52:58 2009 -0400
@@ -62,14 +62,29 @@
params = util.Params( kwd )
msg = util.restore_text( params.get( 'msg', '' ) )
messagetype = params.get( 'messagetype', 'done' )
- all_libraries = trans.app.model.Library.filter( trans.app.model.Library.table.c.deleted==False ).order_by( trans.app.model.Library.name ).all()
+ user = trans.user
+ if user:
+ roles = user.all_roles()
+ else:
+ roles = None
+ all_libraries = trans.app.model.Library.filter( trans.app.model.Library.table.c.deleted==False ) \
+ .order_by( trans.app.model.Library.name ).all()
authorized_libraries = []
for library in all_libraries:
- if trans.app.security_agent.allow_action( trans.user, trans.app.security_agent.permitted_actions.LIBRARY_ADD, library_item=library ) or \
- trans.app.security_agent.allow_action( trans.user, trans.app.security_agent.permitted_actions.LIBRARY_MODIFY, library_item=library ) or \
- trans.app.security_agent.allow_action( trans.user, trans.app.security_agent.permitted_actions.LIBRARY_MANAGE, library_item=library ) or \
- trans.app.security_agent.check_folder_contents( trans.user, library ) or \
- trans.app.security_agent.show_library_item( trans.user, library ):
+ if trans.app.security_agent.allow_action( user,
+ roles,
+ trans.app.security_agent.permitted_actions.LIBRARY_ADD,
+ library_item=library ) or \
+ trans.app.security_agent.allow_action( user,
+ roles,
+ trans.app.security_agent.permitted_actions.LIBRARY_MODIFY,
+ library_item=library ) or \
+ trans.app.security_agent.allow_action( user,
+ roles,
+ trans.app.security_agent.permitted_actions.LIBRARY_MANAGE,
+ library_item=library ) or \
+ trans.app.security_agent.check_folder_contents( user, roles, library.root_folder ) or \
+ trans.app.security_agent.show_library_item( user, roles, library ):
authorized_libraries.append( library )
return trans.fill_template( '/library/browse_libraries.mako',
libraries=authorized_libraries,
@@ -264,9 +279,15 @@
msg=util.sanitize_text( msg ),
messagetype='error' ) )
seen = []
+ user = trans.user
+ if user:
+ roles = user.all_roles()
+ else:
+ roles = None
for id in ldda_ids:
ldda = trans.app.model.LibraryDatasetDatasetAssociation.get( id )
- if not ldda or not trans.app.security_agent.allow_action( trans.user,
+ if not ldda or not trans.app.security_agent.allow_action( user,
+ roles,
trans.app.security_agent.permitted_actions.DATASET_ACCESS,
dataset = ldda.dataset ):
continue
@@ -363,9 +384,15 @@
id=library_id,
msg=util.sanitize_text( msg ),
messagetype='error' ) )
+ user = trans.user
+ if user:
+ roles = user.all_roles()
+ else:
+ roles = None
if action == 'information':
if params.get( 'edit_attributes_button', False ):
- if trans.app.security_agent.allow_action( trans.user,
+ if trans.app.security_agent.allow_action( user,
+ roles,
trans.app.security_agent.permitted_actions.LIBRARY_MODIFY,
library_item=library_dataset ):
if params.get( 'edit_attributes_button', False ):
@@ -391,7 +418,8 @@
messagetype=messagetype )
elif action == 'permissions':
if params.get( 'update_roles_button', False ):
- if trans.app.security_agent.allow_action( trans.user,
+ if trans.app.security_agent.allow_action( user,
+ roles,
trans.app.security_agent.permitted_actions.LIBRARY_MANAGE,
library_item=library_dataset ):
# The user clicked the Save button on the 'Associate With Roles' form
@@ -436,6 +464,11 @@
last_used_build = replace_dataset.library_dataset_dataset_association.dbkey
else:
replace_dataset = None
+ user = trans.user
+ if user:
+ roles = user.all_roles()
+ else:
+ roles = None
# Let's not overwrite the imported datatypes module with the variable datatypes?
# The built-in 'id' is overwritten in lots of places as well
ldatatypes = [ dtype_name for dtype_name, dtype_value in trans.app.datatypes_registry.datatypes_by_extension.iteritems() if dtype_value.allow_datatype_change ]
@@ -479,10 +512,12 @@
if action == 'permissions':
if params.get( 'update_roles_button', False ):
# The user clicked the Save button on the 'Associate With Roles' form
- if trans.app.security_agent.allow_action( trans.user,
+ if trans.app.security_agent.allow_action( user,
+ roles,
trans.app.security_agent.permitted_actions.LIBRARY_MANAGE,
library_item=ldda ) and \
- trans.app.security_agent.allow_action( trans.user,
+ trans.app.security_agent.allow_action( user,
+ roles,
trans.app.security_agent.permitted_actions.DATASET_MANAGE_PERMISSIONS,
dataset=ldda.dataset ):
permissions = {}
@@ -523,7 +558,8 @@
elif action == 'edit_info':
if params.get( 'change', False ):
# The user clicked the Save button on the 'Change data type' form
- if trans.app.security_agent.allow_action( trans.user,
+ if trans.app.security_agent.allow_action( user,
+ roles,
trans.app.security_agent.permitted_actions.LIBRARY_MODIFY,
library_item=ldda ):
if ldda.datatype.allow_datatype_change and trans.app.datatypes_registry.get_datatype_by_extension( params.datatype ).allow_datatype_change:
@@ -546,7 +582,8 @@
messagetype=messagetype )
elif params.get( 'save', False ):
# The user clicked the Save button on the 'Edit Attributes' form
- if trans.app.security_agent.allow_action( trans.user,
+ if trans.app.security_agent.allow_action( user,
+ roles,
trans.app.security_agent.permitted_actions.LIBRARY_MODIFY,
library_item=ldda ):
old_name = ldda.name
@@ -587,7 +624,8 @@
messagetype=messagetype )
elif params.get( 'detect', False ):
# The user clicked the Auto-detect button on the 'Edit Attributes' form
- if trans.app.security_agent.allow_action( trans.user,
+ if trans.app.security_agent.allow_action( user,
+ roles,
trans.app.security_agent.permitted_actions.LIBRARY_MODIFY,
library_item=ldda ):
for name, spec in ldda.datatype.metadata_spec.items():
@@ -611,7 +649,8 @@
msg=msg,
messagetype=messagetype )
elif params.get( 'delete', False ):
- if trans.app.security_agent.allow_action( trans.user,
+ if trans.app.security_agent.allow_action( user,
+ roles,
trans.app.security_agent.permitted_actions.LIBRARY_MODIFY,
library_item=folder ):
ldda.deleted = True
@@ -628,7 +667,8 @@
widgets=widgets,
msg=msg,
messagetype=messagetype )
- if trans.app.security_agent.allow_action( trans.user,
+ if trans.app.security_agent.allow_action( user,
+ roles,
trans.app.security_agent.permitted_actions.LIBRARY_MODIFY,
library_item=ldda ):
ldda.datatype.before_edit( ldda )
@@ -668,10 +708,12 @@
messagetype='error' ) )
if action == 'permissions':
if params.get( 'update_roles_button', False ):
- if trans.app.security_agent.allow_action( trans.user,
+ if trans.app.security_agent.allow_action( user,
+ roles,
trans.app.security_agent.permitted_actions.LIBRARY_MANAGE,
library_item=ldda ) and \
- trans.app.security_agent.allow_action( trans.user,
+ trans.app.security_agent.allow_action( user,
+ roles,
trans.app.security_agent.permitted_actions.DATASET_MANAGE_PERMISSIONS,
dataset=ldda.dataset ):
permissions = {}
@@ -704,10 +746,12 @@
library_id=library_id,
msg=msg,
messagetype=messagetype )
- if trans.app.security_agent.allow_action( trans.user,
+ if trans.app.security_agent.allow_action( user,
+ roles,
trans.app.security_agent.permitted_actions.LIBRARY_MANAGE,
library_item=ldda ) and \
- trans.app.security_agent.allow_action( trans.user,
+ trans.app.security_agent.allow_action( user,
+ roles,
trans.app.security_agent.permitted_actions.DATASET_MANAGE_PERMISSIONS,
dataset=ldda.dataset ):
# Ensure that the permissions across all library items are identical, otherwise we can't update them together.
@@ -741,10 +785,12 @@
library_id=library_id,
msg=msg,
messagetype=messagetype )
- if trans.app.security_agent.allow_action( trans.user,
+ if trans.app.security_agent.allow_action( user,
+ roles,
trans.app.security_agent.permitted_actions.LIBRARY_ADD,
library_item=folder ) or \
- ( replace_dataset and trans.app.security_agent.allow_action( trans.user,
+ ( replace_dataset and trans.app.security_agent.allow_action( user,
+ roles,
trans.app.security_agent.permitted_actions.LIBRARY_MODIFY,
library_item=replace_dataset ) ):
if params.get( 'new_dataset_button', False ):
@@ -769,7 +815,8 @@
# Since permissions on all LibraryDatasetDatasetAssociations must be the same at this point, we only need
# to check one of them to see if the current user can manage permissions on them.
check_ldda = trans.app.model.LibraryDatasetDatasetAssociation.get( ldda_id_list[0] )
- if trans.app.security_agent.allow_action( trans.user,
+ if trans.app.security_agent.allow_action( user,
+ roles,
trans.app.security_agent.permitted_actions.LIBRARY_MANAGE,
library_item=check_ldda ):
if replace_dataset:
@@ -892,7 +939,13 @@
# Since permissions on all LibraryDatasetDatasetAssociations must be the same at this point, we only need
# to check one of them to see if the current user can manage permissions on them.
check_ldda = trans.app.model.LibraryDatasetDatasetAssociation.get( ldda_id_list[0] )
- if trans.app.security_agent.allow_action( trans.user,
+ user = trans.user
+ if user:
+ roles = user.all_roles()
+ else:
+ roles = None
+ if trans.app.security_agent.allow_action( user,
+ roles,
trans.app.security_agent.permitted_actions.LIBRARY_MANAGE,
library_item=check_ldda ):
if replace_dataset:
@@ -957,6 +1010,11 @@
id=library_id,
msg=util.sanitize_text( msg ),
messagetype='error' ) )
+ user = trans.user
+ if user:
+ roles = user.all_roles()
+ else:
+ roles = None
if action == 'new':
if params.new == 'submitted':
new_folder = trans.app.model.LibraryFolder( name=util.restore_text( params.name ),
@@ -994,7 +1052,8 @@
else:
widgets = []
if params.get( 'rename_folder_button', False ):
- if trans.app.security_agent.allow_action( trans.user,
+ if trans.app.security_agent.allow_action( user,
+ roles,
trans.app.security_agent.permitted_actions.LIBRARY_MODIFY,
library_item=folder ):
old_name = folder.name
@@ -1037,7 +1096,8 @@
elif action == 'permissions':
if params.get( 'update_roles_button', False ):
# The user clicked the Save button on the 'Associate With Roles' form
- if trans.app.security_agent.allow_action( trans.user,
+ if trans.app.security_agent.allow_action( user,
+ roles,
trans.app.security_agent.permitted_actions.LIBRARY_MANAGE,
library_item=folder ):
permissions = {}
@@ -1162,12 +1222,24 @@
msg=util.sanitize_text( msg ),
messagetype='done' ) )
-
-def get_authorized_libs(trans, user):
- all_libraries = trans.app.model.Library.filter(trans.app.model.Library.table.c.deleted == False).order_by(trans.app.model.Library.name).all()
+def get_authorized_libs( trans, user ):
+ # TODO: this is a mis-named function - the name should reflect the authorization policy
+ # If user is not authenticated, this method should not even be called. Also, it looks
+ # like all that is using this is the new request stuff, so it should be placed there.
+ if not user:
+ return []
+ roles = user.all_roles()
+ all_libraries = trans.app.model.Library.filter( trans.app.model.Library.table.c.deleted == False ) \
+ .order_by( trans.app.model.Library.name ).all()
authorized_libraries = []
for library in all_libraries:
- if trans.app.security_agent.allow_action(user, trans.app.security_agent.permitted_actions.LIBRARY_ADD, library_item=library) \
- or trans.app.security_agent.allow_action(user, trans.app.security_agent.permitted_actions.LIBRARY_MODIFY, library_item=library):
- authorized_libraries.append(library)
- return authorized_libraries
\ No newline at end of file
+ if trans.app.security_agent.allow_action( user,
+ roles,
+ trans.app.security_agent.permitted_actions.LIBRARY_ADD,
+ library_item=library ) \
+ or trans.app.security_agent.allow_action( user,
+ roles,
+ trans.app.security_agent.permitted_actions.LIBRARY_MODIFY,
+ library_item=library ):
+ authorized_libraries.append( library )
+ return authorized_libraries
diff -r 36f438ce1f82 -r cc4944a62b66 lib/galaxy/web/controllers/root.py
--- a/lib/galaxy/web/controllers/root.py Fri Aug 28 15:59:16 2009 -0400
+++ b/lib/galaxy/web/controllers/root.py Fri Aug 28 16:52:58 2009 -0400
@@ -152,7 +152,15 @@
except:
return "Dataset id '%s' is invalid" %str( id )
if data:
- if trans.app.security_agent.allow_action( trans.user, data.permitted_actions.DATASET_ACCESS, dataset = data ):
+ user = trans.user
+ if user:
+ roles = user.all_roles
+ else:
+ roles = None
+ if trans.app.security_agent.allow_action( user,
+ roles,
+ data.permitted_actions.DATASET_ACCESS,
+ dataset = data.dataset ):
mime = trans.app.datatypes_registry.get_mimetype_by_extension( data.extension.lower() )
trans.response.set_content_type(mime)
if tofile:
@@ -184,7 +192,15 @@
if data:
child = data.get_child_by_designation( designation )
if child:
- if trans.app.security_agent.allow_action( trans.user, child.permitted_actions.DATASET_ACCESS, dataset = child ):
+ user = trans.user
+ if user:
+ roles = user.all_roles
+ else:
+ roles = None
+ if trans.app.security_agent.allow_action( user,
+ roles,
+ child.permitted_actions.DATASET_ACCESS,
+ dataset = child ):
return self.display( trans, id=child.id, tofile=tofile, toext=toext )
else:
return "You are not privileged to access this dataset."
@@ -200,11 +216,21 @@
if 'authz_method' in kwd:
authz_method = kwd['authz_method']
if data:
- if authz_method == 'rbac' and trans.app.security_agent.allow_action( trans.user, data.permitted_actions.DATASET_ACCESS, dataset = data ):
+ user = trans.user
+ if user:
+ roles = user.all_roles
+ else:
+ roles = None
+ if authz_method == 'rbac' and trans.app.security_agent.allow_action( user,
+ roles,
+ data.permitted_actions.DATASET_ACCESS,
+ dataset = data ):
trans.response.set_content_type( data.get_mime() )
trans.log_event( "Formatted dataset id %s for display at %s" % ( str( id ), display_app ) )
return data.as_display_type( display_app, **kwd )
- elif authz_method == 'display_at' and trans.app.host_security_agent.allow_action( trans.request.remote_addr, data.permitted_actions.DATASET_ACCESS, dataset = data ):
+ elif authz_method == 'display_at' and trans.app.host_security_agent.allow_action( trans.request.remote_addr,
+ data.permitted_actions.DATASET_ACCESS,
+ dataset = data ):
trans.response.set_content_type( data.get_mime() )
return data.as_display_type( display_app, **kwd )
else:
@@ -247,7 +273,15 @@
return trans.show_error_message( "Problem retrieving dataset." )
if id is not None and data.history.user is not None and data.history.user != trans.user:
return trans.show_error_message( "This instance of a dataset (%s) in a history does not belong to you." % ( data.id ) )
- if trans.app.security_agent.allow_action( trans.user, data.permitted_actions.DATASET_ACCESS, dataset=data ):
+ user = trans.user
+ if user:
+ roles = user.all_roles()
+ else:
+ roles = None
+ if trans.app.security_agent.allow_action( user,
+ roles,
+ data.permitted_actions.DATASET_ACCESS,
+ dataset=data.dataset ):
if data.state == trans.model.Dataset.states.UPLOAD:
return trans.show_error_message( "Please wait until this dataset finishes uploading before attempting to edit its metadata." )
params = util.Params( kwd, safe=False )
@@ -313,7 +347,10 @@
elif params.update_roles_button:
if not trans.user:
return trans.show_error_message( "You must be logged in if you want to change permissions." )
- if trans.app.security_agent.allow_action( trans.user, data.dataset.permitted_actions.DATASET_MANAGE_PERMISSIONS, dataset = data.dataset ):
+ if trans.app.security_agent.allow_action( user,
+ roles,
+ data.dataset.permitted_actions.DATASET_MANAGE_PERMISSIONS,
+ dataset = data.dataset ):
permissions = {}
for k, v in trans.app.model.Dataset.permitted_actions.items():
in_roles = params.get( k + '_in', [] )
diff -r 36f438ce1f82 -r cc4944a62b66 templates/admin/library/browse_library.mako
--- a/templates/admin/library/browse_library.mako Fri Aug 28 15:59:16 2009 -0400
+++ b/templates/admin/library/browse_library.mako Fri Aug 28 16:52:58 2009 -0400
@@ -138,12 +138,12 @@
%if show_deleted:
<%
parent_folders = folder.activatable_folders
- parent_datasets = folder.activatable_datasets
+ parent_datasets = folder.activatable_library_datasets
%>
%else:
<%
parent_folders = folder.active_folders
- parent_datasets = folder.active_datasets
+ parent_datasets = folder.active_library_datasets
%>
%endif
%for folder in name_sorted( parent_folders ):
diff -r 36f438ce1f82 -r cc4944a62b66 templates/dataset/edit_attributes.mako
--- a/templates/dataset/edit_attributes.mako Fri Aug 28 15:59:16 2009 -0400
+++ b/templates/dataset/edit_attributes.mako Fri Aug 28 16:52:58 2009 -0400
@@ -3,6 +3,13 @@
<%def name="title()">${_('Edit Dataset Attributes')}</%def>
+<%
+ user = trans.user
+ if user:
+ user_roles = user.all_roles()
+ else:
+ user_roles = None
+%>
<%def name="datatype( dataset, datatypes )">
<select name="datatype">
@@ -134,9 +141,9 @@
</div>
<p />
-%if trans.app.security_agent.allow_action( trans.user, data.permitted_actions.DATASET_MANAGE_PERMISSIONS, dataset = data ):
+%if trans.app.security_agent.allow_action( user, user_roles, data.permitted_actions.DATASET_MANAGE_PERMISSIONS, dataset=data.dataset ):
<%namespace file="/dataset/security_common.mako" import="render_permission_form" />
- ${render_permission_form( data.dataset, data.name, h.url_for( controller='root', action='edit', id=data.id ), trans.user.all_roles() )}
+ ${render_permission_form( data.dataset, data.name, h.url_for( controller='root', action='edit', id=data.id ), user_roles )}
%elif trans.user:
<div class="toolForm">
<div class="toolFormTitle">View Permissions</div>
diff -r 36f438ce1f82 -r cc4944a62b66 templates/library/browse_library.mako
--- a/templates/library/browse_library.mako Fri Aug 28 15:59:16 2009 -0400
+++ b/templates/library/browse_library.mako Fri Aug 28 16:52:58 2009 -0400
@@ -1,6 +1,15 @@
<%inherit file="/base.mako"/>
<%namespace file="/message.mako" import="render_msg" />
-<% from galaxy import util %>
+<%
+ from galaxy import util
+ from time import strftime
+
+ user = trans.user
+ if user:
+ roles = user.all_roles()
+ else:
+ roles = None
+%>
<%def name="title()">Browse data library</%def>
<%def name="stylesheets()">
@@ -110,14 +119,14 @@
<a href="${h.url_for( controller='library', action='library_dataset_dataset_association', library_id=library.id, folder_id=library_dataset.folder.id, id=ldda.id, info=True )}"><b>${ldda.name[:60]}</b></a>
<a id="dataset-${ldda.id}-popup" class="popup-arrow" style="display: none;">▼</a>
<div popupmenu="dataset-${ldda.id}-popup">
- %if trans.app.security_agent.allow_action( trans.user, trans.app.security_agent.permitted_actions.LIBRARY_MODIFY, library_item=ldda.library_dataset ):
+ %if trans.app.security_agent.allow_action( user, roles, trans.app.security_agent.permitted_actions.LIBRARY_MODIFY, library_item=ldda.library_dataset ):
<a class="action-button" href="${h.url_for( controller='library', action='library_dataset_dataset_association', library_id=library.id, folder_id=library_dataset.folder.id, id=ldda.id, edit_info=True )}">Edit this dataset's information</a>
%else:
<a class="action-button" href="${h.url_for( controller='library', action='library_dataset_dataset_association', library_id=library.id, folder_id=library_dataset.folder.id, id=ldda.id, information=True )}">View this dataset's information</a>
%endif
- %if trans.app.security_agent.allow_action( trans.user, trans.app.security_agent.permitted_actions.DATASET_MANAGE_PERMISSIONS, dataset=ldda.dataset ) and trans.app.security_agent.allow_action( trans.user, trans.app.security_agent.permitted_actions.LIBRARY_MANAGE, library_item=ldda.library_dataset ):
+ %if trans.app.security_agent.allow_action( user, roles, trans.app.security_agent.permitted_actions.DATASET_MANAGE_PERMISSIONS, dataset=ldda.dataset ) and trans.app.security_agent.allow_action( user, roles, trans.app.security_agent.permitted_actions.LIBRARY_MANAGE, library_item=ldda.library_dataset ):
<a class="action-button" href="${h.url_for( controller='library', action='library_dataset_dataset_association', library_id=library.id, folder_id=library_dataset.folder.id, id=ldda.id, permissions=True )}">Edit this dataset's permissions</a>
- %if current_version and trans.app.security_agent.allow_action( trans.user, trans.app.security_agent.permitted_actions.LIBRARY_MODIFY, library_item=ldda.library_dataset ):
+ %if current_version and trans.app.security_agent.allow_action( user, roles, trans.app.security_agent.permitted_actions.LIBRARY_MODIFY, library_item=ldda.library_dataset ):
<a class="action-button" href="${h.url_for( controller='library', action='library_dataset_dataset_association', library_id=library.id, folder_id=library_dataset.folder.id, replace_id=library_dataset.id )}">Upload a new version of this dataset</a>
%endif
%endif
@@ -126,24 +135,26 @@
<a class="action-button" href="${h.url_for( controller='library', action='download_dataset_from_folder', id=ldda.id, library_id=library.id )}">Download this dataset</a>
%endif
</div>
-
</td>
<td>${ldda.message}</td>
<td>${uploaded_by}</td>
<td>${ldda.create_time.strftime( "%Y-%m-%d" )}</td>
- </tr>
-
+ </tr>
<%
my_row = row_counter.count
row_counter.increment()
%>
</%def>
-
<%def name="render_folder( folder, folder_pad, created_ldda_ids, library_id, parent=None, row_counter=None )">
<%
def show_folder():
- if trans.app.security_agent.check_folder_contents( trans.user, folder ) or trans.app.security_agent.show_library_item( trans.user, folder ):
+ ## TODO: instead of calling check_folder_contents(), which we've already done prior to getting here,
+ ## add a new method that will itself call check_folder_contents() and build a list of accessible folders
+ ## for each library - this should improve performance dor large libraries where the current user can only
+ ## access a small number of folders.
+ if trans.app.security_agent.check_folder_contents( user, roles, folder ) or \
+ trans.app.security_agent.show_library_item( user, roles, folder ):
return True
return False
if not show_folder:
@@ -179,21 +190,21 @@
%endif
<a id="folder_img-${folder.id}-popup" class="popup-arrow" style="display: none;">▼</a>
<div popupmenu="folder_img-${folder.id}-popup">
- %if trans.app.security_agent.allow_action( trans.user, trans.app.security_agent.permitted_actions.LIBRARY_ADD, library_item=folder ):
+ %if trans.app.security_agent.allow_action( user, roles, trans.app.security_agent.permitted_actions.LIBRARY_ADD, library_item=folder ):
<a class="action-button" href="${h.url_for( controller='library', action='library_dataset_dataset_association', library_id=library_id, folder_id=folder.id )}">Add datasets to this folder</a>
<a class="action-button" href="${h.url_for( controller='library', action='folder', new=True, id=folder.id, library_id=library_id )}">Create a new sub-folder in this folder</a>
%endif
- %if trans.app.security_agent.allow_action( trans.user, trans.app.security_agent.permitted_actions.LIBRARY_MODIFY, library_item=folder ):
+ %if trans.app.security_agent.allow_action( user, roles, trans.app.security_agent.permitted_actions.LIBRARY_MODIFY, library_item=folder ):
<a class="action-button" href="${h.url_for( controller='library', action='folder', information=True, id=folder.id, library_id=library_id )}">Edit this folder's information</a>
%else:
<a class="action-button" href="${h.url_for( controller='library', action='folder', information=True, id=folder.id, library_id=library_id )}">View this folder's information</a>
%endif
%if forms and not folder.info_association:
- %if trans.app.security_agent.allow_action( trans.user, trans.app.security_agent.permitted_actions.LIBRARY_ADD, library_item=library ):
+ %if trans.app.security_agent.allow_action( user, roles, trans.app.security_agent.permitted_actions.LIBRARY_ADD, library_item=library ):
<a class="action-button" href="${h.url_for( controller='library', action='info_template', library_id=library.id, add=True )}">Add an information template to this folder</a>
%endif
%endif
- %if trans.app.security_agent.allow_action( trans.user, trans.app.security_agent.permitted_actions.LIBRARY_MANAGE, library_item=folder ):
+ %if trans.app.security_agent.allow_action( user, roles, trans.app.security_agent.permitted_actions.LIBRARY_MANAGE, library_item=folder ):
<a class="action-button" href="${h.url_for( controller='library', action='folder', permissions=True, id=folder.id, library_id=library_id )}">Edit this folder's permissions</a>
%endif
</div>
@@ -208,11 +219,11 @@
%for child_folder in name_sorted( folder.active_folders ):
${render_folder( child_folder, pad, created_ldda_ids, library_id, my_row, row_counter )}
%endfor
- %for library_dataset in name_sorted( folder.active_datasets ):
+ %for library_dataset in name_sorted( folder.active_library_datasets ):
<%
selected = created_ldda_ids and library_dataset.library_dataset_dataset_association.id in created_ldda_ids
%>
- %if trans.app.security_agent.allow_action( trans.user, trans.app.security_agent.permitted_actions.DATASET_ACCESS, dataset=library_dataset.library_dataset_dataset_association.dataset ):
+ %if trans.app.security_agent.allow_action( user, roles, trans.app.security_agent.permitted_actions.DATASET_ACCESS, dataset=library_dataset.library_dataset_dataset_association.dataset ):
${render_dataset( library_dataset, selected, library, pad, my_row, row_counter )}
%endif
%endfor
@@ -221,7 +232,7 @@
<h2>Data Library “${library.name}”</h2>
<ul class="manage-table-actions">
- %if trans.app.security_agent.allow_action( trans.user, trans.app.security_agent.permitted_actions.LIBRARY_ADD, library_item=library ):
+ %if trans.app.security_agent.allow_action( user, roles, trans.app.security_agent.permitted_actions.LIBRARY_ADD, library_item=library ):
%if not deleted:
<li>
<a class="action-button" href="${h.url_for( controller='library', action='library_dataset_dataset_association', library_id=library.id, folder_id=library.root_folder.id )}"><span>Add datasets to this library</span></a>
@@ -231,17 +242,17 @@
</li>
%endif
%endif
- %if trans.app.security_agent.allow_action( trans.user, trans.app.security_agent.permitted_actions.LIBRARY_MODIFY, library_item=library ):
+ %if trans.app.security_agent.allow_action( user, roles, trans.app.security_agent.permitted_actions.LIBRARY_MODIFY, library_item=library ):
<li><a class="action-button" href="${h.url_for( controller='library', action='library', information=True, id=library.id )}">Edit this library's information</a></li>
%else:
<li><a class="action-button" href="${h.url_for( controller='library', action='library', information=True, id=library.id )}">View this library's information</a></li>
%endif
%if forms and not library.info_association:
- %if trans.app.security_agent.allow_action( trans.user, trans.app.security_agent.permitted_actions.LIBRARY_ADD, library_item=library ):
+ %if trans.app.security_agent.allow_action( user, roles, trans.app.security_agent.permitted_actions.LIBRARY_ADD, library_item=library ):
<a class="action-button" href="${h.url_for( controller='library', action='info_template', library_id=library.id, add=True )}">Add an information template to this library</a>
%endif
%endif
- %if trans.app.security_agent.allow_action( trans.user, trans.app.security_agent.permitted_actions.LIBRARY_MANAGE, library_item=library ):
+ %if trans.app.security_agent.allow_action( user, roles, trans.app.security_agent.permitted_actions.LIBRARY_MANAGE, library_item=library ):
<li><a class="action-button" href="${h.url_for( controller='library', action='library', permissions=True, id=library.id )}">Edit this library's permissions</a></li>
%endif
</ul>
@@ -265,7 +276,7 @@
</thead>
</tr>
<% row_counter = RowCounter() %>
- ${render_folder( library.root_folder, 0, created_ldda_ids, library.id, Nonw, row_counter )}
+ ${render_folder( library.root_folder, 0, created_ldda_ids, library.id, None, row_counter )}
<tfoot>
<tr>
<td colspan="4" style="padding-left: 42px;">
diff -r 36f438ce1f82 -r cc4944a62b66 templates/library/common.mako
--- a/templates/library/common.mako Fri Aug 28 15:59:16 2009 -0400
+++ b/templates/library/common.mako Fri Aug 28 16:52:58 2009 -0400
@@ -1,65 +1,3 @@
-<% from time import strftime %>
-
-<%def name="render_dataset( library_dataset, selected, library )">
- <%
- ## The received data must always be a LibraryDataset object, but the object id passed to methods from the drop down menu
- ## should be the underlying ldda id to prevent id collision ( which could happen when displaying children, which are always
- ## lddas ). We also need to make sure we're displaying the latest version of this library_dataset, so we display the attributes
- ## from the ldda.
- ldda = library_dataset.library_dataset_dataset_association
- if ldda.user:
- uploaded_by = ldda.user.email
- else:
- uploaded_by = 'anonymous'
- if ldda == ldda.library_dataset.library_dataset_dataset_association:
- current_version = True
- else:
- current_version = False
- %>
- <div class="historyItemWrapper historyItem historyItem-${ldda.state}" id="libraryItem-${ldda.id}">
- ## Header row for library items (name, state, action buttons)
- <div class="historyItemTitleBar">
- <table cellspacing="0" cellpadding="0" border="0" width="100%">
- <tr>
- <td width="*">
- %if selected:
- <input type="checkbox" name="ldda_ids" value="${ldda.id}" checked/>
- %else:
- <input type="checkbox" name="ldda_ids" value="${ldda.id}"/>
- %endif
- <a href="${h.url_for( controller='library', action='library_dataset_dataset_association', library_id=library.id, folder_id=library_dataset.folder.id, id=ldda.id, info=True )}"><b>${ldda.name[:60]}</b></a>
- <a id="dataset-${ldda.id}-popup" class="popup-arrow" style="display: none;">▼</a>
- <div popupmenu="dataset-${ldda.id}-popup">
- %if trans.app.security_agent.allow_action( trans.user, trans.app.security_agent.permitted_actions.LIBRARY_MODIFY, library_item=ldda.library_dataset ):
- <a class="action-button" href="${h.url_for( controller='library', action='library_dataset_dataset_association', library_id=library.id, folder_id=library_dataset.folder.id, id=ldda.id, edit_info=True )}">Edit this dataset's information</a>
- %else:
- <a class="action-button" href="${h.url_for( controller='library', action='library_dataset_dataset_association', library_id=library.id, folder_id=library_dataset.folder.id, id=ldda.id, information=True )}">View this dataset's information</a>
- %endif
- ## We're disabling the ability to add templates at the LDDA and LibraryDataset level, but will leave this here for possible future use
- ##%if trans.app.security_agent.allow_action( trans.user, trans.app.security_agent.permitted_actions.LIBRARY_ADD, library_item=ldda.library_dataset ):
- ## <a class="action-button" href="${h.url_for( controller='library', action='info_template', library_id=library.id, library_dataset_id=library_dataset.id, new_template=True )}">Add an information template to this dataset</a>
- ##%endif
- %if trans.app.security_agent.allow_action( trans.user, trans.app.security_agent.permitted_actions.DATASET_MANAGE_PERMISSIONS, dataset=ldda.dataset ) and trans.app.security_agent.allow_action( trans.user, trans.app.security_agent.permitted_actions.LIBRARY_MANAGE, library_item=ldda.library_dataset ):
- <a class="action-button" href="${h.url_for( controller='library', action='library_dataset_dataset_association', library_id=library.id, folder_id=library_dataset.folder.id, id=ldda.id, permissions=True )}">Edit this dataset's permissions</a>
- %if current_version and trans.app.security_agent.allow_action( trans.user, trans.app.security_agent.permitted_actions.LIBRARY_MODIFY, library_item=ldda.library_dataset ):
- <a class="action-button" href="${h.url_for( controller='library', action='library_dataset_dataset_association', library_id=library.id, folder_id=library_dataset.folder.id, replace_id=library_dataset.id )}">Upload a new version of this dataset</a>
- %endif
- %endif
- %if ldda.has_data:
- <a class="action-button" href="${h.url_for( controller='library', action='datasets', library_id=library.id, ldda_ids=str( ldda.id ), do_action='add' )}">Import this dataset into your current history</a>
- <a class="action-button" href="${h.url_for( controller='library', action='download_dataset_from_folder', id=ldda.id, library_id=library.id )}">Download this dataset</a>
- %endif
- </div>
- </td>
- <td width="500">${ldda.message}</td>
- <td width="150">${uploaded_by}</td>
- <td width="60">${ldda.create_time.strftime( "%Y-%m-%d" )}</td>
- </tr>
- </table>
- </div>
- </div>
-</%def>
-
<%def name="render_template_info( library_item, library_id, widgets, editable=True )">
<%
library_item_type = 'unknown type'
@@ -76,13 +14,18 @@
elif isinstance( library_item, trans.app.model.LibraryDatasetDatasetAssociation ):
library_item_type = 'library_dataset_dataset_association'
library_item_desc = 'library dataset'
+ user = trans.user
+ if user:
+ roles = user.all_roles()
+ else:
+ roles = None
%>
%if widgets:
<p/>
<div class="toolForm">
<div class="toolFormTitle">Other information about ${library_item_desc} ${library_item.name}</div>
<div class="toolFormBody">
- %if editable and trans.app.security_agent.allow_action( trans.user, trans.app.security_agent.permitted_actions.LIBRARY_MODIFY, library_item=library_item ):
+ %if editable and trans.app.security_agent.allow_action( user, roles, trans.app.security_agent.permitted_actions.LIBRARY_MODIFY, library_item=library_item ):
<form name="edit_info" action="${h.url_for( controller='library', action='edit_template_info', library_id=library_id, num_widgets=len( widgets ) )}" method="post">
<input type="hidden" name="library_item_id" value="${library_item.id}"/>
<input type="hidden" name="library_item_type" value="${library_item_type}"/>
diff -r 36f438ce1f82 -r cc4944a62b66 templates/library/folder_info.mako
--- a/templates/library/folder_info.mako Fri Aug 28 15:59:16 2009 -0400
+++ b/templates/library/folder_info.mako Fri Aug 28 16:52:58 2009 -0400
@@ -1,6 +1,14 @@
<%inherit file="/base.mako"/>
<%namespace file="/message.mako" import="render_msg" />
<%namespace file="/library/common.mako" import="render_template_info" />
+
+<%
+ user = trans.user
+ if user:
+ roles = user.all_roles()
+ else:
+ roles = None
+%>
<br/><br/>
<ul class="manage-table-actions">
@@ -16,7 +24,7 @@
<div class="toolForm">
<div class="toolFormTitle">Edit folder name and description</div>
<div class="toolFormBody">
- %if trans.app.security_agent.allow_action( trans.user, trans.app.security_agent.permitted_actions.LIBRARY_MODIFY, library_item=folder ):
+ %if trans.app.security_agent.allow_action( user, roles, trans.app.security_agent.permitted_actions.LIBRARY_MODIFY, library_item=folder ):
<form name="folder" action="${h.url_for( controller='library', action='folder', rename=True, id=folder.id, library_id=library_id )}" method="post" >
<div class="form-row">
<label>Name:</label>
diff -r 36f438ce1f82 -r cc4944a62b66 templates/library/folder_permissions.mako
--- a/templates/library/folder_permissions.mako Fri Aug 28 15:59:16 2009 -0400
+++ b/templates/library/folder_permissions.mako Fri Aug 28 16:52:58 2009 -0400
@@ -1,6 +1,14 @@
<%inherit file="/base.mako"/>
<%namespace file="/message.mako" import="render_msg" />
<%namespace file="/dataset/security_common.mako" import="render_permission_form" />
+
+<%
+ user = trans.user
+ if user:
+ roles = user.all_roles()
+ else:
+ roles = None
+%>
<br/><br/>
<ul class="manage-table-actions">
@@ -13,6 +21,6 @@
${render_msg( msg, messagetype )}
%endif
-%if trans.app.security_agent.allow_action( trans.user, trans.app.security_agent.permitted_actions.LIBRARY_MANAGE, library_item=folder ):
+%if trans.app.security_agent.allow_action( user, roles, trans.app.security_agent.permitted_actions.LIBRARY_MANAGE, library_item=folder ):
${render_permission_form( folder, folder.name, h.url_for( controller='library', action='folder', id=folder.id, library_id=library_id, permissions=True ), trans.user.all_roles() )}
%endif
diff -r 36f438ce1f82 -r cc4944a62b66 templates/library/ldda_edit_info.mako
--- a/templates/library/ldda_edit_info.mako Fri Aug 28 15:59:16 2009 -0400
+++ b/templates/library/ldda_edit_info.mako Fri Aug 28 16:52:58 2009 -0400
@@ -2,6 +2,14 @@
<%namespace file="/message.mako" import="render_msg" />
<%namespace file="/library/common.mako" import="render_template_info" />
<% from galaxy import util %>
+
+<%
+ user = trans.user
+ if user:
+ roles = user.all_roles()
+ else:
+ roles = None
+%>
%if ldda == ldda.library_dataset.library_dataset_dataset_association:
<b><i>This is the latest version of this library dataset</i></b>
@@ -32,7 +40,7 @@
</select>
</%def>
-%if trans.app.security_agent.allow_action( trans.user, trans.app.security_agent.permitted_actions.LIBRARY_MODIFY, library_item=ldda.library_dataset ):
+%if trans.app.security_agent.allow_action( user, roles, trans.app.security_agent.permitted_actions.LIBRARY_MODIFY, library_item=ldda.library_dataset ):
<div class="toolForm">
<div class="toolFormTitle">Edit attributes of ${ldda.name}</div>
<div class="toolFormBody">
diff -r 36f438ce1f82 -r cc4944a62b66 templates/library/ldda_info.mako
--- a/templates/library/ldda_info.mako Fri Aug 28 15:59:16 2009 -0400
+++ b/templates/library/ldda_info.mako Fri Aug 28 16:52:58 2009 -0400
@@ -8,6 +8,11 @@
current_version = True
else:
current_version = False
+ user = trans.user
+ if user:
+ roles = user.all_roles()
+ else:
+ roles = None
%>
%if current_version:
@@ -39,15 +44,15 @@
Information about ${ldda.name}
<a id="dataset-${ldda.id}-popup" class="popup-arrow" style="display: none;">▼</a>
<div popupmenu="dataset-${ldda.id}-popup">
- %if trans.app.security_agent.allow_action( trans.user, trans.app.security_agent.permitted_actions.LIBRARY_MODIFY, library_item=ldda.library_dataset ):
+ %if trans.app.security_agent.allow_action( user, roles, trans.app.security_agent.permitted_actions.LIBRARY_MODIFY, library_item=ldda.library_dataset ):
<a class="action-button" href="${h.url_for( controller='library', action='library_dataset_dataset_association', library_id=library_id, folder_id=ldda.library_dataset.folder.id, id=ldda.id, edit_info=True )}">Edit this dataset's information</a>
%else:
<a class="action-button" href="${h.url_for( controller='library', action='library_dataset_dataset_association', library_id=library_id, folder_id=ldda.library_dataset.folder.id, id=ldda.id, information=True )}">View this dataset's information</a>
%endif
- %if trans.app.security_agent.allow_action( trans.user, trans.app.security_agent.permitted_actions.DATASET_MANAGE_PERMISSIONS, dataset=ldda.dataset ) and trans.app.security_agent.allow_action( trans.user, trans.app.security_agent.permitted_actions.LIBRARY_MANAGE, library_item=ldda.library_dataset ):
+ %if trans.app.security_agent.allow_action( user, roles, trans.app.security_agent.permitted_actions.DATASET_MANAGE_PERMISSIONS, dataset=ldda.dataset ) and trans.app.security_agent.allow_action( user, roles, trans.app.security_agent.permitted_actions.LIBRARY_MANAGE, library_item=ldda.library_dataset ):
<a class="action-button" href="${h.url_for( controller='library', action='library_dataset_dataset_association', library_id=library_id, folder_id=ldda.library_dataset.folder.id, id=ldda.id, permissions=True )}">Edit this dataset's permissions</a>
%endif
- %if current_version and trans.app.security_agent.allow_action( trans.user, trans.app.security_agent.permitted_actions.LIBRARY_MODIFY, library_item=ldda.library_dataset ):
+ %if current_version and trans.app.security_agent.allow_action( user, roles, trans.app.security_agent.permitted_actions.LIBRARY_MODIFY, library_item=ldda.library_dataset ):
<a class="action-button" href="${h.url_for( controller='library', action='library_dataset_dataset_association', library_id=library_id, folder_id=ldda.library_dataset.folder.id, replace_id=ldda.library_dataset.id )}">Upload a new version of this dataset</a>
%endif
%if ldda.has_data:
@@ -92,6 +97,8 @@
<div><pre id="peek${ldda.id}" class="peek">${ldda.display_peek()}</pre></div>
%endif
## Recurse for child datasets
+ ## TODO: eliminate this - child datasets are deprecated, and where does
+ ## render_dataset() come from anyway - it's not imported!
%if len( ldda.visible_children ) > 0:
<div>
There are ${len( ldda.visible_children )} secondary datasets.
diff -r 36f438ce1f82 -r cc4944a62b66 templates/library/library_dataset_info.mako
--- a/templates/library/library_dataset_info.mako Fri Aug 28 15:59:16 2009 -0400
+++ b/templates/library/library_dataset_info.mako Fri Aug 28 16:52:58 2009 -0400
@@ -1,6 +1,14 @@
<%inherit file="/base.mako"/>
<%namespace file="/message.mako" import="render_msg" />
<%namespace file="/library/common.mako" import="render_template_info" />
+
+<%
+ user = trans.user
+ if user:
+ roles = user.all_roles()
+ else:
+ roles = None
+%>
%if library_dataset == library_dataset.library_dataset_dataset_association.library_dataset:
<b><i>This is the latest version of this library dataset</i></b>
@@ -19,7 +27,7 @@
${render_msg( msg, messagetype )}
%endif
-%if trans.app.security_agent.allow_action( trans.user, trans.app.security_agent.permitted_actions.LIBRARY_MODIFY, library_item=library_dataset ):
+%if trans.app.security_agent.allow_action( user, roles, trans.app.security_agent.permitted_actions.LIBRARY_MODIFY, library_item=library_dataset ):
<div class="toolForm">
<div class="toolFormTitle">Edit attributes of ${library_dataset.name}</div>
<div class="toolFormBody">
diff -r 36f438ce1f82 -r cc4944a62b66 templates/library/library_dataset_permissions.mako
--- a/templates/library/library_dataset_permissions.mako Fri Aug 28 15:59:16 2009 -0400
+++ b/templates/library/library_dataset_permissions.mako Fri Aug 28 16:52:58 2009 -0400
@@ -1,6 +1,14 @@
<%inherit file="/base.mako"/>
<%namespace file="/message.mako" import="render_msg" />
<%namespace file="/dataset/security_common.mako" import="render_permission_form" />>
+
+<%
+ user = trans.user
+ if user:
+ user_roles = user.all_roles()
+ else:
+ user_roles = None
+%>
%if library_dataset == library_dataset.library_dataset_dataset_association.library_dataset:
<b><i>This is the latest version of this library dataset</i></b>
@@ -19,7 +27,7 @@
${render_msg( msg, messagetype )}
%endif
-%if trans.app.security_agent.allow_action( trans.user, trans.app.security_agent.permitted_actions.LIBRARY_manage, library_item=library_dataset ):
+%if trans.app.security_agent.allow_action( user, user_roles, trans.app.security_agent.permitted_actions.LIBRARY_manage, library_item=library_dataset ):
<%
roles = trans.app.model.Role.filter( trans.app.model.Role.table.c.deleted==False ).order_by( trans.app.model.Role.table.c.name ).all()
%>
diff -r 36f438ce1f82 -r cc4944a62b66 templates/library/library_info.mako
--- a/templates/library/library_info.mako Fri Aug 28 15:59:16 2009 -0400
+++ b/templates/library/library_info.mako Fri Aug 28 16:52:58 2009 -0400
@@ -1,6 +1,14 @@
<%inherit file="/base.mako"/>
<%namespace file="/message.mako" import="render_msg" />
<%namespace file="/library/common.mako" import="render_template_info" />
+
+<%
+ user = trans.user
+ if user:
+ roles = user.all_roles()
+ else:
+ roles = None
+%>
<br/><br/>
<ul class="manage-table-actions">
@@ -13,7 +21,7 @@
${render_msg( msg, messagetype )}
%endif
-%if trans.app.security_agent.allow_action( trans.user, trans.app.security_agent.permitted_actions.LIBRARY_MODIFY, library_item=library ):
+%if trans.app.security_agent.allow_action( user, roles, trans.app.security_agent.permitted_actions.LIBRARY_MODIFY, library_item=library ):
<div class="toolForm">
<div class="toolFormTitle">Change library name and description</div>
<div class="toolFormBody">
diff -r 36f438ce1f82 -r cc4944a62b66 templates/library/library_permissions.mako
--- a/templates/library/library_permissions.mako Fri Aug 28 15:59:16 2009 -0400
+++ b/templates/library/library_permissions.mako Fri Aug 28 16:52:58 2009 -0400
@@ -1,6 +1,14 @@
<%inherit file="/base.mako"/>
<%namespace file="/message.mako" import="render_msg" />
<%namespace file="/dataset/security_common.mako" import="render_permission_form" />
+
+<%
+ user = trans.user
+ if user:
+ user_roles = user.all_roles()
+ else:
+ user_roles = None
+%>
<br/><br/>
<ul class="manage-table-actions">
@@ -13,7 +21,7 @@
${render_msg( msg, messagetype )}
%endif
-%if trans.app.security_agent.allow_action( trans.user, trans.app.security_agent.permitted_actions.LIBRARY_MANAGE, library_item=library ):
+%if trans.app.security_agent.allow_action( user, user_roles, trans.app.security_agent.permitted_actions.LIBRARY_MANAGE, library_item=library ):
<%
roles = trans.app.model.Role.filter( trans.app.model.Role.table.c.deleted==False ).order_by( trans.app.model.Role.table.c.name ).all()
%>
diff -r 36f438ce1f82 -r cc4944a62b66 templates/mobile/history/detail.mako
--- a/templates/mobile/history/detail.mako Fri Aug 28 15:59:16 2009 -0400
+++ b/templates/mobile/history/detail.mako Fri Aug 28 16:52:58 2009 -0400
@@ -36,8 +36,14 @@
<div class="secondary">
## Body for history items, extra info and actions, data "peek"
-
- %if not trans.app.security_agent.allow_action( trans.user, data.permitted_actions.DATASET_ACCESS, dataset = data.dataset ):
+ <%
+ user = trans.user
+ if user:
+ roles = user.all_roles()
+ else:
+ roles = None
+ %>
+ %if not trans.app.security_agent.allow_action( user, roles, data.permitted_actions.DATASET_ACCESS, dataset = data.dataset ):
<div>You do not have permission to view this dataset.</div>
%elif data_state == "queued":
<div>Job is waiting to run</div>
diff -r 36f438ce1f82 -r cc4944a62b66 templates/mobile/manage_library.mako
--- a/templates/mobile/manage_library.mako Fri Aug 28 15:59:16 2009 -0400
+++ b/templates/mobile/manage_library.mako Fri Aug 28 16:52:58 2009 -0400
@@ -3,11 +3,19 @@
<%namespace file="/dataset/security_common.mako" import="render_permission_form" />
<%namespace file="/library/common.mako" import="render_template_info" />
+<%
+ user = trans.user
+ if user:
+ roles = user.all_roles()
+ else:
+ roles = None
+%>
+
%if msg:
${render_msg( msg, messagetype )}
%endif
-%if trans.app.security_agent.allow_action( trans.user, trans.app.security_agent.permitted_actions.LIBRARY_MODIFY, library_item=library ):
+%if trans.app.security_agent.allow_action( user, roles, trans.app.security_agent.permitted_actions.LIBRARY_MODIFY, library_item=library ):
<div class="toolForm">
<div class="toolFormTitle">Change library name and description</div>
<div class="toolFormBody">
@@ -53,7 +61,7 @@
</div>
</div>
%endif
-%if trans.app.security_agent.allow_action( trans.user, trans.app.security_agent.permitted_actions.LIBRARY_MANAGE, library_item=library ):
+%if trans.app.security_agent.allow_action( user, roles, trans.app.security_agent.permitted_actions.LIBRARY_MANAGE, library_item=library ):
<%
roles = trans.app.model.Role.filter( trans.app.model.Role.table.c.deleted==False ).order_by( trans.app.model.Role.table.c.name ).all()
%>
diff -r 36f438ce1f82 -r cc4944a62b66 templates/root/history_common.mako
--- a/templates/root/history_common.mako Fri Aug 28 15:59:16 2009 -0400
+++ b/templates/root/history_common.mako Fri Aug 28 16:52:58 2009 -0400
@@ -2,12 +2,17 @@
## Render the dataset `data` as history item, using `hid` as the displayed id
<%def name="render_dataset( data, hid, show_deleted_on_refresh = False )">
<%
- if data.state in ['no state','',None]:
- data_state = "queued"
- else:
- data_state = data.state
+ if data.state in ['no state','',None]:
+ data_state = "queued"
+ else:
+ data_state = data.state
+ user = trans.user
+ if user:
+ roles = user.all_roles()
+ else:
+ roles = None
%>
- %if not trans.app.security_agent.allow_action( trans.user, data.permitted_actions.DATASET_ACCESS, dataset = data.dataset ):
+ %if not trans.app.security_agent.allow_action( user, roles, data.permitted_actions.DATASET_ACCESS, dataset = data.dataset ):
<div class="historyItemWrapper historyItem historyItem-${data_state} historyItem-noPermission" id="historyItem-${data.id}">
%else:
<div class="historyItemWrapper historyItem historyItem-${data_state}" id="historyItem-${data.id}">
@@ -41,7 +46,7 @@
## Body for history items, extra info and actions, data "peek"
<div id="info${data.id}" class="historyItemBody">
- %if not trans.app.security_agent.allow_action( trans.user, data.permitted_actions.DATASET_ACCESS, dataset = data.dataset ):
+ %if not trans.app.security_agent.allow_action( user, roles, data.permitted_actions.DATASET_ACCESS, dataset = data.dataset ):
<div>You do not have permission to view this dataset.</div>
%elif data_state == "upload":
<div>Dataset is uploading</div>
diff -r 36f438ce1f82 -r cc4944a62b66 test/base/twilltestcase.py
--- a/test/base/twilltestcase.py Fri Aug 28 15:59:16 2009 -0400
+++ b/test/base/twilltestcase.py Fri Aug 28 16:52:58 2009 -0400
@@ -1229,7 +1229,7 @@
tc.fv( '1', 'new_element_description_1', ele_help_1.replace( '+', ' ' ) )
tc.submit( 'new_info_template_button' )
self.home()
- def add_folder( self, library_id, folder_id, name='Folder One', description='NThis is Folder One' ):
+ def add_folder( self, library_id, folder_id, name='Folder One', description='This is Folder One' ):
"""Create a new folder"""
self.home()
self.visit_url( "%s/admin/folder?library_id=%s&id=%s&new=True" % ( self.url, library_id, folder_id ) )
diff -r 36f438ce1f82 -r cc4944a62b66 universe_wsgi.ini.sample
--- a/universe_wsgi.ini.sample Fri Aug 28 15:59:16 2009 -0400
+++ b/universe_wsgi.ini.sample Fri Aug 28 16:52:58 2009 -0400
@@ -25,6 +25,11 @@
#database_engine_option_echo_pool = true
#database_engine_option_pool_size = 10
#database_engine_option_max_overflow = 20
+
+# If using MySQL, see:
+# http://rapd.wordpress.com/2008/03/02/sqlalchemy-sqlerror-operationalerror-2…
+# To handle this issue, try the following setting:
+#database_engine_option_pool_recycle = 7200
# Where dataset files are saved
file_path = database/files
1
0