galaxy-commits
Threads by month
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
February 2014
- 1 participants
- 192 discussions
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/057069969de0/
Changeset: 057069969de0
User: guerler
Date: 2014-02-19 19:18:37
Summary: Merge
Affected #: 0 files
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: guerler: Grids: Fix negative page numbers
by commits-noreply@bitbucket.org 19 Feb '14
by commits-noreply@bitbucket.org 19 Feb '14
19 Feb '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/0770af01a257/
Changeset: 0770af01a257
Branch: stable
User: guerler
Date: 2014-02-19 19:16:36
Summary: Grids: Fix negative page numbers
Affected #: 2 files
diff -r d270d3cf7627a42b6fac2aa69701deadb89c8ffc -r 0770af01a257818ee82f11a191d4305880ea0b91 static/scripts/galaxy.grids.js
--- a/static/scripts/galaxy.grids.js
+++ b/static/scripts/galaxy.grids.js
@@ -847,7 +847,7 @@
var page_link_range = num_page_links / 2;
var min_page = cur_page_num - page_link_range
var min_offset = 0;
- if (min_page == 0) {
+ if (min_page <= 0) {
// Min page is too low.
min_page = 1;
min_offset = page_link_range - ( cur_page_num - min_page );
diff -r d270d3cf7627a42b6fac2aa69701deadb89c8ffc -r 0770af01a257818ee82f11a191d4305880ea0b91 static/scripts/packed/galaxy.grids.js
--- a/static/scripts/packed/galaxy.grids.js
+++ b/static/scripts/packed/galaxy.grids.js
@@ -1,1 +1,1 @@
-jQuery.ajaxSettings.traditional=true;define(["mvc/ui"],function(){var a=Backbone.Model.extend({defaults:{url_base:"",async:false,async_ops:[],categorical_filters:[],filters:{},sort_key:null,show_item_checkboxes:false,advanced_search:false,cur_page:1,num_pages:1,operation:undefined,item_ids:undefined},can_async_op:function(c){return _.indexOf(this.attributes.async_ops,c)!==-1},add_filter:function(g,h,d){if(d){var e=this.attributes.filters[g],c;if(e===null||e===undefined){c=h}else{if(typeof(e)=="string"){if(e=="All"){c=h}else{var f=[];f[0]=e;f[1]=h;c=f}}else{c=e;c.push(h)}}this.attributes.filters[g]=c}else{this.attributes.filters[g]=h}},remove_filter:function(d,g){var c=this.attributes.filters[d];if(c===null||c===undefined){return false}var f=true;if(typeof(c)==="string"){if(c=="All"){f=false}else{delete this.attributes.filters[d]}}else{var e=_.indexOf(c,g);if(e!==-1){c.splice(e,1)}else{f=false}}return f},get_url_data:function(){var c={async:this.attributes.async,sort:this.attributes.sort_key,page:this.attributes.cur_page,show_item_checkboxes:this.attributes.show_item_checkboxes,advanced_search:this.attributes.advanced_search};if(this.attributes.operation){c.operation=this.attributes.operation}if(this.attributes.item_ids){c.id=this.attributes.item_ids}var d=this;_.each(_.pairs(d.attributes.filters),function(e){c["f-"+e[0]]=e[1]});return c},get_url:function(c){return this.get("url_base")+"?"+$.param(this.get_url_data())+"&"+$.param(c)}});var b=Backbone.View.extend({grid:null,initialize:function(c){this.init_grid(c);this.init_grid_controls();$("input[type=text]").each(function(){$(this).click(function(){$(this).select()}).keyup(function(){$(this).css("font-style","normal")})})},handle_refresh:function(c){if(c){if($.inArray("history",c)>-1){if(top.Galaxy&&top.Galaxy.currHistoryPanel){top.Galaxy.currHistoryPanel.loadCurrentHistory()}}}},init_grid:function(e){this.grid=new a(e);var d=this.grid.attributes;this.handle_refresh(d.refresh_frames);var c=this.grid.get("url_base");c=c.replace(/^.*\/\/[^\/]+/,"");this.grid.set("url_base",c);$("#grid-table-body").html(this.template_body(d));$("#grid-table-footer").html(this.template_footer(d));if(d.message){$("#grid-message").html(this.template_message(d));if(d.use_hide_message){setTimeout(function(){$("#grid-message").html("")},5000)}}this.init_grid_elements();init_refresh_on_change()},init_grid_controls:function(){$(".submit-image").each(function(){$(this).mousedown(function(){$(this).addClass("gray-background")});$(this).mouseup(function(){$(this).removeClass("gray-background")})});var c=this;$(".sort-link").each(function(){$(this).click(function(){c.set_sort_condition($(this).attr("sort_key"));return false})});$(".categorical-filter > a").each(function(){$(this).click(function(){c.set_categorical_filter($(this).attr("filter_key"),$(this).attr("filter_val"));return false})});$(".text-filter-form").each(function(){$(this).submit(function(){var g=$(this).attr("column_key");var f=$("#input-"+g+"-filter");var h=f.val();f.val("");c.add_filter_condition(g,h);return false})});var d=$("#input-tags-filter");if(d.length){d.autocomplete(this.grid.history_tag_autocomplete_url,{selectFirst:false,autoFill:false,highlight:false,mustMatch:false})}var e=$("#input-name-filter");if(e.length){e.autocomplete(this.grid.history_name_autocomplete_url,{selectFirst:false,autoFill:false,highlight:false,mustMatch:false})}$(".advanced-search-toggle").each(function(){$(this).click(function(){$("#standard-search").slideToggle("fast");$("#advanced-search").slideToggle("fast");return false})})},init_grid_elements:function(){$(".grid").each(function(){var s=$(this).find("input.grid-row-select-checkbox");var r=$(this).find("span.grid-selected-count");var t=function(){r.text($(s).filter(":checked").length)};$(s).each(function(){$(this).change(t)});t()});if($(".community_rating_star").length!==0){$(".community_rating_star").rating({})}var q=this.grid.attributes;var p=this;$(".page-link > a").each(function(){$(this).click(function(){p.set_page($(this).attr("page_num"));return false})});$(".use-inbound").each(function(){$(this).click(function(r){p.execute({href:$(this).attr("href"),inbound:true});return false})});$(".use-outbound").each(function(){$(this).click(function(r){p.execute({href:$(this).attr("href")});return false})});var f=q.items.length;if(f==0){return}for(var k in q.items){var o=q.items[k];var l=$("#grid-"+k+"-popup");l.off();var d=new PopupMenu(l);for(var h in q.operations){var e=q.operations[h];var m=e.label;var c=o.operation_config[m];var g=o.encode_id;if(c.allowed&&e.allow_popup){var n={html:e.label,href:c.url_args,target:c.target,confirmation_text:e.confirm,inbound:e.inbound};n.func=function(t){t.preventDefault();var s=$(t.target).html();var r=this.findItemByHtml(s);p.execute(r)};d.addItem(n)}}}},add_filter_condition:function(e,g){if(g===""){return false}this.grid.add_filter(e,g,true);var f=$("<span>"+g+"<a href='javascript:void(0);'><span class='delete-search-icon' /></span></a>");f.addClass("text-filter-val");var d=this;f.click(function(){d.grid.remove_filter(e,g);$(this).remove();d.go_page_one();d.execute()});var c=$("#"+e+"-filtering-criteria");c.append(f);this.go_page_one();this.execute()},set_sort_condition:function(h){var g=this.grid.get("sort_key");var f=h;if(g.indexOf(h)!==-1){if(g.substring(0,1)!=="-"){f="-"+h}else{}}$(".sort-arrow").remove();var e=(f.substring(0,1)=="-")?"↑":"↓";var c=$("<span>"+e+"</span>").addClass("sort-arrow");var d=$("#"+h+"-header");d.append(c);this.grid.set("sort_key",f);this.go_page_one();this.execute()},set_categorical_filter:function(e,g){var d=this.grid.get("categorical_filters")[e],f=this.grid.get("filters")[e];var c=this;$("."+e+"-filter").each(function(){var m=$.trim($(this).text());var k=d[m];var l=k[e];if(l==g){$(this).empty();$(this).addClass("current-filter");$(this).append(m)}else{if(l==f){$(this).empty();var h=$("<a href='#'>"+m+"</a>");h.click(function(){c.set_categorical_filter(e,l)});$(this).removeClass("current-filter");$(this).append(h)}}});this.grid.add_filter(e,g);this.go_page_one();this.execute()},set_page:function(c){var d=this;$(".page-link").each(function(){var k=$(this).attr("id"),g=parseInt(k.split("-")[2],10),e=d.grid.get("cur_page"),h;if(g===c){h=$(this).children().text();$(this).empty();$(this).addClass("inactive-link");$(this).text(h)}else{if(g===e){h=$(this).text();$(this).empty();$(this).removeClass("inactive-link");var f=$("<a href='#'>"+h+"</a>");f.click(function(){d.set_page(g)});$(this).append(f)}}});if(c==="all"){this.grid.set("cur_page",c)}else{this.grid.set("cur_page",parseInt(c,10))}this.execute()},submit_operation:function(f,g){var e=$('input[name="id"]:checked').length;if(!e>0){return false}var d=$(f).val();var c=[];$("input[name=id]:checked").each(function(){c.push($(this).val())});this.execute({operation:d,id:c,confirmation_text:g});return true},execute:function(n){var f=null;var e=null;var g=null;var c=null;var m=null;if(n){e=n.href;g=n.operation;f=n.id;c=n.confirmation_text;m=n.inbound;if(e!==undefined&&e.indexOf("operation=")!=-1){var l=e.split("?");if(l.length>1){var k=l[1];var d=k.split("&");for(var h=0;h<d.length;h++){if(d[h].indexOf("operation")!=-1){g=d[h].split("=")[1];g=g.replace(/\+/g," ")}else{if(d[h].indexOf("id")!=-1){f=d[h].split("=")[1]}}}}}}if(g&&f){if(c&&c!=""&&c!="None"&&c!="null"){if(!confirm(c)){return false}}g=g.toLowerCase();this.grid.set({operation:g,item_ids:f});if(this.grid.can_async_op(g)){this.update_grid()}else{this.go_to(m,"")}return false}if(e){this.go_to(m,e);return false}if(this.grid.get("async")){this.update_grid()}else{this.go_to(m,"")}return false},go_to:function(f,d){var e=this.grid.get("async");this.grid.set("async",false);advanced_search=$("#advanced-search").is(":visible");this.grid.set("advanced_search",advanced_search);if(!d){d=this.grid.get("url_base")+"?"+$.param(this.grid.get_url_data())}this.grid.set({operation:undefined,item_ids:undefined,async:e});if(f){var c=$(".grid-header").closest(".inbound");if(c.length!==0){c.load(d);return}}window.location=d},update_grid:function(){var d=(this.grid.get("operation")?"POST":"GET");$(".loading-elt-overlay").show();var c=this;$.ajax({type:d,url:c.grid.get("url_base"),data:c.grid.get_url_data(),error:function(e){alert("Grid refresh failed")},success:function(e){c.init_grid($.parseJSON(e));$(".loading-elt-overlay").hide()},complete:function(){c.grid.set({operation:undefined,item_ids:undefined})}})},check_all_items:function(){var c=document.getElementById("check_all"),d=document.getElementsByTagName("input"),f=0,e;if(c.checked===true){for(e=0;e<d.length;e++){if(d[e].name.indexOf("id")!==-1){d[e].checked=true;f++}}}else{for(e=0;e<d.length;e++){if(d[e].name.indexOf("id")!==-1){d[e].checked=false}}}this.init_grid_elements()},go_page_one:function(){var c=this.grid.get("cur_page");if(c!==null&&c!==undefined&&c!=="all"){this.grid.set("cur_page",1)}},template_body:function(t){var m="";var u=0;var g=t.items.length;if(g==0){m+='<tr><td colspan="100"><em>No Items</em></td></tr>';u=1}for(var h in t.items){var r=t.items[h];var c=r.encode_id;var k="grid-"+h+"-popup";m+="<tr ";if(t.current_item_id==r.id){m+='class="current"'}m+=">";if(t.show_item_checkboxes){m+='<td style="width: 1.5em;"><input type="checkbox" name="id" value="'+c+'" id="'+c+'" class="grid-row-select-checkbox" /></td>'}for(j in t.columns){var f=t.columns[j];if(f.visible){var e="";if(f.nowrap){e='style="white-space:nowrap;"'}var s=r.column_config[f.label];var l=s.link;var n=s.value;var q=s.inbound;if(jQuery.type(n)==="string"){n=n.replace(/\/\//g,"/")}var d="";var p="";if(f.attach_popup){d="grid-"+h+"-popup";p="menubutton";if(l!=""){p+=" split"}p+=" popup"}m+="<td "+e+">";if(l){if(t.operations.length!=0){m+='<div id="'+d+'" class="'+p+'" style="float: left;">'}var o="";if(q){o="use-inbound"}else{o="use-outbound"}m+='<a class="label '+o+'" href="'+l+'" onclick="return false;">'+n+"</a>";if(t.operations.length!=0){m+="</div>"}}else{m+='<div id="'+d+'" class="'+p+'"><label id="'+f.label_id_prefix+c+'" for="'+c+'">'+n+"</label></div>"}m+="</td>"}}m+="</tr>";u++}return m},template_footer:function(q){var m="";if(q.use_paging&&q.num_pages>1){var o=q.num_page_links;var c=q.cur_page_num;var p=q.num_pages;var l=o/2;var k=c-l;var g=0;if(k==0){k=1;g=l-(c-k)}var f=l+g;var e=c+f;if(e<=p){max_offset=0}else{e=p;max_offset=f-(e+1-c)}if(max_offset!=0){k-=max_offset;if(k<1){k=1}}m+='<tr id="page-links-row">';if(q.show_item_checkboxes){m+="<td></td>"}m+='<td colspan="100"><span id="page-link-container">Page:';if(k>1){m+='<span class="page-link" id="page-link-1"><a href="'+this.grid.get_url({page:n})+'" page_num="1" onclick="return false;">1</a></span> ...'}for(var n=k;n<e+1;n++){if(n==q.cur_page_num){m+='<span class="page-link inactive-link" id="page-link-'+n+'">'+n+"</span>"}else{m+='<span class="page-link" id="page-link-'+n+'"><a href="'+this.grid.get_url({page:n})+'" onclick="return false;" page_num="'+n+'">'+n+"</a></span>"}}if(e<p){m+='...<span class="page-link" id="page-link-'+p+'"><a href="'+this.grid.get_url({page:p})+'" onclick="return false;" page_num="'+p+'">'+p+"</a></span>"}m+="</span>";m+='<span class="page-link" id="show-all-link-span"> | <a href="'+this.grid.get_url({page:"all"})+'" onclick="return false;" page_num="all">Show All</a></span></td></tr>'}if(q.show_item_checkboxes){m+='<tr><input type="hidden" id="operation" name="operation" value=""><td></td><td colspan="100">For <span class="grid-selected-count"></span> selected '+q.get_class_plural+": ";for(i in q.operations){var d=q.operations[i];if(d.allow_multiple){m+='<input type="button" value="'+d.label+'" class="action-button" onclick="gridView.submit_operation(this, \''+d.confirm+"')\"> "}}m+="</td></tr>"}var h=false;for(i in q.operations){if(q.operations[i].global_operation){h=true;break}}if(h){m+='<tr><td colspan="100">';for(i in q.operations){var d=q.operations[i];if(d.global_operation){m+='<a class="action-button" href="'+d.global_operation+'">'+d.label+"</a>"}}m+="</td></tr>"}if(q.legend){m+='<tr><td colspan="100">'+q.legend+"</td></tr>"}return m},template_message:function(c){return'<p><div class="'+c.status+'message transient-message">'+c.message+'</div><div style="clear: both"></div></p>'}});return{Grid:a,GridView:b}});
\ No newline at end of file
+jQuery.ajaxSettings.traditional=true;define(["mvc/ui"],function(){var a=Backbone.Model.extend({defaults:{url_base:"",async:false,async_ops:[],categorical_filters:[],filters:{},sort_key:null,show_item_checkboxes:false,advanced_search:false,cur_page:1,num_pages:1,operation:undefined,item_ids:undefined},can_async_op:function(c){return _.indexOf(this.attributes.async_ops,c)!==-1},add_filter:function(g,h,d){if(d){var e=this.attributes.filters[g],c;if(e===null||e===undefined){c=h}else{if(typeof(e)=="string"){if(e=="All"){c=h}else{var f=[];f[0]=e;f[1]=h;c=f}}else{c=e;c.push(h)}}this.attributes.filters[g]=c}else{this.attributes.filters[g]=h}},remove_filter:function(d,g){var c=this.attributes.filters[d];if(c===null||c===undefined){return false}var f=true;if(typeof(c)==="string"){if(c=="All"){f=false}else{delete this.attributes.filters[d]}}else{var e=_.indexOf(c,g);if(e!==-1){c.splice(e,1)}else{f=false}}return f},get_url_data:function(){var c={async:this.attributes.async,sort:this.attributes.sort_key,page:this.attributes.cur_page,show_item_checkboxes:this.attributes.show_item_checkboxes,advanced_search:this.attributes.advanced_search};if(this.attributes.operation){c.operation=this.attributes.operation}if(this.attributes.item_ids){c.id=this.attributes.item_ids}var d=this;_.each(_.pairs(d.attributes.filters),function(e){c["f-"+e[0]]=e[1]});return c},get_url:function(c){return this.get("url_base")+"?"+$.param(this.get_url_data())+"&"+$.param(c)}});var b=Backbone.View.extend({grid:null,initialize:function(c){this.init_grid(c);this.init_grid_controls();$("input[type=text]").each(function(){$(this).click(function(){$(this).select()}).keyup(function(){$(this).css("font-style","normal")})})},handle_refresh:function(c){if(c){if($.inArray("history",c)>-1){if(top.Galaxy&&top.Galaxy.currHistoryPanel){top.Galaxy.currHistoryPanel.loadCurrentHistory()}}}},init_grid:function(e){this.grid=new a(e);var d=this.grid.attributes;this.handle_refresh(d.refresh_frames);var c=this.grid.get("url_base");c=c.replace(/^.*\/\/[^\/]+/,"");this.grid.set("url_base",c);$("#grid-table-body").html(this.template_body(d));$("#grid-table-footer").html(this.template_footer(d));if(d.message){$("#grid-message").html(this.template_message(d));if(d.use_hide_message){setTimeout(function(){$("#grid-message").html("")},5000)}}this.init_grid_elements();init_refresh_on_change()},init_grid_controls:function(){$(".submit-image").each(function(){$(this).mousedown(function(){$(this).addClass("gray-background")});$(this).mouseup(function(){$(this).removeClass("gray-background")})});var c=this;$(".sort-link").each(function(){$(this).click(function(){c.set_sort_condition($(this).attr("sort_key"));return false})});$(".categorical-filter > a").each(function(){$(this).click(function(){c.set_categorical_filter($(this).attr("filter_key"),$(this).attr("filter_val"));return false})});$(".text-filter-form").each(function(){$(this).submit(function(){var g=$(this).attr("column_key");var f=$("#input-"+g+"-filter");var h=f.val();f.val("");c.add_filter_condition(g,h);return false})});var d=$("#input-tags-filter");if(d.length){d.autocomplete(this.grid.history_tag_autocomplete_url,{selectFirst:false,autoFill:false,highlight:false,mustMatch:false})}var e=$("#input-name-filter");if(e.length){e.autocomplete(this.grid.history_name_autocomplete_url,{selectFirst:false,autoFill:false,highlight:false,mustMatch:false})}$(".advanced-search-toggle").each(function(){$(this).click(function(){$("#standard-search").slideToggle("fast");$("#advanced-search").slideToggle("fast");return false})})},init_grid_elements:function(){$(".grid").each(function(){var s=$(this).find("input.grid-row-select-checkbox");var r=$(this).find("span.grid-selected-count");var t=function(){r.text($(s).filter(":checked").length)};$(s).each(function(){$(this).change(t)});t()});if($(".community_rating_star").length!==0){$(".community_rating_star").rating({})}var q=this.grid.attributes;var p=this;$(".page-link > a").each(function(){$(this).click(function(){p.set_page($(this).attr("page_num"));return false})});$(".use-inbound").each(function(){$(this).click(function(r){p.execute({href:$(this).attr("href"),inbound:true});return false})});$(".use-outbound").each(function(){$(this).click(function(r){p.execute({href:$(this).attr("href")});return false})});var f=q.items.length;if(f==0){return}for(var k in q.items){var o=q.items[k];var l=$("#grid-"+k+"-popup");l.off();var d=new PopupMenu(l);for(var h in q.operations){var e=q.operations[h];var m=e.label;var c=o.operation_config[m];var g=o.encode_id;if(c.allowed&&e.allow_popup){var n={html:e.label,href:c.url_args,target:c.target,confirmation_text:e.confirm,inbound:e.inbound};n.func=function(t){t.preventDefault();var s=$(t.target).html();var r=this.findItemByHtml(s);p.execute(r)};d.addItem(n)}}}},add_filter_condition:function(e,g){if(g===""){return false}this.grid.add_filter(e,g,true);var f=$("<span>"+g+"<a href='javascript:void(0);'><span class='delete-search-icon' /></span></a>");f.addClass("text-filter-val");var d=this;f.click(function(){d.grid.remove_filter(e,g);$(this).remove();d.go_page_one();d.execute()});var c=$("#"+e+"-filtering-criteria");c.append(f);this.go_page_one();this.execute()},set_sort_condition:function(h){var g=this.grid.get("sort_key");var f=h;if(g.indexOf(h)!==-1){if(g.substring(0,1)!=="-"){f="-"+h}else{}}$(".sort-arrow").remove();var e=(f.substring(0,1)=="-")?"↑":"↓";var c=$("<span>"+e+"</span>").addClass("sort-arrow");var d=$("#"+h+"-header");d.append(c);this.grid.set("sort_key",f);this.go_page_one();this.execute()},set_categorical_filter:function(e,g){var d=this.grid.get("categorical_filters")[e],f=this.grid.get("filters")[e];var c=this;$("."+e+"-filter").each(function(){var m=$.trim($(this).text());var k=d[m];var l=k[e];if(l==g){$(this).empty();$(this).addClass("current-filter");$(this).append(m)}else{if(l==f){$(this).empty();var h=$("<a href='#'>"+m+"</a>");h.click(function(){c.set_categorical_filter(e,l)});$(this).removeClass("current-filter");$(this).append(h)}}});this.grid.add_filter(e,g);this.go_page_one();this.execute()},set_page:function(c){var d=this;$(".page-link").each(function(){var k=$(this).attr("id"),g=parseInt(k.split("-")[2],10),e=d.grid.get("cur_page"),h;if(g===c){h=$(this).children().text();$(this).empty();$(this).addClass("inactive-link");$(this).text(h)}else{if(g===e){h=$(this).text();$(this).empty();$(this).removeClass("inactive-link");var f=$("<a href='#'>"+h+"</a>");f.click(function(){d.set_page(g)});$(this).append(f)}}});if(c==="all"){this.grid.set("cur_page",c)}else{this.grid.set("cur_page",parseInt(c,10))}this.execute()},submit_operation:function(f,g){var e=$('input[name="id"]:checked').length;if(!e>0){return false}var d=$(f).val();var c=[];$("input[name=id]:checked").each(function(){c.push($(this).val())});this.execute({operation:d,id:c,confirmation_text:g});return true},execute:function(n){var f=null;var e=null;var g=null;var c=null;var m=null;if(n){e=n.href;g=n.operation;f=n.id;c=n.confirmation_text;m=n.inbound;if(e!==undefined&&e.indexOf("operation=")!=-1){var l=e.split("?");if(l.length>1){var k=l[1];var d=k.split("&");for(var h=0;h<d.length;h++){if(d[h].indexOf("operation")!=-1){g=d[h].split("=")[1];g=g.replace(/\+/g," ")}else{if(d[h].indexOf("id")!=-1){f=d[h].split("=")[1]}}}}}}if(g&&f){if(c&&c!=""&&c!="None"&&c!="null"){if(!confirm(c)){return false}}g=g.toLowerCase();this.grid.set({operation:g,item_ids:f});if(this.grid.can_async_op(g)){this.update_grid()}else{this.go_to(m,"")}return false}if(e){this.go_to(m,e);return false}if(this.grid.get("async")){this.update_grid()}else{this.go_to(m,"")}return false},go_to:function(f,d){var e=this.grid.get("async");this.grid.set("async",false);advanced_search=$("#advanced-search").is(":visible");this.grid.set("advanced_search",advanced_search);if(!d){d=this.grid.get("url_base")+"?"+$.param(this.grid.get_url_data())}this.grid.set({operation:undefined,item_ids:undefined,async:e});if(f){var c=$(".grid-header").closest(".inbound");if(c.length!==0){c.load(d);return}}window.location=d},update_grid:function(){var d=(this.grid.get("operation")?"POST":"GET");$(".loading-elt-overlay").show();var c=this;$.ajax({type:d,url:c.grid.get("url_base"),data:c.grid.get_url_data(),error:function(e){alert("Grid refresh failed")},success:function(e){c.init_grid($.parseJSON(e));$(".loading-elt-overlay").hide()},complete:function(){c.grid.set({operation:undefined,item_ids:undefined})}})},check_all_items:function(){var c=document.getElementById("check_all"),d=document.getElementsByTagName("input"),f=0,e;if(c.checked===true){for(e=0;e<d.length;e++){if(d[e].name.indexOf("id")!==-1){d[e].checked=true;f++}}}else{for(e=0;e<d.length;e++){if(d[e].name.indexOf("id")!==-1){d[e].checked=false}}}this.init_grid_elements()},go_page_one:function(){var c=this.grid.get("cur_page");if(c!==null&&c!==undefined&&c!=="all"){this.grid.set("cur_page",1)}},template_body:function(t){var m="";var u=0;var g=t.items.length;if(g==0){m+='<tr><td colspan="100"><em>No Items</em></td></tr>';u=1}for(var h in t.items){var r=t.items[h];var c=r.encode_id;var k="grid-"+h+"-popup";m+="<tr ";if(t.current_item_id==r.id){m+='class="current"'}m+=">";if(t.show_item_checkboxes){m+='<td style="width: 1.5em;"><input type="checkbox" name="id" value="'+c+'" id="'+c+'" class="grid-row-select-checkbox" /></td>'}for(j in t.columns){var f=t.columns[j];if(f.visible){var e="";if(f.nowrap){e='style="white-space:nowrap;"'}var s=r.column_config[f.label];var l=s.link;var n=s.value;var q=s.inbound;if(jQuery.type(n)==="string"){n=n.replace(/\/\//g,"/")}var d="";var p="";if(f.attach_popup){d="grid-"+h+"-popup";p="menubutton";if(l!=""){p+=" split"}p+=" popup"}m+="<td "+e+">";if(l){if(t.operations.length!=0){m+='<div id="'+d+'" class="'+p+'" style="float: left;">'}var o="";if(q){o="use-inbound"}else{o="use-outbound"}m+='<a class="label '+o+'" href="'+l+'" onclick="return false;">'+n+"</a>";if(t.operations.length!=0){m+="</div>"}}else{m+='<div id="'+d+'" class="'+p+'"><label id="'+f.label_id_prefix+c+'" for="'+c+'">'+n+"</label></div>"}m+="</td>"}}m+="</tr>";u++}return m},template_footer:function(q){var m="";if(q.use_paging&&q.num_pages>1){var o=q.num_page_links;var c=q.cur_page_num;var p=q.num_pages;var l=o/2;var k=c-l;var g=0;if(k<=0){k=1;g=l-(c-k)}var f=l+g;var e=c+f;if(e<=p){max_offset=0}else{e=p;max_offset=f-(e+1-c)}if(max_offset!=0){k-=max_offset;if(k<1){k=1}}m+='<tr id="page-links-row">';if(q.show_item_checkboxes){m+="<td></td>"}m+='<td colspan="100"><span id="page-link-container">Page:';if(k>1){m+='<span class="page-link" id="page-link-1"><a href="'+this.grid.get_url({page:n})+'" page_num="1" onclick="return false;">1</a></span> ...'}for(var n=k;n<e+1;n++){if(n==q.cur_page_num){m+='<span class="page-link inactive-link" id="page-link-'+n+'">'+n+"</span>"}else{m+='<span class="page-link" id="page-link-'+n+'"><a href="'+this.grid.get_url({page:n})+'" onclick="return false;" page_num="'+n+'">'+n+"</a></span>"}}if(e<p){m+='...<span class="page-link" id="page-link-'+p+'"><a href="'+this.grid.get_url({page:p})+'" onclick="return false;" page_num="'+p+'">'+p+"</a></span>"}m+="</span>";m+='<span class="page-link" id="show-all-link-span"> | <a href="'+this.grid.get_url({page:"all"})+'" onclick="return false;" page_num="all">Show All</a></span></td></tr>'}if(q.show_item_checkboxes){m+='<tr><input type="hidden" id="operation" name="operation" value=""><td></td><td colspan="100">For <span class="grid-selected-count"></span> selected '+q.get_class_plural+": ";for(i in q.operations){var d=q.operations[i];if(d.allow_multiple){m+='<input type="button" value="'+d.label+'" class="action-button" onclick="gridView.submit_operation(this, \''+d.confirm+"')\"> "}}m+="</td></tr>"}var h=false;for(i in q.operations){if(q.operations[i].global_operation){h=true;break}}if(h){m+='<tr><td colspan="100">';for(i in q.operations){var d=q.operations[i];if(d.global_operation){m+='<a class="action-button" href="'+d.global_operation+'">'+d.label+"</a>"}}m+="</td></tr>"}if(q.legend){m+='<tr><td colspan="100">'+q.legend+"</td></tr>"}return m},template_message:function(c){return'<p><div class="'+c.status+'message transient-message">'+c.message+'</div><div style="clear: both"></div></p>'}});return{Grid:a,GridView:b}});
\ No newline at end of file
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/d270d3cf7627/
Changeset: d270d3cf7627
Branch: stable
User: greg
Date: 2014-02-19 19:05:25
Summary: Make managing an in-memory registry of bi-directional installed repository dependency relationships a configurable option for Galaxy instances.
Affected #: 6 files
diff -r 1298d3f6aca59825d0eb3d32afd5686c4b1b9294 -r d270d3cf7627a42b6fac2aa69701deadb89c8ffc lib/galaxy/config.py
--- a/lib/galaxy/config.py
+++ b/lib/galaxy/config.py
@@ -95,6 +95,7 @@
self.tool_data_table_config_path = resolve_path( kwargs.get( 'tool_data_table_config_path', 'tool_data_table_conf.xml' ), self.root )
self.shed_tool_data_table_config = resolve_path( kwargs.get( 'shed_tool_data_table_config', 'shed_tool_data_table_conf.xml' ), self.root )
self.enable_tool_shed_check = string_as_bool( kwargs.get( 'enable_tool_shed_check', False ) )
+ self.manage_dependency_relationships = string_as_bool( kwargs.get( 'manage_dependency_relationships', True ) )
self.running_functional_tests = string_as_bool( kwargs.get( 'running_functional_tests', False ) )
self.hours_between_check = kwargs.get( 'hours_between_check', 12 )
try:
diff -r 1298d3f6aca59825d0eb3d32afd5686c4b1b9294 -r d270d3cf7627a42b6fac2aa69701deadb89c8ffc lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py
--- a/lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py
+++ b/lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py
@@ -271,9 +271,10 @@
if remove_from_disk_checked:
tool_shed_repository.status = trans.install_model.ToolShedRepository.installation_status.UNINSTALLED
tool_shed_repository.error_message = None
- # Remove the uninstalled repository and any tool dependencies from the in-memory dictionaries in the
- # installed_repository_manager.
- trans.app.installed_repository_manager.handle_repository_uninstall( tool_shed_repository )
+ if trans.app.config.manage_dependency_relationships:
+ # Remove the uninstalled repository and any tool dependencies from the in-memory dictionaries in the
+ # installed_repository_manager.
+ trans.app.installed_repository_manager.handle_repository_uninstall( tool_shed_repository )
else:
tool_shed_repository.status = trans.install_model.ToolShedRepository.installation_status.DEACTIVATED
trans.install_model.context.add( tool_shed_repository )
diff -r 1298d3f6aca59825d0eb3d32afd5686c4b1b9294 -r d270d3cf7627a42b6fac2aa69701deadb89c8ffc lib/tool_shed/galaxy_install/installed_repository_manager.py
--- a/lib/tool_shed/galaxy_install/installed_repository_manager.py
+++ b/lib/tool_shed/galaxy_install/installed_repository_manager.py
@@ -62,8 +62,9 @@
# whose values are a list of tuples defining tool_dependency objects (whose status is 'Installed') that require the key
# at runtime. The value defines the entire tool dependency tree.
self.installed_runtime_dependent_tool_dependencies_of_installed_tool_dependencies = {}
- # Load defined dependency relationships for installed tool shed repositories and their contents.
- self.load_dependency_relationships()
+ if app.config.manage_dependency_relationships:
+ # Load defined dependency relationships for installed tool shed repositories and their contents.
+ self.load_dependency_relationships()
def add_entry_to_installed_repository_dependencies_of_installed_repositories( self, repository ):
"""
diff -r 1298d3f6aca59825d0eb3d32afd5686c4b1b9294 -r d270d3cf7627a42b6fac2aa69701deadb89c8ffc lib/tool_shed/galaxy_install/repository_util.py
--- a/lib/tool_shed/galaxy_install/repository_util.py
+++ b/lib/tool_shed/galaxy_install/repository_util.py
@@ -602,8 +602,9 @@
suc.update_tool_shed_repository_status( trans.app,
tool_shed_repository,
trans.install_model.ToolShedRepository.installation_status.INSTALLED )
- # Add the installed repository and any tool dependencies to the in-memory dictionaries in the installed_repository_manager.
- trans.app.installed_repository_manager.handle_repository_install( tool_shed_repository )
+ if trans.app.config.manage_dependency_relationships:
+ # Add the installed repository and any tool dependencies to the in-memory dictionaries in the installed_repository_manager.
+ trans.app.installed_repository_manager.handle_repository_install( tool_shed_repository )
else:
# An error occurred while cloning the repository, so reset everything necessary to enable another attempt.
set_repository_attributes( trans,
diff -r 1298d3f6aca59825d0eb3d32afd5686c4b1b9294 -r d270d3cf7627a42b6fac2aa69701deadb89c8ffc lib/tool_shed/util/common_install_util.py
--- a/lib/tool_shed/util/common_install_util.py
+++ b/lib/tool_shed/util/common_install_util.py
@@ -507,8 +507,9 @@
if tool_dependency and tool_dependency.status in [ app.install_model.ToolDependency.installation_status.INSTALLED,
app.install_model.ToolDependency.installation_status.ERROR ]:
installed_tool_dependencies.append( tool_dependency )
- # Add the tool_dependency to the in-memory dictionaries in the installed_repository_manager.
- app.installed_repository_manager.handle_tool_dependency_install( tool_shed_repository, tool_dependency )
+ if app.config.manage_dependency_relationships:
+ # Add the tool_dependency to the in-memory dictionaries in the installed_repository_manager.
+ app.installed_repository_manager.handle_tool_dependency_install( tool_shed_repository, tool_dependency )
elif elem.tag == 'set_environment':
# <set_environment version="1.0">
# <environment_variable name="R_SCRIPT_PATH"action="set_to">$REPOSITORY_INSTALL_DIR</environment_variable>
diff -r 1298d3f6aca59825d0eb3d32afd5686c4b1b9294 -r d270d3cf7627a42b6fac2aa69701deadb89c8ffc universe_wsgi.ini.sample
--- a/universe_wsgi.ini.sample
+++ b/universe_wsgi.ini.sample
@@ -152,6 +152,11 @@
#enable_tool_shed_check = False
#hours_between_check = 12
+# Enable use of an in-memory registry with bi-directional relationships
+# between repositories (i.e., in addition to lists of dependencies for a
+# repository, keep an in-memory registry of dependent items for each repository.
+#manage_dependency_relationships = True
+
# XML config file that contains data table entries for the ToolDataTableManager. This file is manually
# maintained by the Galaxy administrator.
#tool_data_table_config_path = tool_data_table_conf.xml
https://bitbucket.org/galaxy/galaxy-central/commits/ef0654f99261/
Changeset: ef0654f99261
User: inithello
Date: 2014-02-19 19:09:03
Summary: Merge bugfix from stable.
Affected #: 1 file
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: greg: Make managing an in-memory registry of bi-directional installed repository dependency relationships a configurable option for Galaxy instances.
by commits-noreply@bitbucket.org 19 Feb '14
by commits-noreply@bitbucket.org 19 Feb '14
19 Feb '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/4df1be355e4f/
Changeset: 4df1be355e4f
User: greg
Date: 2014-02-19 19:05:25
Summary: Make managing an in-memory registry of bi-directional installed repository dependency relationships a configurable option for Galaxy instances.
Affected #: 6 files
diff -r e51429649b44d5b434a6b6f4e10daa1dbf390c20 -r 4df1be355e4f7cdbbc927027ce60b81cf222956f lib/galaxy/config.py
--- a/lib/galaxy/config.py
+++ b/lib/galaxy/config.py
@@ -95,6 +95,7 @@
self.tool_data_table_config_path = resolve_path( kwargs.get( 'tool_data_table_config_path', 'tool_data_table_conf.xml' ), self.root )
self.shed_tool_data_table_config = resolve_path( kwargs.get( 'shed_tool_data_table_config', 'shed_tool_data_table_conf.xml' ), self.root )
self.enable_tool_shed_check = string_as_bool( kwargs.get( 'enable_tool_shed_check', False ) )
+ self.manage_dependency_relationships = string_as_bool( kwargs.get( 'manage_dependency_relationships', True ) )
self.running_functional_tests = string_as_bool( kwargs.get( 'running_functional_tests', False ) )
self.hours_between_check = kwargs.get( 'hours_between_check', 12 )
try:
diff -r e51429649b44d5b434a6b6f4e10daa1dbf390c20 -r 4df1be355e4f7cdbbc927027ce60b81cf222956f lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py
--- a/lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py
+++ b/lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py
@@ -271,9 +271,10 @@
if remove_from_disk_checked:
tool_shed_repository.status = trans.install_model.ToolShedRepository.installation_status.UNINSTALLED
tool_shed_repository.error_message = None
- # Remove the uninstalled repository and any tool dependencies from the in-memory dictionaries in the
- # installed_repository_manager.
- trans.app.installed_repository_manager.handle_repository_uninstall( tool_shed_repository )
+ if trans.app.config.manage_dependency_relationships:
+ # Remove the uninstalled repository and any tool dependencies from the in-memory dictionaries in the
+ # installed_repository_manager.
+ trans.app.installed_repository_manager.handle_repository_uninstall( tool_shed_repository )
else:
tool_shed_repository.status = trans.install_model.ToolShedRepository.installation_status.DEACTIVATED
trans.install_model.context.add( tool_shed_repository )
diff -r e51429649b44d5b434a6b6f4e10daa1dbf390c20 -r 4df1be355e4f7cdbbc927027ce60b81cf222956f lib/tool_shed/galaxy_install/installed_repository_manager.py
--- a/lib/tool_shed/galaxy_install/installed_repository_manager.py
+++ b/lib/tool_shed/galaxy_install/installed_repository_manager.py
@@ -62,8 +62,9 @@
# whose values are a list of tuples defining tool_dependency objects (whose status is 'Installed') that require the key
# at runtime. The value defines the entire tool dependency tree.
self.installed_runtime_dependent_tool_dependencies_of_installed_tool_dependencies = {}
- # Load defined dependency relationships for installed tool shed repositories and their contents.
- self.load_dependency_relationships()
+ if app.config.manage_dependency_relationships:
+ # Load defined dependency relationships for installed tool shed repositories and their contents.
+ self.load_dependency_relationships()
def add_entry_to_installed_repository_dependencies_of_installed_repositories( self, repository ):
"""
diff -r e51429649b44d5b434a6b6f4e10daa1dbf390c20 -r 4df1be355e4f7cdbbc927027ce60b81cf222956f lib/tool_shed/galaxy_install/repository_util.py
--- a/lib/tool_shed/galaxy_install/repository_util.py
+++ b/lib/tool_shed/galaxy_install/repository_util.py
@@ -602,8 +602,9 @@
suc.update_tool_shed_repository_status( trans.app,
tool_shed_repository,
trans.install_model.ToolShedRepository.installation_status.INSTALLED )
- # Add the installed repository and any tool dependencies to the in-memory dictionaries in the installed_repository_manager.
- trans.app.installed_repository_manager.handle_repository_install( tool_shed_repository )
+ if trans.app.config.manage_dependency_relationships:
+ # Add the installed repository and any tool dependencies to the in-memory dictionaries in the installed_repository_manager.
+ trans.app.installed_repository_manager.handle_repository_install( tool_shed_repository )
else:
# An error occurred while cloning the repository, so reset everything necessary to enable another attempt.
set_repository_attributes( trans,
diff -r e51429649b44d5b434a6b6f4e10daa1dbf390c20 -r 4df1be355e4f7cdbbc927027ce60b81cf222956f lib/tool_shed/util/common_install_util.py
--- a/lib/tool_shed/util/common_install_util.py
+++ b/lib/tool_shed/util/common_install_util.py
@@ -507,8 +507,9 @@
if tool_dependency and tool_dependency.status in [ app.install_model.ToolDependency.installation_status.INSTALLED,
app.install_model.ToolDependency.installation_status.ERROR ]:
installed_tool_dependencies.append( tool_dependency )
- # Add the tool_dependency to the in-memory dictionaries in the installed_repository_manager.
- app.installed_repository_manager.handle_tool_dependency_install( tool_shed_repository, tool_dependency )
+ if app.config.manage_dependency_relationships:
+ # Add the tool_dependency to the in-memory dictionaries in the installed_repository_manager.
+ app.installed_repository_manager.handle_tool_dependency_install( tool_shed_repository, tool_dependency )
elif elem.tag == 'set_environment':
# <set_environment version="1.0">
# <environment_variable name="R_SCRIPT_PATH"action="set_to">$REPOSITORY_INSTALL_DIR</environment_variable>
diff -r e51429649b44d5b434a6b6f4e10daa1dbf390c20 -r 4df1be355e4f7cdbbc927027ce60b81cf222956f universe_wsgi.ini.sample
--- a/universe_wsgi.ini.sample
+++ b/universe_wsgi.ini.sample
@@ -152,6 +152,11 @@
#enable_tool_shed_check = False
#hours_between_check = 12
+# Enable use of an in-memory registry with bi-directional relationships
+# between repositories (i.e., in addition to lists of dependencies for a
+# repository, keep an in-memory registry of dependent items for each repository.
+#manage_dependency_relationships = True
+
# XML config file that contains data table entries for the ToolDataTableManager. This file is manually
# maintained by the Galaxy administrator.
#tool_data_table_config_path = tool_data_table_conf.xml
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
3 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/1298d3f6aca5/
Changeset: 1298d3f6aca5
Branch: stable
User: natefoo
Date: 2014-02-19 19:00:33
Summary: Stop jobs when all output datasets are deleted via the API.
Affected #: 3 files
diff -r 44968207ddd283d0023c72e3d25fd39b1c71eb99 -r 1298d3f6aca59825d0eb3d32afd5686c4b1b9294 lib/galaxy/web/base/controller.py
--- a/lib/galaxy/web/base/controller.py
+++ b/lib/galaxy/web/base/controller.py
@@ -849,6 +849,18 @@
break
return job
+ def stop_hda_creating_job( self, hda ):
+ """
+ Stops an HDA's creating job if all the job's other outputs are deleted.
+ """
+ if hda.parent_id is None and len( hda.creating_job_associations ) > 0:
+ # Mark associated job for deletion
+ job = hda.creating_job_associations[0].job
+ if job.state in [ self.app.model.Job.states.QUEUED, self.app.model.Job.states.RUNNING, self.app.model.Job.states.NEW ]:
+ # Are *all* of the job's other output datasets deleted?
+ if job.check_if_output_datasets_deleted():
+ job.mark_deleted( self.app.config.track_jobs_in_database )
+ self.app.job_manager.job_stop_queue.put( job.id )
class UsesLibraryMixin:
diff -r 44968207ddd283d0023c72e3d25fd39b1c71eb99 -r 1298d3f6aca59825d0eb3d32afd5686c4b1b9294 lib/galaxy/webapps/galaxy/api/history_contents.py
--- a/lib/galaxy/webapps/galaxy/api/history_contents.py
+++ b/lib/galaxy/webapps/galaxy/api/history_contents.py
@@ -278,6 +278,8 @@
# get_dataset can return a string during an error
if hda and isinstance( hda, trans.model.HistoryDatasetAssociation ):
changed = self.set_hda_from_dict( trans, hda, payload )
+ if payload.get( 'deleted', False ):
+ self.stop_hda_creating_job( hda )
except Exception, exception:
log.error( 'Update of history (%s), HDA (%s) failed: %s',
history_id, id, str( exception ), exc_info=True )
@@ -347,6 +349,8 @@
trans.sa_session.flush()
rval[ 'purged' ] = True
+ self.stop_hda_creating_job( hda )
+
trans.sa_session.flush()
rval[ 'deleted' ] = True
diff -r 44968207ddd283d0023c72e3d25fd39b1c71eb99 -r 1298d3f6aca59825d0eb3d32afd5686c4b1b9294 lib/galaxy/webapps/galaxy/controllers/dataset.py
--- a/lib/galaxy/webapps/galaxy/controllers/dataset.py
+++ b/lib/galaxy/webapps/galaxy/controllers/dataset.py
@@ -839,14 +839,7 @@
hda.mark_deleted()
hda.clear_associated_files()
trans.log_event( "Dataset id %s marked as deleted" % str(id) )
- if hda.parent_id is None and len( hda.creating_job_associations ) > 0:
- # Mark associated job for deletion
- job = hda.creating_job_associations[0].job
- if job.state in [ self.app.model.Job.states.QUEUED, self.app.model.Job.states.RUNNING, self.app.model.Job.states.NEW ]:
- # Are *all* of the job's other output datasets deleted?
- if job.check_if_output_datasets_deleted():
- job.mark_deleted( self.app.config.track_jobs_in_database )
- self.app.job_manager.job_stop_queue.put( job.id )
+ self.stop_hda_creating_job( hda )
trans.sa_session.flush()
except Exception, e:
msg = 'HDA deletion failed (encoded: %s, decoded: %s)' % ( dataset_id, id )
https://bitbucket.org/galaxy/galaxy-central/commits/0db8172d6d36/
Changeset: 0db8172d6d36
User: natefoo
Date: 2014-02-19 19:01:03
Summary: merge.
Affected #: 3 files
diff -r c85f8fb5d63e667b63e10cdce518254f56002f55 -r 0db8172d6d363ba1010df08a79f6db435f4f0ee7 lib/galaxy/web/base/controller.py
--- a/lib/galaxy/web/base/controller.py
+++ b/lib/galaxy/web/base/controller.py
@@ -892,6 +892,18 @@
break
return job
+ def stop_hda_creating_job( self, hda ):
+ """
+ Stops an HDA's creating job if all the job's other outputs are deleted.
+ """
+ if hda.parent_id is None and len( hda.creating_job_associations ) > 0:
+ # Mark associated job for deletion
+ job = hda.creating_job_associations[0].job
+ if job.state in [ self.app.model.Job.states.QUEUED, self.app.model.Job.states.RUNNING, self.app.model.Job.states.NEW ]:
+ # Are *all* of the job's other output datasets deleted?
+ if job.check_if_output_datasets_deleted():
+ job.mark_deleted( self.app.config.track_jobs_in_database )
+ self.app.job_manager.job_stop_queue.put( job.id )
class UsesLibraryMixin:
diff -r c85f8fb5d63e667b63e10cdce518254f56002f55 -r 0db8172d6d363ba1010df08a79f6db435f4f0ee7 lib/galaxy/webapps/galaxy/api/history_contents.py
--- a/lib/galaxy/webapps/galaxy/api/history_contents.py
+++ b/lib/galaxy/webapps/galaxy/api/history_contents.py
@@ -280,6 +280,8 @@
# get_dataset can return a string during an error
if hda and isinstance( hda, trans.model.HistoryDatasetAssociation ):
changed = self.set_hda_from_dict( trans, hda, payload )
+ if payload.get( 'deleted', False ):
+ self.stop_hda_creating_job( hda )
except Exception, exception:
log.error( 'Update of history (%s), HDA (%s) failed: %s',
history_id, id, str( exception ), exc_info=True )
@@ -349,6 +351,8 @@
trans.sa_session.flush()
rval[ 'purged' ] = True
+ self.stop_hda_creating_job( hda )
+
trans.sa_session.flush()
rval[ 'deleted' ] = True
diff -r c85f8fb5d63e667b63e10cdce518254f56002f55 -r 0db8172d6d363ba1010df08a79f6db435f4f0ee7 lib/galaxy/webapps/galaxy/controllers/dataset.py
--- a/lib/galaxy/webapps/galaxy/controllers/dataset.py
+++ b/lib/galaxy/webapps/galaxy/controllers/dataset.py
@@ -839,14 +839,7 @@
hda.mark_deleted()
hda.clear_associated_files()
trans.log_event( "Dataset id %s marked as deleted" % str(id) )
- if hda.parent_id is None and len( hda.creating_job_associations ) > 0:
- # Mark associated job for deletion
- job = hda.creating_job_associations[0].job
- if job.state in [ self.app.model.Job.states.QUEUED, self.app.model.Job.states.RUNNING, self.app.model.Job.states.NEW ]:
- # Are *all* of the job's other output datasets deleted?
- if job.check_if_output_datasets_deleted():
- job.mark_deleted( self.app.config.track_jobs_in_database )
- self.app.job_manager.job_stop_queue.put( job.id )
+ self.stop_hda_creating_job( hda )
trans.sa_session.flush()
except Exception, e:
msg = 'HDA deletion failed (encoded: %s, decoded: %s)' % ( dataset_id, id )
https://bitbucket.org/galaxy/galaxy-central/commits/e51429649b44/
Changeset: e51429649b44
User: natefoo
Date: 2014-02-19 19:02:12
Summary: merge.
Affected #: 6 files
diff -r 0db8172d6d363ba1010df08a79f6db435f4f0ee7 -r e51429649b44d5b434a6b6f4e10daa1dbf390c20 lib/galaxy/webapps/galaxy/controllers/history.py
--- a/lib/galaxy/webapps/galaxy/controllers/history.py
+++ b/lib/galaxy/webapps/galaxy/controllers/history.py
@@ -843,35 +843,6 @@
history. <br>You can <a href="%s">continue and import this history</a> or %s.
""" % ( web.url_for(controller='history', action='imp', id=id, confirm=True, referer=trans.request.referer ), referer_message ), use_panels=True )
- # Replaced with view (below) but kept (available via manual URL editing) for now
- @web.expose
- def original_view( self, trans, id=None, show_deleted=False, use_panels=True ):
- """View a history. If a history is importable, then it is viewable by any user."""
- # Get history to view.
- if not id:
- return trans.show_error_message( "You must specify a history you want to view." )
- history_to_view = self.get_history( trans, id, False)
- # Integrity checks.
- if not history_to_view:
- return trans.show_error_message( "The specified history does not exist." )
- # Admin users can view any history
- if( ( history_to_view.user != trans.user )
- and ( not trans.user_is_admin() )
- and ( not history_to_view.importable ) ):
- error( "Either you are not allowed to view this history or the owner of this history has not made it accessible." )
- # View history.
- show_deleted = galaxy.util.string_as_bool( show_deleted )
- datasets = self.get_history_datasets( trans, history_to_view, show_deleted=show_deleted )
- try:
- use_panels = galaxy.util.string_as_bool( use_panels )
- except:
- pass # already a bool
- return trans.stream_template_mako( "history/original_view.mako",
- history = history_to_view,
- datasets = datasets,
- show_deleted = show_deleted,
- use_panels = use_panels )
-
@web.expose
def view( self, trans, id=None, show_deleted=False, show_hidden=False, use_panels=True ):
"""
diff -r 0db8172d6d363ba1010df08a79f6db435f4f0ee7 -r e51429649b44d5b434a6b6f4e10daa1dbf390c20 static/scripts/mvc/ui.js
--- a/static/scripts/mvc/ui.js
+++ b/static/scripts/mvc/ui.js
@@ -783,77 +783,110 @@
* });
* $( '.myElement' ).modeButton( 'callModeFn', 'bler' );
*/
+ /** constructor */
function ModeButton( element, options ){
this.currModeIndex = 0;
- return this.init( element, options );
+ return this._init( element, options );
}
+ /** html5 data key to store this object inside an element */
ModeButton.prototype.DATA_KEY = 'mode-button';
+ /** default options */
ModeButton.prototype.defaults = {
- modes : [
- { mode: 'default' }
- ]
+ switchModesOnClick : true
};
- ModeButton.prototype.init = function _init( element, options ){
+ // ---- private interface
+ /** set up options, intial mode, and the click handler */
+ ModeButton.prototype._init = function _init( element, options ){
+ //console.debug( 'ModeButton._init:', element, options );
options = options || {};
this.$element = $( element );
this.options = jQuery.extend( true, {}, this.defaults, options );
+ if( !options.modes ){
+ throw new Error( 'ModeButton requires a "modes" array' );
+ }
var modeButton = this;
this.$element.click( function _ModeButtonClick( event ){
-
// call the curr mode fn
modeButton.callModeFn();
// inc the curr mode index
- modeButton._incModeIndex();
+ if( modeButton.options.switchModesOnClick ){ modeButton._incModeIndex(); }
// set the element html
$( this ).html( modeButton.options.modes[ modeButton.currModeIndex ].html );
});
-
- this.currModeIndex = 0;
- if( this.options.initialMode ){
- this.currModeIndex = this._getModeIndex( this.options.initialMode );
- }
- return this;
+ return this.reset();
};
-
-
- ModeButton.prototype._getModeIndex = function __getModeIndex( modeKey ){
- for( var i=0; i<this.options.modes.length; i+=1 ){
- if( this.options.modes[ i ].mode === modeKey ){ return i; }
- }
- throw new Error( 'mode not found: ' + modeKey );
- };
- ModeButton.prototype.getCurrMode = function _getCurrMode(){
- return this.options.modes[ this.currModeIndex ];
- };
- ModeButton.prototype.getMode = function _getMode( modeKey ){
- if( !modeKey ){ return this.getCurrMode(); }
- return this.options.modes[( this._getModeIndex( modeKey ) )];
- };
- ModeButton.prototype.hasMode = function _hasMode( modeKey ){
- return !!this.getMode( modeKey );
- };
- ModeButton.prototype.currentMode = function _currentMode(){
- return this.options.modes[ this.currModeIndex ];
- };
- ModeButton.prototype.setMode = function _setMode( newModeKey ){
- var newMode = this.getMode( newModeKey );
- this.$element.html( newMode.html || null );
- return this;
- };
- ModeButton.prototype._incModeIndex = function __incModeIndex(){
+ /** increment the mode index to the next in the array, looping back to zero if at the last */
+ ModeButton.prototype._incModeIndex = function _incModeIndex(){
this.currModeIndex += 1;
if( this.currModeIndex >= this.options.modes.length ){
this.currModeIndex = 0;
}
return this;
};
- ModeButton.prototype.callModeFn = function _callModeFn( modeKey ){
+ /** get the mode index in the modes array for the given key (mode name) */
+ ModeButton.prototype._getModeIndex = function _getModeIndex( modeKey ){
+ for( var i=0; i<this.options.modes.length; i+=1 ){
+ if( this.options.modes[ i ].mode === modeKey ){ return i; }
+ }
+ throw new Error( 'mode not found: ' + modeKey );
+ };
+ /** set the current mode to the one with the given index and set button html */
+ ModeButton.prototype._setModeByIndex = function _setModeByIndex( index ){
+ var newMode = this.options.modes[ index ];
+ if( !newMode ){
+ throw new Error( 'mode index not found: ' + index );
+ }
+ this.currModeIndex = index;
+ if( newMode.html ){
+ this.$element.html( newMode.html );
+ }
+ return this;
+ };
+
+ // ---- public interface
+ /** get the current mode object (not just the mode name) */
+ ModeButton.prototype.currentMode = function currentMode(){
+ return this.options.modes[ this.currModeIndex ];
+ };
+ /** return the mode key of the current mode */
+ ModeButton.prototype.current = function current(){
+ // sugar for returning mode name
+ return this.currentMode().mode;
+ };
+ /** get the mode with the given modeKey or the current mode if modeKey is undefined */
+ ModeButton.prototype.getMode = function getMode( modeKey ){
+ if( !modeKey ){ return this.currentMode(); }
+ return this.options.modes[( this._getModeIndex( modeKey ) )];
+ };
+ /** T/F if the button has the given mode */
+ ModeButton.prototype.hasMode = function hasMode( modeKey ){
+ try {
+ return !!this.getMode( modeKey );
+ } catch( err ){}
+ return false;
+ };
+ /** set the current mode to the mode with the given name */
+ ModeButton.prototype.setMode = function setMode( modeKey ){
+ return this._setModeByIndex( this._getModeIndex( modeKey ) );
+ };
+ /** reset to the initial mode */
+ ModeButton.prototype.reset = function reset(){
+ this.currModeIndex = 0;
+ if( this.options.initialMode ){
+ this.currModeIndex = this._getModeIndex( this.options.initialMode );
+ }
+ return this._setModeByIndex( this.currModeIndex );
+ };
+ /** manually call the click handler of the given mode */
+ ModeButton.prototype.callModeFn = function callModeFn( modeKey ){
var modeFn = this.getMode( modeKey ).onclick;
if( modeFn && jQuery.type( modeFn === 'function' ) ){
- return modeFn.call( this );
+ // call with the element as context (std jquery pattern)
+ modeFn.call( this.$element.get(0) );
+ return this;
}
return undefined;
};
@@ -861,26 +894,32 @@
// as jq plugin
jQuery.fn.extend({
modeButton : function $modeButton( options ){
- var nonOptionsArgs = jQuery.makeArray( arguments ).slice( 1 );
+ if( !this.size() ){ return this; }
+
//TODO: does map still work with jq multi selection (i.e. $( '.class-for-many-btns' ).modeButton)?
- return this.map( function(){
- var $this = $( this ),
- data = $this.data( 'mode-button' );
+ if( jQuery.type( options ) === 'object' ){
+ return this.map( function(){
+ var $this = $( this );
+ $this.data( 'mode-button', new ModeButton( $this, options ) );
+ return this;
+ });
+ }
- if( jQuery.type( options ) === 'object' ){
- data = new ModeButton( $this, options );
- $this.data( 'mode-button', data );
+ var $first = $( this[0] ),
+ button = $first.data( 'mode-button' );
+ console.debug( 'first, button', $first, button );
- } else if( data && jQuery.type( options ) === 'string' ){
- var fn = data[ options ];
- if( jQuery.type( fn ) === 'function' ){
- return fn.apply( data, nonOptionsArgs );
- }
- } else if ( data ){
- return data;
+ if( !button ){
+ throw new Error( 'modeButton needs an options object or string name of a function' );
+ }
+
+ if( button && jQuery.type( options ) === 'string' ){
+ var fnName = options;
+ if( button && jQuery.type( button[ fnName ] ) === 'function' ){
+ return button[ fnName ].apply( button, jQuery.makeArray( arguments ).slice( 1 ) );
}
- return this;
- });
+ }
+ return button;
}
});
}());
diff -r 0db8172d6d363ba1010df08a79f6db435f4f0ee7 -r e51429649b44d5b434a6b6f4e10daa1dbf390c20 static/scripts/packed/mvc/ui.js
--- a/static/scripts/packed/mvc/ui.js
+++ b/static/scripts/packed/mvc/ui.js
@@ -1,1 +1,1 @@
-var IconButton=Backbone.Model.extend({defaults:{title:"",icon_class:"",on_click:null,menu_options:null,is_menu_button:true,id:null,href:null,target:null,enabled:true,visible:true,tooltip_config:{}}});var IconButtonView=Backbone.View.extend({initialize:function(){this.model.attributes.tooltip_config={placement:"bottom"};this.model.bind("change",this.render,this)},render:function(){this.$el.tooltip("hide");var a=this.template(this.model.toJSON());a.tooltip(this.model.get("tooltip_config"));this.$el.replaceWith(a);this.setElement(a);return this},events:{click:"click"},click:function(a){if(_.isFunction(this.model.get("on_click"))){this.model.get("on_click")(a);return false}return true},template:function(b){var a='title="'+b.title+'" class="icon-button';if(b.is_menu_button){a+=" menu-button"}a+=" "+b.icon_class;if(!b.enabled){a+="_disabled"}a+='"';if(b.id){a+=' id="'+b.id+'"'}a+=' href="'+b.href+'"';if(b.target){a+=' target="'+b.target+'"'}if(!b.visible){a+=' style="display: none;"'}if(b.enabled){a="<a "+a+"/>"}else{a="<span "+a+"/>"}return $(a)}});var IconButtonCollection=Backbone.Collection.extend({model:IconButton});var IconButtonMenuView=Backbone.View.extend({tagName:"div",initialize:function(){this.render()},render:function(){var a=this;this.collection.each(function(d){var b=$("<a/>").attr("href","javascript:void(0)").attr("title",d.attributes.title).addClass("icon-button menu-button").addClass(d.attributes.icon_class).appendTo(a.$el).click(d.attributes.on_click);if(d.attributes.tooltip_config){b.tooltip(d.attributes.tooltip_config)}var c=d.get("options");if(c){make_popupmenu(b,c)}});return this}});var create_icon_buttons_menu=function(b,a){if(!a){a={}}var c=new IconButtonCollection(_.map(b,function(d){return new IconButton(_.extend(d,a))}));return new IconButtonMenuView({collection:c})};var Grid=Backbone.Collection.extend({});var GridView=Backbone.View.extend({});var PopupMenu=Backbone.View.extend({initialize:function(b,a){this.$button=b;if(!this.$button.size()){this.$button=$("<div/>")}this.options=a||[];var c=this;this.$button.click(function(d){$(".popmenu-wrapper").remove();c._renderAndShow(d);return false})},_renderAndShow:function(a){this.render();this.$el.appendTo("body").css(this._getShownPosition(a)).show();this._setUpCloseBehavior()},render:function(){this.$el.addClass("popmenu-wrapper").hide().css({position:"absolute"}).html(this.template(this.$button.attr("id"),this.options));if(this.options.length){var a=this;this.$el.find("li").each(function(c,b){var d=a.options[c];if(d.func){$(this).children("a.popupmenu-option").click(function(e){d.func.call(a,e,d)})}})}return this},template:function(b,a){return['<ul id="',b,'-menu" class="dropdown-menu">',this._templateOptions(a),"</ul>"].join("")},_templateOptions:function(a){if(!a.length){return"<li>(no options)</li>"}return _.map(a,function(d){if(d.divider){return'<li class="divider"></li>'}else{if(d.header){return['<li class="head"><a href="javascript:void(0);">',d.html,"</a></li>"].join("")}}var c=d.href||"javascript:void(0);",e=(d.target)?(' target="'+d.target+'"'):(""),b=(d.checked)?('<span class="fa fa-check"></span>'):("");return['<li><a class="popupmenu-option" href="',c,'"',e,">",b,d.html,"</a></li>"].join("")}).join("")},_getShownPosition:function(b){var c=this.$el.width();var a=b.pageX-c/2;a=Math.min(a,$(document).scrollLeft()+$(window).width()-c-5);a=Math.max(a,$(document).scrollLeft()+5);return{top:b.pageY,left:a}},_setUpCloseBehavior:function(){var c=this;function a(e){$(document).off("click.close_popup");if(window.parent!==window){try{$(window.parent.document).off("click.close_popup")}catch(d){}}else{try{$("iframe#galaxy_main").contents().off("click.close_popup")}catch(d){}}c.remove()}$("html").one("click.close_popup",a);if(window.parent!==window){try{$(window.parent.document).find("html").one("click.close_popup",a)}catch(b){}}else{try{$("iframe#galaxy_main").contents().one("click.close_popup",a)}catch(b){}}},addItem:function(b,a){a=(a>=0)?a:this.options.length;this.options.splice(a,0,b);return this},removeItem:function(a){if(a>=0){this.options.splice(a,1)}return this},findIndexByHtml:function(b){for(var a=0;a<this.options.length;a++){if(_.has(this.options[a],"html")&&(this.options[a].html===b)){return a}}return null},findItemByHtml:function(a){return this.options[(this.findIndexByHtml(a))]},toString:function(){return"PopupMenu"}});PopupMenu.create=function _create(b,a){return new PopupMenu(b,a)};PopupMenu.make_popupmenu=function(b,c){var a=[];_.each(c,function(f,d){var e={html:d};if(f===null){e.header=true}else{if(jQuery.type(f)==="function"){e.func=f}}a.push(e)});return new PopupMenu($(b),a)};PopupMenu.convertLinksToOptions=function(c,a){c=$(c);a=a||"a";var b=[];c.find(a).each(function(g,e){var f={},d=$(g);f.html=d.text();if(d.attr("href")){var j=d.attr("href"),k=d.attr("target"),h=d.attr("confirm");f.func=function(){if((h)&&(!confirm(h))){return}switch(k){case"_parent":window.parent.location=j;break;case"_top":window.top.location=j;break;default:window.location=j}}}b.push(f)});return b};PopupMenu.fromExistingDom=function(d,c,a){d=$(d);c=$(c);var b=PopupMenu.convertLinksToOptions(c,a);c.remove();return new PopupMenu(d,b)};PopupMenu.make_popup_menus=function(c,b,d){c=c||document;b=b||"div[popupmenu]";d=d||function(e,f){return"#"+e.attr("popupmenu")};var a=[];$(c).find(b).each(function(){var e=$(this),f=$(c).find(d(e,c));a.push(PopupMenu.fromDom(f,e));f.addClass("popup")});return a};var faIconButton=function(a){a=a||{};a.tooltipConfig=a.tooltipConfig||{placement:"bottom"};a.classes=["icon-btn"].concat(a.classes||[]);if(a.disabled){a.classes.push("disabled")}var b=['<a class="',a.classes.join(" "),'"',((a.title)?(' title="'+a.title+'"'):("")),((!a.disabled&&a.target)?(' target="'+a.target+'"'):("")),' href="',((!a.disabled&&a.href)?(a.href):("javascript:void(0);")),'">','<span class="fa ',a.faIcon,'"></span>',"</a>"].join("");var c=$(b).tooltip(a.tooltipConfig);if(_.isFunction(a.onclick)){c.click(a.onclick)}return c};function LoadingIndicator(a,c){var b=this;c=jQuery.extend({cover:false},c||{});function d(){var e=['<div class="loading-indicator">','<div class="loading-indicator-text">','<span class="fa fa-spinner fa-spin fa-lg"></span>','<span class="loading-indicator-message">loading...</span>',"</div>","</div>"].join("\n");var g=$(e).hide().css(c.css||{position:"fixed"}),f=g.children(".loading-indicator-text");if(c.cover){g.css({"z-index":2,top:a.css("top"),bottom:a.css("bottom"),left:a.css("left"),right:a.css("right"),opacity:0.5,"background-color":"white","text-align":"center"});f=g.children(".loading-indicator-text").css({"margin-top":"20px"})}else{f=g.children(".loading-indicator-text").css({margin:"12px 0px 0px 10px",opacity:"0.85",color:"grey"});f.children(".loading-indicator-message").css({margin:"0px 8px 0px 0px","font-style":"italic"})}return g}b.show=function(f,e,g){f=f||"loading...";e=e||"fast";b.$indicator=d().insertBefore(a);b.message(f);b.$indicator.fadeIn(e,g);return b};b.message=function(e){b.$indicator.find("i").text(e)};b.hide=function(e,f){e=e||"fast";if(b.$indicator&&b.$indicator.size()){b.$indicator.fadeOut(e,function(){b.$indicator.remove();if(f){f()}})}else{if(f){f()}}return b};return b}(function(){function a(j,p){var d=27,m=13,c=$(j),e=true,g={initialVal:"",name:"search",placeholder:"search",classes:"",onclear:function(){},onfirstsearch:null,onsearch:function(q){},minSearchLen:0,escWillClear:true,oninit:function(){}};function i(q){var r=$(this).parent().children("input");r.val("");r.trigger("clear:searchInput");p.onclear()}function o(r,q){$(this).trigger("search:searchInput",q);if(typeof p.onfirstsearch==="function"&&e){e=false;p.onfirstsearch(q)}else{p.onsearch(q)}}function f(){return['<input type="text" name="',p.name,'" placeholder="',p.placeholder,'" ','class="search-query ',p.classes,'" ',"/>"].join("")}function l(){return $(f()).focus(function(q){$(this).select()}).keyup(function(r){if(r.which===d&&p.escWillClear){i.call(this,r)}else{var q=$(this).val();if((r.which===m)||(p.minSearchLen&&q.length>=p.minSearchLen)){o.call(this,r,q)}else{if(!q.length){i.call(this,r)}}}}).val(p.initialVal)}function k(){return $(['<span class="search-clear fa fa-times-circle" ','title="',_l("clear search (esc)"),'"></span>'].join("")).tooltip({placement:"bottom"}).click(function(q){i.call(this,q)})}function n(){return $(['<span class="search-loading fa fa-spinner fa-spin" ','title="',_l("loading..."),'"></span>'].join("")).hide().tooltip({placement:"bottom"})}function h(){c.find(".search-loading").toggle();c.find(".search-clear").toggle()}if(jQuery.type(p)==="string"){if(p==="toggle-loading"){h()}return c}if(jQuery.type(p)==="object"){p=jQuery.extend(true,{},g,p)}return c.addClass("search-input").prepend([l(),k(),n()])}jQuery.fn.extend({searchInput:function b(c){return this.each(function(){return a(this,c)})}})}());(function(){function b(m,l){this.currModeIndex=0;return this.init(m,l)}b.prototype.DATA_KEY="mode-button";b.prototype.defaults={modes:[{mode:"default"}]};b.prototype.init=function f(m,l){l=l||{};this.$element=$(m);this.options=jQuery.extend(true,{},this.defaults,l);var o=this;this.$element.click(function n(p){o.callModeFn();o._incModeIndex();$(this).html(o.options.modes[o.currModeIndex].html)});this.currModeIndex=0;if(this.options.initialMode){this.currModeIndex=this._getModeIndex(this.options.initialMode)}return this};b.prototype._getModeIndex=function j(l){for(var m=0;m<this.options.modes.length;m+=1){if(this.options.modes[m].mode===l){return m}}throw new Error("mode not found: "+l)};b.prototype.getCurrMode=function a(){return this.options.modes[this.currModeIndex]};b.prototype.getMode=function g(l){if(!l){return this.getCurrMode()}return this.options.modes[(this._getModeIndex(l))]};b.prototype.hasMode=function k(l){return !!this.getMode(l)};b.prototype.currentMode=function e(){return this.options.modes[this.currModeIndex]};b.prototype.setMode=function c(m){var l=this.getMode(m);this.$element.html(l.html||null);return this};b.prototype._incModeIndex=function d(){this.currModeIndex+=1;if(this.currModeIndex>=this.options.modes.length){this.currModeIndex=0}return this};b.prototype.callModeFn=function h(l){var m=this.getMode(l).onclick;if(m&&jQuery.type(m==="function")){return m.call(this)}return undefined};jQuery.fn.extend({modeButton:function i(m){var l=jQuery.makeArray(arguments).slice(1);return this.map(function(){var p=$(this),o=p.data("mode-button");if(jQuery.type(m)==="object"){o=new b(p,m);p.data("mode-button",o)}else{if(o&&jQuery.type(m)==="string"){var n=o[m];if(jQuery.type(n)==="function"){return n.apply(o,l)}}else{if(o){return o}}}return this})}})}());function dropDownSelect(b,c){c=c||((!_.isEmpty(b))?(b[0]):(""));var a=$(['<div class="dropdown-select btn-group">','<button type="button" class="btn btn-default">','<span class="dropdown-select-selected">'+c+"</span>","</button>","</div>"].join("\n"));if(b&&b.length>1){a.find("button").addClass("dropdown-toggle").attr("data-toggle","dropdown").append(' <span class="caret"></span>');a.append(['<ul class="dropdown-menu" role="menu">',_.map(b,function(e){return['<li><a href="javascript:void(0)">',e,"</a></li>"].join("")}).join("\n"),"</ul>"].join("\n"))}function d(g){var h=$(this),f=h.parents(".dropdown-select"),e=h.text();f.find(".dropdown-select-selected").text(e);f.trigger("change.dropdown-select",e)}a.find("a").click(d);return a}(function(){function e(k,j){return this.init(k,j)}e.prototype.DATA_KEY="filter-control";e.prototype.init=function g(k,j){j=j||{filters:[]};this.$element=$(k).addClass("filter-control btn-group");this.options=jQuery.extend(true,{},this.defaults,j);this.currFilter=this.options.filters[0];return this.render()};e.prototype.render=function d(){this.$element.empty().append([this._renderKeySelect(),this._renderOpSelect(),this._renderValueInput()]);return this};e.prototype._renderKeySelect=function a(){var j=this;var k=this.options.filters.map(function(l){return l.key});this.$keySelect=dropDownSelect(k,this.currFilter.key).addClass("filter-control-key").on("change.dropdown-select",function(m,l){j.currFilter=_.findWhere(j.options.filters,{key:l});j.render()._triggerChange()});return this.$keySelect};e.prototype._renderOpSelect=function i(){var j=this,k=this.currFilter.ops;this.$opSelect=dropDownSelect(k,k[0]).addClass("filter-control-op").on("change.dropdown-select",function(m,l){j._triggerChange()});return this.$opSelect};e.prototype._renderValueInput=function c(){var j=this;if(this.currFilter.values){this.$valueSelect=dropDownSelect(this.currFilter.values,this.currFilter.values[0]).on("change.dropdown-select",function(l,k){j._triggerChange()})}else{this.$valueSelect=$("<input/>").addClass("form-control").on("change",function(k,l){j._triggerChange()})}this.$valueSelect.addClass("filter-control-value");return this.$valueSelect};e.prototype.val=function b(){var k=this.$element.find(".filter-control-key .dropdown-select-selected").text(),m=this.$element.find(".filter-control-op .dropdown-select-selected").text(),j=this.$element.find(".filter-control-value"),l=(j.hasClass("dropdown-select"))?(j.find(".dropdown-select-selected").text()):(j.val());return{key:k,op:m,value:l}};e.prototype._triggerChange=function h(){this.$element.trigger("change.filter-control",this.val())};jQuery.fn.extend({filterControl:function f(k){var j=jQuery.makeArray(arguments).slice(1);return this.map(function(){var n=$(this),m=n.data(e.prototype.DATA_KEY);if(jQuery.type(k)==="object"){m=new e(n,k);n.data(e.prototype.DATA_KEY,m)}if(m&&jQuery.type(k)==="string"){var l=m[k];if(jQuery.type(l)==="function"){return l.apply(m,j)}}return this})}})}());(function(){function i(o,n){this.numPages=null;this.currPage=0;return this.init(o,n)}i.prototype.DATA_KEY="pagination";i.prototype.defaults={startingPage:0,perPage:20,totalDataSize:null,currDataSize:null};i.prototype.init=function g(n,o){o=o||{};this.$element=n;this.options=jQuery.extend(true,{},this.defaults,o);this.currPage=this.options.startingPage;if(this.options.totalDataSize!==null){this.numPages=Math.ceil(this.options.totalDataSize/this.options.perPage);if(this.currPage>=this.numPages){this.currPage=this.numPages-1}}this.$element.data(i.prototype.DATA_KEY,this);this._render();return this};function m(n){return $(['<li><a href="javascript:void(0);">',n,"</a></li>"].join(""))}i.prototype._render=function e(){if(this.options.totalDataSize===0){return this}if(this.numPages===1){return this}if(this.numPages>0){this._renderPages();this._scrollToActivePage()}else{this._renderPrevNext()}return this};i.prototype._renderPrevNext=function b(){var o=this,p=m("Prev"),n=m("Next"),q=$("<ul/>").addClass("pagination pagination-prev-next");if(this.currPage===0){p.addClass("disabled")}else{p.click(function(){o.prevPage()})}if((this.numPages&&this.currPage===(this.numPages-1))||(this.options.currDataSize&&this.options.currDataSize<this.options.perPage)){n.addClass("disabled")}else{n.click(function(){o.nextPage()})}this.$element.html(q.append([p,n]));return this.$element};i.prototype._renderPages=function a(){var n=this,q=$("<div>").addClass("pagination-scroll-container"),s=$("<ul/>").addClass("pagination pagination-page-list"),r=function(t){n.goToPage($(this).data("page"))};for(var o=0;o<this.numPages;o+=1){var p=m(o+1).attr("data-page",o).click(r);if(o===this.currPage){p.addClass("active")}s.append(p)}return this.$element.html(q.html(s))};i.prototype._scrollToActivePage=function l(){var p=this.$element.find(".pagination-scroll-container");if(!p.size()){return this}var o=this.$element.find("li.active"),n=p.width()/2;p.scrollLeft(p.scrollLeft()+o.position().left-n);return this};i.prototype.goToPage=function j(n){if(n<=0){n=0}if(this.numPages&&n>=this.numPages){n=this.numPages-1}if(n===this.currPage){return this}this.currPage=n;this.$element.trigger("pagination.page-change",this.currPage);this._render();return this};i.prototype.prevPage=function c(){return this.goToPage(this.currPage-1)};i.prototype.nextPage=function h(){return this.goToPage(this.currPage+1)};i.prototype.page=function f(){return this.currPage};i.create=function k(n,o){return new i(n,o)};jQuery.fn.extend({pagination:function d(o){var n=jQuery.makeArray(arguments).slice(1);if(jQuery.type(o)==="object"){return this.map(function(){i.create($(this),o);return this})}var q=$(this[0]),r=q.data(i.prototype.DATA_KEY);if(r){if(jQuery.type(o)==="string"){var p=r[o];if(jQuery.type(p)==="function"){return p.apply(r,n)}}else{return r}}return undefined}})}());(function(){var g={renameColumns:false,columnNames:[],commentChar:"#",hideCommentRows:false,includePrompts:true,topLeftContent:"Columns:"},s="peek-control.change",t="peek-control.rename",l="peek-control",v="control",f="control-prompt",c="selected",n="disabled",u="button",q="renamable-header",p="column-index",a="column-name";function i(w){if(w.disabled&&jQuery.type(w.disabled)!=="array"){throw new Error('"disabled" must be defined as an array of indeces: '+JSON.stringify(w))}if(w.multiselect&&w.selected&&jQuery.type(w.selected)!=="array"){throw new Error('Mulitselect rows need an array for "selected": '+JSON.stringify(w))}if(!w.label||!w.id){throw new Error("Peek controls need a label and id for each control row: "+JSON.stringify(w))}if(w.disabled&&w.disabled.indexOf(w.selected)!==-1){throw new Error("Selected column is in the list of disabled columns: "+JSON.stringify(w))}return w}function o(x,w){return $("<div/>").addClass(u).text(x.label)}function k(x,w){var y=$("<td/>").html(o(x,w)).attr("data-"+p,w);if(x.disabled&&x.disabled.indexOf(w)!==-1){y.addClass(n)}return y}function e(y,z,w){var x=y.children("."+u);if(y.hasClass(c)){x.html((z.selectedText!==undefined)?(z.selectedText):(z.label))}else{x.html((z.unselectedText!==undefined)?(z.unselectedText):(z.label))}}function h(z,x){var y=k(z,x);if(z.selected===x){y.addClass(c)}e(y,z,x);if(!y.hasClass(n)){y.click(function w(D){var E=$(this);if(!E.hasClass(c)){var A=E.parent().children("."+c).removeClass(c);A.each(function(){e($(this),z,x)});E.addClass(c);e(E,z,x);var C={},B=E.parent().attr("id"),F=E.data(p);C[B]=F;E.parents(".peek").trigger(s,C)}})}return y}function m(z,x){var y=k(z,x);if(z.selected&&z.selected.indexOf(x)!==-1){y.addClass(c)}e(y,z,x);if(!y.hasClass(n)){y.click(function w(D){var E=$(this);E.toggleClass(c);e(E,z,x);var C=E.parent().find("."+c).map(function(G,H){return $(H).data(p)});var B={},A=E.parent().attr("id"),F=jQuery.makeArray(C);B[A]=F;E.parents(".peek").trigger(s,B)})}return y}function j(y,z){var w=[];for(var x=0;x<y;x+=1){w.push(z.multiselect?m(z,x):h(z,x))}return w}function r(y,z,x){var A=$("<tr/>").attr("id",z.id).addClass(v);if(x){var w=$("<td/>").addClass(f).text(z.label+":");A.append(w)}A.append(j(y,z));return A}function b(E){E=jQuery.extend(true,{},g,E);var D=$(this).addClass(l),A=D.find("table"),z=A.find("th").size(),C=A.find("tr").size(),w=A.find("td[colspan]").map(function(H,F){var G=$(this);if(G.text()&&G.text().match(new RegExp("^"+E.commentChar))){return $(this).css("color","grey").parent().get(0)}return null});if(E.hideCommentRows){w.hide();C-=w.size()}if(E.includePrompts){var y=$("<th/>").addClass("top-left").text(E.topLeftContent).attr("rowspan",C);A.find("tr").first().prepend(y)}var B=A.find("th:not(.top-left)").each(function(G,I){var H=$(this),J=H.text().replace(/^\d+\.*/,""),F=E.columnNames[G]||J;H.attr("data-"+a,F).text((G+1)+((F)?("."+F):("")))});if(E.renameColumns){B.addClass(q).click(function x(){var G=$(this),F=G.index()+(E.includePrompts?0:1),I=G.data(a),H=prompt("New column name:",I);if(H!==null&&H!==I){G.text(F+(H?("."+H):"")).data(a,H).attr("data-",a,H);var J=jQuery.makeArray(G.parent().children("th:not(.top-left)").map(function(){return $(this).data(a)}));G.parents(".peek").trigger(t,J)}})}E.controls.forEach(function(G,F){i(G);var H=r(z,G,E.includePrompts);A.find("tbody").append(H)});return this}jQuery.fn.extend({peekControl:function d(w){return this.map(function(){return b.call(this,w)})}})}());
\ No newline at end of file
+var IconButton=Backbone.Model.extend({defaults:{title:"",icon_class:"",on_click:null,menu_options:null,is_menu_button:true,id:null,href:null,target:null,enabled:true,visible:true,tooltip_config:{}}});var IconButtonView=Backbone.View.extend({initialize:function(){this.model.attributes.tooltip_config={placement:"bottom"};this.model.bind("change",this.render,this)},render:function(){this.$el.tooltip("hide");var a=this.template(this.model.toJSON());a.tooltip(this.model.get("tooltip_config"));this.$el.replaceWith(a);this.setElement(a);return this},events:{click:"click"},click:function(a){if(_.isFunction(this.model.get("on_click"))){this.model.get("on_click")(a);return false}return true},template:function(b){var a='title="'+b.title+'" class="icon-button';if(b.is_menu_button){a+=" menu-button"}a+=" "+b.icon_class;if(!b.enabled){a+="_disabled"}a+='"';if(b.id){a+=' id="'+b.id+'"'}a+=' href="'+b.href+'"';if(b.target){a+=' target="'+b.target+'"'}if(!b.visible){a+=' style="display: none;"'}if(b.enabled){a="<a "+a+"/>"}else{a="<span "+a+"/>"}return $(a)}});var IconButtonCollection=Backbone.Collection.extend({model:IconButton});var IconButtonMenuView=Backbone.View.extend({tagName:"div",initialize:function(){this.render()},render:function(){var a=this;this.collection.each(function(d){var b=$("<a/>").attr("href","javascript:void(0)").attr("title",d.attributes.title).addClass("icon-button menu-button").addClass(d.attributes.icon_class).appendTo(a.$el).click(d.attributes.on_click);if(d.attributes.tooltip_config){b.tooltip(d.attributes.tooltip_config)}var c=d.get("options");if(c){make_popupmenu(b,c)}});return this}});var create_icon_buttons_menu=function(b,a){if(!a){a={}}var c=new IconButtonCollection(_.map(b,function(d){return new IconButton(_.extend(d,a))}));return new IconButtonMenuView({collection:c})};var Grid=Backbone.Collection.extend({});var GridView=Backbone.View.extend({});var PopupMenu=Backbone.View.extend({initialize:function(b,a){this.$button=b;if(!this.$button.size()){this.$button=$("<div/>")}this.options=a||[];var c=this;this.$button.click(function(d){$(".popmenu-wrapper").remove();c._renderAndShow(d);return false})},_renderAndShow:function(a){this.render();this.$el.appendTo("body").css(this._getShownPosition(a)).show();this._setUpCloseBehavior()},render:function(){this.$el.addClass("popmenu-wrapper").hide().css({position:"absolute"}).html(this.template(this.$button.attr("id"),this.options));if(this.options.length){var a=this;this.$el.find("li").each(function(c,b){var d=a.options[c];if(d.func){$(this).children("a.popupmenu-option").click(function(e){d.func.call(a,e,d)})}})}return this},template:function(b,a){return['<ul id="',b,'-menu" class="dropdown-menu">',this._templateOptions(a),"</ul>"].join("")},_templateOptions:function(a){if(!a.length){return"<li>(no options)</li>"}return _.map(a,function(d){if(d.divider){return'<li class="divider"></li>'}else{if(d.header){return['<li class="head"><a href="javascript:void(0);">',d.html,"</a></li>"].join("")}}var c=d.href||"javascript:void(0);",e=(d.target)?(' target="'+d.target+'"'):(""),b=(d.checked)?('<span class="fa fa-check"></span>'):("");return['<li><a class="popupmenu-option" href="',c,'"',e,">",b,d.html,"</a></li>"].join("")}).join("")},_getShownPosition:function(b){var c=this.$el.width();var a=b.pageX-c/2;a=Math.min(a,$(document).scrollLeft()+$(window).width()-c-5);a=Math.max(a,$(document).scrollLeft()+5);return{top:b.pageY,left:a}},_setUpCloseBehavior:function(){var c=this;function a(e){$(document).off("click.close_popup");if(window.parent!==window){try{$(window.parent.document).off("click.close_popup")}catch(d){}}else{try{$("iframe#galaxy_main").contents().off("click.close_popup")}catch(d){}}c.remove()}$("html").one("click.close_popup",a);if(window.parent!==window){try{$(window.parent.document).find("html").one("click.close_popup",a)}catch(b){}}else{try{$("iframe#galaxy_main").contents().one("click.close_popup",a)}catch(b){}}},addItem:function(b,a){a=(a>=0)?a:this.options.length;this.options.splice(a,0,b);return this},removeItem:function(a){if(a>=0){this.options.splice(a,1)}return this},findIndexByHtml:function(b){for(var a=0;a<this.options.length;a++){if(_.has(this.options[a],"html")&&(this.options[a].html===b)){return a}}return null},findItemByHtml:function(a){return this.options[(this.findIndexByHtml(a))]},toString:function(){return"PopupMenu"}});PopupMenu.create=function _create(b,a){return new PopupMenu(b,a)};PopupMenu.make_popupmenu=function(b,c){var a=[];_.each(c,function(f,d){var e={html:d};if(f===null){e.header=true}else{if(jQuery.type(f)==="function"){e.func=f}}a.push(e)});return new PopupMenu($(b),a)};PopupMenu.convertLinksToOptions=function(c,a){c=$(c);a=a||"a";var b=[];c.find(a).each(function(g,e){var f={},d=$(g);f.html=d.text();if(d.attr("href")){var j=d.attr("href"),k=d.attr("target"),h=d.attr("confirm");f.func=function(){if((h)&&(!confirm(h))){return}switch(k){case"_parent":window.parent.location=j;break;case"_top":window.top.location=j;break;default:window.location=j}}}b.push(f)});return b};PopupMenu.fromExistingDom=function(d,c,a){d=$(d);c=$(c);var b=PopupMenu.convertLinksToOptions(c,a);c.remove();return new PopupMenu(d,b)};PopupMenu.make_popup_menus=function(c,b,d){c=c||document;b=b||"div[popupmenu]";d=d||function(e,f){return"#"+e.attr("popupmenu")};var a=[];$(c).find(b).each(function(){var e=$(this),f=$(c).find(d(e,c));a.push(PopupMenu.fromDom(f,e));f.addClass("popup")});return a};var faIconButton=function(a){a=a||{};a.tooltipConfig=a.tooltipConfig||{placement:"bottom"};a.classes=["icon-btn"].concat(a.classes||[]);if(a.disabled){a.classes.push("disabled")}var b=['<a class="',a.classes.join(" "),'"',((a.title)?(' title="'+a.title+'"'):("")),((!a.disabled&&a.target)?(' target="'+a.target+'"'):("")),' href="',((!a.disabled&&a.href)?(a.href):("javascript:void(0);")),'">','<span class="fa ',a.faIcon,'"></span>',"</a>"].join("");var c=$(b).tooltip(a.tooltipConfig);if(_.isFunction(a.onclick)){c.click(a.onclick)}return c};function LoadingIndicator(a,c){var b=this;c=jQuery.extend({cover:false},c||{});function d(){var e=['<div class="loading-indicator">','<div class="loading-indicator-text">','<span class="fa fa-spinner fa-spin fa-lg"></span>','<span class="loading-indicator-message">loading...</span>',"</div>","</div>"].join("\n");var g=$(e).hide().css(c.css||{position:"fixed"}),f=g.children(".loading-indicator-text");if(c.cover){g.css({"z-index":2,top:a.css("top"),bottom:a.css("bottom"),left:a.css("left"),right:a.css("right"),opacity:0.5,"background-color":"white","text-align":"center"});f=g.children(".loading-indicator-text").css({"margin-top":"20px"})}else{f=g.children(".loading-indicator-text").css({margin:"12px 0px 0px 10px",opacity:"0.85",color:"grey"});f.children(".loading-indicator-message").css({margin:"0px 8px 0px 0px","font-style":"italic"})}return g}b.show=function(f,e,g){f=f||"loading...";e=e||"fast";b.$indicator=d().insertBefore(a);b.message(f);b.$indicator.fadeIn(e,g);return b};b.message=function(e){b.$indicator.find("i").text(e)};b.hide=function(e,f){e=e||"fast";if(b.$indicator&&b.$indicator.size()){b.$indicator.fadeOut(e,function(){b.$indicator.remove();if(f){f()}})}else{if(f){f()}}return b};return b}(function(){function a(j,p){var d=27,m=13,c=$(j),e=true,g={initialVal:"",name:"search",placeholder:"search",classes:"",onclear:function(){},onfirstsearch:null,onsearch:function(q){},minSearchLen:0,escWillClear:true,oninit:function(){}};function i(q){var r=$(this).parent().children("input");r.val("");r.trigger("clear:searchInput");p.onclear()}function o(r,q){$(this).trigger("search:searchInput",q);if(typeof p.onfirstsearch==="function"&&e){e=false;p.onfirstsearch(q)}else{p.onsearch(q)}}function f(){return['<input type="text" name="',p.name,'" placeholder="',p.placeholder,'" ','class="search-query ',p.classes,'" ',"/>"].join("")}function l(){return $(f()).focus(function(q){$(this).select()}).keyup(function(r){if(r.which===d&&p.escWillClear){i.call(this,r)}else{var q=$(this).val();if((r.which===m)||(p.minSearchLen&&q.length>=p.minSearchLen)){o.call(this,r,q)}else{if(!q.length){i.call(this,r)}}}}).val(p.initialVal)}function k(){return $(['<span class="search-clear fa fa-times-circle" ','title="',_l("clear search (esc)"),'"></span>'].join("")).tooltip({placement:"bottom"}).click(function(q){i.call(this,q)})}function n(){return $(['<span class="search-loading fa fa-spinner fa-spin" ','title="',_l("loading..."),'"></span>'].join("")).hide().tooltip({placement:"bottom"})}function h(){c.find(".search-loading").toggle();c.find(".search-clear").toggle()}if(jQuery.type(p)==="string"){if(p==="toggle-loading"){h()}return c}if(jQuery.type(p)==="object"){p=jQuery.extend(true,{},g,p)}return c.addClass("search-input").prepend([l(),k(),n()])}jQuery.fn.extend({searchInput:function b(c){return this.each(function(){return a(this,c)})}})}());(function(){function c(o,n){this.currModeIndex=0;return this._init(o,n)}c.prototype.DATA_KEY="mode-button";c.prototype.defaults={switchModesOnClick:true};c.prototype._init=function j(o,n){n=n||{};this.$element=$(o);this.options=jQuery.extend(true,{},this.defaults,n);if(!n.modes){throw new Error('ModeButton requires a "modes" array')}var q=this;this.$element.click(function p(r){q.callModeFn();if(q.options.switchModesOnClick){q._incModeIndex()}$(this).html(q.options.modes[q.currModeIndex].html)});return this.reset()};c.prototype._incModeIndex=function l(){this.currModeIndex+=1;if(this.currModeIndex>=this.options.modes.length){this.currModeIndex=0}return this};c.prototype._getModeIndex=function f(n){for(var o=0;o<this.options.modes.length;o+=1){if(this.options.modes[o].mode===n){return o}}throw new Error("mode not found: "+n)};c.prototype._setModeByIndex=function m(n){var o=this.options.modes[n];if(!o){throw new Error("mode index not found: "+n)}this.currModeIndex=n;if(o.html){this.$element.html(o.html)}return this};c.prototype.currentMode=function d(){return this.options.modes[this.currModeIndex]};c.prototype.current=function i(){return this.currentMode().mode};c.prototype.getMode=function g(n){if(!n){return this.currentMode()}return this.options.modes[(this._getModeIndex(n))]};c.prototype.hasMode=function b(n){try{return !!this.getMode(n)}catch(o){}return false};c.prototype.setMode=function a(n){return this._setModeByIndex(this._getModeIndex(n))};c.prototype.reset=function h(){this.currModeIndex=0;if(this.options.initialMode){this.currModeIndex=this._getModeIndex(this.options.initialMode)}return this._setModeByIndex(this.currModeIndex)};c.prototype.callModeFn=function e(n){var o=this.getMode(n).onclick;if(o&&jQuery.type(o==="function")){o.call(this.$element.get(0));return this}return undefined};jQuery.fn.extend({modeButton:function k(n){if(!this.size()){return this}if(jQuery.type(n)==="object"){return this.map(function(){var r=$(this);r.data("mode-button",new c(r,n));return this})}var p=$(this[0]),o=p.data("mode-button");console.debug("first, button",p,o);if(!o){throw new Error("modeButton needs an options object or string name of a function")}if(o&&jQuery.type(n)==="string"){var q=n;if(o&&jQuery.type(o[q])==="function"){return o[q].apply(o,jQuery.makeArray(arguments).slice(1))}}return o}})}());function dropDownSelect(b,c){c=c||((!_.isEmpty(b))?(b[0]):(""));var a=$(['<div class="dropdown-select btn-group">','<button type="button" class="btn btn-default">','<span class="dropdown-select-selected">'+c+"</span>","</button>","</div>"].join("\n"));if(b&&b.length>1){a.find("button").addClass("dropdown-toggle").attr("data-toggle","dropdown").append(' <span class="caret"></span>');a.append(['<ul class="dropdown-menu" role="menu">',_.map(b,function(e){return['<li><a href="javascript:void(0)">',e,"</a></li>"].join("")}).join("\n"),"</ul>"].join("\n"))}function d(g){var h=$(this),f=h.parents(".dropdown-select"),e=h.text();f.find(".dropdown-select-selected").text(e);f.trigger("change.dropdown-select",e)}a.find("a").click(d);return a}(function(){function e(k,j){return this.init(k,j)}e.prototype.DATA_KEY="filter-control";e.prototype.init=function g(k,j){j=j||{filters:[]};this.$element=$(k).addClass("filter-control btn-group");this.options=jQuery.extend(true,{},this.defaults,j);this.currFilter=this.options.filters[0];return this.render()};e.prototype.render=function d(){this.$element.empty().append([this._renderKeySelect(),this._renderOpSelect(),this._renderValueInput()]);return this};e.prototype._renderKeySelect=function a(){var j=this;var k=this.options.filters.map(function(l){return l.key});this.$keySelect=dropDownSelect(k,this.currFilter.key).addClass("filter-control-key").on("change.dropdown-select",function(m,l){j.currFilter=_.findWhere(j.options.filters,{key:l});j.render()._triggerChange()});return this.$keySelect};e.prototype._renderOpSelect=function i(){var j=this,k=this.currFilter.ops;this.$opSelect=dropDownSelect(k,k[0]).addClass("filter-control-op").on("change.dropdown-select",function(m,l){j._triggerChange()});return this.$opSelect};e.prototype._renderValueInput=function c(){var j=this;if(this.currFilter.values){this.$valueSelect=dropDownSelect(this.currFilter.values,this.currFilter.values[0]).on("change.dropdown-select",function(l,k){j._triggerChange()})}else{this.$valueSelect=$("<input/>").addClass("form-control").on("change",function(k,l){j._triggerChange()})}this.$valueSelect.addClass("filter-control-value");return this.$valueSelect};e.prototype.val=function b(){var k=this.$element.find(".filter-control-key .dropdown-select-selected").text(),m=this.$element.find(".filter-control-op .dropdown-select-selected").text(),j=this.$element.find(".filter-control-value"),l=(j.hasClass("dropdown-select"))?(j.find(".dropdown-select-selected").text()):(j.val());return{key:k,op:m,value:l}};e.prototype._triggerChange=function h(){this.$element.trigger("change.filter-control",this.val())};jQuery.fn.extend({filterControl:function f(k){var j=jQuery.makeArray(arguments).slice(1);return this.map(function(){var n=$(this),m=n.data(e.prototype.DATA_KEY);if(jQuery.type(k)==="object"){m=new e(n,k);n.data(e.prototype.DATA_KEY,m)}if(m&&jQuery.type(k)==="string"){var l=m[k];if(jQuery.type(l)==="function"){return l.apply(m,j)}}return this})}})}());(function(){function i(o,n){this.numPages=null;this.currPage=0;return this.init(o,n)}i.prototype.DATA_KEY="pagination";i.prototype.defaults={startingPage:0,perPage:20,totalDataSize:null,currDataSize:null};i.prototype.init=function g(n,o){o=o||{};this.$element=n;this.options=jQuery.extend(true,{},this.defaults,o);this.currPage=this.options.startingPage;if(this.options.totalDataSize!==null){this.numPages=Math.ceil(this.options.totalDataSize/this.options.perPage);if(this.currPage>=this.numPages){this.currPage=this.numPages-1}}this.$element.data(i.prototype.DATA_KEY,this);this._render();return this};function m(n){return $(['<li><a href="javascript:void(0);">',n,"</a></li>"].join(""))}i.prototype._render=function e(){if(this.options.totalDataSize===0){return this}if(this.numPages===1){return this}if(this.numPages>0){this._renderPages();this._scrollToActivePage()}else{this._renderPrevNext()}return this};i.prototype._renderPrevNext=function b(){var o=this,p=m("Prev"),n=m("Next"),q=$("<ul/>").addClass("pagination pagination-prev-next");if(this.currPage===0){p.addClass("disabled")}else{p.click(function(){o.prevPage()})}if((this.numPages&&this.currPage===(this.numPages-1))||(this.options.currDataSize&&this.options.currDataSize<this.options.perPage)){n.addClass("disabled")}else{n.click(function(){o.nextPage()})}this.$element.html(q.append([p,n]));return this.$element};i.prototype._renderPages=function a(){var n=this,q=$("<div>").addClass("pagination-scroll-container"),s=$("<ul/>").addClass("pagination pagination-page-list"),r=function(t){n.goToPage($(this).data("page"))};for(var o=0;o<this.numPages;o+=1){var p=m(o+1).attr("data-page",o).click(r);if(o===this.currPage){p.addClass("active")}s.append(p)}return this.$element.html(q.html(s))};i.prototype._scrollToActivePage=function l(){var p=this.$element.find(".pagination-scroll-container");if(!p.size()){return this}var o=this.$element.find("li.active"),n=p.width()/2;p.scrollLeft(p.scrollLeft()+o.position().left-n);return this};i.prototype.goToPage=function j(n){if(n<=0){n=0}if(this.numPages&&n>=this.numPages){n=this.numPages-1}if(n===this.currPage){return this}this.currPage=n;this.$element.trigger("pagination.page-change",this.currPage);this._render();return this};i.prototype.prevPage=function c(){return this.goToPage(this.currPage-1)};i.prototype.nextPage=function h(){return this.goToPage(this.currPage+1)};i.prototype.page=function f(){return this.currPage};i.create=function k(n,o){return new i(n,o)};jQuery.fn.extend({pagination:function d(o){var n=jQuery.makeArray(arguments).slice(1);if(jQuery.type(o)==="object"){return this.map(function(){i.create($(this),o);return this})}var q=$(this[0]),r=q.data(i.prototype.DATA_KEY);if(r){if(jQuery.type(o)==="string"){var p=r[o];if(jQuery.type(p)==="function"){return p.apply(r,n)}}else{return r}}return undefined}})}());(function(){var g={renameColumns:false,columnNames:[],commentChar:"#",hideCommentRows:false,includePrompts:true,topLeftContent:"Columns:"},s="peek-control.change",t="peek-control.rename",l="peek-control",v="control",f="control-prompt",c="selected",n="disabled",u="button",q="renamable-header",p="column-index",a="column-name";function i(w){if(w.disabled&&jQuery.type(w.disabled)!=="array"){throw new Error('"disabled" must be defined as an array of indeces: '+JSON.stringify(w))}if(w.multiselect&&w.selected&&jQuery.type(w.selected)!=="array"){throw new Error('Mulitselect rows need an array for "selected": '+JSON.stringify(w))}if(!w.label||!w.id){throw new Error("Peek controls need a label and id for each control row: "+JSON.stringify(w))}if(w.disabled&&w.disabled.indexOf(w.selected)!==-1){throw new Error("Selected column is in the list of disabled columns: "+JSON.stringify(w))}return w}function o(x,w){return $("<div/>").addClass(u).text(x.label)}function k(x,w){var y=$("<td/>").html(o(x,w)).attr("data-"+p,w);if(x.disabled&&x.disabled.indexOf(w)!==-1){y.addClass(n)}return y}function e(y,z,w){var x=y.children("."+u);if(y.hasClass(c)){x.html((z.selectedText!==undefined)?(z.selectedText):(z.label))}else{x.html((z.unselectedText!==undefined)?(z.unselectedText):(z.label))}}function h(z,x){var y=k(z,x);if(z.selected===x){y.addClass(c)}e(y,z,x);if(!y.hasClass(n)){y.click(function w(D){var E=$(this);if(!E.hasClass(c)){var A=E.parent().children("."+c).removeClass(c);A.each(function(){e($(this),z,x)});E.addClass(c);e(E,z,x);var C={},B=E.parent().attr("id"),F=E.data(p);C[B]=F;E.parents(".peek").trigger(s,C)}})}return y}function m(z,x){var y=k(z,x);if(z.selected&&z.selected.indexOf(x)!==-1){y.addClass(c)}e(y,z,x);if(!y.hasClass(n)){y.click(function w(D){var E=$(this);E.toggleClass(c);e(E,z,x);var C=E.parent().find("."+c).map(function(G,H){return $(H).data(p)});var B={},A=E.parent().attr("id"),F=jQuery.makeArray(C);B[A]=F;E.parents(".peek").trigger(s,B)})}return y}function j(y,z){var w=[];for(var x=0;x<y;x+=1){w.push(z.multiselect?m(z,x):h(z,x))}return w}function r(y,z,x){var A=$("<tr/>").attr("id",z.id).addClass(v);if(x){var w=$("<td/>").addClass(f).text(z.label+":");A.append(w)}A.append(j(y,z));return A}function b(E){E=jQuery.extend(true,{},g,E);var D=$(this).addClass(l),A=D.find("table"),z=A.find("th").size(),C=A.find("tr").size(),w=A.find("td[colspan]").map(function(H,F){var G=$(this);if(G.text()&&G.text().match(new RegExp("^"+E.commentChar))){return $(this).css("color","grey").parent().get(0)}return null});if(E.hideCommentRows){w.hide();C-=w.size()}if(E.includePrompts){var y=$("<th/>").addClass("top-left").text(E.topLeftContent).attr("rowspan",C);A.find("tr").first().prepend(y)}var B=A.find("th:not(.top-left)").each(function(G,I){var H=$(this),J=H.text().replace(/^\d+\.*/,""),F=E.columnNames[G]||J;H.attr("data-"+a,F).text((G+1)+((F)?("."+F):("")))});if(E.renameColumns){B.addClass(q).click(function x(){var G=$(this),F=G.index()+(E.includePrompts?0:1),I=G.data(a),H=prompt("New column name:",I);if(H!==null&&H!==I){G.text(F+(H?("."+H):"")).data(a,H).attr("data-",a,H);var J=jQuery.makeArray(G.parent().children("th:not(.top-left)").map(function(){return $(this).data(a)}));G.parents(".peek").trigger(t,J)}})}E.controls.forEach(function(G,F){i(G);var H=r(z,G,E.includePrompts);A.find("tbody").append(H)});return this}jQuery.fn.extend({peekControl:function d(w){return this.map(function(){return b.call(this,w)})}})}());
\ No newline at end of file
diff -r 0db8172d6d363ba1010df08a79f6db435f4f0ee7 -r e51429649b44d5b434a6b6f4e10daa1dbf390c20 templates/webapps/galaxy/history/original_view.mako
--- a/templates/webapps/galaxy/history/original_view.mako
+++ /dev/null
@@ -1,173 +0,0 @@
-<%namespace file="/display_common.mako" import="get_history_link, get_controller_name" />
-<%namespace file="/root/history_common.mako" import="render_dataset" />
-<%namespace file="/tagging_common.mako" import="render_individual_tagging_element, render_community_tagging_element" />
-
-<%!
- def inherit(context):
- if context.get('use_panels'):
- return '/webapps/galaxy/base_panels.mako'
- else:
- return '/base.mako'
-%>
-<%inherit file="${inherit(context)}"/>
-
-<%def name="javascripts()">
- ${parent.javascripts()}
- ${h.js( "libs/jquery/jstorage" )}
- <script type="text/javascript">
- $(function() {
- init_history_items( $("div.historyItemWrapper"), false, "nochanges" );
- $( '#switch-to-link' ).click( function( event ){
- var galaxy = window.Galaxy || window.parent.Galaxy;
- if( galaxy ){
- galaxy.currHistoryPanel.switchToHistory( '${ trans.security.encode_id( history.id ) }' );
- }
- });
- $( '#refresh' ).click( function( event ){ window.location.reload( true ); })
- });
- </script>
-</%def>
-
-<%def name="stylesheets()">
- ${parent.stylesheets()}
- ${h.css( "history", "autocomplete_tagging" )}
-
- <style type="text/css">
-
- /* these don't appear to be used? */
- .page-body
- {
- padding: 10px;
- float: left;
- width: 65%;
- }
- .page-meta
- {
- float: right;
- width: 27%;
- padding: 0.5em;
- margin: 0.25em;
- vertical-align: text-top;
- border: 2px solid #DDDDDD;
- border-top: 4px solid #DDDDDD;
- }
-
-
- body {
- padding: 0px;
- margin: 0px;
- }
-
- div.unified-panel-body {
- position: absolute;
- top: 0px;
- width: 100%;
- }
-
- #history-name-area {
- margin: 12px 0px 0px 16px;
- font-size: 120%;
- }
- #top-links {
- margin: 4px 0px 8px 16px;
- }
-
- .historyItemContainer {
- /*padding-right: 3px;*/
- }
- .historyItemBody {
- display: none;
- }
- div.historyItemWrapper {
- margin: 0px 4px 0px 4px ;
- border-left: 1px solid #999999;
- border-right: 1px solid #999999;
- }
- /* TODO: unify with other history css and into .less */
- </style>
-
- <noscript>
- <style>
- .historyItemBody {
- display: block;
- }
- </style>
- </noscript>
-</%def>
-
-<%def name="init()">
-<%
- self.has_left_panel=False
- self.has_right_panel=False
- self.message_box_visible=False
-%>
-</%def>
-
-<%def name="body()">
- ${center_panel()}
-</%def>
-
-<%def name="center_panel()">
- ## Get URL to other histories owned by user that owns this history.
- <%
- ##TODO: is there a better way to create this URL? Can't use 'f-username' as a key b/c it's not a valid identifier.
- href_to_published_histories = h.url_for( controller='/history', action='list_published')
- if history.user is not None:
- href_to_user_histories = h.url_for( controller='/history', action='list_published', xxx=history.user.username).replace( 'xxx', 'f-username')
- else:
- href_to_user_histories = h.url_for( controller='/history', action='list_published' )##should this instead be be None or empty string?
- %>
-
- <div class="unified-panel-body">
- <div style="overflow: auto; height: 100%;">
- ## Render view of history.
- <div id="history-name-area" class="historyLinks" style="color: gray; font-weight: bold; padding: 0px 0px 5px 0px">
- <div id="history-name">${history.get_display_name()}</div>
- </div>
-
- <div id="top-links" class="historyLinks" style="padding: 0px 0px 5px 0px">
- %if not history.purged and history.user != trans.user:
- ##TODO: need to remove _top
- <a href="${h.url_for(controller='history', action='imp', id=trans.security.encode_id(history.id) )}"
- >import and start using history</a> |
- <a id="refresh" href="javascript:void(0)" >${_('refresh')}</a> |
- %endif
- %if not history.purged and history.user == trans.user:
- <a id="switch-to-link" href="javascript:void(0)">${_('switch to this history')}</a> |
- <a id="refresh" href="javascript:void(0)" >${_('refresh')}</a> |
- %endif
- %if show_deleted:
- <a href="${h.url_for(controller='history', action='view', id=trans.security.encode_id(history.id), show_deleted=False, use_panels=use_panels )}">${_('hide deleted')}</a> |
- %else:
- <a href="${h.url_for(controller='history', action='view', id=trans.security.encode_id(history.id), show_deleted=True, use_panels=use_panels )}">${_('show deleted')}</a> |
- %endif
- <a href="#" class="toggle">collapse all</a>
- </div>
-
- %if history.deleted:
- <div class="warningmessagesmall">
- ${_('You are currently viewing a deleted history!')}
- </div>
- <p></p>
- %endif
-
- %if not datasets:
- <div class="infomessagesmall" id="emptyHistoryMessage">
-
- %else:
- ## Render requested datasets, ordered from newest to oldest
- %for data in datasets:
- %if data.visible:
- <div class="historyItemContainer visible-right-border" id="historyItemContainer-${data.id}">
- ${render_dataset( data, data.hid, show_deleted_on_refresh = show_deleted, for_editing=False )}
- </div>
- %endif
- %endfor
-
- <div class="infomessagesmall" id="emptyHistoryMessage" style="display:none;">
- %endif
- ${_("Your history is empty. Click 'Get Data' on the left pane to start")}
- </div>
- </div>
- </div>
-</%def>
diff -r 0db8172d6d363ba1010df08a79f6db435f4f0ee7 -r e51429649b44d5b434a6b6f4e10daa1dbf390c20 templates/webapps/galaxy/history/view.mako
--- a/templates/webapps/galaxy/history/view.mako
+++ b/templates/webapps/galaxy/history/view.mako
@@ -77,6 +77,7 @@
%endif
<script type="text/javascript">
+ ##TODO: remove when Galaxy is either ensured or removed from the history panel
var using_panels = ${ 'false' if not use_panels else 'true' };
%if not use_panels:
window.Galaxy = {};
@@ -87,113 +88,107 @@
## ----------------------------------------------------------------------------
<%def name="center_panel()">
+<%
+ show_deleted = context.get( 'show_deleted', None )
+ show_hidden = context.get( 'show_hidden', None )
+
+ user_is_owner_json = 'true' if user_is_owner else 'false'
+ show_deleted_json = h.to_json_string( show_deleted )
+ show_hidden_json = h.to_json_string( show_hidden )
+
+ imp_with_deleted_url = h.url_for( controller='history', action='imp', id=history['id'], all_datasets=True )
+ imp_without_deleted_url = h.url_for( controller='history', action='imp', id=history['id'] )
+%>
+
<div id="header" class="clear"><div id="history-view-controls" class="pull-right">
- <%
- show_deleted = context.get( 'show_deleted', None )
- show_hidden = context.get( 'show_hidden', None )
-
- show_deleted_js = 'true' if show_deleted == True else ( 'null' if show_deleted == None else 'false' )
- show_hidden_js = 'true' if show_hidden == True else ( 'null' if show_hidden == None else 'false' )
- print 'user_is_owner:', user_is_owner
- %>
%if not user_is_owner and not history[ 'purged' ]:
- <a id="import" class="btn btn-default" style="display: none;"
- href="${h.url_for( controller='history', action='imp', id=history['id'], all_datasets=show_deleted )}">
- ${_('Import and start using history')}
- </a>
+ <button id="import" class="btn btn-default"></button>
%endif
- <button id="toggle-deleted" class="btn btn-default">
- ${_('Exclude deleted') if show_deleted else _('Include deleted')}
- </button>
- <button id="toggle-hidden" class="btn btn-default">
- ${_('Exclude hidden') if show_hidden else _('Include hidden')}
- </button>
+ <button id="toggle-deleted" class="btn btn-default"></button>
+ <button id="toggle-hidden" class="btn btn-default"></button></div></div><div id="history-${ history[ 'id' ] }" class="history-panel unified-panel-body" style="overflow: auto;"></div><script type="text/javascript">
+ $(function(){
+ $( '#toggle-deleted' ).modeButton({
+ initialMode : "${ 'showing_deleted' if show_deleted else 'not_showing_deleted' }",
+ modes: [
+ { mode: 'showing_deleted', html: _l( 'Exclude deleted' ) },
+ { mode: 'not_showing_deleted', html: _l( 'Include deleted' ) }
+ ]
+ }).click( function(){
+ // allow the 'include/exclude deleted' button to control whether the 'import' button includes deleted
+ // datasets when importing or not; when deleted datasets are shown, they'll be imported
+ $( '#import' ).modeButton( 'setMode',
+ $( this ).modeButton( 'current' ) === 'showing_deleted'? 'with_deleted': 'without_deleted' )
+ });
+
+ $( '#toggle-hidden' ).modeButton({
+ initialMode : "${ 'showing_hidden' if show_hidden else 'not_showing_hidden' }",
+ modes: [
+ { mode: 'showing_hidden', html: _l( 'Exclude hidden' ) },
+ { mode: 'not_showing_hidden', html: _l( 'Include hidden' ) }
+ ]
+ });
+
+ $( '#import' ).modeButton({
+ switchModesOnClick : false,
+ initialMode : "${ 'with_deleted' if show_deleted else 'without_deleted' }",
+ modes: [
+ { mode: 'with_deleted', html: _l( 'Import with deleted datasets and start using history' ),
+ onclick: function importWithDeleted(){
+ window.location = '${imp_with_deleted_url}';
+ }
+ },
+ { mode: 'without_deleted', html: _l( 'Import and start using history' ),
+ onclick: function importWithoutDeleted(){
+ window.location = '${imp_without_deleted_url}';
+ }
+ },
+ ]
+ });
+ });
+
var debugging = JSON.parse( sessionStorage.getItem( 'debugging' ) ) || false,
userIsOwner = ${'true' if user_is_owner else 'false'},
historyJSON = ${h.to_json_string( history )},
hdaJSON = ${h.to_json_string( hdas )};
- window.hdaJSON = hdaJSON;
-
- $( '#toggle-deleted' ).modeButton({
- initialMode : (${ show_deleted_js })?( 'exclude' ):( 'include' ),
- modes: [
- { mode: 'exclude', html: _l( 'Exclude deleted' ) },
- { mode: 'include', html: _l( 'Include deleted' ) }
- ]
- }).click( function(){
- // allow the 'include/exclude deleted' button to control whether the 'import' button includes deleted datasets
- // when importing or not; when deleted datasets are shown, they'll be imported
- var $importBtn = $( '#import' );
- if( $importBtn.size() ){
- // a bit hacky
- var href = $importBtn.attr( 'href' ),
- includeDeleted = $( this ).modeButton()[0].getMode().mode === 'exclude';
- href = href.replace( /all_datasets=True|False/, ( includeDeleted )?( 'True' ):( 'False' ) );
- $importBtn.attr( 'href', href );
- $importBtn.text( includeDeleted ? _l( 'Import with deleted datasets and start using history' )
- : _l( 'Import and start using history' ) );
- }
- });
-
- $( '#toggle-hidden' ).modeButton({
- initialMode : (${ show_hidden_js })?( 'exclude' ):( 'include' ),
- modes: [
- { mode: 'exclude', html: _l( 'Exclude hidden' ) },
- { mode: 'include', html: _l( 'Include hidden' ) }
- ]
- });
-
- ##TODO: move to mako
- if( Galaxy.currUser.id !== historyJSON.user_id ){
- $( '#import' ).show();
- }
+ panelToUse = ( userIsOwner )?
+ ({ location: 'mvc/history/history-panel', className: 'HistoryPanel' }):
+ ({ location: 'mvc/history/readonly-history-panel', className: 'ReadOnlyHistoryPanel' });
require.config({
baseUrl : "${h.url_for( '/static/scripts' )}"
- })([
- %if user_is_owner:
- 'mvc/history/history-panel'
- %else:
- 'mvc/history/readonly-history-panel'
- %endif
- ${ }
- ], function( panelMod ){
- //require([ "mvc/history/history-panel" ], function( historyPanel ){
- // history module is already in the dpn chain from the panel. We can re-scope it here.
- var historyModel = require( 'mvc/history/history-model' ),
- hdaBaseView = require( 'mvc/dataset/hda-base' ),
- history = new historyModel.History( historyJSON, hdaJSON, {
- logger: ( debugging )?( console ):( null )
+ })([ panelToUse.location ], function( panelMod ){
+ $(function(){
+ var panelClass = panelMod[ panelToUse.className ],
+ // history module is already in the dpn chain from the panel. We can re-scope it here.
+ historyModel = require( 'mvc/history/history-model' ),
+ hdaBaseView = require( 'mvc/dataset/hda-base' ),
+ history = new historyModel.History( historyJSON, hdaJSON, {
+ logger: ( debugging )?( console ):( null )
+ });
+
+ window.historyPanel = new panelClass({
+ show_deleted : ${show_deleted_json},
+ show_hidden : ${show_hidden_json},
+ el : $( "#history-" + historyJSON.id ),
+ model : history,
+ onready : function(){
+ var panel = this;
+ $( '#toggle-deleted' ).on( 'click', function(){
+ panel.toggleShowDeleted();
+ });
+ $( '#toggle-hidden' ).on( 'click', function(){
+ panel.toggleShowHidden();
+ });
+ this.render();
+ }
});
-
- window.panelMod = panelMod;
- %if user_is_owner:
- window.panelClass = panelMod.HistoryPanel;
- %else:
- window.panelClass = panelMod.ReadOnlyHistoryPanel;
- %endif
- window.historyPanel = new panelClass({
- show_deleted : ${show_deleted_js},
- show_hidden : ${show_hidden_js},
- el : $( "#history-" + historyJSON.id ),
- model : history,
- onready : function(){
- var panel = this;
- $( '#toggle-deleted' ).on( 'click', function(){
- panel.toggleShowDeleted();
- });
- $( '#toggle-hidden' ).on( 'click', function(){
- panel.toggleShowHidden();
- });
- this.render();
- }
});
});
</script>
diff -r 0db8172d6d363ba1010df08a79f6db435f4f0ee7 -r e51429649b44d5b434a6b6f4e10daa1dbf390c20 tools/data_source/upload.xml
--- a/tools/data_source/upload.xml
+++ b/tools/data_source/upload.xml
@@ -1,7 +1,6 @@
<?xml version="1.0"?><tool name="Upload File" id="upload1" version="1.1.4" workflow_compatible="false">
- <hidden>True</hidden><description>
from your computer
</description>
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: guerler: Add get data back to to tool panel (will be replaced by a placeholder soon)
by commits-noreply@bitbucket.org 19 Feb '14
by commits-noreply@bitbucket.org 19 Feb '14
19 Feb '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/742b4ffd3b99/
Changeset: 742b4ffd3b99
User: guerler
Date: 2014-02-19 18:51:52
Summary: Add get data back to to tool panel (will be replaced by a placeholder soon)
Affected #: 1 file
diff -r 7ebec9da47844efbf37942faab3809cb0169e5c2 -r 742b4ffd3b99160cae864049f09defe710dd7ee4 tools/data_source/upload.xml
--- a/tools/data_source/upload.xml
+++ b/tools/data_source/upload.xml
@@ -1,7 +1,6 @@
<?xml version="1.0"?><tool name="Upload File" id="upload1" version="1.1.4" workflow_compatible="false">
- <hidden>True</hidden><description>
from your computer
</description>
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: carlfeberhard: history/view: clean up, replace import link with window.location; UI mode button: several fixes, clean up, docs; Remove original_view from controllers/history (and templates)
by commits-noreply@bitbucket.org 19 Feb '14
by commits-noreply@bitbucket.org 19 Feb '14
19 Feb '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/7ebec9da4784/
Changeset: 7ebec9da4784
User: carlfeberhard
Date: 2014-02-19 18:32:06
Summary: history/view: clean up, replace import link with window.location; UI mode button: several fixes, clean up, docs; Remove original_view from controllers/history (and templates)
Affected #: 5 files
diff -r c85f8fb5d63e667b63e10cdce518254f56002f55 -r 7ebec9da47844efbf37942faab3809cb0169e5c2 lib/galaxy/webapps/galaxy/controllers/history.py
--- a/lib/galaxy/webapps/galaxy/controllers/history.py
+++ b/lib/galaxy/webapps/galaxy/controllers/history.py
@@ -843,35 +843,6 @@
history. <br>You can <a href="%s">continue and import this history</a> or %s.
""" % ( web.url_for(controller='history', action='imp', id=id, confirm=True, referer=trans.request.referer ), referer_message ), use_panels=True )
- # Replaced with view (below) but kept (available via manual URL editing) for now
- @web.expose
- def original_view( self, trans, id=None, show_deleted=False, use_panels=True ):
- """View a history. If a history is importable, then it is viewable by any user."""
- # Get history to view.
- if not id:
- return trans.show_error_message( "You must specify a history you want to view." )
- history_to_view = self.get_history( trans, id, False)
- # Integrity checks.
- if not history_to_view:
- return trans.show_error_message( "The specified history does not exist." )
- # Admin users can view any history
- if( ( history_to_view.user != trans.user )
- and ( not trans.user_is_admin() )
- and ( not history_to_view.importable ) ):
- error( "Either you are not allowed to view this history or the owner of this history has not made it accessible." )
- # View history.
- show_deleted = galaxy.util.string_as_bool( show_deleted )
- datasets = self.get_history_datasets( trans, history_to_view, show_deleted=show_deleted )
- try:
- use_panels = galaxy.util.string_as_bool( use_panels )
- except:
- pass # already a bool
- return trans.stream_template_mako( "history/original_view.mako",
- history = history_to_view,
- datasets = datasets,
- show_deleted = show_deleted,
- use_panels = use_panels )
-
@web.expose
def view( self, trans, id=None, show_deleted=False, show_hidden=False, use_panels=True ):
"""
diff -r c85f8fb5d63e667b63e10cdce518254f56002f55 -r 7ebec9da47844efbf37942faab3809cb0169e5c2 static/scripts/mvc/ui.js
--- a/static/scripts/mvc/ui.js
+++ b/static/scripts/mvc/ui.js
@@ -783,77 +783,110 @@
* });
* $( '.myElement' ).modeButton( 'callModeFn', 'bler' );
*/
+ /** constructor */
function ModeButton( element, options ){
this.currModeIndex = 0;
- return this.init( element, options );
+ return this._init( element, options );
}
+ /** html5 data key to store this object inside an element */
ModeButton.prototype.DATA_KEY = 'mode-button';
+ /** default options */
ModeButton.prototype.defaults = {
- modes : [
- { mode: 'default' }
- ]
+ switchModesOnClick : true
};
- ModeButton.prototype.init = function _init( element, options ){
+ // ---- private interface
+ /** set up options, intial mode, and the click handler */
+ ModeButton.prototype._init = function _init( element, options ){
+ //console.debug( 'ModeButton._init:', element, options );
options = options || {};
this.$element = $( element );
this.options = jQuery.extend( true, {}, this.defaults, options );
+ if( !options.modes ){
+ throw new Error( 'ModeButton requires a "modes" array' );
+ }
var modeButton = this;
this.$element.click( function _ModeButtonClick( event ){
-
// call the curr mode fn
modeButton.callModeFn();
// inc the curr mode index
- modeButton._incModeIndex();
+ if( modeButton.options.switchModesOnClick ){ modeButton._incModeIndex(); }
// set the element html
$( this ).html( modeButton.options.modes[ modeButton.currModeIndex ].html );
});
-
- this.currModeIndex = 0;
- if( this.options.initialMode ){
- this.currModeIndex = this._getModeIndex( this.options.initialMode );
- }
- return this;
+ return this.reset();
};
-
-
- ModeButton.prototype._getModeIndex = function __getModeIndex( modeKey ){
- for( var i=0; i<this.options.modes.length; i+=1 ){
- if( this.options.modes[ i ].mode === modeKey ){ return i; }
- }
- throw new Error( 'mode not found: ' + modeKey );
- };
- ModeButton.prototype.getCurrMode = function _getCurrMode(){
- return this.options.modes[ this.currModeIndex ];
- };
- ModeButton.prototype.getMode = function _getMode( modeKey ){
- if( !modeKey ){ return this.getCurrMode(); }
- return this.options.modes[( this._getModeIndex( modeKey ) )];
- };
- ModeButton.prototype.hasMode = function _hasMode( modeKey ){
- return !!this.getMode( modeKey );
- };
- ModeButton.prototype.currentMode = function _currentMode(){
- return this.options.modes[ this.currModeIndex ];
- };
- ModeButton.prototype.setMode = function _setMode( newModeKey ){
- var newMode = this.getMode( newModeKey );
- this.$element.html( newMode.html || null );
- return this;
- };
- ModeButton.prototype._incModeIndex = function __incModeIndex(){
+ /** increment the mode index to the next in the array, looping back to zero if at the last */
+ ModeButton.prototype._incModeIndex = function _incModeIndex(){
this.currModeIndex += 1;
if( this.currModeIndex >= this.options.modes.length ){
this.currModeIndex = 0;
}
return this;
};
- ModeButton.prototype.callModeFn = function _callModeFn( modeKey ){
+ /** get the mode index in the modes array for the given key (mode name) */
+ ModeButton.prototype._getModeIndex = function _getModeIndex( modeKey ){
+ for( var i=0; i<this.options.modes.length; i+=1 ){
+ if( this.options.modes[ i ].mode === modeKey ){ return i; }
+ }
+ throw new Error( 'mode not found: ' + modeKey );
+ };
+ /** set the current mode to the one with the given index and set button html */
+ ModeButton.prototype._setModeByIndex = function _setModeByIndex( index ){
+ var newMode = this.options.modes[ index ];
+ if( !newMode ){
+ throw new Error( 'mode index not found: ' + index );
+ }
+ this.currModeIndex = index;
+ if( newMode.html ){
+ this.$element.html( newMode.html );
+ }
+ return this;
+ };
+
+ // ---- public interface
+ /** get the current mode object (not just the mode name) */
+ ModeButton.prototype.currentMode = function currentMode(){
+ return this.options.modes[ this.currModeIndex ];
+ };
+ /** return the mode key of the current mode */
+ ModeButton.prototype.current = function current(){
+ // sugar for returning mode name
+ return this.currentMode().mode;
+ };
+ /** get the mode with the given modeKey or the current mode if modeKey is undefined */
+ ModeButton.prototype.getMode = function getMode( modeKey ){
+ if( !modeKey ){ return this.currentMode(); }
+ return this.options.modes[( this._getModeIndex( modeKey ) )];
+ };
+ /** T/F if the button has the given mode */
+ ModeButton.prototype.hasMode = function hasMode( modeKey ){
+ try {
+ return !!this.getMode( modeKey );
+ } catch( err ){}
+ return false;
+ };
+ /** set the current mode to the mode with the given name */
+ ModeButton.prototype.setMode = function setMode( modeKey ){
+ return this._setModeByIndex( this._getModeIndex( modeKey ) );
+ };
+ /** reset to the initial mode */
+ ModeButton.prototype.reset = function reset(){
+ this.currModeIndex = 0;
+ if( this.options.initialMode ){
+ this.currModeIndex = this._getModeIndex( this.options.initialMode );
+ }
+ return this._setModeByIndex( this.currModeIndex );
+ };
+ /** manually call the click handler of the given mode */
+ ModeButton.prototype.callModeFn = function callModeFn( modeKey ){
var modeFn = this.getMode( modeKey ).onclick;
if( modeFn && jQuery.type( modeFn === 'function' ) ){
- return modeFn.call( this );
+ // call with the element as context (std jquery pattern)
+ modeFn.call( this.$element.get(0) );
+ return this;
}
return undefined;
};
@@ -861,26 +894,32 @@
// as jq plugin
jQuery.fn.extend({
modeButton : function $modeButton( options ){
- var nonOptionsArgs = jQuery.makeArray( arguments ).slice( 1 );
+ if( !this.size() ){ return this; }
+
//TODO: does map still work with jq multi selection (i.e. $( '.class-for-many-btns' ).modeButton)?
- return this.map( function(){
- var $this = $( this ),
- data = $this.data( 'mode-button' );
+ if( jQuery.type( options ) === 'object' ){
+ return this.map( function(){
+ var $this = $( this );
+ $this.data( 'mode-button', new ModeButton( $this, options ) );
+ return this;
+ });
+ }
- if( jQuery.type( options ) === 'object' ){
- data = new ModeButton( $this, options );
- $this.data( 'mode-button', data );
+ var $first = $( this[0] ),
+ button = $first.data( 'mode-button' );
+ console.debug( 'first, button', $first, button );
- } else if( data && jQuery.type( options ) === 'string' ){
- var fn = data[ options ];
- if( jQuery.type( fn ) === 'function' ){
- return fn.apply( data, nonOptionsArgs );
- }
- } else if ( data ){
- return data;
+ if( !button ){
+ throw new Error( 'modeButton needs an options object or string name of a function' );
+ }
+
+ if( button && jQuery.type( options ) === 'string' ){
+ var fnName = options;
+ if( button && jQuery.type( button[ fnName ] ) === 'function' ){
+ return button[ fnName ].apply( button, jQuery.makeArray( arguments ).slice( 1 ) );
}
- return this;
- });
+ }
+ return button;
}
});
}());
diff -r c85f8fb5d63e667b63e10cdce518254f56002f55 -r 7ebec9da47844efbf37942faab3809cb0169e5c2 static/scripts/packed/mvc/ui.js
--- a/static/scripts/packed/mvc/ui.js
+++ b/static/scripts/packed/mvc/ui.js
@@ -1,1 +1,1 @@
-var IconButton=Backbone.Model.extend({defaults:{title:"",icon_class:"",on_click:null,menu_options:null,is_menu_button:true,id:null,href:null,target:null,enabled:true,visible:true,tooltip_config:{}}});var IconButtonView=Backbone.View.extend({initialize:function(){this.model.attributes.tooltip_config={placement:"bottom"};this.model.bind("change",this.render,this)},render:function(){this.$el.tooltip("hide");var a=this.template(this.model.toJSON());a.tooltip(this.model.get("tooltip_config"));this.$el.replaceWith(a);this.setElement(a);return this},events:{click:"click"},click:function(a){if(_.isFunction(this.model.get("on_click"))){this.model.get("on_click")(a);return false}return true},template:function(b){var a='title="'+b.title+'" class="icon-button';if(b.is_menu_button){a+=" menu-button"}a+=" "+b.icon_class;if(!b.enabled){a+="_disabled"}a+='"';if(b.id){a+=' id="'+b.id+'"'}a+=' href="'+b.href+'"';if(b.target){a+=' target="'+b.target+'"'}if(!b.visible){a+=' style="display: none;"'}if(b.enabled){a="<a "+a+"/>"}else{a="<span "+a+"/>"}return $(a)}});var IconButtonCollection=Backbone.Collection.extend({model:IconButton});var IconButtonMenuView=Backbone.View.extend({tagName:"div",initialize:function(){this.render()},render:function(){var a=this;this.collection.each(function(d){var b=$("<a/>").attr("href","javascript:void(0)").attr("title",d.attributes.title).addClass("icon-button menu-button").addClass(d.attributes.icon_class).appendTo(a.$el).click(d.attributes.on_click);if(d.attributes.tooltip_config){b.tooltip(d.attributes.tooltip_config)}var c=d.get("options");if(c){make_popupmenu(b,c)}});return this}});var create_icon_buttons_menu=function(b,a){if(!a){a={}}var c=new IconButtonCollection(_.map(b,function(d){return new IconButton(_.extend(d,a))}));return new IconButtonMenuView({collection:c})};var Grid=Backbone.Collection.extend({});var GridView=Backbone.View.extend({});var PopupMenu=Backbone.View.extend({initialize:function(b,a){this.$button=b;if(!this.$button.size()){this.$button=$("<div/>")}this.options=a||[];var c=this;this.$button.click(function(d){$(".popmenu-wrapper").remove();c._renderAndShow(d);return false})},_renderAndShow:function(a){this.render();this.$el.appendTo("body").css(this._getShownPosition(a)).show();this._setUpCloseBehavior()},render:function(){this.$el.addClass("popmenu-wrapper").hide().css({position:"absolute"}).html(this.template(this.$button.attr("id"),this.options));if(this.options.length){var a=this;this.$el.find("li").each(function(c,b){var d=a.options[c];if(d.func){$(this).children("a.popupmenu-option").click(function(e){d.func.call(a,e,d)})}})}return this},template:function(b,a){return['<ul id="',b,'-menu" class="dropdown-menu">',this._templateOptions(a),"</ul>"].join("")},_templateOptions:function(a){if(!a.length){return"<li>(no options)</li>"}return _.map(a,function(d){if(d.divider){return'<li class="divider"></li>'}else{if(d.header){return['<li class="head"><a href="javascript:void(0);">',d.html,"</a></li>"].join("")}}var c=d.href||"javascript:void(0);",e=(d.target)?(' target="'+d.target+'"'):(""),b=(d.checked)?('<span class="fa fa-check"></span>'):("");return['<li><a class="popupmenu-option" href="',c,'"',e,">",b,d.html,"</a></li>"].join("")}).join("")},_getShownPosition:function(b){var c=this.$el.width();var a=b.pageX-c/2;a=Math.min(a,$(document).scrollLeft()+$(window).width()-c-5);a=Math.max(a,$(document).scrollLeft()+5);return{top:b.pageY,left:a}},_setUpCloseBehavior:function(){var c=this;function a(e){$(document).off("click.close_popup");if(window.parent!==window){try{$(window.parent.document).off("click.close_popup")}catch(d){}}else{try{$("iframe#galaxy_main").contents().off("click.close_popup")}catch(d){}}c.remove()}$("html").one("click.close_popup",a);if(window.parent!==window){try{$(window.parent.document).find("html").one("click.close_popup",a)}catch(b){}}else{try{$("iframe#galaxy_main").contents().one("click.close_popup",a)}catch(b){}}},addItem:function(b,a){a=(a>=0)?a:this.options.length;this.options.splice(a,0,b);return this},removeItem:function(a){if(a>=0){this.options.splice(a,1)}return this},findIndexByHtml:function(b){for(var a=0;a<this.options.length;a++){if(_.has(this.options[a],"html")&&(this.options[a].html===b)){return a}}return null},findItemByHtml:function(a){return this.options[(this.findIndexByHtml(a))]},toString:function(){return"PopupMenu"}});PopupMenu.create=function _create(b,a){return new PopupMenu(b,a)};PopupMenu.make_popupmenu=function(b,c){var a=[];_.each(c,function(f,d){var e={html:d};if(f===null){e.header=true}else{if(jQuery.type(f)==="function"){e.func=f}}a.push(e)});return new PopupMenu($(b),a)};PopupMenu.convertLinksToOptions=function(c,a){c=$(c);a=a||"a";var b=[];c.find(a).each(function(g,e){var f={},d=$(g);f.html=d.text();if(d.attr("href")){var j=d.attr("href"),k=d.attr("target"),h=d.attr("confirm");f.func=function(){if((h)&&(!confirm(h))){return}switch(k){case"_parent":window.parent.location=j;break;case"_top":window.top.location=j;break;default:window.location=j}}}b.push(f)});return b};PopupMenu.fromExistingDom=function(d,c,a){d=$(d);c=$(c);var b=PopupMenu.convertLinksToOptions(c,a);c.remove();return new PopupMenu(d,b)};PopupMenu.make_popup_menus=function(c,b,d){c=c||document;b=b||"div[popupmenu]";d=d||function(e,f){return"#"+e.attr("popupmenu")};var a=[];$(c).find(b).each(function(){var e=$(this),f=$(c).find(d(e,c));a.push(PopupMenu.fromDom(f,e));f.addClass("popup")});return a};var faIconButton=function(a){a=a||{};a.tooltipConfig=a.tooltipConfig||{placement:"bottom"};a.classes=["icon-btn"].concat(a.classes||[]);if(a.disabled){a.classes.push("disabled")}var b=['<a class="',a.classes.join(" "),'"',((a.title)?(' title="'+a.title+'"'):("")),((!a.disabled&&a.target)?(' target="'+a.target+'"'):("")),' href="',((!a.disabled&&a.href)?(a.href):("javascript:void(0);")),'">','<span class="fa ',a.faIcon,'"></span>',"</a>"].join("");var c=$(b).tooltip(a.tooltipConfig);if(_.isFunction(a.onclick)){c.click(a.onclick)}return c};function LoadingIndicator(a,c){var b=this;c=jQuery.extend({cover:false},c||{});function d(){var e=['<div class="loading-indicator">','<div class="loading-indicator-text">','<span class="fa fa-spinner fa-spin fa-lg"></span>','<span class="loading-indicator-message">loading...</span>',"</div>","</div>"].join("\n");var g=$(e).hide().css(c.css||{position:"fixed"}),f=g.children(".loading-indicator-text");if(c.cover){g.css({"z-index":2,top:a.css("top"),bottom:a.css("bottom"),left:a.css("left"),right:a.css("right"),opacity:0.5,"background-color":"white","text-align":"center"});f=g.children(".loading-indicator-text").css({"margin-top":"20px"})}else{f=g.children(".loading-indicator-text").css({margin:"12px 0px 0px 10px",opacity:"0.85",color:"grey"});f.children(".loading-indicator-message").css({margin:"0px 8px 0px 0px","font-style":"italic"})}return g}b.show=function(f,e,g){f=f||"loading...";e=e||"fast";b.$indicator=d().insertBefore(a);b.message(f);b.$indicator.fadeIn(e,g);return b};b.message=function(e){b.$indicator.find("i").text(e)};b.hide=function(e,f){e=e||"fast";if(b.$indicator&&b.$indicator.size()){b.$indicator.fadeOut(e,function(){b.$indicator.remove();if(f){f()}})}else{if(f){f()}}return b};return b}(function(){function a(j,p){var d=27,m=13,c=$(j),e=true,g={initialVal:"",name:"search",placeholder:"search",classes:"",onclear:function(){},onfirstsearch:null,onsearch:function(q){},minSearchLen:0,escWillClear:true,oninit:function(){}};function i(q){var r=$(this).parent().children("input");r.val("");r.trigger("clear:searchInput");p.onclear()}function o(r,q){$(this).trigger("search:searchInput",q);if(typeof p.onfirstsearch==="function"&&e){e=false;p.onfirstsearch(q)}else{p.onsearch(q)}}function f(){return['<input type="text" name="',p.name,'" placeholder="',p.placeholder,'" ','class="search-query ',p.classes,'" ',"/>"].join("")}function l(){return $(f()).focus(function(q){$(this).select()}).keyup(function(r){if(r.which===d&&p.escWillClear){i.call(this,r)}else{var q=$(this).val();if((r.which===m)||(p.minSearchLen&&q.length>=p.minSearchLen)){o.call(this,r,q)}else{if(!q.length){i.call(this,r)}}}}).val(p.initialVal)}function k(){return $(['<span class="search-clear fa fa-times-circle" ','title="',_l("clear search (esc)"),'"></span>'].join("")).tooltip({placement:"bottom"}).click(function(q){i.call(this,q)})}function n(){return $(['<span class="search-loading fa fa-spinner fa-spin" ','title="',_l("loading..."),'"></span>'].join("")).hide().tooltip({placement:"bottom"})}function h(){c.find(".search-loading").toggle();c.find(".search-clear").toggle()}if(jQuery.type(p)==="string"){if(p==="toggle-loading"){h()}return c}if(jQuery.type(p)==="object"){p=jQuery.extend(true,{},g,p)}return c.addClass("search-input").prepend([l(),k(),n()])}jQuery.fn.extend({searchInput:function b(c){return this.each(function(){return a(this,c)})}})}());(function(){function b(m,l){this.currModeIndex=0;return this.init(m,l)}b.prototype.DATA_KEY="mode-button";b.prototype.defaults={modes:[{mode:"default"}]};b.prototype.init=function f(m,l){l=l||{};this.$element=$(m);this.options=jQuery.extend(true,{},this.defaults,l);var o=this;this.$element.click(function n(p){o.callModeFn();o._incModeIndex();$(this).html(o.options.modes[o.currModeIndex].html)});this.currModeIndex=0;if(this.options.initialMode){this.currModeIndex=this._getModeIndex(this.options.initialMode)}return this};b.prototype._getModeIndex=function j(l){for(var m=0;m<this.options.modes.length;m+=1){if(this.options.modes[m].mode===l){return m}}throw new Error("mode not found: "+l)};b.prototype.getCurrMode=function a(){return this.options.modes[this.currModeIndex]};b.prototype.getMode=function g(l){if(!l){return this.getCurrMode()}return this.options.modes[(this._getModeIndex(l))]};b.prototype.hasMode=function k(l){return !!this.getMode(l)};b.prototype.currentMode=function e(){return this.options.modes[this.currModeIndex]};b.prototype.setMode=function c(m){var l=this.getMode(m);this.$element.html(l.html||null);return this};b.prototype._incModeIndex=function d(){this.currModeIndex+=1;if(this.currModeIndex>=this.options.modes.length){this.currModeIndex=0}return this};b.prototype.callModeFn=function h(l){var m=this.getMode(l).onclick;if(m&&jQuery.type(m==="function")){return m.call(this)}return undefined};jQuery.fn.extend({modeButton:function i(m){var l=jQuery.makeArray(arguments).slice(1);return this.map(function(){var p=$(this),o=p.data("mode-button");if(jQuery.type(m)==="object"){o=new b(p,m);p.data("mode-button",o)}else{if(o&&jQuery.type(m)==="string"){var n=o[m];if(jQuery.type(n)==="function"){return n.apply(o,l)}}else{if(o){return o}}}return this})}})}());function dropDownSelect(b,c){c=c||((!_.isEmpty(b))?(b[0]):(""));var a=$(['<div class="dropdown-select btn-group">','<button type="button" class="btn btn-default">','<span class="dropdown-select-selected">'+c+"</span>","</button>","</div>"].join("\n"));if(b&&b.length>1){a.find("button").addClass("dropdown-toggle").attr("data-toggle","dropdown").append(' <span class="caret"></span>');a.append(['<ul class="dropdown-menu" role="menu">',_.map(b,function(e){return['<li><a href="javascript:void(0)">',e,"</a></li>"].join("")}).join("\n"),"</ul>"].join("\n"))}function d(g){var h=$(this),f=h.parents(".dropdown-select"),e=h.text();f.find(".dropdown-select-selected").text(e);f.trigger("change.dropdown-select",e)}a.find("a").click(d);return a}(function(){function e(k,j){return this.init(k,j)}e.prototype.DATA_KEY="filter-control";e.prototype.init=function g(k,j){j=j||{filters:[]};this.$element=$(k).addClass("filter-control btn-group");this.options=jQuery.extend(true,{},this.defaults,j);this.currFilter=this.options.filters[0];return this.render()};e.prototype.render=function d(){this.$element.empty().append([this._renderKeySelect(),this._renderOpSelect(),this._renderValueInput()]);return this};e.prototype._renderKeySelect=function a(){var j=this;var k=this.options.filters.map(function(l){return l.key});this.$keySelect=dropDownSelect(k,this.currFilter.key).addClass("filter-control-key").on("change.dropdown-select",function(m,l){j.currFilter=_.findWhere(j.options.filters,{key:l});j.render()._triggerChange()});return this.$keySelect};e.prototype._renderOpSelect=function i(){var j=this,k=this.currFilter.ops;this.$opSelect=dropDownSelect(k,k[0]).addClass("filter-control-op").on("change.dropdown-select",function(m,l){j._triggerChange()});return this.$opSelect};e.prototype._renderValueInput=function c(){var j=this;if(this.currFilter.values){this.$valueSelect=dropDownSelect(this.currFilter.values,this.currFilter.values[0]).on("change.dropdown-select",function(l,k){j._triggerChange()})}else{this.$valueSelect=$("<input/>").addClass("form-control").on("change",function(k,l){j._triggerChange()})}this.$valueSelect.addClass("filter-control-value");return this.$valueSelect};e.prototype.val=function b(){var k=this.$element.find(".filter-control-key .dropdown-select-selected").text(),m=this.$element.find(".filter-control-op .dropdown-select-selected").text(),j=this.$element.find(".filter-control-value"),l=(j.hasClass("dropdown-select"))?(j.find(".dropdown-select-selected").text()):(j.val());return{key:k,op:m,value:l}};e.prototype._triggerChange=function h(){this.$element.trigger("change.filter-control",this.val())};jQuery.fn.extend({filterControl:function f(k){var j=jQuery.makeArray(arguments).slice(1);return this.map(function(){var n=$(this),m=n.data(e.prototype.DATA_KEY);if(jQuery.type(k)==="object"){m=new e(n,k);n.data(e.prototype.DATA_KEY,m)}if(m&&jQuery.type(k)==="string"){var l=m[k];if(jQuery.type(l)==="function"){return l.apply(m,j)}}return this})}})}());(function(){function i(o,n){this.numPages=null;this.currPage=0;return this.init(o,n)}i.prototype.DATA_KEY="pagination";i.prototype.defaults={startingPage:0,perPage:20,totalDataSize:null,currDataSize:null};i.prototype.init=function g(n,o){o=o||{};this.$element=n;this.options=jQuery.extend(true,{},this.defaults,o);this.currPage=this.options.startingPage;if(this.options.totalDataSize!==null){this.numPages=Math.ceil(this.options.totalDataSize/this.options.perPage);if(this.currPage>=this.numPages){this.currPage=this.numPages-1}}this.$element.data(i.prototype.DATA_KEY,this);this._render();return this};function m(n){return $(['<li><a href="javascript:void(0);">',n,"</a></li>"].join(""))}i.prototype._render=function e(){if(this.options.totalDataSize===0){return this}if(this.numPages===1){return this}if(this.numPages>0){this._renderPages();this._scrollToActivePage()}else{this._renderPrevNext()}return this};i.prototype._renderPrevNext=function b(){var o=this,p=m("Prev"),n=m("Next"),q=$("<ul/>").addClass("pagination pagination-prev-next");if(this.currPage===0){p.addClass("disabled")}else{p.click(function(){o.prevPage()})}if((this.numPages&&this.currPage===(this.numPages-1))||(this.options.currDataSize&&this.options.currDataSize<this.options.perPage)){n.addClass("disabled")}else{n.click(function(){o.nextPage()})}this.$element.html(q.append([p,n]));return this.$element};i.prototype._renderPages=function a(){var n=this,q=$("<div>").addClass("pagination-scroll-container"),s=$("<ul/>").addClass("pagination pagination-page-list"),r=function(t){n.goToPage($(this).data("page"))};for(var o=0;o<this.numPages;o+=1){var p=m(o+1).attr("data-page",o).click(r);if(o===this.currPage){p.addClass("active")}s.append(p)}return this.$element.html(q.html(s))};i.prototype._scrollToActivePage=function l(){var p=this.$element.find(".pagination-scroll-container");if(!p.size()){return this}var o=this.$element.find("li.active"),n=p.width()/2;p.scrollLeft(p.scrollLeft()+o.position().left-n);return this};i.prototype.goToPage=function j(n){if(n<=0){n=0}if(this.numPages&&n>=this.numPages){n=this.numPages-1}if(n===this.currPage){return this}this.currPage=n;this.$element.trigger("pagination.page-change",this.currPage);this._render();return this};i.prototype.prevPage=function c(){return this.goToPage(this.currPage-1)};i.prototype.nextPage=function h(){return this.goToPage(this.currPage+1)};i.prototype.page=function f(){return this.currPage};i.create=function k(n,o){return new i(n,o)};jQuery.fn.extend({pagination:function d(o){var n=jQuery.makeArray(arguments).slice(1);if(jQuery.type(o)==="object"){return this.map(function(){i.create($(this),o);return this})}var q=$(this[0]),r=q.data(i.prototype.DATA_KEY);if(r){if(jQuery.type(o)==="string"){var p=r[o];if(jQuery.type(p)==="function"){return p.apply(r,n)}}else{return r}}return undefined}})}());(function(){var g={renameColumns:false,columnNames:[],commentChar:"#",hideCommentRows:false,includePrompts:true,topLeftContent:"Columns:"},s="peek-control.change",t="peek-control.rename",l="peek-control",v="control",f="control-prompt",c="selected",n="disabled",u="button",q="renamable-header",p="column-index",a="column-name";function i(w){if(w.disabled&&jQuery.type(w.disabled)!=="array"){throw new Error('"disabled" must be defined as an array of indeces: '+JSON.stringify(w))}if(w.multiselect&&w.selected&&jQuery.type(w.selected)!=="array"){throw new Error('Mulitselect rows need an array for "selected": '+JSON.stringify(w))}if(!w.label||!w.id){throw new Error("Peek controls need a label and id for each control row: "+JSON.stringify(w))}if(w.disabled&&w.disabled.indexOf(w.selected)!==-1){throw new Error("Selected column is in the list of disabled columns: "+JSON.stringify(w))}return w}function o(x,w){return $("<div/>").addClass(u).text(x.label)}function k(x,w){var y=$("<td/>").html(o(x,w)).attr("data-"+p,w);if(x.disabled&&x.disabled.indexOf(w)!==-1){y.addClass(n)}return y}function e(y,z,w){var x=y.children("."+u);if(y.hasClass(c)){x.html((z.selectedText!==undefined)?(z.selectedText):(z.label))}else{x.html((z.unselectedText!==undefined)?(z.unselectedText):(z.label))}}function h(z,x){var y=k(z,x);if(z.selected===x){y.addClass(c)}e(y,z,x);if(!y.hasClass(n)){y.click(function w(D){var E=$(this);if(!E.hasClass(c)){var A=E.parent().children("."+c).removeClass(c);A.each(function(){e($(this),z,x)});E.addClass(c);e(E,z,x);var C={},B=E.parent().attr("id"),F=E.data(p);C[B]=F;E.parents(".peek").trigger(s,C)}})}return y}function m(z,x){var y=k(z,x);if(z.selected&&z.selected.indexOf(x)!==-1){y.addClass(c)}e(y,z,x);if(!y.hasClass(n)){y.click(function w(D){var E=$(this);E.toggleClass(c);e(E,z,x);var C=E.parent().find("."+c).map(function(G,H){return $(H).data(p)});var B={},A=E.parent().attr("id"),F=jQuery.makeArray(C);B[A]=F;E.parents(".peek").trigger(s,B)})}return y}function j(y,z){var w=[];for(var x=0;x<y;x+=1){w.push(z.multiselect?m(z,x):h(z,x))}return w}function r(y,z,x){var A=$("<tr/>").attr("id",z.id).addClass(v);if(x){var w=$("<td/>").addClass(f).text(z.label+":");A.append(w)}A.append(j(y,z));return A}function b(E){E=jQuery.extend(true,{},g,E);var D=$(this).addClass(l),A=D.find("table"),z=A.find("th").size(),C=A.find("tr").size(),w=A.find("td[colspan]").map(function(H,F){var G=$(this);if(G.text()&&G.text().match(new RegExp("^"+E.commentChar))){return $(this).css("color","grey").parent().get(0)}return null});if(E.hideCommentRows){w.hide();C-=w.size()}if(E.includePrompts){var y=$("<th/>").addClass("top-left").text(E.topLeftContent).attr("rowspan",C);A.find("tr").first().prepend(y)}var B=A.find("th:not(.top-left)").each(function(G,I){var H=$(this),J=H.text().replace(/^\d+\.*/,""),F=E.columnNames[G]||J;H.attr("data-"+a,F).text((G+1)+((F)?("."+F):("")))});if(E.renameColumns){B.addClass(q).click(function x(){var G=$(this),F=G.index()+(E.includePrompts?0:1),I=G.data(a),H=prompt("New column name:",I);if(H!==null&&H!==I){G.text(F+(H?("."+H):"")).data(a,H).attr("data-",a,H);var J=jQuery.makeArray(G.parent().children("th:not(.top-left)").map(function(){return $(this).data(a)}));G.parents(".peek").trigger(t,J)}})}E.controls.forEach(function(G,F){i(G);var H=r(z,G,E.includePrompts);A.find("tbody").append(H)});return this}jQuery.fn.extend({peekControl:function d(w){return this.map(function(){return b.call(this,w)})}})}());
\ No newline at end of file
+var IconButton=Backbone.Model.extend({defaults:{title:"",icon_class:"",on_click:null,menu_options:null,is_menu_button:true,id:null,href:null,target:null,enabled:true,visible:true,tooltip_config:{}}});var IconButtonView=Backbone.View.extend({initialize:function(){this.model.attributes.tooltip_config={placement:"bottom"};this.model.bind("change",this.render,this)},render:function(){this.$el.tooltip("hide");var a=this.template(this.model.toJSON());a.tooltip(this.model.get("tooltip_config"));this.$el.replaceWith(a);this.setElement(a);return this},events:{click:"click"},click:function(a){if(_.isFunction(this.model.get("on_click"))){this.model.get("on_click")(a);return false}return true},template:function(b){var a='title="'+b.title+'" class="icon-button';if(b.is_menu_button){a+=" menu-button"}a+=" "+b.icon_class;if(!b.enabled){a+="_disabled"}a+='"';if(b.id){a+=' id="'+b.id+'"'}a+=' href="'+b.href+'"';if(b.target){a+=' target="'+b.target+'"'}if(!b.visible){a+=' style="display: none;"'}if(b.enabled){a="<a "+a+"/>"}else{a="<span "+a+"/>"}return $(a)}});var IconButtonCollection=Backbone.Collection.extend({model:IconButton});var IconButtonMenuView=Backbone.View.extend({tagName:"div",initialize:function(){this.render()},render:function(){var a=this;this.collection.each(function(d){var b=$("<a/>").attr("href","javascript:void(0)").attr("title",d.attributes.title).addClass("icon-button menu-button").addClass(d.attributes.icon_class).appendTo(a.$el).click(d.attributes.on_click);if(d.attributes.tooltip_config){b.tooltip(d.attributes.tooltip_config)}var c=d.get("options");if(c){make_popupmenu(b,c)}});return this}});var create_icon_buttons_menu=function(b,a){if(!a){a={}}var c=new IconButtonCollection(_.map(b,function(d){return new IconButton(_.extend(d,a))}));return new IconButtonMenuView({collection:c})};var Grid=Backbone.Collection.extend({});var GridView=Backbone.View.extend({});var PopupMenu=Backbone.View.extend({initialize:function(b,a){this.$button=b;if(!this.$button.size()){this.$button=$("<div/>")}this.options=a||[];var c=this;this.$button.click(function(d){$(".popmenu-wrapper").remove();c._renderAndShow(d);return false})},_renderAndShow:function(a){this.render();this.$el.appendTo("body").css(this._getShownPosition(a)).show();this._setUpCloseBehavior()},render:function(){this.$el.addClass("popmenu-wrapper").hide().css({position:"absolute"}).html(this.template(this.$button.attr("id"),this.options));if(this.options.length){var a=this;this.$el.find("li").each(function(c,b){var d=a.options[c];if(d.func){$(this).children("a.popupmenu-option").click(function(e){d.func.call(a,e,d)})}})}return this},template:function(b,a){return['<ul id="',b,'-menu" class="dropdown-menu">',this._templateOptions(a),"</ul>"].join("")},_templateOptions:function(a){if(!a.length){return"<li>(no options)</li>"}return _.map(a,function(d){if(d.divider){return'<li class="divider"></li>'}else{if(d.header){return['<li class="head"><a href="javascript:void(0);">',d.html,"</a></li>"].join("")}}var c=d.href||"javascript:void(0);",e=(d.target)?(' target="'+d.target+'"'):(""),b=(d.checked)?('<span class="fa fa-check"></span>'):("");return['<li><a class="popupmenu-option" href="',c,'"',e,">",b,d.html,"</a></li>"].join("")}).join("")},_getShownPosition:function(b){var c=this.$el.width();var a=b.pageX-c/2;a=Math.min(a,$(document).scrollLeft()+$(window).width()-c-5);a=Math.max(a,$(document).scrollLeft()+5);return{top:b.pageY,left:a}},_setUpCloseBehavior:function(){var c=this;function a(e){$(document).off("click.close_popup");if(window.parent!==window){try{$(window.parent.document).off("click.close_popup")}catch(d){}}else{try{$("iframe#galaxy_main").contents().off("click.close_popup")}catch(d){}}c.remove()}$("html").one("click.close_popup",a);if(window.parent!==window){try{$(window.parent.document).find("html").one("click.close_popup",a)}catch(b){}}else{try{$("iframe#galaxy_main").contents().one("click.close_popup",a)}catch(b){}}},addItem:function(b,a){a=(a>=0)?a:this.options.length;this.options.splice(a,0,b);return this},removeItem:function(a){if(a>=0){this.options.splice(a,1)}return this},findIndexByHtml:function(b){for(var a=0;a<this.options.length;a++){if(_.has(this.options[a],"html")&&(this.options[a].html===b)){return a}}return null},findItemByHtml:function(a){return this.options[(this.findIndexByHtml(a))]},toString:function(){return"PopupMenu"}});PopupMenu.create=function _create(b,a){return new PopupMenu(b,a)};PopupMenu.make_popupmenu=function(b,c){var a=[];_.each(c,function(f,d){var e={html:d};if(f===null){e.header=true}else{if(jQuery.type(f)==="function"){e.func=f}}a.push(e)});return new PopupMenu($(b),a)};PopupMenu.convertLinksToOptions=function(c,a){c=$(c);a=a||"a";var b=[];c.find(a).each(function(g,e){var f={},d=$(g);f.html=d.text();if(d.attr("href")){var j=d.attr("href"),k=d.attr("target"),h=d.attr("confirm");f.func=function(){if((h)&&(!confirm(h))){return}switch(k){case"_parent":window.parent.location=j;break;case"_top":window.top.location=j;break;default:window.location=j}}}b.push(f)});return b};PopupMenu.fromExistingDom=function(d,c,a){d=$(d);c=$(c);var b=PopupMenu.convertLinksToOptions(c,a);c.remove();return new PopupMenu(d,b)};PopupMenu.make_popup_menus=function(c,b,d){c=c||document;b=b||"div[popupmenu]";d=d||function(e,f){return"#"+e.attr("popupmenu")};var a=[];$(c).find(b).each(function(){var e=$(this),f=$(c).find(d(e,c));a.push(PopupMenu.fromDom(f,e));f.addClass("popup")});return a};var faIconButton=function(a){a=a||{};a.tooltipConfig=a.tooltipConfig||{placement:"bottom"};a.classes=["icon-btn"].concat(a.classes||[]);if(a.disabled){a.classes.push("disabled")}var b=['<a class="',a.classes.join(" "),'"',((a.title)?(' title="'+a.title+'"'):("")),((!a.disabled&&a.target)?(' target="'+a.target+'"'):("")),' href="',((!a.disabled&&a.href)?(a.href):("javascript:void(0);")),'">','<span class="fa ',a.faIcon,'"></span>',"</a>"].join("");var c=$(b).tooltip(a.tooltipConfig);if(_.isFunction(a.onclick)){c.click(a.onclick)}return c};function LoadingIndicator(a,c){var b=this;c=jQuery.extend({cover:false},c||{});function d(){var e=['<div class="loading-indicator">','<div class="loading-indicator-text">','<span class="fa fa-spinner fa-spin fa-lg"></span>','<span class="loading-indicator-message">loading...</span>',"</div>","</div>"].join("\n");var g=$(e).hide().css(c.css||{position:"fixed"}),f=g.children(".loading-indicator-text");if(c.cover){g.css({"z-index":2,top:a.css("top"),bottom:a.css("bottom"),left:a.css("left"),right:a.css("right"),opacity:0.5,"background-color":"white","text-align":"center"});f=g.children(".loading-indicator-text").css({"margin-top":"20px"})}else{f=g.children(".loading-indicator-text").css({margin:"12px 0px 0px 10px",opacity:"0.85",color:"grey"});f.children(".loading-indicator-message").css({margin:"0px 8px 0px 0px","font-style":"italic"})}return g}b.show=function(f,e,g){f=f||"loading...";e=e||"fast";b.$indicator=d().insertBefore(a);b.message(f);b.$indicator.fadeIn(e,g);return b};b.message=function(e){b.$indicator.find("i").text(e)};b.hide=function(e,f){e=e||"fast";if(b.$indicator&&b.$indicator.size()){b.$indicator.fadeOut(e,function(){b.$indicator.remove();if(f){f()}})}else{if(f){f()}}return b};return b}(function(){function a(j,p){var d=27,m=13,c=$(j),e=true,g={initialVal:"",name:"search",placeholder:"search",classes:"",onclear:function(){},onfirstsearch:null,onsearch:function(q){},minSearchLen:0,escWillClear:true,oninit:function(){}};function i(q){var r=$(this).parent().children("input");r.val("");r.trigger("clear:searchInput");p.onclear()}function o(r,q){$(this).trigger("search:searchInput",q);if(typeof p.onfirstsearch==="function"&&e){e=false;p.onfirstsearch(q)}else{p.onsearch(q)}}function f(){return['<input type="text" name="',p.name,'" placeholder="',p.placeholder,'" ','class="search-query ',p.classes,'" ',"/>"].join("")}function l(){return $(f()).focus(function(q){$(this).select()}).keyup(function(r){if(r.which===d&&p.escWillClear){i.call(this,r)}else{var q=$(this).val();if((r.which===m)||(p.minSearchLen&&q.length>=p.minSearchLen)){o.call(this,r,q)}else{if(!q.length){i.call(this,r)}}}}).val(p.initialVal)}function k(){return $(['<span class="search-clear fa fa-times-circle" ','title="',_l("clear search (esc)"),'"></span>'].join("")).tooltip({placement:"bottom"}).click(function(q){i.call(this,q)})}function n(){return $(['<span class="search-loading fa fa-spinner fa-spin" ','title="',_l("loading..."),'"></span>'].join("")).hide().tooltip({placement:"bottom"})}function h(){c.find(".search-loading").toggle();c.find(".search-clear").toggle()}if(jQuery.type(p)==="string"){if(p==="toggle-loading"){h()}return c}if(jQuery.type(p)==="object"){p=jQuery.extend(true,{},g,p)}return c.addClass("search-input").prepend([l(),k(),n()])}jQuery.fn.extend({searchInput:function b(c){return this.each(function(){return a(this,c)})}})}());(function(){function c(o,n){this.currModeIndex=0;return this._init(o,n)}c.prototype.DATA_KEY="mode-button";c.prototype.defaults={switchModesOnClick:true};c.prototype._init=function j(o,n){n=n||{};this.$element=$(o);this.options=jQuery.extend(true,{},this.defaults,n);if(!n.modes){throw new Error('ModeButton requires a "modes" array')}var q=this;this.$element.click(function p(r){q.callModeFn();if(q.options.switchModesOnClick){q._incModeIndex()}$(this).html(q.options.modes[q.currModeIndex].html)});return this.reset()};c.prototype._incModeIndex=function l(){this.currModeIndex+=1;if(this.currModeIndex>=this.options.modes.length){this.currModeIndex=0}return this};c.prototype._getModeIndex=function f(n){for(var o=0;o<this.options.modes.length;o+=1){if(this.options.modes[o].mode===n){return o}}throw new Error("mode not found: "+n)};c.prototype._setModeByIndex=function m(n){var o=this.options.modes[n];if(!o){throw new Error("mode index not found: "+n)}this.currModeIndex=n;if(o.html){this.$element.html(o.html)}return this};c.prototype.currentMode=function d(){return this.options.modes[this.currModeIndex]};c.prototype.current=function i(){return this.currentMode().mode};c.prototype.getMode=function g(n){if(!n){return this.currentMode()}return this.options.modes[(this._getModeIndex(n))]};c.prototype.hasMode=function b(n){try{return !!this.getMode(n)}catch(o){}return false};c.prototype.setMode=function a(n){return this._setModeByIndex(this._getModeIndex(n))};c.prototype.reset=function h(){this.currModeIndex=0;if(this.options.initialMode){this.currModeIndex=this._getModeIndex(this.options.initialMode)}return this._setModeByIndex(this.currModeIndex)};c.prototype.callModeFn=function e(n){var o=this.getMode(n).onclick;if(o&&jQuery.type(o==="function")){o.call(this.$element.get(0));return this}return undefined};jQuery.fn.extend({modeButton:function k(n){if(!this.size()){return this}if(jQuery.type(n)==="object"){return this.map(function(){var r=$(this);r.data("mode-button",new c(r,n));return this})}var p=$(this[0]),o=p.data("mode-button");console.debug("first, button",p,o);if(!o){throw new Error("modeButton needs an options object or string name of a function")}if(o&&jQuery.type(n)==="string"){var q=n;if(o&&jQuery.type(o[q])==="function"){return o[q].apply(o,jQuery.makeArray(arguments).slice(1))}}return o}})}());function dropDownSelect(b,c){c=c||((!_.isEmpty(b))?(b[0]):(""));var a=$(['<div class="dropdown-select btn-group">','<button type="button" class="btn btn-default">','<span class="dropdown-select-selected">'+c+"</span>","</button>","</div>"].join("\n"));if(b&&b.length>1){a.find("button").addClass("dropdown-toggle").attr("data-toggle","dropdown").append(' <span class="caret"></span>');a.append(['<ul class="dropdown-menu" role="menu">',_.map(b,function(e){return['<li><a href="javascript:void(0)">',e,"</a></li>"].join("")}).join("\n"),"</ul>"].join("\n"))}function d(g){var h=$(this),f=h.parents(".dropdown-select"),e=h.text();f.find(".dropdown-select-selected").text(e);f.trigger("change.dropdown-select",e)}a.find("a").click(d);return a}(function(){function e(k,j){return this.init(k,j)}e.prototype.DATA_KEY="filter-control";e.prototype.init=function g(k,j){j=j||{filters:[]};this.$element=$(k).addClass("filter-control btn-group");this.options=jQuery.extend(true,{},this.defaults,j);this.currFilter=this.options.filters[0];return this.render()};e.prototype.render=function d(){this.$element.empty().append([this._renderKeySelect(),this._renderOpSelect(),this._renderValueInput()]);return this};e.prototype._renderKeySelect=function a(){var j=this;var k=this.options.filters.map(function(l){return l.key});this.$keySelect=dropDownSelect(k,this.currFilter.key).addClass("filter-control-key").on("change.dropdown-select",function(m,l){j.currFilter=_.findWhere(j.options.filters,{key:l});j.render()._triggerChange()});return this.$keySelect};e.prototype._renderOpSelect=function i(){var j=this,k=this.currFilter.ops;this.$opSelect=dropDownSelect(k,k[0]).addClass("filter-control-op").on("change.dropdown-select",function(m,l){j._triggerChange()});return this.$opSelect};e.prototype._renderValueInput=function c(){var j=this;if(this.currFilter.values){this.$valueSelect=dropDownSelect(this.currFilter.values,this.currFilter.values[0]).on("change.dropdown-select",function(l,k){j._triggerChange()})}else{this.$valueSelect=$("<input/>").addClass("form-control").on("change",function(k,l){j._triggerChange()})}this.$valueSelect.addClass("filter-control-value");return this.$valueSelect};e.prototype.val=function b(){var k=this.$element.find(".filter-control-key .dropdown-select-selected").text(),m=this.$element.find(".filter-control-op .dropdown-select-selected").text(),j=this.$element.find(".filter-control-value"),l=(j.hasClass("dropdown-select"))?(j.find(".dropdown-select-selected").text()):(j.val());return{key:k,op:m,value:l}};e.prototype._triggerChange=function h(){this.$element.trigger("change.filter-control",this.val())};jQuery.fn.extend({filterControl:function f(k){var j=jQuery.makeArray(arguments).slice(1);return this.map(function(){var n=$(this),m=n.data(e.prototype.DATA_KEY);if(jQuery.type(k)==="object"){m=new e(n,k);n.data(e.prototype.DATA_KEY,m)}if(m&&jQuery.type(k)==="string"){var l=m[k];if(jQuery.type(l)==="function"){return l.apply(m,j)}}return this})}})}());(function(){function i(o,n){this.numPages=null;this.currPage=0;return this.init(o,n)}i.prototype.DATA_KEY="pagination";i.prototype.defaults={startingPage:0,perPage:20,totalDataSize:null,currDataSize:null};i.prototype.init=function g(n,o){o=o||{};this.$element=n;this.options=jQuery.extend(true,{},this.defaults,o);this.currPage=this.options.startingPage;if(this.options.totalDataSize!==null){this.numPages=Math.ceil(this.options.totalDataSize/this.options.perPage);if(this.currPage>=this.numPages){this.currPage=this.numPages-1}}this.$element.data(i.prototype.DATA_KEY,this);this._render();return this};function m(n){return $(['<li><a href="javascript:void(0);">',n,"</a></li>"].join(""))}i.prototype._render=function e(){if(this.options.totalDataSize===0){return this}if(this.numPages===1){return this}if(this.numPages>0){this._renderPages();this._scrollToActivePage()}else{this._renderPrevNext()}return this};i.prototype._renderPrevNext=function b(){var o=this,p=m("Prev"),n=m("Next"),q=$("<ul/>").addClass("pagination pagination-prev-next");if(this.currPage===0){p.addClass("disabled")}else{p.click(function(){o.prevPage()})}if((this.numPages&&this.currPage===(this.numPages-1))||(this.options.currDataSize&&this.options.currDataSize<this.options.perPage)){n.addClass("disabled")}else{n.click(function(){o.nextPage()})}this.$element.html(q.append([p,n]));return this.$element};i.prototype._renderPages=function a(){var n=this,q=$("<div>").addClass("pagination-scroll-container"),s=$("<ul/>").addClass("pagination pagination-page-list"),r=function(t){n.goToPage($(this).data("page"))};for(var o=0;o<this.numPages;o+=1){var p=m(o+1).attr("data-page",o).click(r);if(o===this.currPage){p.addClass("active")}s.append(p)}return this.$element.html(q.html(s))};i.prototype._scrollToActivePage=function l(){var p=this.$element.find(".pagination-scroll-container");if(!p.size()){return this}var o=this.$element.find("li.active"),n=p.width()/2;p.scrollLeft(p.scrollLeft()+o.position().left-n);return this};i.prototype.goToPage=function j(n){if(n<=0){n=0}if(this.numPages&&n>=this.numPages){n=this.numPages-1}if(n===this.currPage){return this}this.currPage=n;this.$element.trigger("pagination.page-change",this.currPage);this._render();return this};i.prototype.prevPage=function c(){return this.goToPage(this.currPage-1)};i.prototype.nextPage=function h(){return this.goToPage(this.currPage+1)};i.prototype.page=function f(){return this.currPage};i.create=function k(n,o){return new i(n,o)};jQuery.fn.extend({pagination:function d(o){var n=jQuery.makeArray(arguments).slice(1);if(jQuery.type(o)==="object"){return this.map(function(){i.create($(this),o);return this})}var q=$(this[0]),r=q.data(i.prototype.DATA_KEY);if(r){if(jQuery.type(o)==="string"){var p=r[o];if(jQuery.type(p)==="function"){return p.apply(r,n)}}else{return r}}return undefined}})}());(function(){var g={renameColumns:false,columnNames:[],commentChar:"#",hideCommentRows:false,includePrompts:true,topLeftContent:"Columns:"},s="peek-control.change",t="peek-control.rename",l="peek-control",v="control",f="control-prompt",c="selected",n="disabled",u="button",q="renamable-header",p="column-index",a="column-name";function i(w){if(w.disabled&&jQuery.type(w.disabled)!=="array"){throw new Error('"disabled" must be defined as an array of indeces: '+JSON.stringify(w))}if(w.multiselect&&w.selected&&jQuery.type(w.selected)!=="array"){throw new Error('Mulitselect rows need an array for "selected": '+JSON.stringify(w))}if(!w.label||!w.id){throw new Error("Peek controls need a label and id for each control row: "+JSON.stringify(w))}if(w.disabled&&w.disabled.indexOf(w.selected)!==-1){throw new Error("Selected column is in the list of disabled columns: "+JSON.stringify(w))}return w}function o(x,w){return $("<div/>").addClass(u).text(x.label)}function k(x,w){var y=$("<td/>").html(o(x,w)).attr("data-"+p,w);if(x.disabled&&x.disabled.indexOf(w)!==-1){y.addClass(n)}return y}function e(y,z,w){var x=y.children("."+u);if(y.hasClass(c)){x.html((z.selectedText!==undefined)?(z.selectedText):(z.label))}else{x.html((z.unselectedText!==undefined)?(z.unselectedText):(z.label))}}function h(z,x){var y=k(z,x);if(z.selected===x){y.addClass(c)}e(y,z,x);if(!y.hasClass(n)){y.click(function w(D){var E=$(this);if(!E.hasClass(c)){var A=E.parent().children("."+c).removeClass(c);A.each(function(){e($(this),z,x)});E.addClass(c);e(E,z,x);var C={},B=E.parent().attr("id"),F=E.data(p);C[B]=F;E.parents(".peek").trigger(s,C)}})}return y}function m(z,x){var y=k(z,x);if(z.selected&&z.selected.indexOf(x)!==-1){y.addClass(c)}e(y,z,x);if(!y.hasClass(n)){y.click(function w(D){var E=$(this);E.toggleClass(c);e(E,z,x);var C=E.parent().find("."+c).map(function(G,H){return $(H).data(p)});var B={},A=E.parent().attr("id"),F=jQuery.makeArray(C);B[A]=F;E.parents(".peek").trigger(s,B)})}return y}function j(y,z){var w=[];for(var x=0;x<y;x+=1){w.push(z.multiselect?m(z,x):h(z,x))}return w}function r(y,z,x){var A=$("<tr/>").attr("id",z.id).addClass(v);if(x){var w=$("<td/>").addClass(f).text(z.label+":");A.append(w)}A.append(j(y,z));return A}function b(E){E=jQuery.extend(true,{},g,E);var D=$(this).addClass(l),A=D.find("table"),z=A.find("th").size(),C=A.find("tr").size(),w=A.find("td[colspan]").map(function(H,F){var G=$(this);if(G.text()&&G.text().match(new RegExp("^"+E.commentChar))){return $(this).css("color","grey").parent().get(0)}return null});if(E.hideCommentRows){w.hide();C-=w.size()}if(E.includePrompts){var y=$("<th/>").addClass("top-left").text(E.topLeftContent).attr("rowspan",C);A.find("tr").first().prepend(y)}var B=A.find("th:not(.top-left)").each(function(G,I){var H=$(this),J=H.text().replace(/^\d+\.*/,""),F=E.columnNames[G]||J;H.attr("data-"+a,F).text((G+1)+((F)?("."+F):("")))});if(E.renameColumns){B.addClass(q).click(function x(){var G=$(this),F=G.index()+(E.includePrompts?0:1),I=G.data(a),H=prompt("New column name:",I);if(H!==null&&H!==I){G.text(F+(H?("."+H):"")).data(a,H).attr("data-",a,H);var J=jQuery.makeArray(G.parent().children("th:not(.top-left)").map(function(){return $(this).data(a)}));G.parents(".peek").trigger(t,J)}})}E.controls.forEach(function(G,F){i(G);var H=r(z,G,E.includePrompts);A.find("tbody").append(H)});return this}jQuery.fn.extend({peekControl:function d(w){return this.map(function(){return b.call(this,w)})}})}());
\ No newline at end of file
diff -r c85f8fb5d63e667b63e10cdce518254f56002f55 -r 7ebec9da47844efbf37942faab3809cb0169e5c2 templates/webapps/galaxy/history/original_view.mako
--- a/templates/webapps/galaxy/history/original_view.mako
+++ /dev/null
@@ -1,173 +0,0 @@
-<%namespace file="/display_common.mako" import="get_history_link, get_controller_name" />
-<%namespace file="/root/history_common.mako" import="render_dataset" />
-<%namespace file="/tagging_common.mako" import="render_individual_tagging_element, render_community_tagging_element" />
-
-<%!
- def inherit(context):
- if context.get('use_panels'):
- return '/webapps/galaxy/base_panels.mako'
- else:
- return '/base.mako'
-%>
-<%inherit file="${inherit(context)}"/>
-
-<%def name="javascripts()">
- ${parent.javascripts()}
- ${h.js( "libs/jquery/jstorage" )}
- <script type="text/javascript">
- $(function() {
- init_history_items( $("div.historyItemWrapper"), false, "nochanges" );
- $( '#switch-to-link' ).click( function( event ){
- var galaxy = window.Galaxy || window.parent.Galaxy;
- if( galaxy ){
- galaxy.currHistoryPanel.switchToHistory( '${ trans.security.encode_id( history.id ) }' );
- }
- });
- $( '#refresh' ).click( function( event ){ window.location.reload( true ); })
- });
- </script>
-</%def>
-
-<%def name="stylesheets()">
- ${parent.stylesheets()}
- ${h.css( "history", "autocomplete_tagging" )}
-
- <style type="text/css">
-
- /* these don't appear to be used? */
- .page-body
- {
- padding: 10px;
- float: left;
- width: 65%;
- }
- .page-meta
- {
- float: right;
- width: 27%;
- padding: 0.5em;
- margin: 0.25em;
- vertical-align: text-top;
- border: 2px solid #DDDDDD;
- border-top: 4px solid #DDDDDD;
- }
-
-
- body {
- padding: 0px;
- margin: 0px;
- }
-
- div.unified-panel-body {
- position: absolute;
- top: 0px;
- width: 100%;
- }
-
- #history-name-area {
- margin: 12px 0px 0px 16px;
- font-size: 120%;
- }
- #top-links {
- margin: 4px 0px 8px 16px;
- }
-
- .historyItemContainer {
- /*padding-right: 3px;*/
- }
- .historyItemBody {
- display: none;
- }
- div.historyItemWrapper {
- margin: 0px 4px 0px 4px ;
- border-left: 1px solid #999999;
- border-right: 1px solid #999999;
- }
- /* TODO: unify with other history css and into .less */
- </style>
-
- <noscript>
- <style>
- .historyItemBody {
- display: block;
- }
- </style>
- </noscript>
-</%def>
-
-<%def name="init()">
-<%
- self.has_left_panel=False
- self.has_right_panel=False
- self.message_box_visible=False
-%>
-</%def>
-
-<%def name="body()">
- ${center_panel()}
-</%def>
-
-<%def name="center_panel()">
- ## Get URL to other histories owned by user that owns this history.
- <%
- ##TODO: is there a better way to create this URL? Can't use 'f-username' as a key b/c it's not a valid identifier.
- href_to_published_histories = h.url_for( controller='/history', action='list_published')
- if history.user is not None:
- href_to_user_histories = h.url_for( controller='/history', action='list_published', xxx=history.user.username).replace( 'xxx', 'f-username')
- else:
- href_to_user_histories = h.url_for( controller='/history', action='list_published' )##should this instead be be None or empty string?
- %>
-
- <div class="unified-panel-body">
- <div style="overflow: auto; height: 100%;">
- ## Render view of history.
- <div id="history-name-area" class="historyLinks" style="color: gray; font-weight: bold; padding: 0px 0px 5px 0px">
- <div id="history-name">${history.get_display_name()}</div>
- </div>
-
- <div id="top-links" class="historyLinks" style="padding: 0px 0px 5px 0px">
- %if not history.purged and history.user != trans.user:
- ##TODO: need to remove _top
- <a href="${h.url_for(controller='history', action='imp', id=trans.security.encode_id(history.id) )}"
- >import and start using history</a> |
- <a id="refresh" href="javascript:void(0)" >${_('refresh')}</a> |
- %endif
- %if not history.purged and history.user == trans.user:
- <a id="switch-to-link" href="javascript:void(0)">${_('switch to this history')}</a> |
- <a id="refresh" href="javascript:void(0)" >${_('refresh')}</a> |
- %endif
- %if show_deleted:
- <a href="${h.url_for(controller='history', action='view', id=trans.security.encode_id(history.id), show_deleted=False, use_panels=use_panels )}">${_('hide deleted')}</a> |
- %else:
- <a href="${h.url_for(controller='history', action='view', id=trans.security.encode_id(history.id), show_deleted=True, use_panels=use_panels )}">${_('show deleted')}</a> |
- %endif
- <a href="#" class="toggle">collapse all</a>
- </div>
-
- %if history.deleted:
- <div class="warningmessagesmall">
- ${_('You are currently viewing a deleted history!')}
- </div>
- <p></p>
- %endif
-
- %if not datasets:
- <div class="infomessagesmall" id="emptyHistoryMessage">
-
- %else:
- ## Render requested datasets, ordered from newest to oldest
- %for data in datasets:
- %if data.visible:
- <div class="historyItemContainer visible-right-border" id="historyItemContainer-${data.id}">
- ${render_dataset( data, data.hid, show_deleted_on_refresh = show_deleted, for_editing=False )}
- </div>
- %endif
- %endfor
-
- <div class="infomessagesmall" id="emptyHistoryMessage" style="display:none;">
- %endif
- ${_("Your history is empty. Click 'Get Data' on the left pane to start")}
- </div>
- </div>
- </div>
-</%def>
diff -r c85f8fb5d63e667b63e10cdce518254f56002f55 -r 7ebec9da47844efbf37942faab3809cb0169e5c2 templates/webapps/galaxy/history/view.mako
--- a/templates/webapps/galaxy/history/view.mako
+++ b/templates/webapps/galaxy/history/view.mako
@@ -77,6 +77,7 @@
%endif
<script type="text/javascript">
+ ##TODO: remove when Galaxy is either ensured or removed from the history panel
var using_panels = ${ 'false' if not use_panels else 'true' };
%if not use_panels:
window.Galaxy = {};
@@ -87,113 +88,107 @@
## ----------------------------------------------------------------------------
<%def name="center_panel()">
+<%
+ show_deleted = context.get( 'show_deleted', None )
+ show_hidden = context.get( 'show_hidden', None )
+
+ user_is_owner_json = 'true' if user_is_owner else 'false'
+ show_deleted_json = h.to_json_string( show_deleted )
+ show_hidden_json = h.to_json_string( show_hidden )
+
+ imp_with_deleted_url = h.url_for( controller='history', action='imp', id=history['id'], all_datasets=True )
+ imp_without_deleted_url = h.url_for( controller='history', action='imp', id=history['id'] )
+%>
+
<div id="header" class="clear"><div id="history-view-controls" class="pull-right">
- <%
- show_deleted = context.get( 'show_deleted', None )
- show_hidden = context.get( 'show_hidden', None )
-
- show_deleted_js = 'true' if show_deleted == True else ( 'null' if show_deleted == None else 'false' )
- show_hidden_js = 'true' if show_hidden == True else ( 'null' if show_hidden == None else 'false' )
- print 'user_is_owner:', user_is_owner
- %>
%if not user_is_owner and not history[ 'purged' ]:
- <a id="import" class="btn btn-default" style="display: none;"
- href="${h.url_for( controller='history', action='imp', id=history['id'], all_datasets=show_deleted )}">
- ${_('Import and start using history')}
- </a>
+ <button id="import" class="btn btn-default"></button>
%endif
- <button id="toggle-deleted" class="btn btn-default">
- ${_('Exclude deleted') if show_deleted else _('Include deleted')}
- </button>
- <button id="toggle-hidden" class="btn btn-default">
- ${_('Exclude hidden') if show_hidden else _('Include hidden')}
- </button>
+ <button id="toggle-deleted" class="btn btn-default"></button>
+ <button id="toggle-hidden" class="btn btn-default"></button></div></div><div id="history-${ history[ 'id' ] }" class="history-panel unified-panel-body" style="overflow: auto;"></div><script type="text/javascript">
+ $(function(){
+ $( '#toggle-deleted' ).modeButton({
+ initialMode : "${ 'showing_deleted' if show_deleted else 'not_showing_deleted' }",
+ modes: [
+ { mode: 'showing_deleted', html: _l( 'Exclude deleted' ) },
+ { mode: 'not_showing_deleted', html: _l( 'Include deleted' ) }
+ ]
+ }).click( function(){
+ // allow the 'include/exclude deleted' button to control whether the 'import' button includes deleted
+ // datasets when importing or not; when deleted datasets are shown, they'll be imported
+ $( '#import' ).modeButton( 'setMode',
+ $( this ).modeButton( 'current' ) === 'showing_deleted'? 'with_deleted': 'without_deleted' )
+ });
+
+ $( '#toggle-hidden' ).modeButton({
+ initialMode : "${ 'showing_hidden' if show_hidden else 'not_showing_hidden' }",
+ modes: [
+ { mode: 'showing_hidden', html: _l( 'Exclude hidden' ) },
+ { mode: 'not_showing_hidden', html: _l( 'Include hidden' ) }
+ ]
+ });
+
+ $( '#import' ).modeButton({
+ switchModesOnClick : false,
+ initialMode : "${ 'with_deleted' if show_deleted else 'without_deleted' }",
+ modes: [
+ { mode: 'with_deleted', html: _l( 'Import with deleted datasets and start using history' ),
+ onclick: function importWithDeleted(){
+ window.location = '${imp_with_deleted_url}';
+ }
+ },
+ { mode: 'without_deleted', html: _l( 'Import and start using history' ),
+ onclick: function importWithoutDeleted(){
+ window.location = '${imp_without_deleted_url}';
+ }
+ },
+ ]
+ });
+ });
+
var debugging = JSON.parse( sessionStorage.getItem( 'debugging' ) ) || false,
userIsOwner = ${'true' if user_is_owner else 'false'},
historyJSON = ${h.to_json_string( history )},
hdaJSON = ${h.to_json_string( hdas )};
- window.hdaJSON = hdaJSON;
-
- $( '#toggle-deleted' ).modeButton({
- initialMode : (${ show_deleted_js })?( 'exclude' ):( 'include' ),
- modes: [
- { mode: 'exclude', html: _l( 'Exclude deleted' ) },
- { mode: 'include', html: _l( 'Include deleted' ) }
- ]
- }).click( function(){
- // allow the 'include/exclude deleted' button to control whether the 'import' button includes deleted datasets
- // when importing or not; when deleted datasets are shown, they'll be imported
- var $importBtn = $( '#import' );
- if( $importBtn.size() ){
- // a bit hacky
- var href = $importBtn.attr( 'href' ),
- includeDeleted = $( this ).modeButton()[0].getMode().mode === 'exclude';
- href = href.replace( /all_datasets=True|False/, ( includeDeleted )?( 'True' ):( 'False' ) );
- $importBtn.attr( 'href', href );
- $importBtn.text( includeDeleted ? _l( 'Import with deleted datasets and start using history' )
- : _l( 'Import and start using history' ) );
- }
- });
-
- $( '#toggle-hidden' ).modeButton({
- initialMode : (${ show_hidden_js })?( 'exclude' ):( 'include' ),
- modes: [
- { mode: 'exclude', html: _l( 'Exclude hidden' ) },
- { mode: 'include', html: _l( 'Include hidden' ) }
- ]
- });
-
- ##TODO: move to mako
- if( Galaxy.currUser.id !== historyJSON.user_id ){
- $( '#import' ).show();
- }
+ panelToUse = ( userIsOwner )?
+ ({ location: 'mvc/history/history-panel', className: 'HistoryPanel' }):
+ ({ location: 'mvc/history/readonly-history-panel', className: 'ReadOnlyHistoryPanel' });
require.config({
baseUrl : "${h.url_for( '/static/scripts' )}"
- })([
- %if user_is_owner:
- 'mvc/history/history-panel'
- %else:
- 'mvc/history/readonly-history-panel'
- %endif
- ${ }
- ], function( panelMod ){
- //require([ "mvc/history/history-panel" ], function( historyPanel ){
- // history module is already in the dpn chain from the panel. We can re-scope it here.
- var historyModel = require( 'mvc/history/history-model' ),
- hdaBaseView = require( 'mvc/dataset/hda-base' ),
- history = new historyModel.History( historyJSON, hdaJSON, {
- logger: ( debugging )?( console ):( null )
+ })([ panelToUse.location ], function( panelMod ){
+ $(function(){
+ var panelClass = panelMod[ panelToUse.className ],
+ // history module is already in the dpn chain from the panel. We can re-scope it here.
+ historyModel = require( 'mvc/history/history-model' ),
+ hdaBaseView = require( 'mvc/dataset/hda-base' ),
+ history = new historyModel.History( historyJSON, hdaJSON, {
+ logger: ( debugging )?( console ):( null )
+ });
+
+ window.historyPanel = new panelClass({
+ show_deleted : ${show_deleted_json},
+ show_hidden : ${show_hidden_json},
+ el : $( "#history-" + historyJSON.id ),
+ model : history,
+ onready : function(){
+ var panel = this;
+ $( '#toggle-deleted' ).on( 'click', function(){
+ panel.toggleShowDeleted();
+ });
+ $( '#toggle-hidden' ).on( 'click', function(){
+ panel.toggleShowHidden();
+ });
+ this.render();
+ }
});
-
- window.panelMod = panelMod;
- %if user_is_owner:
- window.panelClass = panelMod.HistoryPanel;
- %else:
- window.panelClass = panelMod.ReadOnlyHistoryPanel;
- %endif
- window.historyPanel = new panelClass({
- show_deleted : ${show_deleted_js},
- show_hidden : ${show_hidden_js},
- el : $( "#history-" + historyJSON.id ),
- model : history,
- onready : function(){
- var panel = this;
- $( '#toggle-deleted' ).on( 'click', function(){
- panel.toggleShowDeleted();
- });
- $( '#toggle-hidden' ).on( 'click', function(){
- panel.toggleShowHidden();
- });
- this.render();
- }
});
});
</script>
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: carlfeberhard: Fix TypeDef error in history panel by adding sanity check for tags/annotations being open (Thanks, Aysam)
by commits-noreply@bitbucket.org 18 Feb '14
by commits-noreply@bitbucket.org 18 Feb '14
18 Feb '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/c85f8fb5d63e/
Changeset: c85f8fb5d63e
User: carlfeberhard
Date: 2014-02-18 22:40:23
Summary: Fix TypeDef error in history panel by adding sanity check for tags/annotations being open (Thanks, Aysam)
Affected #: 2 files
diff -r 82d6ee82d5d4714eefdbce041f6c983a806a58d7 -r c85f8fb5d63e667b63e10cdce518254f56002f55 static/scripts/mvc/history/history-panel.js
--- a/static/scripts/mvc/history/history-panel.js
+++ b/static/scripts/mvc/history/history-panel.js
@@ -44,6 +44,11 @@
/** selected hda ids */
this.selectedHdaIds = [];
+ /** editor for tags - sub-view */
+ this.tagsEditor = null;
+ /** editor for annotations - sub-view */
+ this.annotationEditor = null;
+
// states/modes the panel can be in
/** is the panel currently showing the dataset selection controls? */
this.selecting = attributes.selecting || false;
@@ -250,8 +255,8 @@
selectable : this.selecting,
hasUser : this.model.ownedByCurrUser(),
logger : this.logger,
- tagsEditorShown : !this.tagsEditor.isHidden(),
- annotationEditorShown : !this.annotationEditor.isHidden()
+ tagsEditorShown : ( this.tagsEditor && !this.tagsEditor.isHidden() ),
+ annotationEditorShown : ( this.annotationEditor && !this.annotationEditor.isHidden() )
});
this._setUpHdaListeners( hdaView );
return hdaView;
diff -r 82d6ee82d5d4714eefdbce041f6c983a806a58d7 -r c85f8fb5d63e667b63e10cdce518254f56002f55 static/scripts/packed/mvc/history/history-panel.js
--- a/static/scripts/packed/mvc/history/history-panel.js
+++ b/static/scripts/packed/mvc/history/history-panel.js
@@ -1,1 +1,1 @@
-define(["mvc/dataset/hda-model","mvc/dataset/hda-edit","mvc/history/readonly-history-panel"],function(c,a,b){var d=b.ReadOnlyHistoryPanel.extend({HDAViewClass:a.HDAEditView,initialize:function(e){e=e||{};this.selectedHdaIds=[];this.selecting=e.selecting||false;this.annotationEditorShown=e.annotationEditorShown||false;this.tagsEditorShown=e.tagsEditorShown||false;b.ReadOnlyHistoryPanel.prototype.initialize.call(this,e)},_setUpModelEventHandlers:function(){b.ReadOnlyHistoryPanel.prototype._setUpModelEventHandlers.call(this);this.model.on("change:nice_size",this.updateHistoryDiskSize,this);this.model.hdas.on("change:deleted",this.handleHdaDeletionChange,this);this.model.hdas.on("change:visible",this.handleHdaVisibleChange,this);this.model.hdas.on("change:purged",function(e){this.model.fetch()},this)},renderModel:function(){var e=$("<div/>");e.append(d.templates.historyPanel(this.model.toJSON()));if(Galaxy.currUser.id&&Galaxy.currUser.id===this.model.get("user_id")){this._renderTags(e);this._renderAnnotation(e)}e.find(".history-secondary-actions").prepend(this._renderSelectButton());e.find(".history-dataset-actions").toggle(this.selecting);e.find(".history-secondary-actions").prepend(this._renderSearchButton());this._setUpBehaviours(e);this.renderHdas(e);return e},_renderTags:function(e){var f=this;this.tagsEditor=new TagsEditor({model:this.model,el:e.find(".history-controls .tags-display"),onshowFirstTime:function(){this.render()},onshow:function(){f.toggleHDATagEditors(true,f.fxSpeed)},onhide:function(){f.toggleHDATagEditors(false,f.fxSpeed)},$activator:faIconButton({title:_l("Edit history tags"),classes:"history-tag-btn",faIcon:"fa-tags"}).appendTo(e.find(".history-secondary-actions"))})},_renderAnnotation:function(e){var f=this;this.annotationEditor=new AnnotationEditor({model:this.model,el:e.find(".history-controls .annotation-display"),onshowFirstTime:function(){this.render()},onshow:function(){f.toggleHDAAnnotationEditors(true,f.fxSpeed)},onhide:function(){f.toggleHDAAnnotationEditors(false,f.fxSpeed)},$activator:faIconButton({title:_l("Edit history Annotation"),classes:"history-annotate-btn",faIcon:"fa-comment"}).appendTo(e.find(".history-secondary-actions"))})},_renderSelectButton:function(e){return faIconButton({title:_l("Operations on multiple datasets"),classes:"history-select-btn",faIcon:"fa-check-square-o"})},_setUpBehaviours:function(e){e=e||this.$el;e.find("[title]").tooltip({placement:"bottom"});if(!this.model){return}this._setUpDatasetActionsPopup(e);if((!Galaxy.currUser||Galaxy.currUser.isAnonymous())||(Galaxy.currUser.id!==this.model.get("user_id"))){return}var f=this;e.find(".history-name").attr("title",_l("Click to rename history")).tooltip({placement:"bottom"}).make_text_editable({on_finish:function(g){var h=f.model.get("name");if(g&&g!==h){f.$el.find(".history-name").text(g);f.model.save({name:g}).fail(function(){f.$el.find(".history-name").text(f.model.previous("name"))})}else{f.$el.find(".history-name").text(h)}}})},_setUpDatasetActionsPopup:function(e){var f=this;(new PopupMenu(e.find(".history-dataset-action-popup-btn"),[{html:_l("Hide datasets"),func:function(){var g=c.HistoryDatasetAssociation.prototype.hide;f.getSelectedHdaCollection().ajaxQueue(g)}},{html:_l("Unhide datasets"),func:function(){var g=c.HistoryDatasetAssociation.prototype.unhide;f.getSelectedHdaCollection().ajaxQueue(g)}},{html:_l("Delete datasets"),func:function(){var g=c.HistoryDatasetAssociation.prototype["delete"];f.getSelectedHdaCollection().ajaxQueue(g)}},{html:_l("Undelete datasets"),func:function(){var g=c.HistoryDatasetAssociation.prototype.undelete;f.getSelectedHdaCollection().ajaxQueue(g)}},{html:_l("Permanently delete datasets"),func:function(){if(confirm(_l("This will permanently remove the data in your datasets. Are you sure?"))){var g=c.HistoryDatasetAssociation.prototype.purge;f.getSelectedHdaCollection().ajaxQueue(g)}}}]))},handleHdaDeletionChange:function(e){if(e.get("deleted")&&!this.storage.get("show_deleted")){this.removeHdaView(this.hdaViews[e.id])}},handleHdaVisibleChange:function(e){if(e.hidden()&&!this.storage.get("show_hidden")){this.removeHdaView(this.hdaViews[e.id])}},createHdaView:function(f){var e=f.get("id"),g=new this.HDAViewClass({model:f,linkTarget:this.linkTarget,expanded:this.storage.get("expandedHdas")[e],selectable:this.selecting,hasUser:this.model.ownedByCurrUser(),logger:this.logger,tagsEditorShown:!this.tagsEditor.isHidden(),annotationEditorShown:!this.annotationEditor.isHidden()});this._setUpHdaListeners(g);return g},_setUpHdaListeners:function(f){var e=this;b.ReadOnlyHistoryPanel.prototype._setUpHdaListeners.call(this,f);f.on("selected",function(g){var h=g.model.get("id");e.selectedHdaIds=_.union(e.selectedHdaIds,[h])});f.on("de-selected",function(g){var h=g.model.get("id");e.selectedHdaIds=_.without(e.selectedHdaIds,h)})},toggleHDATagEditors:function(e){var f=arguments;_.each(this.hdaViews,function(g){if(g.tagsEditor){g.tagsEditor.toggle.apply(g.tagsEditor,f)}})},toggleHDAAnnotationEditors:function(e){var f=arguments;_.each(this.hdaViews,function(g){if(g.annotationEditor){g.annotationEditor.toggle.apply(g.annotationEditor,f)}})},removeHdaView:function(f){if(!f){return}var e=this;f.$el.fadeOut(e.fxSpeed,function(){f.off();f.remove();delete e.hdaViews[f.model.id];if(_.isEmpty(e.hdaViews)){e.$el.find(e.emptyMsgSelector).fadeIn(e.fxSpeed,function(){e.trigger("empty-history",e)})}})},events:_.extend(_.clone(b.ReadOnlyHistoryPanel.prototype.events),{"click .history-select-btn":function(f){this.toggleSelectors(this.fxSpeed)},"click .history-select-all-datasets-btn":"selectAllDatasets","click .history-deselect-all-datasets-btn":"deselectAllDatasets"}),updateHistoryDiskSize:function(){this.$el.find(".history-size").text(this.model.get("nice_size"))},showSelectors:function(e){this.selecting=true;this.$el.find(".history-dataset-actions").slideDown(e);_.each(this.hdaViews,function(f){f.showSelector(e)});this.selectedHdaIds=[]},hideSelectors:function(e){this.selecting=false;this.$el.find(".history-dataset-actions").slideUp(e);_.each(this.hdaViews,function(f){f.hideSelector(e)});this.selectedHdaIds=[]},toggleSelectors:function(e){if(!this.selecting){this.showSelectors(e)}else{this.hideSelectors(e)}},selectAllDatasets:function(e){_.each(this.hdaViews,function(f){f.select(e)})},deselectAllDatasets:function(e){_.each(this.hdaViews,function(f){f.deselect(e)})},getSelectedHdaViews:function(){return _.filter(this.hdaViews,function(e){return e.selected})},getSelectedHdaCollection:function(){return new c.HDACollection(_.map(this.getSelectedHdaViews(),function(e){return e.model}),{historyId:this.model.id})},toString:function(){return"HistoryPanel("+((this.model)?(this.model.get("name")):(""))+")"}});d.templates={historyPanel:Handlebars.templates["template-history-historyPanel"],anonHistoryPanel:Handlebars.templates["template-history-historyPanel-anon"]};return{HistoryPanel:d}});
\ No newline at end of file
+define(["mvc/dataset/hda-model","mvc/dataset/hda-edit","mvc/history/readonly-history-panel"],function(c,a,b){var d=b.ReadOnlyHistoryPanel.extend({HDAViewClass:a.HDAEditView,initialize:function(e){e=e||{};this.selectedHdaIds=[];this.tagsEditor=null;this.annotationEditor=null;this.selecting=e.selecting||false;this.annotationEditorShown=e.annotationEditorShown||false;this.tagsEditorShown=e.tagsEditorShown||false;b.ReadOnlyHistoryPanel.prototype.initialize.call(this,e)},_setUpModelEventHandlers:function(){b.ReadOnlyHistoryPanel.prototype._setUpModelEventHandlers.call(this);this.model.on("change:nice_size",this.updateHistoryDiskSize,this);this.model.hdas.on("change:deleted",this.handleHdaDeletionChange,this);this.model.hdas.on("change:visible",this.handleHdaVisibleChange,this);this.model.hdas.on("change:purged",function(e){this.model.fetch()},this)},renderModel:function(){var e=$("<div/>");e.append(d.templates.historyPanel(this.model.toJSON()));if(Galaxy.currUser.id&&Galaxy.currUser.id===this.model.get("user_id")){this._renderTags(e);this._renderAnnotation(e)}e.find(".history-secondary-actions").prepend(this._renderSelectButton());e.find(".history-dataset-actions").toggle(this.selecting);e.find(".history-secondary-actions").prepend(this._renderSearchButton());this._setUpBehaviours(e);this.renderHdas(e);return e},_renderTags:function(e){var f=this;this.tagsEditor=new TagsEditor({model:this.model,el:e.find(".history-controls .tags-display"),onshowFirstTime:function(){this.render()},onshow:function(){f.toggleHDATagEditors(true,f.fxSpeed)},onhide:function(){f.toggleHDATagEditors(false,f.fxSpeed)},$activator:faIconButton({title:_l("Edit history tags"),classes:"history-tag-btn",faIcon:"fa-tags"}).appendTo(e.find(".history-secondary-actions"))})},_renderAnnotation:function(e){var f=this;this.annotationEditor=new AnnotationEditor({model:this.model,el:e.find(".history-controls .annotation-display"),onshowFirstTime:function(){this.render()},onshow:function(){f.toggleHDAAnnotationEditors(true,f.fxSpeed)},onhide:function(){f.toggleHDAAnnotationEditors(false,f.fxSpeed)},$activator:faIconButton({title:_l("Edit history Annotation"),classes:"history-annotate-btn",faIcon:"fa-comment"}).appendTo(e.find(".history-secondary-actions"))})},_renderSelectButton:function(e){return faIconButton({title:_l("Operations on multiple datasets"),classes:"history-select-btn",faIcon:"fa-check-square-o"})},_setUpBehaviours:function(e){e=e||this.$el;e.find("[title]").tooltip({placement:"bottom"});if(!this.model){return}this._setUpDatasetActionsPopup(e);if((!Galaxy.currUser||Galaxy.currUser.isAnonymous())||(Galaxy.currUser.id!==this.model.get("user_id"))){return}var f=this;e.find(".history-name").attr("title",_l("Click to rename history")).tooltip({placement:"bottom"}).make_text_editable({on_finish:function(g){var h=f.model.get("name");if(g&&g!==h){f.$el.find(".history-name").text(g);f.model.save({name:g}).fail(function(){f.$el.find(".history-name").text(f.model.previous("name"))})}else{f.$el.find(".history-name").text(h)}}})},_setUpDatasetActionsPopup:function(e){var f=this;(new PopupMenu(e.find(".history-dataset-action-popup-btn"),[{html:_l("Hide datasets"),func:function(){var g=c.HistoryDatasetAssociation.prototype.hide;f.getSelectedHdaCollection().ajaxQueue(g)}},{html:_l("Unhide datasets"),func:function(){var g=c.HistoryDatasetAssociation.prototype.unhide;f.getSelectedHdaCollection().ajaxQueue(g)}},{html:_l("Delete datasets"),func:function(){var g=c.HistoryDatasetAssociation.prototype["delete"];f.getSelectedHdaCollection().ajaxQueue(g)}},{html:_l("Undelete datasets"),func:function(){var g=c.HistoryDatasetAssociation.prototype.undelete;f.getSelectedHdaCollection().ajaxQueue(g)}},{html:_l("Permanently delete datasets"),func:function(){if(confirm(_l("This will permanently remove the data in your datasets. Are you sure?"))){var g=c.HistoryDatasetAssociation.prototype.purge;f.getSelectedHdaCollection().ajaxQueue(g)}}}]))},handleHdaDeletionChange:function(e){if(e.get("deleted")&&!this.storage.get("show_deleted")){this.removeHdaView(this.hdaViews[e.id])}},handleHdaVisibleChange:function(e){if(e.hidden()&&!this.storage.get("show_hidden")){this.removeHdaView(this.hdaViews[e.id])}},createHdaView:function(f){var e=f.get("id"),g=new this.HDAViewClass({model:f,linkTarget:this.linkTarget,expanded:this.storage.get("expandedHdas")[e],selectable:this.selecting,hasUser:this.model.ownedByCurrUser(),logger:this.logger,tagsEditorShown:(this.tagsEditor&&!this.tagsEditor.isHidden()),annotationEditorShown:(this.annotationEditor&&!this.annotationEditor.isHidden())});this._setUpHdaListeners(g);return g},_setUpHdaListeners:function(f){var e=this;b.ReadOnlyHistoryPanel.prototype._setUpHdaListeners.call(this,f);f.on("selected",function(g){var h=g.model.get("id");e.selectedHdaIds=_.union(e.selectedHdaIds,[h])});f.on("de-selected",function(g){var h=g.model.get("id");e.selectedHdaIds=_.without(e.selectedHdaIds,h)})},toggleHDATagEditors:function(e){var f=arguments;_.each(this.hdaViews,function(g){if(g.tagsEditor){g.tagsEditor.toggle.apply(g.tagsEditor,f)}})},toggleHDAAnnotationEditors:function(e){var f=arguments;_.each(this.hdaViews,function(g){if(g.annotationEditor){g.annotationEditor.toggle.apply(g.annotationEditor,f)}})},removeHdaView:function(f){if(!f){return}var e=this;f.$el.fadeOut(e.fxSpeed,function(){f.off();f.remove();delete e.hdaViews[f.model.id];if(_.isEmpty(e.hdaViews)){e.$el.find(e.emptyMsgSelector).fadeIn(e.fxSpeed,function(){e.trigger("empty-history",e)})}})},events:_.extend(_.clone(b.ReadOnlyHistoryPanel.prototype.events),{"click .history-select-btn":function(f){this.toggleSelectors(this.fxSpeed)},"click .history-select-all-datasets-btn":"selectAllDatasets","click .history-deselect-all-datasets-btn":"deselectAllDatasets"}),updateHistoryDiskSize:function(){this.$el.find(".history-size").text(this.model.get("nice_size"))},showSelectors:function(e){this.selecting=true;this.$el.find(".history-dataset-actions").slideDown(e);_.each(this.hdaViews,function(f){f.showSelector(e)});this.selectedHdaIds=[]},hideSelectors:function(e){this.selecting=false;this.$el.find(".history-dataset-actions").slideUp(e);_.each(this.hdaViews,function(f){f.hideSelector(e)});this.selectedHdaIds=[]},toggleSelectors:function(e){if(!this.selecting){this.showSelectors(e)}else{this.hideSelectors(e)}},selectAllDatasets:function(e){_.each(this.hdaViews,function(f){f.select(e)})},deselectAllDatasets:function(e){_.each(this.hdaViews,function(f){f.deselect(e)})},getSelectedHdaViews:function(){return _.filter(this.hdaViews,function(e){return e.selected})},getSelectedHdaCollection:function(){return new c.HDACollection(_.map(this.getSelectedHdaViews(),function(e){return e.model}),{historyId:this.model.id})},toString:function(){return"HistoryPanel("+((this.model)?(this.model.get("name")):(""))+")"}});d.templates={historyPanel:Handlebars.templates["template-history-historyPanel"],anonHistoryPanel:Handlebars.templates["template-history-historyPanel-anon"]};return{HistoryPanel:d}});
\ No newline at end of file
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/33812bcdc523/
Changeset: 33812bcdc523
User: carlfeberhard
Date: 2014-02-18 21:11:48
Summary: History panel: begin process of breaking up panel into more focused prototypes
Affected #: 11 files
diff -r 26e37f6af3a8a090d9d6e923fa3e90acb0e64572 -r 33812bcdc52393bf179dd501b4334be4ec4e97a7 lib/galaxy/webapps/galaxy/controllers/history.py
--- a/lib/galaxy/webapps/galaxy/controllers/history.py
+++ b/lib/galaxy/webapps/galaxy/controllers/history.py
@@ -887,10 +887,13 @@
history_dictionary = {}
hda_dictionaries = []
+ user_is_owner = False
try:
history_to_view = self.get_history( trans, id, False )
if not history_to_view:
return trans.show_error_message( "The specified history does not exist." )
+ if history_to_view.user == trans.user:
+ user_is_owner = True
# Admin users can view any history
if( ( history_to_view.user != trans.user )
@@ -925,7 +928,7 @@
+ 'Please contact a Galaxy administrator if the problem persists.' )
return trans.fill_template_mako( "history/view.mako",
- history=history_dictionary, hdas=hda_dictionaries,
+ history=history_dictionary, hdas=hda_dictionaries, user_is_owner=user_is_owner,
show_deleted=show_deleted, show_hidden=show_hidden, use_panels=use_panels )
@web.expose
@@ -941,9 +944,8 @@
# Security check raises error if user cannot access history.
self.security_check( trans, history, False, True)
- # Get datasets.
+ # Get datasets and annotations
datasets = self.get_history_datasets( trans, history )
- # Get annotations.
history.annotation = self.get_item_annotation_str( trans.sa_session, history.user, history )
for dataset in datasets:
dataset.annotation = self.get_item_annotation_str( trans.sa_session, history.user, dataset )
@@ -957,8 +959,9 @@
else:
user_item_rating = 0
ave_item_rating, num_ratings = self.get_ave_item_rating_data( trans.sa_session, history )
- return trans.stream_template_mako( "history/display.mako", item = history, item_data = datasets,
- user_item_rating = user_item_rating, ave_item_rating=ave_item_rating, num_ratings=num_ratings )
+
+ return trans.stream_template_mako( "history/display.mako", item=history, item_data=datasets,
+ user_item_rating = user_item_rating, ave_item_rating=ave_item_rating, num_ratings=num_ratings )
@web.expose
@web.require_login( "share Galaxy histories" )
diff -r 26e37f6af3a8a090d9d6e923fa3e90acb0e64572 -r 33812bcdc52393bf179dd501b4334be4ec4e97a7 static/scripts/mvc/history/current-history-panel.js
--- /dev/null
+++ b/static/scripts/mvc/history/current-history-panel.js
@@ -0,0 +1,285 @@
+define([
+ "mvc/dataset/hda-edit",
+ "mvc/history/history-panel"
+], function( hdaEdit, hpanel ){
+// ============================================================================
+/** session storage for history panel preferences (and to maintain state)
+ */
+var HistoryPanelPrefs = SessionStorageModel.extend({
+ defaults : {
+ /** is the panel currently showing the search/filter controls? */
+ searching : false,
+ /** should the tags editor be shown or hidden initially? */
+ tagsEditorShown : false,
+ /** should the annotation editor be shown or hidden initially? */
+ annotationEditorShown : false
+ },
+ toString : function(){
+ return 'HistoryPanelPrefs(' + JSON.stringify( this.toJSON() ) + ')';
+ }
+});
+
+/** key string to store panel prefs (made accessible on class so you can access sessionStorage directly) */
+HistoryPanelPrefs.storageKey = function storageKey(){
+ return ( 'history-panel' );
+};
+
+/* =============================================================================
+TODO:
+
+============================================================================= */
+/** @class View/Controller for the user's current history model as used in the history
+ * panel (current right hand panel).
+ * @name HistoryPanel
+ *
+ * @augments Backbone.View
+ * @borrows LoggableMixin#logger as #logger
+ * @borrows LoggableMixin#log as #log
+ * @constructs
+ */
+var CurrentHistoryPanel = hpanel.HistoryPanel.extend(
+/** @lends HistoryPanel.prototype */{
+
+ ///** logger used to record this.log messages, commonly set to console */
+ //// comment this out to suppress log output
+ //logger : console,
+
+ /** class to use for constructing the HDA views */
+ HDAViewClass : hdaEdit.HDAEditView,
+
+ emptyMsg : _l( "This history is empty. Click 'Get Data' on the left pane to start" ),
+ noneFoundMsg : _l( "No matching datasets found" ),
+
+ // ......................................................................... SET UP
+ /** Set up the view, set up storage, bind listeners to HDACollection events
+ * @param {Object} attributes
+ * @config {Object} urlTemplates.hda nested object containing url templates for HDAViews
+ * @throws 'needs urlTemplates' if urlTemplates.history or urlTemplates.hda aren't present
+ * @see PersistentStorage
+ * @see Backbone.View#initialize
+ */
+ initialize : function( attributes ){
+ attributes = attributes || {};
+
+ // ---- persistent preferences
+ /** maintain state / preferences over page loads */
+ this.preferences = new HistoryPanelPrefs( _.extend({
+ id : HistoryPanelPrefs.storageKey()
+ }, _.pick( attributes, _.keys( HistoryPanelPrefs.prototype.defaults ) )));
+
+ hpanel.HistoryPanel.prototype.initialize.call( this, attributes );
+ if( this.model ){
+ console.debug( this.model );
+ this.model.checkForUpdates();
+ }
+ },
+
+ // ------------------------------------------------------------------------ loading history/hda models
+ /** (re-)loads the user's current history & hdas w/ details */
+ loadCurrentHistory : function( attributes ){
+ // implemented as a 'fresh start' or for when there is no model (intial panel render)
+ var panel = this;
+ return this.loadHistoryWithHDADetails( 'current', attributes )
+ .then(function( historyData, hdaData ){
+ panel.trigger( 'current-history', panel );
+ });
+ },
+
+ /** loads a history & hdas w/ details and makes them the current history */
+ switchToHistory : function( historyId, attributes ){
+ //console.info( 'switchToHistory:', historyId, attributes );
+ var panel = this,
+ historyFn = function(){
+ // make this current and get history data with one call
+ return jQuery.post( galaxy_config.root + 'api/histories/' + historyId + '/set_as_current' );
+ };
+ return this.loadHistoryWithHDADetails( historyId, attributes, historyFn )
+ .then(function( historyData, hdaData ){
+ panel.trigger( 'switched-history', panel );
+ });
+ },
+
+ /** creates a new history on the server and sets it as the user's current history */
+ createNewHistory : function( attributes ){
+ if( !Galaxy || !Galaxy.currUser || Galaxy.currUser.isAnonymous() ){
+ this.displayMessage( 'error', _l( 'You must be logged in to create histories' ) );
+ return $.when();
+ }
+ var panel = this,
+ historyFn = function(){
+ // get history data from posting a new history (and setting it to current)
+ return jQuery.post( galaxy_config.root + 'api/histories', { current: true });
+ };
+ // id undefined bc there is no historyId yet - the server will provide
+ // (no need for details - nothing expanded in new history)
+ return this.loadHistory( undefined, attributes, historyFn )
+ .then(function( historyData, hdaData ){
+ panel.trigger( 'new-history', panel );
+ });
+ },
+
+ /** release/free/shutdown old models and set up panel for new models */
+ setModel : function( newHistoryJSON, newHdaJSON, attributes ){
+ attributes = attributes || {};
+ hpanel.HistoryPanel.prototype.setModel.call( this, newHistoryJSON, newHdaJSON, attributes );
+ this.model.checkForUpdates();
+ return this;
+ },
+
+ // ------------------------------------------------------------------------ history/hda event listening
+ /** listening for history and HDA events */
+ _setUpModelEventHandlers : function(){
+ hpanel.HistoryPanel.prototype._setUpModelEventHandlers.call( this );
+ // ---- history
+ // update the quota meter when current history changes size
+ if( Galaxy && Galaxy.quotaMeter ){
+ this.listenTo( this.model, 'change:nice_size', function(){
+ //console.info( '!! model size changed:', this.model.get( 'nice_size' ) )
+//TODO: global
+ Galaxy.quotaMeter.update();
+ });
+ }
+
+ // if an a hidden hda is created (gen. by a workflow), moves thru the updater to the ready state,
+ // then: remove it from the collection if the panel is set to NOT show hidden datasets
+ this.model.hdas.on( 'state:ready', function( hda, newState, oldState ){
+ if( ( !hda.get( 'visible' ) )
+ && ( !this.storage.get( 'show_hidden' ) ) ){
+ this.removeHdaView( this.hdaViews[ hda.id ] );
+ }
+ }, this );
+
+ },
+
+ // ------------------------------------------------------------------------ panel rendering
+ /** Render urls, historyPanel body, and hdas (if any are shown)
+ * @fires: rendered when the panel is attached and fully visible
+ * @see Backbone.View#render
+ */
+ render : function( speed, callback ){
+ // send a speed of 0 to have no fade in/out performed
+ speed = ( speed === undefined )?( this.fxSpeed ):( speed );
+ var panel = this,
+ $newRender;
+
+ // handle the possibility of no model (can occur if fetching the model returns an error)
+ if( this.model ){
+ $newRender = this.renderModel();
+ } else {
+ $newRender = this.renderWithoutModel();
+ }
+
+ // fade out existing, swap with the new, fade in, set up behaviours
+ $( panel ).queue( 'fx', [
+ function( next ){
+ //panel.$el.fadeTo( panel.fxSpeed, 0.0001, next );
+ if( speed && panel.$el.is( ':visible' ) ){
+ panel.$el.fadeOut( speed, next );
+ } else {
+ next();
+ }
+ },
+ function( next ){
+ // swap over from temp div newRender
+ panel.$el.empty();
+ if( $newRender ){
+ panel.$el.append( $newRender.children() );
+ panel.renderBasedOnPrefs();
+ }
+ next();
+ },
+ function( next ){
+ if( speed && !panel.$el.is( ':visible' ) ){
+ panel.$el.fadeIn( speed, next );
+ } else {
+ next();
+ }
+ },
+ function( next ){
+ //TODO: ideally, these would be set up before the fade in (can't because of async save text)
+ if( callback ){ callback.call( this ); }
+ panel.trigger( 'rendered', this );
+ next();
+ }
+ ]);
+ return this;
+ },
+
+ renderBasedOnPrefs : function(){
+ if( this.preferences.get( 'searching' ) ){
+ this.showSearchControls( 0 );
+ }
+ },
+
+ // ........................................................................ external objects/MVC
+ //TODO: remove quota meter from panel and remove this
+ /** add listeners to an external quota meter (mvc/user/user-quotameter.js) */
+ connectToQuotaMeter : function( quotaMeter ){
+ if( !quotaMeter ){
+ return this;
+ }
+ // show/hide the 'over quota message' in the history when the meter tells it to
+ this.listenTo( quotaMeter, 'quota:over', this.showQuotaMessage );
+ this.listenTo( quotaMeter, 'quota:under', this.hideQuotaMessage );
+
+ // having to add this to handle re-render of hview while overquota (the above do not fire)
+ this.on( 'rendered rendered:initial', function(){
+ if( quotaMeter && quotaMeter.isOverQuota() ){
+ this.showQuotaMessage();
+ }
+ });
+ return this;
+ },
+
+//TODO: this seems more like a per user message than a history message; IOW, this doesn't belong here
+ /** Show the over quota message (which happens to be in the history panel).
+ */
+ showQuotaMessage : function(){
+ var msg = this.$el.find( '.quota-message' );
+ //this.log( this + ' showing quota message:', msg, userData );
+ if( msg.is( ':hidden' ) ){ msg.slideDown( this.fxSpeed ); }
+ },
+
+//TODO: this seems more like a per user message than a history message
+ /** Hide the over quota message (which happens to be in the history panel).
+ */
+ hideQuotaMessage : function(){
+ var msg = this.$el.find( '.quota-message' );
+ //this.log( this + ' hiding quota message:', msg, userData );
+ if( !msg.is( ':hidden' ) ){ msg.slideUp( this.fxSpeed ); }
+ },
+
+//TODO: move show_deleted/hidden into panel from opt menu and remove this
+ /** add listeners to an external options menu (templates/webapps/galaxy/root/index.mako) */
+ connectToOptionsMenu : function( optionsMenu ){
+ if( !optionsMenu ){
+ return this;
+ }
+ // set a visible indication in the popupmenu for show_hidden/deleted based on the currHistoryPanel's settings
+ this.on( 'new-storage', function( storage, panel ){
+ if( optionsMenu && storage ){
+ optionsMenu.findItemByHtml( _l( 'Include Deleted Datasets' ) ).checked = storage.get( 'show_deleted' );
+ optionsMenu.findItemByHtml( _l( 'Include Hidden Datasets' ) ).checked = storage.get( 'show_hidden' );
+ }
+ });
+ return this;
+ },
+
+ /** Return a string rep of the history
+ */
+ toString : function(){
+ return 'CurrentHistoryPanel(' + (( this.model )?( this.model.get( 'name' )):( '' )) + ')';
+ }
+});
+
+//------------------------------------------------------------------------------ TEMPLATES
+CurrentHistoryPanel.templates = {
+ historyPanel : Handlebars.templates[ 'template-history-historyPanel' ],
+ anonHistoryPanel : Handlebars.templates[ 'template-history-historyPanel-anon' ]
+};
+
+//==============================================================================
+ return {
+ CurrentHistoryPanel : CurrentHistoryPanel
+ };
+});
diff -r 26e37f6af3a8a090d9d6e923fa3e90acb0e64572 -r 33812bcdc52393bf179dd501b4334be4ec4e97a7 static/scripts/mvc/history/history-model.js
--- a/static/scripts/mvc/history/history-model.js
+++ b/static/scripts/mvc/history/history-model.js
@@ -75,7 +75,7 @@
/** cached timeout id for the HDA updater */
this.updateTimeoutId = null;
// set up update timeout if needed
- this.checkForUpdates();
+ //this.checkForUpdates();
},
/** set up any event listeners for this history including those to the contained HDAs
diff -r 26e37f6af3a8a090d9d6e923fa3e90acb0e64572 -r 33812bcdc52393bf179dd501b4334be4ec4e97a7 static/scripts/mvc/history/history-panel.js
--- a/static/scripts/mvc/history/history-panel.js
+++ b/static/scripts/mvc/history/history-panel.js
@@ -1,157 +1,46 @@
define([
- "mvc/history/history-model",
"mvc/dataset/hda-model",
- "mvc/dataset/hda-base",
- "mvc/dataset/hda-edit"
-], function( historyModel, hdaModel, hdaBase, hdaEdit ){
+ "mvc/dataset/hda-edit",
+ "mvc/history/readonly-history-panel"
+], function( hdaModel, hdaEdit, readonlyPanel ){
+/* =============================================================================
+TODO:
-
-// ============================================================================
-/** session storage for history panel preferences (and to maintain state)
- */
-var HistoryPanelPrefs = SessionStorageModel.extend({
- defaults : {
- /** is the panel currently showing the search/filter controls? */
- searching : false,
- /** should the tags editor be shown or hidden initially? */
- tagsEditorShown : false,
- /** should the annotation editor be shown or hidden initially? */
- annotationEditorShown : false
- },
- toString : function(){
- return 'HistoryPanelPrefs(' + JSON.stringify( this.toJSON() ) + ')';
- }
-});
-
-/** key string to store panel prefs (made accessible on class so you can access sessionStorage directly) */
-HistoryPanelPrefs.storageKey = function storageKey(){
- return ( 'history-panel' );
-};
-
-
-// ============================================================================
-/** session storage for individual history preferences
- */
-var HistoryPrefs = SessionStorageModel.extend({
- defaults : {
- //TODO:?? expandedHdas to array?
- expandedHdas : {},
- //TODO:?? move to user?
- show_deleted : false,
- show_hidden : false
- //TODO: add scroll position?
- },
- /** add an hda id to the hash of expanded hdas */
- addExpandedHda : function( id ){
- this.save( 'expandedHdas', _.extend( this.get( 'expandedHdas' ), _.object([ id ], [ true ]) ) );
- },
- /** remove an hda id from the hash of expanded hdas */
- removeExpandedHda : function( id ){
- this.save( 'expandedHdas', _.omit( this.get( 'expandedHdas' ), id ) );
- },
- toString : function(){
- return 'HistoryPrefs(' + this.id + ')';
- }
-});
-
-/** key string to store each histories settings under */
-HistoryPrefs.historyStorageKey = function historyStorageKey( historyId ){
- // class lvl for access w/o instantiation
- if( !historyId ){
- throw new Error( 'HistoryPrefs.historyStorageKey needs valid id: ' + historyId );
- }
- // single point of change
- return ( 'history:' + historyId );
-};
-
-
-/* =============================================================================
-Backbone.js implementation of history panel
-
-r.js optimizer cline:
-r.js -o baseUrl=. name=./mvc/history/history-panel.js out=history-panel.min.js
-
-TODO:
- tags & annotations -> out
- use model.save instead of urls
-
- feature creep:
- lineage
- hide button
- show permissions in info
- show shared/sharing status on ds, history
- selection, multi-select (and actions common to selected (ugh))
- searching
- sorting, re-shuffling
-
============================================================================= */
-/** @class View/Controller for the history model as used in the history
- * panel (current right hand panel).
+/** @class View/Controller for the history model.
* @name HistoryPanel
*
+ * Allows:
+ * (everything ReadOnlyHistoryPanel allows)
+ * changing the name
+ * displaying and editing tags and annotations
+ * multi-selection and operations on mulitple hdas
+ * Does not allow:
+ * changing the name
+ *
* @augments Backbone.View
* @borrows LoggableMixin#logger as #logger
* @borrows LoggableMixin#log as #log
* @constructs
*/
-var HistoryPanel = Backbone.View.extend( LoggableMixin ).extend(
+var HistoryPanel = readonlyPanel.ReadOnlyHistoryPanel.extend(
/** @lends HistoryPanel.prototype */{
-
+
///** logger used to record this.log messages, commonly set to console */
//// comment this out to suppress log output
//logger : console,
- /** which class to use for constructing the HDA views */
- //defaultHDAViewClass : hdaBase.HDABaseView,
- defaultHDAViewClass : hdaEdit.HDAEditView,
+ /** class to use for constructing the HDA views */
+ HDAViewClass : hdaEdit.HDAEditView,
- tagName : 'div',
- className : 'history-panel',
-
- /** (in ms) that jquery effects will use */
- fxSpeed : 'fast',
-
- datasetsSelector : '.datasets-list',
- emptyMsgSelector : '.empty-history-message',
- msgsSelector : '.message-container',
-
// ......................................................................... SET UP
/** Set up the view, set up storage, bind listeners to HDACollection events
* @param {Object} attributes
- * @config {Object} urlTemplates.hda nested object containing url templates for HDAViews
- * @throws 'needs urlTemplates' if urlTemplates.history or urlTemplates.hda aren't present
- * @see PersistentStorage
- * @see Backbone.View#initialize
*/
initialize : function( attributes ){
attributes = attributes || {};
- // set the logger if requested
- if( attributes.logger ){
- this.logger = attributes.logger;
- }
- this.log( this + '.initialize:', attributes );
// ---- set up instance vars
- // control contents/behavior based on where (and in what context) the panel is being used
- /** which backbone view class to use when displaying the hda list */
- this.HDAViewClass = attributes.HDAViewClass || this.defaultHDAViewClass;
- /** where should pages from links be displayed? (default to new tab/window) */
- this.linkTarget = attributes.linkTarget || '_blank';
-
- // ---- sub views and saved elements
- /** map of hda model ids to hda views */
- this.hdaViews = {};
- /** loading indicator */
- this.indicator = new LoadingIndicator( this.$el );
-
- // ---- persistent state and preferences
- /** maintain state / preferences over page loads */
- this.preferences = new HistoryPanelPrefs( _.extend({
- id : HistoryPanelPrefs.storageKey()
- }, _.pick( attributes, _.keys( HistoryPanelPrefs.prototype.defaults ) )));
-
- /** filters for displaying hdas */
- this.filters = [];
/** selected hda ids */
this.selectedHdaIds = [];
@@ -161,443 +50,33 @@
this.annotationEditorShown = attributes.annotationEditorShown || false;
this.tagsEditorShown = attributes.tagsEditorShown || false;
- this._setUpListeners();
-
- // ---- handle models passed on init
- if( this.model ){
- this._setUpWebStorage( attributes.initiallyExpanded, attributes.show_deleted, attributes.show_hidden );
- this._setUpModelEventHandlers();
- }
-//TODO: remove?
- // ---- and any run functions
- if( attributes.onready ){
- attributes.onready.call( this );
- }
+ readonlyPanel.ReadOnlyHistoryPanel.prototype.initialize.call( this, attributes );
},
- /** create any event listeners for the panel
- * @fires: rendered:initial on the first render
- * @fires: empty-history when switching to a history with no HDAs or creating a new history
- */
- _setUpListeners : function(){
- // ---- event handlers for self
- this.on( 'error', function( model, xhr, options, msg, details ){
- this.errorHandler( model, xhr, options, msg, details );
- });
-
- this.on( 'loading-history', function(){
- // show the loading indicator when loading a new history starts...
- this.showLoadingIndicator( 'loading history...', 40 );
- });
- this.on( 'loading-done', function(){
- // ...hiding it again when loading is done (or there's been an error)
- this.hideLoadingIndicator( 40 );
- });
-
- // throw the first render up as a diff namespace using once
- // (for outside consumption)
- this.once( 'rendered', function(){
- this.trigger( 'rendered:initial', this );
- return false;
- });
-
- // trigger an event when there are no visible hdas
- // (for outside consumption)
- this.on( 'switched-history current-history new-history', function(){
- if( _.isEmpty( this.hdaViews ) ){
- this.trigger( 'empty-history', this );
- }
- });
-
- // debugging
- if( this.logger ){
- this.on( 'all', function( event ){
- this.log( this + '', arguments );
- }, this );
- }
- },
-
- //TODO: see base-mvc
- //onFree : function(){
- // _.each( this.hdaViews, function( view, modelId ){
- // view.free();
- // });
- // this.hdaViews = null;
- //},
-
- // ........................................................................ error handling
- /** Event listener to handle errors (from the panel, the history, or the history's HDAs)
- * @param {Model or View} model the (Backbone) source of the error
- * @param {XMLHTTPRequest} xhr any ajax obj. assoc. with the error
- * @param {Object} options the options map commonly used with bbone ajax
- * @param {String} msg optional message passed to ease error location
- * @param {Object} msg optional object containing error details
- */
- errorHandler : function( model, xhr, options, msg, details ){
- var parsed = this._parseErrorMessage( model, xhr, options, msg, details );
-
- // interrupted ajax
- if( xhr && xhr.status === 0 && xhr.readyState === 0 ){
-
- // bad gateway
- } else if( xhr && xhr.status === 502 ){
-//TODO: gmail style 'reconnecting in Ns'
-
- // otherwise, show an error message inside the panel
- } else {
- // it's possible to have a triggered error before the message container is rendered - wait for it to show
- if( !this.$el.find( this.msgsSelector ).is( ':visible' ) ){
- this.once( 'rendered', function(){
- this.displayMessage( 'error', parsed.message, parsed.details );
- });
- } else {
- this.displayMessage( 'error', parsed.message, parsed.details );
- }
- }
- },
-
- /** Parse an error event into an Object usable by displayMessage based on the parameters
- * note: see errorHandler for more info on params
- */
- _parseErrorMessage : function( model, xhr, options, msg, details ){
- var user = Galaxy.currUser,
- // add the args (w/ some extra info) into an obj
- parsed = {
- message : this._bePolite( msg ),
- details : {
- user : ( user instanceof User )?( user.toJSON() ):( user + '' ),
- source : ( model instanceof Backbone.Model )?( model.toJSON() ):( model + '' ),
- xhr : xhr,
- options : ( xhr )?( _.omit( options, 'xhr' ) ):( options )
- }
- };
- // add any extra details passed in
- _.extend( parsed.details, details || {} );
- // fancy xhr.header parsing (--> obj)
- if( xhr && _.isFunction( xhr.getAllResponseHeaders ) ){
- var responseHeaders = xhr.getAllResponseHeaders();
- responseHeaders = _.compact( responseHeaders.split( '\n' ) );
- responseHeaders = _.map( responseHeaders, function( header ){
- return header.split( ': ' );
- });
- parsed.details.xhr.responseHeaders = _.object( responseHeaders );
- }
- return parsed;
- },
-
- /** Modify an error message to be fancy and wear a monocle. */
- _bePolite : function( msg ){
- msg = msg || _l( 'An error occurred while getting updates from the server' );
- return msg + '. ' + _l( 'Please contact a Galaxy administrator if the problem persists.' );
- },
-
- // ------------------------------------------------------------------------ loading history/hda models
-
- //NOTE: all the following fns replace the existing history model with a new model
- // (in the following 'details' refers to the full set of hda api data (urls, display_apps, misc_info, etc.)
- // - hdas w/o details will have summary data only (name, hid, deleted, visible, state, etc.))
-
- /** (re-)loads the user's current history & hdas w/ details */
- loadCurrentHistory : function( attributes ){
- // implemented as a 'fresh start' or for when there is no model (intial panel render)
- var panel = this;
- return this.loadHistoryWithHDADetails( 'current', attributes )
- .then(function( historyData, hdaData ){
- panel.trigger( 'current-history', panel );
- });
- },
-
- /** loads a history & hdas w/ details and makes them the current history */
- switchToHistory : function( historyId, attributes ){
- //console.info( 'switchToHistory:', historyId, attributes );
- var panel = this,
- historyFn = function(){
- // make this current and get history data with one call
- return jQuery.post( galaxy_config.root + 'api/histories/' + historyId + '/set_as_current' );
- };
- return this.loadHistoryWithHDADetails( historyId, attributes, historyFn )
- .then(function( historyData, hdaData ){
- panel.trigger( 'switched-history', panel );
- });
- },
-
- /** creates a new history on the server and sets it as the user's current history */
- createNewHistory : function( attributes ){
- if( !Galaxy || !Galaxy.currUser || Galaxy.currUser.isAnonymous() ){
- this.displayMessage( 'error', _l( 'You must be logged in to create histories' ) );
- return $.when();
- }
- var panel = this,
- historyFn = function(){
- // get history data from posting a new history (and setting it to current)
- return jQuery.post( galaxy_config.root + 'api/histories', { current: true });
- };
- // id undefined bc there is no historyId yet - the server will provide
- // (no need for details - nothing expanded in new history)
- return this.loadHistory( undefined, attributes, historyFn )
- .then(function( historyData, hdaData ){
- panel.trigger( 'new-history', panel );
- });
- },
-
- /** loads a history & hdas w/ details (but does not make them the current history) */
- loadHistoryWithHDADetails : function( historyId, attributes, historyFn, hdaFn ){
- //console.info( 'loadHistoryWithHDADetails:', historyId, attributes, historyFn, hdaFn );
- var panel = this,
- // will be called to get hda ids that need details from the api
- hdaDetailIds = function( historyData ){
-//TODO: non-visible HDAs are getting details loaded... either stop loading them at all or filter ids thru isVisible
- return panel.getExpandedHdaIds( historyData.id );
- };
- return this.loadHistory( historyId, attributes, historyFn, hdaFn, hdaDetailIds );
- },
-
- /** loads a history & hdas w/ NO details (but does not make them the current history) */
- loadHistory : function( historyId, attributes, historyFn, hdaFn, hdaDetailIds ){
- this.trigger( 'loading-history', this );
- attributes = attributes || {};
- var panel = this;
- //console.info( 'loadHistory:', historyId, attributes, historyFn, hdaFn, hdaDetailIds );
- var xhr = historyModel.History.getHistoryData( historyId, {
- historyFn : historyFn,
- hdaFn : hdaFn,
- hdaDetailIds : attributes.initiallyExpanded || hdaDetailIds
- });
- return this._loadHistoryFromXHR( xhr, attributes )
- .fail( function( xhr, where, history ){
- // throw an error up for the error handler
- panel.trigger( 'error', panel, xhr, attributes, _l( 'An error was encountered while ' + where ),
- { historyId: historyId, history: history || {} });
- })
- .always( function(){
- // bc hideLoadingIndicator relies on this firing
- panel.trigger( 'loading-done', panel );
- });
- },
-
- /** given an xhr that will provide both history and hda data, pass data to set model or handle xhr errors */
- _loadHistoryFromXHR : function( xhr, attributes ){
- var panel = this;
- xhr.then( function( historyJSON, hdaJSON ){
- panel.setModel( historyJSON, hdaJSON, attributes );
- });
- xhr.fail( function( xhr, where ){
- // always render - whether we get a model or not
- panel.render();
- });
- return xhr;
- },
-
- /** release/free/shutdown old models and set up panel for new models */
- setModel : function( newHistoryJSON, newHdaJSON, attributes ){
- attributes = attributes || {};
- //console.info( 'setModel:', newHistoryJSON, newHdaJSON.length, attributes );
-
- // stop/release the previous model, and clear cache to hda sub-views
- if( this.model ){
- this.model.clearUpdateTimeout();
- this.stopListening( this.model );
- this.stopListening( this.model.hdas );
- //TODO: see base-mvc
- //this.model.free();
- }
- this.hdaViews = {};
-
- // set up the new model and render
- if( Galaxy && Galaxy.currUser ){
-//TODO: global
- newHistoryJSON.user = Galaxy.currUser.toJSON();
- }
- this.model = new historyModel.History( newHistoryJSON, newHdaJSON, attributes );
- this._setUpWebStorage( attributes.initiallyExpanded, attributes.show_deleted, attributes.show_hidden );
- this._setUpModelEventHandlers();
- this.selectedHdaIds = [];
- this.trigger( 'new-model', this );
- this.render();
- return this;
- },
-
- // ------------------------------------------------------------------------ browser stored prefs
- /** Set up client side storage. Currently PersistanStorage keyed under 'HistoryPanel.<id>'
- * @param {Object} initiallyExpanded
- * @param {Boolean} show_deleted whether to show deleted HDAs (overrides stored)
- * @param {Boolean} show_hidden
- * @see PersistentStorage
- */
- _setUpWebStorage : function( initiallyExpanded, show_deleted, show_hidden ){
- //console.debug( '_setUpWebStorage', initiallyExpanded, show_deleted, show_hidden );
- this.storage = new HistoryPrefs({
- id: HistoryPrefs.historyStorageKey( this.model.get( 'id' ) )
- });
-
- // expanded Hdas is a map of hda.ids -> a boolean repr'ing whether this hda's body is already expanded
- // store any pre-expanded ids passed in
- if( _.isObject( initiallyExpanded ) ){
- this.storage.set( 'exandedHdas', initiallyExpanded );
- }
-
- // get the show_deleted/hidden settings giving priority to values passed in, using web storage otherwise
- // if the page has specifically requested show_deleted/hidden, these will be either true or false
- // (as opposed to undefined, null) - and we give priority to that setting
- if( _.isBoolean( show_deleted ) ){
- this.storage.set( 'show_deleted', show_deleted );
- }
- if( _.isBoolean( show_hidden ) ){
- this.storage.set( 'show_hidden', show_hidden );
- }
-
- this.trigger( 'new-storage', this.storage, this );
- this.log( this + ' (init\'d) storage:', this.storage.get() );
- },
-
- /** clear all stored history panel data */
- clearWebStorage : function(){
- for( var key in sessionStorage ){
- if( key.indexOf( 'history:' ) === 0 ){
- sessionStorage.removeItem( key );
- }
- }
- },
-
- /** get all stored data as an Object for a history with the given id */
- getStoredOptions : function( historyId ){
- if( !historyId || historyId === 'current' ){
- return ( this.storage )?( this.storage.get() ):( {} );
- }
- //TODO: make storage engine generic
- var item = sessionStorage.getItem( HistoryPrefs.historyStorageKey( historyId ) );
- return ( item === null )?( {} ):( JSON.parse( item ) );
- },
-
- /** get an array of expanded hda ids for the given history id */
- getExpandedHdaIds : function( historyId ){
- var expandedHdas = this.getStoredOptions( historyId ).expandedHdas;
- return (( _.isEmpty( expandedHdas ) )?( [] ):( _.keys( expandedHdas ) ));
- },
-
- // ------------------------------------------------------------------------ history/hda event listening
+ // ------------------------------------------------------------------------ panel rendering
/** listening for history and HDA events */
_setUpModelEventHandlers : function(){
- // ---- history
- // on a model error - bounce it up to the panel and remove it from the model
- this.model.on( 'error error:hdas', function( model, xhr, options, msg ){
- this.errorHandler( model, xhr, options, msg );
- }, this );
+ readonlyPanel.ReadOnlyHistoryPanel.prototype._setUpModelEventHandlers.call( this );
- // don't need to re-render entire model on all changes, just render disk size when it changes
this.model.on( 'change:nice_size', this.updateHistoryDiskSize, this );
- // update the quota meter when current history changes size
- if( Galaxy && Galaxy.quotaMeter ){
- this.listenTo( this.model, 'change:nice_size', function(){
- //console.info( '!! model size changed:', this.model.get( 'nice_size' ) )
-//TODO: global
- Galaxy.quotaMeter.update();
- });
- }
-
- // ---- hdas
- // bind events from the model's hda collection
- // note: don't listen to the hdas for errors, history will pass that to us
- //this.model.hdas.on( 'reset', this.addAll, this );
- this.model.hdas.on( 'add', this.addHdaView, this );
-
this.model.hdas.on( 'change:deleted', this.handleHdaDeletionChange, this );
this.model.hdas.on( 'change:visible', this.handleHdaVisibleChange, this );
- // when an hda is purged the disk size changes
this.model.hdas.on( 'change:purged', function( hda ){
// hafta get the new nice-size w/o the purged hda
this.model.fetch();
}, this );
-
- // if an a hidden hda is created (gen. by a workflow), moves thru the updater to the ready state,
- // then: remove it from the collection if the panel is set to NOT show hidden datasets
- this.model.hdas.on( 'state:ready', function( hda, newState, oldState ){
- if( ( !hda.get( 'visible' ) )
- && ( !this.storage.get( 'show_hidden' ) ) ){
- this.removeHdaView( this.hdaViews[ hda.id ] );
- }
- }, this );
-
},
// ------------------------------------------------------------------------ panel rendering
- /** Render urls, historyPanel body, and hdas (if any are shown)
- * @fires: rendered when the panel is attached and fully visible
- * @see Backbone.View#render
- */
- render : function( speed, callback ){
- // send a speed of 0 to have no fade in/out performed
- speed = ( speed === undefined )?( this.fxSpeed ):( speed );
- var panel = this,
- $newRender;
-
- // handle the possibility of no model (can occur if fetching the model returns an error)
- if( this.model ){
- $newRender = this.renderModel();
- } else {
- $newRender = this.renderWithoutModel();
- }
-
- // fade out existing, swap with the new, fade in, set up behaviours
- $( panel ).queue( 'fx', [
- function( next ){
- //panel.$el.fadeTo( panel.fxSpeed, 0.0001, next );
- if( speed && panel.$el.is( ':visible' ) ){
- panel.$el.fadeOut( speed, next );
- } else {
- next();
- }
- },
- function( next ){
- // swap over from temp div newRender
- panel.$el.empty();
- if( $newRender ){
- panel.$el.append( $newRender.children() );
- panel.renderBasedOnPrefs();
- }
- next();
- },
- function( next ){
- if( speed && !panel.$el.is( ':visible' ) ){
- panel.$el.fadeIn( speed, next );
- } else {
- next();
- }
- },
- function( next ){
- //TODO: ideally, these would be set up before the fade in (can't because of async save text)
- if( callback ){ callback.call( this ); }
- panel.trigger( 'rendered', this );
- next();
- }
- ]);
- return this;
- },
-
- /** render with no history data */
- renderWithoutModel : function( ){
- // we'll always need the message container
- var $newRender = $( '<div/>' ),
- $msgContainer = $( '<div/>' ).addClass( 'message-container' )
- .css({ 'margin-left': '4px', 'margin-right': '4px' });
- return $newRender.append( $msgContainer );
- },
-
/** render with history data */
renderModel : function( ){
var $newRender = $( '<div/>' );
- // render based on anonymity, set up behaviors
- if( !Galaxy || !Galaxy.currUser || Galaxy.currUser.isAnonymous() ){
- $newRender.append( HistoryPanel.templates.anonHistoryPanel( this.model.toJSON() ) );
-
- } else {
- $newRender.append( HistoryPanel.templates.historyPanel( this.model.toJSON() ) );
- if( Galaxy.currUser.id && Galaxy.currUser.id === this.model.get( 'user_id' ) ){
- this._renderTags( $newRender );
- this._renderAnnotation( $newRender );
- }
+ $newRender.append( HistoryPanel.templates.historyPanel( this.model.toJSON() ) );
+ if( Galaxy.currUser.id && Galaxy.currUser.id === this.model.get( 'user_id' ) ){
+ this._renderTags( $newRender );
+ this._renderAnnotation( $newRender );
}
// search and select available to both anon/logged-in users
$newRender.find( '.history-secondary-actions' ).prepend( this._renderSelectButton() );
@@ -611,12 +90,6 @@
return $newRender;
},
- renderBasedOnPrefs : function(){
- if( this.preferences.get( 'searching' ) ){
- this.showSearchControls( 0 );
- }
- },
-
_renderTags : function( $where ){
var panel = this;
this.tagsEditor = new TagsEditor({
@@ -625,11 +98,9 @@
onshowFirstTime : function(){ this.render(); },
// show hide hda view tag editors when this is shown/hidden
onshow : function(){
- panel.preferences.set( 'tagsEditorShown', true );
panel.toggleHDATagEditors( true, panel.fxSpeed );
},
onhide : function(){
- panel.preferences.set( 'tagsEditorShown', false );
panel.toggleHDATagEditors( false, panel.fxSpeed );
},
$activator : faIconButton({
@@ -638,9 +109,6 @@
faIcon : 'fa-tags'
}).appendTo( $where.find( '.history-secondary-actions' ) )
});
- if( this.preferences.get( 'tagsEditorShown' ) ){
- this.tagsEditor.toggle( true );
- }
},
_renderAnnotation : function( $where ){
var panel = this;
@@ -650,11 +118,9 @@
onshowFirstTime : function(){ this.render(); },
// show hide hda view annotation editors when this is shown/hidden
onshow : function(){
- panel.preferences.set( 'annotationEditorShown', true );
panel.toggleHDAAnnotationEditors( true, panel.fxSpeed );
},
onhide : function(){
- panel.preferences.set( 'annotationEditorShown', false );
panel.toggleHDAAnnotationEditors( false, panel.fxSpeed );
},
$activator : faIconButton({
@@ -663,18 +129,8 @@
faIcon : 'fa-comment'
}).appendTo( $where.find( '.history-secondary-actions' ) )
});
- if( this.preferences.get( 'annotationEditorShown' ) ){
- this.annotationEditor.toggle( true );
- }
},
- /** button for opening search */
- _renderSearchButton : function( $where ){
- return faIconButton({
- title : _l( 'Search datasets' ),
- classes : 'history-search-btn',
- faIcon : 'fa-search'
- });
- },
+
/** button for starting select mode */
_renderSelectButton : function( $where ){
return faIconButton({
@@ -762,45 +218,23 @@
},
// ------------------------------------------------------------------------ hda sub-views
- /** alias to the model. Updates the hda list only (not the history) */
- refreshHdas : function( detailIds, options ){
- if( this.model ){
- return this.model.refresh( detailIds, options );
- }
- // may have callbacks - so return an empty promise
- return $.when();
+ /** If this hda is deleted and we're not showing deleted hdas, remove the view
+ * @param {HistoryDataAssociation} the hda to check
+ */
+ handleHdaDeletionChange : function( hda ){
+ if( hda.get( 'deleted' ) && !this.storage.get( 'show_deleted' ) ){
+ this.removeHdaView( this.hdaViews[ hda.id ] );
+ } // otherwise, the hdaView rendering should handle it
},
- /** Add an hda view to the panel for the given hda
- * @param {HistoryDatasetAssociation} hda
+
+ /** If this hda is hidden and we're not showing hidden hdas, remove the view
+ * @param {HistoryDataAssociation} the hda to check
*/
- addHdaView : function( hda ){
- this.log( 'add.' + this, hda );
- var panel = this;
-
- // don't add the view if it wouldn't be visible accrd. to current settings
- if( !hda.isVisible( this.storage.get( 'show_deleted' ), this.storage.get( 'show_hidden' ) ) ){
- return;
- }
-
- // create and prepend to current el, if it was empty fadeout the emptyMsg first
- $({}).queue([
- function fadeOutEmptyMsg( next ){
- var $emptyMsg = panel.$el.find( panel.emptyMsgSelector );
- if( $emptyMsg.is( ':visible' ) ){
- $emptyMsg.fadeOut( panel.fxSpeed, next );
- } else {
- next();
- }
- },
- function createAndPrepend( next ){
- panel.scrollToTop();
- var $whereTo = panel.$el.find( panel.datasetsSelector ),
- hdaView = panel.createHdaView( hda );
- panel.hdaViews[ hda.id ] = hdaView;
- hdaView.render().$el.hide().prependTo( $whereTo ).slideDown( panel.fxSpeed );
- }
- ]);
+ handleHdaVisibleChange : function( hda ){
+ if( hda.hidden() && !this.storage.get( 'show_hidden' ) ){
+ this.removeHdaView( this.hdaViews[ hda.id ] );
+ } // otherwise, the hdaView rendering should handle it
},
/** Create an HDA view for the given HDA (but leave attachment for addHdaView above)
@@ -816,8 +250,8 @@
selectable : this.selecting,
hasUser : this.model.ownedByCurrUser(),
logger : this.logger,
- tagsEditorShown : this.preferences.get( 'tagsEditorShown' ),
- annotationEditorShown : this.preferences.get( 'annotationEditorShown' )
+ tagsEditorShown : !this.tagsEditor.isHidden(),
+ annotationEditorShown : !this.annotationEditor.isHidden()
});
this._setUpHdaListeners( hdaView );
return hdaView;
@@ -829,13 +263,8 @@
*/
_setUpHdaListeners : function( hdaView ){
var historyView = this;
- // maintain a list of hdas whose bodies are expanded
- hdaView.on( 'body-expanded', function( id ){
- historyView.storage.addExpandedHda( id );
- });
- hdaView.on( 'body-collapsed', function( id ){
- historyView.storage.removeExpandedHda( id );
- });
+ readonlyPanel.ReadOnlyHistoryPanel.prototype._setUpHdaListeners.call( this, hdaView );
+
// maintain a list of hdas that are selected
hdaView.on( 'selected', function( hdaView ){
var id = hdaView.model.get( 'id' );
@@ -847,88 +276,6 @@
historyView.selectedHdaIds = _.without( historyView.selectedHdaIds, id );
//console.debug( 'de-selected', historyView.selectedHdaIds );
});
-//TODO: remove?
- hdaView.on( 'error', function( model, xhr, options, msg ){
- historyView.errorHandler( model, xhr, options, msg );
- });
- },
-
- /** If this hda is deleted and we're not showing deleted hdas, remove the view
- * @param {HistoryDataAssociation} the hda to check
- */
- handleHdaDeletionChange : function( hda ){
- if( hda.get( 'deleted' ) && !this.storage.get( 'show_deleted' ) ){
- this.removeHdaView( this.hdaViews[ hda.id ] );
- } // otherwise, the hdaView rendering should handle it
- },
-
- /** If this hda is hidden and we're not showing hidden hdas, remove the view
- * @param {HistoryDataAssociation} the hda to check
- */
- handleHdaVisibleChange : function( hda ){
- if( hda.hidden() && !this.storage.get( 'show_hidden' ) ){
- this.removeHdaView( this.hdaViews[ hda.id ] );
- } // otherwise, the hdaView rendering should handle it
- },
-
- /** Remove a view from the panel and if the panel is now empty, re-render
- * @param {Int} the id of the hdaView to remove
- */
- removeHdaView : function( hdaView ){
- if( !hdaView ){ return; }
-
- var panel = this;
- hdaView.$el.fadeOut( panel.fxSpeed, function(){
- hdaView.off();
- hdaView.remove();
- delete panel.hdaViews[ hdaView.model.id ];
- if( _.isEmpty( panel.hdaViews ) ){
- panel.$el.find( panel.emptyMsgSelector ).fadeIn( panel.fxSpeed, function(){
- panel.trigger( 'empty-history', panel );
- });
- }
- });
- },
-
- /** Set up/render a view for each HDA to be shown, init with model and listeners.
- * HDA views are cached to the map this.hdaViews (using the model.id as key).
- * @param {jQuery} $whereTo what dom element to prepend the HDA views to
- * @returns the number of visible hda views
- */
- renderHdas : function( $whereTo ){
- $whereTo = $whereTo || this.$el;
- var historyView = this,
- newHdaViews = {},
- $datasetsList = $whereTo.find( this.datasetsSelector ),
- // only render the shown hdas
- //TODO: switch to more general filtered pattern
- visibleHdas = this.model.hdas.getVisible(
- this.storage.get( 'show_deleted' ),
- this.storage.get( 'show_hidden' ),
- this.filters
- );
- //console.debug( 'renderHdas, visibleHdas:', visibleHdas, $whereTo );
- $datasetsList.empty();
-
- if( visibleHdas.length ){
- visibleHdas.each( function( hda ){
- // render it (NOTE: reverse order, newest on top (prepend))
- var hdaId = hda.get( 'id' ),
- hdaView = historyView.createHdaView( hda );
- newHdaViews[ hdaId ] = hdaView;
- if( _.contains( historyView.selectedHdaIds, hdaId ) ){
- hdaView.selected = true;
- }
- $datasetsList.prepend( hdaView.render().$el );
- });
- $whereTo.find( this.emptyMsgSelector ).hide();
-
- } else {
- //console.debug( 'emptyMsg:', $whereTo.find( this.emptyMsgSelector ) )
- $whereTo.find( this.emptyMsgSelector ).show();
- }
- this.hdaViews = newHdaViews;
- return this.hdaViews;
},
/** toggle the visibility of each hdaView's tagsEditor applying all the args sent to this function */
@@ -951,149 +298,41 @@
});
},
+ /** Remove a view from the panel and if the panel is now empty, re-render
+ * @param {Int} the id of the hdaView to remove
+ */
+ removeHdaView : function( hdaView ){
+ if( !hdaView ){ return; }
+
+ var panel = this;
+ hdaView.$el.fadeOut( panel.fxSpeed, function(){
+ hdaView.off();
+ hdaView.remove();
+ delete panel.hdaViews[ hdaView.model.id ];
+ if( _.isEmpty( panel.hdaViews ) ){
+ panel.$el.find( panel.emptyMsgSelector ).fadeIn( panel.fxSpeed, function(){
+ panel.trigger( 'empty-history', panel );
+ });
+ }
+ });
+ },
+
// ------------------------------------------------------------------------ panel events
/** event map */
- events : {
- // allow (error) messages to be clicked away
- //TODO: switch to common close (X) idiom
- 'click .message-container' : 'clearMessages',
-
- 'click .history-search-btn' : 'toggleSearchControls',
+ events : _.extend( _.clone( readonlyPanel.ReadOnlyHistoryPanel.prototype.events ), {
'click .history-select-btn' : function( e ){ this.toggleSelectors( this.fxSpeed ); },
-
'click .history-select-all-datasets-btn' : 'selectAllDatasets',
'click .history-deselect-all-datasets-btn' : 'deselectAllDatasets'
- },
+ }),
/** Update the history size display (curr. upper right of panel).
*/
updateHistoryDiskSize : function(){
this.$el.find( '.history-size' ).text( this.model.get( 'nice_size' ) );
},
-
- /** Collapse all hda bodies and clear expandedHdas in the storage
- */
- collapseAllHdaBodies : function(){
- _.each( this.hdaViews, function( item ){
- item.toggleBodyVisibility( null, false );
- });
- this.storage.set( 'expandedHdas', {} );
- },
-
- /** Handle the user toggling the deleted visibility by:
- * (1) storing the new value in the persistent storage
- * (2) re-rendering the history
- * @returns {Boolean} new show_deleted setting
- */
- toggleShowDeleted : function(){
- this.storage.set( 'show_deleted', !this.storage.get( 'show_deleted' ) );
- this.renderHdas();
- return this.storage.get( 'show_deleted' );
- },
-
- /** Handle the user toggling the deleted visibility by:
- * (1) storing the new value in the persistent storage
- * (2) re-rendering the history
- * @returns {Boolean} new show_hidden setting
- */
- toggleShowHidden : function(){
- this.storage.set( 'show_hidden', !this.storage.get( 'show_hidden' ) );
- this.renderHdas();
- return this.storage.get( 'show_hidden' );
- },
-
- // ........................................................................ filters
- /** render a search input for filtering datasets shown
- * (see the search section in the HDA model for implementation of the actual searching)
- * return will start the search
- * esc will clear the search
- * clicking the clear button will clear the search
- * uses searchInput in ui.js
- */
- setUpSearchInput : function( $where ){
- var panel = this,
- inputSelector = '.history-search-input';
-
- function onSearch( searchFor ){
- //console.debug( 'onSearch', searchFor, panel );
- panel.searchFor = searchFor;
- panel.filters = [ function( hda ){ return hda.matchesAll( panel.searchFor ); } ];
- panel.trigger( 'search:searching', searchFor, panel );
- panel.renderHdas();
- }
- function onFirstSearch( searchFor ){
- //console.debug( 'onSearch', searchFor, panel );
- if( panel.model.hdas.haveDetails() ){
- onSearch( searchFor );
- return;
- }
- panel.$el.find( inputSelector ).searchInput( 'toggle-loading' );
- panel.model.hdas.fetchAllDetails({ silent: true })
- .always( function(){
- panel.$el.find( inputSelector ).searchInput( 'toggle-loading' );
- })
- .done( function(){
- onSearch( searchFor );
- });
- }
- function onSearchClear(){
- //console.debug( 'onSearchClear', panel );
- panel.searchFor = '';
- panel.filters = [];
- panel.trigger( 'search:clear', panel );
- panel.renderHdas();
- }
- $where.searchInput({
- initialVal : panel.searchFor,
- name : 'history-search',
- placeholder : 'search datasets',
- classes : 'history-search',
- onfirstsearch : onFirstSearch,
- onsearch : onSearch,
- onclear : onSearchClear
- });
- return $where;
- },
-//TODO: to hidden/shown plugin
- showSearchControls : function( speed ){
- speed = ( speed === undefined )?( this.fxSpeed ):( speed );
- var panel = this,
- $searchControls = this.$el.find( '.history-search-controls' ),
- $input = $searchControls.find( '.history-search-input' );
- // if it hasn't been rendered - do it now
- if( !$input.children().size() ){
- this.setUpSearchInput( $input );
- //$searchControls.append( faIconButton({
- // title : _l( 'More search options' ),
- // classes : 'history-search-advanced',
- // faIcon : 'fa-ellipsis-horizontal'
- //}) );
- }
- // then slide open, focusing on the input, and persisting the setting when it's done
- $searchControls.slideDown( speed, function(){
- $( this ).find( 'input' ).focus();
- panel.preferences.set( 'searching', true );
- });
- },
- hideSearchControls : function(){
- speed = ( speed === undefined )?( this.fxSpeed ):( speed );
- var panel = this;
- this.$el.find( '.history-search-controls' ).slideUp( speed, function(){
- panel.preferences.set( 'searching', false );
- });
- },
-
- /** toggle showing/hiding the search controls (rendering first on the initial show) */
- toggleSearchControls : function( eventOrSpeed ){
- speed = ( jQuery.type( eventOrSpeed ) === 'number' )?( eventOrSpeed ):( this.fxSpeed );
- if( this.$el.find( '.history-search-controls' ).is( ':visible' ) ){
- this.hideSearchControls( speed );
- } else {
- this.showSearchControls( speed );
- }
- },
// ........................................................................ multi-select of hdas
+ /** show selectors on all visible hdas and associated controls */
showSelectors : function( speed ){
this.selecting = true;
this.$el.find( '.history-dataset-actions' ).slideDown( speed );
@@ -1103,6 +342,7 @@
this.selectedHdaIds = [];
},
+ /** hide selectors on all visible hdas and associated controls */
hideSelectors : function( speed ){
this.selecting = false;
this.$el.find( '.history-dataset-actions' ).slideUp( speed );
@@ -1112,6 +352,7 @@
this.selectedHdaIds = [];
},
+ /** show or hide selectors on all visible hdas and associated controls */
toggleSelectors : function( speed ){
if( !this.selecting ){
this.showSelectors( speed );
@@ -1120,245 +361,36 @@
}
},
+ /** select all visible hdas */
selectAllDatasets : function( event ){
_.each( this.hdaViews, function( view ){
view.select( event );
});
},
+ /** deselect all visible hdas */
deselectAllDatasets : function( event ){
_.each( this.hdaViews, function( view ){
view.deselect( event );
});
},
+ /** return an array of all currently selected hdas */
getSelectedHdaViews : function(){
return _.filter( this.hdaViews, function( v ){
return v.selected;
});
},
+ /** return an HdaCollection of the models of all currenly selected hdas */
getSelectedHdaCollection : function(){
return new hdaModel.HDACollection( _.map( this.getSelectedHdaViews(), function( hdaView ){
return hdaView.model;
}), { historyId: this.model.id });
},
- // ........................................................................ loading indicator
- /** hide the panel and display a loading indicator (in the panel's parent) when history model's are switched */
- showLoadingIndicator : function( msg, speed, callback ){
- speed = ( speed !== undefined )?( speed ):( this.fxSpeed );
- if( !this.indicator ){
- this.indicator = new LoadingIndicator( this.$el, this.$el.parent() );
- }
- if( !this.$el.is( ':visible' ) ){
- this.indicator.show( 0, callback );
- } else {
- this.$el.fadeOut( speed );
- this.indicator.show( msg, speed, callback );
- }
- },
-
- /** hide the loading indicator */
- hideLoadingIndicator : function( speed, callback ){
- speed = ( speed !== undefined )?( speed ):( this.fxSpeed );
- if( this.indicator ){
- this.indicator.hide( speed, callback );
- }
- },
-
- // ........................................................................ (error) messages
- /** Display a message in the top of the panel.
- * @param {String} type type of message ('done', 'error', 'warning')
- * @param {String} msg the message to display
- */
- displayMessage : function( type, msg, details ){
- //precondition: msgContainer must have been rendered even if there's no model
- var panel = this;
- //console.debug( 'displayMessage', type, msg, details );
-
- this.scrollToTop();
- var $msgContainer = this.$el.find( this.msgsSelector ),
- $msg = $( '<div/>' ).addClass( type + 'message' ).html( msg );
- //console.debug( ' ', $msgContainer );
-
- if( !_.isEmpty( details ) ){
- var $detailsLink = $( '<a href="javascript:void(0)">Details</a>' )
- .click( function(){
- Galaxy.modal.show( panel.messageToModalOptions( type, msg, details ) );
- return false;
- });
- $msg.append( ' ', $detailsLink );
- }
- return $msgContainer.html( $msg );
- },
-
- /** convert msg and details into modal options usable by Galaxy.modal */
- messageToModalOptions : function( type, msg, details ){
- // only error is fleshed out here
- var panel = this,
- $modalBody = $( '<div/>' ),
- options = { title: 'Details' };
-
- //TODO: to some util library
- function objToTable( obj ){
- obj = _.omit( obj, _.functions( obj ) );
- return [
- '<table>',
- _.map( obj, function( val, key ){
- val = ( _.isObject( val ) )?( objToTable( val ) ):( val );
- return '<tr><td style="vertical-align: top; color: grey">' + key + '</td>'
- + '<td style="padding-left: 8px">' + val + '</td></tr>';
- }).join( '' ),
- '</table>'
- ].join( '' );
- }
-
- if( _.isObject( details ) ){
- options.body = $modalBody.append( objToTable( details ) );
-
- } else {
- options.body = $modalBody.html( details );
- }
- options.buttons = {
- 'Ok': function(){
- Galaxy.modal.hide();
- panel.clearMessages();
- }
- //TODO: if( type === 'error' ){ options.buttons[ 'Report this error' ] = function(){} }
- };
- return options;
- },
-
- /** Remove all messages from the panel.
- */
- clearMessages : function(){
- var $msgContainer = this.$el.find( this.msgsSelector );
- $msgContainer.empty();
- },
-
- // ........................................................................ scrolling
- /** get the current scroll position of the panel in its parent */
- scrollPosition : function(){
- return this.$el.parent().scrollTop();
- },
-
- /** set the current scroll position of the panel in its parent */
- scrollTo : function( pos ){
- this.$el.parent().scrollTop( pos );
- },
-
- /** Scrolls the panel to the top.
- * @returns {HistoryPanel} the panel
- */
- scrollToTop : function(){
- this.$el.parent().scrollTop( 0 );
- return this;
- },
-
- /** Scrolls the panel (the enclosing container - in gen., the page) so that some object
- * is displayed in the vertical middle.
- * NOTE: if no size is given the panel will scroll to objTop (putting it at the top).
- * @param {Number} objTop the top offset of the object to view
- * @param {Number} objSize the size of the object to view
- * @returns {HistoryPanel} the panel
- */
- scrollIntoView : function( where, size ){
- if( !size ){
- this.$el.parent().parent().scrollTop( where );
- return this;
- }
- // otherwise, place the object in the vertical middle
- var viewport = window,
- panelContainer = this.$el.parent().parent(),
- containerHeight = $( viewport ).innerHeight(),
- middleOffset = ( containerHeight / 2 ) - ( size / 2 );
-
- $( panelContainer ).scrollTop( where - middleOffset );
- return this;
- },
-
- /** Scrolls the panel to show the HDA with the given id.
- * @param {String} id the id of HDA to scroll into view
- * @returns {HistoryPanel} the panel
- */
- scrollToId : function( id ){
- // do nothing if id not found
- if( ( !id ) || ( !this.hdaViews[ id ] ) ){
- return this;
- }
- var $viewEl = this.hdaViews[ id ].$el;
- this.scrollIntoView( $viewEl.offset().top, $viewEl.outerHeight() );
- return this;
- },
-
- /** Scrolls the panel to show the HDA with the given hid.
- * @param {Integer} hid the hid of HDA to scroll into view
- * @returns {HistoryPanel} the panel
- */
- scrollToHid : function( hid ){
- var hda = this.model.hdas.getByHid( hid );
- // do nothing if hid not found
- if( !hda ){ return this; }
- return this.scrollToId( hda.id );
- },
-
- // ........................................................................ external objects/MVC
- //TODO: remove quota meter from panel and remove this
- /** add listeners to an external quota meter (mvc/user/user-quotameter.js) */
- connectToQuotaMeter : function( quotaMeter ){
- if( !quotaMeter ){
- return this;
- }
- // show/hide the 'over quota message' in the history when the meter tells it to
- this.listenTo( quotaMeter, 'quota:over', this.showQuotaMessage );
- this.listenTo( quotaMeter, 'quota:under', this.hideQuotaMessage );
-
- // having to add this to handle re-render of hview while overquota (the above do not fire)
- this.on( 'rendered rendered:initial', function(){
- if( quotaMeter && quotaMeter.isOverQuota() ){
- this.showQuotaMessage();
- }
- });
- return this;
- },
-
-//TODO: this seems more like a per user message than a history message; IOW, this doesn't belong here
- /** Show the over quota message (which happens to be in the history panel).
- */
- showQuotaMessage : function(){
- var msg = this.$el.find( '.quota-message' );
- //this.log( this + ' showing quota message:', msg, userData );
- if( msg.is( ':hidden' ) ){ msg.slideDown( this.fxSpeed ); }
- },
-
-//TODO: this seems more like a per user message than a history message
- /** Hide the over quota message (which happens to be in the history panel).
- */
- hideQuotaMessage : function(){
- var msg = this.$el.find( '.quota-message' );
- //this.log( this + ' hiding quota message:', msg, userData );
- if( !msg.is( ':hidden' ) ){ msg.slideUp( this.fxSpeed ); }
- },
-
-//TODO: move show_deleted/hidden into panel from opt menu and remove this
- /** add listeners to an external options menu (templates/webapps/galaxy/root/index.mako) */
- connectToOptionsMenu : function( optionsMenu ){
- if( !optionsMenu ){
- return this;
- }
- // set a visible indication in the popupmenu for show_hidden/deleted based on the currHistoryPanel's settings
- this.on( 'new-storage', function( storage, panel ){
- if( optionsMenu && storage ){
- optionsMenu.findItemByHtml( _l( 'Include Deleted Datasets' ) ).checked = storage.get( 'show_deleted' );
- optionsMenu.findItemByHtml( _l( 'Include Hidden Datasets' ) ).checked = storage.get( 'show_hidden' );
- }
- });
- return this;
- },
-
- /** Return a string rep of the history
- */
+ // ........................................................................ misc
+ /** Return a string rep of the history */
toString : function(){
return 'HistoryPanel(' + (( this.model )?( this.model.get( 'name' )):( '' )) + ')';
}
@@ -1372,6 +404,6 @@
//==============================================================================
return {
- HistoryPanel : HistoryPanel
+ HistoryPanel : HistoryPanel
};
});
This diff is so big that we needed to truncate the remainder.
https://bitbucket.org/galaxy/galaxy-central/commits/82d6ee82d5d4/
Changeset: 82d6ee82d5d4
User: carlfeberhard
Date: 2014-02-18 21:12:31
Summary: merge
Affected #: 1 file
diff -r 33812bcdc52393bf179dd501b4334be4ec4e97a7 -r 82d6ee82d5d4714eefdbce041f6c983a806a58d7 templates/webapps/galaxy/mobile/history/detail.mako
--- a/templates/webapps/galaxy/mobile/history/detail.mako
+++ b/templates/webapps/galaxy/mobile/history/detail.mako
@@ -12,7 +12,7 @@
if data.state in ['no state','',None]:
data_state = "queued"
else:
- data_state = data.state
+ data_state = str( data.state )
%><li id="historyItemContainer-${data.id}">
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: dan: Fix for server error caused by unicode substitution in url_for.
by commits-noreply@bitbucket.org 18 Feb '14
by commits-noreply@bitbucket.org 18 Feb '14
18 Feb '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/e9d3248c6fc3/
Changeset: e9d3248c6fc3
User: dan
Date: 2014-02-18 21:09:46
Summary: Fix for server error caused by unicode substitution in url_for.
Affected #: 1 file
diff -r 26e37f6af3a8a090d9d6e923fa3e90acb0e64572 -r e9d3248c6fc312f8c7671a8e1233265c4ff0a0b1 templates/webapps/galaxy/mobile/history/detail.mako
--- a/templates/webapps/galaxy/mobile/history/detail.mako
+++ b/templates/webapps/galaxy/mobile/history/detail.mako
@@ -12,7 +12,7 @@
if data.state in ['no state','',None]:
data_state = "queued"
else:
- data_state = data.state
+ data_state = str( data.state )
%><li id="historyItemContainer-${data.id}">
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0