details: http://www.bx.psu.edu/hg/galaxy/rev/032478337b82 changeset: 2683:032478337b82 user: jeremy goecks <jeremy.goecks@emory.edu> date: Fri Sep 11 14:57:02 2009 -0400 description: (1) Unicode support for tagging and (2) added tagging_common mako file to support creation and standardization of tagging elements across all pages. 9 file(s) affected in this change: lib/galaxy/web/controllers/history.py lib/galaxy/web/controllers/tag.py static/scripts/autocomplete_tagging.js static/scripts/packed/autocomplete_tagging.js templates/dataset/edit_attributes.mako templates/history/grid.mako templates/root/history.mako templates/tagging_common.mako tool_conf.xml.main diffs (781 lines): diff -r ed4cbaf23c88 -r 032478337b82 lib/galaxy/web/controllers/history.py --- a/lib/galaxy/web/controllers/history.py Fri Sep 11 09:00:36 2009 -0400 +++ b/lib/galaxy/web/controllers/history.py Fri Sep 11 14:57:02 2009 -0400 @@ -38,6 +38,17 @@ if item.users_shared_with or item.importable: return dict( operation="sharing" ) return None + class TagsColumn( grids.GridColumn ): + def __init__(self, col_name): + grids.GridColumn.__init__(self, col_name) + self.tag_elt_id_gen = 0 + + def get_value( self, trans, grid, history ): + self.tag_elt_id_gen += 1 + return trans.fill_template( "/tagging_common.mako", trans=trans, + tagged_item=history, + elt_id="tagging-elt" + str(self.tag_elt_id_gen) ) + # Grid definition title = "Stored histories" model_class = model.History @@ -48,6 +59,7 @@ link=( lambda item: iff( item.deleted, None, dict( operation="switch", id=item.id ) ) ), attach_popup=True ), DatasetsByStateColumn( "Datasets (by state)", ncells=4 ), + #TagsColumn( "Tags" ), StatusColumn( "Status", attach_popup=False ), grids.GridColumn( "Created", key="create_time", format=time_ago ), grids.GridColumn( "Last Updated", key="update_time", format=time_ago ), diff -r ed4cbaf23c88 -r 032478337b82 lib/galaxy/web/controllers/tag.py --- a/lib/galaxy/web/controllers/tag.py Fri Sep 11 09:00:36 2009 -0400 +++ b/lib/galaxy/web/controllers/tag.py Fri Sep 11 14:57:02 2009 -0400 @@ -4,7 +4,6 @@ from galaxy.model import History, HistoryTagAssociation, Dataset, DatasetTagAssociation, \ HistoryDatasetAssociation, HistoryDatasetAssociationTagAssociation, Page, PageTagAssociation - from galaxy.web.base.controller import * from galaxy.tags.tag_handler import * from sqlalchemy.sql.expression import func, and_ @@ -15,65 +14,68 @@ def __init__(self, app): BaseController.__init__(self, app) - # Set up dict for mapping from short-hand to full item class. - self.shorthand_to_item_class_dict = dict() - self.shorthand_to_item_class_dict["history"] = History - self.shorthand_to_item_class_dict["hda"] = HistoryDatasetAssociation + # Keep a list of taggable classes. + self.taggable_classes = dict() + self.taggable_classes[History.__name__] = History + self.taggable_classes[HistoryDatasetAssociation.__name__] = HistoryDatasetAssociation + self.taggable_classes[Page.__name__] = Page - # Set up tag handler to recognize the following items: History, HistoryDatasetAssociation, ... + # Set up tag handler to recognize the following items: History, HistoryDatasetAssociation, Page, ... self.tag_handler = TagHandler() self.tag_handler.add_tag_assoc_class(History, HistoryTagAssociation) self.tag_handler.add_tag_assoc_class(HistoryDatasetAssociation, HistoryDatasetAssociationTagAssociation) - + self.tag_handler.add_tag_assoc_class(Page, PageTagAssociation) + @web.expose - def add_tag_async( self, trans, id=None, item_type=None, new_tag=None ): + @web.require_login( "Add tag to an item." ) + def add_tag_async( self, trans, id=None, item_class=None, new_tag=None ): """ Add tag to an item. """ - item = self._get_item(trans, item_type, trans.security.decode_id(id)) + item = self._get_item(trans, item_class, trans.security.decode_id(id)) self._do_security_check(trans, item) - self.tag_handler.apply_item_tags(trans.sa_session, item, new_tag) + self.tag_handler.apply_item_tags( trans.sa_session, item, unicode(new_tag).encode('utf-8') ) trans.sa_session.flush() @web.expose - def remove_tag_async( self, trans, id=None, item_type=None, tag_name=None ): + @web.require_login( "Remove tag from an item." ) + def remove_tag_async( self, trans, id=None, item_class=None, tag_name=None ): """ Remove tag from an item. """ - item = self._get_item(trans, item_type, trans.security.decode_id(id)) + item = self._get_item(trans, item_class, trans.security.decode_id(id)) self._do_security_check(trans, item) - self.tag_handler.remove_item_tag(item, tag_name) + self.tag_handler.remove_item_tag( item, unicode(tag_name).encode('utf-8') ) + #print tag_name + #print unicode(tag_name) trans.sa_session.flush() # Retag an item. All previous tags are deleted and new tags are applied. @web.expose - def retag_async( self, trans, id=None, item_type=None, new_tags=None ): + @web.require_login( "Apply a new set of tags to an item; previous tags are deleted." ) + def retag_async( self, trans, id=None, item_class=None, new_tags=None ): """ Apply a new set of tags to an item; previous tags are deleted. """ - item = self._get_item(trans, item_type, trans.security.decode_id(id)) + item = self._get_item(trans, item_class, trans.security.decode_id(id)) self._do_security_check(trans, item) tag_handler.delete_item_tags(item) - self.tag_handler.apply_item_tags(trans.sa_session, item, new_tag) + self.tag_handler.apply_item_tags( trans.sa_session, item, unicode(new_tags).encode('utf-8') ) trans.sa_session.flush() - - tag_handler.delete_item_tags(history) - tag_handler.apply_item_tags(trans.sa_session, history, new_tags) - # Flush to complete changes. - trans.sa_session.flush() - + @web.expose @web.require_login( "get autocomplete data for an item's tags" ) - def tag_autocomplete_data(self, trans, id=None, item_type=None, q=None, limit=None, timestamp=None): + def tag_autocomplete_data(self, trans, id=None, item_class=None, q=None, limit=None, timestamp=None): """ Get autocomplete data for an item's tags. """ # # Get item, do security check, and get autocomplete data. # - item = self._get_item(trans, item_type, trans.security.decode_id(id)) + item = self._get_item(trans, item_class, trans.security.decode_id(id)) self._do_security_check(trans, item) + q = unicode(q).encode('utf-8') if q.find(":") == -1: return self._get_tag_autocomplete_names(trans, item, q, limit, timestamp) else: @@ -184,9 +186,9 @@ # Use the user_id associated with the HDA's history. return History.table.c.user_id - def _get_item(self, trans, item_type, id): + def _get_item(self, trans, item_class_name, id): """ Get an item based on type and id. """ - item_class = self.shorthand_to_item_class_dict[item_type] + item_class = self.taggable_classes[item_class_name] item = trans.sa_session.query(item_class).filter("id=" + str(id))[0] return item; diff -r ed4cbaf23c88 -r 032478337b82 static/scripts/autocomplete_tagging.js --- a/static/scripts/autocomplete_tagging.js Fri Sep 11 09:00:36 2009 -0400 +++ b/static/scripts/autocomplete_tagging.js Fri Sep 11 14:57:02 2009 -0400 @@ -187,13 +187,14 @@ // Tag button is image's parent. var tag_button = $(this).parent(); - // Get tag name. + // Get tag name, value. 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]; + var tag_name_and_value = get_tag_name_and_value(tag_str); + var tag_name = tag_name_and_value[0]; + var tag_value = tag_name_and_value[1]; - // TODO: should remove succeed if tag is not already applied to - // history? + var prev_button = tag_button.prev(); tag_button.remove(); // Remove tag from local list for consistency. @@ -209,12 +210,28 @@ data: { tag_name: tag_name }, error: function() { - // Failed. - alert( "Remove tag failed" ); + // Failed. Roll back changes and show alert. + settings.tags[tag_name] = tag_value; + if (prev_button.hasClass("tag-button")) + prev_button.after(tag_button); + else + tag_area.prepend(tag_button); + var new_text = settings.get_toggle_link_text_fn(settings.tags); + alert( "Remove tag failed" ); + + toggle_link.text(new_text); + + // TODO: no idea why it's necessary to set this up again. + delete_img.mouseenter( function () + { + $(this).attr("src", settings.delete_tag_img_rollover); + }); + delete_img.mouseleave( function () + { + $(this).attr("src", settings.delete_tag_img); + }); }, - success: function() - { - } + success: function() {} }); return true; @@ -323,8 +340,9 @@ data: { new_tag: new_value }, error: function() { - // Remove tag and show alert. + // Failed. Roll back changes and show alert. new_tag_button.remove(); + delete settings.tags[tag_name_and_value[0]]; var new_text = settings.get_toggle_link_text_fn(settings.tags); toggle_link.text(new_text); alert( "Add tag failed" ); diff -r ed4cbaf23c88 -r 032478337b82 static/scripts/packed/autocomplete_tagging.js --- a/static/scripts/packed/autocomplete_tagging.js Fri Sep 11 09:00:36 2009 -0400 +++ b/static/scripts/packed/autocomplete_tagging.js Fri Sep 11 14:57:02 2009 -0400 @@ -1,1 +1,1 @@ -var ac_tag_area_id_gen=1;jQuery.fn.autocomplete_tagging=function(c){var e={get_toggle_link_text_fn:function(u){var w="";var v=o(u);if(v!=0){w=v+(v!=0?" Tags":" Tag")}else{w="Add tags"}return w},tag_click_fn:function(u){},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:""};var p=jQuery.extend(e,c);var k="tag-area-"+(ac_tag_area_id_gen)++;var m=$("<div></div>").attr("id",k).addClass("tag-area");this.append(m);var o=function(u){if(u.length){return u.length}var v=0;for(element in u){v++}return v};var b=function(){var u=p.get_toggle_link_text_fn(p.tags);var v=$("<a href='/history/tags'>"+u+"</a>").addClass("toggle-link");v.click(function(){var w=(m.css("display")=="none");var x;if(w){x=function(){var y=o(p.tags);if(y==0){m.click()}}}else{x=function(){m.blur()}}m.slideToggle("fast",x);return false});return v};var s=b(); if(p.use_toggle_link){this.prepend(s)}var t=function(u){var v=new Array();for(key in u){v[v.length]=key+"-->"+u[key]}return"{"+v.join(",")+"}"};var a=function(v,u){return v+((u!=""&&u)?":"+u:"")};var h=function(u){return u.split(":")};var i=function(u){var v=$("<img src='"+p.add_tag_img+"' rollover='"+p.add_tag_img_rollover+"'/>").addClass("add-tag-button");v.click(function(){$(this).hide();m.click();return false});return v};var j=function(u){var v=$("<img src='"+p.delete_tag_img+"'/>").addClass("delete-tag-img");v.mouseenter(function(){$(this).attr("src",p.delete_tag_img_rollover)});v.mouseleave(function(){$(this).attr("src",p.delete_tag_img)});v.click(function(){var B=$(this).parent();var A=B.find(".tag-name").eq(0);var z=A.text();var C=h(z)[0];B.remove();delete p.tags[C];var y=p.get_toggle_link_text_fn(p.tags);s.text(y);$.ajax({url:p.ajax_delete_tag_url,data:{tag_name:C},error:function(){alert("Remove tag failed")},success:function(){}});return true});var w=$("<span>"+u+" </span>").addClass("tag-name");w.click(function(){p.tag_click_fn(u);return true});var x=$("<span></span>").addClass("tag-button");x.append(w);x.append(v);return x};var d=function(v){var u;if(p.in_form){u=$("<textarea id='history-tag-input' rows='1' cols='"+p.input_size+"' value='"+v+"'></textarea>")}else{u=$("<input id='history-tag-input' type='text' size='"+p.input_size+"' value='"+v+"'></input>")}u.keyup(function(D){if(D.keyCode==27){$(this).trigger("blur")}else{if((D.keyCode==13)||(D.keyCode==188)||(D.keyCode==32)){new_value=this.value;if(return_key_pressed_for_autocomplete==true){return_key_pressed_for_autocomplete=false;return false}if(new_value.indexOf(": ",new_value.length-2)!=-1){this.value=new_value.substring(0,new_value.length-1);return false}if((D.keyCode==188)||(D.keyCode==32)){new_value=new_value.substring(0,new_value.length-1)}new_value=new_value.replace(/^\s+|\s+$/g,"");if(new_value.length<3){return false}this.value="";var A=j(new_value);var z=m.children(".tag -button");if(z.length!=0){var E=z.slice(z.length-1);E.after(A)}else{m.prepend(A)}var y=new_value.split(":");p.tags[y[0]]=y[1];var B=p.get_toggle_link_text_fn(p.tags);s.text(B);var C=$(this);$.ajax({url:p.ajax_add_tag_url,data:{new_tag:new_value},error:function(){A.remove();var F=p.get_toggle_link_text_fn(p.tags);s.text(F);alert("Add tag failed")},success:function(){C.flushCache()}});return false}}});var w=function(A,z,y,C,B){tag_name_and_value=C.split(":");return(tag_name_and_value.length==1?tag_name_and_value[0]:tag_name_and_value[1])};var x={selectFirst:false,formatItem:w,autoFill:false,highlight:false};u.autocomplete(p.ajax_autocomplete_tag_url,x);u.addClass("tag-input");return u};for(tag_name in p.tags){var q=p.tags[tag_name];var l=a(tag_name,q);var g=j(l,s,p.tags);m.append(g)}var n=d("");var f=i(n);m.blur(function(u){r=o(p.tags);if(r!=0){f.show();n.hide();m.removeClass("active-tag-area")}else{}});m.append(f);m.append(n);n.hide();m.click(function(w){var v=$(this).hasClas s("active-tag-area");if($(w.target).hasClass("delete-tag-img")&&!v){return false}if($(w.target).hasClass("tag-name")&&!v){return false}$(this).addClass("active-tag-area");f.hide();n.show();n.focus();var u=function(y){var x=m.attr("id");if(($(y.target).attr("id")!=x)&&($(y.target).parents().filter(x).length==0)){m.blur();$(document).unbind("click",u)}};$(window).click(u);return false});if(p.use_toggle_link){m.hide()}else{var r=o(p.tags);if(r==0){f.hide();n.show()}}return this.addClass("tag-element")}; \ No newline at end of file +var ac_tag_area_id_gen=1;jQuery.fn.autocomplete_tagging=function(c){var e={get_toggle_link_text_fn:function(u){var w="";var v=o(u);if(v!=0){w=v+(v!=0?" Tags":" Tag")}else{w="Add tags"}return w},tag_click_fn:function(u){},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:""};var p=jQuery.extend(e,c);var k="tag-area-"+(ac_tag_area_id_gen)++;var m=$("<div></div>").attr("id",k).addClass("tag-area");this.append(m);var o=function(u){if(u.length){return u.length}var v=0;for(element in u){v++}return v};var b=function(){var u=p.get_toggle_link_text_fn(p.tags);var v=$("<a href='/history/tags'>"+u+"</a>").addClass("toggle-link");v.click(function(){var w=(m.css("display")=="none");var x;if(w){x=function(){var y=o(p.tags);if(y==0){m.click()}}}else{x=function(){m.blur()}}m.slideToggle("fast",x);return false});return v};var s=b(); if(p.use_toggle_link){this.prepend(s)}var t=function(u){var v=new Array();for(key in u){v[v.length]=key+"-->"+u[key]}return"{"+v.join(",")+"}"};var a=function(v,u){return v+((u!=""&&u)?":"+u:"")};var h=function(u){return u.split(":")};var i=function(u){var v=$("<img src='"+p.add_tag_img+"' rollover='"+p.add_tag_img_rollover+"'/>").addClass("add-tag-button");v.click(function(){$(this).hide();m.click();return false});return v};var j=function(u){var v=$("<img src='"+p.delete_tag_img+"'/>").addClass("delete-tag-img");v.mouseenter(function(){$(this).attr("src",p.delete_tag_img_rollover)});v.mouseleave(function(){$(this).attr("src",p.delete_tag_img)});v.click(function(){var D=$(this).parent();var C=D.find(".tag-name").eq(0);var B=C.text();var z=h(B);var F=z[0];var y=z[1];var E=D.prev();D.remove();delete p.tags[F];var A=p.get_toggle_link_text_fn(p.tags);s.text(A);$.ajax({url:p.ajax_delete_tag_url,data:{tag_name:F},error:function(){p.tags[F]=y;if(E.hasClass("tag-button")){E.after(D) }else{m.prepend(D)}var G=p.get_toggle_link_text_fn(p.tags);alert("Remove tag failed");s.text(G);v.mouseenter(function(){$(this).attr("src",p.delete_tag_img_rollover)});v.mouseleave(function(){$(this).attr("src",p.delete_tag_img)})},success:function(){}});return true});var w=$("<span>"+u+"</span>").addClass("tag-name");w.click(function(){p.tag_click_fn(u);return true});var x=$("<span></span>").addClass("tag-button");x.append(w);x.append(v);return x};var d=function(v){var u;if(p.in_form){u=$("<textarea id='history-tag-input' rows='1' cols='"+p.input_size+"' value='"+v+"'></textarea>")}else{u=$("<input id='history-tag-input' type='text' size='"+p.input_size+"' value='"+v+"'></input>")}u.keyup(function(D){if(D.keyCode==27){$(this).trigger("blur")}else{if((D.keyCode==13)||(D.keyCode==188)||(D.keyCode==32)){new_value=this.value;if(return_key_pressed_for_autocomplete==true){return_key_pressed_for_autocomplete=false;return false}if(new_value.indexOf(": ",new_value.length-2)!=-1){thi s.value=new_value.substring(0,new_value.length-1);return false}if((D.keyCode==188)||(D.keyCode==32)){new_value=new_value.substring(0,new_value.length-1)}new_value=new_value.replace(/^\s+|\s+$/g,"");if(new_value.length<3){return false}this.value="";var A=j(new_value);var z=m.children(".tag-button");if(z.length!=0){var E=z.slice(z.length-1);E.after(A)}else{m.prepend(A)}var y=new_value.split(":");p.tags[y[0]]=y[1];var B=p.get_toggle_link_text_fn(p.tags);s.text(B);var C=$(this);$.ajax({url:p.ajax_add_tag_url,data:{new_tag:new_value},error:function(){A.remove();delete p.tags[y[0]];var F=p.get_toggle_link_text_fn(p.tags);s.text(F);alert("Add tag failed")},success:function(){C.flushCache()}});return false}}});var w=function(A,z,y,C,B){tag_name_and_value=C.split(":");return(tag_name_and_value.length==1?tag_name_and_value[0]:tag_name_and_value[1])};var x={selectFirst:false,formatItem:w,autoFill:false,highlight:false};u.autocomplete(p.ajax_autocomplete_tag_url,x);u.addClass("tag-input ");return u};for(tag_name in p.tags){var q=p.tags[tag_name];var l=a(tag_name,q);var g=j(l,s,p.tags);m.append(g)}var n=d("");var f=i(n);m.blur(function(u){r=o(p.tags);if(r!=0){f.show();n.hide();m.removeClass("active-tag-area")}else{}});m.append(f);m.append(n);n.hide();m.click(function(w){var v=$(this).hasClass("active-tag-area");if($(w.target).hasClass("delete-tag-img")&&!v){return false}if($(w.target).hasClass("tag-name")&&!v){return false}$(this).addClass("active-tag-area");f.hide();n.show();n.focus();var u=function(y){var x=m.attr("id");if(($(y.target).attr("id")!=x)&&($(y.target).parents().filter(x).length==0)){m.blur();$(document).unbind("click",u)}};$(window).click(u);return false});if(p.use_toggle_link){m.hide()}else{var r=o(p.tags);if(r==0){f.hide();n.show()}}return this.addClass("tag-element")}; \ No newline at end of file diff -r ed4cbaf23c88 -r 032478337b82 templates/dataset/edit_attributes.mako --- a/templates/dataset/edit_attributes.mako Fri Sep 11 09:00:36 2009 -0400 +++ b/templates/dataset/edit_attributes.mako Fri Sep 11 14:57:02 2009 -0400 @@ -9,43 +9,8 @@ <% user, user_roles = trans.get_user_and_roles() %> <%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> + ${parent.javascripts()} + ${h.js( "jquery.autocomplete", "autocomplete_tagging" )} </%def> <%def name="datatype( dataset, datatypes )"> @@ -84,16 +49,18 @@ <div style="clear: both"></div> </div> %if trans.get_user() is not None: - <div class="form-row"> - <label> - Tags: - </label> - <div id="dataset-tag-area" + <%namespace file="../tagging_common.mako" import="render_tagging_element" /> + <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 + </div> + <div style="clear: both"></div> + </div> + ${render_tagging_element(data, "dataset-tag-area", use_toggle_link="false", in_form="true", input_size="30")} + %endif %for name, spec in data.metadata.spec.items(): %if spec.visible: <div class="form-row"> diff -r ed4cbaf23c88 -r 032478337b82 templates/history/grid.mako --- a/templates/history/grid.mako Fri Sep 11 09:00:36 2009 -0400 +++ b/templates/history/grid.mako Fri Sep 11 14:57:02 2009 -0400 @@ -10,6 +10,7 @@ <%def name="javascripts()"> ${parent.javascripts()} + ${h.js("jquery.autocomplete", "autocomplete_tagging" )} <script type="text/javascript"> ## TODO: generalize and move into galaxy.base.js $(document).ready(function() { @@ -58,7 +59,7 @@ </%def> <%def name="stylesheets()"> - <link href="${h.url_for('/static/style/base.css')}" rel="stylesheet" type="text/css" /> + ${h.css( "base", "autocomplete_tagging" )} <style> ## Not generic to all grids -- move to base? .count-box { diff -r ed4cbaf23c88 -r 032478337b82 templates/root/history.mako --- a/templates/root/history.mako Fri Sep 11 09:00:36 2009 -0400 +++ b/templates/root/history.mako Fri Sep 11 14:57:02 2009 -0400 @@ -77,83 +77,6 @@ <% updateable = [data for data in reversed( datasets ) if data.visible and data.state not in [ "deleted", "empty", "error", "ok" ]] %> ${ ",".join( map(lambda data: "\"%s\" : \"%s\"" % (data.id, data.state), updateable) ) } }); - - // 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 function initShowHide() { @@ -361,7 +284,13 @@ <div id="history-tag-area" style="margin-bottom: 1em"> </div> +<%namespace file="../tagging_common.mako" import="render_tagging_element" /> <%namespace file="history_common.mako" import="render_dataset" /> + +%if trans.get_user() is not None: + <div id='history-tag-area' class="tag-element"></div> + ${render_tagging_element(history, "history-tag-area")} +%endif %if not datasets: diff -r ed4cbaf23c88 -r 032478337b82 templates/tagging_common.mako --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/templates/tagging_common.mako Fri Sep 11 14:57:02 2009 -0400 @@ -0,0 +1,92 @@ +## Render the tags 'tags' as an autocomplete element. +<%def name="render_tagging_element(tagged_item, elt_id, use_toggle_link='true', in_form='false', input_size='15')"> + <script type="text/javascript"> + + // + // Set up autocomplete tagger. + // + <% + ## Build string of tag name, values. + tag_names_and_values = list() + for tag in tagged_item.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 history"; + } + return text; + }; + + var options = + { + tags : {${unicode(", ".join(tag_names_and_values), 'utf-8')}}, + get_toggle_link_text_fn: get_toggle_link_text, + tag_click_fn: function(tag) { /* Do nothing. */ }, + <% tagged_item_id = trans.security.encode_id(tagged_item.id) %> + ajax_autocomplete_tag_url: "${h.url_for( controller='tag', action='tag_autocomplete_data', id=tagged_item_id, item_class=tagged_item.__class__.__name__ )}", + ajax_add_tag_url: "${h.url_for( controller='tag', action='add_tag_async', id=tagged_item_id, item_class=tagged_item.__class__.__name__ )}", + ajax_delete_tag_url: "${h.url_for( controller='tag', action='remove_tag_async', id=tagged_item_id, item_class=tagged_item.__class__.__name__ )}", + 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')}", + input_size: ${input_size}, + in_form: ${in_form}, + use_toggle_link: ${use_toggle_link} + }; + + $("#${elt_id}").autocomplete_tagging(options) + </script> +</%def> \ No newline at end of file diff -r ed4cbaf23c88 -r 032478337b82 tool_conf.xml.main --- a/tool_conf.xml.main Fri Sep 11 09:00:36 2009 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,263 +0,0 @@ -<?xml version="1.0"?> -<toolbox> - <section name="Get Data" id="getext"> - <tool file="data_source/upload.xml"/> - <tool file="data_source/ucsc_tablebrowser.xml" /> - <tool file="data_source/ucsc_tablebrowser_archaea.xml" /> - <tool file="data_source/microbial_import.xml" /> - <tool file="data_source/biomart.xml" /> - <tool file="data_source/gramene_mart.xml" /> - <tool file="data_source/flymine.xml" /> - <tool file="data_source/encode_db.xml" /> - <tool file="data_source/epigraph_import.xml" /> - </section> - <section name="Send Data" id="send"> - <tool file="data_destination/epigraph.xml" /> - </section> - <section name="ENCODE Tools" id="EncodeTools"> - <tool file="encode/gencode_partition.xml" /> - <tool file="encode/random_intervals.xml" /> - </section> - <section name="Lift-Over" id="liftOver"> - <tool file="extract/liftOver_wrapper.xml" /> - </section> - <section name="Text Manipulation" id="textutil"> - <tool file="filters/fixedValueColumn.xml" /> - <tool file="stats/column_maker.xml" /> - <tool file="filters/catWrapper.xml" /> - <tool file="filters/condense_characters.xml" /> - <tool file="filters/convert_characters.xml" /> - <tool file="filters/CreateInterval.xml" /> - <tool file="filters/cutWrapper.xml" /> - <tool file="filters/changeCase.xml" /> - <tool file="filters/pasteWrapper.xml" /> - <tool file="filters/remove_beginning.xml" /> - <tool file="filters/headWrapper.xml" /> - <tool file="filters/tailWrapper.xml" /> - </section> - <section name="Convert Formats" id="convert"> - <tool file="filters/bed2gff.xml" /> - <tool file="fasta_tools/fasta_to_tabular.xml" /> - <tool file="filters/gff2bed.xml" /> - <tool file="maf/maf_to_bed.xml" /> - <tool file="maf/maf_to_fasta.xml" /> - <tool file="fasta_tools/tabular_to_fasta.xml" /> - </section> - <section name="FASTA manipulation" id="fasta_manipulation"> - <tool file="fasta_tools/fasta_compute_length.xml" /> - <tool file="fasta_tools/fasta_filter_by_length.xml" /> - <tool file="fasta_tools/fasta_concatenate_by_species.xml" /> - <tool file="fasta_tools/fasta_to_tabular.xml" /> - <tool file="fasta_tools/tabular_to_fasta.xml" /> - </section> - <section name="Filter and Sort" id="filter"> - <tool file="stats/filtering.xml" /> - <tool file="filters/sorter.xml" /> - <tool file="filters/grep.xml" /> - </section> - <section name="Join, Subtract and Group" id="group"> - <tool file="filters/joiner.xml" /> - <tool file="filters/compare.xml"/> - <tool file="new_operations/subtract_query.xml"/> - <tool file="stats/grouping.xml" /> - </section> - <section name="Extract Features" id="features"> - <tool file="filters/ucsc_gene_bed_to_exon_bed.xml" /> - <tool file="extract/extract_GFF_Features.xml" /> - </section> - <section name="Fetch Sequences" id="fetchSeq"> - <tool file="extract/extract_genomic_dna.xml" /> - </section> - <section name="Fetch Alignments" id="fetchAlign"> - <tool file="maf/interval2maf_pairwise.xml" /> - <tool file="maf/interval2maf.xml" /> - <tool file="maf/interval_maf_to_merged_fasta.xml" /> - <tool file="maf/genebed_maf_to_fasta.xml"/> - <tool file="maf/maf_stats.xml"/> - <tool file="maf/maf_thread_for_species.xml"/> - <tool file="maf/maf_limit_to_species.xml"/> - <tool file="maf/maf_limit_size.xml"/> - <tool file="maf/maf_by_block_number.xml"/> - <tool file="maf/maf_filter.xml"/> - <!-- - <tool file="maf/maf_reverse_complement.xml"/> - --> - </section> - <section name="Get Genomic Scores" id="scores"> - <tool file="stats/wiggle_to_simple.xml" /> - <tool file="stats/aggregate_binned_scores_in_intervals.xml" /> - <tool file="extract/phastOdds/phastOdds_tool.xml" /> - </section> - <section name="Operate on Genomic Intervals" id="bxops"> - <tool file="new_operations/intersect.xml" /> - <tool file="new_operations/subtract.xml" /> - <tool file="new_operations/merge.xml" /> - <tool file="new_operations/concat.xml" /> - <tool file="new_operations/basecoverage.xml" /> - <tool file="new_operations/coverage.xml" /> - <tool file="new_operations/complement.xml" /> - <tool file="new_operations/cluster.xml" id="cluster" /> - <tool file="new_operations/join.xml" /> - <tool file="new_operations/get_flanks.xml" /> - <tool file="new_operations/flanking_features.xml" /> - <tool file="annotation_profiler/annotation_profiler.xml" /> - </section> - <section name="Statistics" id="stats"> - <tool file="stats/gsummary.xml" /> - <tool file="filters/uniq.xml" /> - <tool file="stats/cor.xml" /> - </section> - <section name="Graph/Display Data" id="plots"> - <tool file="plotting/histogram2.xml" /> - <tool file="plotting/scatterplot.xml" /> - <tool file="plotting/xy_plot.xml" /> - <tool file="visualization/GMAJ.xml" /> - <tool file="visualization/build_ucsc_custom_track.xml" /> - </section> - <section name="Regional Variation" id="regVar"> - <tool file="regVariation/windowSplitter.xml" /> - <tool file="regVariation/featureCounter.xml" /> - <tool file="regVariation/quality_filter.xml" /> - <tool file="regVariation/maf_cpg_filter.xml" /> - <tool file="regVariation/getIndels_2way.xml" /> - <tool file="regVariation/getIndels_3way.xml" /> - <tool file="regVariation/getIndelRates_3way.xml" /> - <tool file="regVariation/substitutions.xml" /> - <tool file="regVariation/substitution_rates.xml" /> - <tool file="regVariation/microsats_alignment_level.xml" /> - <tool file="regVariation/microsats_mutability.xml" /> - </section> - <section name="Multiple regression" id="multReg"> - <tool file="regVariation/linear_regression.xml" /> - <tool file="regVariation/best_regression_subsets.xml" /> - <tool file="regVariation/rcve.xml" /> - </section> - <section name="Evolution: HyPhy" id="hyphy"> - <tool file="hyphy/hyphy_branch_lengths_wrapper.xml" /> - <tool file="hyphy/hyphy_nj_tree_wrapper.xml" /> - <tool file="hyphy/hyphy_dnds_wrapper.xml" /> - </section> - <section name="Metagenomic analyses" id="tax_manipulation"> - <tool file="taxonomy/gi2taxonomy.xml" /> - <tool file="taxonomy/t2t_report.xml" /> - <tool file="taxonomy/t2ps_wrapper.xml" /> - <tool file="taxonomy/find_diag_hits.xml" /> - <tool file="taxonomy/lca.xml" /> - <tool file="taxonomy/poisson2test.xml" /> - </section> - <section name="Short Read Analysis" id="short_read_analysis"> - <tool file="metag_tools/short_reads_figure_score.xml" /> - <tool file="metag_tools/short_reads_trim_seq.xml" /> - <tool file="metag_tools/megablast_wrapper.xml" /> - <tool file="metag_tools/megablast_xml_parser.xml" /> - </section> - <section name="EMBOSS" id="EMBOSSLite"> - <tool file="emboss_5/emboss_antigenic.xml" /> - <tool file="emboss_5/emboss_backtranseq.xml" /> - <tool file="emboss_5/emboss_banana.xml" /> - <tool file="emboss_5/emboss_biosed.xml" /> - <tool file="emboss_5/emboss_btwisted.xml" /> - <tool file="emboss_5/emboss_cai_custom.xml" /> - <tool file="emboss_5/emboss_cai.xml" /> - <tool file="emboss_5/emboss_chaos.xml" /> - <tool file="emboss_5/emboss_charge.xml" /> - <tool file="emboss_5/emboss_checktrans.xml" /> - <tool file="emboss_5/emboss_chips.xml" /> - <tool file="emboss_5/emboss_cirdna.xml" /> - <tool file="emboss_5/emboss_codcmp.xml" /> - <tool file="emboss_5/emboss_coderet.xml" /> - <tool file="emboss_5/emboss_compseq.xml" /> - <tool file="emboss_5/emboss_cpgplot.xml" /> - <tool file="emboss_5/emboss_cpgreport.xml" /> - <tool file="emboss_5/emboss_cusp.xml" /> - <tool file="emboss_5/emboss_cutseq.xml" /> - <tool file="emboss_5/emboss_dan.xml" /> - <tool file="emboss_5/emboss_degapseq.xml" /> - <tool file="emboss_5/emboss_descseq.xml" /> - <tool file="emboss_5/emboss_diffseq.xml" /> - <tool file="emboss_5/emboss_digest.xml" /> - <tool file="emboss_5/emboss_dotmatcher.xml" /> - <tool file="emboss_5/emboss_dotpath.xml" /> - <tool file="emboss_5/emboss_dottup.xml" /> - <tool file="emboss_5/emboss_dreg.xml" /> - <tool file="emboss_5/emboss_einverted.xml" /> - <tool file="emboss_5/emboss_epestfind.xml" /> - <tool file="emboss_5/emboss_equicktandem.xml" /> - <tool file="emboss_5/emboss_est2genome.xml" /> - <tool file="emboss_5/emboss_etandem.xml" /> - <tool file="emboss_5/emboss_extractfeat.xml" /> - <tool file="emboss_5/emboss_extractseq.xml" /> - <tool file="emboss_5/emboss_freak.xml" /> - <tool file="emboss_5/emboss_fuzznuc.xml" /> - <tool file="emboss_5/emboss_fuzzpro.xml" /> - <tool file="emboss_5/emboss_fuzztran.xml" /> - <tool file="emboss_5/emboss_garnier.xml" /> - <tool file="emboss_5/emboss_geecee.xml" /> - <tool file="emboss_5/emboss_getorf.xml" /> - <tool file="emboss_5/emboss_helixturnhelix.xml" /> - <tool file="emboss_5/emboss_hmoment.xml" /> - <tool file="emboss_5/emboss_iep.xml" /> - <tool file="emboss_5/emboss_infoseq.xml" /> - <tool file="emboss_5/emboss_isochore.xml" /> - <tool file="emboss_5/emboss_lindna.xml" /> - <tool file="emboss_5/emboss_marscan.xml" /> - <tool file="emboss_5/emboss_maskfeat.xml" /> - <tool file="emboss_5/emboss_maskseq.xml" /> - <tool file="emboss_5/emboss_matcher.xml" /> - <tool file="emboss_5/emboss_megamerger.xml" /> - <tool file="emboss_5/emboss_merger.xml" /> - <tool file="emboss_5/emboss_msbar.xml" /> - <tool file="emboss_5/emboss_needle.xml" /> - <tool file="emboss_5/emboss_newcpgreport.xml" /> - <tool file="emboss_5/emboss_newcpgseek.xml" /> - <tool file="emboss_5/emboss_newseq.xml" /> - <tool file="emboss_5/emboss_noreturn.xml" /> - <tool file="emboss_5/emboss_notseq.xml" /> - <tool file="emboss_5/emboss_nthseq.xml" /> - <tool file="emboss_5/emboss_octanol.xml" /> - <tool file="emboss_5/emboss_oddcomp.xml" /> - <tool file="emboss_5/emboss_palindrome.xml" /> - <tool file="emboss_5/emboss_pasteseq.xml" /> - <tool file="emboss_5/emboss_patmatdb.xml" /> - <tool file="emboss_5/emboss_pepcoil.xml" /> - <tool file="emboss_5/emboss_pepinfo.xml" /> - <tool file="emboss_5/emboss_pepnet.xml" /> - <tool file="emboss_5/emboss_pepstats.xml" /> - <tool file="emboss_5/emboss_pepwheel.xml" /> - <tool file="emboss_5/emboss_pepwindow.xml" /> - <tool file="emboss_5/emboss_pepwindowall.xml" /> - <tool file="emboss_5/emboss_plotcon.xml" /> - <tool file="emboss_5/emboss_plotorf.xml" /> - <tool file="emboss_5/emboss_polydot.xml" /> - <tool file="emboss_5/emboss_preg.xml" /> - <tool file="emboss_5/emboss_prettyplot.xml" /> - <tool file="emboss_5/emboss_prettyseq.xml" /> - <tool file="emboss_5/emboss_primersearch.xml" /> - <tool file="emboss_5/emboss_revseq.xml" /> - <tool file="emboss_5/emboss_seqmatchall.xml" /> - <tool file="emboss_5/emboss_seqret.xml" /> - <tool file="emboss_5/emboss_showfeat.xml" /> - <tool file="emboss_5/emboss_shuffleseq.xml" /> - <tool file="emboss_5/emboss_sigcleave.xml" /> - <tool file="emboss_5/emboss_sirna.xml" /> - <tool file="emboss_5/emboss_sixpack.xml" /> - <tool file="emboss_5/emboss_skipseq.xml" /> - <tool file="emboss_5/emboss_splitter.xml" /> - <tool file="emboss_5/emboss_supermatcher.xml" /> - <tool file="emboss_5/emboss_syco.xml" /> - <tool file="emboss_5/emboss_tcode.xml" /> - <tool file="emboss_5/emboss_textsearch.xml" /> - <tool file="emboss_5/emboss_tmap.xml" /> - <tool file="emboss_5/emboss_tranalign.xml" /> - <tool file="emboss_5/emboss_transeq.xml" /> - <tool file="emboss_5/emboss_trimest.xml" /> - <tool file="emboss_5/emboss_trimseq.xml" /> - <tool file="emboss_5/emboss_twofeat.xml" /> - <tool file="emboss_5/emboss_union.xml" /> - <tool file="emboss_5/emboss_vectorstrip.xml" /> - <tool file="emboss_5/emboss_water.xml" /> - <tool file="emboss_5/emboss_wobble.xml" /> - <tool file="emboss_5/emboss_wordcount.xml" /> - <tool file="emboss_5/emboss_wordmatch.xml" /> - </section> -</toolbox>